From 5c2612fcf1925e209367facf626b1e44d74dc9f4 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Tue, 1 Oct 2024 17:41:17 -0700 Subject: [PATCH] 1.21 --- blackboxmc-rs-bukkit/src/advancement/mod.rs | 341 +- blackboxmc-rs-bukkit/src/attribute/mod.rs | 866 +- blackboxmc-rs-bukkit/src/block/banner/mod.rs | 160 +- blackboxmc-rs-bukkit/src/block/data/mod.rs | 249 +- .../src/block/data/mod_type/mod.rs | 7274 +- blackboxmc-rs-bukkit/src/block/mod.rs | 19548 ++- blackboxmc-rs-bukkit/src/block/sign/mod.rs | 42 +- .../src/block/structure/mod.rs | 191 +- blackboxmc-rs-bukkit/src/boss/mod.rs | 349 +- .../src/command/defaults/mod.rs | 794 +- blackboxmc-rs-bukkit/src/command/mod.rs | 1898 +- .../src/configuration/file/mod.rs | 370 +- blackboxmc-rs-bukkit/src/configuration/mod.rs | 2124 +- .../src/configuration/serialization/mod.rs | 242 +- blackboxmc-rs-bukkit/src/conversations/mod.rs | 3453 +- blackboxmc-rs-bukkit/src/damage/mod.rs | 118 +- blackboxmc-rs-bukkit/src/enchantments/mod.rs | 540 +- blackboxmc-rs-bukkit/src/entity/memory/mod.rs | 31 + .../src/entity/minecart/mod.rs | 151 + blackboxmc-rs-bukkit/src/entity/mod.rs | 127814 ++++++++------- blackboxmc-rs-bukkit/src/event/block/mod.rs | 7295 +- .../src/event/enchantment/mod.rs | 27 +- blackboxmc-rs-bukkit/src/event/entity/mod.rs | 8521 +- blackboxmc-rs-bukkit/src/event/hanging/mod.rs | 89 +- .../src/event/inventory/mod.rs | 5556 +- blackboxmc-rs-bukkit/src/event/mod.rs | 515 +- blackboxmc-rs-bukkit/src/event/player/mod.rs | 12855 +- blackboxmc-rs-bukkit/src/event/raid/mod.rs | 89 +- blackboxmc-rs-bukkit/src/event/server/mod.rs | 532 +- blackboxmc-rs-bukkit/src/event/weather/mod.rs | 820 +- blackboxmc-rs-bukkit/src/event/world/mod.rs | 443 +- blackboxmc-rs-bukkit/src/help/mod.rs | 346 +- .../src/inventory/meta/components/mod.rs | 217 +- .../src/inventory/meta/mod.rs | 20904 +-- blackboxmc-rs-bukkit/src/inventory/mod.rs | 14577 +- .../src/inventory/recipe/mod.rs | 133 +- .../src/inventory/view/mod.rs | 4042 + blackboxmc-rs-bukkit/src/lib.rs | 89547 ++++++++-- blackboxmc-rs-bukkit/src/loot/mod.rs | 2900 +- blackboxmc-rs-bukkit/src/map/mod.rs | 2218 +- blackboxmc-rs-bukkit/src/material/mod.rs | 8817 +- .../src/material/types/mod.rs | 199 +- blackboxmc-rs-bukkit/src/metadata/mod.rs | 1299 +- blackboxmc-rs-bukkit/src/packs/mod.rs | 1002 +- blackboxmc-rs-bukkit/src/permissions/mod.rs | 1048 +- blackboxmc-rs-bukkit/src/plugin/java/mod.rs | 244 +- .../src/plugin/messaging/mod.rs | 550 +- blackboxmc-rs-bukkit/src/plugin/mod.rs | 3476 +- blackboxmc-rs-bukkit/src/potion/mod.rs | 2295 +- blackboxmc-rs-bukkit/src/profile/mod.rs | 52 +- blackboxmc-rs-bukkit/src/scheduler/mod.rs | 500 +- blackboxmc-rs-bukkit/src/scoreboard/mod.rs | 784 +- blackboxmc-rs-bukkit/src/spawner/mod.rs | 1231 + blackboxmc-rs-bukkit/src/util/io/mod.rs | 28 +- blackboxmc-rs-bukkit/src/util/mod.rs | 4607 +- blackboxmc-rs-bukkit/src/util/noise/mod.rs | 610 +- blackboxmc-rs-proc/README.md | 3 + generate.py | 54 +- pprint.py | 1 + 59 files changed, 227450 insertions(+), 137531 deletions(-) create mode 100644 blackboxmc-rs-bukkit/src/inventory/view/mod.rs create mode 100644 blackboxmc-rs-bukkit/src/spawner/mod.rs create mode 100644 blackboxmc-rs-proc/README.md mode change 100644 => 100755 pprint.py diff --git a/blackboxmc-rs-bukkit/src/advancement/mod.rs b/blackboxmc-rs-bukkit/src/advancement/mod.rs index fec14f2..62f18a7 100644 --- a/blackboxmc-rs-bukkit/src/advancement/mod.rs +++ b/blackboxmc-rs-bukkit/src/advancement/mod.rs @@ -2,6 +2,203 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; +pub enum AdvancementDisplayType<'mc> { + Task { + inner: AdvancementDisplayTypeStruct<'mc>, + }, + Challenge { + inner: AdvancementDisplayTypeStruct<'mc>, + }, + Goal { + inner: AdvancementDisplayTypeStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for AdvancementDisplayType<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + AdvancementDisplayType::Task { .. } => f.write_str("TASK"), + AdvancementDisplayType::Challenge { .. } => f.write_str("CHALLENGE"), + AdvancementDisplayType::Goal { .. } => f.write_str("GOAL"), + } + } +} +impl<'mc> std::ops::Deref for AdvancementDisplayType<'mc> { + type Target = AdvancementDisplayTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + AdvancementDisplayType::Task { inner } => inner, + AdvancementDisplayType::Challenge { inner } => inner, + AdvancementDisplayType::Goal { inner } => inner, + } + } +} + +impl<'mc> AdvancementDisplayType<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/advancement/AdvancementDisplayType"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/advancement/AdvancementDisplayType;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "TASK" => Ok(AdvancementDisplayType::Task { + inner: AdvancementDisplayTypeStruct::from_raw(env, obj)?, + }), + "CHALLENGE" => Ok(AdvancementDisplayType::Challenge { + inner: AdvancementDisplayTypeStruct::from_raw(env, obj)?, + }), + "GOAL" => Ok(AdvancementDisplayType::Goal { + inner: AdvancementDisplayTypeStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct AdvancementDisplayTypeStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for AdvancementDisplayType<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Task { inner } => inner.0.clone(), + Self::Challenge { inner } => inner.0.clone(), + Self::Goal { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Task { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Challenge { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Goal { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for AdvancementDisplayType<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate AdvancementDisplayType from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/advancement/AdvancementDisplayType")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a AdvancementDisplayType object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "TASK" => Ok(AdvancementDisplayType::Task { + inner: AdvancementDisplayTypeStruct::from_raw(env, obj)?, + }), + "CHALLENGE" => Ok(AdvancementDisplayType::Challenge { + inner: AdvancementDisplayTypeStruct::from_raw(env, obj)?, + }), + "GOAL" => Ok(AdvancementDisplayType::Goal { + inner: AdvancementDisplayTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for AdvancementDisplayTypeStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for AdvancementDisplayTypeStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate AdvancementDisplayTypeStruct from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/advancement/AdvancementDisplayType")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a AdvancementDisplayTypeStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> AdvancementDisplayTypeStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/advancement/AdvancementDisplayType;"); + let cls = jni.find_class("org/bukkit/advancement/AdvancementDisplayType"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::advancement::AdvancementDisplayType::from_raw(&jni, obj) + } + /// The chat color used by Minecraft for this advancement. + pub fn color(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/ChatColor;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::ChatColor::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} #[repr(C)] pub struct AdvancementDisplay<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, @@ -422,147 +619,3 @@ impl<'mc> Into> for Advancement<'mc> { .expect("Error converting Advancement into crate::Keyed") } } -pub enum AdvancementDisplayType<'mc> {} -impl<'mc> std::fmt::Display for AdvancementDisplayType<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> AdvancementDisplayType<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/advancement/AdvancementDisplayType"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/advancement/AdvancementDisplayType;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct AdvancementDisplayTypeStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for AdvancementDisplayType<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for AdvancementDisplayType<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate AdvancementDisplayType from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/advancement/AdvancementDisplayType")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a AdvancementDisplayType object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for AdvancementDisplayTypeStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for AdvancementDisplayTypeStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate AdvancementDisplayTypeStruct from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/advancement/AdvancementDisplayType")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a AdvancementDisplayTypeStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> AdvancementDisplayTypeStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/advancement/AdvancementDisplayType;"); - let cls = jni.find_class("org/bukkit/advancement/AdvancementDisplayType"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::advancement::AdvancementDisplayType::from_raw(&jni, obj) - } - /// The chat color used by Minecraft for this advancement. - pub fn color(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/ChatColor;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::ChatColor::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} diff --git a/blackboxmc-rs-bukkit/src/attribute/mod.rs b/blackboxmc-rs-bukkit/src/attribute/mod.rs index 7b3a5c2..e471c18 100644 --- a/blackboxmc-rs-bukkit/src/attribute/mod.rs +++ b/blackboxmc-rs-bukkit/src/attribute/mod.rs @@ -2,160 +2,6 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; -pub enum Attribute<'mc> {} -impl<'mc> std::fmt::Display for Attribute<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> Attribute<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/attribute/Attribute"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/attribute/Attribute;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct AttributeStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Attribute<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for Attribute<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Attribute from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/attribute/Attribute")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Attribute object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for AttributeStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for AttributeStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate AttributeStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/attribute/Attribute")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a AttributeStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> AttributeStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/attribute/Attribute;"); - let cls = jni.find_class("org/bukkit/attribute/Attribute"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::attribute::Attribute::from_raw(&jni, obj) - } - - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn translation_key(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTranslationKey", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} #[repr(C)] pub struct AttributeModifier<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, @@ -196,42 +42,32 @@ impl<'mc> JNIInstantiatable<'mc> for AttributeModifier<'mc> { impl<'mc> AttributeModifier<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - uuid: impl Into>, - name: impl Into, + key: impl Into>, amount: f64, - operation: std::option::Option< - impl Into>, - >, + operation: impl Into>, slot: std::option::Option>>, ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; + sig += "Lorg/bukkit/NamespacedKey;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) + jni::objects::JObject::from_raw(key.into().jni_object().clone()) }); args.push(val_1); - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(name.into())?, - )); - args.push(val_2); sig += "D"; - let val_3 = jni::objects::JValueGen::Double(amount); + let val_2 = jni::objects::JValueGen::Double(amount); + args.push(val_2); + sig += "Lorg/bukkit/attribute/AttributeModifier/Operation;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(operation.into().jni_object().clone()) + }); args.push(val_3); - if let Some(a) = operation { - sig += "Lorg/bukkit/attribute/AttributeModifier/Operation;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_4); - } if let Some(a) = slot { sig += "Lorg/bukkit/inventory/EquipmentSlotGroup;"; - let val_5 = jni::objects::JValueGen::Object(unsafe { + let val_4 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); - args.push(val_5); + args.push(val_4); } sig += ")V"; let cls = jni.find_class("org/bukkit/attribute/AttributeModifier"); @@ -240,6 +76,7 @@ impl<'mc> AttributeModifier<'mc> { let res = jni.translate_error_no_gen(res)?; crate::attribute::AttributeModifier::from_raw(&jni, res) } + #[deprecated] /// Get the unique ID for this modifier. pub fn unique_id( &self, @@ -253,6 +90,17 @@ impl<'mc> AttributeModifier<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } + + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } /// Get the name of this modifier. pub fn name(&self) -> Result> { let sig = String::from("()Ljava/lang/String;"); @@ -416,10 +264,40 @@ impl<'mc> Into {} +impl<'mc> Into> for AttributeModifier<'mc> { + fn into(self) -> crate::Keyed<'mc> { + crate::Keyed::from_raw(&self.jni_ref(), self.1) + .expect("Error converting AttributeModifier into crate::Keyed") + } +} +pub enum AttributeModifierOperation<'mc> { + AddNumber { + inner: AttributeModifierOperationStruct<'mc>, + }, + AddScalar { + inner: AttributeModifierOperationStruct<'mc>, + }, + MultiplyScalar1 { + inner: AttributeModifierOperationStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for AttributeModifierOperation<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + AttributeModifierOperation::AddNumber { .. } => f.write_str("ADD_NUMBER"), + AttributeModifierOperation::AddScalar { .. } => f.write_str("ADD_SCALAR"), + AttributeModifierOperation::MultiplyScalar1 { .. } => f.write_str("MULTIPLY_SCALAR_1"), + } + } +} +impl<'mc> std::ops::Deref for AttributeModifierOperation<'mc> { + type Target = AttributeModifierOperationStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + AttributeModifierOperation::AddNumber { inner } => inner, + AttributeModifierOperation::AddScalar { inner } => inner, + AttributeModifierOperation::MultiplyScalar1 { inner } => inner, + } } } @@ -446,6 +324,16 @@ impl<'mc> AttributeModifierOperation<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "ADD_NUMBER" => Ok(AttributeModifierOperation::AddNumber { + inner: AttributeModifierOperationStruct::from_raw(env, obj)?, + }), + "ADD_SCALAR" => Ok(AttributeModifierOperation::AddScalar { + inner: AttributeModifierOperationStruct::from_raw(env, obj)?, + }), + "MULTIPLY_SCALAR_1" => Ok(AttributeModifierOperation::MultiplyScalar1 { + inner: AttributeModifierOperationStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -459,10 +347,24 @@ pub struct AttributeModifierOperationStruct<'mc>( impl<'mc> JNIRaw<'mc> for AttributeModifierOperation<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::AddNumber { inner } => inner.0.clone(), + Self::AddScalar { inner } => inner.0.clone(), + Self::MultiplyScalar1 { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::AddNumber { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AddScalar { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MultiplyScalar1 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } impl<'mc> JNIInstantiatable<'mc> for AttributeModifierOperation<'mc> { @@ -492,6 +394,15 @@ impl<'mc> JNIInstantiatable<'mc> for AttributeModifierOperation<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "ADD_NUMBER" => Ok(AttributeModifierOperation::AddNumber { + inner: AttributeModifierOperationStruct::from_raw(env, obj)?, + }), + "ADD_SCALAR" => Ok(AttributeModifierOperation::AddScalar { + inner: AttributeModifierOperationStruct::from_raw(env, obj)?, + }), + "MULTIPLY_SCALAR_1" => Ok(AttributeModifierOperation::MultiplyScalar1 { + inner: AttributeModifierOperationStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -549,6 +460,601 @@ impl<'mc> AttributeModifierOperationStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +pub enum Attribute<'mc> { + GenericMaxHealth { inner: AttributeStruct<'mc> }, + GenericFollowRange { inner: AttributeStruct<'mc> }, + GenericKnockbackResistance { inner: AttributeStruct<'mc> }, + GenericMovementSpeed { inner: AttributeStruct<'mc> }, + GenericFlyingSpeed { inner: AttributeStruct<'mc> }, + GenericAttackDamage { inner: AttributeStruct<'mc> }, + GenericAttackKnockback { inner: AttributeStruct<'mc> }, + GenericAttackSpeed { inner: AttributeStruct<'mc> }, + GenericArmor { inner: AttributeStruct<'mc> }, + GenericArmorToughness { inner: AttributeStruct<'mc> }, + GenericFallDamageMultiplier { inner: AttributeStruct<'mc> }, + GenericLuck { inner: AttributeStruct<'mc> }, + GenericMaxAbsorption { inner: AttributeStruct<'mc> }, + GenericSafeFallDistance { inner: AttributeStruct<'mc> }, + GenericScale { inner: AttributeStruct<'mc> }, + GenericStepHeight { inner: AttributeStruct<'mc> }, + GenericGravity { inner: AttributeStruct<'mc> }, + GenericJumpStrength { inner: AttributeStruct<'mc> }, + GenericBurningTime { inner: AttributeStruct<'mc> }, + GenericExplosionKnockbackResistance { inner: AttributeStruct<'mc> }, + GenericMovementEfficiency { inner: AttributeStruct<'mc> }, + GenericOxygenBonus { inner: AttributeStruct<'mc> }, + GenericWaterMovementEfficiency { inner: AttributeStruct<'mc> }, + PlayerBlockInteractionRange { inner: AttributeStruct<'mc> }, + PlayerEntityInteractionRange { inner: AttributeStruct<'mc> }, + PlayerBlockBreakSpeed { inner: AttributeStruct<'mc> }, + PlayerMiningEfficiency { inner: AttributeStruct<'mc> }, + PlayerSneakingSpeed { inner: AttributeStruct<'mc> }, + PlayerSubmergedMiningSpeed { inner: AttributeStruct<'mc> }, + PlayerSweepingDamageRatio { inner: AttributeStruct<'mc> }, + ZombieSpawnReinforcements { inner: AttributeStruct<'mc> }, +} +impl<'mc> std::fmt::Display for Attribute<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Attribute::GenericMaxHealth { .. } => f.write_str("GENERIC_MAX_HEALTH"), + Attribute::GenericFollowRange { .. } => f.write_str("GENERIC_FOLLOW_RANGE"), + Attribute::GenericKnockbackResistance { .. } => { + f.write_str("GENERIC_KNOCKBACK_RESISTANCE") + } + Attribute::GenericMovementSpeed { .. } => f.write_str("GENERIC_MOVEMENT_SPEED"), + Attribute::GenericFlyingSpeed { .. } => f.write_str("GENERIC_FLYING_SPEED"), + Attribute::GenericAttackDamage { .. } => f.write_str("GENERIC_ATTACK_DAMAGE"), + Attribute::GenericAttackKnockback { .. } => f.write_str("GENERIC_ATTACK_KNOCKBACK"), + Attribute::GenericAttackSpeed { .. } => f.write_str("GENERIC_ATTACK_SPEED"), + Attribute::GenericArmor { .. } => f.write_str("GENERIC_ARMOR"), + Attribute::GenericArmorToughness { .. } => f.write_str("GENERIC_ARMOR_TOUGHNESS"), + Attribute::GenericFallDamageMultiplier { .. } => { + f.write_str("GENERIC_FALL_DAMAGE_MULTIPLIER") + } + Attribute::GenericLuck { .. } => f.write_str("GENERIC_LUCK"), + Attribute::GenericMaxAbsorption { .. } => f.write_str("GENERIC_MAX_ABSORPTION"), + Attribute::GenericSafeFallDistance { .. } => f.write_str("GENERIC_SAFE_FALL_DISTANCE"), + Attribute::GenericScale { .. } => f.write_str("GENERIC_SCALE"), + Attribute::GenericStepHeight { .. } => f.write_str("GENERIC_STEP_HEIGHT"), + Attribute::GenericGravity { .. } => f.write_str("GENERIC_GRAVITY"), + Attribute::GenericJumpStrength { .. } => f.write_str("GENERIC_JUMP_STRENGTH"), + Attribute::GenericBurningTime { .. } => f.write_str("GENERIC_BURNING_TIME"), + Attribute::GenericExplosionKnockbackResistance { .. } => { + f.write_str("GENERIC_EXPLOSION_KNOCKBACK_RESISTANCE") + } + Attribute::GenericMovementEfficiency { .. } => { + f.write_str("GENERIC_MOVEMENT_EFFICIENCY") + } + Attribute::GenericOxygenBonus { .. } => f.write_str("GENERIC_OXYGEN_BONUS"), + Attribute::GenericWaterMovementEfficiency { .. } => { + f.write_str("GENERIC_WATER_MOVEMENT_EFFICIENCY") + } + Attribute::PlayerBlockInteractionRange { .. } => { + f.write_str("PLAYER_BLOCK_INTERACTION_RANGE") + } + Attribute::PlayerEntityInteractionRange { .. } => { + f.write_str("PLAYER_ENTITY_INTERACTION_RANGE") + } + Attribute::PlayerBlockBreakSpeed { .. } => f.write_str("PLAYER_BLOCK_BREAK_SPEED"), + Attribute::PlayerMiningEfficiency { .. } => f.write_str("PLAYER_MINING_EFFICIENCY"), + Attribute::PlayerSneakingSpeed { .. } => f.write_str("PLAYER_SNEAKING_SPEED"), + Attribute::PlayerSubmergedMiningSpeed { .. } => { + f.write_str("PLAYER_SUBMERGED_MINING_SPEED") + } + Attribute::PlayerSweepingDamageRatio { .. } => { + f.write_str("PLAYER_SWEEPING_DAMAGE_RATIO") + } + Attribute::ZombieSpawnReinforcements { .. } => { + f.write_str("ZOMBIE_SPAWN_REINFORCEMENTS") + } + } + } +} +impl<'mc> std::ops::Deref for Attribute<'mc> { + type Target = AttributeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + Attribute::GenericMaxHealth { inner } => inner, + Attribute::GenericFollowRange { inner } => inner, + Attribute::GenericKnockbackResistance { inner } => inner, + Attribute::GenericMovementSpeed { inner } => inner, + Attribute::GenericFlyingSpeed { inner } => inner, + Attribute::GenericAttackDamage { inner } => inner, + Attribute::GenericAttackKnockback { inner } => inner, + Attribute::GenericAttackSpeed { inner } => inner, + Attribute::GenericArmor { inner } => inner, + Attribute::GenericArmorToughness { inner } => inner, + Attribute::GenericFallDamageMultiplier { inner } => inner, + Attribute::GenericLuck { inner } => inner, + Attribute::GenericMaxAbsorption { inner } => inner, + Attribute::GenericSafeFallDistance { inner } => inner, + Attribute::GenericScale { inner } => inner, + Attribute::GenericStepHeight { inner } => inner, + Attribute::GenericGravity { inner } => inner, + Attribute::GenericJumpStrength { inner } => inner, + Attribute::GenericBurningTime { inner } => inner, + Attribute::GenericExplosionKnockbackResistance { inner } => inner, + Attribute::GenericMovementEfficiency { inner } => inner, + Attribute::GenericOxygenBonus { inner } => inner, + Attribute::GenericWaterMovementEfficiency { inner } => inner, + Attribute::PlayerBlockInteractionRange { inner } => inner, + Attribute::PlayerEntityInteractionRange { inner } => inner, + Attribute::PlayerBlockBreakSpeed { inner } => inner, + Attribute::PlayerMiningEfficiency { inner } => inner, + Attribute::PlayerSneakingSpeed { inner } => inner, + Attribute::PlayerSubmergedMiningSpeed { inner } => inner, + Attribute::PlayerSweepingDamageRatio { inner } => inner, + Attribute::ZombieSpawnReinforcements { inner } => inner, + } + } +} + +impl<'mc> Attribute<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/attribute/Attribute"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/attribute/Attribute;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "GENERIC_MAX_HEALTH" => Ok(Attribute::GenericMaxHealth { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_FOLLOW_RANGE" => Ok(Attribute::GenericFollowRange { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_KNOCKBACK_RESISTANCE" => Ok(Attribute::GenericKnockbackResistance { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_MOVEMENT_SPEED" => Ok(Attribute::GenericMovementSpeed { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_FLYING_SPEED" => Ok(Attribute::GenericFlyingSpeed { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_ATTACK_DAMAGE" => Ok(Attribute::GenericAttackDamage { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_ATTACK_KNOCKBACK" => Ok(Attribute::GenericAttackKnockback { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_ATTACK_SPEED" => Ok(Attribute::GenericAttackSpeed { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_ARMOR" => Ok(Attribute::GenericArmor { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_ARMOR_TOUGHNESS" => Ok(Attribute::GenericArmorToughness { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_FALL_DAMAGE_MULTIPLIER" => Ok(Attribute::GenericFallDamageMultiplier { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_LUCK" => Ok(Attribute::GenericLuck { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_MAX_ABSORPTION" => Ok(Attribute::GenericMaxAbsorption { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_SAFE_FALL_DISTANCE" => Ok(Attribute::GenericSafeFallDistance { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_SCALE" => Ok(Attribute::GenericScale { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_STEP_HEIGHT" => Ok(Attribute::GenericStepHeight { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_GRAVITY" => Ok(Attribute::GenericGravity { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_JUMP_STRENGTH" => Ok(Attribute::GenericJumpStrength { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_BURNING_TIME" => Ok(Attribute::GenericBurningTime { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_EXPLOSION_KNOCKBACK_RESISTANCE" => { + Ok(Attribute::GenericExplosionKnockbackResistance { + inner: AttributeStruct::from_raw(env, obj)?, + }) + } + "GENERIC_MOVEMENT_EFFICIENCY" => Ok(Attribute::GenericMovementEfficiency { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_OXYGEN_BONUS" => Ok(Attribute::GenericOxygenBonus { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_WATER_MOVEMENT_EFFICIENCY" => Ok(Attribute::GenericWaterMovementEfficiency { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "PLAYER_BLOCK_INTERACTION_RANGE" => Ok(Attribute::PlayerBlockInteractionRange { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "PLAYER_ENTITY_INTERACTION_RANGE" => Ok(Attribute::PlayerEntityInteractionRange { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "PLAYER_BLOCK_BREAK_SPEED" => Ok(Attribute::PlayerBlockBreakSpeed { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "PLAYER_MINING_EFFICIENCY" => Ok(Attribute::PlayerMiningEfficiency { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "PLAYER_SNEAKING_SPEED" => Ok(Attribute::PlayerSneakingSpeed { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "PLAYER_SUBMERGED_MINING_SPEED" => Ok(Attribute::PlayerSubmergedMiningSpeed { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "PLAYER_SWEEPING_DAMAGE_RATIO" => Ok(Attribute::PlayerSweepingDamageRatio { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "ZOMBIE_SPAWN_REINFORCEMENTS" => Ok(Attribute::ZombieSpawnReinforcements { + inner: AttributeStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct AttributeStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Attribute<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::GenericMaxHealth { inner } => inner.0.clone(), + Self::GenericFollowRange { inner } => inner.0.clone(), + Self::GenericKnockbackResistance { inner } => inner.0.clone(), + Self::GenericMovementSpeed { inner } => inner.0.clone(), + Self::GenericFlyingSpeed { inner } => inner.0.clone(), + Self::GenericAttackDamage { inner } => inner.0.clone(), + Self::GenericAttackKnockback { inner } => inner.0.clone(), + Self::GenericAttackSpeed { inner } => inner.0.clone(), + Self::GenericArmor { inner } => inner.0.clone(), + Self::GenericArmorToughness { inner } => inner.0.clone(), + Self::GenericFallDamageMultiplier { inner } => inner.0.clone(), + Self::GenericLuck { inner } => inner.0.clone(), + Self::GenericMaxAbsorption { inner } => inner.0.clone(), + Self::GenericSafeFallDistance { inner } => inner.0.clone(), + Self::GenericScale { inner } => inner.0.clone(), + Self::GenericStepHeight { inner } => inner.0.clone(), + Self::GenericGravity { inner } => inner.0.clone(), + Self::GenericJumpStrength { inner } => inner.0.clone(), + Self::GenericBurningTime { inner } => inner.0.clone(), + Self::GenericExplosionKnockbackResistance { inner } => inner.0.clone(), + Self::GenericMovementEfficiency { inner } => inner.0.clone(), + Self::GenericOxygenBonus { inner } => inner.0.clone(), + Self::GenericWaterMovementEfficiency { inner } => inner.0.clone(), + Self::PlayerBlockInteractionRange { inner } => inner.0.clone(), + Self::PlayerEntityInteractionRange { inner } => inner.0.clone(), + Self::PlayerBlockBreakSpeed { inner } => inner.0.clone(), + Self::PlayerMiningEfficiency { inner } => inner.0.clone(), + Self::PlayerSneakingSpeed { inner } => inner.0.clone(), + Self::PlayerSubmergedMiningSpeed { inner } => inner.0.clone(), + Self::PlayerSweepingDamageRatio { inner } => inner.0.clone(), + Self::ZombieSpawnReinforcements { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::GenericMaxHealth { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GenericFollowRange { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GenericKnockbackResistance { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GenericMovementSpeed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GenericFlyingSpeed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GenericAttackDamage { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GenericAttackKnockback { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GenericAttackSpeed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GenericArmor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GenericArmorToughness { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GenericFallDamageMultiplier { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GenericLuck { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GenericMaxAbsorption { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GenericSafeFallDistance { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GenericScale { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GenericStepHeight { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GenericGravity { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GenericJumpStrength { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GenericBurningTime { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GenericExplosionKnockbackResistance { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GenericMovementEfficiency { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GenericOxygenBonus { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GenericWaterMovementEfficiency { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PlayerBlockInteractionRange { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PlayerEntityInteractionRange { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PlayerBlockBreakSpeed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PlayerMiningEfficiency { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PlayerSneakingSpeed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PlayerSubmergedMiningSpeed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PlayerSweepingDamageRatio { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ZombieSpawnReinforcements { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for Attribute<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Attribute from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/attribute/Attribute")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Attribute object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "GENERIC_MAX_HEALTH" => Ok(Attribute::GenericMaxHealth { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_FOLLOW_RANGE" => Ok(Attribute::GenericFollowRange { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_KNOCKBACK_RESISTANCE" => Ok(Attribute::GenericKnockbackResistance { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_MOVEMENT_SPEED" => Ok(Attribute::GenericMovementSpeed { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_FLYING_SPEED" => Ok(Attribute::GenericFlyingSpeed { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_ATTACK_DAMAGE" => Ok(Attribute::GenericAttackDamage { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_ATTACK_KNOCKBACK" => Ok(Attribute::GenericAttackKnockback { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_ATTACK_SPEED" => Ok(Attribute::GenericAttackSpeed { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_ARMOR" => Ok(Attribute::GenericArmor { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_ARMOR_TOUGHNESS" => Ok(Attribute::GenericArmorToughness { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_FALL_DAMAGE_MULTIPLIER" => Ok(Attribute::GenericFallDamageMultiplier { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_LUCK" => Ok(Attribute::GenericLuck { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_MAX_ABSORPTION" => Ok(Attribute::GenericMaxAbsorption { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_SAFE_FALL_DISTANCE" => Ok(Attribute::GenericSafeFallDistance { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_SCALE" => Ok(Attribute::GenericScale { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_STEP_HEIGHT" => Ok(Attribute::GenericStepHeight { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_GRAVITY" => Ok(Attribute::GenericGravity { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_JUMP_STRENGTH" => Ok(Attribute::GenericJumpStrength { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_BURNING_TIME" => Ok(Attribute::GenericBurningTime { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_EXPLOSION_KNOCKBACK_RESISTANCE" => { + Ok(Attribute::GenericExplosionKnockbackResistance { + inner: AttributeStruct::from_raw(env, obj)?, + }) + } + "GENERIC_MOVEMENT_EFFICIENCY" => Ok(Attribute::GenericMovementEfficiency { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_OXYGEN_BONUS" => Ok(Attribute::GenericOxygenBonus { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "GENERIC_WATER_MOVEMENT_EFFICIENCY" => { + Ok(Attribute::GenericWaterMovementEfficiency { + inner: AttributeStruct::from_raw(env, obj)?, + }) + } + "PLAYER_BLOCK_INTERACTION_RANGE" => Ok(Attribute::PlayerBlockInteractionRange { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "PLAYER_ENTITY_INTERACTION_RANGE" => Ok(Attribute::PlayerEntityInteractionRange { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "PLAYER_BLOCK_BREAK_SPEED" => Ok(Attribute::PlayerBlockBreakSpeed { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "PLAYER_MINING_EFFICIENCY" => Ok(Attribute::PlayerMiningEfficiency { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "PLAYER_SNEAKING_SPEED" => Ok(Attribute::PlayerSneakingSpeed { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "PLAYER_SUBMERGED_MINING_SPEED" => Ok(Attribute::PlayerSubmergedMiningSpeed { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "PLAYER_SWEEPING_DAMAGE_RATIO" => Ok(Attribute::PlayerSweepingDamageRatio { + inner: AttributeStruct::from_raw(env, obj)?, + }), + "ZOMBIE_SPAWN_REINFORCEMENTS" => Ok(Attribute::ZombieSpawnReinforcements { + inner: AttributeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for AttributeStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for AttributeStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate AttributeStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/attribute/Attribute")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a AttributeStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> AttributeStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/attribute/Attribute;"); + let cls = jni.find_class("org/bukkit/attribute/Attribute"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::attribute::Attribute::from_raw(&jni, obj) + } + + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn translation_key(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTranslationKey", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} #[repr(C)] pub struct AttributeInstance<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, diff --git a/blackboxmc-rs-bukkit/src/block/banner/mod.rs b/blackboxmc-rs-bukkit/src/block/banner/mod.rs index 74dc905..5c42e29 100644 --- a/blackboxmc-rs-bukkit/src/block/banner/mod.rs +++ b/blackboxmc-rs-bukkit/src/block/banner/mod.rs @@ -2,53 +2,18 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; -pub enum PatternType<'mc> {} -impl<'mc> std::fmt::Display for PatternType<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> PatternType<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/block/banner/PatternType"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/block/banner/PatternType;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - #[repr(C)] -pub struct PatternTypeStruct<'mc>( +pub struct PatternType<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); impl<'mc> JNIRaw<'mc> for PatternType<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + self.0.clone() } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } impl<'mc> JNIInstantiatable<'mc> for PatternType<'mc> { @@ -66,64 +31,13 @@ impl<'mc> JNIInstantiatable<'mc> for PatternType<'mc> { name ) .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for PatternTypeStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PatternTypeStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate PatternTypeStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/banner/PatternType")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PatternTypeStruct object, got {}", - name - ) - .into()) } else { Ok(Self(env.clone(), obj)) } } } -impl<'mc> PatternTypeStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/banner/PatternType;"); - let cls = jni.find_class("org/bukkit/block/banner/PatternType"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::block::banner::PatternType::from_raw(&jni, obj) - } - +impl<'mc> PatternType<'mc> { pub fn key(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/NamespacedKey;"); let res = self @@ -175,12 +89,78 @@ impl<'mc> PatternTypeStruct<'mc> { &jni, obj, )?)) } + #[deprecated] + + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/banner/PatternType;"); + let cls = jni.find_class("org/bukkit/block/banner/PatternType"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::block::banner::PatternType::from_raw(&jni, obj) + } + #[deprecated] + + pub fn compare_to( + &self, + other: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(LT;)I"); + let val_1 = jni::objects::JValueGen::Object(other); + let res = self.jni_ref().call_method( + &self.jni_object(), + "compareTo", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + #[deprecated] + + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "name", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + #[deprecated] + + pub fn ordinal(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "ordinal", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for PatternType<'mc> { + fn into(self) -> crate::util::OldEnum<'mc> { + crate::util::OldEnum::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PatternType into crate::util::OldEnum") + } +} +impl<'mc> Into> for PatternType<'mc> { + fn into(self) -> crate::Keyed<'mc> { + crate::Keyed::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PatternType into crate::Keyed") + } +} #[repr(C)] pub struct Pattern<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, diff --git a/blackboxmc-rs-bukkit/src/block/data/mod.rs b/blackboxmc-rs-bukkit/src/block/data/mod.rs index 723b175..bc75292 100644 --- a/blackboxmc-rs-bukkit/src/block/data/mod.rs +++ b/blackboxmc-rs-bukkit/src/block/data/mod.rs @@ -3091,10 +3091,25 @@ impl<'mc> Into> for Bisected<'mc> { .expect("Error converting Bisected into crate::block::data::BlockData") } } -pub enum BisectedHalf<'mc> {} +pub enum BisectedHalf<'mc> { + Top { inner: BisectedHalfStruct<'mc> }, + Bottom { inner: BisectedHalfStruct<'mc> }, +} impl<'mc> std::fmt::Display for BisectedHalf<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + BisectedHalf::Top { .. } => f.write_str("TOP"), + BisectedHalf::Bottom { .. } => f.write_str("BOTTOM"), + } + } +} +impl<'mc> std::ops::Deref for BisectedHalf<'mc> { + type Target = BisectedHalfStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + BisectedHalf::Top { inner } => inner, + BisectedHalf::Bottom { inner } => inner, + } } } @@ -3121,6 +3136,13 @@ impl<'mc> BisectedHalf<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "TOP" => Ok(BisectedHalf::Top { + inner: BisectedHalfStruct::from_raw(env, obj)?, + }), + "BOTTOM" => Ok(BisectedHalf::Bottom { + inner: BisectedHalfStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -3134,10 +3156,16 @@ pub struct BisectedHalfStruct<'mc>( impl<'mc> JNIRaw<'mc> for BisectedHalf<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Top { inner } => inner.0.clone(), + Self::Bottom { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Top { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Bottom { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for BisectedHalf<'mc> { @@ -3163,6 +3191,12 @@ impl<'mc> JNIInstantiatable<'mc> for BisectedHalf<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "TOP" => Ok(BisectedHalf::Top { + inner: BisectedHalfStruct::from_raw(env, obj)?, + }), + "BOTTOM" => Ok(BisectedHalf::Bottom { + inner: BisectedHalfStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -5435,10 +5469,34 @@ impl<'mc> Into> for FaceAttachable<'mc> { .expect("Error converting FaceAttachable into crate::block::data::BlockData") } } -pub enum FaceAttachableAttachedFace<'mc> {} +pub enum FaceAttachableAttachedFace<'mc> { + Floor { + inner: FaceAttachableAttachedFaceStruct<'mc>, + }, + Wall { + inner: FaceAttachableAttachedFaceStruct<'mc>, + }, + Ceiling { + inner: FaceAttachableAttachedFaceStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for FaceAttachableAttachedFace<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + FaceAttachableAttachedFace::Floor { .. } => f.write_str("FLOOR"), + FaceAttachableAttachedFace::Wall { .. } => f.write_str("WALL"), + FaceAttachableAttachedFace::Ceiling { .. } => f.write_str("CEILING"), + } + } +} +impl<'mc> std::ops::Deref for FaceAttachableAttachedFace<'mc> { + type Target = FaceAttachableAttachedFaceStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + FaceAttachableAttachedFace::Floor { inner } => inner, + FaceAttachableAttachedFace::Wall { inner } => inner, + FaceAttachableAttachedFace::Ceiling { inner } => inner, + } } } @@ -5465,6 +5523,16 @@ impl<'mc> FaceAttachableAttachedFace<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "FLOOR" => Ok(FaceAttachableAttachedFace::Floor { + inner: FaceAttachableAttachedFaceStruct::from_raw(env, obj)?, + }), + "WALL" => Ok(FaceAttachableAttachedFace::Wall { + inner: FaceAttachableAttachedFaceStruct::from_raw(env, obj)?, + }), + "CEILING" => Ok(FaceAttachableAttachedFace::Ceiling { + inner: FaceAttachableAttachedFaceStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -5478,10 +5546,18 @@ pub struct FaceAttachableAttachedFaceStruct<'mc>( impl<'mc> JNIRaw<'mc> for FaceAttachableAttachedFace<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Floor { inner } => inner.0.clone(), + Self::Wall { inner } => inner.0.clone(), + Self::Ceiling { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Floor { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Wall { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Ceiling { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for FaceAttachableAttachedFace<'mc> { @@ -5511,6 +5587,15 @@ impl<'mc> JNIInstantiatable<'mc> for FaceAttachableAttachedFace<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "FLOOR" => Ok(FaceAttachableAttachedFace::Floor { + inner: FaceAttachableAttachedFaceStruct::from_raw(env, obj)?, + }), + "WALL" => Ok(FaceAttachableAttachedFace::Wall { + inner: FaceAttachableAttachedFaceStruct::from_raw(env, obj)?, + }), + "CEILING" => Ok(FaceAttachableAttachedFace::Ceiling { + inner: FaceAttachableAttachedFaceStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -8257,10 +8342,49 @@ impl<'mc> Into> for Rail<'mc> { .expect("Error converting Rail into crate::block::data::Waterlogged") } } -pub enum RailShape<'mc> {} +pub enum RailShape<'mc> { + NorthSouth { inner: RailShapeStruct<'mc> }, + EastWest { inner: RailShapeStruct<'mc> }, + AscendingEast { inner: RailShapeStruct<'mc> }, + AscendingWest { inner: RailShapeStruct<'mc> }, + AscendingNorth { inner: RailShapeStruct<'mc> }, + AscendingSouth { inner: RailShapeStruct<'mc> }, + SouthEast { inner: RailShapeStruct<'mc> }, + SouthWest { inner: RailShapeStruct<'mc> }, + NorthWest { inner: RailShapeStruct<'mc> }, + NorthEast { inner: RailShapeStruct<'mc> }, +} impl<'mc> std::fmt::Display for RailShape<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + RailShape::NorthSouth { .. } => f.write_str("NORTH_SOUTH"), + RailShape::EastWest { .. } => f.write_str("EAST_WEST"), + RailShape::AscendingEast { .. } => f.write_str("ASCENDING_EAST"), + RailShape::AscendingWest { .. } => f.write_str("ASCENDING_WEST"), + RailShape::AscendingNorth { .. } => f.write_str("ASCENDING_NORTH"), + RailShape::AscendingSouth { .. } => f.write_str("ASCENDING_SOUTH"), + RailShape::SouthEast { .. } => f.write_str("SOUTH_EAST"), + RailShape::SouthWest { .. } => f.write_str("SOUTH_WEST"), + RailShape::NorthWest { .. } => f.write_str("NORTH_WEST"), + RailShape::NorthEast { .. } => f.write_str("NORTH_EAST"), + } + } +} +impl<'mc> std::ops::Deref for RailShape<'mc> { + type Target = RailShapeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + RailShape::NorthSouth { inner } => inner, + RailShape::EastWest { inner } => inner, + RailShape::AscendingEast { inner } => inner, + RailShape::AscendingWest { inner } => inner, + RailShape::AscendingNorth { inner } => inner, + RailShape::AscendingSouth { inner } => inner, + RailShape::SouthEast { inner } => inner, + RailShape::SouthWest { inner } => inner, + RailShape::NorthWest { inner } => inner, + RailShape::NorthEast { inner } => inner, + } } } @@ -8287,6 +8411,37 @@ impl<'mc> RailShape<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NORTH_SOUTH" => Ok(RailShape::NorthSouth { + inner: RailShapeStruct::from_raw(env, obj)?, + }), + "EAST_WEST" => Ok(RailShape::EastWest { + inner: RailShapeStruct::from_raw(env, obj)?, + }), + "ASCENDING_EAST" => Ok(RailShape::AscendingEast { + inner: RailShapeStruct::from_raw(env, obj)?, + }), + "ASCENDING_WEST" => Ok(RailShape::AscendingWest { + inner: RailShapeStruct::from_raw(env, obj)?, + }), + "ASCENDING_NORTH" => Ok(RailShape::AscendingNorth { + inner: RailShapeStruct::from_raw(env, obj)?, + }), + "ASCENDING_SOUTH" => Ok(RailShape::AscendingSouth { + inner: RailShapeStruct::from_raw(env, obj)?, + }), + "SOUTH_EAST" => Ok(RailShape::SouthEast { + inner: RailShapeStruct::from_raw(env, obj)?, + }), + "SOUTH_WEST" => Ok(RailShape::SouthWest { + inner: RailShapeStruct::from_raw(env, obj)?, + }), + "NORTH_WEST" => Ok(RailShape::NorthWest { + inner: RailShapeStruct::from_raw(env, obj)?, + }), + "NORTH_EAST" => Ok(RailShape::NorthEast { + inner: RailShapeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -8300,10 +8455,50 @@ pub struct RailShapeStruct<'mc>( impl<'mc> JNIRaw<'mc> for RailShape<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::NorthSouth { inner } => inner.0.clone(), + Self::EastWest { inner } => inner.0.clone(), + Self::AscendingEast { inner } => inner.0.clone(), + Self::AscendingWest { inner } => inner.0.clone(), + Self::AscendingNorth { inner } => inner.0.clone(), + Self::AscendingSouth { inner } => inner.0.clone(), + Self::SouthEast { inner } => inner.0.clone(), + Self::SouthWest { inner } => inner.0.clone(), + Self::NorthWest { inner } => inner.0.clone(), + Self::NorthEast { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::NorthSouth { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EastWest { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::AscendingEast { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AscendingWest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AscendingNorth { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AscendingSouth { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SouthEast { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SouthWest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NorthWest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NorthEast { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } impl<'mc> JNIInstantiatable<'mc> for RailShape<'mc> { @@ -8329,6 +8524,36 @@ impl<'mc> JNIInstantiatable<'mc> for RailShape<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NORTH_SOUTH" => Ok(RailShape::NorthSouth { + inner: RailShapeStruct::from_raw(env, obj)?, + }), + "EAST_WEST" => Ok(RailShape::EastWest { + inner: RailShapeStruct::from_raw(env, obj)?, + }), + "ASCENDING_EAST" => Ok(RailShape::AscendingEast { + inner: RailShapeStruct::from_raw(env, obj)?, + }), + "ASCENDING_WEST" => Ok(RailShape::AscendingWest { + inner: RailShapeStruct::from_raw(env, obj)?, + }), + "ASCENDING_NORTH" => Ok(RailShape::AscendingNorth { + inner: RailShapeStruct::from_raw(env, obj)?, + }), + "ASCENDING_SOUTH" => Ok(RailShape::AscendingSouth { + inner: RailShapeStruct::from_raw(env, obj)?, + }), + "SOUTH_EAST" => Ok(RailShape::SouthEast { + inner: RailShapeStruct::from_raw(env, obj)?, + }), + "SOUTH_WEST" => Ok(RailShape::SouthWest { + inner: RailShapeStruct::from_raw(env, obj)?, + }), + "NORTH_WEST" => Ok(RailShape::NorthWest { + inner: RailShapeStruct::from_raw(env, obj)?, + }), + "NORTH_EAST" => Ok(RailShape::NorthEast { + inner: RailShapeStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } diff --git a/blackboxmc-rs-bukkit/src/block/data/mod_type/mod.rs b/blackboxmc-rs-bukkit/src/block/data/mod_type/mod.rs index 537853d..7b57c27 100644 --- a/blackboxmc-rs-bukkit/src/block/data/mod_type/mod.rs +++ b/blackboxmc-rs-bukkit/src/block/data/mod_type/mod.rs @@ -3,12 +3,12 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] -pub struct Vault<'mc>( +pub struct Sapling<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Vault<'mc> { +impl<'mc> JNIRaw<'mc> for Sapling<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -16,18 +16,18 @@ impl<'mc> JNIRaw<'mc> for Vault<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Vault<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Sapling<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Vault from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Sapling from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Vault")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Sapling")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Vault object, got {}", + "Invalid argument passed. Expected a Sapling object, got {}", name ) .into()) @@ -37,602 +37,305 @@ impl<'mc> JNIInstantiatable<'mc> for Vault<'mc> { } } -impl<'mc> Vault<'mc> { - /// Gets the value of the 'vault_state' property. - pub fn trial_spawner_state( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/type/Vault/State;"); +impl<'mc> Sapling<'mc> { + /// Gets the value of the 'stage' property. + pub fn stage(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getStage", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the value of the 'stage' property. + pub fn set_stage(&self, stage: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(stage); let res = self.jni_ref().call_method( &self.jni_object(), - "getTrialSpawnerState", + "setStage", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the maximum allowed value of the 'stage' property. + pub fn maximum_stage(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaximumStage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::data::mod_type::VaultState::from_raw(&self.jni_ref(), unsafe { + Ok(res.i()?) + } + /// Get the Material represented by this block data. + pub fn material(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaterial", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the value of the 'vault_state' property. - pub fn set_trial_spawner_state( + /// Gets a string, which when passed into a method such as + /// {@link Server#createBlockData(java.lang.String)} will recreate this or a + /// similar instance where unspecified states (if any) may be optionally + /// omitted. If this instance was parsed and states are omitted, this exact + /// instance will be creatable when parsed again, else their equality cannot + /// be guaranteed. + /// + /// This method will only take effect for BlockData instances created by + /// methods such as {@link Server#createBlockData(String)} or any similar + /// method whereby states are optionally defined. If otherwise, the result of + /// {@link #getAsString()} will be returned. The following behaviour would be + /// expected: + ///
{@code
+    /// String dataString = "minecraft:chest[waterlogged=true]"
+    /// BlockData data = Bukkit.createBlockData(dataString);
+    /// dataString.equals(data.getAsString(true)); // This would return true
+    /// dataString.equals(data.getAsString(false)); // This would return false as all states are present
+    /// dataString.equals(data.getAsString()); // This is equivalent to the above, "getAsString(false)"
+    /// }
+ pub fn get_as_string( &self, - state: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/data/type/Vault/State;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(state.into().jni_object().clone()) - }); + hide_unspecified: bool, + ) -> Result> { + let sig = String::from("(Z)Ljava/lang/String;"); + let val_1 = jni::objects::JValueGen::Bool(hide_unspecified.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setTrialSpawnerState", + "getAsString", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the value of the 'ominous' property. - pub fn is_ominous(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isOminous", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets the value of the 'ominous' property. - pub fn set_ominous(&self, ominous: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(ominous.into()); + /// Merges all explicitly set states from the given data with this BlockData. + /// + /// Note that the given data MUST have been created from one of the String + /// parse methods, e.g. {@link Server#createBlockData(java.lang.String)} and + /// not have been subsequently modified. + /// + /// Note also that the block types must match identically. + pub fn merge( + &self, + data: impl Into>, + ) -> Result, Box> { + let sig = + String::from("(Lorg/bukkit/block/data/BlockData;)Lorg/bukkit/block/data/BlockData;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(data.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setOminous", + "merge", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the value of the 'facing' property. - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the value of the 'facing' property. - pub fn set_facing( + /// Checks if the specified BlockData matches this block data. + /// + /// The semantics of this method are such that for manually created or + /// modified BlockData it has the same effect as + /// {@link Object#equals(java.lang.Object)}, whilst for parsed data (that to + /// which {@link #merge(org.bukkit.block.data.BlockData)} applies, it will + /// return true when the type and all explicitly set states match. + /// + /// Note that these semantics mean that a.matches(b) may not be the same + /// as b.matches(a) + pub fn matches( &self, - facing: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + data: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/block/data/BlockData;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(facing.into().jni_object().clone()) + jni::objects::JObject::from_raw(data.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setFacing", + "matches", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the faces which are applicable to this block. - pub fn faces(&self) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Returns a copy of this BlockData. + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getFaces", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + /// Gets the block's {@link SoundGroup} which can be used to get its step + /// sound, hit sound, and others. + pub fn sound_group(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/SoundGroup;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSoundGroup", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::SoundGroup::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> Into> for Vault<'mc> { - fn into(self) -> crate::block::data::Directional<'mc> { - crate::block::data::Directional::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Vault into crate::block::data::Directional") + /// Get the amount of light emitted by this state when in the world. + pub fn light_emission(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLightEmission", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} -pub enum VaultState<'mc> {} -impl<'mc> std::fmt::Display for VaultState<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + /// Check whether or not this state will occlude other blocks. + /// + /// Block state occlusion affects visual features of other blocks (e.g. leaves and + /// wet sponges will not spawn dripping water particles if an occluding state is + /// below it), or whether light will pass through it. + pub fn is_occluding(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isOccluding", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} - -impl<'mc> VaultState<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/block/data/type/Vault/State"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/block/data/type/Vault/State;", - vec![jni::objects::JValueGen::from(val_1)], + /// Check whether or not this state requires a specific item to be used to drop + /// items when broken. For example, diamond ore requires an iron pickaxe and will + /// not drop diamonds when broken with a wooden or stone pickaxe. + pub fn requires_correct_tool_for_drops(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "requiresCorrectToolForDrops", + sig.as_str(), + vec![], ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct VaultStateStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for VaultState<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for VaultState<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate VaultState from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Vault/State")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a VaultState object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for VaultStateStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for VaultStateStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate VaultStateStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Vault/State")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a VaultStateStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> VaultStateStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/type/Vault/State;"); - let cls = jni.find_class("org/bukkit/block/data/type/Vault/State"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::block::data::mod_type::VaultState::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct TrialSpawner<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for TrialSpawner<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for TrialSpawner<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate TrialSpawner from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/TrialSpawner")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a TrialSpawner object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Returns if the given item is a preferred choice to break this Block. + /// In some cases this determines if a block will drop anything or extra + /// loot. + pub fn is_preferred_tool( + &self, + tool: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(tool.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isPreferredTool", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} - -impl<'mc> TrialSpawner<'mc> { - /// Gets the value of the 'trial_spawner_state' property. - pub fn trial_spawner_state( + /// Returns the reaction of the block when moved by a piston + pub fn piston_move_reaction( &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/block/data/type/TrialSpawner/State;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getTrialSpawnerState", + "getPistonMoveReaction", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::block::data::mod_type::TrialSpawnerState::from_raw(&self.jni_ref(), unsafe { + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the value of the 'trial_spawner_state' property. - pub fn set_trial_spawner_state( + /// Checks if this state would be properly supported if it were placed at + /// the block at the given {@link Location}. + /// + /// This may be useful, for instance, to check whether or not a wall torch is + /// capable of surviving on its neighbouring block states. + pub fn is_supported( &self, - state: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/data/type/TrialSpawner/State;)V"); + location: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(state.into().jni_object().clone()) + jni::objects::JObject::from_raw(location.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTrialSpawnerState", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the value of the 'ominous' property. - pub fn is_ominous(&self) -> Result> { - let sig = String::from("()Z"); + args.push(val_1); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isOminous", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSupported", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the value of the 'ominous' property. - pub fn set_ominous(&self, ominous: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(ominous.into()); + /// Checks if a state's {@link BlockFace} is capable of providing a given level + /// of {@link BlockSupport} for neighbouring block states. + /// + /// Any given state may support either none, one, or more than one level of block + /// support depending on its states. A common example would be a wall's ability to support + /// torches only on the center of the upper block face, whereas a grass block would + /// support all levels of block support on all block faces. + pub fn is_face_sturdy( + &self, + face: impl Into>, + support: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;Lorg/bukkit/block/BlockSupport;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(support.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setOminous", + "isFaceSturdy", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Get the Material represented by this block data. - pub fn material(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); + /// Gets the color this block should appear as when rendered on a map. + pub fn map_color(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Color;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaterial", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMapColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { + crate::Color::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets a string, which when passed into a method such as - /// {@link Server#createBlockData(java.lang.String)} will recreate this or a - /// similar instance where unspecified states (if any) may be optionally - /// omitted. If this instance was parsed and states are omitted, this exact - /// instance will be creatable when parsed again, else their equality cannot - /// be guaranteed. - /// - /// This method will only take effect for BlockData instances created by - /// methods such as {@link Server#createBlockData(String)} or any similar - /// method whereby states are optionally defined. If otherwise, the result of - /// {@link #getAsString()} will be returned. The following behaviour would be - /// expected: - ///
{@code
-    /// String dataString = "minecraft:chest[waterlogged=true]"
-    /// BlockData data = Bukkit.createBlockData(dataString);
-    /// dataString.equals(data.getAsString(true)); // This would return true
-    /// dataString.equals(data.getAsString(false)); // This would return false as all states are present
-    /// dataString.equals(data.getAsString()); // This is equivalent to the above, "getAsString(false)"
-    /// }
- pub fn get_as_string( - &self, - hide_unspecified: bool, - ) -> Result> { - let sig = String::from("(Z)Ljava/lang/String;"); - let val_1 = jni::objects::JValueGen::Bool(hide_unspecified.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAsString", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Merges all explicitly set states from the given data with this BlockData. - /// - /// Note that the given data MUST have been created from one of the String - /// parse methods, e.g. {@link Server#createBlockData(java.lang.String)} and - /// not have been subsequently modified. - /// - /// Note also that the block types must match identically. - pub fn merge( - &self, - data: impl Into>, - ) -> Result, Box> { - let sig = - String::from("(Lorg/bukkit/block/data/BlockData;)Lorg/bukkit/block/data/BlockData;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "merge", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Checks if the specified BlockData matches this block data. - /// - /// The semantics of this method are such that for manually created or - /// modified BlockData it has the same effect as - /// {@link Object#equals(java.lang.Object)}, whilst for parsed data (that to - /// which {@link #merge(org.bukkit.block.data.BlockData)} applies, it will - /// return true when the type and all explicitly set states match. - /// - /// Note that these semantics mean that a.matches(b) may not be the same - /// as b.matches(a) - pub fn matches( - &self, - data: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/block/data/BlockData;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "matches", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns a copy of this BlockData. - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the block's {@link SoundGroup} which can be used to get its step - /// sound, hit sound, and others. - pub fn sound_group(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/SoundGroup;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSoundGroup", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::SoundGroup::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the amount of light emitted by this state when in the world. - pub fn light_emission(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLightEmission", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Check whether or not this state will occlude other blocks. - /// - /// Block state occlusion affects visual features of other blocks (e.g. leaves and - /// wet sponges will not spawn dripping water particles if an occluding state is - /// below it), or whether light will pass through it. - pub fn is_occluding(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isOccluding", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Check whether or not this state requires a specific item to be used to drop - /// items when broken. For example, diamond ore requires an iron pickaxe and will - /// not drop diamonds when broken with a wooden or stone pickaxe. - pub fn requires_correct_tool_for_drops(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "requiresCorrectToolForDrops", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns if the given item is a preferred choice to break this Block. - /// In some cases this determines if a block will drop anything or extra - /// loot. - pub fn is_preferred_tool( - &self, - tool: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tool.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isPreferredTool", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the reaction of the block when moved by a piston - pub fn piston_move_reaction( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPistonMoveReaction", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Checks if this state would be properly supported if it were placed at - /// the block at the given {@link Location}. - /// - /// This may be useful, for instance, to check whether or not a wall torch is - /// capable of surviving on its neighbouring block states. - pub fn is_supported( - &self, - location: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSupported", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Checks if a state's {@link BlockFace} is capable of providing a given level - /// of {@link BlockSupport} for neighbouring block states. - /// - /// Any given state may support either none, one, or more than one level of block - /// support depending on its states. A common example would be a wall's ability to support - /// torches only on the center of the upper block face, whereas a grass block would - /// support all levels of block support on all block faces. - pub fn is_face_sturdy( - &self, - face: impl Into>, - support: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;Lorg/bukkit/block/BlockSupport;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(support.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isFaceSturdy", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the color this block should appear as when rendered on a map. - pub fn map_color(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Color;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMapColor", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Color::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the material that a player would use to place this block. + /// Gets the material that a player would use to place this block. /// /// For most blocks this is the same as {@link #getMaterial()} but some blocks /// have different materials used to place them. @@ -738,94 +441,19 @@ impl<'mc> TrialSpawner<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for TrialSpawner<'mc> { +impl<'mc> Into> for Sapling<'mc> { fn into(self) -> crate::block::data::BlockData<'mc> { crate::block::data::BlockData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting TrialSpawner into crate::block::data::BlockData") - } -} -pub enum TrialSpawnerState<'mc> {} -impl<'mc> std::fmt::Display for TrialSpawnerState<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + .expect("Error converting Sapling into crate::block::data::BlockData") } } +#[repr(C)] +pub struct Fence<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); -impl<'mc> TrialSpawnerState<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/block/data/type/TrialSpawner/State"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/block/data/type/TrialSpawner/State;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct TrialSpawnerStateStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for TrialSpawnerState<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for TrialSpawnerState<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate TrialSpawnerState from null object.").into(), - ); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/block/data/type/TrialSpawner/State")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a TrialSpawnerState object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for TrialSpawnerStateStruct<'mc> { +impl<'mc> JNIRaw<'mc> for Fence<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -833,22 +461,18 @@ impl<'mc> JNIRaw<'mc> for TrialSpawnerStateStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for TrialSpawnerStateStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Fence<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate TrialSpawnerStateStruct from null object." - ) - .into()); + return Err(eyre::eyre!("Tried to instantiate Fence from null object.").into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/block/data/type/TrialSpawner/State")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Fence")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a TrialSpawnerStateStruct object, got {}", + "Invalid argument passed. Expected a Fence object, got {}", name ) .into()) @@ -858,18 +482,93 @@ impl<'mc> JNIInstantiatable<'mc> for TrialSpawnerStateStruct<'mc> { } } -impl<'mc> TrialSpawnerStateStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/block/data/type/TrialSpawner/State;"); - let cls = jni.find_class("org/bukkit/block/data/type/TrialSpawner/State"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::block::data::mod_type::TrialSpawnerState::from_raw(&jni, obj) +impl<'mc> Fence<'mc> { + /// Checks if this block has the specified face enabled. + pub fn has_face( + &self, + face: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasFace", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set whether this block has the specified face enabled. + pub fn set_face( + &self, + face: impl Into>, + has: bool, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;Z)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Bool(has.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFace", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get all of the faces which are enabled on this block. + pub fn faces(&self) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFaces", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets all of this faces which may be set on this block. + pub fn allowed_faces( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAllowedFaces", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the value of the 'waterlogged' property. + pub fn is_waterlogged(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isWaterlogged", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the value of the 'waterlogged' property. + pub fn set_waterlogged(&self, waterlogged: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(waterlogged.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setWaterlogged", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -877,13 +576,25 @@ impl<'mc> TrialSpawnerStateStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for Fence<'mc> { + fn into(self) -> crate::block::data::MultipleFacing<'mc> { + crate::block::data::MultipleFacing::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Fence into crate::block::data::MultipleFacing") + } +} +impl<'mc> Into> for Fence<'mc> { + fn into(self) -> crate::block::data::Waterlogged<'mc> { + crate::block::data::Waterlogged::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Fence into crate::block::data::Waterlogged") + } +} #[repr(C)] -pub struct Crafter<'mc>( +pub struct Light<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Crafter<'mc> { +impl<'mc> JNIRaw<'mc> for Light<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -891,18 +602,18 @@ impl<'mc> JNIRaw<'mc> for Crafter<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Crafter<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Light<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Crafter from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Light from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Crafter")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Light")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Crafter object, got {}", + "Invalid argument passed. Expected a Light object, got {}", name ) .into()) @@ -912,82 +623,122 @@ impl<'mc> JNIInstantiatable<'mc> for Crafter<'mc> { } } -impl<'mc> Crafter<'mc> { - /// Gets the value of the 'crafting' property. - pub fn is_crafting(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCrafting", sig.as_str(), vec![]); +impl<'mc> Light<'mc> { + /// Gets the value of the 'level' property. + pub fn level(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLevel", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets the value of the 'crafting' property. - pub fn set_crafting(&self, crafting: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(crafting.into()); + /// Sets the value of the 'level' property. + pub fn set_level(&self, level: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(level); let res = self.jni_ref().call_method( &self.jni_object(), - "setCrafting", + "setLevel", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the value of the 'triggered' property. - pub fn is_triggered(&self) -> Result> { + /// Gets the maximum allowed value of the 'level' property. + pub fn maximum_level(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaximumLevel", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the value of the 'waterlogged' property. + pub fn is_waterlogged(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isTriggered", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isWaterlogged", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the value of the 'triggered' property. - pub fn set_triggered(&self, triggered: bool) -> Result<(), Box> { + /// Sets the value of the 'waterlogged' property. + pub fn set_waterlogged(&self, waterlogged: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(triggered.into()); + let val_1 = jni::objects::JValueGen::Bool(waterlogged.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setTriggered", + "setWaterlogged", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the value of the 'orientation' property. - pub fn orientation( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/block/data/type/Crafter/Orientation;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getOrientation", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::data::mod_type::CrafterOrientation::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Sets the value of the 'orientation' property. - pub fn set_orientation( - &self, - orientation: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/data/type/Crafter/Orientation;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(orientation.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setOrientation", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +} +impl<'mc> Into> for Light<'mc> { + fn into(self) -> crate::block::data::Levelled<'mc> { + crate::block::data::Levelled::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Light into crate::block::data::Levelled") + } +} +impl<'mc> Into> for Light<'mc> { + fn into(self) -> crate::block::data::Waterlogged<'mc> { + crate::block::data::Waterlogged::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Light into crate::block::data::Waterlogged") + } +} +#[repr(C)] +pub struct Jukebox<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Jukebox<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Jukebox<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Jukebox from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Jukebox")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Jukebox object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Jukebox<'mc> { + /// Gets the value of the 'has_record' property. + pub fn has_record(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasRecord", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } /// Get the Material represented by this block data. pub fn material(&self) -> Result, Box> { @@ -1361,94 +1112,129 @@ impl<'mc> Crafter<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Crafter<'mc> { +impl<'mc> Into> for Jukebox<'mc> { fn into(self) -> crate::block::data::BlockData<'mc> { crate::block::data::BlockData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Crafter into crate::block::data::BlockData") - } -} -pub enum CrafterOrientation<'mc> {} -impl<'mc> std::fmt::Display for CrafterOrientation<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> CrafterOrientation<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/block/data/type/Crafter/Orientation"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/block/data/type/Crafter/Orientation;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + .expect("Error converting Jukebox into crate::block::data::BlockData") } } - #[repr(C)] -pub struct CrafterOrientationStruct<'mc>( +pub struct Piston<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for CrafterOrientation<'mc> { +impl<'mc> JNIRaw<'mc> for Piston<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + self.0.clone() } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for CrafterOrientation<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Piston<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate CrafterOrientation from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate Piston from null object.").into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/block/data/type/Crafter/Orientation")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Piston")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a CrafterOrientation object, got {}", + "Invalid argument passed. Expected a Piston object, got {}", name ) .into()) } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + Ok(Self(env.clone(), obj)) } } } -impl<'mc> JNIRaw<'mc> for CrafterOrientationStruct<'mc> { +impl<'mc> Piston<'mc> { + /// Gets the value of the 'extended' property. + pub fn is_extended(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isExtended", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the value of the 'extended' property. + pub fn set_extended(&self, extended: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(extended.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setExtended", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the value of the 'facing' property. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the value of the 'facing' property. + pub fn set_facing( + &self, + facing: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(facing.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFacing", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the faces which are applicable to this block. + pub fn faces(&self) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFaces", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Piston<'mc> { + fn into(self) -> crate::block::data::Directional<'mc> { + crate::block::data::Directional::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Piston into crate::block::data::Directional") + } +} +#[repr(C)] +pub struct HangingSign<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for HangingSign<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1456,22 +1242,18 @@ impl<'mc> JNIRaw<'mc> for CrafterOrientationStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for CrafterOrientationStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for HangingSign<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate CrafterOrientationStruct from null object." - ) - .into()); + return Err(eyre::eyre!("Tried to instantiate HangingSign from null object.").into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/block/data/type/Crafter/Orientation")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/HangingSign")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a CrafterOrientationStruct object, got {}", + "Invalid argument passed. Expected a HangingSign object, got {}", name ) .into()) @@ -1481,18 +1263,79 @@ impl<'mc> JNIInstantiatable<'mc> for CrafterOrientationStruct<'mc> { } } -impl<'mc> CrafterOrientationStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/block/data/type/Crafter/Orientation;"); - let cls = jni.find_class("org/bukkit/block/data/type/Crafter/Orientation"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::block::data::mod_type::CrafterOrientation::from_raw(&jni, obj) +impl<'mc> HangingSign<'mc> { + /// Gets the value of the 'attached' property. + pub fn is_attached(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isAttached", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the value of the 'attached' property. + pub fn set_attached(&self, attached: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(attached.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAttached", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the value of the 'rotation' property. + pub fn rotation(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRotation", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the value of the 'rotation' property. + pub fn set_rotation( + &self, + rotation: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(rotation.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRotation", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the value of the 'waterlogged' property. + pub fn is_waterlogged(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isWaterlogged", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the value of the 'waterlogged' property. + pub fn set_waterlogged(&self, waterlogged: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(waterlogged.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setWaterlogged", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1500,13 +1343,31 @@ impl<'mc> CrafterOrientationStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for HangingSign<'mc> { + fn into(self) -> crate::block::data::Attachable<'mc> { + crate::block::data::Attachable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting HangingSign into crate::block::data::Attachable") + } +} +impl<'mc> Into> for HangingSign<'mc> { + fn into(self) -> crate::block::data::Rotatable<'mc> { + crate::block::data::Rotatable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting HangingSign into crate::block::data::Rotatable") + } +} +impl<'mc> Into> for HangingSign<'mc> { + fn into(self) -> crate::block::data::Waterlogged<'mc> { + crate::block::data::Waterlogged::from_raw(&self.jni_ref(), self.1) + .expect("Error converting HangingSign into crate::block::data::Waterlogged") + } +} #[repr(C)] -pub struct CopperBulb<'mc>( +pub struct RedstoneRail<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for CopperBulb<'mc> { +impl<'mc> JNIRaw<'mc> for RedstoneRail<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1514,18 +1375,18 @@ impl<'mc> JNIRaw<'mc> for CopperBulb<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for CopperBulb<'mc> { +impl<'mc> JNIInstantiatable<'mc> for RedstoneRail<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate CopperBulb from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate RedstoneRail from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/CopperBulb")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/RedstoneRail")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a CopperBulb object, got {}", + "Invalid argument passed. Expected a RedstoneRail object, got {}", name ) .into()) @@ -1535,76 +1396,96 @@ impl<'mc> JNIInstantiatable<'mc> for CopperBulb<'mc> { } } -impl<'mc> CopperBulb<'mc> { - /// Gets the value of the 'lit' property. - pub fn is_lit(&self) -> Result> { +impl<'mc> RedstoneRail<'mc> { + /// Gets the value of the 'powered' property. + pub fn is_powered(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isLit", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the value of the 'lit' property. - pub fn set_lit(&self, lit: bool) -> Result<(), Box> { + /// Sets the value of the 'powered' property. + pub fn set_powered(&self, powered: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(lit.into()); + let val_1 = jni::objects::JValueGen::Bool(powered.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLit", + "setPowered", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the value of the 'powered' property. - pub fn is_powered(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the value of the 'shape' property. + pub fn shape(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/Rail/Shape;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getShape", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::data::RailShape::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the value of the 'powered' property. - pub fn set_powered(&self, powered: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(powered.into()); + /// Sets the value of the 'shape' property. + pub fn set_shape( + &self, + shape: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/data/Rail/Shape;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(shape.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPowered", + "setShape", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } + /// Gets the shapes which are applicable to this block. + pub fn shapes( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getShapes", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for CopperBulb<'mc> { - fn into(self) -> crate::block::data::Lightable<'mc> { - crate::block::data::Lightable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting CopperBulb into crate::block::data::Lightable") - } -} -impl<'mc> Into> for CopperBulb<'mc> { +impl<'mc> Into> for RedstoneRail<'mc> { fn into(self) -> crate::block::data::Powerable<'mc> { crate::block::data::Powerable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting CopperBulb into crate::block::data::Powerable") + .expect("Error converting RedstoneRail into crate::block::data::Powerable") + } +} +impl<'mc> Into> for RedstoneRail<'mc> { + fn into(self) -> crate::block::data::Rail<'mc> { + crate::block::data::Rail::from_raw(&self.jni_ref(), self.1) + .expect("Error converting RedstoneRail into crate::block::data::Rail") } } #[repr(C)] -pub struct Sapling<'mc>( +pub struct BigDripleaf<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Sapling<'mc> { +impl<'mc> JNIRaw<'mc> for BigDripleaf<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1612,18 +1493,18 @@ impl<'mc> JNIRaw<'mc> for Sapling<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Sapling<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BigDripleaf<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Sapling from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate BigDripleaf from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Sapling")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/BigDripleaf")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Sapling object, got {}", + "Invalid argument passed. Expected a BigDripleaf object, got {}", name ) .into()) @@ -1633,538 +1514,233 @@ impl<'mc> JNIInstantiatable<'mc> for Sapling<'mc> { } } -impl<'mc> Sapling<'mc> { - /// Gets the value of the 'stage' property. - pub fn stage(&self) -> Result> { - let sig = String::from("()I"); +impl<'mc> BigDripleaf<'mc> { + /// Gets the value of the 'tilt' property. + pub fn tilt( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/block/data/type/BigDripleaf/Tilt;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getStage", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTilt", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::block::data::mod_type::BigDripleafTilt::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the value of the 'stage' property. - pub fn set_stage(&self, stage: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(stage); + /// Sets the value of the 'tilt' property. + pub fn set_tilt( + &self, + tilt: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/data/type/BigDripleaf/Tilt;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(tilt.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setStage", + "setTilt", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the maximum allowed value of the 'stage' property. - pub fn maximum_stage(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaximumStage", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Get the Material represented by this block data. - pub fn material(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaterial", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} +impl<'mc> Into> for BigDripleaf<'mc> { + fn into(self) -> crate::block::data::mod_type::Dripleaf<'mc> { + crate::block::data::mod_type::Dripleaf::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BigDripleaf into crate::block::data::mod_type::Dripleaf") } - /// Gets a string, which when passed into a method such as - /// {@link Server#createBlockData(java.lang.String)} will recreate this or a - /// similar instance where unspecified states (if any) may be optionally - /// omitted. If this instance was parsed and states are omitted, this exact - /// instance will be creatable when parsed again, else their equality cannot - /// be guaranteed. - /// - /// This method will only take effect for BlockData instances created by - /// methods such as {@link Server#createBlockData(String)} or any similar - /// method whereby states are optionally defined. If otherwise, the result of - /// {@link #getAsString()} will be returned. The following behaviour would be - /// expected: - ///
{@code
-    /// String dataString = "minecraft:chest[waterlogged=true]"
-    /// BlockData data = Bukkit.createBlockData(dataString);
-    /// dataString.equals(data.getAsString(true)); // This would return true
-    /// dataString.equals(data.getAsString(false)); // This would return false as all states are present
-    /// dataString.equals(data.getAsString()); // This is equivalent to the above, "getAsString(false)"
-    /// }
- pub fn get_as_string( - &self, - hide_unspecified: bool, - ) -> Result> { - let sig = String::from("(Z)Ljava/lang/String;"); - let val_1 = jni::objects::JValueGen::Bool(hide_unspecified.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAsString", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Merges all explicitly set states from the given data with this BlockData. - /// - /// Note that the given data MUST have been created from one of the String - /// parse methods, e.g. {@link Server#createBlockData(java.lang.String)} and - /// not have been subsequently modified. - /// - /// Note also that the block types must match identically. - pub fn merge( - &self, - data: impl Into>, - ) -> Result, Box> { - let sig = - String::from("(Lorg/bukkit/block/data/BlockData;)Lorg/bukkit/block/data/BlockData;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "merge", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Checks if the specified BlockData matches this block data. - /// - /// The semantics of this method are such that for manually created or - /// modified BlockData it has the same effect as - /// {@link Object#equals(java.lang.Object)}, whilst for parsed data (that to - /// which {@link #merge(org.bukkit.block.data.BlockData)} applies, it will - /// return true when the type and all explicitly set states match. - /// - /// Note that these semantics mean that a.matches(b) may not be the same - /// as b.matches(a) - pub fn matches( - &self, - data: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/block/data/BlockData;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "matches", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns a copy of this BlockData. - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the block's {@link SoundGroup} which can be used to get its step - /// sound, hit sound, and others. - pub fn sound_group(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/SoundGroup;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSoundGroup", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::SoundGroup::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the amount of light emitted by this state when in the world. - pub fn light_emission(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLightEmission", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Check whether or not this state will occlude other blocks. - /// - /// Block state occlusion affects visual features of other blocks (e.g. leaves and - /// wet sponges will not spawn dripping water particles if an occluding state is - /// below it), or whether light will pass through it. - pub fn is_occluding(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isOccluding", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Check whether or not this state requires a specific item to be used to drop - /// items when broken. For example, diamond ore requires an iron pickaxe and will - /// not drop diamonds when broken with a wooden or stone pickaxe. - pub fn requires_correct_tool_for_drops(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "requiresCorrectToolForDrops", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns if the given item is a preferred choice to break this Block. - /// In some cases this determines if a block will drop anything or extra - /// loot. - pub fn is_preferred_tool( - &self, - tool: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tool.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isPreferredTool", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the reaction of the block when moved by a piston - pub fn piston_move_reaction( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPistonMoveReaction", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Checks if this state would be properly supported if it were placed at - /// the block at the given {@link Location}. - /// - /// This may be useful, for instance, to check whether or not a wall torch is - /// capable of surviving on its neighbouring block states. - pub fn is_supported( - &self, - location: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSupported", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Checks if a state's {@link BlockFace} is capable of providing a given level - /// of {@link BlockSupport} for neighbouring block states. - /// - /// Any given state may support either none, one, or more than one level of block - /// support depending on its states. A common example would be a wall's ability to support - /// torches only on the center of the upper block face, whereas a grass block would - /// support all levels of block support on all block faces. - pub fn is_face_sturdy( - &self, - face: impl Into>, - support: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;Lorg/bukkit/block/BlockSupport;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(support.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isFaceSturdy", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the color this block should appear as when rendered on a map. - pub fn map_color(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Color;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMapColor", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Color::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the material that a player would use to place this block. - /// - /// For most blocks this is the same as {@link #getMaterial()} but some blocks - /// have different materials used to place them. - /// For example: - ///
-    /// {@link Material#REDSTONE_WIRE} -> {@link Material#REDSTONE}
-    /// {@link Material#CARROTS} -> {@link Material#CARROT}
-    /// 
- pub fn placement_material(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPlacementMaterial", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Rotates this blockdata by the specified {@link StructureRotation}. - /// - /// This has no effect on blocks that do not have any rotatable states. - pub fn rotate( - &self, - rotation: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/structure/StructureRotation;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(rotation.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "rotate", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Mirrors this blockdata using the specified {@link Mirror}. - /// - /// This has no effect on blocks that do not have any mirrorable states. - pub fn mirror( - &self, - mirror: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/structure/Mirror;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(mirror.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "mirror", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Copies all applicable properties from this BlockData to the provided - /// BlockData. - /// - /// Only modifies properties that both blocks share in common. - pub fn copy_to( - &self, - other: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "copyTo", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Creates a new default {@link BlockState} for this type of Block, not - /// bound to a location. - pub fn create_block_state( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockState;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "createBlockState", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) +} +pub enum BigDripleafTilt<'mc> { + None { inner: BigDripleafTiltStruct<'mc> }, + Unstable { inner: BigDripleafTiltStruct<'mc> }, + Partial { inner: BigDripleafTiltStruct<'mc> }, + Full { inner: BigDripleafTiltStruct<'mc> }, +} +impl<'mc> std::fmt::Display for BigDripleafTilt<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + BigDripleafTilt::None { .. } => f.write_str("NONE"), + BigDripleafTilt::Unstable { .. } => f.write_str("UNSTABLE"), + BigDripleafTilt::Partial { .. } => f.write_str("PARTIAL"), + BigDripleafTilt::Full { .. } => f.write_str("FULL"), + } } } -impl<'mc> Into> for Sapling<'mc> { - fn into(self) -> crate::block::data::BlockData<'mc> { - crate::block::data::BlockData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Sapling into crate::block::data::BlockData") +impl<'mc> std::ops::Deref for BigDripleafTilt<'mc> { + type Target = BigDripleafTiltStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + BigDripleafTilt::None { inner } => inner, + BigDripleafTilt::Unstable { inner } => inner, + BigDripleafTilt::Partial { inner } => inner, + BigDripleafTilt::Full { inner } => inner, + } + } +} + +impl<'mc> BigDripleafTilt<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/block/data/type/BigDripleaf/Tilt"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/block/data/type/BigDripleaf/Tilt;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "NONE" => Ok(BigDripleafTilt::None { + inner: BigDripleafTiltStruct::from_raw(env, obj)?, + }), + "UNSTABLE" => Ok(BigDripleafTilt::Unstable { + inner: BigDripleafTiltStruct::from_raw(env, obj)?, + }), + "PARTIAL" => Ok(BigDripleafTilt::Partial { + inner: BigDripleafTiltStruct::from_raw(env, obj)?, + }), + "FULL" => Ok(BigDripleafTilt::Full { + inner: BigDripleafTiltStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } + #[repr(C)] -pub struct Fence<'mc>( +pub struct BigDripleafTiltStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Fence<'mc> { +impl<'mc> JNIRaw<'mc> for BigDripleafTilt<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + match self { + Self::None { inner } => inner.0.clone(), + Self::Unstable { inner } => inner.0.clone(), + Self::Partial { inner } => inner.0.clone(), + Self::Full { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + match self { + Self::None { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Unstable { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Partial { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Full { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for Fence<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BigDripleafTilt<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Fence from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate BigDripleafTilt from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Fence")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/block/data/type/BigDripleaf/Tilt")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Fence object, got {}", + "Invalid argument passed. Expected a BigDripleafTilt object, got {}", name ) .into()) } else { - Ok(Self(env.clone(), obj)) + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "NONE" => Ok(BigDripleafTilt::None { + inner: BigDripleafTiltStruct::from_raw(env, obj)?, + }), + "UNSTABLE" => Ok(BigDripleafTilt::Unstable { + inner: BigDripleafTiltStruct::from_raw(env, obj)?, + }), + "PARTIAL" => Ok(BigDripleafTilt::Partial { + inner: BigDripleafTiltStruct::from_raw(env, obj)?, + }), + "FULL" => Ok(BigDripleafTilt::Full { + inner: BigDripleafTiltStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } } -impl<'mc> Fence<'mc> { - /// Checks if this block has the specified face enabled. - pub fn has_face( - &self, - face: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasFace", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Set whether this block has the specified face enabled. - pub fn set_face( - &self, - face: impl Into>, - has: bool, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;Z)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Bool(has.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFace", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get all of the faces which are enabled on this block. - pub fn faces(&self) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFaces", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +impl<'mc> JNIRaw<'mc> for BigDripleafTiltStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Gets all of this faces which may be set on this block. - pub fn allowed_faces( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAllowedFaces", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Gets the value of the 'waterlogged' property. - pub fn is_waterlogged(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isWaterlogged", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} +impl<'mc> JNIInstantiatable<'mc> for BigDripleafTiltStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate BigDripleafTiltStruct from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/block/data/type/BigDripleaf/Tilt")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BigDripleafTiltStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } - /// Sets the value of the 'waterlogged' property. - pub fn set_waterlogged(&self, waterlogged: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(waterlogged.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setWaterlogged", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +} + +impl<'mc> BigDripleafTiltStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/block/data/type/BigDripleaf/Tilt;"); + let cls = jni.find_class("org/bukkit/block/data/type/BigDripleaf/Tilt"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::block::data::mod_type::BigDripleafTilt::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -2172,25 +1748,13 @@ impl<'mc> Fence<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Fence<'mc> { - fn into(self) -> crate::block::data::MultipleFacing<'mc> { - crate::block::data::MultipleFacing::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Fence into crate::block::data::MultipleFacing") - } -} -impl<'mc> Into> for Fence<'mc> { - fn into(self) -> crate::block::data::Waterlogged<'mc> { - crate::block::data::Waterlogged::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Fence into crate::block::data::Waterlogged") - } -} #[repr(C)] -pub struct Light<'mc>( +pub struct Candle<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Light<'mc> { +impl<'mc> JNIRaw<'mc> for Candle<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2198,18 +1762,18 @@ impl<'mc> JNIRaw<'mc> for Light<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Light<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Candle<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Light from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Candle from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Light")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Candle")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Light object, got {}", + "Invalid argument passed. Expected a Candle object, got {}", name ) .into()) @@ -2219,38 +1783,63 @@ impl<'mc> JNIInstantiatable<'mc> for Light<'mc> { } } -impl<'mc> Light<'mc> { - /// Gets the value of the 'level' property. - pub fn level(&self) -> Result> { +impl<'mc> Candle<'mc> { + /// Gets the value of the 'candles' property. + pub fn candles(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCandles", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the value of the 'candles' property. + pub fn set_candles(&self, candles: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(candles); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCandles", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the maximum allowed value of the 'candles' property. + pub fn maximum_candles(&self) -> Result> { let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaximumCandles", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the value of the 'lit' property. + pub fn is_lit(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getLevel", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isLit", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the value of the 'level' property. - pub fn set_level(&self, level: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(level); + /// Sets the value of the 'lit' property. + pub fn set_lit(&self, lit: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(lit.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLevel", + "setLit", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the maximum allowed value of the 'level' property. - pub fn maximum_level(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaximumLevel", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } /// Gets the value of the 'waterlogged' property. pub fn is_waterlogged(&self) -> Result> { let sig = String::from("()Z"); @@ -2279,25 +1868,25 @@ impl<'mc> Light<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Light<'mc> { - fn into(self) -> crate::block::data::Levelled<'mc> { - crate::block::data::Levelled::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Light into crate::block::data::Levelled") +impl<'mc> Into> for Candle<'mc> { + fn into(self) -> crate::block::data::Lightable<'mc> { + crate::block::data::Lightable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Candle into crate::block::data::Lightable") } } -impl<'mc> Into> for Light<'mc> { +impl<'mc> Into> for Candle<'mc> { fn into(self) -> crate::block::data::Waterlogged<'mc> { crate::block::data::Waterlogged::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Light into crate::block::data::Waterlogged") + .expect("Error converting Candle into crate::block::data::Waterlogged") } } #[repr(C)] -pub struct Jukebox<'mc>( +pub struct Stairs<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Jukebox<'mc> { +impl<'mc> JNIRaw<'mc> for Stairs<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2305,18 +1894,18 @@ impl<'mc> JNIRaw<'mc> for Jukebox<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Jukebox<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Stairs<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Jukebox from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Stairs from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Jukebox")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Stairs")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Jukebox object, got {}", + "Invalid argument passed. Expected a Stairs object, got {}", name ) .into()) @@ -2326,381 +1915,350 @@ impl<'mc> JNIInstantiatable<'mc> for Jukebox<'mc> { } } -impl<'mc> Jukebox<'mc> { - /// Gets the value of the 'has_record' property. - pub fn has_record(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasRecord", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the Material represented by this block data. - pub fn material(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaterial", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets a string, which when passed into a method such as - /// {@link Server#createBlockData(java.lang.String)} will recreate this or a - /// similar instance where unspecified states (if any) may be optionally - /// omitted. If this instance was parsed and states are omitted, this exact - /// instance will be creatable when parsed again, else their equality cannot - /// be guaranteed. - /// - /// This method will only take effect for BlockData instances created by - /// methods such as {@link Server#createBlockData(String)} or any similar - /// method whereby states are optionally defined. If otherwise, the result of - /// {@link #getAsString()} will be returned. The following behaviour would be - /// expected: - ///
{@code
-    /// String dataString = "minecraft:chest[waterlogged=true]"
-    /// BlockData data = Bukkit.createBlockData(dataString);
-    /// dataString.equals(data.getAsString(true)); // This would return true
-    /// dataString.equals(data.getAsString(false)); // This would return false as all states are present
-    /// dataString.equals(data.getAsString()); // This is equivalent to the above, "getAsString(false)"
-    /// }
- pub fn get_as_string( - &self, - hide_unspecified: bool, - ) -> Result> { - let sig = String::from("(Z)Ljava/lang/String;"); - let val_1 = jni::objects::JValueGen::Bool(hide_unspecified.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAsString", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Merges all explicitly set states from the given data with this BlockData. - /// - /// Note that the given data MUST have been created from one of the String - /// parse methods, e.g. {@link Server#createBlockData(java.lang.String)} and - /// not have been subsequently modified. - /// - /// Note also that the block types must match identically. - pub fn merge( - &self, - data: impl Into>, - ) -> Result, Box> { - let sig = - String::from("(Lorg/bukkit/block/data/BlockData;)Lorg/bukkit/block/data/BlockData;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "merge", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Checks if the specified BlockData matches this block data. - /// - /// The semantics of this method are such that for manually created or - /// modified BlockData it has the same effect as - /// {@link Object#equals(java.lang.Object)}, whilst for parsed data (that to - /// which {@link #merge(org.bukkit.block.data.BlockData)} applies, it will - /// return true when the type and all explicitly set states match. - /// - /// Note that these semantics mean that a.matches(b) may not be the same - /// as b.matches(a) - pub fn matches( +impl<'mc> Stairs<'mc> { + /// Gets the value of the 'shape' property. + pub fn shape( &self, - data: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/block/data/BlockData;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "matches", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns a copy of this BlockData. - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/type/Stairs/Shape;"); let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the block's {@link SoundGroup} which can be used to get its step - /// sound, hit sound, and others. - pub fn sound_group(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/SoundGroup;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSoundGroup", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::SoundGroup::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the amount of light emitted by this state when in the world. - pub fn light_emission(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLightEmission", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Check whether or not this state will occlude other blocks. - /// - /// Block state occlusion affects visual features of other blocks (e.g. leaves and - /// wet sponges will not spawn dripping water particles if an occluding state is - /// below it), or whether light will pass through it. - pub fn is_occluding(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isOccluding", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Check whether or not this state requires a specific item to be used to drop - /// items when broken. For example, diamond ore requires an iron pickaxe and will - /// not drop diamonds when broken with a wooden or stone pickaxe. - pub fn requires_correct_tool_for_drops(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "requiresCorrectToolForDrops", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns if the given item is a preferred choice to break this Block. - /// In some cases this determines if a block will drop anything or extra - /// loot. - pub fn is_preferred_tool( - &self, - tool: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tool.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isPreferredTool", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the reaction of the block when moved by a piston - pub fn piston_move_reaction( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPistonMoveReaction", - sig.as_str(), - vec![], - ); + .jni_ref() + .call_method(&self.jni_object(), "getShape", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + crate::block::data::mod_type::StairsShape::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Checks if this state would be properly supported if it were placed at - /// the block at the given {@link Location}. - /// - /// This may be useful, for instance, to check whether or not a wall torch is - /// capable of surviving on its neighbouring block states. - pub fn is_supported( + /// Sets the value of the 'shape' property. + pub fn set_shape( &self, - location: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; + shape: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/data/type/Stairs/Shape;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) + jni::objects::JObject::from_raw(shape.into().jni_object().clone()) }); - args.push(val_1); - sig += ")Z"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "setShape", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the value of the 'half' property. + pub fn half( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/Bisected/Half;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isSupported", sig.as_str(), args); + .call_method(&self.jni_object(), "getHalf", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::data::BisectedHalf::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Checks if a state's {@link BlockFace} is capable of providing a given level - /// of {@link BlockSupport} for neighbouring block states. - /// - /// Any given state may support either none, one, or more than one level of block - /// support depending on its states. A common example would be a wall's ability to support - /// torches only on the center of the upper block face, whereas a grass block would - /// support all levels of block support on all block faces. - pub fn is_face_sturdy( + /// Sets the value of the 'half' property. + pub fn set_half( &self, - face: impl Into>, - support: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;Lorg/bukkit/block/BlockSupport;)Z"); + half: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/data/Bisected/Half;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(support.into().jni_object().clone()) + jni::objects::JObject::from_raw(half.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "isFaceSturdy", + "setHalf", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the color this block should appear as when rendered on a map. - pub fn map_color(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Color;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMapColor", sig.as_str(), vec![]); + /// Gets the value of the 'facing' property. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Color::from_raw(&self.jni_ref(), unsafe { + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the material that a player would use to place this block. - /// - /// For most blocks this is the same as {@link #getMaterial()} but some blocks - /// have different materials used to place them. - /// For example: - ///
-    /// {@link Material#REDSTONE_WIRE} -> {@link Material#REDSTONE}
-    /// {@link Material#CARROTS} -> {@link Material#CARROT}
-    /// 
- pub fn placement_material(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); + /// Sets the value of the 'facing' property. + pub fn set_facing( + &self, + facing: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(facing.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getPlacementMaterial", + "setFacing", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the faces which are applicable to this block. + pub fn faces(&self) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFaces", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Rotates this blockdata by the specified {@link StructureRotation}. - /// - /// This has no effect on blocks that do not have any rotatable states. - pub fn rotate( - &self, - rotation: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/structure/StructureRotation;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(rotation.into().jni_object().clone()) - }); + /// Gets the value of the 'waterlogged' property. + pub fn is_waterlogged(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isWaterlogged", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the value of the 'waterlogged' property. + pub fn set_waterlogged(&self, waterlogged: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(waterlogged.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "rotate", + "setWaterlogged", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Mirrors this blockdata using the specified {@link Mirror}. - /// - /// This has no effect on blocks that do not have any mirrorable states. - pub fn mirror( - &self, - mirror: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/structure/Mirror;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(mirror.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "mirror", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Stairs<'mc> { + fn into(self) -> crate::block::data::Bisected<'mc> { + crate::block::data::Bisected::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Stairs into crate::block::data::Bisected") + } +} +impl<'mc> Into> for Stairs<'mc> { + fn into(self) -> crate::block::data::Directional<'mc> { + crate::block::data::Directional::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Stairs into crate::block::data::Directional") + } +} +impl<'mc> Into> for Stairs<'mc> { + fn into(self) -> crate::block::data::Waterlogged<'mc> { + crate::block::data::Waterlogged::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Stairs into crate::block::data::Waterlogged") + } +} +pub enum StairsShape<'mc> { + Straight { inner: StairsShapeStruct<'mc> }, + InnerLeft { inner: StairsShapeStruct<'mc> }, + InnerRight { inner: StairsShapeStruct<'mc> }, + OuterLeft { inner: StairsShapeStruct<'mc> }, + OuterRight { inner: StairsShapeStruct<'mc> }, +} +impl<'mc> std::fmt::Display for StairsShape<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + StairsShape::Straight { .. } => f.write_str("STRAIGHT"), + StairsShape::InnerLeft { .. } => f.write_str("INNER_LEFT"), + StairsShape::InnerRight { .. } => f.write_str("INNER_RIGHT"), + StairsShape::OuterLeft { .. } => f.write_str("OUTER_LEFT"), + StairsShape::OuterRight { .. } => f.write_str("OUTER_RIGHT"), + } + } +} +impl<'mc> std::ops::Deref for StairsShape<'mc> { + type Target = StairsShapeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + StairsShape::Straight { inner } => inner, + StairsShape::InnerLeft { inner } => inner, + StairsShape::InnerRight { inner } => inner, + StairsShape::OuterLeft { inner } => inner, + StairsShape::OuterRight { inner } => inner, + } + } +} + +impl<'mc> StairsShape<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/block/data/type/Stairs/Shape"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/block/data/type/Stairs/Shape;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "STRAIGHT" => Ok(StairsShape::Straight { + inner: StairsShapeStruct::from_raw(env, obj)?, + }), + "INNER_LEFT" => Ok(StairsShape::InnerLeft { + inner: StairsShapeStruct::from_raw(env, obj)?, + }), + "INNER_RIGHT" => Ok(StairsShape::InnerRight { + inner: StairsShapeStruct::from_raw(env, obj)?, + }), + "OUTER_LEFT" => Ok(StairsShape::OuterLeft { + inner: StairsShapeStruct::from_raw(env, obj)?, + }), + "OUTER_RIGHT" => Ok(StairsShape::OuterRight { + inner: StairsShapeStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct StairsShapeStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for StairsShape<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Straight { inner } => inner.0.clone(), + Self::InnerLeft { inner } => inner.0.clone(), + Self::InnerRight { inner } => inner.0.clone(), + Self::OuterLeft { inner } => inner.0.clone(), + Self::OuterRight { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Straight { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::InnerLeft { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::InnerRight { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OuterLeft { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OuterRight { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for StairsShape<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate StairsShape from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Stairs/Shape")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a StairsShape object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "STRAIGHT" => Ok(StairsShape::Straight { + inner: StairsShapeStruct::from_raw(env, obj)?, + }), + "INNER_LEFT" => Ok(StairsShape::InnerLeft { + inner: StairsShapeStruct::from_raw(env, obj)?, + }), + "INNER_RIGHT" => Ok(StairsShape::InnerRight { + inner: StairsShapeStruct::from_raw(env, obj)?, + }), + "OUTER_LEFT" => Ok(StairsShape::OuterLeft { + inner: StairsShapeStruct::from_raw(env, obj)?, + }), + "OUTER_RIGHT" => Ok(StairsShape::OuterRight { + inner: StairsShapeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for StairsShapeStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Copies all applicable properties from this BlockData to the provided - /// BlockData. - /// - /// Only modifies properties that both blocks share in common. - pub fn copy_to( - &self, - other: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "copyTo", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Creates a new default {@link BlockState} for this type of Block, not - /// bound to a location. - pub fn create_block_state( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockState;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "createBlockState", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} +impl<'mc> JNIInstantiatable<'mc> for StairsShapeStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate StairsShapeStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Stairs/Shape")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a StairsShapeStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> StairsShapeStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/type/Stairs/Shape;"); + let cls = jni.find_class("org/bukkit/block/data/type/Stairs/Shape"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::block::data::mod_type::StairsShape::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -2708,19 +2266,13 @@ impl<'mc> Jukebox<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Jukebox<'mc> { - fn into(self) -> crate::block::data::BlockData<'mc> { - crate::block::data::BlockData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Jukebox into crate::block::data::BlockData") - } -} #[repr(C)] -pub struct Piston<'mc>( +pub struct Crafter<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Piston<'mc> { +impl<'mc> JNIRaw<'mc> for Crafter<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2728,18 +2280,18 @@ impl<'mc> JNIRaw<'mc> for Piston<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Piston<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Crafter<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Piston from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Crafter from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Piston")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Crafter")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Piston object, got {}", + "Invalid argument passed. Expected a Crafter object, got {}", name ) .into()) @@ -2749,431 +2301,549 @@ impl<'mc> JNIInstantiatable<'mc> for Piston<'mc> { } } -impl<'mc> Piston<'mc> { - /// Gets the value of the 'extended' property. - pub fn is_extended(&self) -> Result> { +impl<'mc> Crafter<'mc> { + /// Gets the value of the 'crafting' property. + pub fn is_crafting(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isExtended", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCrafting", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the value of the 'extended' property. - pub fn set_extended(&self, extended: bool) -> Result<(), Box> { + /// Sets the value of the 'crafting' property. + pub fn set_crafting(&self, crafting: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(extended.into()); + let val_1 = jni::objects::JValueGen::Bool(crafting.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setExtended", + "setCrafting", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the value of the 'facing' property. - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self + /// Gets the value of the 'triggered' property. + pub fn is_triggered(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isTriggered", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the value of the 'triggered' property. + pub fn set_triggered(&self, triggered: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(triggered.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTriggered", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the value of the 'orientation' property. + pub fn orientation( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/block/data/type/Crafter/Orientation;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getOrientation", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::data::mod_type::CrafterOrientation::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the value of the 'orientation' property. + pub fn set_orientation( + &self, + orientation: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/data/type/Crafter/Orientation;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(orientation.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setOrientation", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the Material represented by this block data. + pub fn material(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaterial", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets a string, which when passed into a method such as + /// {@link Server#createBlockData(java.lang.String)} will recreate this or a + /// similar instance where unspecified states (if any) may be optionally + /// omitted. If this instance was parsed and states are omitted, this exact + /// instance will be creatable when parsed again, else their equality cannot + /// be guaranteed. + /// + /// This method will only take effect for BlockData instances created by + /// methods such as {@link Server#createBlockData(String)} or any similar + /// method whereby states are optionally defined. If otherwise, the result of + /// {@link #getAsString()} will be returned. The following behaviour would be + /// expected: + ///
{@code
+    /// String dataString = "minecraft:chest[waterlogged=true]"
+    /// BlockData data = Bukkit.createBlockData(dataString);
+    /// dataString.equals(data.getAsString(true)); // This would return true
+    /// dataString.equals(data.getAsString(false)); // This would return false as all states are present
+    /// dataString.equals(data.getAsString()); // This is equivalent to the above, "getAsString(false)"
+    /// }
+ pub fn get_as_string( + &self, + hide_unspecified: bool, + ) -> Result> { + let sig = String::from("(Z)Ljava/lang/String;"); + let val_1 = jni::objects::JValueGen::Bool(hide_unspecified.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAsString", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Merges all explicitly set states from the given data with this BlockData. + /// + /// Note that the given data MUST have been created from one of the String + /// parse methods, e.g. {@link Server#createBlockData(java.lang.String)} and + /// not have been subsequently modified. + /// + /// Note also that the block types must match identically. + pub fn merge( + &self, + data: impl Into>, + ) -> Result, Box> { + let sig = + String::from("(Lorg/bukkit/block/data/BlockData;)Lorg/bukkit/block/data/BlockData;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(data.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "merge", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the value of the 'facing' property. - pub fn set_facing( + /// Checks if the specified BlockData matches this block data. + /// + /// The semantics of this method are such that for manually created or + /// modified BlockData it has the same effect as + /// {@link Object#equals(java.lang.Object)}, whilst for parsed data (that to + /// which {@link #merge(org.bukkit.block.data.BlockData)} applies, it will + /// return true when the type and all explicitly set states match. + /// + /// Note that these semantics mean that a.matches(b) may not be the same + /// as b.matches(a) + pub fn matches( &self, - facing: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + data: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/block/data/BlockData;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(facing.into().jni_object().clone()) + jni::objects::JObject::from_raw(data.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setFacing", + "matches", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the faces which are applicable to this block. - pub fn faces(&self) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Returns a copy of this BlockData. + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getFaces", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Piston<'mc> { - fn into(self) -> crate::block::data::Directional<'mc> { - crate::block::data::Directional::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Piston into crate::block::data::Directional") - } -} -#[repr(C)] -pub struct HangingSign<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for HangingSign<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets the block's {@link SoundGroup} which can be used to get its step + /// sound, hit sound, and others. + pub fn sound_group(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/SoundGroup;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSoundGroup", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::SoundGroup::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> JNIInstantiatable<'mc> for HangingSign<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate HangingSign from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/HangingSign")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a HangingSign object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Get the amount of light emitted by this state when in the world. + pub fn light_emission(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLightEmission", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} - -impl<'mc> HangingSign<'mc> { - /// Gets the value of the 'attached' property. - pub fn is_attached(&self) -> Result> { + /// Check whether or not this state will occlude other blocks. + /// + /// Block state occlusion affects visual features of other blocks (e.g. leaves and + /// wet sponges will not spawn dripping water particles if an occluding state is + /// below it), or whether light will pass through it. + pub fn is_occluding(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isAttached", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isOccluding", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the value of the 'attached' property. - pub fn set_attached(&self, attached: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(attached.into()); + /// Check whether or not this state requires a specific item to be used to drop + /// items when broken. For example, diamond ore requires an iron pickaxe and will + /// not drop diamonds when broken with a wooden or stone pickaxe. + pub fn requires_correct_tool_for_drops(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "setAttached", + "requiresCorrectToolForDrops", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the value of the 'rotation' property. - pub fn rotation(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRotation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets the value of the 'rotation' property. - pub fn set_rotation( + /// Returns if the given item is a preferred choice to break this Block. + /// In some cases this determines if a block will drop anything or extra + /// loot. + pub fn is_preferred_tool( &self, - rotation: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + tool: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(rotation.into().jni_object().clone()) + jni::objects::JObject::from_raw(tool.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setRotation", + "isPreferredTool", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the value of the 'waterlogged' property. - pub fn is_waterlogged(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isWaterlogged", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the value of the 'waterlogged' property. - pub fn set_waterlogged(&self, waterlogged: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(waterlogged.into()); + /// Returns the reaction of the block when moved by a piston + pub fn piston_move_reaction( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setWaterlogged", + "getPistonMoveReaction", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for HangingSign<'mc> { - fn into(self) -> crate::block::data::Attachable<'mc> { - crate::block::data::Attachable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting HangingSign into crate::block::data::Attachable") - } -} -impl<'mc> Into> for HangingSign<'mc> { - fn into(self) -> crate::block::data::Rotatable<'mc> { - crate::block::data::Rotatable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting HangingSign into crate::block::data::Rotatable") - } -} -impl<'mc> Into> for HangingSign<'mc> { - fn into(self) -> crate::block::data::Waterlogged<'mc> { - crate::block::data::Waterlogged::from_raw(&self.jni_ref(), self.1) - .expect("Error converting HangingSign into crate::block::data::Waterlogged") - } -} -#[repr(C)] -pub struct RedstoneRail<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for RedstoneRail<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for RedstoneRail<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate RedstoneRail from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/RedstoneRail")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a RedstoneRail object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + let res = self.jni_ref().translate_error(res)?; + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} - -impl<'mc> RedstoneRail<'mc> { - /// Gets the value of the 'powered' property. - pub fn is_powered(&self) -> Result> { - let sig = String::from("()Z"); + /// Checks if this state would be properly supported if it were placed at + /// the block at the given {@link Location}. + /// + /// This may be useful, for instance, to check whether or not a wall torch is + /// capable of surviving on its neighbouring block states. + pub fn is_supported( + &self, + location: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSupported", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the value of the 'powered' property. - pub fn set_powered(&self, powered: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(powered.into()); + /// Checks if a state's {@link BlockFace} is capable of providing a given level + /// of {@link BlockSupport} for neighbouring block states. + /// + /// Any given state may support either none, one, or more than one level of block + /// support depending on its states. A common example would be a wall's ability to support + /// torches only on the center of the upper block face, whereas a grass block would + /// support all levels of block support on all block faces. + pub fn is_face_sturdy( + &self, + face: impl Into>, + support: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;Lorg/bukkit/block/BlockSupport;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(support.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPowered", + "isFaceSturdy", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the value of the 'shape' property. - pub fn shape(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/Rail/Shape;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getShape", sig.as_str(), vec![]); + /// Gets the color this block should appear as when rendered on a map. + pub fn map_color(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Color;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMapColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::data::RailShape::from_raw(&self.jni_ref(), unsafe { + crate::Color::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the value of the 'shape' property. - pub fn set_shape( + /// Gets the material that a player would use to place this block. + /// + /// For most blocks this is the same as {@link #getMaterial()} but some blocks + /// have different materials used to place them. + /// For example: + ///
+    /// {@link Material#REDSTONE_WIRE} -> {@link Material#REDSTONE}
+    /// {@link Material#CARROTS} -> {@link Material#CARROT}
+    /// 
+ pub fn placement_material(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPlacementMaterial", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Rotates this blockdata by the specified {@link StructureRotation}. + /// + /// This has no effect on blocks that do not have any rotatable states. + pub fn rotate( &self, - shape: impl Into>, + rotation: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/data/Rail/Shape;)V"); + let sig = String::from("(Lorg/bukkit/block/structure/StructureRotation;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(shape.into().jni_object().clone()) + jni::objects::JObject::from_raw(rotation.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setShape", + "rotate", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the shapes which are applicable to this block. - pub fn shapes( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getShapes", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for RedstoneRail<'mc> { - fn into(self) -> crate::block::data::Powerable<'mc> { - crate::block::data::Powerable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting RedstoneRail into crate::block::data::Powerable") - } -} -impl<'mc> Into> for RedstoneRail<'mc> { - fn into(self) -> crate::block::data::Rail<'mc> { - crate::block::data::Rail::from_raw(&self.jni_ref(), self.1) - .expect("Error converting RedstoneRail into crate::block::data::Rail") - } -} -#[repr(C)] -pub struct BigDripleaf<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for BigDripleaf<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for BigDripleaf<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate BigDripleaf from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/BigDripleaf")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a BigDripleaf object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> BigDripleaf<'mc> { - /// Gets the value of the 'tilt' property. - pub fn tilt( + /// Mirrors this blockdata using the specified {@link Mirror}. + /// + /// This has no effect on blocks that do not have any mirrorable states. + pub fn mirror( &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/block/data/type/BigDripleaf/Tilt;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTilt", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::data::mod_type::BigDripleafTilt::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + mirror: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/structure/Mirror;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(mirror.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "mirror", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the value of the 'tilt' property. - pub fn set_tilt( + /// Copies all applicable properties from this BlockData to the provided + /// BlockData. + /// + /// Only modifies properties that both blocks share in common. + pub fn copy_to( &self, - tilt: impl Into>, + other: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/data/type/BigDripleaf/Tilt;)V"); + let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tilt.into().jni_object().clone()) + jni::objects::JObject::from_raw(other.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setTilt", + "copyTo", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } + /// Creates a new default {@link BlockState} for this type of Block, not + /// bound to a location. + pub fn create_block_state( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockState;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "createBlockState", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BigDripleaf<'mc> { - fn into(self) -> crate::block::data::mod_type::Dripleaf<'mc> { - crate::block::data::mod_type::Dripleaf::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BigDripleaf into crate::block::data::mod_type::Dripleaf") +impl<'mc> Into> for Crafter<'mc> { + fn into(self) -> crate::block::data::BlockData<'mc> { + crate::block::data::BlockData::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Crafter into crate::block::data::BlockData") } } -pub enum BigDripleafTilt<'mc> {} -impl<'mc> std::fmt::Display for BigDripleafTilt<'mc> { +pub enum CrafterOrientation<'mc> { + DownEast { + inner: CrafterOrientationStruct<'mc>, + }, + DownNorth { + inner: CrafterOrientationStruct<'mc>, + }, + DownSouth { + inner: CrafterOrientationStruct<'mc>, + }, + DownWest { + inner: CrafterOrientationStruct<'mc>, + }, + UpEast { + inner: CrafterOrientationStruct<'mc>, + }, + UpNorth { + inner: CrafterOrientationStruct<'mc>, + }, + UpSouth { + inner: CrafterOrientationStruct<'mc>, + }, + UpWest { + inner: CrafterOrientationStruct<'mc>, + }, + WestUp { + inner: CrafterOrientationStruct<'mc>, + }, + EastUp { + inner: CrafterOrientationStruct<'mc>, + }, + NorthUp { + inner: CrafterOrientationStruct<'mc>, + }, + SouthUp { + inner: CrafterOrientationStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for CrafterOrientation<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + CrafterOrientation::DownEast { .. } => f.write_str("DOWN_EAST"), + CrafterOrientation::DownNorth { .. } => f.write_str("DOWN_NORTH"), + CrafterOrientation::DownSouth { .. } => f.write_str("DOWN_SOUTH"), + CrafterOrientation::DownWest { .. } => f.write_str("DOWN_WEST"), + CrafterOrientation::UpEast { .. } => f.write_str("UP_EAST"), + CrafterOrientation::UpNorth { .. } => f.write_str("UP_NORTH"), + CrafterOrientation::UpSouth { .. } => f.write_str("UP_SOUTH"), + CrafterOrientation::UpWest { .. } => f.write_str("UP_WEST"), + CrafterOrientation::WestUp { .. } => f.write_str("WEST_UP"), + CrafterOrientation::EastUp { .. } => f.write_str("EAST_UP"), + CrafterOrientation::NorthUp { .. } => f.write_str("NORTH_UP"), + CrafterOrientation::SouthUp { .. } => f.write_str("SOUTH_UP"), + } + } +} +impl<'mc> std::ops::Deref for CrafterOrientation<'mc> { + type Target = CrafterOrientationStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + CrafterOrientation::DownEast { inner } => inner, + CrafterOrientation::DownNorth { inner } => inner, + CrafterOrientation::DownSouth { inner } => inner, + CrafterOrientation::DownWest { inner } => inner, + CrafterOrientation::UpEast { inner } => inner, + CrafterOrientation::UpNorth { inner } => inner, + CrafterOrientation::UpSouth { inner } => inner, + CrafterOrientation::UpWest { inner } => inner, + CrafterOrientation::WestUp { inner } => inner, + CrafterOrientation::EastUp { inner } => inner, + CrafterOrientation::NorthUp { inner } => inner, + CrafterOrientation::SouthUp { inner } => inner, + } } } -impl<'mc> BigDripleafTilt<'mc> { +impl<'mc> CrafterOrientation<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/block/data/type/BigDripleaf/Tilt"); + let cls = env.find_class("org/bukkit/block/data/type/Crafter/Orientation"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/block/data/type/BigDripleaf/Tilt;", + "(Ljava/lang/String;)Lorg/bukkit/block/data/type/Crafter/Orientation;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -3185,40 +2855,107 @@ impl<'mc> BigDripleafTilt<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "DOWN_EAST" => Ok(CrafterOrientation::DownEast { + inner: CrafterOrientationStruct::from_raw(env, obj)?, + }), + "DOWN_NORTH" => Ok(CrafterOrientation::DownNorth { + inner: CrafterOrientationStruct::from_raw(env, obj)?, + }), + "DOWN_SOUTH" => Ok(CrafterOrientation::DownSouth { + inner: CrafterOrientationStruct::from_raw(env, obj)?, + }), + "DOWN_WEST" => Ok(CrafterOrientation::DownWest { + inner: CrafterOrientationStruct::from_raw(env, obj)?, + }), + "UP_EAST" => Ok(CrafterOrientation::UpEast { + inner: CrafterOrientationStruct::from_raw(env, obj)?, + }), + "UP_NORTH" => Ok(CrafterOrientation::UpNorth { + inner: CrafterOrientationStruct::from_raw(env, obj)?, + }), + "UP_SOUTH" => Ok(CrafterOrientation::UpSouth { + inner: CrafterOrientationStruct::from_raw(env, obj)?, + }), + "UP_WEST" => Ok(CrafterOrientation::UpWest { + inner: CrafterOrientationStruct::from_raw(env, obj)?, + }), + "WEST_UP" => Ok(CrafterOrientation::WestUp { + inner: CrafterOrientationStruct::from_raw(env, obj)?, + }), + "EAST_UP" => Ok(CrafterOrientation::EastUp { + inner: CrafterOrientationStruct::from_raw(env, obj)?, + }), + "NORTH_UP" => Ok(CrafterOrientation::NorthUp { + inner: CrafterOrientationStruct::from_raw(env, obj)?, + }), + "SOUTH_UP" => Ok(CrafterOrientation::SouthUp { + inner: CrafterOrientationStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct BigDripleafTiltStruct<'mc>( +pub struct CrafterOrientationStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BigDripleafTilt<'mc> { +impl<'mc> JNIRaw<'mc> for CrafterOrientation<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::DownEast { inner } => inner.0.clone(), + Self::DownNorth { inner } => inner.0.clone(), + Self::DownSouth { inner } => inner.0.clone(), + Self::DownWest { inner } => inner.0.clone(), + Self::UpEast { inner } => inner.0.clone(), + Self::UpNorth { inner } => inner.0.clone(), + Self::UpSouth { inner } => inner.0.clone(), + Self::UpWest { inner } => inner.0.clone(), + Self::WestUp { inner } => inner.0.clone(), + Self::EastUp { inner } => inner.0.clone(), + Self::NorthUp { inner } => inner.0.clone(), + Self::SouthUp { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::DownEast { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DownNorth { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DownSouth { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DownWest { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::UpEast { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::UpNorth { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::UpSouth { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::UpWest { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::WestUp { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::EastUp { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::NorthUp { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SouthUp { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for BigDripleafTilt<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CrafterOrientation<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate BigDripleafTilt from null object.").into(), + eyre::eyre!("Tried to instantiate CrafterOrientation from null object.").into(), ); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/block/data/type/BigDripleaf/Tilt")?; + env.validate_name(&obj, "org/bukkit/block/data/type/Crafter/Orientation")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BigDripleafTilt object, got {}", + "Invalid argument passed. Expected a CrafterOrientation object, got {}", name ) .into()) @@ -3230,13 +2967,49 @@ impl<'mc> JNIInstantiatable<'mc> for BigDripleafTilt<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "DOWN_EAST" => Ok(CrafterOrientation::DownEast { + inner: CrafterOrientationStruct::from_raw(env, obj)?, + }), + "DOWN_NORTH" => Ok(CrafterOrientation::DownNorth { + inner: CrafterOrientationStruct::from_raw(env, obj)?, + }), + "DOWN_SOUTH" => Ok(CrafterOrientation::DownSouth { + inner: CrafterOrientationStruct::from_raw(env, obj)?, + }), + "DOWN_WEST" => Ok(CrafterOrientation::DownWest { + inner: CrafterOrientationStruct::from_raw(env, obj)?, + }), + "UP_EAST" => Ok(CrafterOrientation::UpEast { + inner: CrafterOrientationStruct::from_raw(env, obj)?, + }), + "UP_NORTH" => Ok(CrafterOrientation::UpNorth { + inner: CrafterOrientationStruct::from_raw(env, obj)?, + }), + "UP_SOUTH" => Ok(CrafterOrientation::UpSouth { + inner: CrafterOrientationStruct::from_raw(env, obj)?, + }), + "UP_WEST" => Ok(CrafterOrientation::UpWest { + inner: CrafterOrientationStruct::from_raw(env, obj)?, + }), + "WEST_UP" => Ok(CrafterOrientation::WestUp { + inner: CrafterOrientationStruct::from_raw(env, obj)?, + }), + "EAST_UP" => Ok(CrafterOrientation::EastUp { + inner: CrafterOrientationStruct::from_raw(env, obj)?, + }), + "NORTH_UP" => Ok(CrafterOrientation::NorthUp { + inner: CrafterOrientationStruct::from_raw(env, obj)?, + }), + "SOUTH_UP" => Ok(CrafterOrientation::SouthUp { + inner: CrafterOrientationStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for BigDripleafTiltStruct<'mc> { +impl<'mc> JNIRaw<'mc> for CrafterOrientationStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3244,22 +3017,22 @@ impl<'mc> JNIRaw<'mc> for BigDripleafTiltStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BigDripleafTiltStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CrafterOrientationStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate BigDripleafTiltStruct from null object." + "Tried to instantiate CrafterOrientationStruct from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/block/data/type/BigDripleaf/Tilt")?; + env.validate_name(&obj, "org/bukkit/block/data/type/Crafter/Orientation")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BigDripleafTiltStruct object, got {}", + "Invalid argument passed. Expected a CrafterOrientationStruct object, got {}", name ) .into()) @@ -3269,138 +3042,18 @@ impl<'mc> JNIInstantiatable<'mc> for BigDripleafTiltStruct<'mc> { } } -impl<'mc> BigDripleafTiltStruct<'mc> { +impl<'mc> CrafterOrientationStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> + ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/type/BigDripleaf/Tilt;"); - let cls = jni.find_class("org/bukkit/block/data/type/BigDripleaf/Tilt"); + let sig = String::from("()Lorg/bukkit/block/data/type/Crafter/Orientation;"); + let cls = jni.find_class("org/bukkit/block/data/type/Crafter/Orientation"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::block::data::mod_type::BigDripleafTilt::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct Candle<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Candle<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Candle<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Candle from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Candle")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Candle object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Candle<'mc> { - /// Gets the value of the 'candles' property. - pub fn candles(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCandles", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the value of the 'candles' property. - pub fn set_candles(&self, candles: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(candles); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCandles", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the maximum allowed value of the 'candles' property. - pub fn maximum_candles(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMaximumCandles", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the value of the 'lit' property. - pub fn is_lit(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isLit", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets the value of the 'lit' property. - pub fn set_lit(&self, lit: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(lit.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLit", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the value of the 'waterlogged' property. - pub fn is_waterlogged(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isWaterlogged", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets the value of the 'waterlogged' property. - pub fn set_waterlogged(&self, waterlogged: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(waterlogged.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setWaterlogged", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::block::data::mod_type::CrafterOrientation::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -3408,116 +3061,42 @@ impl<'mc> Candle<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Candle<'mc> { - fn into(self) -> crate::block::data::Lightable<'mc> { - crate::block::data::Lightable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Candle into crate::block::data::Lightable") - } -} -impl<'mc> Into> for Candle<'mc> { - fn into(self) -> crate::block::data::Waterlogged<'mc> { - crate::block::data::Waterlogged::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Candle into crate::block::data::Waterlogged") - } -} #[repr(C)] -pub struct Stairs<'mc>( +pub struct WallSign<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Stairs<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Stairs<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Stairs from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Stairs")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Stairs object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Stairs<'mc> { - /// Gets the value of the 'shape' property. - pub fn shape( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/type/Stairs/Shape;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getShape", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::data::mod_type::StairsShape::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the value of the 'shape' property. - pub fn set_shape( - &self, - shape: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/data/type/Stairs/Shape;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(shape.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setShape", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the value of the 'half' property. - pub fn half( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/Bisected/Half;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHalf", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::data::BisectedHalf::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the value of the 'half' property. - pub fn set_half( - &self, - half: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/data/Bisected/Half;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(half.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setHalf", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +); + +impl<'mc> JNIRaw<'mc> for WallSign<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for WallSign<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate WallSign from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/WallSign")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a WallSign object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } +} + +impl<'mc> WallSign<'mc> { /// Gets the value of the 'facing' property. pub fn facing(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/block/BlockFace;"); @@ -3586,103 +3165,141 @@ impl<'mc> Stairs<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Stairs<'mc> { - fn into(self) -> crate::block::data::Bisected<'mc> { - crate::block::data::Bisected::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Stairs into crate::block::data::Bisected") - } -} -impl<'mc> Into> for Stairs<'mc> { +impl<'mc> Into> for WallSign<'mc> { fn into(self) -> crate::block::data::Directional<'mc> { crate::block::data::Directional::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Stairs into crate::block::data::Directional") + .expect("Error converting WallSign into crate::block::data::Directional") } } -impl<'mc> Into> for Stairs<'mc> { +impl<'mc> Into> for WallSign<'mc> { fn into(self) -> crate::block::data::Waterlogged<'mc> { crate::block::data::Waterlogged::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Stairs into crate::block::data::Waterlogged") - } -} -pub enum StairsShape<'mc> {} -impl<'mc> std::fmt::Display for StairsShape<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> StairsShape<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/block/data/type/Stairs/Shape"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/block/data/type/Stairs/Shape;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + .expect("Error converting WallSign into crate::block::data::Waterlogged") } } - #[repr(C)] -pub struct StairsShapeStruct<'mc>( +pub struct SeaPickle<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for StairsShape<'mc> { +impl<'mc> JNIRaw<'mc> for SeaPickle<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + self.0.clone() } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for StairsShape<'mc> { +impl<'mc> JNIInstantiatable<'mc> for SeaPickle<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate StairsShape from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate SeaPickle from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Stairs/Shape")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/SeaPickle")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a StairsShape object, got {}", + "Invalid argument passed. Expected a SeaPickle object, got {}", name ) .into()) } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + Ok(Self(env.clone(), obj)) } } } -impl<'mc> JNIRaw<'mc> for StairsShapeStruct<'mc> { +impl<'mc> SeaPickle<'mc> { + /// Gets the value of the 'pickles' property. + pub fn pickles(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPickles", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the value of the 'pickles' property. + pub fn set_pickles(&self, pickles: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(pickles); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPickles", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the minimum allowed value of the 'pickles' property. + pub fn minimum_pickles(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMinimumPickles", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the maximum allowed value of the 'pickles' property. + pub fn maximum_pickles(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaximumPickles", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the value of the 'waterlogged' property. + pub fn is_waterlogged(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isWaterlogged", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the value of the 'waterlogged' property. + pub fn set_waterlogged(&self, waterlogged: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(waterlogged.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setWaterlogged", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for SeaPickle<'mc> { + fn into(self) -> crate::block::data::Waterlogged<'mc> { + crate::block::data::Waterlogged::from_raw(&self.jni_ref(), self.1) + .expect("Error converting SeaPickle into crate::block::data::Waterlogged") + } +} +#[repr(C)] +pub struct Vault<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Vault<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3690,20 +3307,18 @@ impl<'mc> JNIRaw<'mc> for StairsShapeStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for StairsShapeStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Vault<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate StairsShapeStruct from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate Vault from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Stairs/Shape")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Vault")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a StairsShapeStruct object, got {}", + "Invalid argument passed. Expected a Vault object, got {}", name ) .into()) @@ -3713,60 +3328,63 @@ impl<'mc> JNIInstantiatable<'mc> for StairsShapeStruct<'mc> { } } -impl<'mc> StairsShapeStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/type/Stairs/Shape;"); - let cls = jni.find_class("org/bukkit/block/data/type/Stairs/Shape"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::block::data::mod_type::StairsShape::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) +impl<'mc> Vault<'mc> { + /// Gets the value of the 'vault_state' property. + pub fn trial_spawner_state( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/type/Vault/State;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTrialSpawnerState", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::block::data::mod_type::VaultState::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -#[repr(C)] -pub struct WallSign<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for WallSign<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Sets the value of the 'vault_state' property. + pub fn set_trial_spawner_state( + &self, + state: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/data/type/Vault/State;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(state.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTrialSpawnerState", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets the value of the 'ominous' property. + pub fn is_ominous(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isOminous", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for WallSign<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate WallSign from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/WallSign")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a WallSign object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Sets the value of the 'ominous' property. + pub fn set_ominous(&self, ominous: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(ominous.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setOminous", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> WallSign<'mc> { /// Gets the value of the 'facing' property. pub fn facing(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/block/BlockFace;"); @@ -3807,149 +3425,196 @@ impl<'mc> WallSign<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the value of the 'waterlogged' property. - pub fn is_waterlogged(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isWaterlogged", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets the value of the 'waterlogged' property. - pub fn set_waterlogged(&self, waterlogged: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(waterlogged.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setWaterlogged", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for WallSign<'mc> { +impl<'mc> Into> for Vault<'mc> { fn into(self) -> crate::block::data::Directional<'mc> { crate::block::data::Directional::from_raw(&self.jni_ref(), self.1) - .expect("Error converting WallSign into crate::block::data::Directional") + .expect("Error converting Vault into crate::block::data::Directional") } } -impl<'mc> Into> for WallSign<'mc> { - fn into(self) -> crate::block::data::Waterlogged<'mc> { - crate::block::data::Waterlogged::from_raw(&self.jni_ref(), self.1) - .expect("Error converting WallSign into crate::block::data::Waterlogged") +pub enum VaultState<'mc> { + Inactive { inner: VaultStateStruct<'mc> }, + Active { inner: VaultStateStruct<'mc> }, + Unlocking { inner: VaultStateStruct<'mc> }, + Ejecting { inner: VaultStateStruct<'mc> }, +} +impl<'mc> std::fmt::Display for VaultState<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + VaultState::Inactive { .. } => f.write_str("INACTIVE"), + VaultState::Active { .. } => f.write_str("ACTIVE"), + VaultState::Unlocking { .. } => f.write_str("UNLOCKING"), + VaultState::Ejecting { .. } => f.write_str("EJECTING"), + } + } +} +impl<'mc> std::ops::Deref for VaultState<'mc> { + type Target = VaultStateStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + VaultState::Inactive { inner } => inner, + VaultState::Active { inner } => inner, + VaultState::Unlocking { inner } => inner, + VaultState::Ejecting { inner } => inner, + } + } +} + +impl<'mc> VaultState<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/block/data/type/Vault/State"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/block/data/type/Vault/State;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "INACTIVE" => Ok(VaultState::Inactive { + inner: VaultStateStruct::from_raw(env, obj)?, + }), + "ACTIVE" => Ok(VaultState::Active { + inner: VaultStateStruct::from_raw(env, obj)?, + }), + "UNLOCKING" => Ok(VaultState::Unlocking { + inner: VaultStateStruct::from_raw(env, obj)?, + }), + "EJECTING" => Ok(VaultState::Ejecting { + inner: VaultStateStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } + #[repr(C)] -pub struct SeaPickle<'mc>( +pub struct VaultStateStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for SeaPickle<'mc> { +impl<'mc> JNIRaw<'mc> for VaultState<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + match self { + Self::Inactive { inner } => inner.0.clone(), + Self::Active { inner } => inner.0.clone(), + Self::Unlocking { inner } => inner.0.clone(), + Self::Ejecting { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + match self { + Self::Inactive { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Active { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Unlocking { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Ejecting { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for SeaPickle<'mc> { +impl<'mc> JNIInstantiatable<'mc> for VaultState<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate SeaPickle from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate VaultState from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/SeaPickle")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Vault/State")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SeaPickle object, got {}", + "Invalid argument passed. Expected a VaultState object, got {}", name ) .into()) } else { - Ok(Self(env.clone(), obj)) + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "INACTIVE" => Ok(VaultState::Inactive { + inner: VaultStateStruct::from_raw(env, obj)?, + }), + "ACTIVE" => Ok(VaultState::Active { + inner: VaultStateStruct::from_raw(env, obj)?, + }), + "UNLOCKING" => Ok(VaultState::Unlocking { + inner: VaultStateStruct::from_raw(env, obj)?, + }), + "EJECTING" => Ok(VaultState::Ejecting { + inner: VaultStateStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } } -impl<'mc> SeaPickle<'mc> { - /// Gets the value of the 'pickles' property. - pub fn pickles(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPickles", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the value of the 'pickles' property. - pub fn set_pickles(&self, pickles: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(pickles); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPickles", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the minimum allowed value of the 'pickles' property. - pub fn minimum_pickles(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMinimumPickles", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) +impl<'mc> JNIRaw<'mc> for VaultStateStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Gets the maximum allowed value of the 'pickles' property. - pub fn maximum_pickles(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMaximumPickles", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Gets the value of the 'waterlogged' property. - pub fn is_waterlogged(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isWaterlogged", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} +impl<'mc> JNIInstantiatable<'mc> for VaultStateStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate VaultStateStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Vault/State")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a VaultStateStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } - /// Sets the value of the 'waterlogged' property. - pub fn set_waterlogged(&self, waterlogged: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(waterlogged.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setWaterlogged", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +} + +impl<'mc> VaultStateStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/type/Vault/State;"); + let cls = jni.find_class("org/bukkit/block/data/type/Vault/State"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::block::data::mod_type::VaultState::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -3957,12 +3622,6 @@ impl<'mc> SeaPickle<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for SeaPickle<'mc> { - fn into(self) -> crate::block::data::Waterlogged<'mc> { - crate::block::data::Waterlogged::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SeaPickle into crate::block::data::Waterlogged") - } -} #[repr(C)] pub struct SculkSensor<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, @@ -4102,10 +3761,28 @@ impl<'mc> Into> for SculkSensor<'mc> { .expect("Error converting SculkSensor into crate::block::data::Waterlogged") } } -pub enum SculkSensorPhase<'mc> {} +pub enum SculkSensorPhase<'mc> { + Inactive { inner: SculkSensorPhaseStruct<'mc> }, + Active { inner: SculkSensorPhaseStruct<'mc> }, + Cooldown { inner: SculkSensorPhaseStruct<'mc> }, +} impl<'mc> std::fmt::Display for SculkSensorPhase<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + SculkSensorPhase::Inactive { .. } => f.write_str("INACTIVE"), + SculkSensorPhase::Active { .. } => f.write_str("ACTIVE"), + SculkSensorPhase::Cooldown { .. } => f.write_str("COOLDOWN"), + } + } +} +impl<'mc> std::ops::Deref for SculkSensorPhase<'mc> { + type Target = SculkSensorPhaseStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + SculkSensorPhase::Inactive { inner } => inner, + SculkSensorPhase::Active { inner } => inner, + SculkSensorPhase::Cooldown { inner } => inner, + } } } @@ -4132,6 +3809,16 @@ impl<'mc> SculkSensorPhase<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "INACTIVE" => Ok(SculkSensorPhase::Inactive { + inner: SculkSensorPhaseStruct::from_raw(env, obj)?, + }), + "ACTIVE" => Ok(SculkSensorPhase::Active { + inner: SculkSensorPhaseStruct::from_raw(env, obj)?, + }), + "COOLDOWN" => Ok(SculkSensorPhase::Cooldown { + inner: SculkSensorPhaseStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -4145,10 +3832,18 @@ pub struct SculkSensorPhaseStruct<'mc>( impl<'mc> JNIRaw<'mc> for SculkSensorPhase<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Inactive { inner } => inner.0.clone(), + Self::Active { inner } => inner.0.clone(), + Self::Cooldown { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Inactive { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Active { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Cooldown { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for SculkSensorPhase<'mc> { @@ -4177,6 +3872,15 @@ impl<'mc> JNIInstantiatable<'mc> for SculkSensorPhase<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "INACTIVE" => Ok(SculkSensorPhase::Inactive { + inner: SculkSensorPhaseStruct::from_raw(env, obj)?, + }), + "ACTIVE" => Ok(SculkSensorPhase::Active { + inner: SculkSensorPhaseStruct::from_raw(env, obj)?, + }), + "COOLDOWN" => Ok(SculkSensorPhase::Cooldown { + inner: SculkSensorPhaseStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -5078,10 +4782,28 @@ impl<'mc> Into> for Wall<'mc> { .expect("Error converting Wall into crate::block::data::Waterlogged") } } -pub enum WallHeight<'mc> {} +pub enum WallHeight<'mc> { + None { inner: WallHeightStruct<'mc> }, + Low { inner: WallHeightStruct<'mc> }, + Tall { inner: WallHeightStruct<'mc> }, +} impl<'mc> std::fmt::Display for WallHeight<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + WallHeight::None { .. } => f.write_str("NONE"), + WallHeight::Low { .. } => f.write_str("LOW"), + WallHeight::Tall { .. } => f.write_str("TALL"), + } + } +} +impl<'mc> std::ops::Deref for WallHeight<'mc> { + type Target = WallHeightStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + WallHeight::None { inner } => inner, + WallHeight::Low { inner } => inner, + WallHeight::Tall { inner } => inner, + } } } @@ -5108,6 +4830,16 @@ impl<'mc> WallHeight<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NONE" => Ok(WallHeight::None { + inner: WallHeightStruct::from_raw(env, obj)?, + }), + "LOW" => Ok(WallHeight::Low { + inner: WallHeightStruct::from_raw(env, obj)?, + }), + "TALL" => Ok(WallHeight::Tall { + inner: WallHeightStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -5121,10 +4853,18 @@ pub struct WallHeightStruct<'mc>( impl<'mc> JNIRaw<'mc> for WallHeight<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::None { inner } => inner.0.clone(), + Self::Low { inner } => inner.0.clone(), + Self::Tall { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::None { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Low { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Tall { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for WallHeight<'mc> { @@ -5150,6 +4890,15 @@ impl<'mc> JNIInstantiatable<'mc> for WallHeight<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NONE" => Ok(WallHeight::None { + inner: WallHeightStruct::from_raw(env, obj)?, + }), + "LOW" => Ok(WallHeight::Low { + inner: WallHeightStruct::from_raw(env, obj)?, + }), + "TALL" => Ok(WallHeight::Tall { + inner: WallHeightStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -5903,10 +5652,44 @@ impl<'mc> Into> for PointedDripstone<'mc> { .expect("Error converting PointedDripstone into crate::block::data::Waterlogged") } } -pub enum PointedDripstoneThickness<'mc> {} +pub enum PointedDripstoneThickness<'mc> { + TipMerge { + inner: PointedDripstoneThicknessStruct<'mc>, + }, + Tip { + inner: PointedDripstoneThicknessStruct<'mc>, + }, + Frustum { + inner: PointedDripstoneThicknessStruct<'mc>, + }, + Middle { + inner: PointedDripstoneThicknessStruct<'mc>, + }, + Base { + inner: PointedDripstoneThicknessStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for PointedDripstoneThickness<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + PointedDripstoneThickness::TipMerge { .. } => f.write_str("TIP_MERGE"), + PointedDripstoneThickness::Tip { .. } => f.write_str("TIP"), + PointedDripstoneThickness::Frustum { .. } => f.write_str("FRUSTUM"), + PointedDripstoneThickness::Middle { .. } => f.write_str("MIDDLE"), + PointedDripstoneThickness::Base { .. } => f.write_str("BASE"), + } + } +} +impl<'mc> std::ops::Deref for PointedDripstoneThickness<'mc> { + type Target = PointedDripstoneThicknessStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + PointedDripstoneThickness::TipMerge { inner } => inner, + PointedDripstoneThickness::Tip { inner } => inner, + PointedDripstoneThickness::Frustum { inner } => inner, + PointedDripstoneThickness::Middle { inner } => inner, + PointedDripstoneThickness::Base { inner } => inner, + } } } @@ -5933,6 +5716,22 @@ impl<'mc> PointedDripstoneThickness<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "TIP_MERGE" => Ok(PointedDripstoneThickness::TipMerge { + inner: PointedDripstoneThicknessStruct::from_raw(env, obj)?, + }), + "TIP" => Ok(PointedDripstoneThickness::Tip { + inner: PointedDripstoneThicknessStruct::from_raw(env, obj)?, + }), + "FRUSTUM" => Ok(PointedDripstoneThickness::Frustum { + inner: PointedDripstoneThicknessStruct::from_raw(env, obj)?, + }), + "MIDDLE" => Ok(PointedDripstoneThickness::Middle { + inner: PointedDripstoneThicknessStruct::from_raw(env, obj)?, + }), + "BASE" => Ok(PointedDripstoneThickness::Base { + inner: PointedDripstoneThicknessStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -5946,10 +5745,22 @@ pub struct PointedDripstoneThicknessStruct<'mc>( impl<'mc> JNIRaw<'mc> for PointedDripstoneThickness<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::TipMerge { inner } => inner.0.clone(), + Self::Tip { inner } => inner.0.clone(), + Self::Frustum { inner } => inner.0.clone(), + Self::Middle { inner } => inner.0.clone(), + Self::Base { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::TipMerge { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Tip { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Frustum { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Middle { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Base { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for PointedDripstoneThickness<'mc> { @@ -5981,6 +5792,21 @@ impl<'mc> JNIInstantiatable<'mc> for PointedDripstoneThickness<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "TIP_MERGE" => Ok(PointedDripstoneThickness::TipMerge { + inner: PointedDripstoneThicknessStruct::from_raw(env, obj)?, + }), + "TIP" => Ok(PointedDripstoneThickness::Tip { + inner: PointedDripstoneThicknessStruct::from_raw(env, obj)?, + }), + "FRUSTUM" => Ok(PointedDripstoneThickness::Frustum { + inner: PointedDripstoneThicknessStruct::from_raw(env, obj)?, + }), + "MIDDLE" => Ok(PointedDripstoneThickness::Middle { + inner: PointedDripstoneThicknessStruct::from_raw(env, obj)?, + }), + "BASE" => Ok(PointedDripstoneThickness::Base { + inner: PointedDripstoneThicknessStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -6442,10 +6268,34 @@ impl<'mc> Into> for RedstoneWire<'mc> .expect("Error converting RedstoneWire into crate::block::data::AnaloguePowerable") } } -pub enum RedstoneWireConnection<'mc> {} +pub enum RedstoneWireConnection<'mc> { + Up { + inner: RedstoneWireConnectionStruct<'mc>, + }, + Side { + inner: RedstoneWireConnectionStruct<'mc>, + }, + None { + inner: RedstoneWireConnectionStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for RedstoneWireConnection<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + RedstoneWireConnection::Up { .. } => f.write_str("UP"), + RedstoneWireConnection::Side { .. } => f.write_str("SIDE"), + RedstoneWireConnection::None { .. } => f.write_str("NONE"), + } + } +} +impl<'mc> std::ops::Deref for RedstoneWireConnection<'mc> { + type Target = RedstoneWireConnectionStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + RedstoneWireConnection::Up { inner } => inner, + RedstoneWireConnection::Side { inner } => inner, + RedstoneWireConnection::None { inner } => inner, + } } } @@ -6472,6 +6322,16 @@ impl<'mc> RedstoneWireConnection<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "UP" => Ok(RedstoneWireConnection::Up { + inner: RedstoneWireConnectionStruct::from_raw(env, obj)?, + }), + "SIDE" => Ok(RedstoneWireConnection::Side { + inner: RedstoneWireConnectionStruct::from_raw(env, obj)?, + }), + "NONE" => Ok(RedstoneWireConnection::None { + inner: RedstoneWireConnectionStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -6485,10 +6345,18 @@ pub struct RedstoneWireConnectionStruct<'mc>( impl<'mc> JNIRaw<'mc> for RedstoneWireConnection<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Up { inner } => inner.0.clone(), + Self::Side { inner } => inner.0.clone(), + Self::None { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Up { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Side { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::None { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for RedstoneWireConnection<'mc> { @@ -6518,6 +6386,15 @@ impl<'mc> JNIInstantiatable<'mc> for RedstoneWireConnection<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "UP" => Ok(RedstoneWireConnection::Up { + inner: RedstoneWireConnectionStruct::from_raw(env, obj)?, + }), + "SIDE" => Ok(RedstoneWireConnection::Side { + inner: RedstoneWireConnectionStruct::from_raw(env, obj)?, + }), + "NONE" => Ok(RedstoneWireConnection::None { + inner: RedstoneWireConnectionStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -7437,10 +7314,25 @@ impl<'mc> Into> for Door<'mc> { .expect("Error converting Door into crate::block::data::Powerable") } } -pub enum DoorHinge<'mc> {} +pub enum DoorHinge<'mc> { + Left { inner: DoorHingeStruct<'mc> }, + Right { inner: DoorHingeStruct<'mc> }, +} impl<'mc> std::fmt::Display for DoorHinge<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + DoorHinge::Left { .. } => f.write_str("LEFT"), + DoorHinge::Right { .. } => f.write_str("RIGHT"), + } + } +} +impl<'mc> std::ops::Deref for DoorHinge<'mc> { + type Target = DoorHingeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + DoorHinge::Left { inner } => inner, + DoorHinge::Right { inner } => inner, + } } } @@ -7467,6 +7359,13 @@ impl<'mc> DoorHinge<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "LEFT" => Ok(DoorHinge::Left { + inner: DoorHingeStruct::from_raw(env, obj)?, + }), + "RIGHT" => Ok(DoorHinge::Right { + inner: DoorHingeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -7480,10 +7379,16 @@ pub struct DoorHingeStruct<'mc>( impl<'mc> JNIRaw<'mc> for DoorHinge<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Left { inner } => inner.0.clone(), + Self::Right { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Left { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Right { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for DoorHinge<'mc> { @@ -7509,6 +7414,12 @@ impl<'mc> JNIInstantiatable<'mc> for DoorHinge<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "LEFT" => Ok(DoorHinge::Left { + inner: DoorHingeStruct::from_raw(env, obj)?, + }), + "RIGHT" => Ok(DoorHinge::Right { + inner: DoorHingeStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -8165,6 +8076,111 @@ impl<'mc> Into> for TrapDoor<'mc> { } } #[repr(C)] +pub struct Skull<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Skull<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Skull<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Skull from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Skull")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Skull object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Skull<'mc> { + /// Gets the value of the 'powered' property. + pub fn is_powered(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the value of the 'powered' property. + pub fn set_powered(&self, powered: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(powered.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPowered", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the value of the 'rotation' property. + pub fn rotation(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRotation", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the value of the 'rotation' property. + pub fn set_rotation( + &self, + rotation: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(rotation.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRotation", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Skull<'mc> { + fn into(self) -> crate::block::data::Powerable<'mc> { + crate::block::data::Powerable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Skull into crate::block::data::Powerable") + } +} +impl<'mc> Into> for Skull<'mc> { + fn into(self) -> crate::block::data::Rotatable<'mc> { + crate::block::data::Rotatable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Skull into crate::block::data::Rotatable") + } +} +#[repr(C)] pub struct PitcherCrop<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, @@ -10987,10 +11003,25 @@ impl<'mc> Into> for Bed<'mc> { .expect("Error converting Bed into crate::block::data::Directional") } } -pub enum BedPart<'mc> {} +pub enum BedPart<'mc> { + Head { inner: BedPartStruct<'mc> }, + Foot { inner: BedPartStruct<'mc> }, +} impl<'mc> std::fmt::Display for BedPart<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + BedPart::Head { .. } => f.write_str("HEAD"), + BedPart::Foot { .. } => f.write_str("FOOT"), + } + } +} +impl<'mc> std::ops::Deref for BedPart<'mc> { + type Target = BedPartStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + BedPart::Head { inner } => inner, + BedPart::Foot { inner } => inner, + } } } @@ -11017,6 +11048,13 @@ impl<'mc> BedPart<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "HEAD" => Ok(BedPart::Head { + inner: BedPartStruct::from_raw(env, obj)?, + }), + "FOOT" => Ok(BedPart::Foot { + inner: BedPartStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -11030,10 +11068,16 @@ pub struct BedPartStruct<'mc>( impl<'mc> JNIRaw<'mc> for BedPart<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Head { inner } => inner.0.clone(), + Self::Foot { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Head { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Foot { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for BedPart<'mc> { @@ -11059,6 +11103,12 @@ impl<'mc> JNIInstantiatable<'mc> for BedPart<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "HEAD" => Ok(BedPart::Head { + inner: BedPartStruct::from_raw(env, obj)?, + }), + "FOOT" => Ok(BedPart::Foot { + inner: BedPartStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -11351,19 +11401,138 @@ impl<'mc> Scaffolding<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Scaffolding<'mc> { +impl<'mc> Into> for Scaffolding<'mc> { + fn into(self) -> crate::block::data::Waterlogged<'mc> { + crate::block::data::Waterlogged::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Scaffolding into crate::block::data::Waterlogged") + } +} +#[repr(C)] +pub struct WallHangingSign<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for WallHangingSign<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for WallHangingSign<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate WallHangingSign from null object.").into(), + ); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/block/data/type/WallHangingSign")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a WallHangingSign object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> WallHangingSign<'mc> { + /// Gets the value of the 'facing' property. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the value of the 'facing' property. + pub fn set_facing( + &self, + facing: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(facing.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFacing", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the faces which are applicable to this block. + pub fn faces(&self) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFaces", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the value of the 'waterlogged' property. + pub fn is_waterlogged(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isWaterlogged", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the value of the 'waterlogged' property. + pub fn set_waterlogged(&self, waterlogged: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(waterlogged.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setWaterlogged", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for WallHangingSign<'mc> { + fn into(self) -> crate::block::data::Directional<'mc> { + crate::block::data::Directional::from_raw(&self.jni_ref(), self.1) + .expect("Error converting WallHangingSign into crate::block::data::Directional") + } +} +impl<'mc> Into> for WallHangingSign<'mc> { fn into(self) -> crate::block::data::Waterlogged<'mc> { crate::block::data::Waterlogged::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Scaffolding into crate::block::data::Waterlogged") + .expect("Error converting WallHangingSign into crate::block::data::Waterlogged") } } #[repr(C)] -pub struct WallHangingSign<'mc>( +pub struct WallSkull<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for WallHangingSign<'mc> { +impl<'mc> JNIRaw<'mc> for WallSkull<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -11371,21 +11540,18 @@ impl<'mc> JNIRaw<'mc> for WallHangingSign<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for WallHangingSign<'mc> { +impl<'mc> JNIInstantiatable<'mc> for WallSkull<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate WallHangingSign from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate WallSkull from null object.").into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/block/data/type/WallHangingSign")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/WallSkull")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a WallHangingSign object, got {}", + "Invalid argument passed. Expected a WallSkull object, got {}", name ) .into()) @@ -11395,7 +11561,7 @@ impl<'mc> JNIInstantiatable<'mc> for WallHangingSign<'mc> { } } -impl<'mc> WallHangingSign<'mc> { +impl<'mc> WallSkull<'mc> { /// Gets the value of the 'facing' property. pub fn facing(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/block/BlockFace;"); @@ -11436,22 +11602,22 @@ impl<'mc> WallHangingSign<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the value of the 'waterlogged' property. - pub fn is_waterlogged(&self) -> Result> { + /// Gets the value of the 'powered' property. + pub fn is_powered(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isWaterlogged", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the value of the 'waterlogged' property. - pub fn set_waterlogged(&self, waterlogged: bool) -> Result<(), Box> { + /// Sets the value of the 'powered' property. + pub fn set_powered(&self, powered: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(waterlogged.into()); + let val_1 = jni::objects::JValueGen::Bool(powered.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setWaterlogged", + "setPowered", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -11464,16 +11630,16 @@ impl<'mc> WallHangingSign<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for WallHangingSign<'mc> { +impl<'mc> Into> for WallSkull<'mc> { fn into(self) -> crate::block::data::Directional<'mc> { crate::block::data::Directional::from_raw(&self.jni_ref(), self.1) - .expect("Error converting WallHangingSign into crate::block::data::Directional") + .expect("Error converting WallSkull into crate::block::data::Directional") } } -impl<'mc> Into> for WallHangingSign<'mc> { - fn into(self) -> crate::block::data::Waterlogged<'mc> { - crate::block::data::Waterlogged::from_raw(&self.jni_ref(), self.1) - .expect("Error converting WallHangingSign into crate::block::data::Waterlogged") +impl<'mc> Into> for WallSkull<'mc> { + fn into(self) -> crate::block::data::Powerable<'mc> { + crate::block::data::Powerable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting WallSkull into crate::block::data::Powerable") } } #[repr(C)] @@ -11870,10 +12036,28 @@ impl<'mc> Into> for Chest<'mc> { .expect("Error converting Chest into crate::block::data::Waterlogged") } } -pub enum ChestType<'mc> {} +pub enum ChestType<'mc> { + Single { inner: ChestTypeStruct<'mc> }, + Left { inner: ChestTypeStruct<'mc> }, + Right { inner: ChestTypeStruct<'mc> }, +} impl<'mc> std::fmt::Display for ChestType<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + ChestType::Single { .. } => f.write_str("SINGLE"), + ChestType::Left { .. } => f.write_str("LEFT"), + ChestType::Right { .. } => f.write_str("RIGHT"), + } + } +} +impl<'mc> std::ops::Deref for ChestType<'mc> { + type Target = ChestTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + ChestType::Single { inner } => inner, + ChestType::Left { inner } => inner, + ChestType::Right { inner } => inner, + } } } @@ -11900,6 +12084,16 @@ impl<'mc> ChestType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "SINGLE" => Ok(ChestType::Single { + inner: ChestTypeStruct::from_raw(env, obj)?, + }), + "LEFT" => Ok(ChestType::Left { + inner: ChestTypeStruct::from_raw(env, obj)?, + }), + "RIGHT" => Ok(ChestType::Right { + inner: ChestTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -11913,10 +12107,18 @@ pub struct ChestTypeStruct<'mc>( impl<'mc> JNIRaw<'mc> for ChestType<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Single { inner } => inner.0.clone(), + Self::Left { inner } => inner.0.clone(), + Self::Right { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Single { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Left { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Right { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for ChestType<'mc> { @@ -11942,6 +12144,15 @@ impl<'mc> JNIInstantiatable<'mc> for ChestType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "SINGLE" => Ok(ChestType::Single { + inner: ChestTypeStruct::from_raw(env, obj)?, + }), + "LEFT" => Ok(ChestType::Left { + inner: ChestTypeStruct::from_raw(env, obj)?, + }), + "RIGHT" => Ok(ChestType::Right { + inner: ChestTypeStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -12144,10 +12355,31 @@ impl<'mc> Into> for Bell<'mc> { .expect("Error converting Bell into crate::block::data::Powerable") } } -pub enum BellAttachment<'mc> {} +pub enum BellAttachment<'mc> { + Floor { inner: BellAttachmentStruct<'mc> }, + Ceiling { inner: BellAttachmentStruct<'mc> }, + SingleWall { inner: BellAttachmentStruct<'mc> }, + DoubleWall { inner: BellAttachmentStruct<'mc> }, +} impl<'mc> std::fmt::Display for BellAttachment<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + BellAttachment::Floor { .. } => f.write_str("FLOOR"), + BellAttachment::Ceiling { .. } => f.write_str("CEILING"), + BellAttachment::SingleWall { .. } => f.write_str("SINGLE_WALL"), + BellAttachment::DoubleWall { .. } => f.write_str("DOUBLE_WALL"), + } + } +} +impl<'mc> std::ops::Deref for BellAttachment<'mc> { + type Target = BellAttachmentStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + BellAttachment::Floor { inner } => inner, + BellAttachment::Ceiling { inner } => inner, + BellAttachment::SingleWall { inner } => inner, + BellAttachment::DoubleWall { inner } => inner, + } } } @@ -12174,6 +12406,19 @@ impl<'mc> BellAttachment<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "FLOOR" => Ok(BellAttachment::Floor { + inner: BellAttachmentStruct::from_raw(env, obj)?, + }), + "CEILING" => Ok(BellAttachment::Ceiling { + inner: BellAttachmentStruct::from_raw(env, obj)?, + }), + "SINGLE_WALL" => Ok(BellAttachment::SingleWall { + inner: BellAttachmentStruct::from_raw(env, obj)?, + }), + "DOUBLE_WALL" => Ok(BellAttachment::DoubleWall { + inner: BellAttachmentStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -12187,10 +12432,24 @@ pub struct BellAttachmentStruct<'mc>( impl<'mc> JNIRaw<'mc> for BellAttachment<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Floor { inner } => inner.0.clone(), + Self::Ceiling { inner } => inner.0.clone(), + Self::SingleWall { inner } => inner.0.clone(), + Self::DoubleWall { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Floor { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Ceiling { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SingleWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DoubleWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } impl<'mc> JNIInstantiatable<'mc> for BellAttachment<'mc> { @@ -12219,6 +12478,18 @@ impl<'mc> JNIInstantiatable<'mc> for BellAttachment<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "FLOOR" => Ok(BellAttachment::Floor { + inner: BellAttachmentStruct::from_raw(env, obj)?, + }), + "CEILING" => Ok(BellAttachment::Ceiling { + inner: BellAttachmentStruct::from_raw(env, obj)?, + }), + "SINGLE_WALL" => Ok(BellAttachment::SingleWall { + inner: BellAttachmentStruct::from_raw(env, obj)?, + }), + "DOUBLE_WALL" => Ok(BellAttachment::DoubleWall { + inner: BellAttachmentStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -13570,10 +13841,29 @@ impl<'mc> Into> for TechnicalPiston<'mc> { .expect("Error converting TechnicalPiston into crate::block::data::Directional") } } -pub enum TechnicalPistonType<'mc> {} +pub enum TechnicalPistonType<'mc> { + Normal { + inner: TechnicalPistonTypeStruct<'mc>, + }, + Sticky { + inner: TechnicalPistonTypeStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for TechnicalPistonType<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + TechnicalPistonType::Normal { .. } => f.write_str("NORMAL"), + TechnicalPistonType::Sticky { .. } => f.write_str("STICKY"), + } + } +} +impl<'mc> std::ops::Deref for TechnicalPistonType<'mc> { + type Target = TechnicalPistonTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + TechnicalPistonType::Normal { inner } => inner, + TechnicalPistonType::Sticky { inner } => inner, + } } } @@ -13600,6 +13890,13 @@ impl<'mc> TechnicalPistonType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NORMAL" => Ok(TechnicalPistonType::Normal { + inner: TechnicalPistonTypeStruct::from_raw(env, obj)?, + }), + "STICKY" => Ok(TechnicalPistonType::Sticky { + inner: TechnicalPistonTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -13613,10 +13910,16 @@ pub struct TechnicalPistonTypeStruct<'mc>( impl<'mc> JNIRaw<'mc> for TechnicalPistonType<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Normal { inner } => inner.0.clone(), + Self::Sticky { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Normal { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Sticky { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for TechnicalPistonType<'mc> { @@ -13645,6 +13948,12 @@ impl<'mc> JNIInstantiatable<'mc> for TechnicalPistonType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NORMAL" => Ok(TechnicalPistonType::Normal { + inner: TechnicalPistonTypeStruct::from_raw(env, obj)?, + }), + "STICKY" => Ok(TechnicalPistonType::Sticky { + inner: TechnicalPistonTypeStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -14778,10 +15087,25 @@ impl<'mc> Into> for Comparator<'mc> { .expect("Error converting Comparator into crate::block::data::Powerable") } } -pub enum ComparatorMode<'mc> {} +pub enum ComparatorMode<'mc> { + Compare { inner: ComparatorModeStruct<'mc> }, + Subtract { inner: ComparatorModeStruct<'mc> }, +} impl<'mc> std::fmt::Display for ComparatorMode<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + ComparatorMode::Compare { .. } => f.write_str("COMPARE"), + ComparatorMode::Subtract { .. } => f.write_str("SUBTRACT"), + } + } +} +impl<'mc> std::ops::Deref for ComparatorMode<'mc> { + type Target = ComparatorModeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + ComparatorMode::Compare { inner } => inner, + ComparatorMode::Subtract { inner } => inner, + } } } @@ -14808,6 +15132,13 @@ impl<'mc> ComparatorMode<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "COMPARE" => Ok(ComparatorMode::Compare { + inner: ComparatorModeStruct::from_raw(env, obj)?, + }), + "SUBTRACT" => Ok(ComparatorMode::Subtract { + inner: ComparatorModeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -14821,10 +15152,16 @@ pub struct ComparatorModeStruct<'mc>( impl<'mc> JNIRaw<'mc> for ComparatorMode<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Compare { inner } => inner.0.clone(), + Self::Subtract { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Compare { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Subtract { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for ComparatorMode<'mc> { @@ -14853,6 +15190,12 @@ impl<'mc> JNIInstantiatable<'mc> for ComparatorMode<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "COMPARE" => Ok(ComparatorMode::Compare { + inner: ComparatorModeStruct::from_raw(env, obj)?, + }), + "SUBTRACT" => Ok(ComparatorMode::Subtract { + inner: ComparatorModeStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -16211,10 +16554,28 @@ impl<'mc> Into> for Switch<'mc> { .expect("Error converting Switch into crate::block::data::Powerable") } } -pub enum SwitchFace<'mc> {} +pub enum SwitchFace<'mc> { + Floor { inner: SwitchFaceStruct<'mc> }, + Wall { inner: SwitchFaceStruct<'mc> }, + Ceiling { inner: SwitchFaceStruct<'mc> }, +} impl<'mc> std::fmt::Display for SwitchFace<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + SwitchFace::Floor { .. } => f.write_str("FLOOR"), + SwitchFace::Wall { .. } => f.write_str("WALL"), + SwitchFace::Ceiling { .. } => f.write_str("CEILING"), + } + } +} +impl<'mc> std::ops::Deref for SwitchFace<'mc> { + type Target = SwitchFaceStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + SwitchFace::Floor { inner } => inner, + SwitchFace::Wall { inner } => inner, + SwitchFace::Ceiling { inner } => inner, + } } } @@ -16241,6 +16602,16 @@ impl<'mc> SwitchFace<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "FLOOR" => Ok(SwitchFace::Floor { + inner: SwitchFaceStruct::from_raw(env, obj)?, + }), + "WALL" => Ok(SwitchFace::Wall { + inner: SwitchFaceStruct::from_raw(env, obj)?, + }), + "CEILING" => Ok(SwitchFace::Ceiling { + inner: SwitchFaceStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -16254,10 +16625,18 @@ pub struct SwitchFaceStruct<'mc>( impl<'mc> JNIRaw<'mc> for SwitchFace<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Floor { inner } => inner.0.clone(), + Self::Wall { inner } => inner.0.clone(), + Self::Ceiling { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Floor { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Wall { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Ceiling { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for SwitchFace<'mc> { @@ -16283,6 +16662,15 @@ impl<'mc> JNIInstantiatable<'mc> for SwitchFace<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "FLOOR" => Ok(SwitchFace::Floor { + inner: SwitchFaceStruct::from_raw(env, obj)?, + }), + "WALL" => Ok(SwitchFace::Wall { + inner: SwitchFaceStruct::from_raw(env, obj)?, + }), + "CEILING" => Ok(SwitchFace::Ceiling { + inner: SwitchFaceStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -17603,10 +17991,55 @@ impl<'mc> Into> for Jigsaw<'mc> { .expect("Error converting Jigsaw into crate::block::data::BlockData") } } -pub enum JigsawOrientation<'mc> {} +pub enum JigsawOrientation<'mc> { + DownEast { inner: JigsawOrientationStruct<'mc> }, + DownNorth { inner: JigsawOrientationStruct<'mc> }, + DownSouth { inner: JigsawOrientationStruct<'mc> }, + DownWest { inner: JigsawOrientationStruct<'mc> }, + UpEast { inner: JigsawOrientationStruct<'mc> }, + UpNorth { inner: JigsawOrientationStruct<'mc> }, + UpSouth { inner: JigsawOrientationStruct<'mc> }, + UpWest { inner: JigsawOrientationStruct<'mc> }, + WestUp { inner: JigsawOrientationStruct<'mc> }, + EastUp { inner: JigsawOrientationStruct<'mc> }, + NorthUp { inner: JigsawOrientationStruct<'mc> }, + SouthUp { inner: JigsawOrientationStruct<'mc> }, +} impl<'mc> std::fmt::Display for JigsawOrientation<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + JigsawOrientation::DownEast { .. } => f.write_str("DOWN_EAST"), + JigsawOrientation::DownNorth { .. } => f.write_str("DOWN_NORTH"), + JigsawOrientation::DownSouth { .. } => f.write_str("DOWN_SOUTH"), + JigsawOrientation::DownWest { .. } => f.write_str("DOWN_WEST"), + JigsawOrientation::UpEast { .. } => f.write_str("UP_EAST"), + JigsawOrientation::UpNorth { .. } => f.write_str("UP_NORTH"), + JigsawOrientation::UpSouth { .. } => f.write_str("UP_SOUTH"), + JigsawOrientation::UpWest { .. } => f.write_str("UP_WEST"), + JigsawOrientation::WestUp { .. } => f.write_str("WEST_UP"), + JigsawOrientation::EastUp { .. } => f.write_str("EAST_UP"), + JigsawOrientation::NorthUp { .. } => f.write_str("NORTH_UP"), + JigsawOrientation::SouthUp { .. } => f.write_str("SOUTH_UP"), + } + } +} +impl<'mc> std::ops::Deref for JigsawOrientation<'mc> { + type Target = JigsawOrientationStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + JigsawOrientation::DownEast { inner } => inner, + JigsawOrientation::DownNorth { inner } => inner, + JigsawOrientation::DownSouth { inner } => inner, + JigsawOrientation::DownWest { inner } => inner, + JigsawOrientation::UpEast { inner } => inner, + JigsawOrientation::UpNorth { inner } => inner, + JigsawOrientation::UpSouth { inner } => inner, + JigsawOrientation::UpWest { inner } => inner, + JigsawOrientation::WestUp { inner } => inner, + JigsawOrientation::EastUp { inner } => inner, + JigsawOrientation::NorthUp { inner } => inner, + JigsawOrientation::SouthUp { inner } => inner, + } } } @@ -17633,6 +18066,43 @@ impl<'mc> JigsawOrientation<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "DOWN_EAST" => Ok(JigsawOrientation::DownEast { + inner: JigsawOrientationStruct::from_raw(env, obj)?, + }), + "DOWN_NORTH" => Ok(JigsawOrientation::DownNorth { + inner: JigsawOrientationStruct::from_raw(env, obj)?, + }), + "DOWN_SOUTH" => Ok(JigsawOrientation::DownSouth { + inner: JigsawOrientationStruct::from_raw(env, obj)?, + }), + "DOWN_WEST" => Ok(JigsawOrientation::DownWest { + inner: JigsawOrientationStruct::from_raw(env, obj)?, + }), + "UP_EAST" => Ok(JigsawOrientation::UpEast { + inner: JigsawOrientationStruct::from_raw(env, obj)?, + }), + "UP_NORTH" => Ok(JigsawOrientation::UpNorth { + inner: JigsawOrientationStruct::from_raw(env, obj)?, + }), + "UP_SOUTH" => Ok(JigsawOrientation::UpSouth { + inner: JigsawOrientationStruct::from_raw(env, obj)?, + }), + "UP_WEST" => Ok(JigsawOrientation::UpWest { + inner: JigsawOrientationStruct::from_raw(env, obj)?, + }), + "WEST_UP" => Ok(JigsawOrientation::WestUp { + inner: JigsawOrientationStruct::from_raw(env, obj)?, + }), + "EAST_UP" => Ok(JigsawOrientation::EastUp { + inner: JigsawOrientationStruct::from_raw(env, obj)?, + }), + "NORTH_UP" => Ok(JigsawOrientation::NorthUp { + inner: JigsawOrientationStruct::from_raw(env, obj)?, + }), + "SOUTH_UP" => Ok(JigsawOrientation::SouthUp { + inner: JigsawOrientationStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -17646,10 +18116,40 @@ pub struct JigsawOrientationStruct<'mc>( impl<'mc> JNIRaw<'mc> for JigsawOrientation<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::DownEast { inner } => inner.0.clone(), + Self::DownNorth { inner } => inner.0.clone(), + Self::DownSouth { inner } => inner.0.clone(), + Self::DownWest { inner } => inner.0.clone(), + Self::UpEast { inner } => inner.0.clone(), + Self::UpNorth { inner } => inner.0.clone(), + Self::UpSouth { inner } => inner.0.clone(), + Self::UpWest { inner } => inner.0.clone(), + Self::WestUp { inner } => inner.0.clone(), + Self::EastUp { inner } => inner.0.clone(), + Self::NorthUp { inner } => inner.0.clone(), + Self::SouthUp { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::DownEast { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DownNorth { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DownSouth { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DownWest { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::UpEast { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::UpNorth { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::UpSouth { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::UpWest { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::WestUp { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::EastUp { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::NorthUp { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SouthUp { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for JigsawOrientation<'mc> { @@ -17678,6 +18178,42 @@ impl<'mc> JNIInstantiatable<'mc> for JigsawOrientation<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "DOWN_EAST" => Ok(JigsawOrientation::DownEast { + inner: JigsawOrientationStruct::from_raw(env, obj)?, + }), + "DOWN_NORTH" => Ok(JigsawOrientation::DownNorth { + inner: JigsawOrientationStruct::from_raw(env, obj)?, + }), + "DOWN_SOUTH" => Ok(JigsawOrientation::DownSouth { + inner: JigsawOrientationStruct::from_raw(env, obj)?, + }), + "DOWN_WEST" => Ok(JigsawOrientation::DownWest { + inner: JigsawOrientationStruct::from_raw(env, obj)?, + }), + "UP_EAST" => Ok(JigsawOrientation::UpEast { + inner: JigsawOrientationStruct::from_raw(env, obj)?, + }), + "UP_NORTH" => Ok(JigsawOrientation::UpNorth { + inner: JigsawOrientationStruct::from_raw(env, obj)?, + }), + "UP_SOUTH" => Ok(JigsawOrientation::UpSouth { + inner: JigsawOrientationStruct::from_raw(env, obj)?, + }), + "UP_WEST" => Ok(JigsawOrientation::UpWest { + inner: JigsawOrientationStruct::from_raw(env, obj)?, + }), + "WEST_UP" => Ok(JigsawOrientation::WestUp { + inner: JigsawOrientationStruct::from_raw(env, obj)?, + }), + "EAST_UP" => Ok(JigsawOrientation::EastUp { + inner: JigsawOrientationStruct::from_raw(env, obj)?, + }), + "NORTH_UP" => Ok(JigsawOrientation::NorthUp { + inner: JigsawOrientationStruct::from_raw(env, obj)?, + }), + "SOUTH_UP" => Ok(JigsawOrientation::SouthUp { + inner: JigsawOrientationStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -18249,10 +18785,28 @@ impl<'mc> Into> for Bamboo<'mc> { .expect("Error converting Bamboo into crate::block::data::mod_type::Sapling") } } -pub enum BambooLeaves<'mc> {} +pub enum BambooLeaves<'mc> { + None { inner: BambooLeavesStruct<'mc> }, + Small { inner: BambooLeavesStruct<'mc> }, + Large { inner: BambooLeavesStruct<'mc> }, +} impl<'mc> std::fmt::Display for BambooLeaves<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + BambooLeaves::None { .. } => f.write_str("NONE"), + BambooLeaves::Small { .. } => f.write_str("SMALL"), + BambooLeaves::Large { .. } => f.write_str("LARGE"), + } + } +} +impl<'mc> std::ops::Deref for BambooLeaves<'mc> { + type Target = BambooLeavesStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + BambooLeaves::None { inner } => inner, + BambooLeaves::Small { inner } => inner, + BambooLeaves::Large { inner } => inner, + } } } @@ -18279,6 +18833,16 @@ impl<'mc> BambooLeaves<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NONE" => Ok(BambooLeaves::None { + inner: BambooLeavesStruct::from_raw(env, obj)?, + }), + "SMALL" => Ok(BambooLeaves::Small { + inner: BambooLeavesStruct::from_raw(env, obj)?, + }), + "LARGE" => Ok(BambooLeaves::Large { + inner: BambooLeavesStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -18292,10 +18856,18 @@ pub struct BambooLeavesStruct<'mc>( impl<'mc> JNIRaw<'mc> for BambooLeaves<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::None { inner } => inner.0.clone(), + Self::Small { inner } => inner.0.clone(), + Self::Large { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::None { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Small { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Large { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for BambooLeaves<'mc> { @@ -18321,6 +18893,15 @@ impl<'mc> JNIInstantiatable<'mc> for BambooLeaves<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NONE" => Ok(BambooLeaves::None { + inner: BambooLeavesStruct::from_raw(env, obj)?, + }), + "SMALL" => Ok(BambooLeaves::Small { + inner: BambooLeavesStruct::from_raw(env, obj)?, + }), + "LARGE" => Ok(BambooLeaves::Large { + inner: BambooLeavesStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -18606,211 +19187,625 @@ impl<'mc> StructureBlock<'mc> { &self.jni_object(), "requiresCorrectToolForDrops", sig.as_str(), - vec![], + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns if the given item is a preferred choice to break this Block. + /// In some cases this determines if a block will drop anything or extra + /// loot. + pub fn is_preferred_tool( + &self, + tool: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(tool.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isPreferredTool", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the reaction of the block when moved by a piston + pub fn piston_move_reaction( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPistonMoveReaction", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Checks if this state would be properly supported if it were placed at + /// the block at the given {@link Location}. + /// + /// This may be useful, for instance, to check whether or not a wall torch is + /// capable of surviving on its neighbouring block states. + pub fn is_supported( + &self, + location: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSupported", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks if a state's {@link BlockFace} is capable of providing a given level + /// of {@link BlockSupport} for neighbouring block states. + /// + /// Any given state may support either none, one, or more than one level of block + /// support depending on its states. A common example would be a wall's ability to support + /// torches only on the center of the upper block face, whereas a grass block would + /// support all levels of block support on all block faces. + pub fn is_face_sturdy( + &self, + face: impl Into>, + support: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;Lorg/bukkit/block/BlockSupport;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(support.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isFaceSturdy", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the color this block should appear as when rendered on a map. + pub fn map_color(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Color;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMapColor", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Color::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the material that a player would use to place this block. + /// + /// For most blocks this is the same as {@link #getMaterial()} but some blocks + /// have different materials used to place them. + /// For example: + ///
+    /// {@link Material#REDSTONE_WIRE} -> {@link Material#REDSTONE}
+    /// {@link Material#CARROTS} -> {@link Material#CARROT}
+    /// 
+ pub fn placement_material(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPlacementMaterial", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Rotates this blockdata by the specified {@link StructureRotation}. + /// + /// This has no effect on blocks that do not have any rotatable states. + pub fn rotate( + &self, + rotation: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/structure/StructureRotation;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(rotation.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "rotate", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Mirrors this blockdata using the specified {@link Mirror}. + /// + /// This has no effect on blocks that do not have any mirrorable states. + pub fn mirror( + &self, + mirror: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/structure/Mirror;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(mirror.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "mirror", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns if the given item is a preferred choice to break this Block. - /// In some cases this determines if a block will drop anything or extra - /// loot. - pub fn is_preferred_tool( + /// Copies all applicable properties from this BlockData to the provided + /// BlockData. + /// + /// Only modifies properties that both blocks share in common. + pub fn copy_to( &self, - tool: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Z"); + other: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tool.into().jni_object().clone()) + jni::objects::JObject::from_raw(other.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "isPreferredTool", + "copyTo", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns the reaction of the block when moved by a piston - pub fn piston_move_reaction( + /// Creates a new default {@link BlockState} for this type of Block, not + /// bound to a location. + pub fn create_block_state( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockState;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPistonMoveReaction", + "createBlockState", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Checks if this state would be properly supported if it were placed at - /// the block at the given {@link Location}. - /// - /// This may be useful, for instance, to check whether or not a wall torch is - /// capable of surviving on its neighbouring block states. - pub fn is_supported( - &self, - location: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSupported", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Checks if a state's {@link BlockFace} is capable of providing a given level - /// of {@link BlockSupport} for neighbouring block states. - /// - /// Any given state may support either none, one, or more than one level of block - /// support depending on its states. A common example would be a wall's ability to support - /// torches only on the center of the upper block face, whereas a grass block would - /// support all levels of block support on all block faces. - pub fn is_face_sturdy( - &self, - face: impl Into>, - support: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;Lorg/bukkit/block/BlockSupport;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(support.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isFaceSturdy", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], +} +impl<'mc> Into> for StructureBlock<'mc> { + fn into(self) -> crate::block::data::BlockData<'mc> { + crate::block::data::BlockData::from_raw(&self.jni_ref(), self.1) + .expect("Error converting StructureBlock into crate::block::data::BlockData") + } +} +pub enum StructureBlockMode<'mc> { + Save { + inner: StructureBlockModeStruct<'mc>, + }, + Load { + inner: StructureBlockModeStruct<'mc>, + }, + Corner { + inner: StructureBlockModeStruct<'mc>, + }, + Data { + inner: StructureBlockModeStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for StructureBlockMode<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + StructureBlockMode::Save { .. } => f.write_str("SAVE"), + StructureBlockMode::Load { .. } => f.write_str("LOAD"), + StructureBlockMode::Corner { .. } => f.write_str("CORNER"), + StructureBlockMode::Data { .. } => f.write_str("DATA"), + } + } +} +impl<'mc> std::ops::Deref for StructureBlockMode<'mc> { + type Target = StructureBlockModeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + StructureBlockMode::Save { inner } => inner, + StructureBlockMode::Load { inner } => inner, + StructureBlockMode::Corner { inner } => inner, + StructureBlockMode::Data { inner } => inner, + } + } +} + +impl<'mc> StructureBlockMode<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/block/data/type/StructureBlock/Mode"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/block/data/type/StructureBlock/Mode;", + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "SAVE" => Ok(StructureBlockMode::Save { + inner: StructureBlockModeStruct::from_raw(env, obj)?, + }), + "LOAD" => Ok(StructureBlockMode::Load { + inner: StructureBlockModeStruct::from_raw(env, obj)?, + }), + "CORNER" => Ok(StructureBlockMode::Corner { + inner: StructureBlockModeStruct::from_raw(env, obj)?, + }), + "DATA" => Ok(StructureBlockMode::Data { + inner: StructureBlockModeStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } - /// Gets the color this block should appear as when rendered on a map. - pub fn map_color(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Color;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMapColor", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Color::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} + +#[repr(C)] +pub struct StructureBlockModeStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for StructureBlockMode<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Save { inner } => inner.0.clone(), + Self::Load { inner } => inner.0.clone(), + Self::Corner { inner } => inner.0.clone(), + Self::Data { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Save { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Load { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Corner { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Data { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for StructureBlockMode<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate StructureBlockMode from null object.").into(), + ); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/block/data/type/StructureBlock/Mode")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a StructureBlockMode object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "SAVE" => Ok(StructureBlockMode::Save { + inner: StructureBlockModeStruct::from_raw(env, obj)?, + }), + "LOAD" => Ok(StructureBlockMode::Load { + inner: StructureBlockModeStruct::from_raw(env, obj)?, + }), + "CORNER" => Ok(StructureBlockMode::Corner { + inner: StructureBlockModeStruct::from_raw(env, obj)?, + }), + "DATA" => Ok(StructureBlockMode::Data { + inner: StructureBlockModeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for StructureBlockModeStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for StructureBlockModeStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate StructureBlockModeStruct from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/block/data/type/StructureBlock/Mode")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a StructureBlockModeStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> StructureBlockModeStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/block/data/type/StructureBlock/Mode;"); + let cls = jni.find_class("org/bukkit/block/data/type/StructureBlock/Mode"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::block::data::mod_type::StructureBlockMode::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct Ladder<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Ladder<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Gets the material that a player would use to place this block. - /// - /// For most blocks this is the same as {@link #getMaterial()} but some blocks - /// have different materials used to place them. - /// For example: - ///
-    /// {@link Material#REDSTONE_WIRE} -> {@link Material#REDSTONE}
-    /// {@link Material#CARROTS} -> {@link Material#CARROT}
-    /// 
- pub fn placement_material(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPlacementMaterial", - sig.as_str(), - vec![], - ); + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Ladder<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Ladder from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Ladder")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Ladder object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Ladder<'mc> { + /// Gets the value of the 'facing' property. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Rotates this blockdata by the specified {@link StructureRotation}. - /// - /// This has no effect on blocks that do not have any rotatable states. - pub fn rotate( + /// Sets the value of the 'facing' property. + pub fn set_facing( &self, - rotation: impl Into>, + facing: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/structure/StructureRotation;)V"); + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(rotation.into().jni_object().clone()) + jni::objects::JObject::from_raw(facing.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "rotate", + "setFacing", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Mirrors this blockdata using the specified {@link Mirror}. - /// - /// This has no effect on blocks that do not have any mirrorable states. - pub fn mirror( - &self, - mirror: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/structure/Mirror;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(mirror.into().jni_object().clone()) - }); + /// Gets the faces which are applicable to this block. + pub fn faces(&self) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFaces", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the value of the 'waterlogged' property. + pub fn is_waterlogged(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isWaterlogged", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the value of the 'waterlogged' property. + pub fn set_waterlogged(&self, waterlogged: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(waterlogged.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "mirror", + "setWaterlogged", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Copies all applicable properties from this BlockData to the provided - /// BlockData. - /// - /// Only modifies properties that both blocks share in common. - pub fn copy_to( + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Ladder<'mc> { + fn into(self) -> crate::block::data::Directional<'mc> { + crate::block::data::Directional::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Ladder into crate::block::data::Directional") + } +} +impl<'mc> Into> for Ladder<'mc> { + fn into(self) -> crate::block::data::Waterlogged<'mc> { + crate::block::data::Waterlogged::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Ladder into crate::block::data::Waterlogged") + } +} +#[repr(C)] +pub struct Slab<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Slab<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Slab<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Slab from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Slab")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Slab object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Slab<'mc> { + /// Gets the value of the 'type' property. + pub fn get_type( &self, - other: impl Into>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/type/Slab/Type;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::data::mod_type::SlabType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the value of the 'type' property. + pub fn set_type( + &self, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); + let sig = String::from("(Lorg/bukkit/block/data/type/Slab/Type;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "copyTo", + "setType", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Creates a new default {@link BlockState} for this type of Block, not - /// bound to a location. - pub fn create_block_state( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockState;"); + /// Gets the value of the 'waterlogged' property. + pub fn is_waterlogged(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isWaterlogged", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the value of the 'waterlogged' property. + pub fn set_waterlogged(&self, waterlogged: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(waterlogged.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "createBlockState", + "setWaterlogged", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -18818,31 +19813,49 @@ impl<'mc> StructureBlock<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for StructureBlock<'mc> { - fn into(self) -> crate::block::data::BlockData<'mc> { - crate::block::data::BlockData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting StructureBlock into crate::block::data::BlockData") +impl<'mc> Into> for Slab<'mc> { + fn into(self) -> crate::block::data::Waterlogged<'mc> { + crate::block::data::Waterlogged::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Slab into crate::block::data::Waterlogged") } } -pub enum StructureBlockMode<'mc> {} -impl<'mc> std::fmt::Display for StructureBlockMode<'mc> { +pub enum SlabType<'mc> { + Top { inner: SlabTypeStruct<'mc> }, + Bottom { inner: SlabTypeStruct<'mc> }, + Double { inner: SlabTypeStruct<'mc> }, +} +impl<'mc> std::fmt::Display for SlabType<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + SlabType::Top { .. } => f.write_str("TOP"), + SlabType::Bottom { .. } => f.write_str("BOTTOM"), + SlabType::Double { .. } => f.write_str("DOUBLE"), + } + } +} +impl<'mc> std::ops::Deref for SlabType<'mc> { + type Target = SlabTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + SlabType::Top { inner } => inner, + SlabType::Bottom { inner } => inner, + SlabType::Double { inner } => inner, + } } } -impl<'mc> StructureBlockMode<'mc> { +impl<'mc> SlabType<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/block/data/type/StructureBlock/Mode"); + let cls = env.find_class("org/bukkit/block/data/type/Slab/Type"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/block/data/type/StructureBlock/Mode;", + "(Ljava/lang/String;)Lorg/bukkit/block/data/type/Slab/Type;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -18854,40 +19867,55 @@ impl<'mc> StructureBlockMode<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "TOP" => Ok(SlabType::Top { + inner: SlabTypeStruct::from_raw(env, obj)?, + }), + "BOTTOM" => Ok(SlabType::Bottom { + inner: SlabTypeStruct::from_raw(env, obj)?, + }), + "DOUBLE" => Ok(SlabType::Double { + inner: SlabTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct StructureBlockModeStruct<'mc>( +pub struct SlabTypeStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for StructureBlockMode<'mc> { +impl<'mc> JNIRaw<'mc> for SlabType<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Top { inner } => inner.0.clone(), + Self::Bottom { inner } => inner.0.clone(), + Self::Double { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Top { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Bottom { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Double { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for StructureBlockMode<'mc> { +impl<'mc> JNIInstantiatable<'mc> for SlabType<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate StructureBlockMode from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate SlabType from null object.").into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/block/data/type/StructureBlock/Mode")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Slab/Type")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a StructureBlockMode object, got {}", + "Invalid argument passed. Expected a SlabType object, got {}", name ) .into()) @@ -18899,13 +19927,22 @@ impl<'mc> JNIInstantiatable<'mc> for StructureBlockMode<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "TOP" => Ok(SlabType::Top { + inner: SlabTypeStruct::from_raw(env, obj)?, + }), + "BOTTOM" => Ok(SlabType::Bottom { + inner: SlabTypeStruct::from_raw(env, obj)?, + }), + "DOUBLE" => Ok(SlabType::Double { + inner: SlabTypeStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for StructureBlockModeStruct<'mc> { +impl<'mc> JNIRaw<'mc> for SlabTypeStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -18913,22 +19950,20 @@ impl<'mc> JNIRaw<'mc> for StructureBlockModeStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for StructureBlockModeStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for SlabTypeStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate StructureBlockModeStruct from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate SlabTypeStruct from null object.").into(), + ); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/block/data/type/StructureBlock/Mode")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Slab/Type")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a StructureBlockModeStruct object, got {}", + "Invalid argument passed. Expected a SlabTypeStruct object, got {}", name ) .into()) @@ -18938,18 +19973,17 @@ impl<'mc> JNIInstantiatable<'mc> for StructureBlockModeStruct<'mc> { } } -impl<'mc> StructureBlockModeStruct<'mc> { +impl<'mc> SlabTypeStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/block/data/type/StructureBlock/Mode;"); - let cls = jni.find_class("org/bukkit/block/data/type/StructureBlock/Mode"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/type/Slab/Type;"); + let cls = jni.find_class("org/bukkit/block/data/type/Slab/Type"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::block::data::mod_type::StructureBlockMode::from_raw(&jni, obj) + crate::block::data::mod_type::SlabType::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -18958,12 +19992,12 @@ impl<'mc> StructureBlockModeStruct<'mc> { } } #[repr(C)] -pub struct Ladder<'mc>( +pub struct Barrel<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Ladder<'mc> { +impl<'mc> JNIRaw<'mc> for Barrel<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -18971,18 +20005,18 @@ impl<'mc> JNIRaw<'mc> for Ladder<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Ladder<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Barrel<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Ladder from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Barrel from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Ladder")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Barrel")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Ladder object, got {}", + "Invalid argument passed. Expected a Barrel object, got {}", name ) .into()) @@ -18992,7 +20026,7 @@ impl<'mc> JNIInstantiatable<'mc> for Ladder<'mc> { } } -impl<'mc> Ladder<'mc> { +impl<'mc> Barrel<'mc> { /// Gets the value of the 'facing' property. pub fn facing(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/block/BlockFace;"); @@ -19000,199 +20034,598 @@ impl<'mc> Ladder<'mc> { .jni_ref() .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the value of the 'facing' property. + pub fn set_facing( + &self, + facing: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(facing.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFacing", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the faces which are applicable to this block. + pub fn faces(&self) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFaces", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the value of the 'open' property. + pub fn is_open(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isOpen", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the value of the 'open' property. + pub fn set_open(&self, open: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(open.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setOpen", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Barrel<'mc> { + fn into(self) -> crate::block::data::Directional<'mc> { + crate::block::data::Directional::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Barrel into crate::block::data::Directional") + } +} +impl<'mc> Into> for Barrel<'mc> { + fn into(self) -> crate::block::data::Openable<'mc> { + crate::block::data::Openable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Barrel into crate::block::data::Openable") + } +} +#[repr(C)] +pub struct TrialSpawner<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for TrialSpawner<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for TrialSpawner<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate TrialSpawner from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/TrialSpawner")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a TrialSpawner object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> TrialSpawner<'mc> { + /// Gets the value of the 'trial_spawner_state' property. + pub fn trial_spawner_state( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/block/data/type/TrialSpawner/State;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTrialSpawnerState", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::block::data::mod_type::TrialSpawnerState::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the value of the 'trial_spawner_state' property. + pub fn set_trial_spawner_state( + &self, + state: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/data/type/TrialSpawner/State;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(state.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTrialSpawnerState", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the value of the 'ominous' property. + pub fn is_ominous(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isOminous", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the value of the 'ominous' property. + pub fn set_ominous(&self, ominous: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(ominous.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setOminous", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the Material represented by this block data. + pub fn material(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaterial", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets a string, which when passed into a method such as + /// {@link Server#createBlockData(java.lang.String)} will recreate this or a + /// similar instance where unspecified states (if any) may be optionally + /// omitted. If this instance was parsed and states are omitted, this exact + /// instance will be creatable when parsed again, else their equality cannot + /// be guaranteed. + /// + /// This method will only take effect for BlockData instances created by + /// methods such as {@link Server#createBlockData(String)} or any similar + /// method whereby states are optionally defined. If otherwise, the result of + /// {@link #getAsString()} will be returned. The following behaviour would be + /// expected: + ///
{@code
+    /// String dataString = "minecraft:chest[waterlogged=true]"
+    /// BlockData data = Bukkit.createBlockData(dataString);
+    /// dataString.equals(data.getAsString(true)); // This would return true
+    /// dataString.equals(data.getAsString(false)); // This would return false as all states are present
+    /// dataString.equals(data.getAsString()); // This is equivalent to the above, "getAsString(false)"
+    /// }
+ pub fn get_as_string( + &self, + hide_unspecified: bool, + ) -> Result> { + let sig = String::from("(Z)Ljava/lang/String;"); + let val_1 = jni::objects::JValueGen::Bool(hide_unspecified.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAsString", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Merges all explicitly set states from the given data with this BlockData. + /// + /// Note that the given data MUST have been created from one of the String + /// parse methods, e.g. {@link Server#createBlockData(java.lang.String)} and + /// not have been subsequently modified. + /// + /// Note also that the block types must match identically. + pub fn merge( + &self, + data: impl Into>, + ) -> Result, Box> { + let sig = + String::from("(Lorg/bukkit/block/data/BlockData;)Lorg/bukkit/block/data/BlockData;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(data.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "merge", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the value of the 'facing' property. - pub fn set_facing( + /// Checks if the specified BlockData matches this block data. + /// + /// The semantics of this method are such that for manually created or + /// modified BlockData it has the same effect as + /// {@link Object#equals(java.lang.Object)}, whilst for parsed data (that to + /// which {@link #merge(org.bukkit.block.data.BlockData)} applies, it will + /// return true when the type and all explicitly set states match. + /// + /// Note that these semantics mean that a.matches(b) may not be the same + /// as b.matches(a) + pub fn matches( &self, - facing: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + data: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/block/data/BlockData;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(facing.into().jni_object().clone()) + jni::objects::JObject::from_raw(data.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setFacing", + "matches", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the faces which are applicable to this block. - pub fn faces(&self) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Returns a copy of this BlockData. + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getFaces", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the value of the 'waterlogged' property. - pub fn is_waterlogged(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the block's {@link SoundGroup} which can be used to get its step + /// sound, hit sound, and others. + pub fn sound_group(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/SoundGroup;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isWaterlogged", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSoundGroup", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::SoundGroup::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the value of the 'waterlogged' property. - pub fn set_waterlogged(&self, waterlogged: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(waterlogged.into()); + /// Get the amount of light emitted by this state when in the world. + pub fn light_emission(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "setWaterlogged", + "getLightEmission", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Ladder<'mc> { - fn into(self) -> crate::block::data::Directional<'mc> { - crate::block::data::Directional::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Ladder into crate::block::data::Directional") + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} -impl<'mc> Into> for Ladder<'mc> { - fn into(self) -> crate::block::data::Waterlogged<'mc> { - crate::block::data::Waterlogged::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Ladder into crate::block::data::Waterlogged") + /// Check whether or not this state will occlude other blocks. + /// + /// Block state occlusion affects visual features of other blocks (e.g. leaves and + /// wet sponges will not spawn dripping water particles if an occluding state is + /// below it), or whether light will pass through it. + pub fn is_occluding(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isOccluding", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -#[repr(C)] -pub struct Slab<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Slab<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Check whether or not this state requires a specific item to be used to drop + /// items when broken. For example, diamond ore requires an iron pickaxe and will + /// not drop diamonds when broken with a wooden or stone pickaxe. + pub fn requires_correct_tool_for_drops(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "requiresCorrectToolForDrops", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Returns if the given item is a preferred choice to break this Block. + /// In some cases this determines if a block will drop anything or extra + /// loot. + pub fn is_preferred_tool( + &self, + tool: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(tool.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isPreferredTool", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for Slab<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Slab from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Slab")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Slab object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Returns the reaction of the block when moved by a piston + pub fn piston_move_reaction( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPistonMoveReaction", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} - -impl<'mc> Slab<'mc> { - /// Gets the value of the 'type' property. - pub fn get_type( + /// Checks if this state would be properly supported if it were placed at + /// the block at the given {@link Location}. + /// + /// This may be useful, for instance, to check whether or not a wall torch is + /// capable of surviving on its neighbouring block states. + pub fn is_supported( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/type/Slab/Type;"); + location: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSupported", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks if a state's {@link BlockFace} is capable of providing a given level + /// of {@link BlockSupport} for neighbouring block states. + /// + /// Any given state may support either none, one, or more than one level of block + /// support depending on its states. A common example would be a wall's ability to support + /// torches only on the center of the upper block face, whereas a grass block would + /// support all levels of block support on all block faces. + pub fn is_face_sturdy( + &self, + face: impl Into>, + support: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;Lorg/bukkit/block/BlockSupport;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(support.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isFaceSturdy", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the color this block should appear as when rendered on a map. + pub fn map_color(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Color;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMapColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::data::mod_type::SlabType::from_raw(&self.jni_ref(), unsafe { + crate::Color::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the value of the 'type' property. - pub fn set_type( + /// Gets the material that a player would use to place this block. + /// + /// For most blocks this is the same as {@link #getMaterial()} but some blocks + /// have different materials used to place them. + /// For example: + ///
+    /// {@link Material#REDSTONE_WIRE} -> {@link Material#REDSTONE}
+    /// {@link Material#CARROTS} -> {@link Material#CARROT}
+    /// 
+ pub fn placement_material(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPlacementMaterial", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Rotates this blockdata by the specified {@link StructureRotation}. + /// + /// This has no effect on blocks that do not have any rotatable states. + pub fn rotate( &self, - val_type: impl Into>, + rotation: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/data/type/Slab/Type;)V"); + let sig = String::from("(Lorg/bukkit/block/structure/StructureRotation;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(rotation.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setType", + "rotate", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the value of the 'waterlogged' property. - pub fn is_waterlogged(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isWaterlogged", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Mirrors this blockdata using the specified {@link Mirror}. + /// + /// This has no effect on blocks that do not have any mirrorable states. + pub fn mirror( + &self, + mirror: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/structure/Mirror;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(mirror.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "mirror", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the value of the 'waterlogged' property. - pub fn set_waterlogged(&self, waterlogged: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(waterlogged.into()); + /// Copies all applicable properties from this BlockData to the provided + /// BlockData. + /// + /// Only modifies properties that both blocks share in common. + pub fn copy_to( + &self, + other: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(other.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setWaterlogged", + "copyTo", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } + /// Creates a new default {@link BlockState} for this type of Block, not + /// bound to a location. + pub fn create_block_state( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockState;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "createBlockState", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Slab<'mc> { - fn into(self) -> crate::block::data::Waterlogged<'mc> { - crate::block::data::Waterlogged::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Slab into crate::block::data::Waterlogged") +impl<'mc> Into> for TrialSpawner<'mc> { + fn into(self) -> crate::block::data::BlockData<'mc> { + crate::block::data::BlockData::from_raw(&self.jni_ref(), self.1) + .expect("Error converting TrialSpawner into crate::block::data::BlockData") } } -pub enum SlabType<'mc> {} -impl<'mc> std::fmt::Display for SlabType<'mc> { +pub enum TrialSpawnerState<'mc> { + Inactive { inner: TrialSpawnerStateStruct<'mc> }, + WaitingForPlayers { inner: TrialSpawnerStateStruct<'mc> }, + Active { inner: TrialSpawnerStateStruct<'mc> }, + WaitingForRewardEjection { inner: TrialSpawnerStateStruct<'mc> }, + EjectingReward { inner: TrialSpawnerStateStruct<'mc> }, + Cooldown { inner: TrialSpawnerStateStruct<'mc> }, +} +impl<'mc> std::fmt::Display for TrialSpawnerState<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + TrialSpawnerState::Inactive { .. } => f.write_str("INACTIVE"), + TrialSpawnerState::WaitingForPlayers { .. } => f.write_str("WAITING_FOR_PLAYERS"), + TrialSpawnerState::Active { .. } => f.write_str("ACTIVE"), + TrialSpawnerState::WaitingForRewardEjection { .. } => { + f.write_str("WAITING_FOR_REWARD_EJECTION") + } + TrialSpawnerState::EjectingReward { .. } => f.write_str("EJECTING_REWARD"), + TrialSpawnerState::Cooldown { .. } => f.write_str("COOLDOWN"), + } + } +} +impl<'mc> std::ops::Deref for TrialSpawnerState<'mc> { + type Target = TrialSpawnerStateStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + TrialSpawnerState::Inactive { inner } => inner, + TrialSpawnerState::WaitingForPlayers { inner } => inner, + TrialSpawnerState::Active { inner } => inner, + TrialSpawnerState::WaitingForRewardEjection { inner } => inner, + TrialSpawnerState::EjectingReward { inner } => inner, + TrialSpawnerState::Cooldown { inner } => inner, + } } } -impl<'mc> SlabType<'mc> { +impl<'mc> TrialSpawnerState<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/block/data/type/Slab/Type"); + let cls = env.find_class("org/bukkit/block/data/type/TrialSpawner/State"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/block/data/type/Slab/Type;", + "(Ljava/lang/String;)Lorg/bukkit/block/data/type/TrialSpawner/State;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -19204,37 +20637,79 @@ impl<'mc> SlabType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "INACTIVE" => Ok(TrialSpawnerState::Inactive { + inner: TrialSpawnerStateStruct::from_raw(env, obj)?, + }), + "WAITING_FOR_PLAYERS" => Ok(TrialSpawnerState::WaitingForPlayers { + inner: TrialSpawnerStateStruct::from_raw(env, obj)?, + }), + "ACTIVE" => Ok(TrialSpawnerState::Active { + inner: TrialSpawnerStateStruct::from_raw(env, obj)?, + }), + "WAITING_FOR_REWARD_EJECTION" => Ok(TrialSpawnerState::WaitingForRewardEjection { + inner: TrialSpawnerStateStruct::from_raw(env, obj)?, + }), + "EJECTING_REWARD" => Ok(TrialSpawnerState::EjectingReward { + inner: TrialSpawnerStateStruct::from_raw(env, obj)?, + }), + "COOLDOWN" => Ok(TrialSpawnerState::Cooldown { + inner: TrialSpawnerStateStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct SlabTypeStruct<'mc>( +pub struct TrialSpawnerStateStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for SlabType<'mc> { +impl<'mc> JNIRaw<'mc> for TrialSpawnerState<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Inactive { inner } => inner.0.clone(), + Self::WaitingForPlayers { inner } => inner.0.clone(), + Self::Active { inner } => inner.0.clone(), + Self::WaitingForRewardEjection { inner } => inner.0.clone(), + Self::EjectingReward { inner } => inner.0.clone(), + Self::Cooldown { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Inactive { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::WaitingForPlayers { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Active { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::WaitingForRewardEjection { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EjectingReward { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Cooldown { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for SlabType<'mc> { +impl<'mc> JNIInstantiatable<'mc> for TrialSpawnerState<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate SlabType from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate TrialSpawnerState from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Slab/Type")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/block/data/type/TrialSpawner/State")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SlabType object, got {}", + "Invalid argument passed. Expected a TrialSpawnerState object, got {}", name ) .into()) @@ -19246,13 +20721,31 @@ impl<'mc> JNIInstantiatable<'mc> for SlabType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "INACTIVE" => Ok(TrialSpawnerState::Inactive { + inner: TrialSpawnerStateStruct::from_raw(env, obj)?, + }), + "WAITING_FOR_PLAYERS" => Ok(TrialSpawnerState::WaitingForPlayers { + inner: TrialSpawnerStateStruct::from_raw(env, obj)?, + }), + "ACTIVE" => Ok(TrialSpawnerState::Active { + inner: TrialSpawnerStateStruct::from_raw(env, obj)?, + }), + "WAITING_FOR_REWARD_EJECTION" => Ok(TrialSpawnerState::WaitingForRewardEjection { + inner: TrialSpawnerStateStruct::from_raw(env, obj)?, + }), + "EJECTING_REWARD" => Ok(TrialSpawnerState::EjectingReward { + inner: TrialSpawnerStateStruct::from_raw(env, obj)?, + }), + "COOLDOWN" => Ok(TrialSpawnerState::Cooldown { + inner: TrialSpawnerStateStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for SlabTypeStruct<'mc> { +impl<'mc> JNIRaw<'mc> for TrialSpawnerStateStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -19260,20 +20753,22 @@ impl<'mc> JNIRaw<'mc> for SlabTypeStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for SlabTypeStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for TrialSpawnerStateStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate SlabTypeStruct from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate TrialSpawnerStateStruct from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Slab/Type")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/block/data/type/TrialSpawner/State")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SlabTypeStruct object, got {}", + "Invalid argument passed. Expected a TrialSpawnerStateStruct object, got {}", name ) .into()) @@ -19283,17 +20778,18 @@ impl<'mc> JNIInstantiatable<'mc> for SlabTypeStruct<'mc> { } } -impl<'mc> SlabTypeStruct<'mc> { +impl<'mc> TrialSpawnerStateStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/type/Slab/Type;"); - let cls = jni.find_class("org/bukkit/block/data/type/Slab/Type"); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/block/data/type/TrialSpawner/State;"); + let cls = jni.find_class("org/bukkit/block/data/type/TrialSpawner/State"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::block::data::mod_type::SlabType::from_raw(&jni, obj) + crate::block::data::mod_type::TrialSpawnerState::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -19302,12 +20798,12 @@ impl<'mc> SlabTypeStruct<'mc> { } } #[repr(C)] -pub struct Barrel<'mc>( +pub struct CopperBulb<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Barrel<'mc> { +impl<'mc> JNIRaw<'mc> for CopperBulb<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -19315,18 +20811,18 @@ impl<'mc> JNIRaw<'mc> for Barrel<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Barrel<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CopperBulb<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Barrel from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate CopperBulb from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/Barrel")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/data/type/CopperBulb")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Barrel object, got {}", + "Invalid argument passed. Expected a CopperBulb object, got {}", name ) .into()) @@ -19336,63 +20832,45 @@ impl<'mc> JNIInstantiatable<'mc> for Barrel<'mc> { } } -impl<'mc> Barrel<'mc> { - /// Gets the value of the 'facing' property. - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); +impl<'mc> CopperBulb<'mc> { + /// Gets the value of the 'lit' property. + pub fn is_lit(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isLit", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets the value of the 'facing' property. - pub fn set_facing( - &self, - facing: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(facing.into().jni_object().clone()) - }); + /// Sets the value of the 'lit' property. + pub fn set_lit(&self, lit: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(lit.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setFacing", + "setLit", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the faces which are applicable to this block. - pub fn faces(&self) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFaces", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the value of the 'open' property. - pub fn is_open(&self) -> Result> { + /// Gets the value of the 'powered' property. + pub fn is_powered(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isOpen", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the value of the 'open' property. - pub fn set_open(&self, open: bool) -> Result<(), Box> { + /// Sets the value of the 'powered' property. + pub fn set_powered(&self, powered: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(open.into()); + let val_1 = jni::objects::JValueGen::Bool(powered.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setOpen", + "setPowered", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -19405,16 +20883,16 @@ impl<'mc> Barrel<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Barrel<'mc> { - fn into(self) -> crate::block::data::Directional<'mc> { - crate::block::data::Directional::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Barrel into crate::block::data::Directional") +impl<'mc> Into> for CopperBulb<'mc> { + fn into(self) -> crate::block::data::Lightable<'mc> { + crate::block::data::Lightable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting CopperBulb into crate::block::data::Lightable") } } -impl<'mc> Into> for Barrel<'mc> { - fn into(self) -> crate::block::data::Openable<'mc> { - crate::block::data::Openable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Barrel into crate::block::data::Openable") +impl<'mc> Into> for CopperBulb<'mc> { + fn into(self) -> crate::block::data::Powerable<'mc> { + crate::block::data::Powerable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting CopperBulb into crate::block::data::Powerable") } } #[repr(C)] diff --git a/blackboxmc-rs-bukkit/src/block/mod.rs b/blackboxmc-rs-bukkit/src/block/mod.rs index d89956e..558762b 100644 --- a/blackboxmc-rs-bukkit/src/block/mod.rs +++ b/blackboxmc-rs-bukkit/src/block/mod.rs @@ -2,13 +2,168 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; +pub enum PistonMoveReaction<'mc> { + VariantMove { + inner: PistonMoveReactionStruct<'mc>, + }, + VariantBreak { + inner: PistonMoveReactionStruct<'mc>, + }, + Block { + inner: PistonMoveReactionStruct<'mc>, + }, + Ignore { + inner: PistonMoveReactionStruct<'mc>, + }, + PushOnly { + inner: PistonMoveReactionStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for PistonMoveReaction<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PistonMoveReaction::VariantMove { .. } => f.write_str("MOVE"), + PistonMoveReaction::VariantBreak { .. } => f.write_str("BREAK"), + PistonMoveReaction::Block { .. } => f.write_str("BLOCK"), + PistonMoveReaction::Ignore { .. } => f.write_str("IGNORE"), + PistonMoveReaction::PushOnly { .. } => f.write_str("PUSH_ONLY"), + } + } +} +impl<'mc> std::ops::Deref for PistonMoveReaction<'mc> { + type Target = PistonMoveReactionStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + PistonMoveReaction::VariantMove { inner } => inner, + PistonMoveReaction::VariantBreak { inner } => inner, + PistonMoveReaction::Block { inner } => inner, + PistonMoveReaction::Ignore { inner } => inner, + PistonMoveReaction::PushOnly { inner } => inner, + } + } +} + +impl<'mc> PistonMoveReaction<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/block/PistonMoveReaction"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/block/PistonMoveReaction;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "MOVE" => Ok(PistonMoveReaction::VariantMove { + inner: PistonMoveReactionStruct::from_raw(env, obj)?, + }), + "BREAK" => Ok(PistonMoveReaction::VariantBreak { + inner: PistonMoveReactionStruct::from_raw(env, obj)?, + }), + "BLOCK" => Ok(PistonMoveReaction::Block { + inner: PistonMoveReactionStruct::from_raw(env, obj)?, + }), + "IGNORE" => Ok(PistonMoveReaction::Ignore { + inner: PistonMoveReactionStruct::from_raw(env, obj)?, + }), + "PUSH_ONLY" => Ok(PistonMoveReaction::PushOnly { + inner: PistonMoveReactionStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + #[repr(C)] -pub struct Vault<'mc>( +pub struct PistonMoveReactionStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Vault<'mc> { +impl<'mc> JNIRaw<'mc> for PistonMoveReaction<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::VariantMove { inner } => inner.0.clone(), + Self::VariantBreak { inner } => inner.0.clone(), + Self::Block { inner } => inner.0.clone(), + Self::Ignore { inner } => inner.0.clone(), + Self::PushOnly { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::VariantMove { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VariantBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Block { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Ignore { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PushOnly { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for PistonMoveReaction<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate PistonMoveReaction from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/PistonMoveReaction")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PistonMoveReaction object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "MOVE" => Ok(PistonMoveReaction::VariantMove { + inner: PistonMoveReactionStruct::from_raw(env, obj)?, + }), + "BREAK" => Ok(PistonMoveReaction::VariantBreak { + inner: PistonMoveReactionStruct::from_raw(env, obj)?, + }), + "BLOCK" => Ok(PistonMoveReaction::Block { + inner: PistonMoveReactionStruct::from_raw(env, obj)?, + }), + "IGNORE" => Ok(PistonMoveReaction::Ignore { + inner: PistonMoveReactionStruct::from_raw(env, obj)?, + }), + "PUSH_ONLY" => Ok(PistonMoveReaction::PushOnly { + inner: PistonMoveReactionStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for PistonMoveReactionStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -16,18 +171,21 @@ impl<'mc> JNIRaw<'mc> for Vault<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Vault<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PistonMoveReactionStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Vault from null object.").into()); + return Err(eyre::eyre!( + "Tried to instantiate PistonMoveReactionStruct from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Vault")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/PistonMoveReaction")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Vault object, got {}", + "Invalid argument passed. Expected a PistonMoveReactionStruct object, got {}", name ) .into()) @@ -37,31 +195,50 @@ impl<'mc> JNIInstantiatable<'mc> for Vault<'mc> { } } -impl<'mc> Vault<'mc> { - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - /// - /// This {@link PersistentDataHolder} is only linked to the snapshot instance - /// stored by the {@link BlockState}. - /// When storing changes on the {@link PersistentDataHolder}, the updated - /// content will only be applied to the actual tile entity after one of the - /// {@link #update()} methods is called. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPersistentDataContainer", +impl<'mc> PistonMoveReactionStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + let cls = jni.find_class("org/bukkit/block/PistonMoveReaction"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::block::PistonMoveReaction::from_raw(&jni, obj) + } + #[deprecated] + + pub fn id(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + #[deprecated] + + pub fn get_by_id( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + id: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/block/PistonMoveReaction;"); + let val_1 = jni::objects::JValueGen::Int(id); + let cls = jni.find_class("org/bukkit/block/PistonMoveReaction"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getById", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::block::PistonMoveReaction::from_raw(&jni, obj)?)) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -69,19 +246,332 @@ impl<'mc> Vault<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Vault<'mc> { - fn into(self) -> crate::block::TileState<'mc> { - crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Vault into crate::block::TileState") +pub enum BlockFace<'mc> { + North { inner: BlockFaceStruct<'mc> }, + East { inner: BlockFaceStruct<'mc> }, + South { inner: BlockFaceStruct<'mc> }, + West { inner: BlockFaceStruct<'mc> }, + Up { inner: BlockFaceStruct<'mc> }, + Down { inner: BlockFaceStruct<'mc> }, + NorthEast { inner: BlockFaceStruct<'mc> }, + NorthWest { inner: BlockFaceStruct<'mc> }, + SouthEast { inner: BlockFaceStruct<'mc> }, + SouthWest { inner: BlockFaceStruct<'mc> }, + WestNorthWest { inner: BlockFaceStruct<'mc> }, + NorthNorthWest { inner: BlockFaceStruct<'mc> }, + NorthNorthEast { inner: BlockFaceStruct<'mc> }, + EastNorthEast { inner: BlockFaceStruct<'mc> }, + EastSouthEast { inner: BlockFaceStruct<'mc> }, + SouthSouthEast { inner: BlockFaceStruct<'mc> }, + SouthSouthWest { inner: BlockFaceStruct<'mc> }, + WestSouthWest { inner: BlockFaceStruct<'mc> }, + VariantSelf { inner: BlockFaceStruct<'mc> }, +} +impl<'mc> std::fmt::Display for BlockFace<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + BlockFace::North { .. } => f.write_str("NORTH"), + BlockFace::East { .. } => f.write_str("EAST"), + BlockFace::South { .. } => f.write_str("SOUTH"), + BlockFace::West { .. } => f.write_str("WEST"), + BlockFace::Up { .. } => f.write_str("UP"), + BlockFace::Down { .. } => f.write_str("DOWN"), + BlockFace::NorthEast { .. } => f.write_str("NORTH_EAST"), + BlockFace::NorthWest { .. } => f.write_str("NORTH_WEST"), + BlockFace::SouthEast { .. } => f.write_str("SOUTH_EAST"), + BlockFace::SouthWest { .. } => f.write_str("SOUTH_WEST"), + BlockFace::WestNorthWest { .. } => f.write_str("WEST_NORTH_WEST"), + BlockFace::NorthNorthWest { .. } => f.write_str("NORTH_NORTH_WEST"), + BlockFace::NorthNorthEast { .. } => f.write_str("NORTH_NORTH_EAST"), + BlockFace::EastNorthEast { .. } => f.write_str("EAST_NORTH_EAST"), + BlockFace::EastSouthEast { .. } => f.write_str("EAST_SOUTH_EAST"), + BlockFace::SouthSouthEast { .. } => f.write_str("SOUTH_SOUTH_EAST"), + BlockFace::SouthSouthWest { .. } => f.write_str("SOUTH_SOUTH_WEST"), + BlockFace::WestSouthWest { .. } => f.write_str("WEST_SOUTH_WEST"), + BlockFace::VariantSelf { .. } => f.write_str("SELF"), + } + } +} +impl<'mc> std::ops::Deref for BlockFace<'mc> { + type Target = BlockFaceStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + BlockFace::North { inner } => inner, + BlockFace::East { inner } => inner, + BlockFace::South { inner } => inner, + BlockFace::West { inner } => inner, + BlockFace::Up { inner } => inner, + BlockFace::Down { inner } => inner, + BlockFace::NorthEast { inner } => inner, + BlockFace::NorthWest { inner } => inner, + BlockFace::SouthEast { inner } => inner, + BlockFace::SouthWest { inner } => inner, + BlockFace::WestNorthWest { inner } => inner, + BlockFace::NorthNorthWest { inner } => inner, + BlockFace::NorthNorthEast { inner } => inner, + BlockFace::EastNorthEast { inner } => inner, + BlockFace::EastSouthEast { inner } => inner, + BlockFace::SouthSouthEast { inner } => inner, + BlockFace::SouthSouthWest { inner } => inner, + BlockFace::WestSouthWest { inner } => inner, + BlockFace::VariantSelf { inner } => inner, + } + } +} + +impl<'mc> BlockFace<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/block/BlockFace"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/block/BlockFace;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "NORTH" => Ok(BlockFace::North { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "EAST" => Ok(BlockFace::East { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "SOUTH" => Ok(BlockFace::South { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "WEST" => Ok(BlockFace::West { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "UP" => Ok(BlockFace::Up { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "DOWN" => Ok(BlockFace::Down { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "NORTH_EAST" => Ok(BlockFace::NorthEast { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "NORTH_WEST" => Ok(BlockFace::NorthWest { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "SOUTH_EAST" => Ok(BlockFace::SouthEast { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "SOUTH_WEST" => Ok(BlockFace::SouthWest { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "WEST_NORTH_WEST" => Ok(BlockFace::WestNorthWest { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "NORTH_NORTH_WEST" => Ok(BlockFace::NorthNorthWest { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "NORTH_NORTH_EAST" => Ok(BlockFace::NorthNorthEast { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "EAST_NORTH_EAST" => Ok(BlockFace::EastNorthEast { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "EAST_SOUTH_EAST" => Ok(BlockFace::EastSouthEast { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "SOUTH_SOUTH_EAST" => Ok(BlockFace::SouthSouthEast { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "SOUTH_SOUTH_WEST" => Ok(BlockFace::SouthSouthWest { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "WEST_SOUTH_WEST" => Ok(BlockFace::WestSouthWest { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "SELF" => Ok(BlockFace::VariantSelf { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } + #[repr(C)] -pub struct Crafter<'mc>( +pub struct BlockFaceStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Crafter<'mc> { +impl<'mc> JNIRaw<'mc> for BlockFace<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::North { inner } => inner.0.clone(), + Self::East { inner } => inner.0.clone(), + Self::South { inner } => inner.0.clone(), + Self::West { inner } => inner.0.clone(), + Self::Up { inner } => inner.0.clone(), + Self::Down { inner } => inner.0.clone(), + Self::NorthEast { inner } => inner.0.clone(), + Self::NorthWest { inner } => inner.0.clone(), + Self::SouthEast { inner } => inner.0.clone(), + Self::SouthWest { inner } => inner.0.clone(), + Self::WestNorthWest { inner } => inner.0.clone(), + Self::NorthNorthWest { inner } => inner.0.clone(), + Self::NorthNorthEast { inner } => inner.0.clone(), + Self::EastNorthEast { inner } => inner.0.clone(), + Self::EastSouthEast { inner } => inner.0.clone(), + Self::SouthSouthEast { inner } => inner.0.clone(), + Self::SouthSouthWest { inner } => inner.0.clone(), + Self::WestSouthWest { inner } => inner.0.clone(), + Self::VariantSelf { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::North { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::East { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::South { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::West { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Up { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Down { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::NorthEast { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NorthWest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SouthEast { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SouthWest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WestNorthWest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NorthNorthWest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NorthNorthEast { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EastNorthEast { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EastSouthEast { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SouthSouthEast { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SouthSouthWest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WestSouthWest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VariantSelf { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for BlockFace<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate BlockFace from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/BlockFace")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BlockFace object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "NORTH" => Ok(BlockFace::North { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "EAST" => Ok(BlockFace::East { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "SOUTH" => Ok(BlockFace::South { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "WEST" => Ok(BlockFace::West { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "UP" => Ok(BlockFace::Up { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "DOWN" => Ok(BlockFace::Down { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "NORTH_EAST" => Ok(BlockFace::NorthEast { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "NORTH_WEST" => Ok(BlockFace::NorthWest { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "SOUTH_EAST" => Ok(BlockFace::SouthEast { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "SOUTH_WEST" => Ok(BlockFace::SouthWest { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "WEST_NORTH_WEST" => Ok(BlockFace::WestNorthWest { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "NORTH_NORTH_WEST" => Ok(BlockFace::NorthNorthWest { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "NORTH_NORTH_EAST" => Ok(BlockFace::NorthNorthEast { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "EAST_NORTH_EAST" => Ok(BlockFace::EastNorthEast { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "EAST_SOUTH_EAST" => Ok(BlockFace::EastSouthEast { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "SOUTH_SOUTH_EAST" => Ok(BlockFace::SouthSouthEast { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "SOUTH_SOUTH_WEST" => Ok(BlockFace::SouthSouthWest { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "WEST_SOUTH_WEST" => Ok(BlockFace::WestSouthWest { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + "SELF" => Ok(BlockFace::VariantSelf { + inner: BlockFaceStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for BlockFaceStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -89,18 +579,20 @@ impl<'mc> JNIRaw<'mc> for Crafter<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Crafter<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockFaceStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Crafter from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate BlockFaceStruct from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Crafter")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/BlockFace")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Crafter object, got {}", + "Invalid argument passed. Expected a BlockFaceStruct object, got {}", name ) .into()) @@ -110,196 +602,78 @@ impl<'mc> JNIInstantiatable<'mc> for Crafter<'mc> { } } -impl<'mc> Crafter<'mc> { - /// Gets the number of ticks which this block will remain in the crafting - /// state for. - pub fn crafting_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCraftingTicks", - sig.as_str(), - vec![], - ); +impl<'mc> BlockFaceStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let cls = jni.find_class("org/bukkit/block/BlockFace"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::block::BlockFace::from_raw(&jni, obj) + } + /// Get the amount of X-coordinates to modify to get the represented block + pub fn mod_x(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getModX", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the number of ticks which this block will remain in the crafting - /// state for. - pub fn set_crafting_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCraftingTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether the slot at the specified index is disabled and will not - /// have items placed in it. - pub fn is_slot_disabled(&self, slot: i32) -> Result> { - let sig = String::from("(I)Z"); - let val_1 = jni::objects::JValueGen::Int(slot); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isSlotDisabled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Get the amount of Y-coordinates to modify to get the represented block + pub fn mod_y(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getModY", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether the slot at the specified index is disabled and will not - /// have items placed in it. - pub fn set_slot_disabled( - &self, - slot: i32, - disabled: bool, - ) -> Result<(), Box> { - let sig = String::from("(IZ)V"); - let val_1 = jni::objects::JValueGen::Int(slot); - let val_2 = jni::objects::JValueGen::Bool(disabled.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSlotDisabled", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.i()?) } - /// Gets whether this Crafter is powered. - pub fn is_triggered(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isTriggered", sig.as_str(), vec![]); + /// Get the amount of Z-coordinates to modify to get the represented block + pub fn mod_z(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getModZ", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether this Crafter is powered. - pub fn set_triggered(&self, triggered: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(triggered.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTriggered", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.i()?) } - /// Gets the inventory of the block represented by this block state. - /// - /// If the block was changed to a different type in the meantime, the - /// returned inventory might no longer be valid. - /// - /// If this block state is not placed this will return the captured inventory - /// snapshot instead. - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + /// Gets the normal vector corresponding to this block face. + pub fn direction(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the captured inventory snapshot of this container. - /// - /// The returned inventory is not linked to any block. Any modifications to - /// the returned inventory will not be applied to the block represented by - /// this block state up until {@link #update(boolean, boolean)} has been - /// called. - pub fn snapshot_inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSnapshotInventory", - sig.as_str(), - vec![], - ); + /// Returns true if this face is aligned with one of the unit axes in 3D + /// Cartesian space (ie NORTH, SOUTH, EAST, WEST, UP, DOWN). + pub fn is_cartesian(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCartesian", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Set the loot table for a container or entity. - /// - /// To remove a loot table use null. Do not use {@link LootTables#EMPTY} to - /// clear a LootTable. - pub fn set_loot_table( - &self, - table: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/loot/LootTable;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(table.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLootTable", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.z()?) } - /// Gets the Loot Table attached to this block or entity. - /// - /// If an block/entity does not have a loot table, this will return null, NOT - /// an empty loot table. - pub fn loot_table( + + pub fn opposite_face( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/loot/LootTable;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLootTable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::loot::LootTable::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Set the seed used when this Loot Table generates loot. - pub fn set_seed(&self, seed: i64) -> Result<(), Box> { - let sig = String::from("(J)V"); - let val_1 = jni::objects::JValueGen::Long(seed); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSeed", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the Loot Table's seed. - /// - /// The seed is used when generating loot. - pub fn seed(&self) -> Result> { - let sig = String::from("()J"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSeed", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getOppositeFace", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -307,25 +681,13 @@ impl<'mc> Crafter<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Crafter<'mc> { - fn into(self) -> crate::block::Container<'mc> { - crate::block::Container::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Crafter into crate::block::Container") - } -} -impl<'mc> Into> for Crafter<'mc> { - fn into(self) -> crate::loot::Lootable<'mc> { - crate::loot::Lootable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Crafter into crate::loot::Lootable") - } -} #[repr(C)] -pub struct BlockType<'mc>( +pub struct EndGateway<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockType<'mc> { +impl<'mc> JNIRaw<'mc> for EndGateway<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -333,18 +695,18 @@ impl<'mc> JNIRaw<'mc> for BlockType<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockType<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EndGateway<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate BlockType from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate EndGateway from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/BlockType")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/EndGateway")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockType object, got {}", + "Invalid argument passed. Expected a EndGateway object, got {}", name ) .into()) @@ -354,301 +716,143 @@ impl<'mc> JNIInstantiatable<'mc> for BlockType<'mc> { } } -impl<'mc> BlockType<'mc> { - /// Yields this block type as a typed version of itself with a specific {@link BlockData} representing it. - pub fn typed( +impl<'mc> EndGateway<'mc> { + /// Gets the location that entities are teleported to when + /// entering the gateway portal. + /// + /// If this block state is not placed the location's world will be null. + pub fn exit_location( &self, - block_data_type: std::option::Option>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = block_data_type { - sig += "Ljava/lang/Class;"; - let val_1 = jni::objects::JValueGen::Object(a.into()); - args.push(val_1); - } - sig += ")Lorg/bukkit/block/BlockType/Typed;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "typed", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockTypeTyped::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns true if this BlockType has a corresponding {@link ItemType}. - pub fn has_item_type(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasItemType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the corresponding {@link ItemType} for the given BlockType. - /// - /// If there is no corresponding {@link ItemType} an error will be thrown. - pub fn item_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemType;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getExitLocation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemType::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) + })?)) } - /// Gets the BlockData class of this BlockType - pub fn block_data_class( + /// Sets the exit location that entities are teleported to when + /// they enter the gateway portal. + /// + /// If this block state is not placed the location's world has to be null. + pub fn set_exit_location( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/lang/Class;"); + location: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Location;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getBlockDataClass", + "setExitLocation", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(unsafe { jni::objects::JClass::from_raw(res.as_jni().l) }) - } - /// Creates a new {@link BlockData} instance for this block type, with all - /// properties initialized to unspecified defaults, except for those provided - /// in data. - pub fn create_block_data( - &self, - data: std::option::Option>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = data { - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_1); - } - sig += ")Lorg/bukkit/block/data/BlockData;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "createBlockData", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Check if the blockt type is solid (can be built upon) - pub fn is_solid(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSolid", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Check if the block type can catch fire - pub fn is_flammable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isFlammable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Check if the block type can burn away - pub fn is_burnable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isBurnable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Check if the block type is occludes light in the lighting engine. - /// - /// Generally speaking, most full blocks will occlude light. Non-full blocks are - /// not occluding (e.g. anvils, chests, tall grass, stairs, etc.), nor are specific - /// full blocks such as barriers or spawners which block light despite their texture. - /// - /// An occluding block will have the following effects: - ///
    - ///
  • Chests cannot be opened if an occluding block is above it. - ///
  • Mobs cannot spawn inside of occluding blocks. - ///
  • Only occluding blocks can be "powered" ({@link Block#isBlockPowered()}). - ///
- /// This list may be inconclusive. For a full list of the side effects of an occluding - /// block, see the Minecraft Wiki. - pub fn is_occluding(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isOccluding", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - - pub fn has_gravity(&self) -> Result> { + /// Gets whether this gateway will teleport entities directly to + /// the exit location instead of finding a nearby location. + pub fn is_exact_teleport(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isExactTeleport", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Checks if this block type can be interacted with. - /// - /// Interactable block types include those with functionality when they are - /// interacted with by a player such as chests, furnaces, etc. - /// - /// Some blocks such as piston heads and stairs are considered interactable - /// though may not perform any additional functionality. - /// - /// Note that the interactability of some block types may be dependant on their - /// state as well. This method will return true if there is at least one - /// state in which additional interact handling is performed for the - /// block type. - pub fn is_interactable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInteractable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Sets whether this gateway will teleport entities directly to + /// the exit location instead of finding a nearby location. + pub fn set_exact_teleport(&self, exact: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(exact.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setExactTeleport", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Obtains the block's hardness level (also known as "strength"). + /// Gets the age in ticks of the gateway. /// - /// This number is used to calculate the time required to break each block. - pub fn hardness(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHardness", sig.as_str(), vec![]); + /// If the age is less than 200 ticks a magenta beam will be emitted, whilst + /// if it is a multiple of 2400 ticks a purple beam will be emitted. + pub fn age(&self) -> Result> { + let sig = String::from("()J"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getAge", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + Ok(res.j()?) } - /// Obtains the blast resistance value (also known as block "durability"). + /// Sets the age in ticks of the gateway. /// - /// This value is used in explosions to calculate whether a block should be - /// broken or not. - pub fn blast_resistance(&self) -> Result> { - let sig = String::from("()F"); + /// If the age is less than 200 ticks a magenta beam will be emitted, whilst + /// if it is a multiple of 2400 ticks a purple beam will be emitted. + pub fn set_age(&self, age: i64) -> Result<(), Box> { + let sig = String::from("(J)V"); + let val_1 = jni::objects::JValueGen::Long(age); let res = self.jni_ref().call_method( &self.jni_object(), - "getBlastResistance", + "setAge", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns a value that represents how 'slippery' the block is. - /// - /// Blocks with higher slipperiness, like {@link BlockType#ICE} can be slid on - /// further by the player and other entities. + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. /// - /// Most blocks have a default slipperiness of {@code 0.6f}. - pub fn slipperiness(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSlipperiness", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Check if the block type is an air block. - pub fn is_air(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isAir", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets if the BlockType is enabled by the features in a world. - pub fn is_enabled_by_feature( + /// This {@link PersistentDataHolder} is only linked to the snapshot instance + /// stored by the {@link BlockState}. + /// When storing changes on the {@link PersistentDataHolder}, the updated + /// content will only be applied to the actual tile entity after one of the + /// {@link #update()} methods is called. + pub fn persistent_data_container( &self, - world: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/World;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); let res = self.jni_ref().call_method( &self.jni_object(), - "isEnabledByFeature", + "getPersistentDataContainer", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Tries to convert this BlockType into a Material - pub fn as_material(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "asMaterial", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Return the namespaced identifier for this object. - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the translation key, suitable for use in a translation component. - pub fn translation_key(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTranslationKey", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockType<'mc> { - fn into(self) -> crate::Keyed<'mc> { - crate::Keyed::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockType into crate::Keyed") - } -} -impl<'mc> Into> for BlockType<'mc> { - fn into(self) -> crate::Translatable<'mc> { - crate::Translatable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockType into crate::Translatable") +impl<'mc> Into> for EndGateway<'mc> { + fn into(self) -> crate::block::TileState<'mc> { + crate::block::TileState::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EndGateway into crate::block::TileState") } } #[repr(C)] -pub struct BlockTypeTyped<'mc>( +pub struct HangingSign<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockTypeTyped<'mc> { +impl<'mc> JNIRaw<'mc> for HangingSign<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -656,20 +860,18 @@ impl<'mc> JNIRaw<'mc> for BlockTypeTyped<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockTypeTyped<'mc> { +impl<'mc> JNIInstantiatable<'mc> for HangingSign<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate BlockTypeTyped from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate HangingSign from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/BlockType/Typed")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/HangingSign")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockTypeTyped object, got {}", + "Invalid argument passed. Expected a HangingSign object, got {}", name ) .into()) @@ -679,262 +881,227 @@ impl<'mc> JNIInstantiatable<'mc> for BlockTypeTyped<'mc> { } } -impl<'mc> BlockTypeTyped<'mc> { - /// Gets the BlockData class of this BlockType - pub fn block_data_class( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/lang/Class;"); +impl<'mc> HangingSign<'mc> { + #[deprecated] + /// Gets all the lines of text currently on the {@link Side#FRONT} of this sign. + pub fn lines(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLines", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + #[deprecated] + /// Gets the line of text at the specified index.For example, getLine(0) will return the first line of text on the {@link Side#FRONT}. + pub fn get_line(&self, index: i32) -> Result> { + let sig = String::from("(I)Ljava/lang/String;"); + let val_1 = jni::objects::JValueGen::Int(index); let res = self.jni_ref().call_method( &self.jni_object(), - "getBlockDataClass", + "getLine", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(unsafe { jni::objects::JClass::from_raw(res.as_jni().l) }) - } - /// Creates a new {@link BlockData} instance for this block type, with all - /// properties initialized to unspecified defaults. - pub fn create_block_data( - &self, - ) -> Result, Box> { - let sig = String::from("()LB;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "createBlockData", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Yields this block type as a typed version of itself with a specific {@link BlockData} representing it. - pub fn typed( + #[deprecated] + /// Sets the line of text at the specified index.For example, setLine(0, "Line One") will set the first line of text to "Line One". + pub fn set_line( &self, - block_data_type: std::option::Option>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = block_data_type { - sig += "Ljava/lang/Class;"; - let val_1 = jni::objects::JValueGen::Object(a.into()); - args.push(val_1); - } - sig += ")Lorg/bukkit/block/BlockType/Typed;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "typed", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockTypeTyped::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + index: i32, + line: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(ILjava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Int(index); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(line.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLine", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns true if this BlockType has a corresponding {@link ItemType}. - pub fn has_item_type(&self) -> Result> { + #[deprecated] + /// Marks whether this sign can be edited by players. + pub fn is_editable(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasItemType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isEditable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns the corresponding {@link ItemType} for the given BlockType. - /// - /// If there is no corresponding {@link ItemType} an error will be thrown. - pub fn item_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemType;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + #[deprecated] + /// Marks whether this sign can be edited by players. + pub fn set_editable(&self, editable: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(editable.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setEditable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Check if the blockt type is solid (can be built upon) - pub fn is_solid(&self) -> Result> { + /// Gets whether or not this sign has been waxed. If a sign has been waxed, it + /// cannot be edited by a player. + pub fn is_waxed(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isSolid", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isWaxed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Check if the block type can catch fire - pub fn is_flammable(&self) -> Result> { + /// Sets whether or not this sign has been waxed. If a sign has been waxed, it + /// cannot be edited by a player. + pub fn set_waxed(&self, waxed: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(waxed.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setWaxed", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets whether this sign has glowing text. Only affects the {@link Side#FRONT}. + pub fn is_glowing_text(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isFlammable", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isGlowingText", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Check if the block type can burn away - pub fn is_burnable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isBurnable", sig.as_str(), vec![]); + #[deprecated] + /// Sets whether this sign has glowing text. Only affects the {@link Side#FRONT}. + pub fn set_glowing_text(&self, glowing: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(glowing.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setGlowingText", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// {@inheritDoc} + pub fn color(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/DyeColor;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::DyeColor::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Check if the block type is occludes light in the lighting engine. - /// - /// Generally speaking, most full blocks will occlude light. Non-full blocks are - /// not occluding (e.g. anvils, chests, tall grass, stairs, etc.), nor are specific - /// full blocks such as barriers or spawners which block light despite their texture. - /// - /// An occluding block will have the following effects: - ///
    - ///
  • Chests cannot be opened if an occluding block is above it. - ///
  • Mobs cannot spawn inside of occluding blocks. - ///
  • Only occluding blocks can be "powered" ({@link Block#isBlockPowered()}). - ///
- /// This list may be inconclusive. For a full list of the side effects of an occluding - /// block, see the Minecraft Wiki. - pub fn is_occluding(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isOccluding", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn has_gravity(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Checks if this block type can be interacted with. - /// - /// Interactable block types include those with functionality when they are - /// interacted with by a player such as chests, furnaces, etc. - /// - /// Some blocks such as piston heads and stairs are considered interactable - /// though may not perform any additional functionality. - /// - /// Note that the interactability of some block types may be dependant on their - /// state as well. This method will return true if there is at least one - /// state in which additional interact handling is performed for the - /// block type. - pub fn is_interactable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInteractable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Obtains the block's hardness level (also known as "strength"). - /// - /// This number is used to calculate the time required to break each block. - pub fn hardness(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHardness", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Obtains the blast resistance value (also known as block "durability"). - /// - /// This value is used in explosions to calculate whether a block should be - /// broken or not. - pub fn blast_resistance(&self) -> Result> { - let sig = String::from("()F"); + #[deprecated] + /// {@inheritDoc} + pub fn set_color( + &self, + color: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/DyeColor;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(color.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getBlastResistance", + "setColor", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Returns a value that represents how 'slippery' the block is. - /// - /// Blocks with higher slipperiness, like {@link BlockType#ICE} can be slid on - /// further by the player and other entities. - /// - /// Most blocks have a default slipperiness of {@code 0.6f}. - pub fn slipperiness(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSlipperiness", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Check if the block type is an air block. - pub fn is_air(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isAir", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets if the BlockType is enabled by the features in a world. - pub fn is_enabled_by_feature( + /// Return the side of the sign. + pub fn get_side( &self, - world: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/World;)Z"); + side: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/block/sign/Side;)Lorg/bukkit/block/sign/SignSide;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) + jni::objects::JObject::from_raw(side.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "isEnabledByFeature", + "getSide", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Tries to convert this BlockType into a Material - pub fn as_material(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "asMaterial", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Material::from_raw(&self.jni_ref(), unsafe { + crate::block::sign::SignSide::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + }) } - /// Return the namespaced identifier for this object. - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + /// Gets the side of this sign the given player is currently standing on. + pub fn get_target_side( + &self, + player: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/Player;)Lorg/bukkit/block/sign/SignSide;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(player.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTargetSide", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + crate::block::sign::SignSide::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the translation key, suitable for use in a translation component. - pub fn translation_key(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Gets the player that is currently allowed to edit this sign. + /// + /// Edits from other players will be rejected if this value is not null. + pub fn allowed_editor( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getTranslationKey", + "getAllowedEditor", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Player::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -942,19 +1109,19 @@ impl<'mc> BlockTypeTyped<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockTypeTyped<'mc> { - fn into(self) -> crate::block::BlockType<'mc> { - crate::block::BlockType::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockTypeTyped into crate::block::BlockType") +impl<'mc> Into> for HangingSign<'mc> { + fn into(self) -> crate::block::Sign<'mc> { + crate::block::Sign::from_raw(&self.jni_ref(), self.1) + .expect("Error converting HangingSign into crate::block::Sign") } } #[repr(C)] -pub struct TrialSpawner<'mc>( +pub struct Lockable<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for TrialSpawner<'mc> { +impl<'mc> JNIRaw<'mc> for Lockable<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -962,18 +1129,18 @@ impl<'mc> JNIRaw<'mc> for TrialSpawner<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for TrialSpawner<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Lockable<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate TrialSpawner from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Lockable from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/TrialSpawner")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Lockable")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a TrialSpawner object, got {}", + "Invalid argument passed. Expected a Lockable object, got {}", name ) .into()) @@ -983,31 +1150,44 @@ impl<'mc> JNIInstantiatable<'mc> for TrialSpawner<'mc> { } } -impl<'mc> TrialSpawner<'mc> { - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - /// - /// This {@link PersistentDataHolder} is only linked to the snapshot instance - /// stored by the {@link BlockState}. - /// When storing changes on the {@link PersistentDataHolder}, the updated - /// content will only be applied to the actual tile entity after one of the - /// {@link #update()} methods is called. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); +impl<'mc> Lockable<'mc> { + /// Checks if the container has a valid (non empty) key. + pub fn is_locked(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isLocked", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the key needed to access the container. + pub fn lock(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLock", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the key required to access this container. Set to null (or empty + /// string) to remove key. + pub fn set_lock(&self, key: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(key.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "setLock", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1015,19 +1195,13 @@ impl<'mc> TrialSpawner<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for TrialSpawner<'mc> { - fn into(self) -> crate::block::TileState<'mc> { - crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting TrialSpawner into crate::block::TileState") - } -} #[repr(C)] -pub struct EndGateway<'mc>( +pub struct Block<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EndGateway<'mc> { +impl<'mc> JNIRaw<'mc> for Block<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1035,18 +1209,18 @@ impl<'mc> JNIRaw<'mc> for EndGateway<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EndGateway<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Block<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate EndGateway from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Block from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/EndGateway")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Block")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EndGateway object, got {}", + "Invalid argument passed. Expected a Block object, got {}", name ) .into()) @@ -1056,478 +1230,807 @@ impl<'mc> JNIInstantiatable<'mc> for EndGateway<'mc> { } } -impl<'mc> EndGateway<'mc> { - /// Gets the location that entities are teleported to when - /// entering the gateway portal. - /// - /// If this block state is not placed the location's world will be null. - pub fn exit_location( +impl<'mc> Block<'mc> { + #[deprecated] + /// Gets the metadata for this block + pub fn data(&self) -> Result> { + let sig = String::from("()B"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.b()?) + } + /// Gets the complete block data for this block + pub fn block_data( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getExitLocation", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBlockData", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + }) } - /// Sets the exit location that entities are teleported to when - /// they enter the gateway portal. - /// - /// If this block state is not placed the location's world has to be null. - pub fn set_exit_location( + /// Gets the block at the given offsets + pub fn get_relative( &self, - location: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Location;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setExitLocation", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + mod_x: i32, + mod_y: std::option::Option, + mod_z: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(mod_x); + args.push(val_1); + if let Some(a) = mod_y { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + if let Some(a) = mod_z { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + sig += ")Lorg/bukkit/block/Block;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRelative", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets whether this gateway will teleport entities directly to - /// the exit location instead of finding a nearby location. - pub fn is_exact_teleport(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the type of this block + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the light level between 0-15 + pub fn light_level(&self) -> Result> { + let sig = String::from("()B"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isExactTeleport", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLightLevel", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.b()?) } - /// Sets whether this gateway will teleport entities directly to - /// the exit location instead of finding a nearby location. - pub fn set_exact_teleport(&self, exact: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(exact.into()); + /// Get the amount of light at this block from the sky. + /// + /// Any light given from other sources (such as blocks like torches) will + /// be ignored. + pub fn light_from_sky(&self) -> Result> { + let sig = String::from("()B"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLightFromSky", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.b()?) + } + /// Get the amount of light at this block from nearby blocks. + /// + /// Any light given from other sources (such as the sun) will be ignored. + pub fn light_from_blocks(&self) -> Result> { + let sig = String::from("()B"); let res = self.jni_ref().call_method( &self.jni_object(), - "setExactTeleport", + "getLightFromBlocks", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.b()?) } - /// Gets the age in ticks of the gateway. - /// - /// If the age is less than 200 ticks a magenta beam will be emitted, whilst - /// if it is a multiple of 2400 ticks a purple beam will be emitted. - pub fn age(&self) -> Result> { - let sig = String::from("()J"); + /// Gets the world which contains this Block + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getAge", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the age in ticks of the gateway. - /// - /// If the age is less than 200 ticks a magenta beam will be emitted, whilst - /// if it is a multiple of 2400 ticks a purple beam will be emitted. - pub fn set_age(&self, age: i64) -> Result<(), Box> { - let sig = String::from("(J)V"); - let val_1 = jni::objects::JValueGen::Long(age); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAge", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Gets the x-coordinate of this block + pub fn x(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. + /// Gets the y-coordinate of this block + pub fn y(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the z-coordinate of this block + pub fn z(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Stores the location of the block in the provided Location object. /// - /// This {@link PersistentDataHolder} is only linked to the snapshot instance - /// stored by the {@link BlockState}. - /// When storing changes on the {@link PersistentDataHolder}, the updated - /// content will only be applied to the actual tile entity after one of the - /// {@link #update()} methods is called. - pub fn persistent_data_container( + /// If the provided Location is null this method does nothing and returns + /// null. + pub fn get_location( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "getLocation", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + })?)) } -} -impl<'mc> Into> for EndGateway<'mc> { - fn into(self) -> crate::block::TileState<'mc> { - crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EndGateway into crate::block::TileState") + /// Gets the chunk which contains this block + pub fn chunk(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Chunk;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getChunk", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Chunk::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -#[repr(C)] -pub struct HangingSign<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for HangingSign<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for HangingSign<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate HangingSign from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/HangingSign")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a HangingSign object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + /// Sets the complete data for this block + /// + /// Note that applyPhysics = false is not in general safe. It should only be + /// used when you need to avoid triggering a physics update of neighboring + /// blocks, for example when creating a {@link Bisected} block. If you are + /// using a custom populator, then this parameter may also be required to + /// prevent triggering infinite chunk loads on border blocks. This method + /// should NOT be used to "hack" physics by placing blocks in impossible + /// locations. Such blocks are liable to be removed on various events such as + /// world upgrades. Furthermore setting large amounts of such blocks in close + /// proximity may overload the server physics engine if an update is + /// triggered at a later point. If this occurs, the resulting behavior is + /// undefined. + pub fn set_block_data( + &self, + data: impl Into>, + apply_physics: std::option::Option, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/block/data/BlockData;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(data.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = apply_physics { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); } + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setBlockData", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> HangingSign<'mc> { - #[deprecated] - /// Gets all the lines of text currently on the {@link Side#FRONT} of this sign. - pub fn lines(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Sets the type of this block + /// + /// Note that applyPhysics = false is not in general safe. It should only be + /// used when you need to avoid triggering a physics update of neighboring + /// blocks, for example when creating a {@link Bisected} block. If you are + /// using a custom populator, then this parameter may also be required to + /// prevent triggering infinite chunk loads on border blocks. This method + /// should NOT be used to "hack" physics by placing blocks in impossible + /// locations. Such blocks are liable to be removed on various events such as + /// world upgrades. Furthermore setting large amounts of such blocks in close + /// proximity may overload the server physics engine if an update is + /// triggered at a later point. If this occurs, the resulting behavior is + /// undefined. + pub fn set_type( + &self, + val_type: impl Into>, + apply_physics: std::option::Option, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = apply_physics { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getLines", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + .call_method(&self.jni_object(), "setType", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - #[deprecated] - /// Gets the line of text at the specified index.For example, getLine(0) will return the first line of text on the {@link Side#FRONT}. - pub fn get_line(&self, index: i32) -> Result> { - let sig = String::from("(I)Ljava/lang/String;"); - let val_1 = jni::objects::JValueGen::Int(index); + /// Gets the face relation of this block compared to the given block. + /// + /// For example: + ///
{@code
+    /// Block current = world.getBlockAt(100, 100, 100);
+    /// Block target = world.getBlockAt(100, 101, 100);
+    /// current.getFace(target) == BlockFace.Up;
+    /// }
+ /// + /// If the given block is not connected to this block, null may be returned + pub fn get_face( + &self, + block: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/block/Block;)Lorg/bukkit/block/BlockFace;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(block.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getLine", + "getFace", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(self + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::block::BlockFace::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Captures the current state of this block. You may then cast that state + /// into any accepted type, such as Furnace or Sign. + /// + /// The returned object will never be updated, and you are not guaranteed + /// that (for example) a sign is still a sign after you capture its state. + pub fn state(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockState;"); + let res = self .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + .call_method(&self.jni_object(), "getState", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - /// Sets the line of text at the specified index.For example, setLine(0, "Line One") will set the first line of text to "Line One". - pub fn set_line( + /// Returns the biome that this block resides in + pub fn biome(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/Biome;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBiome", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::Biome::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the biome that this block resides in + pub fn set_biome( &self, - index: i32, - line: impl Into, + bio: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(ILjava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Int(index); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(line.into())?, - )); + let sig = String::from("(Lorg/bukkit/block/Biome;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(bio.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLine", + "setBiome", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Marks whether this sign can be edited by players. - pub fn is_editable(&self) -> Result> { + /// Returns true if the block is being powered by Redstone. + pub fn is_block_powered(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isEditable", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isBlockPowered", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Marks whether this sign can be edited by players. - pub fn set_editable(&self, editable: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(editable.into()); + /// Returns true if the block is being indirectly powered by Redstone. + pub fn is_block_indirectly_powered(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "setEditable", + "isBlockIndirectlyPowered", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether or not this sign has been waxed. If a sign has been waxed, it - /// cannot be edited by a player. - pub fn is_waxed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isWaxed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not this sign has been waxed. If a sign has been waxed, it - /// cannot be edited by a player. - pub fn set_waxed(&self, waxed: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(waxed.into()); + /// Returns true if the block face is being powered by Redstone. + pub fn is_block_face_powered( + &self, + face: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setWaxed", + "isBlockFacePowered", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Gets whether this sign has glowing text. Only affects the {@link Side#FRONT}. - pub fn is_glowing_text(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isGlowingText", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Sets whether this sign has glowing text. Only affects the {@link Side#FRONT}. - pub fn set_glowing_text(&self, glowing: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(glowing.into()); + /// Returns true if the block face is being indirectly powered by Redstone. + pub fn is_block_face_indirectly_powered( + &self, + face: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setGlowingText", + "isBlockFaceIndirectlyPowered", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - #[deprecated] - /// {@inheritDoc} - pub fn color(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/DyeColor;"); + /// Returns the redstone power being provided to this block + pub fn block_power(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBlockPower", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Checks if this block is empty. + /// + /// A block is considered empty when {@link #getType()} returns {@link + /// Material#AIR}. + pub fn is_empty(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::DyeColor::from_raw(&self.jni_ref(), unsafe { + Ok(res.z()?) + } + /// Checks if this block is liquid. + /// + /// A block is considered liquid when {@link #getType()} returns {@link + /// Material#WATER} or {@link Material#LAVA}. + pub fn is_liquid(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isLiquid", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the temperature of this block. + /// + /// If the raw biome temperature without adjusting for height effects is + /// required then please use {@link World#getTemperature(int, int)}. + pub fn temperature(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTemperature", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the humidity of the biome of this block + pub fn humidity(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHumidity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Returns the reaction of the block when moved by a piston + pub fn piston_move_reaction( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPistonMoveReaction", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - #[deprecated] - /// {@inheritDoc} - pub fn set_color( + /// Breaks the block and spawns items as if a player had digged it with a + /// specific tool + pub fn break_naturally( &self, - color: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/DyeColor;)V"); + tool: std::option::Option>>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = tool { + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "breakNaturally", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Simulate bone meal application to this block (if possible). + pub fn apply_bone_meal( + &self, + face: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) + jni::objects::JObject::from_raw(face.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setColor", + "applyBoneMeal", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Return the side of the sign. - pub fn get_side( + /// Returns a list of items which would drop by the entity destroying this + /// block with a specific tool + pub fn get_drops( &self, - side: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/block/sign/Side;)Lorg/bukkit/block/sign/SignSide;"); + tool: impl Into>, + entity: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(side.into().jni_object().clone()) + jni::objects::JObject::from_raw(tool.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = entity { + sig += "Lorg/bukkit/entity/Entity;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Ljava/util/Collection;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getDrops", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::inventory::ItemStack::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Returns if the given item is a preferred choice to break this Block. + /// In some cases this determines if a block will drop anything or extra + /// loot. + pub fn is_preferred_tool( + &self, + tool: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(tool.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getSide", + "isPreferredTool", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::block::sign::SignSide::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Gets the side of this sign the given player is currently standing on. - pub fn get_target_side( + /// Gets the speed at which the given player would break this block, taking + /// into account tools, potion effects, whether or not the player is in + /// water, enchantments, etc. + /// The returned value is the amount of progress made in breaking the block + /// each tick. When the total breaking progress reaches {@code 1.0f}, the + /// block is broken. Note that the break speed can change in the course of + /// breaking a block, e.g. if a potion effect is applied or expires, or the + /// player jumps/enters water. + pub fn get_break_speed( &self, player: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Player;)Lorg/bukkit/block/sign/SignSide;"); + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Player;)F"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getTargetSide", + "getBreakSpeed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::block::sign::SignSide::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.f()?) } - /// Gets the player that is currently allowed to edit this sign. + /// Checks if this block is passable. /// - /// Edits from other players will be rejected if this value is not null. - pub fn allowed_editor( + /// A block is passable if it has no colliding parts that would prevent + /// players from moving through it. + /// + /// Examples: Tall grass, flowers, signs, etc. are passable, but open doors, + /// fence gates, trap doors, etc. are not because they still have parts that + /// can be collided with. + pub fn is_passable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isPassable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Performs a ray trace that checks for collision with this specific block + /// in its current state using its precise collision shape. + pub fn ray_trace( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Player;"); + start: impl Into>, + direction: impl Into>, + max_distance: f64, + fluid_collision_mode: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;Lorg/bukkit/util/Vector;DLorg/bukkit/FluidCollisionMode;)Lorg/bukkit/util/RayTraceResult;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(start.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(direction.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Double(max_distance); + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(fluid_collision_mode.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getAllowedEditor", + "rayTrace", sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + ], ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Player::from_raw( + Ok(Some(crate::util::RayTraceResult::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for HangingSign<'mc> { - fn into(self) -> crate::block::Sign<'mc> { - crate::block::Sign::from_raw(&self.jni_ref(), self.1) - .expect("Error converting HangingSign into crate::block::Sign") + /// Gets the approximate bounding box for this block. + /// + /// This isn't exact as some blocks {@link org.bukkit.block.data.type.Stairs} + /// contain many bounding boxes to establish their complete form. + /// Also, the box may not be exactly the same as the collision shape (such as + /// cactus, which is 16/16 of a block with 15/16 collisional bounds). + /// This method will return an empty bounding box if the geometric shape of + /// the block is empty (such as air blocks). + pub fn bounding_box( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -#[repr(C)] -pub struct Lockable<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Lockable<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Gets the collision shape of this block. + pub fn collision_shape( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/VoxelShape;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCollisionShape", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::util::VoxelShape::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Checks if this block is a valid placement location for the specified + /// block data. + pub fn can_place( + &self, + data: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/block/data/BlockData;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(data.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "canPlace", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for Lockable<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Lockable from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Lockable")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Lockable object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Sets a metadata value in the implementing object's metadata store. + pub fn set_metadata( + &self, + metadata_key: impl Into, + new_metadata_value: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += "Lorg/bukkit/metadata/MetadataValue;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) + }); + args.push(val_2); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setMetadata", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> Lockable<'mc> { - /// Checks if the container has a valid (non empty) key. - pub fn is_locked(&self) -> Result> { - let sig = String::from("()Z"); + /// Returns a list of previously set metadata values from the implementing + /// object's metadata store. + pub fn get_metadata( + &self, + metadata_key: impl Into, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += ")Ljava/util/List;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isLocked", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMetadata", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::metadata::MetadataValue::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(new_vec) } - /// Gets the key needed to access the container. - pub fn lock(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Tests to see whether the implementing object contains the given + /// metadata value in its metadata store. + pub fn has_metadata( + &self, + metadata_key: impl Into, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getLock", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasMetadata", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - /// Sets the key required to access this container. Set to null (or empty - /// string) to remove key. - pub fn set_lock(&self, key: impl Into) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); + /// Removes the given metadata value from the implementing object's + /// metadata store. + pub fn remove_metadata( + &self, + metadata_key: impl Into, + owning_plugin: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(key.into())?, + self.jni_ref().new_string(metadata_key.into())?, )); + args.push(val_1); + sig += "Lorg/bukkit/plugin/Plugin;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + }); + args.push(val_2); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "removeMetadata", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the translation key, suitable for use in a translation component. + pub fn translation_key(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setLock", + "getTranslationKey", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1535,13 +2038,25 @@ impl<'mc> Lockable<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for Block<'mc> { + fn into(self) -> crate::metadata::Metadatable<'mc> { + crate::metadata::Metadatable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Block into crate::metadata::Metadatable") + } +} +impl<'mc> Into> for Block<'mc> { + fn into(self) -> crate::Translatable<'mc> { + crate::Translatable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Block into crate::Translatable") + } +} #[repr(C)] -pub struct Block<'mc>( +pub struct ShulkerBox<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Block<'mc> { +impl<'mc> JNIRaw<'mc> for ShulkerBox<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1549,18 +2064,18 @@ impl<'mc> JNIRaw<'mc> for Block<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Block<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ShulkerBox<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Block from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate ShulkerBox from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Block")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/ShulkerBox")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Block object, got {}", + "Invalid argument passed. Expected a ShulkerBox object, got {}", name ) .into()) @@ -1570,807 +2085,625 @@ impl<'mc> JNIInstantiatable<'mc> for Block<'mc> { } } -impl<'mc> Block<'mc> { - #[deprecated] - /// Gets the metadata for this block - pub fn data(&self) -> Result> { - let sig = String::from("()B"); +impl<'mc> ShulkerBox<'mc> { + /// Get the {@link DyeColor} corresponding to this ShulkerBox + pub fn color(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/DyeColor;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) - } - /// Gets the complete block data for this block - pub fn block_data( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBlockData", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the block at the given offsets - pub fn get_relative( - &self, - mod_x: i32, - mod_y: std::option::Option, - mod_z: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(mod_x); - args.push(val_1); - if let Some(a) = mod_y { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - if let Some(a) = mod_z { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - sig += ")Lorg/bukkit/block/Block;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getRelative", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the type of this block - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { + Ok(Some(crate::DyeColor::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the light level between 0-15 - pub fn light_level(&self) -> Result> { - let sig = String::from("()B"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLightLevel", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) + })?)) } - /// Get the amount of light at this block from the sky. + /// Gets the inventory of the block represented by this block state. /// - /// Any light given from other sources (such as blocks like torches) will - /// be ignored. - pub fn light_from_sky(&self) -> Result> { - let sig = String::from("()B"); + /// If the block was changed to a different type in the meantime, the + /// returned inventory might no longer be valid. + /// + /// If this block state is not placed this will return the captured inventory + /// snapshot instead. + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLightFromSky", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get the amount of light at this block from nearby blocks. + /// Gets the captured inventory snapshot of this container. /// - /// Any light given from other sources (such as the sun) will be ignored. - pub fn light_from_blocks(&self) -> Result> { - let sig = String::from("()B"); + /// The returned inventory is not linked to any block. Any modifications to + /// the returned inventory will not be applied to the block represented by + /// this block state up until {@link #update(boolean, boolean)} has been + /// called. + pub fn snapshot_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLightFromBlocks", + "getSnapshotInventory", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) - } - /// Gets the world which contains this Block - pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the x-coordinate of this block - pub fn x(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the y-coordinate of this block - pub fn y(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the z-coordinate of this block - pub fn z(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Stores the location of the block in the provided Location object. + /// Set the loot table for a container or entity. /// - /// If the provided Location is null this method does nothing and returns - /// null. - pub fn get_location( + /// To remove a loot table use null. Do not use {@link LootTables#EMPTY} to + /// clear a LootTable. + pub fn set_loot_table( &self, - loc: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + table: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/loot/LootTable;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + jni::objects::JObject::from_raw(table.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocation", + "setLootTable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the Loot Table attached to this block or entity. + /// + /// If an block/entity does not have a loot table, this will return null, NOT + /// an empty loot table. + pub fn loot_table( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/loot/LootTable;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLootTable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(Some(crate::loot::LootTable::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets the chunk which contains this block - pub fn chunk(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Chunk;"); + /// Set the seed used when this Loot Table generates loot. + pub fn set_seed(&self, seed: i64) -> Result<(), Box> { + let sig = String::from("(J)V"); + let val_1 = jni::objects::JValueGen::Long(seed); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSeed", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the Loot Table's seed. + /// + /// The seed is used when generating loot. + pub fn seed(&self) -> Result> { + let sig = String::from("()J"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getChunk", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSeed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Chunk::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.j()?) } - /// Sets the complete data for this block - /// - /// Note that applyPhysics = false is not in general safe. It should only be - /// used when you need to avoid triggering a physics update of neighboring - /// blocks, for example when creating a {@link Bisected} block. If you are - /// using a custom populator, then this parameter may also be required to - /// prevent triggering infinite chunk loads on border blocks. This method - /// should NOT be used to "hack" physics by placing blocks in impossible - /// locations. Such blocks are liable to be removed on various events such as - /// world upgrades. Furthermore setting large amounts of such blocks in close - /// proximity may overload the server physics engine if an update is - /// triggered at a later point. If this occurs, the resulting behavior is - /// undefined. - pub fn set_block_data( - &self, - data: impl Into>, - apply_physics: std::option::Option, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/block/data/BlockData;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = apply_physics { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setBlockData", sig.as_str(), args); + /// Sets the block's animated state to open and prevents it from being closed + /// until {@link #close()} is called. + pub fn open(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "open", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets the type of this block - /// - /// Note that applyPhysics = false is not in general safe. It should only be - /// used when you need to avoid triggering a physics update of neighboring - /// blocks, for example when creating a {@link Bisected} block. If you are - /// using a custom populator, then this parameter may also be required to - /// prevent triggering infinite chunk loads on border blocks. This method - /// should NOT be used to "hack" physics by placing blocks in impossible - /// locations. Such blocks are liable to be removed on various events such as - /// world upgrades. Furthermore setting large amounts of such blocks in close - /// proximity may overload the server physics engine if an update is - /// triggered at a later point. If this occurs, the resulting behavior is - /// undefined. - pub fn set_type( - &self, - val_type: impl Into>, - apply_physics: std::option::Option, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = apply_physics { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")V"; + /// Sets the block's animated state to closed even if a player is currently + /// viewing this block. + pub fn close(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self .jni_ref() - .call_method(&self.jni_object(), "setType", sig.as_str(), args); + .call_method(&self.jni_object(), "close", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the face relation of this block compared to the given block. + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for ShulkerBox<'mc> { + fn into(self) -> crate::block::Container<'mc> { + crate::block::Container::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ShulkerBox into crate::block::Container") + } +} +impl<'mc> Into> for ShulkerBox<'mc> { + fn into(self) -> crate::loot::Lootable<'mc> { + crate::loot::Lootable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ShulkerBox into crate::loot::Lootable") + } +} +impl<'mc> Into> for ShulkerBox<'mc> { + fn into(self) -> crate::block::Lidded<'mc> { + crate::block::Lidded::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ShulkerBox into crate::block::Lidded") + } +} +#[repr(C)] +pub struct Chest<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Chest<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Chest<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Chest from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Chest")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Chest object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Chest<'mc> { + /// Gets the inventory of the chest block represented by this block state. /// - /// For example: - ///
{@code
-    /// Block current = world.getBlockAt(100, 100, 100);
-    /// Block target = world.getBlockAt(100, 101, 100);
-    /// current.getFace(target) == BlockFace.Up;
-    /// }
+ /// If the chest is a double chest, it returns just the portion of the + /// inventory linked to the half of the chest corresponding to this block state. /// - /// If the given block is not connected to this block, null may be returned - pub fn get_face( + /// If the block was changed to a different type in the meantime, the + /// returned inventory might no longer be valid. + /// + /// If this block state is not placed this will return the captured + /// inventory snapshot instead. + pub fn block_inventory( &self, - block: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/block/Block;)Lorg/bukkit/block/BlockFace;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) - }); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getFace", + "getBlockInventory", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::block::BlockFace::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Captures the current state of this block. You may then cast that state - /// into any accepted type, such as Furnace or Sign. + /// Gets the inventory of the block represented by this block state. /// - /// The returned object will never be updated, and you are not guaranteed - /// that (for example) a sign is still a sign after you capture its state. - pub fn state(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockState;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getState", sig.as_str(), vec![]); + /// If the block was changed to a different type in the meantime, the + /// returned inventory might no longer be valid. + /// + /// If this block state is not placed this will return the captured inventory + /// snapshot instead. + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns the biome that this block resides in - pub fn biome(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/Biome;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBiome", sig.as_str(), vec![]); + /// Gets the captured inventory snapshot of this container. + /// + /// The returned inventory is not linked to any block. Any modifications to + /// the returned inventory will not be applied to the block represented by + /// this block state up until {@link #update(boolean, boolean)} has been + /// called. + pub fn snapshot_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSnapshotInventory", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::block::Biome::from_raw(&self.jni_ref(), unsafe { + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the biome that this block resides in - pub fn set_biome( + /// Set the loot table for a container or entity. + /// + /// To remove a loot table use null. Do not use {@link LootTables#EMPTY} to + /// clear a LootTable. + pub fn set_loot_table( &self, - bio: impl Into>, + table: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/Biome;)V"); + let sig = String::from("(Lorg/bukkit/loot/LootTable;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(bio.into().jni_object().clone()) + jni::objects::JObject::from_raw(table.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBiome", + "setLootTable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns true if the block is being powered by Redstone. - pub fn is_block_powered(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the Loot Table attached to this block or entity. + /// + /// If an block/entity does not have a loot table, this will return null, NOT + /// an empty loot table. + pub fn loot_table( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/loot/LootTable;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isBlockPowered", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns true if the block is being indirectly powered by Redstone. - pub fn is_block_indirectly_powered(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isBlockIndirectlyPowered", - sig.as_str(), - vec![], - ); + .call_method(&self.jni_object(), "getLootTable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::loot::LootTable::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Returns true if the block face is being powered by Redstone. - pub fn is_block_face_powered( - &self, - face: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); + /// Set the seed used when this Loot Table generates loot. + pub fn set_seed(&self, seed: i64) -> Result<(), Box> { + let sig = String::from("(J)V"); + let val_1 = jni::objects::JValueGen::Long(seed); let res = self.jni_ref().call_method( &self.jni_object(), - "isBlockFacePowered", + "setSeed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the Loot Table's seed. + /// + /// The seed is used when generating loot. + pub fn seed(&self) -> Result> { + let sig = String::from("()J"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSeed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.j()?) } - /// Returns true if the block face is being indirectly powered by Redstone. - pub fn is_block_face_indirectly_powered( - &self, - face: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isBlockFaceIndirectlyPowered", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the redstone power being provided to this block - pub fn block_power(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBlockPower", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Checks if this block is empty. - /// - /// A block is considered empty when {@link #getType()} returns {@link - /// Material#AIR}. - pub fn is_empty(&self) -> Result> { - let sig = String::from("()Z"); + /// Sets the block's animated state to open and prevents it from being closed + /// until {@link #close()} is called. + pub fn open(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + .call_method(&self.jni_object(), "open", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Checks if this block is liquid. - /// - /// A block is considered liquid when {@link #getType()} returns {@link - /// Material#WATER} or {@link Material#LAVA}. - pub fn is_liquid(&self) -> Result> { - let sig = String::from("()Z"); + /// Sets the block's animated state to closed even if a player is currently + /// viewing this block. + pub fn close(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isLiquid", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + .call_method(&self.jni_object(), "close", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the temperature of this block. - /// - /// If the raw biome temperature without adjusting for height effects is - /// required then please use {@link World#getTemperature(int, int)}. - pub fn temperature(&self) -> Result> { - let sig = String::from("()D"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTemperature", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Gets the humidity of the biome of this block - pub fn humidity(&self) -> Result> { - let sig = String::from("()D"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHumidity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) +} +impl<'mc> Into> for Chest<'mc> { + fn into(self) -> crate::block::Container<'mc> { + crate::block::Container::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Chest into crate::block::Container") } - /// Returns the reaction of the block when moved by a piston - pub fn piston_move_reaction( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); +} +impl<'mc> Into> for Chest<'mc> { + fn into(self) -> crate::loot::Lootable<'mc> { + crate::loot::Lootable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Chest into crate::loot::Lootable") + } +} +impl<'mc> Into> for Chest<'mc> { + fn into(self) -> crate::block::Lidded<'mc> { + crate::block::Lidded::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Chest into crate::block::Lidded") + } +} +#[repr(C)] +pub struct SculkSensor<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for SculkSensor<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for SculkSensor<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate SculkSensor from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/SculkSensor")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a SculkSensor object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> SculkSensor<'mc> { + /// Gets the last vibration frequency of this sensor. + /// Different activities detected by the sensor will produce different + /// frequencies and dictate the output of connected comparators. + pub fn last_vibration_frequency(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPistonMoveReaction", + "getLastVibrationFrequency", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Breaks the block and spawns items as if a player had digged it with a - /// specific tool - pub fn break_naturally( - &self, - tool: std::option::Option>>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = tool { - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "breakNaturally", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Simulate bone meal application to this block (if possible). - pub fn apply_bone_meal( + /// Sets the last vibration frequency of this sensor. + /// Different activities detected by the sensor will produce different + /// frequencies and dictate the output of connected comparators. + pub fn set_last_vibration_frequency( &self, - face: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); + last_vibration_frequency: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(last_vibration_frequency); let res = self.jni_ref().call_method( &self.jni_object(), - "applyBoneMeal", + "setLastVibrationFrequency", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns a list of items which would drop by the entity destroying this - /// block with a specific tool - pub fn get_drops( - &self, - tool: impl Into>, - entity: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tool.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = entity { - sig += "Lorg/bukkit/entity/Entity;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Ljava/util/Collection;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getDrops", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::inventory::ItemStack::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns if the given item is a preferred choice to break this Block. - /// In some cases this determines if a block will drop anything or extra - /// loot. - pub fn is_preferred_tool( + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + /// + /// This {@link PersistentDataHolder} is only linked to the snapshot instance + /// stored by the {@link BlockState}. + /// When storing changes on the {@link PersistentDataHolder}, the updated + /// content will only be applied to the actual tile entity after one of the + /// {@link #update()} methods is called. + pub fn persistent_data_container( &self, - tool: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tool.into().jni_object().clone()) - }); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); let res = self.jni_ref().call_method( &self.jni_object(), - "isPreferredTool", + "getPersistentDataContainer", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the speed at which the given player would break this block, taking - /// into account tools, potion effects, whether or not the player is in - /// water, enchantments, etc. - /// The returned value is the amount of progress made in breaking the block - /// each tick. When the total breaking progress reaches {@code 1.0f}, the - /// block is broken. Note that the break speed can change in the course of - /// breaking a block, e.g. if a potion effect is applied or expires, or the - /// player jumps/enters water. - pub fn get_break_speed( - &self, - player: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Player;)F"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getBreakSpeed", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Checks if this block is passable. - /// - /// A block is passable if it has no colliding parts that would prevent - /// players from moving through it. - /// - /// Examples: Tall grass, flowers, signs, etc. are passable, but open doors, - /// fence gates, trap doors, etc. are not because they still have parts that - /// can be collided with. - pub fn is_passable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isPassable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Performs a ray trace that checks for collision with this specific block - /// in its current state using its precise collision shape. - pub fn ray_trace( - &self, - start: impl Into>, - direction: impl Into>, - max_distance: f64, - fluid_collision_mode: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;Lorg/bukkit/util/Vector;DLorg/bukkit/FluidCollisionMode;)Lorg/bukkit/util/RayTraceResult;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(start.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(direction.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Double(max_distance); - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(fluid_collision_mode.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "rayTrace", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - ], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); +} +impl<'mc> Into> for SculkSensor<'mc> { + fn into(self) -> crate::block::TileState<'mc> { + crate::block::TileState::from_raw(&self.jni_ref(), self.1) + .expect("Error converting SculkSensor into crate::block::TileState") + } +} +#[repr(C)] +pub struct Hopper<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Hopper<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Hopper<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Hopper from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Hopper")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Hopper object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - Ok(Some(crate::util::RayTraceResult::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) } - /// Gets the approximate bounding box for this block. +} + +impl<'mc> Hopper<'mc> { + /// Gets the inventory of the block represented by this block state. /// - /// This isn't exact as some blocks {@link org.bukkit.block.data.type.Stairs} - /// contain many bounding boxes to establish their complete form. - /// Also, the box may not be exactly the same as the collision shape (such as - /// cactus, which is 16/16 of a block with 15/16 collisional bounds). - /// This method will return an empty bounding box if the geometric shape of - /// the block is empty (such as air blocks). - pub fn bounding_box( + /// If the block was changed to a different type in the meantime, the + /// returned inventory might no longer be valid. + /// + /// If this block state is not placed this will return the captured inventory + /// snapshot instead. + pub fn inventory( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the collision shape of this block. - pub fn collision_shape( + /// Gets the captured inventory snapshot of this container. + /// + /// The returned inventory is not linked to any block. Any modifications to + /// the returned inventory will not be applied to the block represented by + /// this block state up until {@link #update(boolean, boolean)} has been + /// called. + pub fn snapshot_inventory( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/VoxelShape;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCollisionShape", + "getSnapshotInventory", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::util::VoxelShape::from_raw(&self.jni_ref(), unsafe { + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Checks if this block is a valid placement location for the specified - /// block data. - pub fn can_place( + /// Set the loot table for a container or entity. + /// + /// To remove a loot table use null. Do not use {@link LootTables#EMPTY} to + /// clear a LootTable. + pub fn set_loot_table( &self, - data: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/block/data/BlockData;)Z"); + table: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/loot/LootTable;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) + jni::objects::JObject::from_raw(table.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "canPlace", + "setLootTable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets a metadata value in the implementing object's metadata store. - pub fn set_metadata( - &self, - metadata_key: impl Into, - new_metadata_value: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += "Lorg/bukkit/metadata/MetadataValue;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) - }); - args.push(val_2); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setMetadata", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a list of previously set metadata values from the implementing - /// object's metadata store. - pub fn get_metadata( + /// Gets the Loot Table attached to this block or entity. + /// + /// If an block/entity does not have a loot table, this will return null, NOT + /// an empty loot table. + pub fn loot_table( &self, - metadata_key: impl Into, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += ")Ljava/util/List;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getMetadata", sig.as_str(), args); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/loot/LootTable;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLootTable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::metadata::MetadataValue::from_raw( - &self.jni_ref(), - obj, - )?); + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - Ok(new_vec) + Ok(Some(crate::loot::LootTable::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Tests to see whether the implementing object contains the given - /// metadata value in its metadata store. - pub fn has_metadata( - &self, - metadata_key: impl Into, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasMetadata", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Removes the given metadata value from the implementing object's - /// metadata store. - pub fn remove_metadata( - &self, - metadata_key: impl Into, - owning_plugin: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += "Lorg/bukkit/plugin/Plugin;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) - }); - args.push(val_2); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "removeMetadata", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the translation key, suitable for use in a translation component. - pub fn translation_key(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Set the seed used when this Loot Table generates loot. + pub fn set_seed(&self, seed: i64) -> Result<(), Box> { + let sig = String::from("(J)V"); + let val_1 = jni::objects::JValueGen::Long(seed); let res = self.jni_ref().call_method( &self.jni_object(), - "getTranslationKey", + "setSeed", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(self + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the Loot Table's seed. + /// + /// The seed is used when generating loot. + pub fn seed(&self) -> Result> { + let sig = String::from("()J"); + let res = self .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + .call_method(&self.jni_object(), "getSeed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.j()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -2378,25 +2711,25 @@ impl<'mc> Block<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Block<'mc> { - fn into(self) -> crate::metadata::Metadatable<'mc> { - crate::metadata::Metadatable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Block into crate::metadata::Metadatable") +impl<'mc> Into> for Hopper<'mc> { + fn into(self) -> crate::block::Container<'mc> { + crate::block::Container::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Hopper into crate::block::Container") } } -impl<'mc> Into> for Block<'mc> { - fn into(self) -> crate::Translatable<'mc> { - crate::Translatable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Block into crate::Translatable") +impl<'mc> Into> for Hopper<'mc> { + fn into(self) -> crate::loot::Lootable<'mc> { + crate::loot::Lootable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Hopper into crate::loot::Lootable") } } #[repr(C)] -pub struct ShulkerBox<'mc>( +pub struct BlockState<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ShulkerBox<'mc> { +impl<'mc> JNIRaw<'mc> for BlockState<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2404,18 +2737,18 @@ impl<'mc> JNIRaw<'mc> for ShulkerBox<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ShulkerBox<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockState<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ShulkerBox from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate BlockState from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/ShulkerBox")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/BlockState")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ShulkerBox object, got {}", + "Invalid argument passed. Expected a BlockState object, got {}", name ) .into()) @@ -2425,353 +2758,388 @@ impl<'mc> JNIInstantiatable<'mc> for ShulkerBox<'mc> { } } -impl<'mc> ShulkerBox<'mc> { - /// Get the {@link DyeColor} corresponding to this ShulkerBox - pub fn color(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/DyeColor;"); +impl<'mc> BlockState<'mc> { + /// Gets the block represented by this block state. + pub fn block(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::DyeColor::from_raw(&self.jni_ref(), unsafe { + crate::block::Block::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + }) } - /// Gets the inventory of the block represented by this block state. - /// - /// If the block was changed to a different type in the meantime, the - /// returned inventory might no longer be valid. - /// - /// If this block state is not placed this will return the captured inventory - /// snapshot instead. - pub fn inventory( + /// Gets the metadata for this block state. + pub fn data(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/MaterialData;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the data for this block state. + pub fn block_data( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBlockData", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the captured inventory snapshot of this container. - /// - /// The returned inventory is not linked to any block. Any modifications to - /// the returned inventory will not be applied to the block represented by - /// this block state up until {@link #update(boolean, boolean)} has been - /// called. - pub fn snapshot_inventory( + /// Copies the state to another block as an unplaced BlockState. + pub fn copy( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSnapshotInventory", - sig.as_str(), - vec![], - ); + location: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = location { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Lorg/bukkit/block/BlockState;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Set the loot table for a container or entity. - /// - /// To remove a loot table use null. Do not use {@link LootTables#EMPTY} to - /// clear a LootTable. - pub fn set_loot_table( - &self, - table: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/loot/LootTable;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(table.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLootTable", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Gets the type of this block state. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the Loot Table attached to this block or entity. - /// - /// If an block/entity does not have a loot table, this will return null, NOT - /// an empty loot table. - pub fn loot_table( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/loot/LootTable;"); + /// Gets the current light level of the block represented by this block state. + pub fn light_level(&self) -> Result> { + let sig = String::from("()B"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLootTable", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLightLevel", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::loot::LootTable::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Set the seed used when this Loot Table generates loot. - pub fn set_seed(&self, seed: i64) -> Result<(), Box> { - let sig = String::from("(J)V"); - let val_1 = jni::objects::JValueGen::Long(seed); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSeed", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.b()?) } - /// Get the Loot Table's seed. - /// - /// The seed is used when generating loot. - pub fn seed(&self) -> Result> { - let sig = String::from("()J"); + /// Gets the world which contains the block represented by this block state. + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getSeed", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the block's animated state to open and prevents it from being closed - /// until {@link #close()} is called. - pub fn open(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Gets the x-coordinate of this block state. + pub fn x(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "open", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Sets the block's animated state to closed even if a player is currently - /// viewing this block. - pub fn close(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Gets the y-coordinate of this block state. + pub fn y(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "close", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for ShulkerBox<'mc> { - fn into(self) -> crate::block::Container<'mc> { - crate::block::Container::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ShulkerBox into crate::block::Container") - } -} -impl<'mc> Into> for ShulkerBox<'mc> { - fn into(self) -> crate::loot::Lootable<'mc> { - crate::loot::Lootable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ShulkerBox into crate::loot::Lootable") - } -} -impl<'mc> Into> for ShulkerBox<'mc> { - fn into(self) -> crate::block::Lidded<'mc> { - crate::block::Lidded::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ShulkerBox into crate::block::Lidded") - } -} -#[repr(C)] -pub struct Chest<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Chest<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} -impl<'mc> JNIInstantiatable<'mc> for Chest<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Chest from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Chest")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Chest object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Gets the z-coordinate of this block state. + pub fn z(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} - -impl<'mc> Chest<'mc> { - /// Gets the inventory of the chest block represented by this block state. - /// - /// If the chest is a double chest, it returns just the portion of the - /// inventory linked to the half of the chest corresponding to this block state. + /// Stores the location of this block state in the provided Location object. /// - /// If the block was changed to a different type in the meantime, the - /// returned inventory might no longer be valid. + /// If the provided Location is null this method does nothing and returns + /// null. /// - /// If this block state is not placed this will return the captured - /// inventory snapshot instead. - pub fn block_inventory( + /// If this block state is not placed the location's world will be null! + pub fn get_location( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getBlockInventory", + "getLocation", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) + })?)) } - /// Gets the inventory of the block represented by this block state. - /// - /// If the block was changed to a different type in the meantime, the - /// returned inventory might no longer be valid. - /// - /// If this block state is not placed this will return the captured inventory - /// snapshot instead. - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + /// Gets the chunk which contains the block represented by this block state. + pub fn chunk(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Chunk;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getChunk", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + crate::Chunk::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the captured inventory snapshot of this container. - /// - /// The returned inventory is not linked to any block. Any modifications to - /// the returned inventory will not be applied to the block represented by - /// this block state up until {@link #update(boolean, boolean)} has been - /// called. - pub fn snapshot_inventory( + /// Sets the metadata for this block state. + pub fn set_data( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + data: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/material/MaterialData;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(data.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getSnapshotInventory", + "setData", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Set the loot table for a container or entity. - /// - /// To remove a loot table use null. Do not use {@link LootTables#EMPTY} to - /// clear a LootTable. - pub fn set_loot_table( + /// Sets the data for this block state. + pub fn set_block_data( &self, - table: impl Into>, + data: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/loot/LootTable;)V"); + let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(table.into().jni_object().clone()) + jni::objects::JObject::from_raw(data.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLootTable", + "setBlockData", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the Loot Table attached to this block or entity. - /// - /// If an block/entity does not have a loot table, this will return null, NOT - /// an empty loot table. - pub fn loot_table( + /// Sets the type of this block state. + pub fn set_type( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/loot/LootTable;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLootTable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::loot::LootTable::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Set the seed used when this Loot Table generates loot. - pub fn set_seed(&self, seed: i64) -> Result<(), Box> { - let sig = String::from("(J)V"); - let val_1 = jni::objects::JValueGen::Long(seed); + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Material;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setSeed", + "setType", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the Loot Table's seed. + /// Attempts to update the block represented by this state, setting it to + /// the new values as defined by this state. /// - /// The seed is used when generating loot. - pub fn seed(&self) -> Result> { - let sig = String::from("()J"); + /// If this state is not placed, this will have no effect and return true. + /// + /// Unless force is true, this will not modify the state of a block if it + /// is no longer the same type as it was when this state was taken. It will + /// return false in this eventuality. + /// + /// If force is true, it will set the type of the block to match the new + /// state, set the state data and then return true. + /// + /// If applyPhysics is true, it will trigger a physics update on + /// surrounding blocks which could cause them to update or disappear. + pub fn update( + &self, + force: std::option::Option, + apply_physics: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = force { + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_1); + } + if let Some(a) = apply_physics { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getSeed", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "update", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + Ok(res.z()?) } - /// Sets the block's animated state to open and prevents it from being closed - /// until {@link #close()} is called. - pub fn open(&self) -> Result<(), Box> { - let sig = String::from("()V"); + #[deprecated] + + pub fn raw_data(&self) -> Result> { + let sig = String::from("()B"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRawData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.b()?) + } + #[deprecated] + + pub fn set_raw_data(&self, data: i8) -> Result<(), Box> { + let sig = String::from("(B)V"); + let val_1 = jni::objects::JValueGen::Byte(data); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRawData", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns whether this state is placed in the world. + /// + /// Some methods will not work if the block state isn't + /// placed in the world. + pub fn is_placed(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "open", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isPlaced", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets a metadata value in the implementing object's metadata store. + pub fn set_metadata( + &self, + metadata_key: impl Into, + new_metadata_value: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += "Lorg/bukkit/metadata/MetadataValue;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) + }); + args.push(val_2); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setMetadata", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets the block's animated state to closed even if a player is currently - /// viewing this block. - pub fn close(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Returns a list of previously set metadata values from the implementing + /// object's metadata store. + pub fn get_metadata( + &self, + metadata_key: impl Into, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += ")Ljava/util/List;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "close", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMetadata", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::metadata::MetadataValue::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(new_vec) + } + /// Tests to see whether the implementing object contains the given + /// metadata value in its metadata store. + pub fn has_metadata( + &self, + metadata_key: impl Into, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasMetadata", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Removes the given metadata value from the implementing object's + /// metadata store. + pub fn remove_metadata( + &self, + metadata_key: impl Into, + owning_plugin: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += "Lorg/bukkit/plugin/Plugin;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + }); + args.push(val_2); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "removeMetadata", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } @@ -2781,31 +3149,19 @@ impl<'mc> Chest<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Chest<'mc> { - fn into(self) -> crate::block::Container<'mc> { - crate::block::Container::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Chest into crate::block::Container") - } -} -impl<'mc> Into> for Chest<'mc> { - fn into(self) -> crate::loot::Lootable<'mc> { - crate::loot::Lootable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Chest into crate::loot::Lootable") - } -} -impl<'mc> Into> for Chest<'mc> { - fn into(self) -> crate::block::Lidded<'mc> { - crate::block::Lidded::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Chest into crate::block::Lidded") +impl<'mc> Into> for BlockState<'mc> { + fn into(self) -> crate::metadata::Metadatable<'mc> { + crate::metadata::Metadatable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockState into crate::metadata::Metadatable") } } #[repr(C)] -pub struct SculkSensor<'mc>( +pub struct Smoker<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for SculkSensor<'mc> { +impl<'mc> JNIRaw<'mc> for Smoker<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2813,18 +3169,18 @@ impl<'mc> JNIRaw<'mc> for SculkSensor<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for SculkSensor<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Smoker<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate SculkSensor from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Smoker from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/SculkSensor")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Smoker")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SculkSensor object, got {}", + "Invalid argument passed. Expected a Smoker object, got {}", name ) .into()) @@ -2834,83 +3190,148 @@ impl<'mc> JNIInstantiatable<'mc> for SculkSensor<'mc> { } } -impl<'mc> SculkSensor<'mc> { - /// Gets the last vibration frequency of this sensor. - /// Different activities detected by the sensor will produce different - /// frequencies and dictate the output of connected comparators. - pub fn last_vibration_frequency(&self) -> Result> { - let sig = String::from("()I"); +impl<'mc> Smoker<'mc> { + /// Get burn time. + pub fn burn_time(&self) -> Result> { + let sig = String::from("()S"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBurnTime", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.s()?) + } + /// Set burn time. + /// A burn time greater than 0 will cause this block to be lit, whilst a time + /// less than 0 will extinguish it. + pub fn set_burn_time(&self, burn_time: i16) -> Result<(), Box> { + let sig = String::from("(S)V"); + let val_1 = jni::objects::JValueGen::Short(burn_time); let res = self.jni_ref().call_method( &self.jni_object(), - "getLastVibrationFrequency", + "setBurnTime", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get cook time. + /// This is the amount of time the item has been cooking for. + pub fn cook_time(&self) -> Result> { + let sig = String::from("()S"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCookTime", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.s()?) } - /// Sets the last vibration frequency of this sensor. - /// Different activities detected by the sensor will produce different - /// frequencies and dictate the output of connected comparators. - pub fn set_last_vibration_frequency( - &self, - last_vibration_frequency: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(last_vibration_frequency); + /// Set cook time. + /// This is the amount of time the item has been cooking for. + pub fn set_cook_time(&self, cook_time: i16) -> Result<(), Box> { + let sig = String::from("(S)V"); + let val_1 = jni::objects::JValueGen::Short(cook_time); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastVibrationFrequency", + "setCookTime", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - /// - /// This {@link PersistentDataHolder} is only linked to the snapshot instance - /// stored by the {@link BlockState}. - /// When storing changes on the {@link PersistentDataHolder}, the updated - /// content will only be applied to the actual tile entity after one of the - /// {@link #update()} methods is called. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + /// Get cook time total. + /// This is the amount of time the item is required to cook for. + pub fn cook_time_total(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "getCookTimeTotal", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + Ok(res.i()?) + } + /// Set cook time. + /// This is the amount of time the item is required to cook for. + pub fn set_cook_time_total( + &self, + cook_time_total: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(cook_time_total); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCookTimeTotal", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the recipes used in this furnace. + /// Note: These recipes used are reset when the result item is + /// manually taken from the furnace. + pub fn recipes_used( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Map;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRecipesUsed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/FurnaceInventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::FurnaceInventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn snapshot_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/FurnaceInventory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSnapshotInventory", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::FurnaceInventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for SculkSensor<'mc> { - fn into(self) -> crate::block::TileState<'mc> { - crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SculkSensor into crate::block::TileState") +impl<'mc> Into> for Smoker<'mc> { + fn into(self) -> crate::block::Furnace<'mc> { + crate::block::Furnace::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Smoker into crate::block::Furnace") } } #[repr(C)] -pub struct Hopper<'mc>( +pub struct Barrel<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Hopper<'mc> { +impl<'mc> JNIRaw<'mc> for Barrel<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2918,18 +3339,18 @@ impl<'mc> JNIRaw<'mc> for Hopper<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Hopper<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Barrel<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Hopper from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Barrel from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Hopper")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Barrel")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Hopper object, got {}", + "Invalid argument passed. Expected a Barrel object, got {}", name ) .into()) @@ -2939,7 +3360,7 @@ impl<'mc> JNIInstantiatable<'mc> for Hopper<'mc> { } } -impl<'mc> Hopper<'mc> { +impl<'mc> Barrel<'mc> { /// Gets the inventory of the block represented by this block state. /// /// If the block was changed to a different type in the meantime, the @@ -3045,31 +3466,57 @@ impl<'mc> Hopper<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.j()?) } + /// Sets the block's animated state to open and prevents it from being closed + /// until {@link #close()} is called. + pub fn open(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "open", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets the block's animated state to closed even if a player is currently + /// viewing this block. + pub fn close(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "close", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Hopper<'mc> { +impl<'mc> Into> for Barrel<'mc> { fn into(self) -> crate::block::Container<'mc> { crate::block::Container::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Hopper into crate::block::Container") + .expect("Error converting Barrel into crate::block::Container") } } -impl<'mc> Into> for Hopper<'mc> { +impl<'mc> Into> for Barrel<'mc> { fn into(self) -> crate::loot::Lootable<'mc> { crate::loot::Lootable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Hopper into crate::loot::Lootable") + .expect("Error converting Barrel into crate::loot::Lootable") + } +} +impl<'mc> Into> for Barrel<'mc> { + fn into(self) -> crate::block::Lidded<'mc> { + crate::block::Lidded::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Barrel into crate::block::Lidded") } } #[repr(C)] -pub struct BlockState<'mc>( +pub struct SuspiciousSand<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockState<'mc> { +impl<'mc> JNIRaw<'mc> for SuspiciousSand<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3077,18 +3524,20 @@ impl<'mc> JNIRaw<'mc> for BlockState<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockState<'mc> { +impl<'mc> JNIInstantiatable<'mc> for SuspiciousSand<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate BlockState from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate SuspiciousSand from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/BlockState")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/SuspiciousSand")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockState object, got {}", + "Invalid argument passed. Expected a SuspiciousSand object, got {}", name ) .into()) @@ -3098,390 +3547,266 @@ impl<'mc> JNIInstantiatable<'mc> for BlockState<'mc> { } } -impl<'mc> BlockState<'mc> { - /// Gets the block represented by this block state. - pub fn block(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the metadata for this block state. - pub fn data(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/MaterialData;"); +impl<'mc> SuspiciousSand<'mc> { + /// Get the item which will be revealed when the sand is fully brushed away + /// and uncovered. + pub fn item( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets the data for this block state. - pub fn block_data( + /// Sets the item which will be revealed when the sand is fully brushed away + /// and uncovered. + pub fn set_item( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for SuspiciousSand<'mc> { + fn into(self) -> crate::block::BrushableBlock<'mc> { + crate::block::BrushableBlock::from_raw(&self.jni_ref(), self.1) + .expect("Error converting SuspiciousSand into crate::block::BrushableBlock") + } +} +#[repr(C)] +pub struct Jukebox<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Jukebox<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Jukebox<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Jukebox from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Jukebox")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Jukebox object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Jukebox<'mc> { + /// Gets the record inserted into the jukebox. + pub fn playing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBlockData", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPlaying", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { + crate::Material::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Copies the state to another block as an unplaced BlockState. - pub fn copy( + /// Sets the record being played. + pub fn set_playing( &self, - location: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = location { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")Lorg/bukkit/block/BlockState;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the type of this block state. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the current light level of the block represented by this block state. - pub fn light_level(&self) -> Result> { - let sig = String::from("()B"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLightLevel", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) - } - /// Gets the world which contains the block represented by this block state. - pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the x-coordinate of this block state. - pub fn x(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the y-coordinate of this block state. - pub fn y(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the z-coordinate of this block state. - pub fn z(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Stores the location of this block state in the provided Location object. - /// - /// If the provided Location is null this method does nothing and returns - /// null. - /// - /// If this block state is not placed the location's world will be null! - pub fn get_location( - &self, - loc: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + record: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Material;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + jni::objects::JObject::from_raw(record.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocation", + "setPlaying", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether or not this jukebox has a record. + /// + /// A jukebox can have a record but not {@link #isPlaying() be playing} + /// if it was stopped with {@link #stopPlaying()} or if a record has + /// finished playing. + pub fn has_record(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasRecord", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.z()?) } - /// Gets the chunk which contains the block represented by this block state. - pub fn chunk(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Chunk;"); + /// Gets the record item inserted into the jukebox. + pub fn record(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getChunk", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getRecord", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Chunk::from_raw(&self.jni_ref(), unsafe { + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the metadata for this block state. - pub fn set_data( - &self, - data: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/material/MaterialData;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setData", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Sets the data for this block state. - pub fn set_block_data( - &self, - data: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setBlockData", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Sets the type of this block state. - pub fn set_type( + /// Sets the record being played. The jukebox will start playing automatically. + pub fn set_record( &self, - val_type: impl Into>, + record: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Material;)V"); + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(record.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setType", + "setRecord", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Attempts to update the block represented by this state, setting it to - /// the new values as defined by this state. - /// - /// If this state is not placed, this will have no effect and return true. - /// - /// Unless force is true, this will not modify the state of a block if it - /// is no longer the same type as it was when this state was taken. It will - /// return false in this eventuality. - /// - /// If force is true, it will set the type of the block to match the new - /// state, set the state data and then return true. - /// - /// If applyPhysics is true, it will trigger a physics update on - /// surrounding blocks which could cause them to update or disappear. - pub fn update( - &self, - force: std::option::Option, - apply_physics: std::option::Option, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = force { - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_1); - } - if let Some(a) = apply_physics { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")Z"; + /// Checks if the jukebox is playing a record. + pub fn is_playing(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "update", sig.as_str(), args); + .call_method(&self.jni_object(), "isPlaying", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - - pub fn raw_data(&self) -> Result> { - let sig = String::from("()B"); + /// Starts the jukebox playing if there is a record. + pub fn start_playing(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getRawData", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "startPlaying", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) + Ok(res.z()?) } - #[deprecated] - - pub fn set_raw_data(&self, data: i8) -> Result<(), Box> { - let sig = String::from("(B)V"); - let val_1 = jni::objects::JValueGen::Byte(data); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRawData", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Stops the jukebox playing without ejecting the record. + pub fn stop_playing(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "stopPlaying", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether this state is placed in the world. + /// Stops the jukebox playing and ejects the current record. /// - /// Some methods will not work if the block state isn't - /// placed in the world. - pub fn is_placed(&self) -> Result> { + /// If the block represented by this state is no longer a jukebox, this will + /// do nothing and return false. + pub fn eject(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isPlaced", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets a metadata value in the implementing object's metadata store. - pub fn set_metadata( + + pub fn inventory( &self, - metadata_key: impl Into, - new_metadata_value: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += "Lorg/bukkit/metadata/MetadataValue;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) - }); - args.push(val_2); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setMetadata", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/JukeboxInventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::JukeboxInventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns a list of previously set metadata values from the implementing - /// object's metadata store. - pub fn get_metadata( + + pub fn snapshot_inventory( &self, - metadata_key: impl Into, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += ")Ljava/util/List;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getMetadata", sig.as_str(), args); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/JukeboxInventory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSnapshotInventory", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::metadata::MetadataValue::from_raw( - &self.jni_ref(), - obj, - )?); - } - Ok(new_vec) + crate::inventory::JukeboxInventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Tests to see whether the implementing object contains the given - /// metadata value in its metadata store. - pub fn has_metadata( + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + /// + /// This {@link PersistentDataHolder} is only linked to the snapshot instance + /// stored by the {@link BlockState}. + /// When storing changes on the {@link PersistentDataHolder}, the updated + /// content will only be applied to the actual tile entity after one of the + /// {@link #update()} methods is called. + pub fn persistent_data_container( &self, - metadata_key: impl Into, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += ")Z"; + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPersistentDataContainer", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the block associated with this holder. + pub fn block(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "hasMetadata", sig.as_str(), args); + .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Removes the given metadata value from the implementing object's - /// metadata store. - pub fn remove_metadata( - &self, - metadata_key: impl Into, - owning_plugin: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += "Lorg/bukkit/plugin/Plugin;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) - }); - args.push(val_2); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "removeMetadata", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -3489,19 +3814,25 @@ impl<'mc> BlockState<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockState<'mc> { - fn into(self) -> crate::metadata::Metadatable<'mc> { - crate::metadata::Metadatable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockState into crate::metadata::Metadatable") +impl<'mc> Into> for Jukebox<'mc> { + fn into(self) -> crate::block::TileState<'mc> { + crate::block::TileState::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Jukebox into crate::block::TileState") + } +} +impl<'mc> Into> for Jukebox<'mc> { + fn into(self) -> crate::inventory::BlockInventoryHolder<'mc> { + crate::inventory::BlockInventoryHolder::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Jukebox into crate::inventory::BlockInventoryHolder") } } #[repr(C)] -pub struct Smoker<'mc>( +pub struct Skull<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Smoker<'mc> { +impl<'mc> JNIRaw<'mc> for Skull<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3509,18 +3840,18 @@ impl<'mc> JNIRaw<'mc> for Smoker<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Smoker<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Skull<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Smoker from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Skull from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Smoker")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Skull")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Smoker object, got {}", + "Invalid argument passed. Expected a Skull object, got {}", name ) .into()) @@ -3530,126 +3861,256 @@ impl<'mc> JNIInstantiatable<'mc> for Smoker<'mc> { } } -impl<'mc> Smoker<'mc> { - /// Get burn time. - pub fn burn_time(&self) -> Result> { - let sig = String::from("()S"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBurnTime", sig.as_str(), vec![]); +impl<'mc> Skull<'mc> { + /// Checks to see if the skull has an owner + pub fn has_owner(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasOwner", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.s()?) + Ok(res.z()?) } - /// Set burn time. - /// A burn time greater than 0 will cause this block to be lit, whilst a time - /// less than 0 will extinguish it. - pub fn set_burn_time(&self, burn_time: i16) -> Result<(), Box> { - let sig = String::from("(S)V"); - let val_1 = jni::objects::JValueGen::Short(burn_time); + #[deprecated] + /// Gets the owner of the skull, if one exists + pub fn owner(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + #[deprecated] + /// Sets the owner of the skullInvolves a potentially blocking web request to acquire the profile data for the provided name. + pub fn set_owner(&self, name: impl Into) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setBurnTime", + "setOwner", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Get cook time. - /// This is the amount of time the item has been cooking for. - pub fn cook_time(&self) -> Result> { - let sig = String::from("()S"); + /// Get the player which owns the skull. This player may appear as the + /// texture depending on skull type. + pub fn owning_player( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/OfflinePlayer;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getCookTime", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getOwningPlayer", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.s()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::OfflinePlayer::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Set cook time. - /// This is the amount of time the item has been cooking for. - pub fn set_cook_time(&self, cook_time: i16) -> Result<(), Box> { - let sig = String::from("(S)V"); - let val_1 = jni::objects::JValueGen::Short(cook_time); + /// Set the player which owns the skull. This player may appear as the + /// texture depending on skull type. + pub fn set_owning_player( + &self, + player: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/OfflinePlayer;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(player.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCookTime", + "setOwningPlayer", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get cook time total. - /// This is the amount of time the item is required to cook for. - pub fn cook_time_total(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCookTimeTotal", + /// Gets the profile of the player who owns the skull. This player profile + /// may appear as the texture depending on skull type. + pub fn owner_profile( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/profile/PlayerProfile;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getOwnerProfile", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::profile::PlayerProfile::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets the profile of the player who owns the skull. This player profile + /// may appear as the texture depending on skull type. + /// + /// The profile must contain both a unique id and a skin texture. If either + /// of these is missing, the profile must contain a name by which the server + /// will then attempt to look up the unique id and skin texture. + pub fn set_owner_profile( + &self, + profile: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/profile/PlayerProfile;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(profile.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setOwnerProfile", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the sound to play if the skull is placed on a note block. + /// + /// Note: This only works for player heads. For other heads, + /// see {@link org.bukkit.Instrument}. + pub fn note_block_sound( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNoteBlockSound", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::NamespacedKey::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Set cook time. - /// This is the amount of time the item is required to cook for. - pub fn set_cook_time_total( + /// Sets the sound to play if the skull is placed on a note block. + /// + /// Note: This only works for player heads. For other heads, + /// see {@link org.bukkit.Instrument}. + pub fn set_note_block_sound( &self, - cook_time_total: i32, + note_block_sound: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(cook_time_total); + let sig = String::from("(Lorg/bukkit/NamespacedKey;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(note_block_sound.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCookTimeTotal", + "setNoteBlockSound", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the recipes used in this furnace. - /// Note: These recipes used are reset when the result item is - /// manually taken from the furnace. - pub fn recipes_used( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); + #[deprecated] + /// Gets the rotation of the skull in the world (or facing direction if this is a wall mounted skull). + pub fn rotation(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getRecipesUsed", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getRotation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn inventory( + #[deprecated] + /// Sets the rotation of the skull in the world (or facing direction if this is a wall mounted skull). + pub fn set_rotation( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/FurnaceInventory;"); + rotation: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(rotation.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRotation", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the type of skull + pub fn skull_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/SkullType;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSkullType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::FurnaceInventory::from_raw(&self.jni_ref(), unsafe { + crate::SkullType::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn snapshot_inventory( + #[deprecated] + /// Sets the type of skull + pub fn set_skull_type( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/FurnaceInventory;"); + skull_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/SkullType;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(skull_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getSnapshotInventory", + "setSkullType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + /// + /// This {@link PersistentDataHolder} is only linked to the snapshot instance + /// stored by the {@link BlockState}. + /// When storing changes on the {@link PersistentDataHolder}, the updated + /// content will only be applied to the actual tile entity after one of the + /// {@link #update()} methods is called. + pub fn persistent_data_container( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPersistentDataContainer", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::FurnaceInventory::from_raw(&self.jni_ref(), unsafe { + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -3659,19 +4120,19 @@ impl<'mc> Smoker<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Smoker<'mc> { - fn into(self) -> crate::block::Furnace<'mc> { - crate::block::Furnace::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Smoker into crate::block::Furnace") +impl<'mc> Into> for Skull<'mc> { + fn into(self) -> crate::block::TileState<'mc> { + crate::block::TileState::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Skull into crate::block::TileState") } } #[repr(C)] -pub struct Barrel<'mc>( +pub struct Lidded<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Barrel<'mc> { +impl<'mc> JNIRaw<'mc> for Lidded<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3679,18 +4140,18 @@ impl<'mc> JNIRaw<'mc> for Barrel<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Barrel<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Lidded<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Barrel from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Lidded from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Barrel")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Lidded")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Barrel object, got {}", + "Invalid argument passed. Expected a Lidded object, got {}", name ) .into()) @@ -3700,119 +4161,14 @@ impl<'mc> JNIInstantiatable<'mc> for Barrel<'mc> { } } -impl<'mc> Barrel<'mc> { - /// Gets the inventory of the block represented by this block state. - /// - /// If the block was changed to a different type in the meantime, the - /// returned inventory might no longer be valid. - /// - /// If this block state is not placed this will return the captured inventory - /// snapshot instead. - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the captured inventory snapshot of this container. - /// - /// The returned inventory is not linked to any block. Any modifications to - /// the returned inventory will not be applied to the block represented by - /// this block state up until {@link #update(boolean, boolean)} has been - /// called. - pub fn snapshot_inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSnapshotInventory", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Set the loot table for a container or entity. - /// - /// To remove a loot table use null. Do not use {@link LootTables#EMPTY} to - /// clear a LootTable. - pub fn set_loot_table( - &self, - table: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/loot/LootTable;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(table.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLootTable", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the Loot Table attached to this block or entity. - /// - /// If an block/entity does not have a loot table, this will return null, NOT - /// an empty loot table. - pub fn loot_table( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/loot/LootTable;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLootTable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::loot::LootTable::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Set the seed used when this Loot Table generates loot. - pub fn set_seed(&self, seed: i64) -> Result<(), Box> { - let sig = String::from("(J)V"); - let val_1 = jni::objects::JValueGen::Long(seed); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSeed", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the Loot Table's seed. - /// - /// The seed is used when generating loot. - pub fn seed(&self) -> Result> { - let sig = String::from("()J"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSeed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) - } - /// Sets the block's animated state to open and prevents it from being closed - /// until {@link #close()} is called. - pub fn open(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "open", sig.as_str(), vec![]); +impl<'mc> Lidded<'mc> { + /// Sets the block's animated state to open and prevents it from being closed + /// until {@link #close()} is called. + pub fn open(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "open", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } @@ -3832,31 +4188,13 @@ impl<'mc> Barrel<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Barrel<'mc> { - fn into(self) -> crate::block::Container<'mc> { - crate::block::Container::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Barrel into crate::block::Container") - } -} -impl<'mc> Into> for Barrel<'mc> { - fn into(self) -> crate::loot::Lootable<'mc> { - crate::loot::Lootable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Barrel into crate::loot::Lootable") - } -} -impl<'mc> Into> for Barrel<'mc> { - fn into(self) -> crate::block::Lidded<'mc> { - crate::block::Lidded::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Barrel into crate::block::Lidded") - } -} #[repr(C)] -pub struct SuspiciousSand<'mc>( +pub struct Furnace<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for SuspiciousSand<'mc> { +impl<'mc> JNIRaw<'mc> for Furnace<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3864,20 +4202,18 @@ impl<'mc> JNIRaw<'mc> for SuspiciousSand<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for SuspiciousSand<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Furnace<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate SuspiciousSand from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate Furnace from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/SuspiciousSand")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Furnace")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SuspiciousSand object, got {}", + "Invalid argument passed. Expected a Furnace object, got {}", name ) .into()) @@ -3887,159 +4223,173 @@ impl<'mc> JNIInstantiatable<'mc> for SuspiciousSand<'mc> { } } -impl<'mc> SuspiciousSand<'mc> { - /// Get the item which will be revealed when the sand is fully brushed away - /// and uncovered. - pub fn item( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); +impl<'mc> Furnace<'mc> { + /// Get burn time. + pub fn burn_time(&self) -> Result> { + let sig = String::from("()S"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBurnTime", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.s()?) } - /// Sets the item which will be revealed when the sand is fully brushed away - /// and uncovered. - pub fn set_item( + /// Set burn time. + /// A burn time greater than 0 will cause this block to be lit, whilst a time + /// less than 0 will extinguish it. + pub fn set_burn_time(&self, burn_time: i16) -> Result<(), Box> { + let sig = String::from("(S)V"); + let val_1 = jni::objects::JValueGen::Short(burn_time); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBurnTime", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get cook time. + /// This is the amount of time the item has been cooking for. + pub fn cook_time(&self) -> Result> { + let sig = String::from("()S"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCookTime", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.s()?) + } + /// Set cook time. + /// This is the amount of time the item has been cooking for. + pub fn set_cook_time(&self, cook_time: i16) -> Result<(), Box> { + let sig = String::from("(S)V"); + let val_1 = jni::objects::JValueGen::Short(cook_time); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCookTime", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get cook time total. + /// This is the amount of time the item is required to cook for. + pub fn cook_time_total(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCookTimeTotal", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set cook time. + /// This is the amount of time the item is required to cook for. + pub fn set_cook_time_total( &self, - item: impl Into>, + cook_time_total: i32, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(cook_time_total); let res = self.jni_ref().call_method( &self.jni_object(), - "setItem", + "setCookTimeTotal", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } + /// Get the recipes used in this furnace. + /// Note: These recipes used are reset when the result item is + /// manually taken from the furnace. + pub fn recipes_used( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Map;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRecipesUsed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn snapshot_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/FurnaceInventory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSnapshotInventory", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::FurnaceInventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the inventory of the block represented by this block state. + /// + /// If the block was changed to a different type in the meantime, the + /// returned inventory might no longer be valid. + /// + /// If this block state is not placed this will return the captured inventory + /// snapshot instead. + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for SuspiciousSand<'mc> { - fn into(self) -> crate::block::BrushableBlock<'mc> { - crate::block::BrushableBlock::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SuspiciousSand into crate::block::BrushableBlock") +impl<'mc> Into> for Furnace<'mc> { + fn into(self) -> crate::block::Container<'mc> { + crate::block::Container::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Furnace into crate::block::Container") } } -pub enum PistonMoveReaction<'mc> {} -impl<'mc> std::fmt::Display for PistonMoveReaction<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} +#[repr(C)] +pub struct Beacon<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Beacon<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } - -impl<'mc> PistonMoveReaction<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/block/PistonMoveReaction"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/block/PistonMoveReaction;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct PistonMoveReactionStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PistonMoveReaction<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for PistonMoveReaction<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate PistonMoveReaction from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/PistonMoveReaction")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PistonMoveReaction object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for PistonMoveReactionStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PistonMoveReactionStruct<'mc> { - fn from_raw( +impl<'mc> JNIInstantiatable<'mc> for Beacon<'mc> { + fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PistonMoveReactionStruct from null object." - ) - .into()); + return Err(eyre::eyre!("Tried to instantiate Beacon from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/PistonMoveReaction")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Beacon")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PistonMoveReactionStruct object, got {}", + "Invalid argument passed. Expected a Beacon object, got {}", name ) .into()) @@ -4049,232 +4399,119 @@ impl<'mc> JNIInstantiatable<'mc> for PistonMoveReactionStruct<'mc> { } } -impl<'mc> PistonMoveReactionStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); - let cls = jni.find_class("org/bukkit/block/PistonMoveReaction"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::block::PistonMoveReaction::from_raw(&jni, obj) +impl<'mc> Beacon<'mc> { + /// Returns the list of players within the beacon's range of effect. + /// + /// This will return an empty list if the block represented by this state is + /// no longer a beacon. + pub fn entities_in_range( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getEntitiesInRange", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::LivingEntity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - #[deprecated] - - pub fn id(&self) -> Result> { + /// Returns the tier of the beacon pyramid (0-4). The tier refers to the + /// beacon's power level, based on how many layers of blocks are in the + /// pyramid. Tier 1 refers to a beacon with one layer of 9 blocks under it. + pub fn tier(&self) -> Result> { let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getId", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTier", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - #[deprecated] - - pub fn get_by_id( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - id: i32, - ) -> Result>, Box> { - let sig = String::from("(I)Lorg/bukkit/block/PistonMoveReaction;"); - let val_1 = jni::objects::JValueGen::Int(id); - let cls = jni.find_class("org/bukkit/block/PistonMoveReaction"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getById", + /// Returns the primary effect set on the beacon + pub fn primary_effect( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/potion/PotionEffect;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPrimaryEffect", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - let res = jni.translate_error(res)?; + let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - let obj = res.l()?; - Ok(Some(crate::block::PistonMoveReaction::from_raw(&jni, obj)?)) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct Jukebox<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Jukebox<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + Ok(Some(crate::potion::PotionEffect::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } -} -impl<'mc> JNIInstantiatable<'mc> for Jukebox<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Jukebox from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Jukebox")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Jukebox object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Set the primary effect on this beacon, or null to clear. + pub fn set_primary_effect( + &self, + effect: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPrimaryEffect", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> Jukebox<'mc> { - /// Gets the record inserted into the jukebox. - pub fn playing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPlaying", sig.as_str(), vec![]); + /// Returns the secondary effect set on the beacon. + pub fn secondary_effect( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/potion/PotionEffect;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSecondaryEffect", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::potion::PotionEffect::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the record being played. - pub fn set_playing( + /// Set the secondary effect on this beacon, or null to clear. Note that tier + /// must be >= 4 for this effect to be active. + pub fn set_secondary_effect( &self, - record: impl Into>, + effect: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Material;)V"); + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(record.into().jni_object().clone()) + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPlaying", + "setSecondaryEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not this jukebox has a record. - /// - /// A jukebox can have a record but not {@link #isPlaying() be playing} - /// if it was stopped with {@link #stopPlaying()} or if a record has - /// finished playing. - pub fn has_record(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasRecord", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the record item inserted into the jukebox. - pub fn record(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getRecord", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the record being played. The jukebox will start playing automatically. - pub fn set_record( - &self, - record: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(record.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRecord", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks if the jukebox is playing a record. - pub fn is_playing(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isPlaying", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Starts the jukebox playing if there is a record. - pub fn start_playing(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "startPlaying", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Stops the jukebox playing without ejecting the record. - pub fn stop_playing(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "stopPlaying", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Stops the jukebox playing and ejects the current record. - /// - /// If the block represented by this state is no longer a jukebox, this will - /// do nothing and return false. - pub fn eject(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/JukeboxInventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::JukeboxInventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn snapshot_inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/JukeboxInventory;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSnapshotInventory", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::JukeboxInventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } /// Returns a custom tag container capable of storing tags on the object. /// Note that the tags stored on this container are all stored under their /// own custom namespace therefore modifying default tags using this @@ -4300,16 +4537,91 @@ impl<'mc> Jukebox<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the block associated with this holder. - pub fn block(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); + /// Checks if the container has a valid (non empty) key. + pub fn is_locked(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isLocked", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) + } + /// Gets the key needed to access the container. + pub fn lock(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLock", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the key required to access this container. Set to null (or empty + /// string) to remove key. + pub fn set_lock(&self, key: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(key.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLock", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the custom name on a mob or block. If there is no name this method + /// will return null. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn custom_name(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/lang/String;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCustomName", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Sets a custom name on a mob or block. This name will be used in death + /// messages and can be sent to the client as a nameplate over the mob. + /// + /// Setting the name to null or an empty string will clear it. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn set_custom_name( + &self, + name: impl Into, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setCustomName", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -4317,25 +4629,31 @@ impl<'mc> Jukebox<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Jukebox<'mc> { +impl<'mc> Into> for Beacon<'mc> { fn into(self) -> crate::block::TileState<'mc> { crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Jukebox into crate::block::TileState") + .expect("Error converting Beacon into crate::block::TileState") } } -impl<'mc> Into> for Jukebox<'mc> { - fn into(self) -> crate::inventory::BlockInventoryHolder<'mc> { - crate::inventory::BlockInventoryHolder::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Jukebox into crate::inventory::BlockInventoryHolder") +impl<'mc> Into> for Beacon<'mc> { + fn into(self) -> crate::block::Lockable<'mc> { + crate::block::Lockable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Beacon into crate::block::Lockable") + } +} +impl<'mc> Into> for Beacon<'mc> { + fn into(self) -> crate::Nameable<'mc> { + crate::Nameable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Beacon into crate::Nameable") } } #[repr(C)] -pub struct Skull<'mc>( +pub struct EnchantingTable<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Skull<'mc> { +impl<'mc> JNIRaw<'mc> for EnchantingTable<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -4343,18 +4661,20 @@ impl<'mc> JNIRaw<'mc> for Skull<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Skull<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EnchantingTable<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Skull from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate EnchantingTable from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Skull")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/EnchantingTable")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Skull object, got {}", + "Invalid argument passed. Expected a EnchantingTable object, got {}", name ) .into()) @@ -4364,234 +4684,7 @@ impl<'mc> JNIInstantiatable<'mc> for Skull<'mc> { } } -impl<'mc> Skull<'mc> { - /// Checks to see if the skull has an owner - pub fn has_owner(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasOwner", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Gets the owner of the skull, if one exists - pub fn owner(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - #[deprecated] - /// Sets the owner of the skullInvolves a potentially blocking web request to acquire the profile data for the provided name. - pub fn set_owner(&self, name: impl Into) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setOwner", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the player which owns the skull. This player may appear as the - /// texture depending on skull type. - pub fn owning_player( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/OfflinePlayer;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getOwningPlayer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::OfflinePlayer::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Set the player which owns the skull. This player may appear as the - /// texture depending on skull type. - pub fn set_owning_player( - &self, - player: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/OfflinePlayer;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setOwningPlayer", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the profile of the player who owns the skull. This player profile - /// may appear as the texture depending on skull type. - pub fn owner_profile( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/profile/PlayerProfile;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getOwnerProfile", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::profile::PlayerProfile::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Sets the profile of the player who owns the skull. This player profile - /// may appear as the texture depending on skull type. - /// - /// The profile must contain both a unique id and a skin texture. If either - /// of these is missing, the profile must contain a name by which the server - /// will then attempt to look up the unique id and skin texture. - pub fn set_owner_profile( - &self, - profile: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/profile/PlayerProfile;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(profile.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setOwnerProfile", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the sound to play if the skull is placed on a note block. - /// - /// Note: This only works for player heads. For other heads, - /// see {@link org.bukkit.Instrument}. - pub fn note_block_sound( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getNoteBlockSound", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::NamespacedKey::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Sets the sound to play if the skull is placed on a note block. - /// - /// Note: This only works for player heads. For other heads, - /// see {@link org.bukkit.Instrument}. - pub fn set_note_block_sound( - &self, - note_block_sound: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(note_block_sound.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setNoteBlockSound", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Gets the rotation of the skull in the world (or facing direction if this is a wall mounted skull). - pub fn rotation(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRotation", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - #[deprecated] - /// Sets the rotation of the skull in the world (or facing direction if this is a wall mounted skull). - pub fn set_rotation( - &self, - rotation: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(rotation.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRotation", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Gets the type of skull - pub fn skull_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/SkullType;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSkullType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::SkullType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - #[deprecated] - /// Sets the type of skull - pub fn set_skull_type( - &self, - skull_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/SkullType;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(skull_type.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSkullType", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } +impl<'mc> EnchantingTable<'mc> { /// Returns a custom tag container capable of storing tags on the object. /// Note that the tags stored on this container are all stored under their /// own custom namespace therefore modifying default tags using this @@ -4617,25 +4710,974 @@ impl<'mc> Skull<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } + /// Gets the custom name on a mob or block. If there is no name this method + /// will return null. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn custom_name(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/lang/String;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCustomName", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Sets a custom name on a mob or block. This name will be used in death + /// messages and can be sent to the client as a nameplate over the mob. + /// + /// Setting the name to null or an empty string will clear it. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn set_custom_name( + &self, + name: impl Into, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setCustomName", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Skull<'mc> { +impl<'mc> Into> for EnchantingTable<'mc> { fn into(self) -> crate::block::TileState<'mc> { crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Skull into crate::block::TileState") + .expect("Error converting EnchantingTable into crate::block::TileState") } } +impl<'mc> Into> for EnchantingTable<'mc> { + fn into(self) -> crate::Nameable<'mc> { + crate::Nameable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EnchantingTable into crate::Nameable") + } +} +pub enum Biome<'mc> { + Ocean { inner: BiomeStruct<'mc> }, + Plains { inner: BiomeStruct<'mc> }, + Desert { inner: BiomeStruct<'mc> }, + WindsweptHills { inner: BiomeStruct<'mc> }, + Forest { inner: BiomeStruct<'mc> }, + Taiga { inner: BiomeStruct<'mc> }, + Swamp { inner: BiomeStruct<'mc> }, + MangroveSwamp { inner: BiomeStruct<'mc> }, + River { inner: BiomeStruct<'mc> }, + NetherWastes { inner: BiomeStruct<'mc> }, + TheEnd { inner: BiomeStruct<'mc> }, + FrozenOcean { inner: BiomeStruct<'mc> }, + FrozenRiver { inner: BiomeStruct<'mc> }, + SnowyPlains { inner: BiomeStruct<'mc> }, + MushroomFields { inner: BiomeStruct<'mc> }, + Beach { inner: BiomeStruct<'mc> }, + Jungle { inner: BiomeStruct<'mc> }, + SparseJungle { inner: BiomeStruct<'mc> }, + DeepOcean { inner: BiomeStruct<'mc> }, + StonyShore { inner: BiomeStruct<'mc> }, + SnowyBeach { inner: BiomeStruct<'mc> }, + BirchForest { inner: BiomeStruct<'mc> }, + DarkForest { inner: BiomeStruct<'mc> }, + SnowyTaiga { inner: BiomeStruct<'mc> }, + OldGrowthPineTaiga { inner: BiomeStruct<'mc> }, + WindsweptForest { inner: BiomeStruct<'mc> }, + Savanna { inner: BiomeStruct<'mc> }, + SavannaPlateau { inner: BiomeStruct<'mc> }, + Badlands { inner: BiomeStruct<'mc> }, + WoodedBadlands { inner: BiomeStruct<'mc> }, + SmallEndIslands { inner: BiomeStruct<'mc> }, + EndMidlands { inner: BiomeStruct<'mc> }, + EndHighlands { inner: BiomeStruct<'mc> }, + EndBarrens { inner: BiomeStruct<'mc> }, + WarmOcean { inner: BiomeStruct<'mc> }, + LukewarmOcean { inner: BiomeStruct<'mc> }, + ColdOcean { inner: BiomeStruct<'mc> }, + DeepLukewarmOcean { inner: BiomeStruct<'mc> }, + DeepColdOcean { inner: BiomeStruct<'mc> }, + DeepFrozenOcean { inner: BiomeStruct<'mc> }, + TheVoid { inner: BiomeStruct<'mc> }, + SunflowerPlains { inner: BiomeStruct<'mc> }, + WindsweptGravellyHills { inner: BiomeStruct<'mc> }, + FlowerForest { inner: BiomeStruct<'mc> }, + IceSpikes { inner: BiomeStruct<'mc> }, + OldGrowthBirchForest { inner: BiomeStruct<'mc> }, + OldGrowthSpruceTaiga { inner: BiomeStruct<'mc> }, + WindsweptSavanna { inner: BiomeStruct<'mc> }, + ErodedBadlands { inner: BiomeStruct<'mc> }, + BambooJungle { inner: BiomeStruct<'mc> }, + SoulSandValley { inner: BiomeStruct<'mc> }, + CrimsonForest { inner: BiomeStruct<'mc> }, + WarpedForest { inner: BiomeStruct<'mc> }, + BasaltDeltas { inner: BiomeStruct<'mc> }, + DripstoneCaves { inner: BiomeStruct<'mc> }, + LushCaves { inner: BiomeStruct<'mc> }, + DeepDark { inner: BiomeStruct<'mc> }, + Meadow { inner: BiomeStruct<'mc> }, + Grove { inner: BiomeStruct<'mc> }, + SnowySlopes { inner: BiomeStruct<'mc> }, + FrozenPeaks { inner: BiomeStruct<'mc> }, + JaggedPeaks { inner: BiomeStruct<'mc> }, + StonyPeaks { inner: BiomeStruct<'mc> }, + CherryGrove { inner: BiomeStruct<'mc> }, + Custom { inner: BiomeStruct<'mc> }, +} +impl<'mc> std::fmt::Display for Biome<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Biome::Ocean { .. } => f.write_str("OCEAN"), + Biome::Plains { .. } => f.write_str("PLAINS"), + Biome::Desert { .. } => f.write_str("DESERT"), + Biome::WindsweptHills { .. } => f.write_str("WINDSWEPT_HILLS"), + Biome::Forest { .. } => f.write_str("FOREST"), + Biome::Taiga { .. } => f.write_str("TAIGA"), + Biome::Swamp { .. } => f.write_str("SWAMP"), + Biome::MangroveSwamp { .. } => f.write_str("MANGROVE_SWAMP"), + Biome::River { .. } => f.write_str("RIVER"), + Biome::NetherWastes { .. } => f.write_str("NETHER_WASTES"), + Biome::TheEnd { .. } => f.write_str("THE_END"), + Biome::FrozenOcean { .. } => f.write_str("FROZEN_OCEAN"), + Biome::FrozenRiver { .. } => f.write_str("FROZEN_RIVER"), + Biome::SnowyPlains { .. } => f.write_str("SNOWY_PLAINS"), + Biome::MushroomFields { .. } => f.write_str("MUSHROOM_FIELDS"), + Biome::Beach { .. } => f.write_str("BEACH"), + Biome::Jungle { .. } => f.write_str("JUNGLE"), + Biome::SparseJungle { .. } => f.write_str("SPARSE_JUNGLE"), + Biome::DeepOcean { .. } => f.write_str("DEEP_OCEAN"), + Biome::StonyShore { .. } => f.write_str("STONY_SHORE"), + Biome::SnowyBeach { .. } => f.write_str("SNOWY_BEACH"), + Biome::BirchForest { .. } => f.write_str("BIRCH_FOREST"), + Biome::DarkForest { .. } => f.write_str("DARK_FOREST"), + Biome::SnowyTaiga { .. } => f.write_str("SNOWY_TAIGA"), + Biome::OldGrowthPineTaiga { .. } => f.write_str("OLD_GROWTH_PINE_TAIGA"), + Biome::WindsweptForest { .. } => f.write_str("WINDSWEPT_FOREST"), + Biome::Savanna { .. } => f.write_str("SAVANNA"), + Biome::SavannaPlateau { .. } => f.write_str("SAVANNA_PLATEAU"), + Biome::Badlands { .. } => f.write_str("BADLANDS"), + Biome::WoodedBadlands { .. } => f.write_str("WOODED_BADLANDS"), + Biome::SmallEndIslands { .. } => f.write_str("SMALL_END_ISLANDS"), + Biome::EndMidlands { .. } => f.write_str("END_MIDLANDS"), + Biome::EndHighlands { .. } => f.write_str("END_HIGHLANDS"), + Biome::EndBarrens { .. } => f.write_str("END_BARRENS"), + Biome::WarmOcean { .. } => f.write_str("WARM_OCEAN"), + Biome::LukewarmOcean { .. } => f.write_str("LUKEWARM_OCEAN"), + Biome::ColdOcean { .. } => f.write_str("COLD_OCEAN"), + Biome::DeepLukewarmOcean { .. } => f.write_str("DEEP_LUKEWARM_OCEAN"), + Biome::DeepColdOcean { .. } => f.write_str("DEEP_COLD_OCEAN"), + Biome::DeepFrozenOcean { .. } => f.write_str("DEEP_FROZEN_OCEAN"), + Biome::TheVoid { .. } => f.write_str("THE_VOID"), + Biome::SunflowerPlains { .. } => f.write_str("SUNFLOWER_PLAINS"), + Biome::WindsweptGravellyHills { .. } => f.write_str("WINDSWEPT_GRAVELLY_HILLS"), + Biome::FlowerForest { .. } => f.write_str("FLOWER_FOREST"), + Biome::IceSpikes { .. } => f.write_str("ICE_SPIKES"), + Biome::OldGrowthBirchForest { .. } => f.write_str("OLD_GROWTH_BIRCH_FOREST"), + Biome::OldGrowthSpruceTaiga { .. } => f.write_str("OLD_GROWTH_SPRUCE_TAIGA"), + Biome::WindsweptSavanna { .. } => f.write_str("WINDSWEPT_SAVANNA"), + Biome::ErodedBadlands { .. } => f.write_str("ERODED_BADLANDS"), + Biome::BambooJungle { .. } => f.write_str("BAMBOO_JUNGLE"), + Biome::SoulSandValley { .. } => f.write_str("SOUL_SAND_VALLEY"), + Biome::CrimsonForest { .. } => f.write_str("CRIMSON_FOREST"), + Biome::WarpedForest { .. } => f.write_str("WARPED_FOREST"), + Biome::BasaltDeltas { .. } => f.write_str("BASALT_DELTAS"), + Biome::DripstoneCaves { .. } => f.write_str("DRIPSTONE_CAVES"), + Biome::LushCaves { .. } => f.write_str("LUSH_CAVES"), + Biome::DeepDark { .. } => f.write_str("DEEP_DARK"), + Biome::Meadow { .. } => f.write_str("MEADOW"), + Biome::Grove { .. } => f.write_str("GROVE"), + Biome::SnowySlopes { .. } => f.write_str("SNOWY_SLOPES"), + Biome::FrozenPeaks { .. } => f.write_str("FROZEN_PEAKS"), + Biome::JaggedPeaks { .. } => f.write_str("JAGGED_PEAKS"), + Biome::StonyPeaks { .. } => f.write_str("STONY_PEAKS"), + Biome::CherryGrove { .. } => f.write_str("CHERRY_GROVE"), + Biome::Custom { .. } => f.write_str("CUSTOM"), + } + } +} +impl<'mc> std::ops::Deref for Biome<'mc> { + type Target = BiomeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + Biome::Ocean { inner } => inner, + Biome::Plains { inner } => inner, + Biome::Desert { inner } => inner, + Biome::WindsweptHills { inner } => inner, + Biome::Forest { inner } => inner, + Biome::Taiga { inner } => inner, + Biome::Swamp { inner } => inner, + Biome::MangroveSwamp { inner } => inner, + Biome::River { inner } => inner, + Biome::NetherWastes { inner } => inner, + Biome::TheEnd { inner } => inner, + Biome::FrozenOcean { inner } => inner, + Biome::FrozenRiver { inner } => inner, + Biome::SnowyPlains { inner } => inner, + Biome::MushroomFields { inner } => inner, + Biome::Beach { inner } => inner, + Biome::Jungle { inner } => inner, + Biome::SparseJungle { inner } => inner, + Biome::DeepOcean { inner } => inner, + Biome::StonyShore { inner } => inner, + Biome::SnowyBeach { inner } => inner, + Biome::BirchForest { inner } => inner, + Biome::DarkForest { inner } => inner, + Biome::SnowyTaiga { inner } => inner, + Biome::OldGrowthPineTaiga { inner } => inner, + Biome::WindsweptForest { inner } => inner, + Biome::Savanna { inner } => inner, + Biome::SavannaPlateau { inner } => inner, + Biome::Badlands { inner } => inner, + Biome::WoodedBadlands { inner } => inner, + Biome::SmallEndIslands { inner } => inner, + Biome::EndMidlands { inner } => inner, + Biome::EndHighlands { inner } => inner, + Biome::EndBarrens { inner } => inner, + Biome::WarmOcean { inner } => inner, + Biome::LukewarmOcean { inner } => inner, + Biome::ColdOcean { inner } => inner, + Biome::DeepLukewarmOcean { inner } => inner, + Biome::DeepColdOcean { inner } => inner, + Biome::DeepFrozenOcean { inner } => inner, + Biome::TheVoid { inner } => inner, + Biome::SunflowerPlains { inner } => inner, + Biome::WindsweptGravellyHills { inner } => inner, + Biome::FlowerForest { inner } => inner, + Biome::IceSpikes { inner } => inner, + Biome::OldGrowthBirchForest { inner } => inner, + Biome::OldGrowthSpruceTaiga { inner } => inner, + Biome::WindsweptSavanna { inner } => inner, + Biome::ErodedBadlands { inner } => inner, + Biome::BambooJungle { inner } => inner, + Biome::SoulSandValley { inner } => inner, + Biome::CrimsonForest { inner } => inner, + Biome::WarpedForest { inner } => inner, + Biome::BasaltDeltas { inner } => inner, + Biome::DripstoneCaves { inner } => inner, + Biome::LushCaves { inner } => inner, + Biome::DeepDark { inner } => inner, + Biome::Meadow { inner } => inner, + Biome::Grove { inner } => inner, + Biome::SnowySlopes { inner } => inner, + Biome::FrozenPeaks { inner } => inner, + Biome::JaggedPeaks { inner } => inner, + Biome::StonyPeaks { inner } => inner, + Biome::CherryGrove { inner } => inner, + Biome::Custom { inner } => inner, + } + } +} + +impl<'mc> Biome<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/block/Biome"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/block/Biome;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "OCEAN" => Ok(Biome::Ocean { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "PLAINS" => Ok(Biome::Plains { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "DESERT" => Ok(Biome::Desert { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "WINDSWEPT_HILLS" => Ok(Biome::WindsweptHills { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "FOREST" => Ok(Biome::Forest { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "TAIGA" => Ok(Biome::Taiga { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "SWAMP" => Ok(Biome::Swamp { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "MANGROVE_SWAMP" => Ok(Biome::MangroveSwamp { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "RIVER" => Ok(Biome::River { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "NETHER_WASTES" => Ok(Biome::NetherWastes { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "THE_END" => Ok(Biome::TheEnd { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "FROZEN_OCEAN" => Ok(Biome::FrozenOcean { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "FROZEN_RIVER" => Ok(Biome::FrozenRiver { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "SNOWY_PLAINS" => Ok(Biome::SnowyPlains { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "MUSHROOM_FIELDS" => Ok(Biome::MushroomFields { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "BEACH" => Ok(Biome::Beach { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "JUNGLE" => Ok(Biome::Jungle { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "SPARSE_JUNGLE" => Ok(Biome::SparseJungle { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "DEEP_OCEAN" => Ok(Biome::DeepOcean { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "STONY_SHORE" => Ok(Biome::StonyShore { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "SNOWY_BEACH" => Ok(Biome::SnowyBeach { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "BIRCH_FOREST" => Ok(Biome::BirchForest { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "DARK_FOREST" => Ok(Biome::DarkForest { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "SNOWY_TAIGA" => Ok(Biome::SnowyTaiga { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "OLD_GROWTH_PINE_TAIGA" => Ok(Biome::OldGrowthPineTaiga { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "WINDSWEPT_FOREST" => Ok(Biome::WindsweptForest { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "SAVANNA" => Ok(Biome::Savanna { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "SAVANNA_PLATEAU" => Ok(Biome::SavannaPlateau { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "BADLANDS" => Ok(Biome::Badlands { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "WOODED_BADLANDS" => Ok(Biome::WoodedBadlands { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "SMALL_END_ISLANDS" => Ok(Biome::SmallEndIslands { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "END_MIDLANDS" => Ok(Biome::EndMidlands { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "END_HIGHLANDS" => Ok(Biome::EndHighlands { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "END_BARRENS" => Ok(Biome::EndBarrens { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "WARM_OCEAN" => Ok(Biome::WarmOcean { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "LUKEWARM_OCEAN" => Ok(Biome::LukewarmOcean { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "COLD_OCEAN" => Ok(Biome::ColdOcean { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "DEEP_LUKEWARM_OCEAN" => Ok(Biome::DeepLukewarmOcean { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "DEEP_COLD_OCEAN" => Ok(Biome::DeepColdOcean { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "DEEP_FROZEN_OCEAN" => Ok(Biome::DeepFrozenOcean { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "THE_VOID" => Ok(Biome::TheVoid { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "SUNFLOWER_PLAINS" => Ok(Biome::SunflowerPlains { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "WINDSWEPT_GRAVELLY_HILLS" => Ok(Biome::WindsweptGravellyHills { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "FLOWER_FOREST" => Ok(Biome::FlowerForest { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "ICE_SPIKES" => Ok(Biome::IceSpikes { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "OLD_GROWTH_BIRCH_FOREST" => Ok(Biome::OldGrowthBirchForest { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "OLD_GROWTH_SPRUCE_TAIGA" => Ok(Biome::OldGrowthSpruceTaiga { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "WINDSWEPT_SAVANNA" => Ok(Biome::WindsweptSavanna { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "ERODED_BADLANDS" => Ok(Biome::ErodedBadlands { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "BAMBOO_JUNGLE" => Ok(Biome::BambooJungle { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "SOUL_SAND_VALLEY" => Ok(Biome::SoulSandValley { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "CRIMSON_FOREST" => Ok(Biome::CrimsonForest { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "WARPED_FOREST" => Ok(Biome::WarpedForest { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "BASALT_DELTAS" => Ok(Biome::BasaltDeltas { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "DRIPSTONE_CAVES" => Ok(Biome::DripstoneCaves { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "LUSH_CAVES" => Ok(Biome::LushCaves { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "DEEP_DARK" => Ok(Biome::DeepDark { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "MEADOW" => Ok(Biome::Meadow { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "GROVE" => Ok(Biome::Grove { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "SNOWY_SLOPES" => Ok(Biome::SnowySlopes { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "FROZEN_PEAKS" => Ok(Biome::FrozenPeaks { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "JAGGED_PEAKS" => Ok(Biome::JaggedPeaks { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "STONY_PEAKS" => Ok(Biome::StonyPeaks { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "CHERRY_GROVE" => Ok(Biome::CherryGrove { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "CUSTOM" => Ok(Biome::Custom { + inner: BiomeStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + #[repr(C)] -pub struct Lidded<'mc>( +pub struct BiomeStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Lidded<'mc> { +impl<'mc> JNIRaw<'mc> for Biome<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Ocean { inner } => inner.0.clone(), + Self::Plains { inner } => inner.0.clone(), + Self::Desert { inner } => inner.0.clone(), + Self::WindsweptHills { inner } => inner.0.clone(), + Self::Forest { inner } => inner.0.clone(), + Self::Taiga { inner } => inner.0.clone(), + Self::Swamp { inner } => inner.0.clone(), + Self::MangroveSwamp { inner } => inner.0.clone(), + Self::River { inner } => inner.0.clone(), + Self::NetherWastes { inner } => inner.0.clone(), + Self::TheEnd { inner } => inner.0.clone(), + Self::FrozenOcean { inner } => inner.0.clone(), + Self::FrozenRiver { inner } => inner.0.clone(), + Self::SnowyPlains { inner } => inner.0.clone(), + Self::MushroomFields { inner } => inner.0.clone(), + Self::Beach { inner } => inner.0.clone(), + Self::Jungle { inner } => inner.0.clone(), + Self::SparseJungle { inner } => inner.0.clone(), + Self::DeepOcean { inner } => inner.0.clone(), + Self::StonyShore { inner } => inner.0.clone(), + Self::SnowyBeach { inner } => inner.0.clone(), + Self::BirchForest { inner } => inner.0.clone(), + Self::DarkForest { inner } => inner.0.clone(), + Self::SnowyTaiga { inner } => inner.0.clone(), + Self::OldGrowthPineTaiga { inner } => inner.0.clone(), + Self::WindsweptForest { inner } => inner.0.clone(), + Self::Savanna { inner } => inner.0.clone(), + Self::SavannaPlateau { inner } => inner.0.clone(), + Self::Badlands { inner } => inner.0.clone(), + Self::WoodedBadlands { inner } => inner.0.clone(), + Self::SmallEndIslands { inner } => inner.0.clone(), + Self::EndMidlands { inner } => inner.0.clone(), + Self::EndHighlands { inner } => inner.0.clone(), + Self::EndBarrens { inner } => inner.0.clone(), + Self::WarmOcean { inner } => inner.0.clone(), + Self::LukewarmOcean { inner } => inner.0.clone(), + Self::ColdOcean { inner } => inner.0.clone(), + Self::DeepLukewarmOcean { inner } => inner.0.clone(), + Self::DeepColdOcean { inner } => inner.0.clone(), + Self::DeepFrozenOcean { inner } => inner.0.clone(), + Self::TheVoid { inner } => inner.0.clone(), + Self::SunflowerPlains { inner } => inner.0.clone(), + Self::WindsweptGravellyHills { inner } => inner.0.clone(), + Self::FlowerForest { inner } => inner.0.clone(), + Self::IceSpikes { inner } => inner.0.clone(), + Self::OldGrowthBirchForest { inner } => inner.0.clone(), + Self::OldGrowthSpruceTaiga { inner } => inner.0.clone(), + Self::WindsweptSavanna { inner } => inner.0.clone(), + Self::ErodedBadlands { inner } => inner.0.clone(), + Self::BambooJungle { inner } => inner.0.clone(), + Self::SoulSandValley { inner } => inner.0.clone(), + Self::CrimsonForest { inner } => inner.0.clone(), + Self::WarpedForest { inner } => inner.0.clone(), + Self::BasaltDeltas { inner } => inner.0.clone(), + Self::DripstoneCaves { inner } => inner.0.clone(), + Self::LushCaves { inner } => inner.0.clone(), + Self::DeepDark { inner } => inner.0.clone(), + Self::Meadow { inner } => inner.0.clone(), + Self::Grove { inner } => inner.0.clone(), + Self::SnowySlopes { inner } => inner.0.clone(), + Self::FrozenPeaks { inner } => inner.0.clone(), + Self::JaggedPeaks { inner } => inner.0.clone(), + Self::StonyPeaks { inner } => inner.0.clone(), + Self::CherryGrove { inner } => inner.0.clone(), + Self::Custom { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Ocean { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Plains { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Desert { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::WindsweptHills { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Forest { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Taiga { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Swamp { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::MangroveSwamp { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::River { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::NetherWastes { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TheEnd { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::FrozenOcean { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FrozenRiver { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SnowyPlains { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MushroomFields { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Beach { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Jungle { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SparseJungle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeepOcean { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StonyShore { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SnowyBeach { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BirchForest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DarkForest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SnowyTaiga { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OldGrowthPineTaiga { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WindsweptForest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Savanna { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SavannaPlateau { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Badlands { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::WoodedBadlands { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SmallEndIslands { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EndMidlands { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EndHighlands { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EndBarrens { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WarmOcean { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LukewarmOcean { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ColdOcean { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeepLukewarmOcean { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeepColdOcean { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeepFrozenOcean { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TheVoid { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SunflowerPlains { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WindsweptGravellyHills { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FlowerForest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IceSpikes { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OldGrowthBirchForest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OldGrowthSpruceTaiga { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WindsweptSavanna { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ErodedBadlands { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BambooJungle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SoulSandValley { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrimsonForest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WarpedForest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BasaltDeltas { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DripstoneCaves { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LushCaves { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeepDark { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Meadow { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Grove { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SnowySlopes { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FrozenPeaks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::JaggedPeaks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StonyPeaks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CherryGrove { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Custom { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for Biome<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Biome from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Biome")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Biome object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "OCEAN" => Ok(Biome::Ocean { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "PLAINS" => Ok(Biome::Plains { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "DESERT" => Ok(Biome::Desert { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "WINDSWEPT_HILLS" => Ok(Biome::WindsweptHills { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "FOREST" => Ok(Biome::Forest { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "TAIGA" => Ok(Biome::Taiga { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "SWAMP" => Ok(Biome::Swamp { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "MANGROVE_SWAMP" => Ok(Biome::MangroveSwamp { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "RIVER" => Ok(Biome::River { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "NETHER_WASTES" => Ok(Biome::NetherWastes { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "THE_END" => Ok(Biome::TheEnd { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "FROZEN_OCEAN" => Ok(Biome::FrozenOcean { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "FROZEN_RIVER" => Ok(Biome::FrozenRiver { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "SNOWY_PLAINS" => Ok(Biome::SnowyPlains { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "MUSHROOM_FIELDS" => Ok(Biome::MushroomFields { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "BEACH" => Ok(Biome::Beach { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "JUNGLE" => Ok(Biome::Jungle { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "SPARSE_JUNGLE" => Ok(Biome::SparseJungle { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "DEEP_OCEAN" => Ok(Biome::DeepOcean { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "STONY_SHORE" => Ok(Biome::StonyShore { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "SNOWY_BEACH" => Ok(Biome::SnowyBeach { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "BIRCH_FOREST" => Ok(Biome::BirchForest { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "DARK_FOREST" => Ok(Biome::DarkForest { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "SNOWY_TAIGA" => Ok(Biome::SnowyTaiga { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "OLD_GROWTH_PINE_TAIGA" => Ok(Biome::OldGrowthPineTaiga { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "WINDSWEPT_FOREST" => Ok(Biome::WindsweptForest { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "SAVANNA" => Ok(Biome::Savanna { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "SAVANNA_PLATEAU" => Ok(Biome::SavannaPlateau { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "BADLANDS" => Ok(Biome::Badlands { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "WOODED_BADLANDS" => Ok(Biome::WoodedBadlands { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "SMALL_END_ISLANDS" => Ok(Biome::SmallEndIslands { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "END_MIDLANDS" => Ok(Biome::EndMidlands { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "END_HIGHLANDS" => Ok(Biome::EndHighlands { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "END_BARRENS" => Ok(Biome::EndBarrens { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "WARM_OCEAN" => Ok(Biome::WarmOcean { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "LUKEWARM_OCEAN" => Ok(Biome::LukewarmOcean { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "COLD_OCEAN" => Ok(Biome::ColdOcean { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "DEEP_LUKEWARM_OCEAN" => Ok(Biome::DeepLukewarmOcean { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "DEEP_COLD_OCEAN" => Ok(Biome::DeepColdOcean { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "DEEP_FROZEN_OCEAN" => Ok(Biome::DeepFrozenOcean { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "THE_VOID" => Ok(Biome::TheVoid { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "SUNFLOWER_PLAINS" => Ok(Biome::SunflowerPlains { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "WINDSWEPT_GRAVELLY_HILLS" => Ok(Biome::WindsweptGravellyHills { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "FLOWER_FOREST" => Ok(Biome::FlowerForest { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "ICE_SPIKES" => Ok(Biome::IceSpikes { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "OLD_GROWTH_BIRCH_FOREST" => Ok(Biome::OldGrowthBirchForest { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "OLD_GROWTH_SPRUCE_TAIGA" => Ok(Biome::OldGrowthSpruceTaiga { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "WINDSWEPT_SAVANNA" => Ok(Biome::WindsweptSavanna { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "ERODED_BADLANDS" => Ok(Biome::ErodedBadlands { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "BAMBOO_JUNGLE" => Ok(Biome::BambooJungle { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "SOUL_SAND_VALLEY" => Ok(Biome::SoulSandValley { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "CRIMSON_FOREST" => Ok(Biome::CrimsonForest { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "WARPED_FOREST" => Ok(Biome::WarpedForest { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "BASALT_DELTAS" => Ok(Biome::BasaltDeltas { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "DRIPSTONE_CAVES" => Ok(Biome::DripstoneCaves { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "LUSH_CAVES" => Ok(Biome::LushCaves { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "DEEP_DARK" => Ok(Biome::DeepDark { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "MEADOW" => Ok(Biome::Meadow { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "GROVE" => Ok(Biome::Grove { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "SNOWY_SLOPES" => Ok(Biome::SnowySlopes { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "FROZEN_PEAKS" => Ok(Biome::FrozenPeaks { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "JAGGED_PEAKS" => Ok(Biome::JaggedPeaks { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "STONY_PEAKS" => Ok(Biome::StonyPeaks { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "CHERRY_GROVE" => Ok(Biome::CherryGrove { + inner: BiomeStruct::from_raw(env, obj)?, + }), + "CUSTOM" => Ok(Biome::Custom { + inner: BiomeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for BiomeStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -4643,18 +5685,18 @@ impl<'mc> JNIRaw<'mc> for Lidded<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Lidded<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BiomeStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Lidded from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate BiomeStruct from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Lidded")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Biome")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Lidded object, got {}", + "Invalid argument passed. Expected a BiomeStruct object, got {}", name ) .into()) @@ -4664,26 +5706,28 @@ impl<'mc> JNIInstantiatable<'mc> for Lidded<'mc> { } } -impl<'mc> Lidded<'mc> { - /// Sets the block's animated state to open and prevents it from being closed - /// until {@link #close()} is called. - pub fn open(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "open", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) +impl<'mc> BiomeStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/Biome;"); + let cls = jni.find_class("org/bukkit/block/Biome"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::block::Biome::from_raw(&jni, obj) } - /// Sets the block's animated state to closed even if a player is currently - /// viewing this block. - pub fn close(&self) -> Result<(), Box> { - let sig = String::from("()V"); + + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "close", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -4692,12 +5736,12 @@ impl<'mc> Lidded<'mc> { } } #[repr(C)] -pub struct Furnace<'mc>( +pub struct Dispenser<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Furnace<'mc> { +impl<'mc> JNIRaw<'mc> for Dispenser<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -4705,18 +5749,18 @@ impl<'mc> JNIRaw<'mc> for Furnace<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Furnace<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Dispenser<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Furnace from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Dispenser from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Furnace")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Dispenser")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Furnace object, got {}", + "Invalid argument passed. Expected a Dispenser object, got {}", name ) .into()) @@ -4726,134 +5770,195 @@ impl<'mc> JNIInstantiatable<'mc> for Furnace<'mc> { } } -impl<'mc> Furnace<'mc> { - /// Get burn time. - pub fn burn_time(&self) -> Result> { - let sig = String::from("()S"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBurnTime", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.s()?) - } - /// Set burn time. - /// A burn time greater than 0 will cause this block to be lit, whilst a time - /// less than 0 will extinguish it. - pub fn set_burn_time(&self, burn_time: i16) -> Result<(), Box> { - let sig = String::from("(S)V"); - let val_1 = jni::objects::JValueGen::Short(burn_time); +impl<'mc> Dispenser<'mc> { + /// Gets the BlockProjectileSource object for the dispenser. + /// + /// If the block represented by this state is no longer a dispenser, this + /// will return null. + pub fn block_projectile_source( + &self, + ) -> Result>, Box> + { + let sig = String::from("()Lorg/bukkit/projectiles/BlockProjectileSource;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setBurnTime", + "getBlockProjectileSource", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::projectiles::BlockProjectileSource::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Get cook time. - /// This is the amount of time the item has been cooking for. - pub fn cook_time(&self) -> Result> { - let sig = String::from("()S"); + /// Attempts to dispense the contents of the dispenser. + /// + /// If the block represented by this state is no longer a dispenser, this + /// will return false. + pub fn dispense(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "dispense", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the inventory of the block represented by this block state. + /// + /// If the block was changed to a different type in the meantime, the + /// returned inventory might no longer be valid. + /// + /// If this block state is not placed this will return the captured inventory + /// snapshot instead. + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getCookTime", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.s()?) - } - /// Set cook time. - /// This is the amount of time the item has been cooking for. - pub fn set_cook_time(&self, cook_time: i16) -> Result<(), Box> { - let sig = String::from("(S)V"); - let val_1 = jni::objects::JValueGen::Short(cook_time); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCookTime", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get cook time total. - /// This is the amount of time the item is required to cook for. - pub fn cook_time_total(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the captured inventory snapshot of this container. + /// + /// The returned inventory is not linked to any block. Any modifications to + /// the returned inventory will not be applied to the block represented by + /// this block state up until {@link #update(boolean, boolean)} has been + /// called. + pub fn snapshot_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCookTimeTotal", + "getSnapshotInventory", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set cook time. - /// This is the amount of time the item is required to cook for. - pub fn set_cook_time_total( - &self, - cook_time_total: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(cook_time_total); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCookTimeTotal", + /// Gets the custom name on a mob or block. If there is no name this method + /// will return null. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn custom_name(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/lang/String;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCustomName", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Sets a custom name on a mob or block. This name will be used in death + /// messages and can be sent to the client as a nameplate over the mob. + /// + /// Setting the name to null or an empty string will clear it. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn set_custom_name( + &self, + name: impl Into, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setCustomName", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Set the loot table for a container or entity. + /// + /// To remove a loot table use null. Do not use {@link LootTables#EMPTY} to + /// clear a LootTable. + pub fn set_loot_table( + &self, + table: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/loot/LootTable;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(table.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLootTable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the recipes used in this furnace. - /// Note: These recipes used are reset when the result item is - /// manually taken from the furnace. - pub fn recipes_used( + /// Gets the Loot Table attached to this block or entity. + /// + /// If an block/entity does not have a loot table, this will return null, NOT + /// an empty loot table. + pub fn loot_table( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/loot/LootTable;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getRecipesUsed", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLootTable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::loot::LootTable::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - - pub fn snapshot_inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/FurnaceInventory;"); + /// Set the seed used when this Loot Table generates loot. + pub fn set_seed(&self, seed: i64) -> Result<(), Box> { + let sig = String::from("(J)V"); + let val_1 = jni::objects::JValueGen::Long(seed); let res = self.jni_ref().call_method( &self.jni_object(), - "getSnapshotInventory", + "setSeed", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::FurnaceInventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the inventory of the block represented by this block state. - /// - /// If the block was changed to a different type in the meantime, the - /// returned inventory might no longer be valid. + /// Get the Loot Table's seed. /// - /// If this block state is not placed this will return the captured inventory - /// snapshot instead. - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + /// The seed is used when generating loot. + pub fn seed(&self) -> Result> { + let sig = String::from("()J"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSeed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.j()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -4861,19 +5966,31 @@ impl<'mc> Furnace<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Furnace<'mc> { +impl<'mc> Into> for Dispenser<'mc> { fn into(self) -> crate::block::Container<'mc> { crate::block::Container::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Furnace into crate::block::Container") + .expect("Error converting Dispenser into crate::block::Container") + } +} +impl<'mc> Into> for Dispenser<'mc> { + fn into(self) -> crate::Nameable<'mc> { + crate::Nameable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Dispenser into crate::Nameable") + } +} +impl<'mc> Into> for Dispenser<'mc> { + fn into(self) -> crate::loot::Lootable<'mc> { + crate::loot::Lootable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Dispenser into crate::loot::Lootable") } } #[repr(C)] -pub struct Beacon<'mc>( +pub struct Container<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Beacon<'mc> { +impl<'mc> JNIRaw<'mc> for Container<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -4881,18 +5998,18 @@ impl<'mc> JNIRaw<'mc> for Beacon<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Beacon<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Container<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Beacon from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Container from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Beacon")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Container")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Beacon object, got {}", + "Invalid argument passed. Expected a Container object, got {}", name ) .into()) @@ -4902,141 +6019,80 @@ impl<'mc> JNIInstantiatable<'mc> for Beacon<'mc> { } } -impl<'mc> Beacon<'mc> { - /// Returns the list of players within the beacon's range of effect. +impl<'mc> Container<'mc> { + /// Gets the inventory of the block represented by this block state. /// - /// This will return an empty list if the block represented by this state is - /// no longer a beacon. - pub fn entities_in_range( + /// If the block was changed to a different type in the meantime, the + /// returned inventory might no longer be valid. + /// + /// If this block state is not placed this will return the captured inventory + /// snapshot instead. + pub fn inventory( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the captured inventory snapshot of this container. + /// + /// The returned inventory is not linked to any block. Any modifications to + /// the returned inventory will not be applied to the block represented by + /// this block state up until {@link #update(boolean, boolean)} has been + /// called. + pub fn snapshot_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getEntitiesInRange", + "getSnapshotInventory", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::LivingEntity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Returns the tier of the beacon pyramid (0-4). The tier refers to the - /// beacon's power level, based on how many layers of blocks are in the - /// pyramid. Tier 1 refers to a beacon with one layer of 9 blocks under it. - pub fn tier(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTier", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the primary effect set on the beacon - pub fn primary_effect( + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + /// + /// This {@link PersistentDataHolder} is only linked to the snapshot instance + /// stored by the {@link BlockState}. + /// When storing changes on the {@link PersistentDataHolder}, the updated + /// content will only be applied to the actual tile entity after one of the + /// {@link #update()} methods is called. + pub fn persistent_data_container( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/potion/PotionEffect;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPrimaryEffect", + "getPersistentDataContainer", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::potion::PotionEffect::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the primary effect on this beacon, or null to clear. - pub fn set_primary_effect( - &self, - effect: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(effect.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPrimaryEffect", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns the secondary effect set on the beacon. - pub fn secondary_effect( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/potion/PotionEffect;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSecondaryEffect", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::potion::PotionEffect::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Set the secondary effect on this beacon, or null to clear. Note that tier - /// must be >= 4 for this effect to be active. - pub fn set_secondary_effect( - &self, - effect: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(effect.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSecondaryEffect", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - /// - /// This {@link PersistentDataHolder} is only linked to the snapshot instance - /// stored by the {@link BlockState}. - /// When storing changes on the {@link PersistentDataHolder}, the updated - /// content will only be applied to the actual tile entity after one of the - /// {@link #update()} methods is called. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPersistentDataContainer", - sig.as_str(), - vec![], - ); + /// Gets the block associated with this holder. + pub fn block(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + crate::block::Block::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -5132,31 +6188,37 @@ impl<'mc> Beacon<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Beacon<'mc> { +impl<'mc> Into> for Container<'mc> { fn into(self) -> crate::block::TileState<'mc> { crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Beacon into crate::block::TileState") + .expect("Error converting Container into crate::block::TileState") } } -impl<'mc> Into> for Beacon<'mc> { +impl<'mc> Into> for Container<'mc> { + fn into(self) -> crate::inventory::BlockInventoryHolder<'mc> { + crate::inventory::BlockInventoryHolder::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Container into crate::inventory::BlockInventoryHolder") + } +} +impl<'mc> Into> for Container<'mc> { fn into(self) -> crate::block::Lockable<'mc> { crate::block::Lockable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Beacon into crate::block::Lockable") + .expect("Error converting Container into crate::block::Lockable") } } -impl<'mc> Into> for Beacon<'mc> { +impl<'mc> Into> for Container<'mc> { fn into(self) -> crate::Nameable<'mc> { crate::Nameable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Beacon into crate::Nameable") + .expect("Error converting Container into crate::Nameable") } } #[repr(C)] -pub struct EnchantingTable<'mc>( +pub struct BrushableBlock<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EnchantingTable<'mc> { +impl<'mc> JNIRaw<'mc> for BrushableBlock<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -5164,20 +6226,20 @@ impl<'mc> JNIRaw<'mc> for EnchantingTable<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EnchantingTable<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BrushableBlock<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate EnchantingTable from null object.").into(), + eyre::eyre!("Tried to instantiate BrushableBlock from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/EnchantingTable")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/BrushableBlock")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EnchantingTable object, got {}", + "Invalid argument passed. Expected a BrushableBlock object, got {}", name ) .into()) @@ -5187,7 +6249,109 @@ impl<'mc> JNIInstantiatable<'mc> for EnchantingTable<'mc> { } } -impl<'mc> EnchantingTable<'mc> { +impl<'mc> BrushableBlock<'mc> { + /// Get the item which will be revealed when the sand is fully brushed away + /// and uncovered. + pub fn item( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets the item which will be revealed when the sand is fully brushed away + /// and uncovered. + pub fn set_item( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Set the loot table for a container or entity. + /// + /// To remove a loot table use null. Do not use {@link LootTables#EMPTY} to + /// clear a LootTable. + pub fn set_loot_table( + &self, + table: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/loot/LootTable;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(table.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLootTable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the Loot Table attached to this block or entity. + /// + /// If an block/entity does not have a loot table, this will return null, NOT + /// an empty loot table. + pub fn loot_table( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/loot/LootTable;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLootTable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::loot::LootTable::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Set the seed used when this Loot Table generates loot. + pub fn set_seed(&self, seed: i64) -> Result<(), Box> { + let sig = String::from("(J)V"); + let val_1 = jni::objects::JValueGen::Long(seed); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSeed", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the Loot Table's seed. + /// + /// The seed is used when generating loot. + pub fn seed(&self) -> Result> { + let sig = String::from("()J"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSeed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.j()?) + } /// Returns a custom tag container capable of storing tags on the object. /// Note that the tags stored on this container are all stored under their /// own custom namespace therefore modifying default tags using this @@ -5213,151 +6377,31 @@ impl<'mc> EnchantingTable<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the custom name on a mob or block. If there is no name this method - /// will return null. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn custom_name(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/lang/String;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCustomName", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Sets a custom name on a mob or block. This name will be used in death - /// messages and can be sent to the client as a nameplate over the mob. - /// - /// Setting the name to null or an empty string will clear it. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn set_custom_name( - &self, - name: impl Into, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); - args.push(val_1); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setCustomName", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) +} +impl<'mc> Into> for BrushableBlock<'mc> { + fn into(self) -> crate::loot::Lootable<'mc> { + crate::loot::Lootable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BrushableBlock into crate::loot::Lootable") } } -impl<'mc> Into> for EnchantingTable<'mc> { +impl<'mc> Into> for BrushableBlock<'mc> { fn into(self) -> crate::block::TileState<'mc> { crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EnchantingTable into crate::block::TileState") - } -} -impl<'mc> Into> for EnchantingTable<'mc> { - fn into(self) -> crate::Nameable<'mc> { - crate::Nameable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EnchantingTable into crate::Nameable") - } -} -pub enum Biome<'mc> {} -impl<'mc> std::fmt::Display for Biome<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> Biome<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/block/Biome"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/block/Biome;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + .expect("Error converting BrushableBlock into crate::block::TileState") } } - #[repr(C)] -pub struct BiomeStruct<'mc>( +pub struct ChiseledBookshelf<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Biome<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for Biome<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Biome from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Biome")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Biome object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for BiomeStruct<'mc> { +impl<'mc> JNIRaw<'mc> for ChiseledBookshelf<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -5365,18 +6409,20 @@ impl<'mc> JNIRaw<'mc> for BiomeStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BiomeStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ChiseledBookshelf<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate BiomeStruct from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate ChiseledBookshelf from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Biome")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/ChiseledBookshelf")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BiomeStruct object, got {}", + "Invalid argument passed. Expected a ChiseledBookshelf object, got {}", name ) .into()) @@ -5386,26 +6432,120 @@ impl<'mc> JNIInstantiatable<'mc> for BiomeStruct<'mc> { } } -impl<'mc> BiomeStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/Biome;"); - let cls = jni.find_class("org/bukkit/block/Biome"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::block::Biome::from_raw(&jni, obj) +impl<'mc> ChiseledBookshelf<'mc> { + /// Gets the last interacted inventory slot. + pub fn last_interacted_slot(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLastInteractedSlot", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the last interacted inventory slot. + pub fn set_last_interacted_slot( + &self, + last_interacted_slot: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(last_interacted_slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLastInteractedSlot", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ChiseledBookshelfInventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ChiseledBookshelfInventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn snapshot_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ChiseledBookshelfInventory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSnapshotInventory", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ChiseledBookshelfInventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the appropriate slot based on a vector relative to this block. + /// + /// Will return -1 if the given vector is not within the bounds of any slot. + /// + /// The supplied vector should only contain components with values between 0.0 + /// and 1.0, inclusive. + pub fn get_slot( + &self, + position: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/util/Vector;)I"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(position.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSlot", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + /// + /// This {@link PersistentDataHolder} is only linked to the snapshot instance + /// stored by the {@link BlockState}. + /// When storing changes on the {@link PersistentDataHolder}, the updated + /// content will only be applied to the actual tile entity after one of the + /// {@link #update()} methods is called. + pub fn persistent_data_container( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPersistentDataContainer", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the block associated with this holder. + pub fn block(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + crate::block::Block::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -5415,13 +6555,26 @@ impl<'mc> BiomeStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for ChiseledBookshelf<'mc> { + fn into(self) -> crate::block::TileState<'mc> { + crate::block::TileState::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ChiseledBookshelf into crate::block::TileState") + } +} +impl<'mc> Into> for ChiseledBookshelf<'mc> { + fn into(self) -> crate::inventory::BlockInventoryHolder<'mc> { + crate::inventory::BlockInventoryHolder::from_raw(&self.jni_ref(), self.1).expect( + "Error converting ChiseledBookshelf into crate::inventory::BlockInventoryHolder", + ) + } +} #[repr(C)] -pub struct Dispenser<'mc>( +pub struct Conduit<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Dispenser<'mc> { +impl<'mc> JNIRaw<'mc> for Conduit<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -5429,18 +6582,18 @@ impl<'mc> JNIRaw<'mc> for Dispenser<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Dispenser<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Conduit<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Dispenser from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Conduit from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Dispenser")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Conduit")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Dispenser object, got {}", + "Invalid argument passed. Expected a Conduit object, got {}", name ) .into()) @@ -5450,227 +6603,194 @@ impl<'mc> JNIInstantiatable<'mc> for Dispenser<'mc> { } } -impl<'mc> Dispenser<'mc> { - /// Gets the BlockProjectileSource object for the dispenser. +impl<'mc> Conduit<'mc> { + /// Checks whether or not this conduit is active. /// - /// If the block represented by this state is no longer a dispenser, this - /// will return null. - pub fn block_projectile_source( - &self, - ) -> Result>, Box> - { - let sig = String::from("()Lorg/bukkit/projectiles/BlockProjectileSource;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getBlockProjectileSource", - sig.as_str(), - vec![], - ); + /// A conduit is considered active if there are at least 16 valid frame + /// blocks surrounding it and the conduit is surrounded by a 3x3x3 area of + /// water source blocks (or waterlogged blocks), at which point its animation + /// will activate, start spinning, and apply effects to nearby players. + pub fn is_active(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isActive", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::projectiles::BlockProjectileSource::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Attempts to dispense the contents of the dispenser. + /// Get whether or not this conduit is actively hunting for nearby hostile + /// creatures. /// - /// If the block represented by this state is no longer a dispenser, this - /// will return false. - pub fn dispense(&self) -> Result> { + /// A conduit will hunt if it is active (see {@link #isActive()}) and its + /// frame is complete (it is surrounded by at least 42 valid frame blocks). + /// While hunting, the {@link #getTarget() + /// conduit's target}, if within its {@link #getHuntingArea() hunting area}, + /// will be damaged every 2 seconds. + pub fn is_hunting(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "dispense", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isHunting", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the inventory of the block represented by this block state. - /// - /// If the block was changed to a different type in the meantime, the - /// returned inventory might no longer be valid. - /// - /// If this block state is not placed this will return the captured inventory - /// snapshot instead. - pub fn inventory( + /// Get a {@link Collection} of all {@link Block Blocks} that make up the + /// frame of this conduit. The returned collection will contain only blocks + /// that match the types required by the conduit to make up a valid frame, + /// not the blocks at which the conduit is searching, + /// meaning it will be of variable size depending on how many valid frames + /// are surrounding the conduit at the time of invocation. + pub fn frame_blocks( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFrameBlocks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Gets the captured inventory snapshot of this container. - /// - /// The returned inventory is not linked to any block. Any modifications to - /// the returned inventory will not be applied to the block represented by - /// this block state up until {@link #update(boolean, boolean)} has been - /// called. - pub fn snapshot_inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + /// Get the amount of valid frame blocks that are currently surrounding the + /// conduit. + pub fn frame_block_count(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getSnapshotInventory", + "getFrameBlockCount", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Gets the custom name on a mob or block. If there is no name this method - /// will return null. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn custom_name(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/lang/String;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCustomName", sig.as_str(), args); + /// Get the range (measured in blocks) within which players will receive the + /// conduit's benefits. + pub fn range(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRange", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// Sets a custom name on a mob or block. This name will be used in death - /// messages and can be sent to the client as a nameplate over the mob. - /// - /// Setting the name to null or an empty string will clear it. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn set_custom_name( - &self, - name: impl Into, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); - args.push(val_1); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setCustomName", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.i()?) } - /// Set the loot table for a container or entity. + /// Set the conduit's hunting target. /// - /// To remove a loot table use null. Do not use {@link LootTables#EMPTY} to - /// clear a LootTable. - pub fn set_loot_table( + /// Note that the value set by this method may be overwritten by the + /// conduit's periodic hunting logic. If the target is ever set to + /// {@code null}, the conduit will continue to look for a new target. + /// Additionally, if the target is set to an entity that does not meet a + /// conduit's hunting conditions (e.g. the entity is not within the + /// {@link #getHuntingArea() hunting area}, has already been killed, etc.) + /// then the passed entity will be ignored and the conduit will also continue + /// to look for a new target. + pub fn set_target( &self, - table: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/loot/LootTable;)V"); + target: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(table.into().jni_object().clone()) + jni::objects::JObject::from_raw(target.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLootTable", + "setTarget", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the Loot Table attached to this block or entity. - /// - /// If an block/entity does not have a loot table, this will return null, NOT - /// an empty loot table. - pub fn loot_table( + /// Get the conduit's hunting target. + pub fn target( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/loot/LootTable;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLootTable", sig.as_str(), vec![]); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTarget", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::loot::LootTable::from_raw( + Ok(Some(crate::entity::LivingEntity::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Set the seed used when this Loot Table generates loot. - pub fn set_seed(&self, seed: i64) -> Result<(), Box> { - let sig = String::from("(J)V"); - let val_1 = jni::objects::JValueGen::Long(seed); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSeed", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the Loot Table's seed. - /// - /// The seed is used when generating loot. - pub fn seed(&self) -> Result> { - let sig = String::from("()J"); + /// Check whether or not this conduit has an active (alive) hunting target. + pub fn has_target(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getSeed", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasTarget", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Dispenser<'mc> { - fn into(self) -> crate::block::Container<'mc> { - crate::block::Container::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Dispenser into crate::block::Container") + Ok(res.z()?) } -} -impl<'mc> Into> for Dispenser<'mc> { - fn into(self) -> crate::Nameable<'mc> { - crate::Nameable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Dispenser into crate::Nameable") + /// Get a {@link BoundingBox} (relative to real-world coordinates) in which + /// the conduit will search for hostile entities to target. + pub fn hunting_area( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHuntingArea", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> Into> for Dispenser<'mc> { - fn into(self) -> crate::loot::Lootable<'mc> { - crate::loot::Lootable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Dispenser into crate::loot::Lootable") + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + /// + /// This {@link PersistentDataHolder} is only linked to the snapshot instance + /// stored by the {@link BlockState}. + /// When storing changes on the {@link PersistentDataHolder}, the updated + /// content will only be applied to the actual tile entity after one of the + /// {@link #update()} methods is called. + pub fn persistent_data_container( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPersistentDataContainer", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Conduit<'mc> { + fn into(self) -> crate::block::TileState<'mc> { + crate::block::TileState::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Conduit into crate::block::TileState") } } #[repr(C)] -pub struct Container<'mc>( +pub struct BlastFurnace<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Container<'mc> { +impl<'mc> JNIRaw<'mc> for BlastFurnace<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -5678,18 +6798,18 @@ impl<'mc> JNIRaw<'mc> for Container<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Container<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlastFurnace<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Container from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate BlastFurnace from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Container")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/BlastFurnace")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Container object, got {}", + "Invalid argument passed. Expected a BlastFurnace object, got {}", name ) .into()) @@ -5699,36 +6819,118 @@ impl<'mc> JNIInstantiatable<'mc> for Container<'mc> { } } -impl<'mc> Container<'mc> { - /// Gets the inventory of the block represented by this block state. - /// - /// If the block was changed to a different type in the meantime, the - /// returned inventory might no longer be valid. - /// - /// If this block state is not placed this will return the captured inventory - /// snapshot instead. +impl<'mc> BlastFurnace<'mc> { + /// Get burn time. + pub fn burn_time(&self) -> Result> { + let sig = String::from("()S"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBurnTime", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.s()?) + } + /// Set burn time. + /// A burn time greater than 0 will cause this block to be lit, whilst a time + /// less than 0 will extinguish it. + pub fn set_burn_time(&self, burn_time: i16) -> Result<(), Box> { + let sig = String::from("(S)V"); + let val_1 = jni::objects::JValueGen::Short(burn_time); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBurnTime", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get cook time. + /// This is the amount of time the item has been cooking for. + pub fn cook_time(&self) -> Result> { + let sig = String::from("()S"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCookTime", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.s()?) + } + /// Set cook time. + /// This is the amount of time the item has been cooking for. + pub fn set_cook_time(&self, cook_time: i16) -> Result<(), Box> { + let sig = String::from("(S)V"); + let val_1 = jni::objects::JValueGen::Short(cook_time); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCookTime", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get cook time total. + /// This is the amount of time the item is required to cook for. + pub fn cook_time_total(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCookTimeTotal", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set cook time. + /// This is the amount of time the item is required to cook for. + pub fn set_cook_time_total( + &self, + cook_time_total: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(cook_time_total); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCookTimeTotal", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the recipes used in this furnace. + /// Note: These recipes used are reset when the result item is + /// manually taken from the furnace. + pub fn recipes_used( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Map;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRecipesUsed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + pub fn inventory( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/FurnaceInventory;"); let res = self.jni_ref() .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + crate::inventory::FurnaceInventory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the captured inventory snapshot of this container. - /// - /// The returned inventory is not linked to any block. Any modifications to - /// the returned inventory will not be applied to the block represented by - /// this block state up until {@link #update(boolean, boolean)} has been - /// called. + pub fn snapshot_inventory( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/FurnaceInventory;"); let res = self.jni_ref().call_method( &self.jni_object(), "getSnapshotInventory", @@ -5736,10 +6938,58 @@ impl<'mc> Container<'mc> { vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + crate::inventory::FurnaceInventory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for BlastFurnace<'mc> { + fn into(self) -> crate::block::Furnace<'mc> { + crate::block::Furnace::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlastFurnace into crate::block::Furnace") + } +} +#[repr(C)] +pub struct Vault<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Vault<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Vault<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Vault from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Vault")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Vault object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Vault<'mc> { /// Returns a custom tag container capable of storing tags on the object. /// Note that the tags stored on this container are all stored under their /// own custom namespace therefore modifying default tags using this @@ -5765,140 +7015,25 @@ impl<'mc> Container<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the block associated with this holder. - pub fn block(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Checks if the container has a valid (non empty) key. - pub fn is_locked(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isLocked", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the key needed to access the container. - pub fn lock(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getLock", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Sets the key required to access this container. Set to null (or empty - /// string) to remove key. - pub fn set_lock(&self, key: impl Into) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(key.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLock", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the custom name on a mob or block. If there is no name this method - /// will return null. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn custom_name(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/lang/String;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCustomName", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// Sets a custom name on a mob or block. This name will be used in death - /// messages and can be sent to the client as a nameplate over the mob. - /// - /// Setting the name to null or an empty string will clear it. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn set_custom_name( - &self, - name: impl Into, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); - args.push(val_1); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setCustomName", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Container<'mc> { - fn into(self) -> crate::block::TileState<'mc> { - crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Container into crate::block::TileState") - } -} -impl<'mc> Into> for Container<'mc> { - fn into(self) -> crate::inventory::BlockInventoryHolder<'mc> { - crate::inventory::BlockInventoryHolder::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Container into crate::inventory::BlockInventoryHolder") - } -} -impl<'mc> Into> for Container<'mc> { - fn into(self) -> crate::block::Lockable<'mc> { - crate::block::Lockable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Container into crate::block::Lockable") - } -} -impl<'mc> Into> for Container<'mc> { - fn into(self) -> crate::Nameable<'mc> { - crate::Nameable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Container into crate::Nameable") +} +impl<'mc> Into> for Vault<'mc> { + fn into(self) -> crate::block::TileState<'mc> { + crate::block::TileState::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Vault into crate::block::TileState") } } #[repr(C)] -pub struct BrushableBlock<'mc>( +pub struct TileState<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BrushableBlock<'mc> { +impl<'mc> JNIRaw<'mc> for TileState<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -5906,20 +7041,18 @@ impl<'mc> JNIRaw<'mc> for BrushableBlock<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BrushableBlock<'mc> { +impl<'mc> JNIInstantiatable<'mc> for TileState<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate BrushableBlock from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate TileState from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/BrushableBlock")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/TileState")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BrushableBlock object, got {}", + "Invalid argument passed. Expected a TileState object, got {}", name ) .into()) @@ -5929,109 +7062,7 @@ impl<'mc> JNIInstantiatable<'mc> for BrushableBlock<'mc> { } } -impl<'mc> BrushableBlock<'mc> { - /// Get the item which will be revealed when the sand is fully brushed away - /// and uncovered. - pub fn item( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Sets the item which will be revealed when the sand is fully brushed away - /// and uncovered. - pub fn set_item( - &self, - item: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setItem", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Set the loot table for a container or entity. - /// - /// To remove a loot table use null. Do not use {@link LootTables#EMPTY} to - /// clear a LootTable. - pub fn set_loot_table( - &self, - table: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/loot/LootTable;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(table.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLootTable", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the Loot Table attached to this block or entity. - /// - /// If an block/entity does not have a loot table, this will return null, NOT - /// an empty loot table. - pub fn loot_table( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/loot/LootTable;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLootTable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::loot::LootTable::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Set the seed used when this Loot Table generates loot. - pub fn set_seed(&self, seed: i64) -> Result<(), Box> { - let sig = String::from("(J)V"); - let val_1 = jni::objects::JValueGen::Long(seed); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSeed", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the Loot Table's seed. - /// - /// The seed is used when generating loot. - pub fn seed(&self) -> Result> { - let sig = String::from("()J"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSeed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) - } +impl<'mc> TileState<'mc> { /// Returns a custom tag container capable of storing tags on the object. /// Note that the tags stored on this container are all stored under their /// own custom namespace therefore modifying default tags using this @@ -6057,177 +7088,389 @@ impl<'mc> BrushableBlock<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for BrushableBlock<'mc> { - fn into(self) -> crate::loot::Lootable<'mc> { - crate::loot::Lootable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BrushableBlock into crate::loot::Lootable") + /// Gets the block represented by this block state. + pub fn block(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> Into> for BrushableBlock<'mc> { - fn into(self) -> crate::block::TileState<'mc> { - crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BrushableBlock into crate::block::TileState") + /// Gets the metadata for this block state. + pub fn data(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/MaterialData;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -#[repr(C)] -pub struct ChiseledBookshelf<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for ChiseledBookshelf<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets the data for this block state. + pub fn block_data( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBlockData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> JNIInstantiatable<'mc> for ChiseledBookshelf<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate ChiseledBookshelf from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/ChiseledBookshelf")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ChiseledBookshelf object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + /// Copies the state to another block as an unplaced BlockState. + pub fn copy( + &self, + location: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = location { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); } + sig += ")Lorg/bukkit/block/BlockState;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} - -impl<'mc> ChiseledBookshelf<'mc> { - /// Gets the last interacted inventory slot. - pub fn last_interacted_slot(&self) -> Result> { + /// Gets the type of this block state. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the current light level of the block represented by this block state. + pub fn light_level(&self) -> Result> { + let sig = String::from("()B"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLightLevel", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.b()?) + } + /// Gets the world which contains the block represented by this block state. + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the x-coordinate of this block state. + pub fn x(&self) -> Result> { let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLastInteractedSlot", - sig.as_str(), - vec![], - ); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the last interacted inventory slot. - pub fn set_last_interacted_slot( + /// Gets the y-coordinate of this block state. + pub fn y(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the z-coordinate of this block state. + pub fn z(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Stores the location of this block state in the provided Location object. + /// + /// If the provided Location is null this method does nothing and returns + /// null. + /// + /// If this block state is not placed the location's world will be null! + pub fn get_location( &self, - last_interacted_slot: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(last_interacted_slot); + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastInteractedSlot", + "getLocation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ChiseledBookshelfInventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + /// Gets the chunk which contains the block represented by this block state. + pub fn chunk(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Chunk;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getChunk", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ChiseledBookshelfInventory::from_raw(&self.jni_ref(), unsafe { + crate::Chunk::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn snapshot_inventory( + /// Sets the metadata for this block state. + pub fn set_data( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ChiseledBookshelfInventory;"); + data: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/material/MaterialData;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(data.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getSnapshotInventory", + "setData", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ChiseledBookshelfInventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the appropriate slot based on a vector relative to this block. - /// - /// Will return -1 if the given vector is not within the bounds of any slot. - /// - /// The supplied vector should only contain components with values between 0.0 - /// and 1.0, inclusive. - pub fn get_slot( + /// Sets the data for this block state. + pub fn set_block_data( &self, - position: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/util/Vector;)I"); + data: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(position.into().jni_object().clone()) + jni::objects::JObject::from_raw(data.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getSlot", + "setBlockData", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - /// - /// This {@link PersistentDataHolder} is only linked to the snapshot instance - /// stored by the {@link BlockState}. - /// When storing changes on the {@link PersistentDataHolder}, the updated - /// content will only be applied to the actual tile entity after one of the - /// {@link #update()} methods is called. - pub fn persistent_data_container( + /// Sets the type of this block state. + pub fn set_type( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Material;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "setType", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the block associated with this holder. - pub fn block(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Attempts to update the block represented by this state, setting it to + /// the new values as defined by this state. + /// + /// If this state is not placed, this will have no effect and return true. + /// + /// Unless force is true, this will not modify the state of a block if it + /// is no longer the same type as it was when this state was taken. It will + /// return false in this eventuality. + /// + /// If force is true, it will set the type of the block to match the new + /// state, set the state data and then return true. + /// + /// If applyPhysics is true, it will trigger a physics update on + /// surrounding blocks which could cause them to update or disappear. + pub fn update( + &self, + force: std::option::Option, + apply_physics: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = force { + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_1); + } + if let Some(a) = apply_physics { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "update", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + + pub fn raw_data(&self) -> Result> { + let sig = String::from("()B"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRawData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.b()?) + } + #[deprecated] + + pub fn set_raw_data(&self, data: i8) -> Result<(), Box> { + let sig = String::from("(B)V"); + let val_1 = jni::objects::JValueGen::Byte(data); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRawData", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns whether this state is placed in the world. + /// + /// Some methods will not work if the block state isn't + /// placed in the world. + pub fn is_placed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isPlaced", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets a metadata value in the implementing object's metadata store. + pub fn set_metadata( + &self, + metadata_key: impl Into, + new_metadata_value: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += "Lorg/bukkit/metadata/MetadataValue;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) + }); + args.push(val_2); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setMetadata", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns a list of previously set metadata values from the implementing + /// object's metadata store. + pub fn get_metadata( + &self, + metadata_key: impl Into, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += ")Ljava/util/List;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getMetadata", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::metadata::MetadataValue::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(new_vec) + } + /// Tests to see whether the implementing object contains the given + /// metadata value in its metadata store. + pub fn has_metadata( + &self, + metadata_key: impl Into, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasMetadata", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Removes the given metadata value from the implementing object's + /// metadata store. + pub fn remove_metadata( + &self, + metadata_key: impl Into, + owning_plugin: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += "Lorg/bukkit/plugin/Plugin;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + }); + args.push(val_2); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "removeMetadata", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -6235,26 +7478,25 @@ impl<'mc> ChiseledBookshelf<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for ChiseledBookshelf<'mc> { - fn into(self) -> crate::block::TileState<'mc> { - crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ChiseledBookshelf into crate::block::TileState") +impl<'mc> Into> for TileState<'mc> { + fn into(self) -> crate::block::BlockState<'mc> { + crate::block::BlockState::from_raw(&self.jni_ref(), self.1) + .expect("Error converting TileState into crate::block::BlockState") } } -impl<'mc> Into> for ChiseledBookshelf<'mc> { - fn into(self) -> crate::inventory::BlockInventoryHolder<'mc> { - crate::inventory::BlockInventoryHolder::from_raw(&self.jni_ref(), self.1).expect( - "Error converting ChiseledBookshelf into crate::inventory::BlockInventoryHolder", - ) +impl<'mc> Into> for TileState<'mc> { + fn into(self) -> crate::persistence::PersistentDataHolder<'mc> { + crate::persistence::PersistentDataHolder::from_raw(&self.jni_ref(), self.1) + .expect("Error converting TileState into crate::persistence::PersistentDataHolder") } } #[repr(C)] -pub struct Conduit<'mc>( +pub struct Jigsaw<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Conduit<'mc> { +impl<'mc> JNIRaw<'mc> for Jigsaw<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6262,18 +7504,18 @@ impl<'mc> JNIRaw<'mc> for Conduit<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Conduit<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Jigsaw<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Conduit from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Jigsaw from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Conduit")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Jigsaw")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Conduit object, got {}", + "Invalid argument passed. Expected a Jigsaw object, got {}", name ) .into()) @@ -6283,364 +7525,435 @@ impl<'mc> JNIInstantiatable<'mc> for Conduit<'mc> { } } -impl<'mc> Conduit<'mc> { - /// Checks whether or not this conduit is active. +impl<'mc> Jigsaw<'mc> { + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. /// - /// A conduit is considered active if there are at least 16 valid frame - /// blocks surrounding it and the conduit is surrounded by a 3x3x3 area of - /// water source blocks (or waterlogged blocks), at which point its animation - /// will activate, start spinning, and apply effects to nearby players. - pub fn is_active(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isActive", sig.as_str(), vec![]); + /// This {@link PersistentDataHolder} is only linked to the snapshot instance + /// stored by the {@link BlockState}. + /// When storing changes on the {@link PersistentDataHolder}, the updated + /// content will only be applied to the actual tile entity after one of the + /// {@link #update()} methods is called. + pub fn persistent_data_container( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPersistentDataContainer", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get whether or not this conduit is actively hunting for nearby hostile - /// creatures. - /// - /// A conduit will hunt if it is active (see {@link #isActive()}) and its - /// frame is complete (it is surrounded by at least 42 valid frame blocks). - /// While hunting, the {@link #getTarget() - /// conduit's target}, if within its {@link #getHuntingArea() hunting area}, - /// will be damaged every 2 seconds. - pub fn is_hunting(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the block represented by this block state. + pub fn block(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isHunting", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get a {@link Collection} of all {@link Block Blocks} that make up the - /// frame of this conduit. The returned collection will contain only blocks - /// that match the types required by the conduit to make up a valid frame, - /// not the blocks at which the conduit is searching, - /// meaning it will be of variable size depending on how many valid frames - /// are surrounding the conduit at the time of invocation. - pub fn frame_blocks( + /// Gets the metadata for this block state. + pub fn data(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/MaterialData;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the data for this block state. + pub fn block_data( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFrameBlocks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBlockData", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Copies the state to another block as an unplaced BlockState. + pub fn copy( + &self, + location: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = location { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); } - Ok(new_vec) + sig += ")Lorg/bukkit/block/BlockState;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get the amount of valid frame blocks that are currently surrounding the - /// conduit. - pub fn frame_block_count(&self) -> Result> { + /// Gets the type of this block state. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the current light level of the block represented by this block state. + pub fn light_level(&self) -> Result> { + let sig = String::from("()B"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLightLevel", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.b()?) + } + /// Gets the world which contains the block represented by this block state. + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the x-coordinate of this block state. + pub fn x(&self) -> Result> { let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFrameBlockCount", - sig.as_str(), - vec![], - ); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Get the range (measured in blocks) within which players will receive the - /// conduit's benefits. - pub fn range(&self) -> Result> { + /// Gets the y-coordinate of this block state. + pub fn y(&self) -> Result> { let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getRange", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Set the conduit's hunting target. + /// Gets the z-coordinate of this block state. + pub fn z(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Stores the location of this block state in the provided Location object. /// - /// Note that the value set by this method may be overwritten by the - /// conduit's periodic hunting logic. If the target is ever set to - /// {@code null}, the conduit will continue to look for a new target. - /// Additionally, if the target is set to an entity that does not meet a - /// conduit's hunting conditions (e.g. the entity is not within the - /// {@link #getHuntingArea() hunting area}, has already been killed, etc.) - /// then the passed entity will be ignored and the conduit will also continue - /// to look for a new target. - pub fn set_target( + /// If the provided Location is null this method does nothing and returns + /// null. + /// + /// If this block state is not placed the location's world will be null! + pub fn get_location( &self, - target: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)Z"); + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setTarget", + "getLocation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the conduit's hunting target. - pub fn target( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTarget", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::LivingEntity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Check whether or not this conduit has an active (alive) hunting target. - pub fn has_target(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the chunk which contains the block represented by this block state. + pub fn chunk(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Chunk;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "hasTarget", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get a {@link BoundingBox} (relative to real-world coordinates) in which - /// the conduit will search for hostile entities to target. - pub fn hunting_area( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHuntingArea", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getChunk", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + crate::Chunk::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - /// - /// This {@link PersistentDataHolder} is only linked to the snapshot instance - /// stored by the {@link BlockState}. - /// When storing changes on the {@link PersistentDataHolder}, the updated - /// content will only be applied to the actual tile entity after one of the - /// {@link #update()} methods is called. - pub fn persistent_data_container( + /// Sets the metadata for this block state. + pub fn set_data( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + data: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/material/MaterialData;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(data.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "setData", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + self.jni_ref().translate_error(res)?; + Ok(()) } -} -impl<'mc> Into> for Conduit<'mc> { - fn into(self) -> crate::block::TileState<'mc> { - crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Conduit into crate::block::TileState") + /// Sets the data for this block state. + pub fn set_block_data( + &self, + data: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(data.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBlockData", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -#[repr(C)] -pub struct BlastFurnace<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for BlastFurnace<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for BlastFurnace<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate BlastFurnace from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/BlastFurnace")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a BlastFurnace object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> BlastFurnace<'mc> { - /// Get burn time. - pub fn burn_time(&self) -> Result> { - let sig = String::from("()S"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBurnTime", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.s()?) - } - /// Set burn time. - /// A burn time greater than 0 will cause this block to be lit, whilst a time - /// less than 0 will extinguish it. - pub fn set_burn_time(&self, burn_time: i16) -> Result<(), Box> { - let sig = String::from("(S)V"); - let val_1 = jni::objects::JValueGen::Short(burn_time); + /// Sets the type of this block state. + pub fn set_type( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Material;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBurnTime", + "setType", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get cook time. - /// This is the amount of time the item has been cooking for. - pub fn cook_time(&self) -> Result> { - let sig = String::from("()S"); + /// Attempts to update the block represented by this state, setting it to + /// the new values as defined by this state. + /// + /// If this state is not placed, this will have no effect and return true. + /// + /// Unless force is true, this will not modify the state of a block if it + /// is no longer the same type as it was when this state was taken. It will + /// return false in this eventuality. + /// + /// If force is true, it will set the type of the block to match the new + /// state, set the state data and then return true. + /// + /// If applyPhysics is true, it will trigger a physics update on + /// surrounding blocks which could cause them to update or disappear. + pub fn update( + &self, + force: std::option::Option, + apply_physics: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = force { + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_1); + } + if let Some(a) = apply_physics { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "update", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + + pub fn raw_data(&self) -> Result> { + let sig = String::from("()B"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getCookTime", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getRawData", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.s()?) + Ok(res.b()?) } - /// Set cook time. - /// This is the amount of time the item has been cooking for. - pub fn set_cook_time(&self, cook_time: i16) -> Result<(), Box> { - let sig = String::from("(S)V"); - let val_1 = jni::objects::JValueGen::Short(cook_time); + #[deprecated] + + pub fn set_raw_data(&self, data: i8) -> Result<(), Box> { + let sig = String::from("(B)V"); + let val_1 = jni::objects::JValueGen::Byte(data); let res = self.jni_ref().call_method( &self.jni_object(), - "setCookTime", + "setRawData", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get cook time total. - /// This is the amount of time the item is required to cook for. - pub fn cook_time_total(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCookTimeTotal", - sig.as_str(), - vec![], - ); + /// Returns whether this state is placed in the world. + /// + /// Some methods will not work if the block state isn't + /// placed in the world. + pub fn is_placed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isPlaced", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set cook time. - /// This is the amount of time the item is required to cook for. - pub fn set_cook_time_total( + /// Sets a metadata value in the implementing object's metadata store. + pub fn set_metadata( &self, - cook_time_total: i32, + metadata_key: impl Into, + new_metadata_value: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(cook_time_total); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCookTimeTotal", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += "Lorg/bukkit/metadata/MetadataValue;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) + }); + args.push(val_2); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setMetadata", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the recipes used in this furnace. - /// Note: These recipes used are reset when the result item is - /// manually taken from the furnace. - pub fn recipes_used( + /// Returns a list of previously set metadata values from the implementing + /// object's metadata store. + pub fn get_metadata( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRecipesUsed", sig.as_str(), vec![]); + metadata_key: impl Into, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += ")Ljava/util/List;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getMetadata", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::metadata::MetadataValue::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(new_vec) } - - pub fn inventory( + /// Tests to see whether the implementing object contains the given + /// metadata value in its metadata store. + pub fn has_metadata( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/FurnaceInventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + metadata_key: impl Into, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasMetadata", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::inventory::FurnaceInventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - - pub fn snapshot_inventory( + /// Removes the given metadata value from the implementing object's + /// metadata store. + pub fn remove_metadata( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/FurnaceInventory;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSnapshotInventory", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::FurnaceInventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + metadata_key: impl Into, + owning_plugin: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += "Lorg/bukkit/plugin/Plugin;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + }); + args.push(val_2); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "removeMetadata", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlastFurnace<'mc> { - fn into(self) -> crate::block::Furnace<'mc> { - crate::block::Furnace::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlastFurnace into crate::block::Furnace") +impl<'mc> Into> for Jigsaw<'mc> { + fn into(self) -> crate::block::TileState<'mc> { + crate::block::TileState::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Jigsaw into crate::block::TileState") } } #[repr(C)] -pub struct TileState<'mc>( +pub struct DoubleChest<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for TileState<'mc> { +impl<'mc> JNIRaw<'mc> for DoubleChest<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6648,18 +7961,18 @@ impl<'mc> JNIRaw<'mc> for TileState<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for TileState<'mc> { +impl<'mc> JNIInstantiatable<'mc> for DoubleChest<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate TileState from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate DoubleChest from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/TileState")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/DoubleChest")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a TileState object, got {}", + "Invalid argument passed. Expected a DoubleChest object, got {}", name ) .into()) @@ -6669,310 +7982,530 @@ impl<'mc> JNIInstantiatable<'mc> for TileState<'mc> { } } -impl<'mc> TileState<'mc> { - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - /// - /// This {@link PersistentDataHolder} is only linked to the snapshot instance - /// stored by the {@link BlockState}. - /// When storing changes on the {@link PersistentDataHolder}, the updated - /// content will only be applied to the actual tile entity after one of the - /// {@link #update()} methods is called. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPersistentDataContainer", +impl<'mc> DoubleChest<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + chest: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/DoubleChestInventory;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(chest.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/block/DoubleChest"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the block represented by this block state. - pub fn block(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the metadata for this block state. - pub fn data(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/MaterialData;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let res = jni.translate_error_no_gen(res)?; + crate::block::DoubleChest::from_raw(&jni, res) } - /// Gets the data for this block state. - pub fn block_data( + + pub fn inventory( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBlockData", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Copies the state to another block as an unplaced BlockState. - pub fn copy( + + pub fn left_side( &self, - location: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = location { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")Lorg/bukkit/block/BlockState;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/InventoryHolder;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLeftSide", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::InventoryHolder::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets the type of this block state. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + + pub fn right_side( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/InventoryHolder;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRightSide", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::InventoryHolder::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets the current light level of the block represented by this block state. - pub fn light_level(&self) -> Result> { - let sig = String::from("()B"); + + pub fn location(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLightLevel", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) + crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the world which contains the block represented by this block state. - pub fn world(&self) -> Result, Box> { + + pub fn world(&self) -> Result>, Box> { let sig = String::from("()Lorg/bukkit/World;"); let res = self .jni_ref() .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::World::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) + })?)) } - /// Gets the x-coordinate of this block state. - pub fn x(&self) -> Result> { - let sig = String::from("()I"); + + pub fn x(&self) -> Result> { + let sig = String::from("()D"); let res = self .jni_ref() .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.d()?) } - /// Gets the y-coordinate of this block state. - pub fn y(&self) -> Result> { - let sig = String::from("()I"); + + pub fn y(&self) -> Result> { + let sig = String::from("()D"); let res = self .jni_ref() .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.d()?) } - /// Gets the z-coordinate of this block state. - pub fn z(&self) -> Result> { - let sig = String::from("()I"); + + pub fn z(&self) -> Result> { + let sig = String::from("()D"); let res = self .jni_ref() .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.d()?) } - /// Stores the location of this block state in the provided Location object. - /// - /// If the provided Location is null this method does nothing and returns - /// null. - /// - /// If this block state is not placed the location's world will be null! - pub fn get_location( - &self, - loc: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLocation", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Gets the chunk which contains the block represented by this block state. - pub fn chunk(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Chunk;"); +} +impl<'mc> Into> for DoubleChest<'mc> { + fn into(self) -> crate::inventory::InventoryHolder<'mc> { + crate::inventory::InventoryHolder::from_raw(&self.jni_ref(), self.1) + .expect("Error converting DoubleChest into crate::inventory::InventoryHolder") + } +} +#[repr(C)] +pub struct Lectern<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Lectern<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Lectern<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Lectern from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Lectern")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Lectern object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Lectern<'mc> { + /// Get the current lectern page. + pub fn page(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getChunk", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Chunk::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Sets the metadata for this block state. - pub fn set_data( - &self, - data: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/material/MaterialData;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) - }); + /// Set the current lectern page. + /// If the page is greater than the number of pages of the book currently in + /// the inventory, then behavior is undefined. + pub fn set_page(&self, page: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(page); let res = self.jni_ref().call_method( &self.jni_object(), - "setData", + "setPage", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets the data for this block state. - pub fn set_block_data( + + pub fn inventory( &self, - data: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) - }); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn snapshot_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setBlockData", + "getSnapshotInventory", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the type of this block state. - pub fn set_type( + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + /// + /// This {@link PersistentDataHolder} is only linked to the snapshot instance + /// stored by the {@link BlockState}. + /// When storing changes on the {@link PersistentDataHolder}, the updated + /// content will only be applied to the actual tile entity after one of the + /// {@link #update()} methods is called. + pub fn persistent_data_container( &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Material;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setType", + "getPersistentDataContainer", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Attempts to update the block represented by this state, setting it to - /// the new values as defined by this state. - /// - /// If this state is not placed, this will have no effect and return true. - /// - /// Unless force is true, this will not modify the state of a block if it - /// is no longer the same type as it was when this state was taken. It will - /// return false in this eventuality. - /// - /// If force is true, it will set the type of the block to match the new - /// state, set the state data and then return true. - /// - /// If applyPhysics is true, it will trigger a physics update on - /// surrounding blocks which could cause them to update or disappear. - pub fn update( + /// Gets the block associated with this holder. + pub fn block(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/block/Block;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBlock", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the metadata for this block state. + pub fn data(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/MaterialData;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the data for this block state. + pub fn block_data( &self, - force: std::option::Option, - apply_physics: std::option::Option, - ) -> Result> { + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBlockData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Copies the state to another block as an unplaced BlockState. + pub fn copy( + &self, + location: std::option::Option>>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = force { - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(a.into()); + if let Some(a) = location { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); args.push(val_1); } - if let Some(a) = apply_physics { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")Z"; + sig += ")Lorg/bukkit/block/BlockState;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "update", sig.as_str(), args); + .call_method(&self.jni_object(), "copy", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - - pub fn raw_data(&self) -> Result> { + /// Gets the type of this block state. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the current light level of the block represented by this block state. + pub fn light_level(&self) -> Result> { let sig = String::from("()B"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getRawData", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLightLevel", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.b()?) } - #[deprecated] - - pub fn set_raw_data(&self, data: i8) -> Result<(), Box> { - let sig = String::from("(B)V"); - let val_1 = jni::objects::JValueGen::Byte(data); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRawData", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns whether this state is placed in the world. - /// - /// Some methods will not work if the block state isn't - /// placed in the world. - pub fn is_placed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self + /// Gets the world which contains the block represented by this block state. + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the x-coordinate of this block state. + pub fn x(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the y-coordinate of this block state. + pub fn y(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the z-coordinate of this block state. + pub fn z(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Stores the location of this block state in the provided Location object. + /// + /// If the provided Location is null this method does nothing and returns + /// null. + /// + /// If this block state is not placed the location's world will be null! + pub fn get_location( + &self, + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLocation", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Gets the chunk which contains the block represented by this block state. + pub fn chunk(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Chunk;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getChunk", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Chunk::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the metadata for this block state. + pub fn set_data( + &self, + data: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/material/MaterialData;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(data.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setData", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets the data for this block state. + pub fn set_block_data( + &self, + data: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(data.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBlockData", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets the type of this block state. + pub fn set_type( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Material;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Attempts to update the block represented by this state, setting it to + /// the new values as defined by this state. + /// + /// If this state is not placed, this will have no effect and return true. + /// + /// Unless force is true, this will not modify the state of a block if it + /// is no longer the same type as it was when this state was taken. It will + /// return false in this eventuality. + /// + /// If force is true, it will set the type of the block to match the new + /// state, set the state data and then return true. + /// + /// If applyPhysics is true, it will trigger a physics update on + /// surrounding blocks which could cause them to update or disappear. + pub fn update( + &self, + force: std::option::Option, + apply_physics: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = force { + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_1); + } + if let Some(a) = apply_physics { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "update", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + + pub fn raw_data(&self) -> Result> { + let sig = String::from("()B"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRawData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.b()?) + } + #[deprecated] + + pub fn set_raw_data(&self, data: i8) -> Result<(), Box> { + let sig = String::from("(B)V"); + let val_1 = jni::objects::JValueGen::Byte(data); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRawData", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns whether this state is placed in the world. + /// + /// Some methods will not work if the block state isn't + /// placed in the world. + pub fn is_placed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self .jni_ref() .call_method(&self.jni_object(), "isPlaced", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; @@ -7085,25 +8618,25 @@ impl<'mc> TileState<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for TileState<'mc> { - fn into(self) -> crate::block::BlockState<'mc> { - crate::block::BlockState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting TileState into crate::block::BlockState") +impl<'mc> Into> for Lectern<'mc> { + fn into(self) -> crate::block::TileState<'mc> { + crate::block::TileState::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Lectern into crate::block::TileState") } } -impl<'mc> Into> for TileState<'mc> { - fn into(self) -> crate::persistence::PersistentDataHolder<'mc> { - crate::persistence::PersistentDataHolder::from_raw(&self.jni_ref(), self.1) - .expect("Error converting TileState into crate::persistence::PersistentDataHolder") +impl<'mc> Into> for Lectern<'mc> { + fn into(self) -> crate::inventory::BlockInventoryHolder<'mc> { + crate::inventory::BlockInventoryHolder::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Lectern into crate::inventory::BlockInventoryHolder") } } #[repr(C)] -pub struct Jigsaw<'mc>( +pub struct CalibratedSculkSensor<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Jigsaw<'mc> { +impl<'mc> JNIRaw<'mc> for CalibratedSculkSensor<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -7111,18 +8644,21 @@ impl<'mc> JNIRaw<'mc> for Jigsaw<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Jigsaw<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CalibratedSculkSensor<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Jigsaw from null object.").into()); + return Err(eyre::eyre!( + "Tried to instantiate CalibratedSculkSensor from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Jigsaw")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/CalibratedSculkSensor")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Jigsaw object, got {}", + "Invalid argument passed. Expected a CalibratedSculkSensor object, got {}", name ) .into()) @@ -7132,38 +8668,145 @@ impl<'mc> JNIInstantiatable<'mc> for Jigsaw<'mc> { } } -impl<'mc> Jigsaw<'mc> { - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - /// - /// This {@link PersistentDataHolder} is only linked to the snapshot instance - /// stored by the {@link BlockState}. - /// When storing changes on the {@link PersistentDataHolder}, the updated - /// content will only be applied to the actual tile entity after one of the - /// {@link #update()} methods is called. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); +impl<'mc> CalibratedSculkSensor<'mc> { + /// Gets the last vibration frequency of this sensor. + /// Different activities detected by the sensor will produce different + /// frequencies and dictate the output of connected comparators. + pub fn last_vibration_frequency(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "getLastVibrationFrequency", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) + Ok(res.i()?) + } + /// Sets the last vibration frequency of this sensor. + /// Different activities detected by the sensor will produce different + /// frequencies and dictate the output of connected comparators. + pub fn set_last_vibration_frequency( + &self, + last_vibration_frequency: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(last_vibration_frequency); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLastVibrationFrequency", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + /// + /// This {@link PersistentDataHolder} is only linked to the snapshot instance + /// stored by the {@link BlockState}. + /// When storing changes on the {@link PersistentDataHolder}, the updated + /// content will only be applied to the actual tile entity after one of the + /// {@link #update()} methods is called. + pub fn persistent_data_container( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPersistentDataContainer", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for CalibratedSculkSensor<'mc> { + fn into(self) -> crate::block::SculkSensor<'mc> { + crate::block::SculkSensor::from_raw(&self.jni_ref(), self.1) + .expect("Error converting CalibratedSculkSensor into crate::block::SculkSensor") + } +} +#[repr(C)] +pub struct Comparator<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Comparator<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Comparator<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Comparator from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Comparator")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Comparator object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Comparator<'mc> { + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + /// + /// This {@link PersistentDataHolder} is only linked to the snapshot instance + /// stored by the {@link BlockState}. + /// When storing changes on the {@link PersistentDataHolder}, the updated + /// content will only be applied to the actual tile entity after one of the + /// {@link #update()} methods is called. + pub fn persistent_data_container( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPersistentDataContainer", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) }) } /// Gets the block represented by this block state. pub fn block(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/block/Block;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBlock", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; crate::block::Block::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) @@ -7548,19 +9191,19 @@ impl<'mc> Jigsaw<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Jigsaw<'mc> { +impl<'mc> Into> for Comparator<'mc> { fn into(self) -> crate::block::TileState<'mc> { crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Jigsaw into crate::block::TileState") + .expect("Error converting Comparator into crate::block::TileState") } } #[repr(C)] -pub struct DoubleChest<'mc>( +pub struct Bell<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for DoubleChest<'mc> { +impl<'mc> JNIRaw<'mc> for Bell<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -7568,18 +9211,18 @@ impl<'mc> JNIRaw<'mc> for DoubleChest<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for DoubleChest<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Bell<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate DoubleChest from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Bell from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/DoubleChest")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Bell")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a DoubleChest object, got {}", + "Invalid argument passed. Expected a Bell object, got {}", name ) .into()) @@ -7589,224 +9232,87 @@ impl<'mc> JNIInstantiatable<'mc> for DoubleChest<'mc> { } } -impl<'mc> DoubleChest<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - chest: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/DoubleChestInventory;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(chest.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/block/DoubleChest"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error_no_gen(res)?; - crate::block::DoubleChest::from_raw(&jni, res) - } - - pub fn inventory( +impl<'mc> Bell<'mc> { + /// Ring this bell. This will call a {@link BellRingEvent}. + pub fn ring( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + entity: std::option::Option>>, + direction: std::option::Option>>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = entity { + sig += "Lorg/bukkit/entity/Entity;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + if let Some(a) = direction { + sig += "Lorg/bukkit/block/BlockFace;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "ring", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - - pub fn left_side( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/InventoryHolder;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLeftSide", sig.as_str(), vec![]); + /// Check whether or not this bell is shaking. A bell is considered to be + /// shaking if it was recently rung. + /// + /// A bell will typically shake for 50 ticks. + pub fn is_shaking(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isShaking", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::InventoryHolder::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - - pub fn right_side( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/InventoryHolder;"); + /// Get the amount of ticks since this bell has been shaking, or 0 if the + /// bell is not currently shaking. + /// + /// A bell will typically shake for 50 ticks. + pub fn shaking_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getRightSide", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getShakingTicks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::InventoryHolder::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - - pub fn location(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); + /// Check whether or not this bell is resonating. A bell is considered to be + /// resonating if {@link #isShaking() while shaking}, raiders were detected + /// in the area and are ready to be highlighted to nearby players. + /// + /// A bell will typically resonate for 40 ticks. + pub fn is_resonating(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isResonating", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - - pub fn world(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::World::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - - pub fn x(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - - pub fn y(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - - pub fn z(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for DoubleChest<'mc> { - fn into(self) -> crate::inventory::InventoryHolder<'mc> { - crate::inventory::InventoryHolder::from_raw(&self.jni_ref(), self.1) - .expect("Error converting DoubleChest into crate::inventory::InventoryHolder") - } -} -#[repr(C)] -pub struct Lectern<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Lectern<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Lectern<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Lectern from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Lectern")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Lectern object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Lectern<'mc> { - /// Get the current lectern page. - pub fn page(&self) -> Result> { + /// Get the amount of ticks since this bell has been resonating, or 0 if the + /// bell is not currently resonating. + /// + /// A bell will typically resonate for 40 ticks. + pub fn resonating_ticks(&self) -> Result> { let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPage", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the current lectern page. - /// If the page is greater than the number of pages of the book currently in - /// the inventory, then behavior is undefined. - pub fn set_page(&self, page: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(page); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPage", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn snapshot_inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getSnapshotInventory", + "getResonatingTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } /// Returns a custom tag container capable of storing tags on the object. /// Note that the tags stored on this container are all stored under their @@ -7833,7 +9339,7 @@ impl<'mc> Lectern<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the block associated with this holder. + /// Gets the block represented by this block state. pub fn block(&self) -> Result, Box> { let args = Vec::new(); let mut sig = String::from("("); @@ -8225,25 +9731,19 @@ impl<'mc> Lectern<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Lectern<'mc> { +impl<'mc> Into> for Bell<'mc> { fn into(self) -> crate::block::TileState<'mc> { crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Lectern into crate::block::TileState") - } -} -impl<'mc> Into> for Lectern<'mc> { - fn into(self) -> crate::inventory::BlockInventoryHolder<'mc> { - crate::inventory::BlockInventoryHolder::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Lectern into crate::inventory::BlockInventoryHolder") + .expect("Error converting Bell into crate::block::TileState") } } #[repr(C)] -pub struct CalibratedSculkSensor<'mc>( +pub struct SculkCatalyst<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for CalibratedSculkSensor<'mc> { +impl<'mc> JNIRaw<'mc> for SculkCatalyst<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -8251,21 +9751,18 @@ impl<'mc> JNIRaw<'mc> for CalibratedSculkSensor<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for CalibratedSculkSensor<'mc> { +impl<'mc> JNIInstantiatable<'mc> for SculkCatalyst<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate CalibratedSculkSensor from null object." - ) - .into()); + return Err(eyre::eyre!("Tried to instantiate SculkCatalyst from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/CalibratedSculkSensor")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/SculkCatalyst")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a CalibratedSculkSensor object, got {}", + "Invalid argument passed. Expected a SculkCatalyst object, got {}", name ) .into()) @@ -8275,35 +9772,35 @@ impl<'mc> JNIInstantiatable<'mc> for CalibratedSculkSensor<'mc> { } } -impl<'mc> CalibratedSculkSensor<'mc> { - /// Gets the last vibration frequency of this sensor. - /// Different activities detected by the sensor will produce different - /// frequencies and dictate the output of connected comparators. - pub fn last_vibration_frequency(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLastVibrationFrequency", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the last vibration frequency of this sensor. - /// Different activities detected by the sensor will produce different - /// frequencies and dictate the output of connected comparators. - pub fn set_last_vibration_frequency( +impl<'mc> SculkCatalyst<'mc> { + /// Causes a new sculk bloom, as if an entity just died around this catalyst. + /// + /// Typically, charges should be set to the exp reward of a mob + /// ({@link EntityDeathEvent#getDroppedExp()}), which is usually + /// 3-5 for animals, and 5-10 for the average mob (up to 50 for + /// wither skeletons). Roughly speaking, for each charge, 1 more + /// sculk block will be placed. + /// + /// If charges > 1000, multiple cursors will be spawned in the + /// block. + pub fn bloom( &self, - last_vibration_frequency: i32, + block: impl Into>, + charges: i32, ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(last_vibration_frequency); + let sig = String::from("(Lorg/bukkit/block/Block;I)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(block.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(charges); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastVibrationFrequency", + "bloom", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) @@ -8333,102 +9830,29 @@ impl<'mc> CalibratedSculkSensor<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + /// Gets the block represented by this block state. + pub fn block(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/block/Block;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBlock", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> Into> for CalibratedSculkSensor<'mc> { - fn into(self) -> crate::block::SculkSensor<'mc> { - crate::block::SculkSensor::from_raw(&self.jni_ref(), self.1) - .expect("Error converting CalibratedSculkSensor into crate::block::SculkSensor") - } -} -#[repr(C)] -pub struct Comparator<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Comparator<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Comparator<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Comparator from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Comparator")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Comparator object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Comparator<'mc> { - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - /// - /// This {@link PersistentDataHolder} is only linked to the snapshot instance - /// stored by the {@link BlockState}. - /// When storing changes on the {@link PersistentDataHolder}, the updated - /// content will only be applied to the actual tile entity after one of the - /// {@link #update()} methods is called. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPersistentDataContainer", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the block represented by this block state. - pub fn block(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/block/Block;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBlock", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the metadata for this block state. - pub fn data(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/MaterialData;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Gets the metadata for this block state. + pub fn data(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/MaterialData;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } /// Gets the data for this block state. pub fn block_data( @@ -8798,19 +10222,19 @@ impl<'mc> Comparator<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Comparator<'mc> { +impl<'mc> Into> for SculkCatalyst<'mc> { fn into(self) -> crate::block::TileState<'mc> { crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Comparator into crate::block::TileState") + .expect("Error converting SculkCatalyst into crate::block::TileState") } } #[repr(C)] -pub struct Bell<'mc>( +pub struct Sign<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Bell<'mc> { +impl<'mc> JNIRaw<'mc> for Sign<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -8818,18 +10242,18 @@ impl<'mc> JNIRaw<'mc> for Bell<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Bell<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Sign<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Bell from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Sign from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Bell")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Sign")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Bell object, got {}", + "Invalid argument passed. Expected a Sign object, got {}", name ) .into()) @@ -8839,113 +10263,253 @@ impl<'mc> JNIInstantiatable<'mc> for Bell<'mc> { } } -impl<'mc> Bell<'mc> { - /// Ring this bell. This will call a {@link BellRingEvent}. - pub fn ring( - &self, - entity: std::option::Option>>, - direction: std::option::Option>>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = entity { - sig += "Lorg/bukkit/entity/Entity;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - if let Some(a) = direction { - sig += "Lorg/bukkit/block/BlockFace;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Z"; +impl<'mc> Sign<'mc> { + #[deprecated] + /// Gets all the lines of text currently on the {@link Side#FRONT} of this sign. + pub fn lines(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "ring", sig.as_str(), args); + .call_method(&self.jni_object(), "getLines", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Check whether or not this bell is shaking. A bell is considered to be - /// shaking if it was recently rung. - /// - /// A bell will typically shake for 50 ticks. - pub fn is_shaking(&self) -> Result> { - let sig = String::from("()Z"); - let res = self + Ok(self .jni_ref() - .call_method(&self.jni_object(), "isShaking", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Get the amount of ticks since this bell has been shaking, or 0 if the - /// bell is not currently shaking. - /// - /// A bell will typically shake for 50 ticks. - pub fn shaking_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getShakingTicks", sig.as_str(), vec![]); + #[deprecated] + /// Gets the line of text at the specified index.For example, getLine(0) will return the first line of text on the {@link Side#FRONT}. + pub fn get_line(&self, index: i32) -> Result> { + let sig = String::from("(I)Ljava/lang/String;"); + let val_1 = jni::objects::JValueGen::Int(index); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLine", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Check whether or not this bell is resonating. A bell is considered to be - /// resonating if {@link #isShaking() while shaking}, raiders were detected - /// in the area and are ready to be highlighted to nearby players. - /// - /// A bell will typically resonate for 40 ticks. - pub fn is_resonating(&self) -> Result> { + #[deprecated] + /// Sets the line of text at the specified index.For example, setLine(0, "Line One") will set the first line of text to "Line One". + pub fn set_line( + &self, + index: i32, + line: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(ILjava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Int(index); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(line.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLine", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Marks whether this sign can be edited by players. + pub fn is_editable(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isResonating", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isEditable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get the amount of ticks since this bell has been resonating, or 0 if the - /// bell is not currently resonating. - /// - /// A bell will typically resonate for 40 ticks. - pub fn resonating_ticks(&self) -> Result> { - let sig = String::from("()I"); + #[deprecated] + /// Marks whether this sign can be edited by players. + pub fn set_editable(&self, editable: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(editable.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getResonatingTicks", + "setEditable", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether or not this sign has been waxed. If a sign has been waxed, it + /// cannot be edited by a player. + pub fn is_waxed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isWaxed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - /// - /// This {@link PersistentDataHolder} is only linked to the snapshot instance - /// stored by the {@link BlockState}. - /// When storing changes on the {@link PersistentDataHolder}, the updated - /// content will only be applied to the actual tile entity after one of the - /// {@link #update()} methods is called. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + /// Sets whether or not this sign has been waxed. If a sign has been waxed, it + /// cannot be edited by a player. + pub fn set_waxed(&self, waxed: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(waxed.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "setWaxed", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets whether this sign has glowing text. Only affects the {@link Side#FRONT}. + pub fn is_glowing_text(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isGlowingText", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Sets whether this sign has glowing text. Only affects the {@link Side#FRONT}. + pub fn set_glowing_text(&self, glowing: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(glowing.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setGlowingText", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// {@inheritDoc} + pub fn color(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/DyeColor;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::DyeColor::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + #[deprecated] + /// {@inheritDoc} + pub fn set_color( + &self, + color: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/DyeColor;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(color.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setColor", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Return the side of the sign. + pub fn get_side( + &self, + side: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/block/sign/Side;)Lorg/bukkit/block/sign/SignSide;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(side.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSide", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::block::sign::SignSide::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the side of this sign the given player is currently standing on. + pub fn get_target_side( + &self, + player: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/Player;)Lorg/bukkit/block/sign/SignSide;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(player.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTargetSide", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::block::sign::SignSide::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the player that is currently allowed to edit this sign. + /// + /// Edits from other players will be rejected if this value is not null. + pub fn allowed_editor( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAllowedEditor", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Player::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + /// + /// This {@link PersistentDataHolder} is only linked to the snapshot instance + /// stored by the {@link BlockState}. + /// When storing changes on the {@link PersistentDataHolder}, the updated + /// content will only be applied to the actual tile entity after one of the + /// {@link #update()} methods is called. + pub fn persistent_data_container( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPersistentDataContainer", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } /// Gets the block represented by this block state. pub fn block(&self) -> Result, Box> { let args = Vec::new(); @@ -9338,19 +10902,25 @@ impl<'mc> Bell<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Bell<'mc> { +impl<'mc> Into> for Sign<'mc> { fn into(self) -> crate::block::TileState<'mc> { crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Bell into crate::block::TileState") + .expect("Error converting Sign into crate::block::TileState") + } +} +impl<'mc> Into> for Sign<'mc> { + fn into(self) -> crate::material::Colorable<'mc> { + crate::material::Colorable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Sign into crate::material::Colorable") } } #[repr(C)] -pub struct SculkCatalyst<'mc>( +pub struct DecoratedPot<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for SculkCatalyst<'mc> { +impl<'mc> JNIRaw<'mc> for DecoratedPot<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -9358,18 +10928,18 @@ impl<'mc> JNIRaw<'mc> for SculkCatalyst<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for SculkCatalyst<'mc> { +impl<'mc> JNIInstantiatable<'mc> for DecoratedPot<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate SculkCatalyst from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate DecoratedPot from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/SculkCatalyst")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/DecoratedPot")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SculkCatalyst object, got {}", + "Invalid argument passed. Expected a DecoratedPot object, got {}", name ) .into()) @@ -9379,30 +10949,23 @@ impl<'mc> JNIInstantiatable<'mc> for SculkCatalyst<'mc> { } } -impl<'mc> SculkCatalyst<'mc> { - /// Causes a new sculk bloom, as if an entity just died around this catalyst. - /// - /// Typically, charges should be set to the exp reward of a mob - /// ({@link EntityDeathEvent#getDroppedExp()}), which is usually - /// 3-5 for animals, and 5-10 for the average mob (up to 50 for - /// wither skeletons). Roughly speaking, for each charge, 1 more - /// sculk block will be placed. - /// - /// If charges > 1000, multiple cursors will be spawned in the - /// block. - pub fn bloom( +impl<'mc> DecoratedPot<'mc> { + /// Set the sherd on the provided side. + pub fn set_sherd( &self, - block: impl Into>, - charges: i32, + side: impl Into>, + sherd: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/Block;I)V"); + let sig = String::from("(Lorg/bukkit/block/DecoratedPot/Side;Lorg/bukkit/Material;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) + jni::objects::JObject::from_raw(side.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sherd.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(charges); let res = self.jni_ref().call_method( &self.jni_object(), - "bloom", + "setSherd", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), @@ -9412,59 +10975,140 @@ impl<'mc> SculkCatalyst<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - /// - /// This {@link PersistentDataHolder} is only linked to the snapshot instance - /// stored by the {@link BlockState}. - /// When storing changes on the {@link PersistentDataHolder}, the updated - /// content will only be applied to the actual tile entity after one of the - /// {@link #update()} methods is called. - pub fn persistent_data_container( + /// Get the sherd on the provided side. + pub fn get_sherd( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + side: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/block/DecoratedPot/Side;)Lorg/bukkit/Material;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(side.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "getSherd", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + crate::Material::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the block represented by this block state. - pub fn block(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/block/Block;"; + /// Gets a Map of all sides on this decorated pot and the sherds on them. + /// If a side does not have a specific sherd on it, {@link Material#BRICK} + /// will be the value of that side. + pub fn sherds( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Map;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getBlock", sig.as_str(), args); + .call_method(&self.jni_object(), "getSherds", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the metadata for this block state. - pub fn data(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/MaterialData;"); + #[deprecated] + /// Gets the sherds on this decorated pot. For faces without a specific sherd, {@link Material#BRICK} is used in its place. + pub fn shards(&self) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getShards", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the data for this block state. - pub fn block_data( - &self, - ) -> Result, Box> { + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::Material::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/DecoratedPotInventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::DecoratedPotInventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn snapshot_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/DecoratedPotInventory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSnapshotInventory", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::DecoratedPotInventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + /// + /// This {@link PersistentDataHolder} is only linked to the snapshot instance + /// stored by the {@link BlockState}. + /// When storing changes on the {@link PersistentDataHolder}, the updated + /// content will only be applied to the actual tile entity after one of the + /// {@link #update()} methods is called. + pub fn persistent_data_container( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPersistentDataContainer", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the block associated with this holder. + pub fn block(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/block/Block;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBlock", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the metadata for this block state. + pub fn data(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/MaterialData;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the data for this block state. + pub fn block_data( + &self, + ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); let res = self.jni_ref() @@ -9829,19 +11473,155 @@ impl<'mc> SculkCatalyst<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for SculkCatalyst<'mc> { +impl<'mc> Into> for DecoratedPot<'mc> { fn into(self) -> crate::block::TileState<'mc> { crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SculkCatalyst into crate::block::TileState") + .expect("Error converting DecoratedPot into crate::block::TileState") + } +} +impl<'mc> Into> for DecoratedPot<'mc> { + fn into(self) -> crate::inventory::BlockInventoryHolder<'mc> { + crate::inventory::BlockInventoryHolder::from_raw(&self.jni_ref(), self.1) + .expect("Error converting DecoratedPot into crate::inventory::BlockInventoryHolder") + } +} +pub enum DecoratedPotSide<'mc> { + Back { inner: DecoratedPotSideStruct<'mc> }, + Left { inner: DecoratedPotSideStruct<'mc> }, + Right { inner: DecoratedPotSideStruct<'mc> }, + Front { inner: DecoratedPotSideStruct<'mc> }, +} +impl<'mc> std::fmt::Display for DecoratedPotSide<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + DecoratedPotSide::Back { .. } => f.write_str("BACK"), + DecoratedPotSide::Left { .. } => f.write_str("LEFT"), + DecoratedPotSide::Right { .. } => f.write_str("RIGHT"), + DecoratedPotSide::Front { .. } => f.write_str("FRONT"), + } + } +} +impl<'mc> std::ops::Deref for DecoratedPotSide<'mc> { + type Target = DecoratedPotSideStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + DecoratedPotSide::Back { inner } => inner, + DecoratedPotSide::Left { inner } => inner, + DecoratedPotSide::Right { inner } => inner, + DecoratedPotSide::Front { inner } => inner, + } + } +} + +impl<'mc> DecoratedPotSide<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/block/DecoratedPot/Side"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/block/DecoratedPot/Side;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "BACK" => Ok(DecoratedPotSide::Back { + inner: DecoratedPotSideStruct::from_raw(env, obj)?, + }), + "LEFT" => Ok(DecoratedPotSide::Left { + inner: DecoratedPotSideStruct::from_raw(env, obj)?, + }), + "RIGHT" => Ok(DecoratedPotSide::Right { + inner: DecoratedPotSideStruct::from_raw(env, obj)?, + }), + "FRONT" => Ok(DecoratedPotSide::Front { + inner: DecoratedPotSideStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } + #[repr(C)] -pub struct Sign<'mc>( +pub struct DecoratedPotSideStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Sign<'mc> { +impl<'mc> JNIRaw<'mc> for DecoratedPotSide<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Back { inner } => inner.0.clone(), + Self::Left { inner } => inner.0.clone(), + Self::Right { inner } => inner.0.clone(), + Self::Front { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Back { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Left { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Right { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Front { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for DecoratedPotSide<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate DecoratedPotSide from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/DecoratedPot/Side")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a DecoratedPotSide object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "BACK" => Ok(DecoratedPotSide::Back { + inner: DecoratedPotSideStruct::from_raw(env, obj)?, + }), + "LEFT" => Ok(DecoratedPotSide::Left { + inner: DecoratedPotSideStruct::from_raw(env, obj)?, + }), + "RIGHT" => Ok(DecoratedPotSide::Right { + inner: DecoratedPotSideStruct::from_raw(env, obj)?, + }), + "FRONT" => Ok(DecoratedPotSide::Front { + inner: DecoratedPotSideStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for DecoratedPotSideStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -9849,18 +11629,21 @@ impl<'mc> JNIRaw<'mc> for Sign<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Sign<'mc> { +impl<'mc> JNIInstantiatable<'mc> for DecoratedPotSideStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Sign from null object.").into()); + return Err(eyre::eyre!( + "Tried to instantiate DecoratedPotSideStruct from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Sign")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/DecoratedPot/Side")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Sign object, got {}", + "Invalid argument passed. Expected a DecoratedPotSideStruct object, got {}", name ) .into()) @@ -9870,228 +11653,104 @@ impl<'mc> JNIInstantiatable<'mc> for Sign<'mc> { } } -impl<'mc> Sign<'mc> { - #[deprecated] - /// Gets all the lines of text currently on the {@link Side#FRONT} of this sign. - pub fn lines(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getLines", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) +impl<'mc> DecoratedPotSideStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/DecoratedPot/Side;"); + let cls = jni.find_class("org/bukkit/block/DecoratedPot/Side"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::block::DecoratedPotSide::from_raw(&jni, obj) } - #[deprecated] - /// Gets the line of text at the specified index.For example, getLine(0) will return the first line of text on the {@link Side#FRONT}. - pub fn get_line(&self, index: i32) -> Result> { - let sig = String::from("(I)Ljava/lang/String;"); - let val_1 = jni::objects::JValueGen::Int(index); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLine", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - #[deprecated] - /// Sets the line of text at the specified index.For example, setLine(0, "Line One") will set the first line of text to "Line One". - pub fn set_line( - &self, - index: i32, - line: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(ILjava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Int(index); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(line.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLine", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Marks whether this sign can be edited by players. - pub fn is_editable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isEditable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Marks whether this sign can be edited by players. - pub fn set_editable(&self, editable: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(editable.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setEditable", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +} +#[repr(C)] +pub struct SculkShrieker<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for SculkShrieker<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Gets whether or not this sign has been waxed. If a sign has been waxed, it - /// cannot be edited by a player. - pub fn is_waxed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isWaxed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Sets whether or not this sign has been waxed. If a sign has been waxed, it - /// cannot be edited by a player. - pub fn set_waxed(&self, waxed: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(waxed.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setWaxed", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +} +impl<'mc> JNIInstantiatable<'mc> for SculkShrieker<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate SculkShrieker from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/SculkShrieker")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a SculkShrieker object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } - #[deprecated] - /// Gets whether this sign has glowing text. Only affects the {@link Side#FRONT}. - pub fn is_glowing_text(&self) -> Result> { - let sig = String::from("()Z"); +} + +impl<'mc> SculkShrieker<'mc> { + /// Gets the most recent warning level of this block. + /// When the warning level reaches 4, the shrieker will attempt to spawn a + /// Warden. + pub fn warning_level(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isGlowingText", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getWarningLevel", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - #[deprecated] - /// Sets whether this sign has glowing text. Only affects the {@link Side#FRONT}. - pub fn set_glowing_text(&self, glowing: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(glowing.into()); + /// Sets the most recent warning level of this block. + /// When the warning level reaches 4, the shrieker will attempt to spawn a + /// Warden. + pub fn set_warning_level(&self, level: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(level); let res = self.jni_ref().call_method( &self.jni_object(), - "setGlowingText", + "setWarningLevel", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// {@inheritDoc} - pub fn color(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/DyeColor;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::DyeColor::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - #[deprecated] - /// {@inheritDoc} - pub fn set_color( + /// Simulates a player causing a vibration. + pub fn try_shriek( &self, - color: impl Into>, + player: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/DyeColor;)V"); + let sig = String::from("(Lorg/bukkit/entity/Player;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) + jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setColor", + "tryShriek", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Return the side of the sign. - pub fn get_side( - &self, - side: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/block/sign/Side;)Lorg/bukkit/block/sign/SignSide;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(side.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSide", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::block::sign::SignSide::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the side of this sign the given player is currently standing on. - pub fn get_target_side( - &self, - player: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Player;)Lorg/bukkit/block/sign/SignSide;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTargetSide", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::block::sign::SignSide::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the player that is currently allowed to edit this sign. - /// - /// Edits from other players will be rejected if this value is not null. - pub fn allowed_editor( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Player;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAllowedEditor", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Player::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } /// Returns a custom tag container capable of storing tags on the object. /// Note that the tags stored on this container are all stored under their /// own custom namespace therefore modifying default tags using this @@ -10509,25 +12168,19 @@ impl<'mc> Sign<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Sign<'mc> { +impl<'mc> Into> for SculkShrieker<'mc> { fn into(self) -> crate::block::TileState<'mc> { crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Sign into crate::block::TileState") - } -} -impl<'mc> Into> for Sign<'mc> { - fn into(self) -> crate::material::Colorable<'mc> { - crate::material::Colorable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Sign into crate::material::Colorable") + .expect("Error converting SculkShrieker into crate::block::TileState") } } #[repr(C)] -pub struct DecoratedPot<'mc>( +pub struct EnderChest<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for DecoratedPot<'mc> { +impl<'mc> JNIRaw<'mc> for EnderChest<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -10535,18 +12188,18 @@ impl<'mc> JNIRaw<'mc> for DecoratedPot<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for DecoratedPot<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EnderChest<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate DecoratedPot from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate EnderChest from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/DecoratedPot")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/EnderChest")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a DecoratedPot object, got {}", + "Invalid argument passed. Expected a EnderChest object, got {}", name ) .into()) @@ -10556,112 +12209,26 @@ impl<'mc> JNIInstantiatable<'mc> for DecoratedPot<'mc> { } } -impl<'mc> DecoratedPot<'mc> { - /// Set the sherd on the provided side. - pub fn set_sherd( - &self, - side: impl Into>, - sherd: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/DecoratedPot/Side;Lorg/bukkit/Material;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(side.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sherd.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSherd", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); +impl<'mc> EnderChest<'mc> { + /// Sets the block's animated state to open and prevents it from being closed + /// until {@link #close()} is called. + pub fn open(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "open", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the sherd on the provided side. - pub fn get_sherd( - &self, - side: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/block/DecoratedPot/Side;)Lorg/bukkit/Material;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(side.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSherd", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets a Map of all sides on this decorated pot and the sherds on them. - /// If a side does not have a specific sherd on it, {@link Material#BRICK} - /// will be the value of that side. - pub fn sherds( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSherds", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - #[deprecated] - /// Gets the sherds on this decorated pot. For faces without a specific sherd, {@link Material#BRICK} is used in its place. - pub fn shards(&self) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + /// Sets the block's animated state to closed even if a player is currently + /// viewing this block. + pub fn close(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getShards", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::Material::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/DecoratedPotInventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::DecoratedPotInventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn snapshot_inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/DecoratedPotInventory;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSnapshotInventory", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::DecoratedPotInventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + .call_method(&self.jni_object(), "close", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } /// Returns a custom tag container capable of storing tags on the object. /// Note that the tags stored on this container are all stored under their @@ -10688,7 +12255,7 @@ impl<'mc> DecoratedPot<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the block associated with this holder. + /// Gets the block represented by this block state. pub fn block(&self) -> Result, Box> { let args = Vec::new(); let mut sig = String::from("("); @@ -11080,99 +12647,25 @@ impl<'mc> DecoratedPot<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for DecoratedPot<'mc> { - fn into(self) -> crate::block::TileState<'mc> { - crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting DecoratedPot into crate::block::TileState") - } -} -impl<'mc> Into> for DecoratedPot<'mc> { - fn into(self) -> crate::inventory::BlockInventoryHolder<'mc> { - crate::inventory::BlockInventoryHolder::from_raw(&self.jni_ref(), self.1) - .expect("Error converting DecoratedPot into crate::inventory::BlockInventoryHolder") - } -} -pub enum DecoratedPotSide<'mc> {} -impl<'mc> std::fmt::Display for DecoratedPotSide<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} +impl<'mc> Into> for EnderChest<'mc> { + fn into(self) -> crate::block::Lidded<'mc> { + crate::block::Lidded::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EnderChest into crate::block::Lidded") } } - -impl<'mc> DecoratedPotSide<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/block/DecoratedPot/Side"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/block/DecoratedPot/Side;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } +impl<'mc> Into> for EnderChest<'mc> { + fn into(self) -> crate::block::TileState<'mc> { + crate::block::TileState::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EnderChest into crate::block::TileState") } } - #[repr(C)] -pub struct DecoratedPotSideStruct<'mc>( +pub struct Beehive<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for DecoratedPotSide<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for DecoratedPotSide<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate DecoratedPotSide from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/DecoratedPot/Side")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a DecoratedPotSide object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for DecoratedPotSideStruct<'mc> { +impl<'mc> JNIRaw<'mc> for Beehive<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -11180,21 +12673,18 @@ impl<'mc> JNIRaw<'mc> for DecoratedPotSideStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for DecoratedPotSideStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Beehive<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate DecoratedPotSideStruct from null object." - ) - .into()); + return Err(eyre::eyre!("Tried to instantiate Beehive from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/DecoratedPot/Side")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Beehive")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a DecoratedPotSideStruct object, got {}", + "Invalid argument passed. Expected a Beehive object, got {}", name ) .into()) @@ -11204,50 +12694,160 @@ impl<'mc> JNIInstantiatable<'mc> for DecoratedPotSideStruct<'mc> { } } -impl<'mc> DecoratedPotSideStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/DecoratedPot/Side;"); - let cls = jni.find_class("org/bukkit/block/DecoratedPot/Side"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::block::DecoratedPotSide::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) +impl<'mc> Beehive<'mc> { + /// Get the hive's flower location. + pub fn flower(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFlower", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } -} -#[repr(C)] -pub struct SculkShrieker<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for SculkShrieker<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Set the hive's flower location. + pub fn set_flower( + &self, + location: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Location;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFlower", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Check if the hive is sedated due to smoke from a nearby campfire. + pub fn is_sedated(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSedated", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for SculkShrieker<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, + /// Check if the block is completely full of entities. + pub fn is_full(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFull", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the amount of entities currently in this block. + pub fn entity_count(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEntityCount", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Get the maximum amount of entities this block can hold. + pub fn max_entities(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxEntities", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the maximum amount of entities this block can hold. + pub fn set_max_entities(&self, max: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(max); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaxEntities", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Release all the entities currently stored in the block. + pub fn release_entities( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "releaseEntities", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(obj); + } + Ok(new_vec) + } + /// Add an entity to the block. + pub fn add_entity( + &self, + entity: jni::objects::JObject<'mc>, + ) -> Result<(), Box> { + let sig = String::from("(LT;)V"); + let val_1 = jni::objects::JValueGen::Object(entity); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addEntity", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Beehive<'mc> { + fn into(self) -> crate::block::EntityBlockStorage<'mc> { + crate::block::EntityBlockStorage::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Beehive into crate::block::EntityBlockStorage") + } +} +#[repr(C)] +pub struct CommandBlock<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for CommandBlock<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for CommandBlock<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate SculkShrieker from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate CommandBlock from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/SculkShrieker")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/CommandBlock")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SculkShrieker object, got {}", + "Invalid argument passed. Expected a CommandBlock object, got {}", name ) .into()) @@ -11257,45 +12857,68 @@ impl<'mc> JNIInstantiatable<'mc> for SculkShrieker<'mc> { } } -impl<'mc> SculkShrieker<'mc> { - /// Gets the most recent warning level of this block. - /// When the warning level reaches 4, the shrieker will attempt to spawn a - /// Warden. - pub fn warning_level(&self) -> Result> { - let sig = String::from("()I"); +impl<'mc> CommandBlock<'mc> { + /// Gets the command that this CommandBlock will run when powered. + /// This will never return null.If the CommandBlock does not have a + /// command, an empty String will be returned instead. + pub fn command(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getWarningLevel", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCommand", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets the most recent warning level of this block. - /// When the warning level reaches 4, the shrieker will attempt to spawn a - /// Warden. - pub fn set_warning_level(&self, level: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(level); + /// Sets the command that this CommandBlock will run when powered. + /// Setting the command to null is the same as setting it to an empty + /// String. + pub fn set_command( + &self, + command: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(command.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setWarningLevel", + "setCommand", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Simulates a player causing a vibration. - pub fn try_shriek( - &self, - player: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Player;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) - }); + /// Gets the name of this CommandBlock.The name is used with commands + /// that this CommandBlock executes.This name will never be null, and + /// by default is "@". + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the name of this CommandBlock.The name is used with commands + /// that this CommandBlock executes.Setting the name to null is the + /// same as setting it to "@". + pub fn set_name(&self, name: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "tryShriek", + "setName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -11719,19 +13342,19 @@ impl<'mc> SculkShrieker<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for SculkShrieker<'mc> { +impl<'mc> Into> for CommandBlock<'mc> { fn into(self) -> crate::block::TileState<'mc> { crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SculkShrieker into crate::block::TileState") + .expect("Error converting CommandBlock into crate::block::TileState") } } #[repr(C)] -pub struct EnderChest<'mc>( +pub struct Dropper<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EnderChest<'mc> { +impl<'mc> JNIRaw<'mc> for Dropper<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -11739,18 +13362,18 @@ impl<'mc> JNIRaw<'mc> for EnderChest<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EnderChest<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Dropper<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate EnderChest from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Dropper from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/EnderChest")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Dropper")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EnderChest object, got {}", + "Invalid argument passed. Expected a Dropper object, got {}", name ) .into()) @@ -11760,437 +13383,259 @@ impl<'mc> JNIInstantiatable<'mc> for EnderChest<'mc> { } } -impl<'mc> EnderChest<'mc> { - /// Sets the block's animated state to open and prevents it from being closed - /// until {@link #close()} is called. - pub fn open(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "open", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Sets the block's animated state to closed even if a player is currently - /// viewing this block. - pub fn close(&self) -> Result<(), Box> { +impl<'mc> Dropper<'mc> { + /// Tries to drop a randomly selected item from the dropper's inventory, + /// following the normal behavior of a dropper. + /// + /// Normal behavior of a dropper is as follows: + /// + /// If the block that the dropper is facing is an InventoryHolder, + /// the randomly selected ItemStack is placed within that + /// Inventory in the first slot that's available, starting with 0 and + /// counting up.If the inventory is full, nothing happens. + /// + /// If the block that the dropper is facing is not an InventoryHolder, + /// the randomly selected ItemStack is dropped on + /// the ground in the form of an {@link org.bukkit.entity.Item Item}. + /// + /// If the block represented by this state is no longer a dropper, this will + /// do nothing. + pub fn drop(&self) -> Result<(), Box> { let sig = String::from("()V"); let res = self .jni_ref() - .call_method(&self.jni_object(), "close", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "drop", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. + /// Gets the inventory of the block represented by this block state. /// - /// This {@link PersistentDataHolder} is only linked to the snapshot instance - /// stored by the {@link BlockState}. - /// When storing changes on the {@link PersistentDataHolder}, the updated - /// content will only be applied to the actual tile entity after one of the - /// {@link #update()} methods is called. - pub fn persistent_data_container( + /// If the block was changed to a different type in the meantime, the + /// returned inventory might no longer be valid. + /// + /// If this block state is not placed this will return the captured inventory + /// snapshot instead. + pub fn inventory( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPersistentDataContainer", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the block represented by this block state. - pub fn block(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/block/Block;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBlock", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the metadata for this block state. - pub fn data(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/MaterialData;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the data for this block state. - pub fn block_data( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBlockData", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Copies the state to another block as an unplaced BlockState. - pub fn copy( + /// Gets the captured inventory snapshot of this container. + /// + /// The returned inventory is not linked to any block. Any modifications to + /// the returned inventory will not be applied to the block represented by + /// this block state up until {@link #update(boolean, boolean)} has been + /// called. + pub fn snapshot_inventory( &self, - location: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = location { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")Lorg/bukkit/block/BlockState;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSnapshotInventory", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the type of this block state. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + /// + /// This {@link PersistentDataHolder} is only linked to the snapshot instance + /// stored by the {@link BlockState}. + /// When storing changes on the {@link PersistentDataHolder}, the updated + /// content will only be applied to the actual tile entity after one of the + /// {@link #update()} methods is called. + pub fn persistent_data_container( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPersistentDataContainer", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the current light level of the block represented by this block state. - pub fn light_level(&self) -> Result> { - let sig = String::from("()B"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLightLevel", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) - } - /// Gets the world which contains the block represented by this block state. - pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); + /// Gets the block associated with this holder. + pub fn block(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/block/Block;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBlock", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { + crate::block::Block::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the x-coordinate of this block state. - pub fn x(&self) -> Result> { - let sig = String::from("()I"); + /// Checks if the container has a valid (non empty) key. + pub fn is_locked(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isLocked", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Gets the y-coordinate of this block state. - pub fn y(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the key needed to access the container. + pub fn lock(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the z-coordinate of this block state. - pub fn z(&self) -> Result> { - let sig = String::from("()I"); - let res = self + Ok(self .jni_ref() - .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Stores the location of this block state in the provided Location object. - /// - /// If the provided Location is null this method does nothing and returns - /// null. - /// - /// If this block state is not placed the location's world will be null! - pub fn get_location( - &self, - loc: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) - }); + /// Sets the key required to access this container. Set to null (or empty + /// string) to remove key. + pub fn set_lock(&self, key: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(key.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocation", + "setLock", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the custom name on a mob or block. If there is no name this method + /// will return null. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn custom_name(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/lang/String;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCustomName", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Gets the chunk which contains the block represented by this block state. - pub fn chunk(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Chunk;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getChunk", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Chunk::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Sets a custom name on a mob or block. This name will be used in death + /// messages and can be sent to the client as a nameplate over the mob. + /// + /// Setting the name to null or an empty string will clear it. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn set_custom_name( + &self, + name: impl Into, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setCustomName", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the metadata for this block state. - pub fn set_data( + /// Set the loot table for a container or entity. + /// + /// To remove a loot table use null. Do not use {@link LootTables#EMPTY} to + /// clear a LootTable. + pub fn set_loot_table( &self, - data: impl Into>, + table: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/material/MaterialData;)V"); + let sig = String::from("(Lorg/bukkit/loot/LootTable;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) + jni::objects::JObject::from_raw(table.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setData", + "setLootTable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets the data for this block state. - pub fn set_block_data( - &self, - data: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setBlockData", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Sets the type of this block state. - pub fn set_type( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Material;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setType", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Attempts to update the block represented by this state, setting it to - /// the new values as defined by this state. - /// - /// If this state is not placed, this will have no effect and return true. - /// - /// Unless force is true, this will not modify the state of a block if it - /// is no longer the same type as it was when this state was taken. It will - /// return false in this eventuality. - /// - /// If force is true, it will set the type of the block to match the new - /// state, set the state data and then return true. + /// Gets the Loot Table attached to this block or entity. /// - /// If applyPhysics is true, it will trigger a physics update on - /// surrounding blocks which could cause them to update or disappear. - pub fn update( + /// If an block/entity does not have a loot table, this will return null, NOT + /// an empty loot table. + pub fn loot_table( &self, - force: std::option::Option, - apply_physics: std::option::Option, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = force { - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_1); - } - if let Some(a) = apply_physics { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "update", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - - pub fn raw_data(&self) -> Result> { - let sig = String::from("()B"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/loot/LootTable;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getRawData", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLootTable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::loot::LootTable::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - #[deprecated] - - pub fn set_raw_data(&self, data: i8) -> Result<(), Box> { - let sig = String::from("(B)V"); - let val_1 = jni::objects::JValueGen::Byte(data); + /// Set the seed used when this Loot Table generates loot. + pub fn set_seed(&self, seed: i64) -> Result<(), Box> { + let sig = String::from("(J)V"); + let val_1 = jni::objects::JValueGen::Long(seed); let res = self.jni_ref().call_method( &self.jni_object(), - "setRawData", + "setSeed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether this state is placed in the world. + /// Get the Loot Table's seed. /// - /// Some methods will not work if the block state isn't - /// placed in the world. - pub fn is_placed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isPlaced", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets a metadata value in the implementing object's metadata store. - pub fn set_metadata( - &self, - metadata_key: impl Into, - new_metadata_value: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += "Lorg/bukkit/metadata/MetadataValue;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) - }); - args.push(val_2); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setMetadata", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns a list of previously set metadata values from the implementing - /// object's metadata store. - pub fn get_metadata( - &self, - metadata_key: impl Into, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += ")Ljava/util/List;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getMetadata", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::metadata::MetadataValue::from_raw( - &self.jni_ref(), - obj, - )?); - } - Ok(new_vec) - } - /// Tests to see whether the implementing object contains the given - /// metadata value in its metadata store. - pub fn has_metadata( - &self, - metadata_key: impl Into, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += ")Z"; + /// The seed is used when generating loot. + pub fn seed(&self) -> Result> { + let sig = String::from("()J"); let res = self .jni_ref() - .call_method(&self.jni_object(), "hasMetadata", sig.as_str(), args); + .call_method(&self.jni_object(), "getSeed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Removes the given metadata value from the implementing object's - /// metadata store. - pub fn remove_metadata( - &self, - metadata_key: impl Into, - owning_plugin: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += "Lorg/bukkit/plugin/Plugin;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) - }); - args.push(val_2); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "removeMetadata", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.j()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -12198,25 +13643,25 @@ impl<'mc> EnderChest<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for EnderChest<'mc> { - fn into(self) -> crate::block::Lidded<'mc> { - crate::block::Lidded::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EnderChest into crate::block::Lidded") +impl<'mc> Into> for Dropper<'mc> { + fn into(self) -> crate::block::Container<'mc> { + crate::block::Container::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Dropper into crate::block::Container") } } -impl<'mc> Into> for EnderChest<'mc> { - fn into(self) -> crate::block::TileState<'mc> { - crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EnderChest into crate::block::TileState") +impl<'mc> Into> for Dropper<'mc> { + fn into(self) -> crate::loot::Lootable<'mc> { + crate::loot::Lootable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Dropper into crate::loot::Lootable") } } #[repr(C)] -pub struct Beehive<'mc>( +pub struct Structure<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Beehive<'mc> { +impl<'mc> JNIRaw<'mc> for Structure<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -12224,18 +13669,18 @@ impl<'mc> JNIRaw<'mc> for Beehive<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Beehive<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Structure<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Beehive from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Structure from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Beehive")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Structure")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Beehive object, got {}", + "Invalid argument passed. Expected a Structure object, got {}", name ) .into()) @@ -12245,552 +13690,382 @@ impl<'mc> JNIInstantiatable<'mc> for Beehive<'mc> { } } -impl<'mc> Beehive<'mc> { - /// Get the hive's flower location. - pub fn flower(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFlower", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Set the hive's flower location. - pub fn set_flower( +impl<'mc> Structure<'mc> { + /// The name of this structure. + pub fn structure_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getStructureName", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Set the name of this structure. This is case-sensitive. The name of the + /// structure in the {@link UsageMode#SAVE} structure block MUST match the + /// name within the {@link UsageMode#CORNER} block or the size calculation + /// will fail. + pub fn set_structure_name( &self, - location: impl Into>, + name: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Location;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setFlower", + "setStructureName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check if the hive is sedated due to smoke from a nearby campfire. - pub fn is_sedated(&self) -> Result> { - let sig = String::from("()Z"); + /// Get the name of who created this structure. + pub fn author(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isSedated", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAuthor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Check if the block is completely full of entities. - pub fn is_full(&self) -> Result> { - let sig = String::from("()Z"); + /// Set the name of whoever created this structure using a + /// {@link LivingEntity}. + pub fn set_author( + &self, + living_entity: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/LivingEntity;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(living_entity.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isFull", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the amount of entities currently in this block. - pub fn entity_count(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEntityCount", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + .call_method(&self.jni_object(), "setAuthor", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the maximum amount of entities this block can hold. - pub fn max_entities(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaxEntities", sig.as_str(), vec![]); + /// The relative position of the structure outline based on the position of + /// the structure block. Maximum allowed distance is 48 blocks in any + /// direction. + pub fn relative_position( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/BlockVector;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getRelativePosition", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::util::BlockVector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the maximum amount of entities this block can hold. - pub fn set_max_entities(&self, max: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(max); + /// Set the relative position from the structure block. Maximum allowed + /// distance is 48 blocks in any direction. + pub fn set_relative_position( + &self, + vector: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/BlockVector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(vector.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxEntities", + "setRelativePosition", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Release all the entities currently stored in the block. - pub fn release_entities( + /// The distance to the opposite corner of this structure. The maximum + /// structure size is 48x48x48. When a structure has successfully been + /// calculated (i.e. it is within the maximum allowed distance) a white + /// border surrounds the structure. + pub fn structure_size( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "releaseEntities", sig.as_str(), vec![]); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/BlockVector;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getStructureSize", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(obj); - } - Ok(new_vec) + crate::util::BlockVector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Add an entity to the block. - pub fn add_entity( + /// Set the maximum size of this structure from the origin point. Maximum + /// allowed size is 48x48x48. + pub fn set_structure_size( &self, - entity: jni::objects::JObject<'mc>, + vector: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(LT;)V"); - let val_1 = jni::objects::JValueGen::Object(entity); + let sig = String::from("(Lorg/bukkit/util/BlockVector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(vector.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "addEntity", + "setStructureSize", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Beehive<'mc> { - fn into(self) -> crate::block::EntityBlockStorage<'mc> { - crate::block::EntityBlockStorage::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Beehive into crate::block::EntityBlockStorage") - } -} -#[repr(C)] -pub struct CommandBlock<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for CommandBlock<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for CommandBlock<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate CommandBlock from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/CommandBlock")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a CommandBlock object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> CommandBlock<'mc> { - /// Gets the command that this CommandBlock will run when powered. - /// This will never return null.If the CommandBlock does not have a - /// command, an empty String will be returned instead. - pub fn command(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCommand", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Sets the command that this CommandBlock will run when powered. - /// Setting the command to null is the same as setting it to an empty - /// String. - pub fn set_command( + /// Sets the mirroring of the structure. + pub fn set_mirror( &self, - command: impl Into, + mirror: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(command.into())?, - )); + let sig = String::from("(Lorg/bukkit/block/structure/Mirror;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(mirror.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCommand", + "setMirror", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the name of this CommandBlock.The name is used with commands - /// that this CommandBlock executes.This name will never be null, and - /// by default is "@". - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self + /// How this structure is mirrored. + pub fn mirror( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/structure/Mirror;"); + let res = self .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + .call_method(&self.jni_object(), "getMirror", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::structure::Mirror::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the name of this CommandBlock.The name is used with commands - /// that this CommandBlock executes.Setting the name to null is the - /// same as setting it to "@". - pub fn set_name(&self, name: impl Into) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + /// Set how this structure is rotated. + pub fn set_rotation( + &self, + rotation: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/structure/StructureRotation;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(rotation.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setName", + "setRotation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - /// - /// This {@link PersistentDataHolder} is only linked to the snapshot instance - /// stored by the {@link BlockState}. - /// When storing changes on the {@link PersistentDataHolder}, the updated - /// content will only be applied to the actual tile entity after one of the - /// {@link #update()} methods is called. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPersistentDataContainer", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the block represented by this block state. - pub fn block(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/block/Block;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBlock", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the metadata for this block state. - pub fn data(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/MaterialData;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the data for this block state. - pub fn block_data( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBlockData", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Copies the state to another block as an unplaced BlockState. - pub fn copy( + /// Get how this structure is rotated. + pub fn rotation( &self, - location: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = location { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")Lorg/bukkit/block/BlockState;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the type of this block state. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the current light level of the block represented by this block state. - pub fn light_level(&self) -> Result> { - let sig = String::from("()B"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/structure/StructureRotation;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLightLevel", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) - } - /// Gets the world which contains the block represented by this block state. - pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getRotation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { + crate::block::structure::StructureRotation::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the x-coordinate of this block state. - pub fn x(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the y-coordinate of this block state. - pub fn y(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the z-coordinate of this block state. - pub fn z(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Stores the location of this block state in the provided Location object. - /// - /// If the provided Location is null this method does nothing and returns - /// null. - /// - /// If this block state is not placed the location's world will be null! - pub fn get_location( + /// Set the {@link UsageMode} of this structure block. + pub fn set_usage_mode( &self, - loc: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + mode: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/structure/UsageMode;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + jni::objects::JObject::from_raw(mode.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocation", + "setUsageMode", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the chunk which contains the block represented by this block state. - pub fn chunk(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Chunk;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getChunk", sig.as_str(), vec![]); + /// Get the {@link UsageMode} of this structure block. + pub fn usage_mode( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/structure/UsageMode;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getUsageMode", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Chunk::from_raw(&self.jni_ref(), unsafe { + crate::block::structure::UsageMode::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the metadata for this block state. - pub fn set_data( + /// While in {@link UsageMode#SAVE} mode, this will ignore any entities when + /// saving the structure. + /// + /// While in {@link UsageMode#LOAD} mode this will ignore any entities that + /// were saved to file. + pub fn set_ignore_entities( &self, - data: impl Into>, + ignore_entities: bool, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/material/MaterialData;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) - }); + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(ignore_entities.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setData", + "setIgnoreEntities", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets the data for this block state. - pub fn set_block_data( - &self, - data: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) - }); + /// Get if this structure block should ignore entities. + pub fn is_ignore_entities(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "setBlockData", + "isIgnoreEntities", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Sets the type of this block state. - pub fn set_type( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Material;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Set if the structure outline should show air blocks. + pub fn set_show_air(&self, show_air: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(show_air.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setType", + "setShowAir", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Attempts to update the block represented by this state, setting it to - /// the new values as defined by this state. - /// - /// If this state is not placed, this will have no effect and return true. - /// - /// Unless force is true, this will not modify the state of a block if it - /// is no longer the same type as it was when this state was taken. It will - /// return false in this eventuality. - /// - /// If force is true, it will set the type of the block to match the new - /// state, set the state data and then return true. - /// - /// If applyPhysics is true, it will trigger a physics update on - /// surrounding blocks which could cause them to update or disappear. - pub fn update( - &self, - force: std::option::Option, - apply_physics: std::option::Option, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = force { - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_1); - } - if let Some(a) = apply_physics { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")Z"; + /// Check if this structure block is currently showing all air blocks + pub fn is_show_air(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "update", sig.as_str(), args); + .call_method(&self.jni_object(), "isShowAir", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - - pub fn raw_data(&self) -> Result> { - let sig = String::from("()B"); + /// Set if this structure box should show the bounding box. + pub fn set_bounding_box_visible( + &self, + show_bounding_box: bool, + ) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(show_bounding_box.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBoundingBoxVisible", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get if this structure block is currently showing the bounding box. + pub fn is_bounding_box_visible(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isBoundingBoxVisible", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set the integrity of the structure. Integrity must be between 0.0 and 1.0 + /// Lower integrity values will result in more blocks being removed when + /// loading a structure. Integrity and {@link #getSeed()} are used together + /// to determine which blocks are randomly removed to mimic "decay." + pub fn set_integrity(&self, integrity: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(integrity); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setIntegrity", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the integrity of this structure. + pub fn integrity(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getRawData", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getIntegrity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) + Ok(res.f()?) } - #[deprecated] - - pub fn set_raw_data(&self, data: i8) -> Result<(), Box> { - let sig = String::from("(B)V"); - let val_1 = jni::objects::JValueGen::Byte(data); + /// The seed used to determine which blocks will be removed upon loading. + /// {@link #getIntegrity()} and seed are used together to determine which + /// blocks are randomly removed to mimic "decay." + pub fn set_seed(&self, seed: i64) -> Result<(), Box> { + let sig = String::from("(J)V"); + let val_1 = jni::objects::JValueGen::Long(seed); let res = self.jni_ref().call_method( &self.jni_object(), - "setRawData", + "setSeed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether this state is placed in the world. - /// - /// Some methods will not work if the block state isn't - /// placed in the world. - pub fn is_placed(&self) -> Result> { - let sig = String::from("()Z"); + /// The seed used to determine how many blocks are removed upon loading of + /// this structure. + pub fn seed(&self) -> Result> { + let sig = String::from("()J"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isPlaced", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSeed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.j()?) } /// Sets a metadata value in the implementing object's metadata store. pub fn set_metadata( &self, metadata_key: impl Into, - new_metadata_value: impl Into>, + new_metadata_value: std::option::Option>>, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); @@ -12799,11 +14074,13 @@ impl<'mc> CommandBlock<'mc> { self.jni_ref().new_string(metadata_key.into())?, )); args.push(val_1); - sig += "Lorg/bukkit/metadata/MetadataValue;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) - }); - args.push(val_2); + if let Some(a) = new_metadata_value { + sig += "Lorg/bukkit/metadata/MetadataValue;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } sig += ")V"; let res = self .jni_ref() @@ -12841,352 +14118,361 @@ impl<'mc> CommandBlock<'mc> { } Ok(new_vec) } - /// Tests to see whether the implementing object contains the given - /// metadata value in its metadata store. - pub fn has_metadata( + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + /// + /// This {@link PersistentDataHolder} is only linked to the snapshot instance + /// stored by the {@link BlockState}. + /// When storing changes on the {@link PersistentDataHolder}, the updated + /// content will only be applied to the actual tile entity after one of the + /// {@link #update()} methods is called. + pub fn persistent_data_container( &self, - metadata_key: impl Into, - ) -> Result> { - let mut args = Vec::new(); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPersistentDataContainer", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the block represented by this block state. + pub fn block(&self) -> Result, Box> { + let args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += ")Z"; + sig += ")Lorg/bukkit/block/Block;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "hasMetadata", sig.as_str(), args); + .call_method(&self.jni_object(), "getBlock", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Removes the given metadata value from the implementing object's - /// metadata store. - pub fn remove_metadata( + /// Gets the metadata for this block state. + pub fn data(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/MaterialData;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the data for this block state. + pub fn block_data( &self, - metadata_key: impl Into, - owning_plugin: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += "Lorg/bukkit/plugin/Plugin;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) - }); - args.push(val_2); - sig += ")V"; + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "removeMetadata", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for CommandBlock<'mc> { - fn into(self) -> crate::block::TileState<'mc> { - crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting CommandBlock into crate::block::TileState") + .call_method(&self.jni_object(), "getBlockData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -#[repr(C)] -pub struct Dropper<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Dropper<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Dropper<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Dropper from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Dropper")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Dropper object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + /// Copies the state to another block as an unplaced BlockState. + pub fn copy( + &self, + location: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = location { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); } - } -} - -impl<'mc> Dropper<'mc> { - /// Tries to drop a randomly selected item from the dropper's inventory, - /// following the normal behavior of a dropper. - /// - /// Normal behavior of a dropper is as follows: - /// - /// If the block that the dropper is facing is an InventoryHolder, - /// the randomly selected ItemStack is placed within that - /// Inventory in the first slot that's available, starting with 0 and - /// counting up.If the inventory is full, nothing happens. - /// - /// If the block that the dropper is facing is not an InventoryHolder, - /// the randomly selected ItemStack is dropped on - /// the ground in the form of an {@link org.bukkit.entity.Item Item}. - /// - /// If the block represented by this state is no longer a dropper, this will - /// do nothing. - pub fn drop(&self) -> Result<(), Box> { - let sig = String::from("()V"); + sig += ")Lorg/bukkit/block/BlockState;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "drop", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the inventory of the block represented by this block state. - /// - /// If the block was changed to a different type in the meantime, the - /// returned inventory might no longer be valid. - /// - /// If this block state is not placed this will return the captured inventory - /// snapshot instead. - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "copy", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the captured inventory snapshot of this container. - /// - /// The returned inventory is not linked to any block. Any modifications to - /// the returned inventory will not be applied to the block represented by - /// this block state up until {@link #update(boolean, boolean)} has been - /// called. - pub fn snapshot_inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSnapshotInventory", - sig.as_str(), - vec![], - ); + /// Gets the type of this block state. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + crate::Material::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - /// - /// This {@link PersistentDataHolder} is only linked to the snapshot instance - /// stored by the {@link BlockState}. - /// When storing changes on the {@link PersistentDataHolder}, the updated - /// content will only be applied to the actual tile entity after one of the - /// {@link #update()} methods is called. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPersistentDataContainer", - sig.as_str(), - vec![], - ); + /// Gets the current light level of the block represented by this block state. + pub fn light_level(&self) -> Result> { + let sig = String::from("()B"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLightLevel", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.b()?) } - /// Gets the block associated with this holder. - pub fn block(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/block/Block;"; + /// Gets the world which contains the block represented by this block state. + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getBlock", sig.as_str(), args); + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { + crate::World::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Checks if the container has a valid (non empty) key. - pub fn is_locked(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the x-coordinate of this block state. + pub fn x(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isLocked", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Gets the key needed to access the container. - pub fn lock(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Gets the y-coordinate of this block state. + pub fn y(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getLock", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self + Ok(res.i()?) + } + /// Gets the z-coordinate of this block state. + pub fn z(&self) -> Result> { + let sig = String::from("()I"); + let res = self .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Sets the key required to access this container. Set to null (or empty - /// string) to remove key. - pub fn set_lock(&self, key: impl Into) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(key.into())?, - )); + /// Stores the location of this block state in the provided Location object. + /// + /// If the provided Location is null this method does nothing and returns + /// null. + /// + /// If this block state is not placed the location's world will be null! + pub fn get_location( + &self, + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLock", + "getLocation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the custom name on a mob or block. If there is no name this method - /// will return null. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn custom_name(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/lang/String;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCustomName", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Sets a custom name on a mob or block. This name will be used in death - /// messages and can be sent to the client as a nameplate over the mob. - /// - /// Setting the name to null or an empty string will clear it. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn set_custom_name( + /// Gets the chunk which contains the block represented by this block state. + pub fn chunk(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Chunk;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getChunk", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Chunk::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the metadata for this block state. + pub fn set_data( &self, - name: impl Into, + data: impl Into>, ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); - args.push(val_1); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setCustomName", sig.as_str(), args); + let sig = String::from("(Lorg/bukkit/material/MaterialData;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(data.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setData", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Set the loot table for a container or entity. - /// - /// To remove a loot table use null. Do not use {@link LootTables#EMPTY} to - /// clear a LootTable. - pub fn set_loot_table( + /// Sets the data for this block state. + pub fn set_block_data( &self, - table: impl Into>, + data: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/loot/LootTable;)V"); + let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(table.into().jni_object().clone()) + jni::objects::JObject::from_raw(data.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLootTable", + "setBlockData", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the Loot Table attached to this block or entity. + /// Sets the type of this block state. + pub fn set_type( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Material;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Attempts to update the block represented by this state, setting it to + /// the new values as defined by this state. /// - /// If an block/entity does not have a loot table, this will return null, NOT - /// an empty loot table. - pub fn loot_table( + /// If this state is not placed, this will have no effect and return true. + /// + /// Unless force is true, this will not modify the state of a block if it + /// is no longer the same type as it was when this state was taken. It will + /// return false in this eventuality. + /// + /// If force is true, it will set the type of the block to match the new + /// state, set the state data and then return true. + /// + /// If applyPhysics is true, it will trigger a physics update on + /// surrounding blocks which could cause them to update or disappear. + pub fn update( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/loot/LootTable;"); + force: std::option::Option, + apply_physics: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = force { + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_1); + } + if let Some(a) = apply_physics { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "update", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + + pub fn raw_data(&self) -> Result> { + let sig = String::from("()B"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLootTable", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getRawData", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::loot::LootTable::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.b()?) } - /// Set the seed used when this Loot Table generates loot. - pub fn set_seed(&self, seed: i64) -> Result<(), Box> { - let sig = String::from("(J)V"); - let val_1 = jni::objects::JValueGen::Long(seed); + #[deprecated] + + pub fn set_raw_data(&self, data: i8) -> Result<(), Box> { + let sig = String::from("(B)V"); + let val_1 = jni::objects::JValueGen::Byte(data); let res = self.jni_ref().call_method( &self.jni_object(), - "setSeed", + "setRawData", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the Loot Table's seed. + /// Returns whether this state is placed in the world. /// - /// The seed is used when generating loot. - pub fn seed(&self) -> Result> { - let sig = String::from("()J"); + /// Some methods will not work if the block state isn't + /// placed in the world. + pub fn is_placed(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getSeed", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isPlaced", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + Ok(res.z()?) + } + /// Tests to see whether the implementing object contains the given + /// metadata value in its metadata store. + pub fn has_metadata( + &self, + metadata_key: impl Into, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasMetadata", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Removes the given metadata value from the implementing object's + /// metadata store. + pub fn remove_metadata( + &self, + metadata_key: impl Into, + owning_plugin: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += "Lorg/bukkit/plugin/Plugin;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + }); + args.push(val_2); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "removeMetadata", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -13194,25 +14480,19 @@ impl<'mc> Dropper<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Dropper<'mc> { - fn into(self) -> crate::block::Container<'mc> { - crate::block::Container::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Dropper into crate::block::Container") - } -} -impl<'mc> Into> for Dropper<'mc> { - fn into(self) -> crate::loot::Lootable<'mc> { - crate::loot::Lootable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Dropper into crate::loot::Lootable") +impl<'mc> Into> for Structure<'mc> { + fn into(self) -> crate::block::TileState<'mc> { + crate::block::TileState::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Structure into crate::block::TileState") } } #[repr(C)] -pub struct Structure<'mc>( +pub struct Campfire<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Structure<'mc> { +impl<'mc> JNIRaw<'mc> for Campfire<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -13220,18 +14500,18 @@ impl<'mc> JNIRaw<'mc> for Structure<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Structure<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Campfire<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Structure from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Campfire from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Structure")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Campfire")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Structure object, got {}", + "Invalid argument passed. Expected a Campfire object, got {}", name ) .into()) @@ -13241,376 +14521,441 @@ impl<'mc> JNIInstantiatable<'mc> for Structure<'mc> { } } -impl<'mc> Structure<'mc> { - /// The name of this structure. - pub fn structure_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); +impl<'mc> Campfire<'mc> { + pub fn size(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + + pub fn get_item( + &self, + index: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/ItemStack;"); + let val_1 = jni::objects::JValueGen::Int(index); let res = self.jni_ref().call_method( &self.jni_object(), - "getStructureName", + "getItem", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Set the name of this structure. This is case-sensitive. The name of the - /// structure in the {@link UsageMode#SAVE} structure block MUST match the - /// name within the {@link UsageMode#CORNER} block or the size calculation - /// will fail. - pub fn set_structure_name( + + pub fn set_item( &self, - name: impl Into, + index: i32, + item: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + let sig = String::from("(ILorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Int(index); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setStructureName", + "setItem", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the name of who created this structure. - pub fn author(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getAuthor", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Set the name of whoever created this structure using a - /// {@link LivingEntity}. - pub fn set_author( - &self, - living_entity: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/LivingEntity;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(living_entity.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setAuthor", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// The relative position of the structure outline based on the position of - /// the structure block. Maximum allowed distance is 48 blocks in any - /// direction. - pub fn relative_position( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/BlockVector;"); + /// Get cook time. + /// This is the amount of time the item has been cooking for. + pub fn get_cook_time(&self, index: i32) -> Result> { + let sig = String::from("(I)I"); + let val_1 = jni::objects::JValueGen::Int(index); let res = self.jni_ref().call_method( &self.jni_object(), - "getRelativePosition", + "getCookTime", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::util::BlockVector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Set the relative position from the structure block. Maximum allowed - /// distance is 48 blocks in any direction. - pub fn set_relative_position( + /// Set cook time. + /// This is the amount of time the item has been cooking for. + pub fn set_cook_time( &self, - vector: impl Into>, + index: i32, + cook_time: i32, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/BlockVector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(vector.into().jni_object().clone()) - }); + let sig = String::from("(II)V"); + let val_1 = jni::objects::JValueGen::Int(index); + let val_2 = jni::objects::JValueGen::Int(cook_time); let res = self.jni_ref().call_method( &self.jni_object(), - "setRelativePosition", + "setCookTime", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// The distance to the opposite corner of this structure. The maximum - /// structure size is 48x48x48. When a structure has successfully been - /// calculated (i.e. it is within the maximum allowed distance) a white - /// border surrounds the structure. - pub fn structure_size( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/BlockVector;"); + /// Get cook time total. + /// This is the amount of time the item is required to cook for. + pub fn get_cook_time_total(&self, index: i32) -> Result> { + let sig = String::from("(I)I"); + let val_1 = jni::objects::JValueGen::Int(index); let res = self.jni_ref().call_method( &self.jni_object(), - "getStructureSize", + "getCookTimeTotal", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::util::BlockVector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Set the maximum size of this structure from the origin point. Maximum - /// allowed size is 48x48x48. - pub fn set_structure_size( + /// Set cook time. + /// This is the amount of time the item is required to cook for. + pub fn set_cook_time_total( &self, - vector: impl Into>, + index: i32, + cook_time_total: i32, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/BlockVector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(vector.into().jni_object().clone()) - }); + let sig = String::from("(II)V"); + let val_1 = jni::objects::JValueGen::Int(index); + let val_2 = jni::objects::JValueGen::Int(cook_time_total); let res = self.jni_ref().call_method( &self.jni_object(), - "setStructureSize", + "setCookTimeTotal", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets the mirroring of the structure. - pub fn set_mirror( + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + /// + /// This {@link PersistentDataHolder} is only linked to the snapshot instance + /// stored by the {@link BlockState}. + /// When storing changes on the {@link PersistentDataHolder}, the updated + /// content will only be applied to the actual tile entity after one of the + /// {@link #update()} methods is called. + pub fn persistent_data_container( &self, - mirror: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/structure/Mirror;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(mirror.into().jni_object().clone()) - }); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setMirror", + "getPersistentDataContainer", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// How this structure is mirrored. - pub fn mirror( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/structure/Mirror;"); + /// Gets the block represented by this block state. + pub fn block(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/block/Block;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getMirror", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBlock", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::block::structure::Mirror::from_raw(&self.jni_ref(), unsafe { + crate::block::Block::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Set how this structure is rotated. - pub fn set_rotation( - &self, - rotation: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/structure/StructureRotation;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(rotation.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRotation", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Gets the metadata for this block state. + pub fn data(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/MaterialData;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get how this structure is rotated. - pub fn rotation( + /// Gets the data for this block state. + pub fn block_data( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/structure/StructureRotation;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getRotation", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBlockData", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::structure::StructureRotation::from_raw(&self.jni_ref(), unsafe { + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Set the {@link UsageMode} of this structure block. - pub fn set_usage_mode( - &self, - mode: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/structure/UsageMode;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(mode.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setUsageMode", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the {@link UsageMode} of this structure block. - pub fn usage_mode( + /// Copies the state to another block as an unplaced BlockState. + pub fn copy( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/structure/UsageMode;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getUsageMode", sig.as_str(), vec![]); + location: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = location { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Lorg/bukkit/block/BlockState;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::block::structure::UsageMode::from_raw(&self.jni_ref(), unsafe { + crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// While in {@link UsageMode#SAVE} mode, this will ignore any entities when - /// saving the structure. - /// - /// While in {@link UsageMode#LOAD} mode this will ignore any entities that - /// were saved to file. - pub fn set_ignore_entities( - &self, - ignore_entities: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(ignore_entities.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setIgnoreEntities", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Gets the type of this block state. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get if this structure block should ignore entities. - pub fn is_ignore_entities(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isIgnoreEntities", - sig.as_str(), - vec![], - ); + /// Gets the current light level of the block represented by this block state. + pub fn light_level(&self) -> Result> { + let sig = String::from("()B"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLightLevel", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.b()?) } - /// Set if the structure outline should show air blocks. - pub fn set_show_air(&self, show_air: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(show_air.into()); + /// Gets the world which contains the block represented by this block state. + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the x-coordinate of this block state. + pub fn x(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the y-coordinate of this block state. + pub fn y(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the z-coordinate of this block state. + pub fn z(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Stores the location of this block state in the provided Location object. + /// + /// If the provided Location is null this method does nothing and returns + /// null. + /// + /// If this block state is not placed the location's world will be null! + pub fn get_location( + &self, + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setShowAir", + "getLocation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Check if this structure block is currently showing all air blocks - pub fn is_show_air(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the chunk which contains the block represented by this block state. + pub fn chunk(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Chunk;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isShowAir", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getChunk", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Chunk::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set if this structure box should show the bounding box. - pub fn set_bounding_box_visible( + /// Sets the metadata for this block state. + pub fn set_data( &self, - show_bounding_box: bool, + data: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(show_bounding_box.into()); + let sig = String::from("(Lorg/bukkit/material/MaterialData;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(data.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBoundingBoxVisible", + "setData", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get if this structure block is currently showing the bounding box. - pub fn is_bounding_box_visible(&self) -> Result> { - let sig = String::from("()Z"); + /// Sets the data for this block state. + pub fn set_block_data( + &self, + data: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(data.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "isBoundingBoxVisible", + "setBlockData", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Set the integrity of the structure. Integrity must be between 0.0 and 1.0 - /// Lower integrity values will result in more blocks being removed when - /// loading a structure. Integrity and {@link #getSeed()} are used together - /// to determine which blocks are randomly removed to mimic "decay." - pub fn set_integrity(&self, integrity: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(integrity); + /// Sets the type of this block state. + pub fn set_type( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Material;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setIntegrity", + "setType", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the integrity of this structure. - pub fn integrity(&self) -> Result> { - let sig = String::from("()F"); + /// Attempts to update the block represented by this state, setting it to + /// the new values as defined by this state. + /// + /// If this state is not placed, this will have no effect and return true. + /// + /// Unless force is true, this will not modify the state of a block if it + /// is no longer the same type as it was when this state was taken. It will + /// return false in this eventuality. + /// + /// If force is true, it will set the type of the block to match the new + /// state, set the state data and then return true. + /// + /// If applyPhysics is true, it will trigger a physics update on + /// surrounding blocks which could cause them to update or disappear. + pub fn update( + &self, + force: std::option::Option, + apply_physics: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = force { + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_1); + } + if let Some(a) = apply_physics { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "update", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + + pub fn raw_data(&self) -> Result> { + let sig = String::from("()B"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getIntegrity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getRawData", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + Ok(res.b()?) } - /// The seed used to determine which blocks will be removed upon loading. - /// {@link #getIntegrity()} and seed are used together to determine which - /// blocks are randomly removed to mimic "decay." - pub fn set_seed(&self, seed: i64) -> Result<(), Box> { - let sig = String::from("(J)V"); - let val_1 = jni::objects::JValueGen::Long(seed); + #[deprecated] + + pub fn set_raw_data(&self, data: i8) -> Result<(), Box> { + let sig = String::from("(B)V"); + let val_1 = jni::objects::JValueGen::Byte(data); let res = self.jni_ref().call_method( &self.jni_object(), - "setSeed", + "setRawData", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// The seed used to determine how many blocks are removed upon loading of - /// this structure. - pub fn seed(&self) -> Result> { - let sig = String::from("()J"); + /// Returns whether this state is placed in the world. + /// + /// Some methods will not work if the block state isn't + /// placed in the world. + pub fn is_placed(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getSeed", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isPlaced", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + Ok(res.z()?) } /// Sets a metadata value in the implementing object's metadata store. pub fn set_metadata( @@ -13669,12 +15014,185 @@ impl<'mc> Structure<'mc> { } Ok(new_vec) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - /// - /// This {@link PersistentDataHolder} is only linked to the snapshot instance + /// Tests to see whether the implementing object contains the given + /// metadata value in its metadata store. + pub fn has_metadata( + &self, + metadata_key: impl Into, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasMetadata", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Removes the given metadata value from the implementing object's + /// metadata store. + pub fn remove_metadata( + &self, + metadata_key: impl Into, + owning_plugin: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += "Lorg/bukkit/plugin/Plugin;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + }); + args.push(val_2); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "removeMetadata", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Campfire<'mc> { + fn into(self) -> crate::block::TileState<'mc> { + crate::block::TileState::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Campfire into crate::block::TileState") + } +} +#[repr(C)] +pub struct BrewingStand<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for BrewingStand<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for BrewingStand<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate BrewingStand from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/BrewingStand")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BrewingStand object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> BrewingStand<'mc> { + /// How much time is left in the brewing cycle. + pub fn brewing_time(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBrewingTime", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the time left before brewing completes. + pub fn set_brewing_time(&self, brew_time: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(brew_time); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBrewingTime", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the level of current fuel for brewing. + pub fn fuel_level(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFuelLevel", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the level of current fuel for brewing. + pub fn set_fuel_level(&self, level: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(level); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFuelLevel", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn snapshot_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/BrewerInventory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSnapshotInventory", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::BrewerInventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the inventory of the block represented by this block state. + /// + /// If the block was changed to a different type in the meantime, the + /// returned inventory might no longer be valid. + /// + /// If this block state is not placed this will return the captured inventory + /// snapshot instead. + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + /// + /// This {@link PersistentDataHolder} is only linked to the snapshot instance /// stored by the {@link BlockState}. /// When storing changes on the {@link PersistentDataHolder}, the updated /// content will only be applied to the actual tile entity after one of the @@ -13694,7 +15212,7 @@ impl<'mc> Structure<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the block represented by this block state. + /// Gets the block associated with this holder. pub fn block(&self) -> Result, Box> { let args = Vec::new(); let mut sig = String::from("("); @@ -13707,321 +15225,89 @@ impl<'mc> Structure<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the metadata for this block state. - pub fn data(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/MaterialData;"); + /// Checks if the container has a valid (non empty) key. + pub fn is_locked(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the data for this block state. - pub fn block_data( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBlockData", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isLocked", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Copies the state to another block as an unplaced BlockState. - pub fn copy( - &self, - location: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = location { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")Lorg/bukkit/block/BlockState;"; + /// Gets the key needed to access the container. + pub fn lock(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); + .call_method(&self.jni_object(), "getLock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the type of this block state. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let res = self + Ok(self .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the current light level of the block represented by this block state. - pub fn light_level(&self) -> Result> { - let sig = String::from("()B"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLightLevel", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Gets the world which contains the block represented by this block state. - pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the x-coordinate of this block state. - pub fn x(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the y-coordinate of this block state. - pub fn y(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the z-coordinate of this block state. - pub fn z(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Stores the location of this block state in the provided Location object. - /// - /// If the provided Location is null this method does nothing and returns - /// null. - /// - /// If this block state is not placed the location's world will be null! - pub fn get_location( - &self, - loc: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLocation", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Gets the chunk which contains the block represented by this block state. - pub fn chunk(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Chunk;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getChunk", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Chunk::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the metadata for this block state. - pub fn set_data( - &self, - data: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/material/MaterialData;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setData", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Sets the data for this block state. - pub fn set_block_data( - &self, - data: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setBlockData", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Sets the type of this block state. - pub fn set_type( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Material;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Sets the key required to access this container. Set to null (or empty + /// string) to remove key. + pub fn set_lock(&self, key: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(key.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setType", + "setLock", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Attempts to update the block represented by this state, setting it to - /// the new values as defined by this state. - /// - /// If this state is not placed, this will have no effect and return true. - /// - /// Unless force is true, this will not modify the state of a block if it - /// is no longer the same type as it was when this state was taken. It will - /// return false in this eventuality. - /// - /// If force is true, it will set the type of the block to match the new - /// state, set the state data and then return true. + /// Gets the custom name on a mob or block. If there is no name this method + /// will return null. /// - /// If applyPhysics is true, it will trigger a physics update on - /// surrounding blocks which could cause them to update or disappear. - pub fn update( - &self, - force: std::option::Option, - apply_physics: std::option::Option, - ) -> Result> { - let mut args = Vec::new(); + /// This value has no effect on players, they will always use their real + /// name. + pub fn custom_name(&self) -> Result, Box> { + let args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = force { - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_1); - } - if let Some(a) = apply_physics { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "update", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - - pub fn raw_data(&self) -> Result> { - let sig = String::from("()B"); + sig += ")Ljava/lang/String;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getRawData", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCustomName", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) - } - #[deprecated] - - pub fn set_raw_data(&self, data: i8) -> Result<(), Box> { - let sig = String::from("(B)V"); - let val_1 = jni::objects::JValueGen::Byte(data); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRawData", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Returns whether this state is placed in the world. + /// Sets a custom name on a mob or block. This name will be used in death + /// messages and can be sent to the client as a nameplate over the mob. /// - /// Some methods will not work if the block state isn't - /// placed in the world. - pub fn is_placed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isPlaced", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Tests to see whether the implementing object contains the given - /// metadata value in its metadata store. - pub fn has_metadata( - &self, - metadata_key: impl Into, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasMetadata", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Removes the given metadata value from the implementing object's - /// metadata store. - pub fn remove_metadata( + /// Setting the name to null or an empty string will clear it. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn set_custom_name( &self, - metadata_key: impl Into, - owning_plugin: impl Into>, + name: impl Into, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "Ljava/lang/String;"; let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, + self.jni_ref().new_string(name.into())?, )); args.push(val_1); - sig += "Lorg/bukkit/plugin/Plugin;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) - }); - args.push(val_2); sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "removeMetadata", sig.as_str(), args); + .call_method(&self.jni_object(), "setCustomName", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } @@ -14031,19 +15317,19 @@ impl<'mc> Structure<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Structure<'mc> { - fn into(self) -> crate::block::TileState<'mc> { - crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Structure into crate::block::TileState") +impl<'mc> Into> for BrewingStand<'mc> { + fn into(self) -> crate::block::Container<'mc> { + crate::block::Container::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BrewingStand into crate::block::Container") } } #[repr(C)] -pub struct Campfire<'mc>( +pub struct CreatureSpawner<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Campfire<'mc> { +impl<'mc> JNIRaw<'mc> for CreatureSpawner<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -14051,18 +15337,20 @@ impl<'mc> JNIRaw<'mc> for Campfire<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Campfire<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CreatureSpawner<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Campfire from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate CreatureSpawner from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Campfire")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/CreatureSpawner")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Campfire object, got {}", + "Invalid argument passed. Expected a CreatureSpawner object, got {}", name ) .into()) @@ -14072,131 +15360,46 @@ impl<'mc> JNIInstantiatable<'mc> for Campfire<'mc> { } } -impl<'mc> Campfire<'mc> { - pub fn size(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - - pub fn get_item( - &self, - index: i32, - ) -> Result>, Box> { - let sig = String::from("(I)Lorg/bukkit/inventory/ItemStack;"); - let val_1 = jni::objects::JValueGen::Int(index); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getItem", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - - pub fn set_item( +impl<'mc> CreatureSpawner<'mc> { + #[deprecated] + /// Set the spawner mob type. + pub fn set_creature_type_by_name( &self, - index: i32, - item: impl Into>, + creature_type: impl Into, ) -> Result<(), Box> { - let sig = String::from("(ILorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Int(index); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setItem", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get cook time. - /// This is the amount of time the item has been cooking for. - pub fn get_cook_time(&self, index: i32) -> Result> { - let sig = String::from("(I)I"); - let val_1 = jni::objects::JValueGen::Int(index); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(creature_type.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "getCookTime", + "setCreatureTypeByName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set cook time. - /// This is the amount of time the item has been cooking for. - pub fn set_cook_time( - &self, - index: i32, - cook_time: i32, - ) -> Result<(), Box> { - let sig = String::from("(II)V"); - let val_1 = jni::objects::JValueGen::Int(index); - let val_2 = jni::objects::JValueGen::Int(cook_time); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCookTime", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get cook time total. - /// This is the amount of time the item is required to cook for. - pub fn get_cook_time_total(&self, index: i32) -> Result> { - let sig = String::from("(I)I"); - let val_1 = jni::objects::JValueGen::Int(index); + #[deprecated] + /// Get the spawner's creature type. + pub fn creature_type_name(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCookTimeTotal", + "getCreatureTypeName", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set cook time. - /// This is the amount of time the item is required to cook for. - pub fn set_cook_time_total( - &self, - index: i32, - cook_time_total: i32, - ) -> Result<(), Box> { - let sig = String::from("(II)V"); - let val_1 = jni::objects::JValueGen::Int(index); - let val_2 = jni::objects::JValueGen::Int(cook_time_total); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCookTimeTotal", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } /// Returns a custom tag container capable of storing tags on the object. /// Note that the tags stored on this container are all stored under their @@ -14611,254 +15814,148 @@ impl<'mc> Campfire<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Campfire<'mc> { - fn into(self) -> crate::block::TileState<'mc> { - crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Campfire into crate::block::TileState") - } -} -#[repr(C)] -pub struct BrewingStand<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for BrewingStand<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for BrewingStand<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate BrewingStand from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/BrewingStand")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a BrewingStand object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> BrewingStand<'mc> { - /// How much time is left in the brewing cycle. - pub fn brewing_time(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBrewingTime", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the time left before brewing completes. - pub fn set_brewing_time(&self, brew_time: i32) -> Result<(), Box> { + /// {@inheritDoc} + /// + /// If set to -1, the spawn delay will be reset to a random value between + /// {@link #getMinSpawnDelay} and {@link #getMaxSpawnDelay()}. + pub fn set_delay(&self, delay: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(brew_time); + let val_1 = jni::objects::JValueGen::Int(delay); let res = self.jni_ref().call_method( &self.jni_object(), - "setBrewingTime", + "setDelay", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the level of current fuel for brewing. - pub fn fuel_level(&self) -> Result> { + /// The minimum spawn delay amount (in ticks). + /// + /// This value is used when the spawner resets its delay (for any reason). + /// It will choose a random number between {@link #getMinSpawnDelay()} + /// and {@link #getMaxSpawnDelay()} for its next {@link #getDelay()}. + /// + /// Default value is 200 ticks. + pub fn min_spawn_delay(&self) -> Result> { let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFuelLevel", sig.as_str(), vec![]); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMinSpawnDelay", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Set the level of current fuel for brewing. - pub fn set_fuel_level(&self, level: i32) -> Result<(), Box> { + /// Set the minimum spawn delay amount (in ticks). + pub fn set_min_spawn_delay(&self, delay: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(level); + let val_1 = jni::objects::JValueGen::Int(delay); let res = self.jni_ref().call_method( &self.jni_object(), - "setFuelLevel", + "setMinSpawnDelay", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn snapshot_inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/BrewerInventory;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSnapshotInventory", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::BrewerInventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the inventory of the block represented by this block state. + /// The maximum spawn delay amount (in ticks). /// - /// If the block was changed to a different type in the meantime, the - /// returned inventory might no longer be valid. + /// This value is used when the spawner resets its delay (for any reason). + /// It will choose a random number between {@link #getMinSpawnDelay()} + /// and {@link #getMaxSpawnDelay()} for its next {@link #getDelay()}. /// - /// If this block state is not placed this will return the captured inventory - /// snapshot instead. - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. + /// This value must be greater than 0 and less than or equal to + /// {@link #getMaxSpawnDelay()}. /// - /// This {@link PersistentDataHolder} is only linked to the snapshot instance - /// stored by the {@link BlockState}. - /// When storing changes on the {@link PersistentDataHolder}, the updated - /// content will only be applied to the actual tile entity after one of the - /// {@link #update()} methods is called. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + /// Default value is 800 ticks. + pub fn max_spawn_delay(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "getMaxSpawnDelay", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the block associated with this holder. - pub fn block(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/block/Block;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBlock", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Checks if the container has a valid (non empty) key. - pub fn is_locked(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isLocked", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the key needed to access the container. - pub fn lock(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getLock", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.i()?) } - /// Sets the key required to access this container. Set to null (or empty - /// string) to remove key. - pub fn set_lock(&self, key: impl Into) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(key.into())?, - )); + /// Set the maximum spawn delay amount (in ticks). + /// + /// This value must be greater than 0, as well as greater than or + /// equal to {@link #getMinSpawnDelay()} + pub fn set_max_spawn_delay(&self, delay: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(delay); let res = self.jni_ref().call_method( &self.jni_object(), - "setLock", + "setMaxSpawnDelay", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the custom name on a mob or block. If there is no name this method - /// will return null. + /// Get how many mobs attempt to spawn. /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn custom_name(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/lang/String;"; + /// Default value is 4. + pub fn spawn_count(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getCustomName", sig.as_str(), args); + .call_method(&self.jni_object(), "getSpawnCount", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(res.i()?) } - /// Sets a custom name on a mob or block. This name will be used in death - /// messages and can be sent to the client as a nameplate over the mob. + /// Set how many mobs attempt to spawn. + pub fn set_spawn_count(&self, spawn_count: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(spawn_count); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSpawnCount", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Set the new maximum amount of similar entities that are allowed to be + /// within spawning range of this spawner. /// - /// Setting the name to null or an empty string will clear it. + /// If more than the maximum number of entities are within range, the spawner + /// will not spawn and try again with a new {@link #getDelay()}. /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn set_custom_name( + /// Default value is 16. + pub fn max_nearby_entities(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaxNearbyEntities", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the maximum number of similar entities that are allowed to be within + /// spawning range of this spawner. + /// + /// Similar entities are entities that are of the same {@link EntityType} + pub fn set_max_nearby_entities( &self, - name: impl Into, + max_nearby_entities: i32, ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); - args.push(val_1); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setCustomName", sig.as_str(), args); + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(max_nearby_entities); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaxNearbyEntities", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } @@ -14868,19 +15965,25 @@ impl<'mc> BrewingStand<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BrewingStand<'mc> { - fn into(self) -> crate::block::Container<'mc> { - crate::block::Container::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BrewingStand into crate::block::Container") +impl<'mc> Into> for CreatureSpawner<'mc> { + fn into(self) -> crate::block::TileState<'mc> { + crate::block::TileState::from_raw(&self.jni_ref(), self.1) + .expect("Error converting CreatureSpawner into crate::block::TileState") + } +} +impl<'mc> Into> for CreatureSpawner<'mc> { + fn into(self) -> crate::spawner::Spawner<'mc> { + crate::spawner::Spawner::from_raw(&self.jni_ref(), self.1) + .expect("Error converting CreatureSpawner into crate::spawner::Spawner") } } #[repr(C)] -pub struct CreatureSpawner<'mc>( +pub struct EntityBlockStorage<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for CreatureSpawner<'mc> { +impl<'mc> JNIRaw<'mc> for EntityBlockStorage<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -14888,20 +15991,20 @@ impl<'mc> JNIRaw<'mc> for CreatureSpawner<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for CreatureSpawner<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EntityBlockStorage<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate CreatureSpawner from null object.").into(), + eyre::eyre!("Tried to instantiate EntityBlockStorage from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/CreatureSpawner")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/EntityBlockStorage")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a CreatureSpawner object, got {}", + "Invalid argument passed. Expected a EntityBlockStorage object, got {}", name ) .into()) @@ -14911,861 +16014,836 @@ impl<'mc> JNIInstantiatable<'mc> for CreatureSpawner<'mc> { } } -impl<'mc> CreatureSpawner<'mc> { - /// Get the spawner's creature type. - pub fn spawned_type( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); +impl<'mc> EntityBlockStorage<'mc> { + /// Check if the block is completely full of entities. + pub fn is_full(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFull", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the amount of entities currently in this block. + pub fn entity_count(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getSpawnedType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEntityCount", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::EntityType::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - /// Set the spawner's creature type. - /// - /// This will override any entities that have been added with {@link #addPotentialSpawn} - pub fn set_spawned_type( - &self, - creature_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/EntityType;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(creature_type.into().jni_object().clone()) - }); + /// Get the maximum amount of entities this block can hold. + pub fn max_entities(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxEntities", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the maximum amount of entities this block can hold. + pub fn set_max_entities(&self, max: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(max); let res = self.jni_ref().call_method( &self.jni_object(), - "setSpawnedType", + "setMaxEntities", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Set the spawner mob type. - pub fn set_creature_type_by_name( + /// Release all the entities currently stored in the block. + pub fn release_entities( &self, - creature_type: impl Into, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "releaseEntities", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(obj); + } + Ok(new_vec) + } + /// Add an entity to the block. + pub fn add_entity( + &self, + entity: jni::objects::JObject<'mc>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(creature_type.into())?, - )); + let sig = String::from("(LT;)V"); + let val_1 = jni::objects::JValueGen::Object(entity); let res = self.jni_ref().call_method( &self.jni_object(), - "setCreatureTypeByName", + "addEntity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Get the spawner's creature type. - pub fn creature_type_name(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + /// + /// This {@link PersistentDataHolder} is only linked to the snapshot instance + /// stored by the {@link BlockState}. + /// When storing changes on the {@link PersistentDataHolder}, the updated + /// content will only be applied to the actual tile entity after one of the + /// {@link #update()} methods is called. + pub fn persistent_data_container( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCreatureTypeName", + "getPersistentDataContainer", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the block represented by this block state. + pub fn block(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/block/Block;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBlock", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the metadata for this block state. + pub fn data(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/MaterialData;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the data for this block state. + pub fn block_data( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBlockData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Copies the state to another block as an unplaced BlockState. + pub fn copy( + &self, + location: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = location { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); } - Ok(Some( + sig += ")Lorg/bukkit/block/BlockState;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the type of this block state. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the current light level of the block represented by this block state. + pub fn light_level(&self) -> Result> { + let sig = String::from("()B"); + let res = self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + .call_method(&self.jni_object(), "getLightLevel", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.b()?) } - /// Get the spawner's delay. - /// - /// This is the delay, in ticks, until the spawner will spawn its next mob. - pub fn delay(&self) -> Result> { + /// Gets the world which contains the block represented by this block state. + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the x-coordinate of this block state. + pub fn x(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the y-coordinate of this block state. + pub fn y(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the z-coordinate of this block state. + pub fn z(&self) -> Result> { let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getDelay", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Set the spawner's delay. + /// Stores the location of this block state in the provided Location object. /// - /// If set to -1, the spawn delay will be reset to a random value between - /// {@link #getMinSpawnDelay} and {@link #getMaxSpawnDelay()}. - pub fn set_delay(&self, delay: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(delay); + /// If the provided Location is null this method does nothing and returns + /// null. + /// + /// If this block state is not placed the location's world will be null! + pub fn get_location( + &self, + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setDelay", + "getLocation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// The minimum spawn delay amount (in ticks). - /// - /// This value is used when the spawner resets its delay (for any reason). - /// It will choose a random number between {@link #getMinSpawnDelay()} - /// and {@link #getMaxSpawnDelay()} for its next {@link #getDelay()}. - /// - /// Default value is 200 ticks. - pub fn min_spawn_delay(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the chunk which contains the block represented by this block state. + pub fn chunk(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Chunk;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getChunk", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Chunk::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the metadata for this block state. + pub fn set_data( + &self, + data: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/material/MaterialData;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(data.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getMinSpawnDelay", + "setData", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Set the minimum spawn delay amount (in ticks). - pub fn set_min_spawn_delay(&self, delay: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(delay); + /// Sets the data for this block state. + pub fn set_block_data( + &self, + data: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(data.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setMinSpawnDelay", + "setBlockData", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// The maximum spawn delay amount (in ticks). - /// - /// This value is used when the spawner resets its delay (for any reason). - /// It will choose a random number between {@link #getMinSpawnDelay()} - /// and {@link #getMaxSpawnDelay()} for its next {@link #getDelay()}. - /// - /// This value must be greater than 0 and less than or equal to - /// {@link #getMaxSpawnDelay()}. - /// - /// Default value is 800 ticks. - pub fn max_spawn_delay(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMaxSpawnDelay", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the maximum spawn delay amount (in ticks). - /// - /// This value must be greater than 0, as well as greater than or - /// equal to {@link #getMinSpawnDelay()} - pub fn set_max_spawn_delay(&self, delay: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(delay); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaxSpawnDelay", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get how many mobs attempt to spawn. - /// - /// Default value is 4. - pub fn spawn_count(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSpawnCount", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set how many mobs attempt to spawn. - pub fn set_spawn_count(&self, spawn_count: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(spawn_count); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSpawnCount", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Set the new maximum amount of similar entities that are allowed to be - /// within spawning range of this spawner. - /// - /// If more than the maximum number of entities are within range, the spawner - /// will not spawn and try again with a new {@link #getDelay()}. - /// - /// Default value is 16. - pub fn max_nearby_entities(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMaxNearbyEntities", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the maximum number of similar entities that are allowed to be within - /// spawning range of this spawner. - /// - /// Similar entities are entities that are of the same {@link EntityType} - pub fn set_max_nearby_entities( + /// Sets the type of this block state. + pub fn set_type( &self, - max_nearby_entities: i32, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(max_nearby_entities); + let sig = String::from("(Lorg/bukkit/Material;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxNearbyEntities", + "setType", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the maximum distance(squared) a player can be in order for this - /// spawner to be active. + /// Attempts to update the block represented by this state, setting it to + /// the new values as defined by this state. /// - /// If this value is less than or equal to 0, this spawner is always active - /// (given that there are players online). + /// If this state is not placed, this will have no effect and return true. /// - /// Default value is 16. - pub fn required_player_range(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getRequiredPlayerRange", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the maximum distance (squared) a player can be in order for this - /// spawner to be active. + /// Unless force is true, this will not modify the state of a block if it + /// is no longer the same type as it was when this state was taken. It will + /// return false in this eventuality. /// - /// Setting this value to less than or equal to 0 will make this spawner - /// always active (given that there are players online). - pub fn set_required_player_range( + /// If force is true, it will set the type of the block to match the new + /// state, set the state data and then return true. + /// + /// If applyPhysics is true, it will trigger a physics update on + /// surrounding blocks which could cause them to update or disappear. + pub fn update( &self, - required_player_range: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(required_player_range); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRequiredPlayerRange", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + force: std::option::Option, + apply_physics: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = force { + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_1); + } + if let Some(a) = apply_physics { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "update", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Get the radius around which the spawner will attempt to spawn mobs in. - /// - /// This area is square, includes the block the spawner is in, and is - /// centered on the spawner's x,z coordinates - not the spawner itself. - /// - /// It is 2 blocks high, centered on the spawner's y-coordinate (its bottom); - /// thus allowing mobs to spawn as high as its top surface and as low - /// as 1 block below its bottom surface. - /// - /// Default value is 4. - pub fn spawn_range(&self) -> Result> { - let sig = String::from("()I"); + #[deprecated] + + pub fn raw_data(&self) -> Result> { + let sig = String::from("()B"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getSpawnRange", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getRawData", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.b()?) } - /// Set the new spawn range. - /// - pub fn set_spawn_range(&self, spawn_range: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(spawn_range); + #[deprecated] + + pub fn set_raw_data(&self, data: i8) -> Result<(), Box> { + let sig = String::from("(B)V"); + let val_1 = jni::objects::JValueGen::Byte(data); let res = self.jni_ref().call_method( &self.jni_object(), - "setSpawnRange", + "setRawData", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the {@link EntitySnapshot} that will be spawned by this spawner or null - /// if no entities have been assigned to this spawner. - /// - /// - /// All applicable data from the spawner will be copied, such as custom name, - /// health, and velocity. + /// Returns whether this state is placed in the world. /// - pub fn spawned_entity( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSpawnedEntity", - sig.as_str(), - vec![], - ); + /// Some methods will not work if the block state isn't + /// placed in the world. + pub fn is_placed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isPlaced", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::EntitySnapshot::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Sets the entity that will be spawned by this spawner. - /// - /// This will override any previous entries that have been added with - /// {@link #addPotentialSpawn} - /// - /// All applicable data from the snapshot will be copied, such as custom name, - /// health, and velocity. - /// - pub fn set_spawned_entity( - &self, - snapshot: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/EntitySnapshot;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(snapshot.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSpawnedEntity", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.z()?) } - /// Adds a new {@link EntitySnapshot} to the list of entities this spawner can - /// spawn. - /// - /// The weight will determine how often this entry is chosen to spawn, higher - /// weighted entries will spawn more often than lower weighted ones. - /// - /// The {@link SpawnRule} will determine under what conditions this entry can - /// spawn, passing null will use the default conditions for the given entity. - pub fn add_potential_spawn( + /// Sets a metadata value in the implementing object's metadata store. + pub fn set_metadata( &self, - snapshot: impl Into>, - weight: std::option::Option, - spawn_rule: std::option::Option>>, + metadata_key: impl Into, + new_metadata_value: std::option::Option>>, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/EntitySnapshot;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(snapshot.into().jni_object().clone()) - }); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); args.push(val_1); - if let Some(a) = weight { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - if let Some(a) = spawn_rule { - sig += "Lorg/bukkit/block/spawner/SpawnRule;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { + if let Some(a) = new_metadata_value { + sig += "Lorg/bukkit/metadata/MetadataValue;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); - args.push(val_3); + args.push(val_2); } sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "addPotentialSpawn", sig.as_str(), args); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setMetadata", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets a list of potential spawns from this spawner or an empty list if no - /// entities have been assigned to this spawner. - /// - /// Changes made to the returned list will not be reflected in the spawner unless - /// applied with {@link #setPotentialSpawns} - pub fn potential_spawns( + /// Returns a list of previously set metadata values from the implementing + /// object's metadata store. + pub fn get_metadata( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPotentialSpawns", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); + metadata_key: impl Into, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += ")Ljava/util/List;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getMetadata", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::block::spawner::SpawnerEntry::from_raw( + new_vec.push(crate::metadata::MetadataValue::from_raw( &self.jni_ref(), obj, )?); } Ok(new_vec) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - /// - /// This {@link PersistentDataHolder} is only linked to the snapshot instance - /// stored by the {@link BlockState}. - /// When storing changes on the {@link PersistentDataHolder}, the updated - /// content will only be applied to the actual tile entity after one of the - /// {@link #update()} methods is called. - pub fn persistent_data_container( + /// Tests to see whether the implementing object contains the given + /// metadata value in its metadata store. + pub fn has_metadata( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPersistentDataContainer", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the block represented by this block state. - pub fn block(&self) -> Result, Box> { - let args = Vec::new(); + metadata_key: impl Into, + ) -> Result> { + let mut args = Vec::new(); let mut sig = String::from("("); - sig += ")Lorg/bukkit/block/Block;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBlock", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the metadata for this block state. - pub fn data(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/MaterialData;"); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasMetadata", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Gets the data for this block state. - pub fn block_data( + /// Removes the given metadata value from the implementing object's + /// metadata store. + pub fn remove_metadata( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); + metadata_key: impl Into, + owning_plugin: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += "Lorg/bukkit/plugin/Plugin;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + }); + args.push(val_2); + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getBlockData", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + .call_method(&self.jni_object(), "removeMetadata", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Copies the state to another block as an unplaced BlockState. - pub fn copy( + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for EntityBlockStorage<'mc> { + fn into(self) -> crate::block::TileState<'mc> { + crate::block::TileState::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EntityBlockStorage into crate::block::TileState") + } +} +#[repr(C)] +pub struct BlockType<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for BlockType<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for BlockType<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate BlockType from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/BlockType")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BlockType object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> BlockType<'mc> { + /// Yields this block type as a typed version of itself with a specific {@link BlockData} representing it. + pub fn typed( &self, - location: std::option::Option>>, - ) -> Result, Box> { + block_data_type: std::option::Option>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = location { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); + if let Some(a) = block_data_type { + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(a.into()); args.push(val_1); } - sig += ")Lorg/bukkit/block/BlockState;"; + sig += ")Lorg/bukkit/block/BlockType/Typed;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); + .call_method(&self.jni_object(), "typed", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { + crate::block::BlockTypeTyped::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the type of this block state. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + /// Returns true if this BlockType has a corresponding {@link ItemType}. + pub fn has_item_type(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasItemType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Gets the current light level of the block represented by this block state. - pub fn light_level(&self) -> Result> { - let sig = String::from("()B"); + /// Returns the corresponding {@link ItemType} for the given BlockType. + /// + /// If there is no corresponding {@link ItemType} an error will be thrown. + pub fn item_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemType;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLightLevel", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItemType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) + crate::inventory::ItemType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the world which contains the block represented by this block state. - pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + /// Gets the BlockData class of this BlockType + pub fn block_data_class( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/lang/Class;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBlockDataClass", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { + Ok(unsafe { jni::objects::JClass::from_raw(res.as_jni().l) }) + } + /// Creates a new {@link BlockData} instance for this block type, with all + /// properties initialized to unspecified defaults, except for those provided + /// in data. + pub fn create_block_data( + &self, + data: std::option::Option>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = data { + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_1); + } + sig += ")Lorg/bukkit/block/data/BlockData;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createBlockData", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the x-coordinate of this block state. - pub fn x(&self) -> Result> { - let sig = String::from("()I"); + /// Check if the blockt type is solid (can be built upon) + pub fn is_solid(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSolid", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Gets the y-coordinate of this block state. - pub fn y(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); + /// Check if the block type can catch fire + pub fn is_flammable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isFlammable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Gets the z-coordinate of this block state. - pub fn z(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); + /// Check if the block type can burn away + pub fn is_burnable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isBurnable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Stores the location of this block state in the provided Location object. + /// Check if the block type is occludes light in the lighting engine. /// - /// If the provided Location is null this method does nothing and returns - /// null. + /// Generally speaking, most full blocks will occlude light. Non-full blocks are + /// not occluding (e.g. anvils, chests, tall grass, stairs, etc.), nor are specific + /// full blocks such as barriers or spawners which block light despite their texture. /// - /// If this block state is not placed the location's world will be null! - pub fn get_location( + /// An occluding block will have the following effects: + ///
    + ///
  • Chests cannot be opened if an occluding block is above it. + ///
  • Mobs cannot spawn inside of occluding blocks. + ///
  • Only occluding blocks can be "powered" ({@link Block#isBlockPowered()}). + ///
+ /// This list may be inconclusive. For a full list of the side effects of an occluding + /// block, see the Minecraft Wiki. + pub fn is_occluding(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isOccluding", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn has_gravity(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks if this block type can be interacted with. + /// + /// Interactable block types include those with functionality when they are + /// interacted with by a player such as chests, furnaces, etc. + /// + /// Some blocks such as piston heads and stairs are considered interactable + /// though may not perform any additional functionality. + /// + /// Note that the interactability of some block types may be dependant on their + /// state as well. This method will return true if there is at least one + /// state in which additional interact handling is performed for the + /// block type. + pub fn is_interactable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInteractable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Obtains the block's hardness level (also known as "strength"). + /// + /// This number is used to calculate the time required to break each block. + pub fn hardness(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHardness", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Obtains the blast resistance value (also known as block "durability"). + /// + /// This value is used in explosions to calculate whether a block should be + /// broken or not. + pub fn blast_resistance(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBlastResistance", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Returns a value that represents how 'slippery' the block is. + /// + /// Blocks with higher slipperiness, like {@link BlockType#ICE} can be slid on + /// further by the player and other entities. + /// + /// Most blocks have a default slipperiness of {@code 0.6f}. + pub fn slipperiness(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSlipperiness", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Check if the block type is an air block. + pub fn is_air(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isAir", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets if the BlockType is enabled by the features in a world. + pub fn is_enabled_by_feature( &self, - loc: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + world: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/World;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + jni::objects::JObject::from_raw(world.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocation", + "isEnabledByFeature", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Tries to convert this BlockType into a Material + pub fn as_material(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "asMaterial", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + Ok(Some(crate::Material::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) })?)) } - /// Gets the chunk which contains the block represented by this block state. - pub fn chunk(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Chunk;"); + /// Return the namespaced identifier for this object. + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getChunk", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Chunk::from_raw(&self.jni_ref(), unsafe { + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the metadata for this block state. - pub fn set_data( - &self, - data: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/material/MaterialData;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) - }); + /// Get the translation key, suitable for use in a translation component. + pub fn translation_key(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setData", + "getTranslationKey", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets the data for this block state. - pub fn set_block_data( - &self, - data: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setBlockData", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Sets the type of this block state. - pub fn set_type( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Material;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setType", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Attempts to update the block represented by this state, setting it to - /// the new values as defined by this state. - /// - /// If this state is not placed, this will have no effect and return true. - /// - /// Unless force is true, this will not modify the state of a block if it - /// is no longer the same type as it was when this state was taken. It will - /// return false in this eventuality. - /// - /// If force is true, it will set the type of the block to match the new - /// state, set the state data and then return true. - /// - /// If applyPhysics is true, it will trigger a physics update on - /// surrounding blocks which could cause them to update or disappear. - pub fn update( - &self, - force: std::option::Option, - apply_physics: std::option::Option, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = force { - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_1); - } - if let Some(a) = apply_physics { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "update", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - - pub fn raw_data(&self) -> Result> { - let sig = String::from("()B"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRawData", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) - } - #[deprecated] - - pub fn set_raw_data(&self, data: i8) -> Result<(), Box> { - let sig = String::from("(B)V"); - let val_1 = jni::objects::JValueGen::Byte(data); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRawData", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns whether this state is placed in the world. - /// - /// Some methods will not work if the block state isn't - /// placed in the world. - pub fn is_placed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isPlaced", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets a metadata value in the implementing object's metadata store. - pub fn set_metadata( - &self, - metadata_key: impl Into, - new_metadata_value: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - if let Some(a) = new_metadata_value { - sig += "Lorg/bukkit/metadata/MetadataValue;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setMetadata", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns a list of previously set metadata values from the implementing - /// object's metadata store. - pub fn get_metadata( - &self, - metadata_key: impl Into, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += ")Ljava/util/List;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getMetadata", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::metadata::MetadataValue::from_raw( - &self.jni_ref(), - obj, - )?); - } - Ok(new_vec) - } - /// Tests to see whether the implementing object contains the given - /// metadata value in its metadata store. - pub fn has_metadata( - &self, - metadata_key: impl Into, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasMetadata", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Removes the given metadata value from the implementing object's - /// metadata store. - pub fn remove_metadata( - &self, - metadata_key: impl Into, - owning_plugin: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += "Lorg/bukkit/plugin/Plugin;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) - }); - args.push(val_2); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "removeMetadata", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) +} +impl<'mc> Into> for BlockType<'mc> { + fn into(self) -> crate::Keyed<'mc> { + crate::Keyed::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockType into crate::Keyed") } } -impl<'mc> Into> for CreatureSpawner<'mc> { - fn into(self) -> crate::block::TileState<'mc> { - crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting CreatureSpawner into crate::block::TileState") +impl<'mc> Into> for BlockType<'mc> { + fn into(self) -> crate::Translatable<'mc> { + crate::Translatable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockType into crate::Translatable") } } #[repr(C)] -pub struct EntityBlockStorage<'mc>( +pub struct BlockTypeTyped<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EntityBlockStorage<'mc> { +impl<'mc> JNIRaw<'mc> for BlockTypeTyped<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -15773,20 +16851,20 @@ impl<'mc> JNIRaw<'mc> for EntityBlockStorage<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EntityBlockStorage<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockTypeTyped<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate EntityBlockStorage from null object.").into(), + eyre::eyre!("Tried to instantiate BlockTypeTyped from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/EntityBlockStorage")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/BlockType/Typed")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityBlockStorage object, got {}", + "Invalid argument passed. Expected a BlockTypeTyped object, got {}", name ) .into()) @@ -15796,81 +16874,311 @@ impl<'mc> JNIInstantiatable<'mc> for EntityBlockStorage<'mc> { } } -impl<'mc> EntityBlockStorage<'mc> { - /// Check if the block is completely full of entities. - pub fn is_full(&self) -> Result> { - let sig = String::from("()Z"); +impl<'mc> BlockTypeTyped<'mc> { + /// Gets the BlockData class of this BlockType + pub fn block_data_class( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/lang/Class;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBlockDataClass", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(unsafe { jni::objects::JClass::from_raw(res.as_jni().l) }) + } + /// Creates a new {@link BlockData} instance for this block type, with all + /// properties initialized to unspecified defaults. + pub fn create_block_data( + &self, + ) -> Result, Box> { + let sig = String::from("()LB;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createBlockData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) + } + /// Yields this block type as a typed version of itself with a specific {@link BlockData} representing it. + pub fn typed( + &self, + block_data_type: std::option::Option>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = block_data_type { + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(a.into()); + args.push(val_1); + } + sig += ")Lorg/bukkit/block/BlockType/Typed;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isFull", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "typed", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::BlockTypeTyped::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get the amount of entities currently in this block. - pub fn entity_count(&self) -> Result> { - let sig = String::from("()I"); + /// Returns true if this BlockType has a corresponding {@link ItemType}. + pub fn has_item_type(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getEntityCount", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasItemType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Get the maximum amount of entities this block can hold. - pub fn max_entities(&self) -> Result> { - let sig = String::from("()I"); + /// Returns the corresponding {@link ItemType} for the given BlockType. + /// + /// If there is no corresponding {@link ItemType} an error will be thrown. + pub fn item_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemType;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxEntities", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItemType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::inventory::ItemType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the maximum amount of entities this block can hold. - pub fn set_max_entities(&self, max: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(max); + /// Check if the blockt type is solid (can be built upon) + pub fn is_solid(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSolid", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Check if the block type can catch fire + pub fn is_flammable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isFlammable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Check if the block type can burn away + pub fn is_burnable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isBurnable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Check if the block type is occludes light in the lighting engine. + /// + /// Generally speaking, most full blocks will occlude light. Non-full blocks are + /// not occluding (e.g. anvils, chests, tall grass, stairs, etc.), nor are specific + /// full blocks such as barriers or spawners which block light despite their texture. + /// + /// An occluding block will have the following effects: + ///
    + ///
  • Chests cannot be opened if an occluding block is above it. + ///
  • Mobs cannot spawn inside of occluding blocks. + ///
  • Only occluding blocks can be "powered" ({@link Block#isBlockPowered()}). + ///
+ /// This list may be inconclusive. For a full list of the side effects of an occluding + /// block, see the Minecraft Wiki. + pub fn is_occluding(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isOccluding", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn has_gravity(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks if this block type can be interacted with. + /// + /// Interactable block types include those with functionality when they are + /// interacted with by a player such as chests, furnaces, etc. + /// + /// Some blocks such as piston heads and stairs are considered interactable + /// though may not perform any additional functionality. + /// + /// Note that the interactability of some block types may be dependant on their + /// state as well. This method will return true if there is at least one + /// state in which additional interact handling is performed for the + /// block type. + pub fn is_interactable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInteractable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Obtains the block's hardness level (also known as "strength"). + /// + /// This number is used to calculate the time required to break each block. + pub fn hardness(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHardness", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Obtains the blast resistance value (also known as block "durability"). + /// + /// This value is used in explosions to calculate whether a block should be + /// broken or not. + pub fn blast_resistance(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxEntities", + "getBlastResistance", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) } - /// Release all the entities currently stored in the block. - pub fn release_entities( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + /// Returns a value that represents how 'slippery' the block is. + /// + /// Blocks with higher slipperiness, like {@link BlockType#ICE} can be slid on + /// further by the player and other entities. + /// + /// Most blocks have a default slipperiness of {@code 0.6f}. + pub fn slipperiness(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "releaseEntities", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSlipperiness", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(obj); - } - Ok(new_vec) + Ok(res.f()?) } - /// Add an entity to the block. - pub fn add_entity( + /// Check if the block type is an air block. + pub fn is_air(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isAir", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets if the BlockType is enabled by the features in a world. + pub fn is_enabled_by_feature( &self, - entity: jni::objects::JObject<'mc>, - ) -> Result<(), Box> { - let sig = String::from("(LT;)V"); - let val_1 = jni::objects::JValueGen::Object(entity); + world: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/World;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(world.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "addEntity", + "isEnabledByFeature", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Tries to convert this BlockType into a Material + pub fn as_material(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "asMaterial", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Return the namespaced identifier for this object. + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the translation key, suitable for use in a translation component. + pub fn translation_key(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTranslationKey", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for BlockTypeTyped<'mc> { + fn into(self) -> crate::block::BlockType<'mc> { + crate::block::BlockType::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockTypeTyped into crate::block::BlockType") + } +} +#[repr(C)] +pub struct Bed<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Bed<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Bed<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Bed from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Bed")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Bed object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } +} + +impl<'mc> Bed<'mc> { /// Returns a custom tag container capable of storing tags on the object. /// Note that the tags stored on this container are all stored under their /// own custom namespace therefore modifying default tags using this @@ -16284,25 +17592,69 @@ impl<'mc> EntityBlockStorage<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for EntityBlockStorage<'mc> { - fn into(self) -> crate::block::TileState<'mc> { - crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EntityBlockStorage into crate::block::TileState") + /// Gets the color of this object. + /// + /// This may be null to represent the default color of an object, if the + /// object has a special default color (e.g Shulkers). + pub fn color(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/DyeColor;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::DyeColor::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Sets the color of this object to the specified DyeColor. + /// + /// This may be null to represent the default color of an object, if the + /// object has a special default color (e.g Shulkers). + pub fn set_color( + &self, + color: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/DyeColor;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(color.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setColor", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Bed<'mc> { + fn into(self) -> crate::block::TileState<'mc> { + crate::block::TileState::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Bed into crate::block::TileState") + } +} +impl<'mc> Into> for Bed<'mc> { + fn into(self) -> crate::material::Colorable<'mc> { + crate::material::Colorable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Bed into crate::material::Colorable") } } #[repr(C)] -pub struct Bed<'mc>( +pub struct Crafter<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Bed<'mc> { +impl<'mc> JNIRaw<'mc> for Crafter<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -16310,18 +17662,18 @@ impl<'mc> JNIRaw<'mc> for Bed<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Bed<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Crafter<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Bed from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Crafter from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Bed")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/Crafter")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Bed object, got {}", + "Invalid argument passed. Expected a Crafter object, got {}", name ) .into()) @@ -16331,7 +17683,132 @@ impl<'mc> JNIInstantiatable<'mc> for Bed<'mc> { } } -impl<'mc> Bed<'mc> { +impl<'mc> Crafter<'mc> { + /// Gets the number of ticks which this block will remain in the crafting + /// state for. + pub fn crafting_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCraftingTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the number of ticks which this block will remain in the crafting + /// state for. + pub fn set_crafting_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCraftingTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether the slot at the specified index is disabled and will not + /// have items placed in it. + pub fn is_slot_disabled(&self, slot: i32) -> Result> { + let sig = String::from("(I)Z"); + let val_1 = jni::objects::JValueGen::Int(slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isSlotDisabled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the slot at the specified index is disabled and will not + /// have items placed in it. + pub fn set_slot_disabled( + &self, + slot: i32, + disabled: bool, + ) -> Result<(), Box> { + let sig = String::from("(IZ)V"); + let val_1 = jni::objects::JValueGen::Int(slot); + let val_2 = jni::objects::JValueGen::Bool(disabled.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSlotDisabled", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether this Crafter is powered. + pub fn is_triggered(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isTriggered", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether this Crafter is powered. + pub fn set_triggered(&self, triggered: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(triggered.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTriggered", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the inventory of the block represented by this block state. + /// + /// If the block was changed to a different type in the meantime, the + /// returned inventory might no longer be valid. + /// + /// If this block state is not placed this will return the captured inventory + /// snapshot instead. + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the captured inventory snapshot of this container. + /// + /// The returned inventory is not linked to any block. Any modifications to + /// the returned inventory will not be applied to the block represented by + /// this block state up until {@link #update(boolean, boolean)} has been + /// called. + pub fn snapshot_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSnapshotInventory", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } /// Returns a custom tag container capable of storing tags on the object. /// Note that the tags stored on this container are all stored under their /// own custom namespace therefore modifying default tags using this @@ -16357,7 +17834,7 @@ impl<'mc> Bed<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the block represented by this block state. + /// Gets the block associated with this holder. pub fn block(&self) -> Result, Box> { let args = Vec::new(); let mut sig = String::from("("); @@ -16370,418 +17847,156 @@ impl<'mc> Bed<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the metadata for this block state. - pub fn data(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/MaterialData;"); + /// Checks if the container has a valid (non empty) key. + pub fn is_locked(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the data for this block state. - pub fn block_data( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBlockData", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isLocked", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Copies the state to another block as an unplaced BlockState. - pub fn copy( - &self, - location: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = location { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")Lorg/bukkit/block/BlockState;"; + /// Gets the key needed to access the container. + pub fn lock(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); + .call_method(&self.jni_object(), "getLock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the type of this block state. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let res = self + Ok(self .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the current light level of the block represented by this block state. - pub fn light_level(&self) -> Result> { - let sig = String::from("()B"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLightLevel", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) - } - /// Gets the world which contains the block represented by this block state. - pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the x-coordinate of this block state. - pub fn x(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the y-coordinate of this block state. - pub fn y(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the z-coordinate of this block state. - pub fn z(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Stores the location of this block state in the provided Location object. - /// - /// If the provided Location is null this method does nothing and returns - /// null. - /// - /// If this block state is not placed the location's world will be null! - pub fn get_location( - &self, - loc: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) - }); + /// Sets the key required to access this container. Set to null (or empty + /// string) to remove key. + pub fn set_lock(&self, key: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(key.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocation", + "setLock", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the custom name on a mob or block. If there is no name this method + /// will return null. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn custom_name(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/lang/String;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCustomName", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Gets the chunk which contains the block represented by this block state. - pub fn chunk(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Chunk;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getChunk", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Chunk::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the metadata for this block state. - pub fn set_data( - &self, - data: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/material/MaterialData;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setData", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Sets the data for this block state. - pub fn set_block_data( + /// Sets a custom name on a mob or block. This name will be used in death + /// messages and can be sent to the client as a nameplate over the mob. + /// + /// Setting the name to null or an empty string will clear it. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn set_custom_name( &self, - data: impl Into>, + name: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setBlockData", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setCustomName", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets the type of this block state. - pub fn set_type( + /// Set the loot table for a container or entity. + /// + /// To remove a loot table use null. Do not use {@link LootTables#EMPTY} to + /// clear a LootTable. + pub fn set_loot_table( &self, - val_type: impl Into>, + table: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Material;)V"); + let sig = String::from("(Lorg/bukkit/loot/LootTable;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(table.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setType", + "setLootTable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Attempts to update the block represented by this state, setting it to - /// the new values as defined by this state. - /// - /// If this state is not placed, this will have no effect and return true. - /// - /// Unless force is true, this will not modify the state of a block if it - /// is no longer the same type as it was when this state was taken. It will - /// return false in this eventuality. - /// - /// If force is true, it will set the type of the block to match the new - /// state, set the state data and then return true. + /// Gets the Loot Table attached to this block or entity. /// - /// If applyPhysics is true, it will trigger a physics update on - /// surrounding blocks which could cause them to update or disappear. - pub fn update( + /// If an block/entity does not have a loot table, this will return null, NOT + /// an empty loot table. + pub fn loot_table( &self, - force: std::option::Option, - apply_physics: std::option::Option, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = force { - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_1); - } - if let Some(a) = apply_physics { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "update", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - - pub fn raw_data(&self) -> Result> { - let sig = String::from("()B"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/loot/LootTable;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getRawData", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLootTable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::loot::LootTable::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - #[deprecated] - - pub fn set_raw_data(&self, data: i8) -> Result<(), Box> { - let sig = String::from("(B)V"); - let val_1 = jni::objects::JValueGen::Byte(data); + /// Set the seed used when this Loot Table generates loot. + pub fn set_seed(&self, seed: i64) -> Result<(), Box> { + let sig = String::from("(J)V"); + let val_1 = jni::objects::JValueGen::Long(seed); let res = self.jni_ref().call_method( &self.jni_object(), - "setRawData", + "setSeed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether this state is placed in the world. + /// Get the Loot Table's seed. /// - /// Some methods will not work if the block state isn't - /// placed in the world. - pub fn is_placed(&self) -> Result> { - let sig = String::from("()Z"); + /// The seed is used when generating loot. + pub fn seed(&self) -> Result> { + let sig = String::from("()J"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isPlaced", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSeed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets a metadata value in the implementing object's metadata store. - pub fn set_metadata( - &self, - metadata_key: impl Into, - new_metadata_value: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - if let Some(a) = new_metadata_value { - sig += "Lorg/bukkit/metadata/MetadataValue;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setMetadata", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns a list of previously set metadata values from the implementing - /// object's metadata store. - pub fn get_metadata( - &self, - metadata_key: impl Into, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += ")Ljava/util/List;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getMetadata", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::metadata::MetadataValue::from_raw( - &self.jni_ref(), - obj, - )?); - } - Ok(new_vec) - } - /// Tests to see whether the implementing object contains the given - /// metadata value in its metadata store. - pub fn has_metadata( - &self, - metadata_key: impl Into, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasMetadata", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Removes the given metadata value from the implementing object's - /// metadata store. - pub fn remove_metadata( - &self, - metadata_key: impl Into, - owning_plugin: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += "Lorg/bukkit/plugin/Plugin;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) - }); - args.push(val_2); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "removeMetadata", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the color of this object. - /// - /// This may be null to represent the default color of an object, if the - /// object has a special default color (e.g Shulkers). - pub fn color(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/DyeColor;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::DyeColor::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Sets the color of this object to the specified DyeColor. - /// - /// This may be null to represent the default color of an object, if the - /// object has a special default color (e.g Shulkers). - pub fn set_color( - &self, - color: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/DyeColor;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setColor", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.j()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -16789,16 +18004,16 @@ impl<'mc> Bed<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Bed<'mc> { - fn into(self) -> crate::block::TileState<'mc> { - crate::block::TileState::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Bed into crate::block::TileState") +impl<'mc> Into> for Crafter<'mc> { + fn into(self) -> crate::block::Container<'mc> { + crate::block::Container::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Crafter into crate::block::Container") } } -impl<'mc> Into> for Bed<'mc> { - fn into(self) -> crate::material::Colorable<'mc> { - crate::material::Colorable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Bed into crate::material::Colorable") +impl<'mc> Into> for Crafter<'mc> { + fn into(self) -> crate::loot::Lootable<'mc> { + crate::loot::Lootable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Crafter into crate::loot::Lootable") } } #[repr(C)] @@ -17896,25 +19111,43 @@ impl<'mc> Into> for DaylightDetector<'mc> { .expect("Error converting DaylightDetector into crate::block::TileState") } } -pub enum BlockFace<'mc> {} -impl<'mc> std::fmt::Display for BlockFace<'mc> { +pub enum BlockSupport<'mc> { + Full { inner: BlockSupportStruct<'mc> }, + Center { inner: BlockSupportStruct<'mc> }, + Rigid { inner: BlockSupportStruct<'mc> }, +} +impl<'mc> std::fmt::Display for BlockSupport<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + BlockSupport::Full { .. } => f.write_str("FULL"), + BlockSupport::Center { .. } => f.write_str("CENTER"), + BlockSupport::Rigid { .. } => f.write_str("RIGID"), + } + } +} +impl<'mc> std::ops::Deref for BlockSupport<'mc> { + type Target = BlockSupportStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + BlockSupport::Full { inner } => inner, + BlockSupport::Center { inner } => inner, + BlockSupport::Rigid { inner } => inner, + } } } -impl<'mc> BlockFace<'mc> { +impl<'mc> BlockSupport<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/block/BlockFace"); + let cls = env.find_class("org/bukkit/block/BlockSupport"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/block/BlockFace;", + "(Ljava/lang/String;)Lorg/bukkit/block/BlockSupport;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -17926,37 +19159,55 @@ impl<'mc> BlockFace<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "FULL" => Ok(BlockSupport::Full { + inner: BlockSupportStruct::from_raw(env, obj)?, + }), + "CENTER" => Ok(BlockSupport::Center { + inner: BlockSupportStruct::from_raw(env, obj)?, + }), + "RIGID" => Ok(BlockSupport::Rigid { + inner: BlockSupportStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct BlockFaceStruct<'mc>( +pub struct BlockSupportStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockFace<'mc> { +impl<'mc> JNIRaw<'mc> for BlockSupport<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Full { inner } => inner.0.clone(), + Self::Center { inner } => inner.0.clone(), + Self::Rigid { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Full { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Center { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Rigid { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for BlockFace<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockSupport<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate BlockFace from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate BlockSupport from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/BlockFace")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/BlockSupport")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockFace object, got {}", + "Invalid argument passed. Expected a BlockSupport object, got {}", name ) .into()) @@ -17968,13 +19219,22 @@ impl<'mc> JNIInstantiatable<'mc> for BlockFace<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "FULL" => Ok(BlockSupport::Full { + inner: BlockSupportStruct::from_raw(env, obj)?, + }), + "CENTER" => Ok(BlockSupport::Center { + inner: BlockSupportStruct::from_raw(env, obj)?, + }), + "RIGID" => Ok(BlockSupport::Rigid { + inner: BlockSupportStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for BlockFaceStruct<'mc> { +impl<'mc> JNIRaw<'mc> for BlockSupportStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -17982,20 +19242,20 @@ impl<'mc> JNIRaw<'mc> for BlockFaceStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockFaceStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockSupportStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate BlockFaceStruct from null object.").into(), + eyre::eyre!("Tried to instantiate BlockSupportStruct from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/BlockFace")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/BlockSupport")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockFaceStruct object, got {}", + "Invalid argument passed. Expected a BlockSupportStruct object, got {}", name ) .into()) @@ -18005,205 +19265,763 @@ impl<'mc> JNIInstantiatable<'mc> for BlockFaceStruct<'mc> { } } -impl<'mc> BlockFaceStruct<'mc> { +impl<'mc> BlockSupportStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let cls = jni.find_class("org/bukkit/block/BlockFace"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockSupport;"); + let cls = jni.find_class("org/bukkit/block/BlockSupport"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::block::BlockFace::from_raw(&jni, obj) + crate::block::BlockSupport::from_raw(&jni, obj) } - /// Get the amount of X-coordinates to modify to get the represented block - pub fn mod_x(&self) -> Result> { + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct TrialSpawner<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for TrialSpawner<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for TrialSpawner<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate TrialSpawner from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/block/TrialSpawner")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a TrialSpawner object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> TrialSpawner<'mc> { + /// Gets the length in ticks the spawner will stay in cooldown for. + pub fn cooldown_length(&self) -> Result> { let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getModX", sig.as_str(), vec![]); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCooldownLength", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Get the amount of Y-coordinates to modify to get the represented block - pub fn mod_y(&self) -> Result> { + /// Sets the length in ticks the spawner will stay in cooldown for. + pub fn set_cooldown_length(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCooldownLength", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the maximum distance(squared) a player can be in order for this + /// spawner to be active. + /// + /// If this value is less than or equal to 0, this spawner is always active + /// (given that there are players online). + /// + /// Default value is 16. + pub fn required_player_range(&self) -> Result> { let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getRequiredPlayerRange", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the maximum distance (squared) a player can be in order for this + /// spawner to be active. + /// + /// Setting this value to less than or equal to 0 will make this spawner + /// always active (given that there are players online). + pub fn set_required_player_range( + &self, + required_player_range: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(required_player_range); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRequiredPlayerRange", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the players this spawner is currently tracking. + /// + /// Note: the returned collection is immutable, use + /// {@link #startTrackingPlayer(Player)} or {@link #stopTrackingPlayer(Player)} + /// instead. + pub fn tracked_players( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTrackedPlayers", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Player::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Checks if this spawner is currently tracking the provided player. + pub fn is_tracking_player( + &self, + player: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Player;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(player.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isTrackingPlayer", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Force this spawner to start tracking the provided player. + /// + /// Note: the spawner may decide to stop tracking this player at any given + /// time. + pub fn start_tracking_player( + &self, + player: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Player;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(player.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "startTrackingPlayer", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Force this spawner to stop tracking the provided player. + /// + /// Note: the spawner may decide to start tracking this player again at + /// any given time. + pub fn stop_tracking_player( + &self, + player: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Player;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(player.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "stopTrackingPlayer", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets a list of entities this spawner is currently tracking. + /// + /// Note: the returned collection is immutable, use + /// {@link #startTrackingEntity(Entity)} or {@link #stopTrackingEntity(Entity)} + /// instead. + pub fn tracked_entities( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTrackedEntities", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Checks if this spawner is currently tracking the provided entity. + pub fn is_tracking_entity( + &self, + entity: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isTrackingEntity", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Force this spawner to start tracking the provided entity. + /// + /// Note: the spawner may decide to stop tracking this entity at any given + /// time. + pub fn start_tracking_entity( + &self, + entity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "startTrackingEntity", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Force this spawner to stop tracking the provided entity. + /// + /// Note: the spawner may decide to start tracking this entity again at + /// any given time. + pub fn stop_tracking_entity( + &self, + entity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "stopTrackingEntity", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if this spawner is using the ominous + /// {@link TrialSpawnerConfiguration}. + pub fn is_ominous(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getModY", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isOminous", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Get the amount of Z-coordinates to modify to get the represented block - pub fn mod_z(&self) -> Result> { - let sig = String::from("()I"); + /// Changes this spawner between the normal and ominous + /// {@link TrialSpawnerConfiguration}. + pub fn set_ominous(&self, ominous: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(ominous.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setOminous", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the {@link TrialSpawnerConfiguration} used when {@link #isOminous()} is + /// false. + pub fn normal_configuration( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/spawner/TrialSpawnerConfiguration;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNormalConfiguration", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::spawner::TrialSpawnerConfiguration::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the {@link TrialSpawnerConfiguration} used when {@link #isOminous()} is + /// true. + pub fn ominous_configuration( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/spawner/TrialSpawnerConfiguration;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getOminousConfiguration", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::spawner::TrialSpawnerConfiguration::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + /// + /// This {@link PersistentDataHolder} is only linked to the snapshot instance + /// stored by the {@link BlockState}. + /// When storing changes on the {@link PersistentDataHolder}, the updated + /// content will only be applied to the actual tile entity after one of the + /// {@link #update()} methods is called. + pub fn persistent_data_container( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPersistentDataContainer", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the block represented by this block state. + pub fn block(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/block/Block;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getModZ", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBlock", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the normal vector corresponding to this block face. - pub fn direction(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); + /// Gets the metadata for this block state. + pub fn data(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/MaterialData;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the data for this block state. + pub fn block_data( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBlockData", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns true if this face is aligned with one of the unit axes in 3D - /// Cartesian space (ie NORTH, SOUTH, EAST, WEST, UP, DOWN). - pub fn is_cartesian(&self) -> Result> { - let sig = String::from("()Z"); + /// Copies the state to another block as an unplaced BlockState. + pub fn copy( + &self, + location: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = location { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Lorg/bukkit/block/BlockState;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the type of this block state. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the current light level of the block represented by this block state. + pub fn light_level(&self) -> Result> { + let sig = String::from("()B"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCartesian", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLightLevel", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.b()?) + } + /// Gets the world which contains the block represented by this block state. + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the x-coordinate of this block state. + pub fn x(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the y-coordinate of this block state. + pub fn y(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the z-coordinate of this block state. + pub fn z(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Stores the location of this block state in the provided Location object. + /// + /// If the provided Location is null this method does nothing and returns + /// null. + /// + /// If this block state is not placed the location's world will be null! + pub fn get_location( + &self, + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLocation", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Gets the chunk which contains the block represented by this block state. + pub fn chunk(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Chunk;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getChunk", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Chunk::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the metadata for this block state. + pub fn set_data( + &self, + data: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/material/MaterialData;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(data.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setData", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets the data for this block state. + pub fn set_block_data( + &self, + data: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(data.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBlockData", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets the type of this block state. + pub fn set_type( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Material;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Attempts to update the block represented by this state, setting it to + /// the new values as defined by this state. + /// + /// If this state is not placed, this will have no effect and return true. + /// + /// Unless force is true, this will not modify the state of a block if it + /// is no longer the same type as it was when this state was taken. It will + /// return false in this eventuality. + /// + /// If force is true, it will set the type of the block to match the new + /// state, set the state data and then return true. + /// + /// If applyPhysics is true, it will trigger a physics update on + /// surrounding blocks which could cause them to update or disappear. + pub fn update( + &self, + force: std::option::Option, + apply_physics: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = force { + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_1); + } + if let Some(a) = apply_physics { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "update", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } + #[deprecated] - pub fn opposite_face( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + pub fn raw_data(&self) -> Result> { + let sig = String::from("()B"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getOppositeFace", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getRawData", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -pub enum BlockSupport<'mc> {} -impl<'mc> std::fmt::Display for BlockSupport<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + Ok(res.b()?) } -} + #[deprecated] -impl<'mc> BlockSupport<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/block/BlockSupport"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/block/BlockSupport;", + pub fn set_raw_data(&self, data: i8) -> Result<(), Box> { + let sig = String::from("(B)V"); + let val_1 = jni::objects::JValueGen::Byte(data); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRawData", + sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct BlockSupportStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for BlockSupport<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + self.jni_ref().translate_error(res)?; + Ok(()) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + /// Returns whether this state is placed in the world. + /// + /// Some methods will not work if the block state isn't + /// placed in the world. + pub fn is_placed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isPlaced", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for BlockSupport<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate BlockSupport from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/BlockSupport")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockSupport object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + /// Sets a metadata value in the implementing object's metadata store. + pub fn set_metadata( + &self, + metadata_key: impl Into, + new_metadata_value: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + if let Some(a) = new_metadata_value { + sig += "Lorg/bukkit/metadata/MetadataValue;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setMetadata", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> JNIRaw<'mc> for BlockSupportStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for BlockSupportStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate BlockSupportStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/block/BlockSupport")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockSupportStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + /// Returns a list of previously set metadata values from the implementing + /// object's metadata store. + pub fn get_metadata( + &self, + metadata_key: impl Into, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += ")Ljava/util/List;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getMetadata", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::metadata::MetadataValue::from_raw( + &self.jni_ref(), + obj, + )?); } + Ok(new_vec) } -} - -impl<'mc> BlockSupportStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockSupport;"); - let cls = jni.find_class("org/bukkit/block/BlockSupport"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::block::BlockSupport::from_raw(&jni, obj) + /// Tests to see whether the implementing object contains the given + /// metadata value in its metadata store. + pub fn has_metadata( + &self, + metadata_key: impl Into, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasMetadata", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Removes the given metadata value from the implementing object's + /// metadata store. + pub fn remove_metadata( + &self, + metadata_key: impl Into, + owning_plugin: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += "Lorg/bukkit/plugin/Plugin;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + }); + args.push(val_2); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "removeMetadata", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -18211,6 +20029,12 @@ impl<'mc> BlockSupportStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for TrialSpawner<'mc> { + fn into(self) -> crate::block::TileState<'mc> { + crate::block::TileState::from_raw(&self.jni_ref(), self.1) + .expect("Error converting TrialSpawner into crate::block::TileState") + } +} pub mod banner; pub mod data; pub mod sign; diff --git a/blackboxmc-rs-bukkit/src/block/sign/mod.rs b/blackboxmc-rs-bukkit/src/block/sign/mod.rs index 7331c25..a46c109 100644 --- a/blackboxmc-rs-bukkit/src/block/sign/mod.rs +++ b/blackboxmc-rs-bukkit/src/block/sign/mod.rs @@ -2,10 +2,25 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; -pub enum Side<'mc> {} +pub enum Side<'mc> { + Front { inner: SideStruct<'mc> }, + Back { inner: SideStruct<'mc> }, +} impl<'mc> std::fmt::Display for Side<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + Side::Front { .. } => f.write_str("FRONT"), + Side::Back { .. } => f.write_str("BACK"), + } + } +} +impl<'mc> std::ops::Deref for Side<'mc> { + type Target = SideStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + Side::Front { inner } => inner, + Side::Back { inner } => inner, + } } } @@ -32,6 +47,13 @@ impl<'mc> Side<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "FRONT" => Ok(Side::Front { + inner: SideStruct::from_raw(env, obj)?, + }), + "BACK" => Ok(Side::Back { + inner: SideStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -45,10 +67,16 @@ pub struct SideStruct<'mc>( impl<'mc> JNIRaw<'mc> for Side<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Front { inner } => inner.0.clone(), + Self::Back { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Front { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Back { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for Side<'mc> { @@ -74,6 +102,12 @@ impl<'mc> JNIInstantiatable<'mc> for Side<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "FRONT" => Ok(Side::Front { + inner: SideStruct::from_raw(env, obj)?, + }), + "BACK" => Ok(Side::Back { + inner: SideStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } diff --git a/blackboxmc-rs-bukkit/src/block/structure/mod.rs b/blackboxmc-rs-bukkit/src/block/structure/mod.rs index 69f46fc..a788b3e 100644 --- a/blackboxmc-rs-bukkit/src/block/structure/mod.rs +++ b/blackboxmc-rs-bukkit/src/block/structure/mod.rs @@ -2,10 +2,28 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; -pub enum Mirror<'mc> {} +pub enum Mirror<'mc> { + None { inner: MirrorStruct<'mc> }, + LeftRight { inner: MirrorStruct<'mc> }, + FrontBack { inner: MirrorStruct<'mc> }, +} impl<'mc> std::fmt::Display for Mirror<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + Mirror::None { .. } => f.write_str("NONE"), + Mirror::LeftRight { .. } => f.write_str("LEFT_RIGHT"), + Mirror::FrontBack { .. } => f.write_str("FRONT_BACK"), + } + } +} +impl<'mc> std::ops::Deref for Mirror<'mc> { + type Target = MirrorStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + Mirror::None { inner } => inner, + Mirror::LeftRight { inner } => inner, + Mirror::FrontBack { inner } => inner, + } } } @@ -32,6 +50,16 @@ impl<'mc> Mirror<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NONE" => Ok(Mirror::None { + inner: MirrorStruct::from_raw(env, obj)?, + }), + "LEFT_RIGHT" => Ok(Mirror::LeftRight { + inner: MirrorStruct::from_raw(env, obj)?, + }), + "FRONT_BACK" => Ok(Mirror::FrontBack { + inner: MirrorStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -45,10 +73,22 @@ pub struct MirrorStruct<'mc>( impl<'mc> JNIRaw<'mc> for Mirror<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::None { inner } => inner.0.clone(), + Self::LeftRight { inner } => inner.0.clone(), + Self::FrontBack { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::None { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::LeftRight { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FrontBack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } impl<'mc> JNIInstantiatable<'mc> for Mirror<'mc> { @@ -74,6 +114,15 @@ impl<'mc> JNIInstantiatable<'mc> for Mirror<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NONE" => Ok(Mirror::None { + inner: MirrorStruct::from_raw(env, obj)?, + }), + "LEFT_RIGHT" => Ok(Mirror::LeftRight { + inner: MirrorStruct::from_raw(env, obj)?, + }), + "FRONT_BACK" => Ok(Mirror::FrontBack { + inner: MirrorStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -127,10 +176,31 @@ impl<'mc> MirrorStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum StructureRotation<'mc> {} +pub enum StructureRotation<'mc> { + None { inner: StructureRotationStruct<'mc> }, + Clockwise90 { inner: StructureRotationStruct<'mc> }, + Clockwise180 { inner: StructureRotationStruct<'mc> }, + Counterclockwise90 { inner: StructureRotationStruct<'mc> }, +} impl<'mc> std::fmt::Display for StructureRotation<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + StructureRotation::None { .. } => f.write_str("NONE"), + StructureRotation::Clockwise90 { .. } => f.write_str("CLOCKWISE_90"), + StructureRotation::Clockwise180 { .. } => f.write_str("CLOCKWISE_180"), + StructureRotation::Counterclockwise90 { .. } => f.write_str("COUNTERCLOCKWISE_90"), + } + } +} +impl<'mc> std::ops::Deref for StructureRotation<'mc> { + type Target = StructureRotationStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + StructureRotation::None { inner } => inner, + StructureRotation::Clockwise90 { inner } => inner, + StructureRotation::Clockwise180 { inner } => inner, + StructureRotation::Counterclockwise90 { inner } => inner, + } } } @@ -157,6 +227,19 @@ impl<'mc> StructureRotation<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NONE" => Ok(StructureRotation::None { + inner: StructureRotationStruct::from_raw(env, obj)?, + }), + "CLOCKWISE_90" => Ok(StructureRotation::Clockwise90 { + inner: StructureRotationStruct::from_raw(env, obj)?, + }), + "CLOCKWISE_180" => Ok(StructureRotation::Clockwise180 { + inner: StructureRotationStruct::from_raw(env, obj)?, + }), + "COUNTERCLOCKWISE_90" => Ok(StructureRotation::Counterclockwise90 { + inner: StructureRotationStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -170,10 +253,26 @@ pub struct StructureRotationStruct<'mc>( impl<'mc> JNIRaw<'mc> for StructureRotation<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::None { inner } => inner.0.clone(), + Self::Clockwise90 { inner } => inner.0.clone(), + Self::Clockwise180 { inner } => inner.0.clone(), + Self::Counterclockwise90 { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::None { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Clockwise90 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Clockwise180 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Counterclockwise90 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } impl<'mc> JNIInstantiatable<'mc> for StructureRotation<'mc> { @@ -202,6 +301,18 @@ impl<'mc> JNIInstantiatable<'mc> for StructureRotation<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NONE" => Ok(StructureRotation::None { + inner: StructureRotationStruct::from_raw(env, obj)?, + }), + "CLOCKWISE_90" => Ok(StructureRotation::Clockwise90 { + inner: StructureRotationStruct::from_raw(env, obj)?, + }), + "CLOCKWISE_180" => Ok(StructureRotation::Clockwise180 { + inner: StructureRotationStruct::from_raw(env, obj)?, + }), + "COUNTERCLOCKWISE_90" => Ok(StructureRotation::Counterclockwise90 { + inner: StructureRotationStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -259,10 +370,31 @@ impl<'mc> StructureRotationStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum UsageMode<'mc> {} +pub enum UsageMode<'mc> { + Save { inner: UsageModeStruct<'mc> }, + Load { inner: UsageModeStruct<'mc> }, + Corner { inner: UsageModeStruct<'mc> }, + Data { inner: UsageModeStruct<'mc> }, +} impl<'mc> std::fmt::Display for UsageMode<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + UsageMode::Save { .. } => f.write_str("SAVE"), + UsageMode::Load { .. } => f.write_str("LOAD"), + UsageMode::Corner { .. } => f.write_str("CORNER"), + UsageMode::Data { .. } => f.write_str("DATA"), + } + } +} +impl<'mc> std::ops::Deref for UsageMode<'mc> { + type Target = UsageModeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + UsageMode::Save { inner } => inner, + UsageMode::Load { inner } => inner, + UsageMode::Corner { inner } => inner, + UsageMode::Data { inner } => inner, + } } } @@ -289,6 +421,19 @@ impl<'mc> UsageMode<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "SAVE" => Ok(UsageMode::Save { + inner: UsageModeStruct::from_raw(env, obj)?, + }), + "LOAD" => Ok(UsageMode::Load { + inner: UsageModeStruct::from_raw(env, obj)?, + }), + "CORNER" => Ok(UsageMode::Corner { + inner: UsageModeStruct::from_raw(env, obj)?, + }), + "DATA" => Ok(UsageMode::Data { + inner: UsageModeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -302,10 +447,20 @@ pub struct UsageModeStruct<'mc>( impl<'mc> JNIRaw<'mc> for UsageMode<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Save { inner } => inner.0.clone(), + Self::Load { inner } => inner.0.clone(), + Self::Corner { inner } => inner.0.clone(), + Self::Data { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Save { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Load { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Corner { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Data { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for UsageMode<'mc> { @@ -331,6 +486,18 @@ impl<'mc> JNIInstantiatable<'mc> for UsageMode<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "SAVE" => Ok(UsageMode::Save { + inner: UsageModeStruct::from_raw(env, obj)?, + }), + "LOAD" => Ok(UsageMode::Load { + inner: UsageModeStruct::from_raw(env, obj)?, + }), + "CORNER" => Ok(UsageMode::Corner { + inner: UsageModeStruct::from_raw(env, obj)?, + }), + "DATA" => Ok(UsageMode::Data { + inner: UsageModeStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } diff --git a/blackboxmc-rs-bukkit/src/boss/mod.rs b/blackboxmc-rs-bukkit/src/boss/mod.rs index b5b478b..a8ba4af 100644 --- a/blackboxmc-rs-bukkit/src/boss/mod.rs +++ b/blackboxmc-rs-bukkit/src/boss/mod.rs @@ -2,10 +2,40 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; -pub enum BarColor<'mc> {} +pub enum BarColor<'mc> { + Pink { inner: BarColorStruct<'mc> }, + Blue { inner: BarColorStruct<'mc> }, + Red { inner: BarColorStruct<'mc> }, + Green { inner: BarColorStruct<'mc> }, + Yellow { inner: BarColorStruct<'mc> }, + Purple { inner: BarColorStruct<'mc> }, + White { inner: BarColorStruct<'mc> }, +} impl<'mc> std::fmt::Display for BarColor<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + BarColor::Pink { .. } => f.write_str("PINK"), + BarColor::Blue { .. } => f.write_str("BLUE"), + BarColor::Red { .. } => f.write_str("RED"), + BarColor::Green { .. } => f.write_str("GREEN"), + BarColor::Yellow { .. } => f.write_str("YELLOW"), + BarColor::Purple { .. } => f.write_str("PURPLE"), + BarColor::White { .. } => f.write_str("WHITE"), + } + } +} +impl<'mc> std::ops::Deref for BarColor<'mc> { + type Target = BarColorStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + BarColor::Pink { inner } => inner, + BarColor::Blue { inner } => inner, + BarColor::Red { inner } => inner, + BarColor::Green { inner } => inner, + BarColor::Yellow { inner } => inner, + BarColor::Purple { inner } => inner, + BarColor::White { inner } => inner, + } } } @@ -32,6 +62,28 @@ impl<'mc> BarColor<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "PINK" => Ok(BarColor::Pink { + inner: BarColorStruct::from_raw(env, obj)?, + }), + "BLUE" => Ok(BarColor::Blue { + inner: BarColorStruct::from_raw(env, obj)?, + }), + "RED" => Ok(BarColor::Red { + inner: BarColorStruct::from_raw(env, obj)?, + }), + "GREEN" => Ok(BarColor::Green { + inner: BarColorStruct::from_raw(env, obj)?, + }), + "YELLOW" => Ok(BarColor::Yellow { + inner: BarColorStruct::from_raw(env, obj)?, + }), + "PURPLE" => Ok(BarColor::Purple { + inner: BarColorStruct::from_raw(env, obj)?, + }), + "WHITE" => Ok(BarColor::White { + inner: BarColorStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -45,10 +97,26 @@ pub struct BarColorStruct<'mc>( impl<'mc> JNIRaw<'mc> for BarColor<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Pink { inner } => inner.0.clone(), + Self::Blue { inner } => inner.0.clone(), + Self::Red { inner } => inner.0.clone(), + Self::Green { inner } => inner.0.clone(), + Self::Yellow { inner } => inner.0.clone(), + Self::Purple { inner } => inner.0.clone(), + Self::White { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Pink { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Blue { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Red { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Green { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Yellow { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Purple { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::White { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for BarColor<'mc> { @@ -74,6 +142,27 @@ impl<'mc> JNIInstantiatable<'mc> for BarColor<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "PINK" => Ok(BarColor::Pink { + inner: BarColorStruct::from_raw(env, obj)?, + }), + "BLUE" => Ok(BarColor::Blue { + inner: BarColorStruct::from_raw(env, obj)?, + }), + "RED" => Ok(BarColor::Red { + inner: BarColorStruct::from_raw(env, obj)?, + }), + "GREEN" => Ok(BarColor::Green { + inner: BarColorStruct::from_raw(env, obj)?, + }), + "YELLOW" => Ok(BarColor::Yellow { + inner: BarColorStruct::from_raw(env, obj)?, + }), + "PURPLE" => Ok(BarColor::Purple { + inner: BarColorStruct::from_raw(env, obj)?, + }), + "WHITE" => Ok(BarColor::White { + inner: BarColorStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -644,10 +733,51 @@ impl<'mc> DragonBattle<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum DragonBattleRespawnPhase<'mc> {} +pub enum DragonBattleRespawnPhase<'mc> { + Start { + inner: DragonBattleRespawnPhaseStruct<'mc>, + }, + PreparingToSummonPillars { + inner: DragonBattleRespawnPhaseStruct<'mc>, + }, + SummoningPillars { + inner: DragonBattleRespawnPhaseStruct<'mc>, + }, + SummoningDragon { + inner: DragonBattleRespawnPhaseStruct<'mc>, + }, + End { + inner: DragonBattleRespawnPhaseStruct<'mc>, + }, + None { + inner: DragonBattleRespawnPhaseStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for DragonBattleRespawnPhase<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + DragonBattleRespawnPhase::Start { .. } => f.write_str("START"), + DragonBattleRespawnPhase::PreparingToSummonPillars { .. } => { + f.write_str("PREPARING_TO_SUMMON_PILLARS") + } + DragonBattleRespawnPhase::SummoningPillars { .. } => f.write_str("SUMMONING_PILLARS"), + DragonBattleRespawnPhase::SummoningDragon { .. } => f.write_str("SUMMONING_DRAGON"), + DragonBattleRespawnPhase::End { .. } => f.write_str("END"), + DragonBattleRespawnPhase::None { .. } => f.write_str("NONE"), + } + } +} +impl<'mc> std::ops::Deref for DragonBattleRespawnPhase<'mc> { + type Target = DragonBattleRespawnPhaseStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + DragonBattleRespawnPhase::Start { inner } => inner, + DragonBattleRespawnPhase::PreparingToSummonPillars { inner } => inner, + DragonBattleRespawnPhase::SummoningPillars { inner } => inner, + DragonBattleRespawnPhase::SummoningDragon { inner } => inner, + DragonBattleRespawnPhase::End { inner } => inner, + DragonBattleRespawnPhase::None { inner } => inner, + } } } @@ -674,6 +804,27 @@ impl<'mc> DragonBattleRespawnPhase<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "START" => Ok(DragonBattleRespawnPhase::Start { + inner: DragonBattleRespawnPhaseStruct::from_raw(env, obj)?, + }), + "PREPARING_TO_SUMMON_PILLARS" => { + Ok(DragonBattleRespawnPhase::PreparingToSummonPillars { + inner: DragonBattleRespawnPhaseStruct::from_raw(env, obj)?, + }) + } + "SUMMONING_PILLARS" => Ok(DragonBattleRespawnPhase::SummoningPillars { + inner: DragonBattleRespawnPhaseStruct::from_raw(env, obj)?, + }), + "SUMMONING_DRAGON" => Ok(DragonBattleRespawnPhase::SummoningDragon { + inner: DragonBattleRespawnPhaseStruct::from_raw(env, obj)?, + }), + "END" => Ok(DragonBattleRespawnPhase::End { + inner: DragonBattleRespawnPhaseStruct::from_raw(env, obj)?, + }), + "NONE" => Ok(DragonBattleRespawnPhase::None { + inner: DragonBattleRespawnPhaseStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -687,10 +838,30 @@ pub struct DragonBattleRespawnPhaseStruct<'mc>( impl<'mc> JNIRaw<'mc> for DragonBattleRespawnPhase<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Start { inner } => inner.0.clone(), + Self::PreparingToSummonPillars { inner } => inner.0.clone(), + Self::SummoningPillars { inner } => inner.0.clone(), + Self::SummoningDragon { inner } => inner.0.clone(), + Self::End { inner } => inner.0.clone(), + Self::None { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Start { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PreparingToSummonPillars { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SummoningPillars { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SummoningDragon { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::End { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::None { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for DragonBattleRespawnPhase<'mc> { @@ -719,6 +890,26 @@ impl<'mc> JNIInstantiatable<'mc> for DragonBattleRespawnPhase<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "START" => Ok(DragonBattleRespawnPhase::Start { + inner: DragonBattleRespawnPhaseStruct::from_raw(env, obj)?, + }), + "PREPARING_TO_SUMMON_PILLARS" => { + Ok(DragonBattleRespawnPhase::PreparingToSummonPillars { + inner: DragonBattleRespawnPhaseStruct::from_raw(env, obj)?, + }) + } + "SUMMONING_PILLARS" => Ok(DragonBattleRespawnPhase::SummoningPillars { + inner: DragonBattleRespawnPhaseStruct::from_raw(env, obj)?, + }), + "SUMMONING_DRAGON" => Ok(DragonBattleRespawnPhase::SummoningDragon { + inner: DragonBattleRespawnPhaseStruct::from_raw(env, obj)?, + }), + "END" => Ok(DragonBattleRespawnPhase::End { + inner: DragonBattleRespawnPhaseStruct::from_raw(env, obj)?, + }), + "NONE" => Ok(DragonBattleRespawnPhase::None { + inner: DragonBattleRespawnPhaseStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -775,10 +966,28 @@ impl<'mc> DragonBattleRespawnPhaseStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum BarFlag<'mc> {} +pub enum BarFlag<'mc> { + DarkenSky { inner: BarFlagStruct<'mc> }, + PlayBossMusic { inner: BarFlagStruct<'mc> }, + CreateFog { inner: BarFlagStruct<'mc> }, +} impl<'mc> std::fmt::Display for BarFlag<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + BarFlag::DarkenSky { .. } => f.write_str("DARKEN_SKY"), + BarFlag::PlayBossMusic { .. } => f.write_str("PLAY_BOSS_MUSIC"), + BarFlag::CreateFog { .. } => f.write_str("CREATE_FOG"), + } + } +} +impl<'mc> std::ops::Deref for BarFlag<'mc> { + type Target = BarFlagStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + BarFlag::DarkenSky { inner } => inner, + BarFlag::PlayBossMusic { inner } => inner, + BarFlag::CreateFog { inner } => inner, + } } } @@ -805,6 +1014,16 @@ impl<'mc> BarFlag<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "DARKEN_SKY" => Ok(BarFlag::DarkenSky { + inner: BarFlagStruct::from_raw(env, obj)?, + }), + "PLAY_BOSS_MUSIC" => Ok(BarFlag::PlayBossMusic { + inner: BarFlagStruct::from_raw(env, obj)?, + }), + "CREATE_FOG" => Ok(BarFlag::CreateFog { + inner: BarFlagStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -818,10 +1037,24 @@ pub struct BarFlagStruct<'mc>( impl<'mc> JNIRaw<'mc> for BarFlag<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::DarkenSky { inner } => inner.0.clone(), + Self::PlayBossMusic { inner } => inner.0.clone(), + Self::CreateFog { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::DarkenSky { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PlayBossMusic { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CreateFog { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } impl<'mc> JNIInstantiatable<'mc> for BarFlag<'mc> { @@ -847,6 +1080,15 @@ impl<'mc> JNIInstantiatable<'mc> for BarFlag<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "DARKEN_SKY" => Ok(BarFlag::DarkenSky { + inner: BarFlagStruct::from_raw(env, obj)?, + }), + "PLAY_BOSS_MUSIC" => Ok(BarFlag::PlayBossMusic { + inner: BarFlagStruct::from_raw(env, obj)?, + }), + "CREATE_FOG" => Ok(BarFlag::CreateFog { + inner: BarFlagStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -900,10 +1142,34 @@ impl<'mc> BarFlagStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum BarStyle<'mc> {} +pub enum BarStyle<'mc> { + Solid { inner: BarStyleStruct<'mc> }, + Segmented6 { inner: BarStyleStruct<'mc> }, + Segmented10 { inner: BarStyleStruct<'mc> }, + Segmented12 { inner: BarStyleStruct<'mc> }, + Segmented20 { inner: BarStyleStruct<'mc> }, +} impl<'mc> std::fmt::Display for BarStyle<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + BarStyle::Solid { .. } => f.write_str("SOLID"), + BarStyle::Segmented6 { .. } => f.write_str("SEGMENTED_6"), + BarStyle::Segmented10 { .. } => f.write_str("SEGMENTED_10"), + BarStyle::Segmented12 { .. } => f.write_str("SEGMENTED_12"), + BarStyle::Segmented20 { .. } => f.write_str("SEGMENTED_20"), + } + } +} +impl<'mc> std::ops::Deref for BarStyle<'mc> { + type Target = BarStyleStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + BarStyle::Solid { inner } => inner, + BarStyle::Segmented6 { inner } => inner, + BarStyle::Segmented10 { inner } => inner, + BarStyle::Segmented12 { inner } => inner, + BarStyle::Segmented20 { inner } => inner, + } } } @@ -930,6 +1196,22 @@ impl<'mc> BarStyle<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "SOLID" => Ok(BarStyle::Solid { + inner: BarStyleStruct::from_raw(env, obj)?, + }), + "SEGMENTED_6" => Ok(BarStyle::Segmented6 { + inner: BarStyleStruct::from_raw(env, obj)?, + }), + "SEGMENTED_10" => Ok(BarStyle::Segmented10 { + inner: BarStyleStruct::from_raw(env, obj)?, + }), + "SEGMENTED_12" => Ok(BarStyle::Segmented12 { + inner: BarStyleStruct::from_raw(env, obj)?, + }), + "SEGMENTED_20" => Ok(BarStyle::Segmented20 { + inner: BarStyleStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -943,10 +1225,30 @@ pub struct BarStyleStruct<'mc>( impl<'mc> JNIRaw<'mc> for BarStyle<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Solid { inner } => inner.0.clone(), + Self::Segmented6 { inner } => inner.0.clone(), + Self::Segmented10 { inner } => inner.0.clone(), + Self::Segmented12 { inner } => inner.0.clone(), + Self::Segmented20 { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Solid { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Segmented6 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Segmented10 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Segmented12 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Segmented20 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } impl<'mc> JNIInstantiatable<'mc> for BarStyle<'mc> { @@ -972,6 +1274,21 @@ impl<'mc> JNIInstantiatable<'mc> for BarStyle<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "SOLID" => Ok(BarStyle::Solid { + inner: BarStyleStruct::from_raw(env, obj)?, + }), + "SEGMENTED_6" => Ok(BarStyle::Segmented6 { + inner: BarStyleStruct::from_raw(env, obj)?, + }), + "SEGMENTED_10" => Ok(BarStyle::Segmented10 { + inner: BarStyleStruct::from_raw(env, obj)?, + }), + "SEGMENTED_12" => Ok(BarStyle::Segmented12 { + inner: BarStyleStruct::from_raw(env, obj)?, + }), + "SEGMENTED_20" => Ok(BarStyle::Segmented20 { + inner: BarStyleStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } diff --git a/blackboxmc-rs-bukkit/src/command/defaults/mod.rs b/blackboxmc-rs-bukkit/src/command/defaults/mod.rs index deddf53..f97a1a2 100644 --- a/blackboxmc-rs-bukkit/src/command/defaults/mod.rs +++ b/blackboxmc-rs-bukkit/src/command/defaults/mod.rs @@ -3,12 +3,12 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] -pub struct PluginsCommand<'mc>( +pub struct VersionCommand<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PluginsCommand<'mc> { +impl<'mc> JNIRaw<'mc> for VersionCommand<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -16,21 +16,21 @@ impl<'mc> JNIRaw<'mc> for PluginsCommand<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PluginsCommand<'mc> { +impl<'mc> JNIInstantiatable<'mc> for VersionCommand<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate PluginsCommand from null object.").into(), + eyre::eyre!("Tried to instantiate VersionCommand from null object.").into(), ); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/command/defaults/PluginsCommand")?; + env.validate_name(&obj, "org/bukkit/command/defaults/VersionCommand")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PluginsCommand object, got {}", + "Invalid argument passed. Expected a VersionCommand object, got {}", name ) .into()) @@ -40,16 +40,16 @@ impl<'mc> JNIInstantiatable<'mc> for PluginsCommand<'mc> { } } -impl<'mc> PluginsCommand<'mc> { +impl<'mc> VersionCommand<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, name: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let sig = String::from("(Ljava/lang/String;)V"); let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( jni.new_string(name.into())?, )); - let cls = jni.find_class("org/bukkit/command/defaults/PluginsCommand"); + let cls = jni.find_class("org/bukkit/command/defaults/VersionCommand"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -57,7 +57,7 @@ impl<'mc> PluginsCommand<'mc> { vec![jni::objects::JValueGen::from(val_1)], ); let res = jni.translate_error_no_gen(res)?; - crate::command::defaults::PluginsCommand::from_raw(&jni, res) + crate::command::defaults::VersionCommand::from_raw(&jni, res) } pub fn execute( @@ -140,19 +140,19 @@ impl<'mc> PluginsCommand<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PluginsCommand<'mc> { +impl<'mc> Into> for VersionCommand<'mc> { fn into(self) -> crate::command::defaults::BukkitCommand<'mc> { crate::command::defaults::BukkitCommand::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PluginsCommand into crate::command::defaults::BukkitCommand") + .expect("Error converting VersionCommand into crate::command::defaults::BukkitCommand") } } #[repr(C)] -pub struct BukkitCommand<'mc>( +pub struct TimingsCommand<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BukkitCommand<'mc> { +impl<'mc> JNIRaw<'mc> for TimingsCommand<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -160,18 +160,21 @@ impl<'mc> JNIRaw<'mc> for BukkitCommand<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BukkitCommand<'mc> { +impl<'mc> JNIInstantiatable<'mc> for TimingsCommand<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate BukkitCommand from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate TimingsCommand from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/command/defaults/BukkitCommand")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/command/defaults/TimingsCommand")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BukkitCommand object, got {}", + "Invalid argument passed. Expected a TimingsCommand object, got {}", name ) .into()) @@ -181,151 +184,84 @@ impl<'mc> JNIInstantiatable<'mc> for BukkitCommand<'mc> { } } -impl<'mc> BukkitCommand<'mc> { - // SUPER CLASS: org.bukkit.command.Command ( []) - /// Executed on tab completion for this command, returning a list of - /// options the player can tab through. - pub fn tab_complete( +impl<'mc> TimingsCommand<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + name: impl Into, + ) -> Result, Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(name.into())?, + )); + let cls = jni.find_class("org/bukkit/command/defaults/TimingsCommand"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error_no_gen(res)?; + crate::command::defaults::TimingsCommand::from_raw(&jni, res) + } + + pub fn execute( &self, sender: impl Into>, - alias: impl Into, + current_alias: impl Into, val_args: impl Into, - location: std::option::Option>>, - ) -> Result, Box> { - let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::command::Command = temp_clone.into(); - real.tab_complete(sender, alias, val_args, location) - } - /// Returns the name of this command - pub fn name(&self) -> Result> { - let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::command::Command = temp_clone.into(); - real.name() - } - /// Sets the name of this command. - /// - /// May only be used before registering the command. - /// Will return true if the new name is set, and false - /// if the command has already been registered. - pub fn set_name(&self, name: impl Into) -> Result> { - let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::command::Command = temp_clone.into(); - real.set_name(name) - } - /// Gets the permission required by users to be able to perform this - /// command - pub fn permission(&self) -> Result, Box> { - let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::command::Command = temp_clone.into(); - real.permission() - } - /// Sets the permission required by users to be able to perform this - /// command - pub fn set_permission( - &self, - permission: impl Into, - ) -> Result<(), Box> { - let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::command::Command = temp_clone.into(); - real.set_permission(permission) - } - /// Tests the given {@link CommandSender} to see if they can perform this - /// command. - /// - /// If they do not have permission, they will be informed that they cannot - /// do this. - pub fn test_permission( - &self, - target: impl Into>, - ) -> Result> { - let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::command::Command = temp_clone.into(); - real.test_permission(target) - } - /// Tests the given {@link CommandSender} to see if they can perform this - /// command. - /// - /// No error is sent to the sender. - pub fn test_permission_silent( - &self, - target: impl Into>, - ) -> Result> { - let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::command::Command = temp_clone.into(); - real.test_permission_silent(target) - } - /// Returns the label for this command - pub fn label(&self) -> Result> { - let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::command::Command = temp_clone.into(); - real.label() - } - /// Sets the label of this command. - /// - /// May only be used before registering the command. - /// Will return true if the new name is set, and false - /// if the command has already been registered. - pub fn set_label(&self, name: impl Into) -> Result> { - let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::command::Command = temp_clone.into(); - real.set_label(name) - } - /// Registers this command to a CommandMap. - /// Once called it only allows changes the registered CommandMap - pub fn register( - &self, - command_map: impl Into>, ) -> Result> { - let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::command::Command = temp_clone.into(); - real.register(command_map) + let sig = String::from( + "(Lorg/bukkit/command/CommandSender;Ljava/lang/String;Ljava/lang/String;)Z", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(current_alias.into())?, + )); + let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(val_args.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "execute", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Unregisters this command from the passed CommandMap applying any - /// outstanding changes - pub fn unregister( + + pub fn tab_complete( &self, - command_map: impl Into>, - ) -> Result> { - let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::command::Command = temp_clone.into(); - real.unregister(command_map) - } - /// Returns the current registered state of this command - pub fn is_registered(&self) -> Result> { - let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::command::Command = temp_clone.into(); - real.is_registered() - } - /// Returns a list of active aliases of this command - pub fn aliases(&self) -> Result, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAliases", sig.as_str(), vec![]); + sender: impl Into>, + alias: impl Into, + val_args: impl Into, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/command/CommandSender;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(alias.into())?, + )); + let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(val_args.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "tabComplete", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; @@ -341,135 +277,26 @@ impl<'mc> BukkitCommand<'mc> { } Ok(new_vec) } - /// Returns a message to be displayed on a failed permission check for this command - pub fn permission_message(&self) -> Result, Box> { - let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::command::Command = temp_clone.into(); - real.permission_message() - } - /// Gets a brief description of this command - pub fn description(&self) -> Result> { - let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::command::Command = temp_clone.into(); - real.description() - } - /// Gets an example usage of this command - pub fn usage(&self) -> Result> { - let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::command::Command = temp_clone.into(); - real.usage() - } - /// Sets the list of aliases to request on registration for this command. - /// This is not effective outside of defining aliases in the {@link - /// PluginDescriptionFile#getCommands()} (under the - /// `aliases' node) is equivalent to this method. - pub fn set_aliases( - &self, - aliases: Vec>, - ) -> Result, Box> { - let sig = String::from("(Ljava/util/List;)Lorg/bukkit/command/Command;"); - let raw_val_1 = self - .jni_ref() - .new_object("java/util/ArrayList", "()V", vec![])?; - for v in aliases { - let map_val_0 = jni::objects::JValueGen::Object(v); - self.jni_ref().call_method( - &raw_val_1, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_1 = jni::objects::JValueGen::Object(raw_val_1); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAliases", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::command::Command::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets a brief description of this command. Defining a description in the - /// {@link PluginDescriptionFile#getCommands()} (under the - /// `description' node) is equivalent to this method. - pub fn set_description( - &self, - description: impl Into, - ) -> Result, Box> { - let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::command::Command = temp_clone.into(); - real.set_description(description) - } - /// Sets the message sent when a permission check fails - pub fn set_permission_message( - &self, - permission_message: impl Into, - ) -> Result, Box> { - let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::command::Command = temp_clone.into(); - real.set_permission_message(permission_message) - } - /// Sets the example usage of this command - pub fn set_usage( - &self, - usage: impl Into, - ) -> Result, Box> { - let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::command::Command = temp_clone.into(); - real.set_usage(usage) - } - - pub fn broadcast_command_message( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - source: impl Into>, - message: impl Into, - send_to_source: std::option::Option, - ) -> Result<(), Box> { - crate::command::Command::broadcast_command_message(jni, source, message, send_to_source) - } - - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::command::Command = temp_clone.into(); - real.internal_to_string() - } + // SUPER CLASS: org.bukkit.command.defaults.BukkitCommand ( ['execute', 'tabComplete']) pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BukkitCommand<'mc> { - fn into(self) -> crate::command::Command<'mc> { - crate::command::Command::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BukkitCommand into crate::command::Command") +impl<'mc> Into> for TimingsCommand<'mc> { + fn into(self) -> crate::command::defaults::BukkitCommand<'mc> { + crate::command::defaults::BukkitCommand::from_raw(&self.jni_ref(), self.1) + .expect("Error converting TimingsCommand into crate::command::defaults::BukkitCommand") } } #[repr(C)] -pub struct VersionCommand<'mc>( +pub struct PluginsCommand<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for VersionCommand<'mc> { +impl<'mc> JNIRaw<'mc> for PluginsCommand<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -477,21 +304,21 @@ impl<'mc> JNIRaw<'mc> for VersionCommand<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for VersionCommand<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PluginsCommand<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate VersionCommand from null object.").into(), + eyre::eyre!("Tried to instantiate PluginsCommand from null object.").into(), ); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/command/defaults/VersionCommand")?; + env.validate_name(&obj, "org/bukkit/command/defaults/PluginsCommand")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a VersionCommand object, got {}", + "Invalid argument passed. Expected a PluginsCommand object, got {}", name ) .into()) @@ -501,16 +328,16 @@ impl<'mc> JNIInstantiatable<'mc> for VersionCommand<'mc> { } } -impl<'mc> VersionCommand<'mc> { +impl<'mc> PluginsCommand<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, name: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let sig = String::from("(Ljava/lang/String;)V"); let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( jni.new_string(name.into())?, )); - let cls = jni.find_class("org/bukkit/command/defaults/VersionCommand"); + let cls = jni.find_class("org/bukkit/command/defaults/PluginsCommand"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -518,7 +345,7 @@ impl<'mc> VersionCommand<'mc> { vec![jni::objects::JValueGen::from(val_1)], ); let res = jni.translate_error_no_gen(res)?; - crate::command::defaults::VersionCommand::from_raw(&jni, res) + crate::command::defaults::PluginsCommand::from_raw(&jni, res) } pub fn execute( @@ -601,19 +428,19 @@ impl<'mc> VersionCommand<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for VersionCommand<'mc> { +impl<'mc> Into> for PluginsCommand<'mc> { fn into(self) -> crate::command::defaults::BukkitCommand<'mc> { crate::command::defaults::BukkitCommand::from_raw(&self.jni_ref(), self.1) - .expect("Error converting VersionCommand into crate::command::defaults::BukkitCommand") + .expect("Error converting PluginsCommand into crate::command::defaults::BukkitCommand") } } #[repr(C)] -pub struct ReloadCommand<'mc>( +pub struct HelpCommand<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ReloadCommand<'mc> { +impl<'mc> JNIRaw<'mc> for HelpCommand<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -621,18 +448,18 @@ impl<'mc> JNIRaw<'mc> for ReloadCommand<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ReloadCommand<'mc> { +impl<'mc> JNIInstantiatable<'mc> for HelpCommand<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ReloadCommand from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate HelpCommand from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/command/defaults/ReloadCommand")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/command/defaults/HelpCommand")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ReloadCommand object, got {}", + "Invalid argument passed. Expected a HelpCommand object, got {}", name ) .into()) @@ -642,24 +469,16 @@ impl<'mc> JNIInstantiatable<'mc> for ReloadCommand<'mc> { } } -impl<'mc> ReloadCommand<'mc> { +impl<'mc> HelpCommand<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - name: impl Into, - ) -> Result, Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(name.into())?, - )); - let cls = jni.find_class("org/bukkit/command/defaults/ReloadCommand"); + ) -> Result, Box> { + let sig = String::from("()V"); + let cls = jni.find_class("org/bukkit/command/defaults/HelpCommand"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + let res = jni.new_object(cls, sig.as_str(), vec![]); let res = jni.translate_error_no_gen(res)?; - crate::command::defaults::ReloadCommand::from_raw(&jni, res) + crate::command::defaults::HelpCommand::from_raw(&jni, res) } pub fn execute( @@ -742,19 +561,19 @@ impl<'mc> ReloadCommand<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for ReloadCommand<'mc> { +impl<'mc> Into> for HelpCommand<'mc> { fn into(self) -> crate::command::defaults::BukkitCommand<'mc> { crate::command::defaults::BukkitCommand::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ReloadCommand into crate::command::defaults::BukkitCommand") + .expect("Error converting HelpCommand into crate::command::defaults::BukkitCommand") } } #[repr(C)] -pub struct HelpCommand<'mc>( +pub struct BukkitCommand<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for HelpCommand<'mc> { +impl<'mc> JNIRaw<'mc> for BukkitCommand<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -762,18 +581,18 @@ impl<'mc> JNIRaw<'mc> for HelpCommand<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for HelpCommand<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BukkitCommand<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate HelpCommand from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate BukkitCommand from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/command/defaults/HelpCommand")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/command/defaults/BukkitCommand")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a HelpCommand object, got {}", + "Invalid argument passed. Expected a BukkitCommand object, got {}", name ) .into()) @@ -783,78 +602,153 @@ impl<'mc> JNIInstantiatable<'mc> for HelpCommand<'mc> { } } -impl<'mc> HelpCommand<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/command/defaults/HelpCommand"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), vec![]); - let res = jni.translate_error_no_gen(res)?; - crate::command::defaults::HelpCommand::from_raw(&jni, res) - } - - pub fn execute( - &self, - sender: impl Into>, - current_alias: impl Into, - val_args: impl Into, - ) -> Result> { - let sig = String::from( - "(Lorg/bukkit/command/CommandSender;Ljava/lang/String;Ljava/lang/String;)Z", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(current_alias.into())?, - )); - let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(val_args.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "execute", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - +impl<'mc> BukkitCommand<'mc> { + // SUPER CLASS: org.bukkit.command.Command ( []) + /// Executed on tab completion for this command, returning a list of + /// options the player can tab through. pub fn tab_complete( &self, sender: impl Into>, alias: impl Into, val_args: impl Into, + location: std::option::Option>>, ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/command/CommandSender;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(alias.into())?, - )); - let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(val_args.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "tabComplete", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); + let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::command::Command = temp_clone.into(); + real.tab_complete(sender, alias, val_args, location) + } + /// Returns the name of this command + pub fn name(&self) -> Result> { + let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::command::Command = temp_clone.into(); + real.name() + } + /// Sets the name of this command. + /// + /// May only be used before registering the command. + /// Will return true if the new name is set, and false + /// if the command has already been registered. + pub fn set_name(&self, name: impl Into) -> Result> { + let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::command::Command = temp_clone.into(); + real.set_name(name) + } + /// Gets the permission required by users to be able to perform this + /// command + pub fn permission(&self) -> Result, Box> { + let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::command::Command = temp_clone.into(); + real.permission() + } + /// Sets the permission required by users to be able to perform this + /// command + pub fn set_permission( + &self, + permission: impl Into, + ) -> Result<(), Box> { + let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::command::Command = temp_clone.into(); + real.set_permission(permission) + } + /// Tests the given {@link CommandSender} to see if they can perform this + /// command. + /// + /// If they do not have permission, they will be informed that they cannot + /// do this. + pub fn test_permission( + &self, + target: impl Into>, + ) -> Result> { + let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::command::Command = temp_clone.into(); + real.test_permission(target) + } + /// Tests the given {@link CommandSender} to see if they can perform this + /// command. + /// + /// No error is sent to the sender. + pub fn test_permission_silent( + &self, + target: impl Into>, + ) -> Result> { + let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::command::Command = temp_clone.into(); + real.test_permission_silent(target) + } + /// Returns the label for this command + pub fn label(&self) -> Result> { + let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::command::Command = temp_clone.into(); + real.label() + } + /// Sets the label of this command. + /// + /// May only be used before registering the command. + /// Will return true if the new name is set, and false + /// if the command has already been registered. + pub fn set_label(&self, name: impl Into) -> Result> { + let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::command::Command = temp_clone.into(); + real.set_label(name) + } + /// Registers this command to a CommandMap. + /// Once called it only allows changes the registered CommandMap + pub fn register( + &self, + command_map: impl Into>, + ) -> Result> { + let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::command::Command = temp_clone.into(); + real.register(command_map) + } + /// Unregisters this command from the passed CommandMap applying any + /// outstanding changes + pub fn unregister( + &self, + command_map: impl Into>, + ) -> Result> { + let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::command::Command = temp_clone.into(); + real.unregister(command_map) + } + /// Returns the current registered state of this command + pub fn is_registered(&self) -> Result> { + let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::command::Command = temp_clone.into(); + real.is_registered() + } + /// Returns a list of active aliases of this command + pub fn aliases(&self) -> Result, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAliases", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; let iter = list.iterator()?; while iter.has_next()? { @@ -868,26 +762,135 @@ impl<'mc> HelpCommand<'mc> { } Ok(new_vec) } - // SUPER CLASS: org.bukkit.command.defaults.BukkitCommand ( ['execute', 'tabComplete']) + /// Returns a message to be displayed on a failed permission check for this command + pub fn permission_message(&self) -> Result, Box> { + let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::command::Command = temp_clone.into(); + real.permission_message() + } + /// Gets a brief description of this command + pub fn description(&self) -> Result> { + let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::command::Command = temp_clone.into(); + real.description() + } + /// Gets an example usage of this command + pub fn usage(&self) -> Result> { + let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::command::Command = temp_clone.into(); + real.usage() + } + /// Sets the list of aliases to request on registration for this command. + /// This is not effective outside of defining aliases in the {@link + /// PluginDescriptionFile#getCommands()} (under the + /// `aliases' node) is equivalent to this method. + pub fn set_aliases( + &self, + aliases: Vec>, + ) -> Result, Box> { + let sig = String::from("(Ljava/util/List;)Lorg/bukkit/command/Command;"); + let raw_val_1 = self + .jni_ref() + .new_object("java/util/ArrayList", "()V", vec![])?; + for v in aliases { + let map_val_0 = jni::objects::JValueGen::Object(v); + self.jni_ref().call_method( + &raw_val_1, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_1 = jni::objects::JValueGen::Object(raw_val_1); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAliases", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::command::Command::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets a brief description of this command. Defining a description in the + /// {@link PluginDescriptionFile#getCommands()} (under the + /// `description' node) is equivalent to this method. + pub fn set_description( + &self, + description: impl Into, + ) -> Result, Box> { + let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::command::Command = temp_clone.into(); + real.set_description(description) + } + /// Sets the message sent when a permission check fails + pub fn set_permission_message( + &self, + permission_message: impl Into, + ) -> Result, Box> { + let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::command::Command = temp_clone.into(); + real.set_permission_message(permission_message) + } + /// Sets the example usage of this command + pub fn set_usage( + &self, + usage: impl Into, + ) -> Result, Box> { + let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::command::Command = temp_clone.into(); + real.set_usage(usage) + } + + pub fn broadcast_command_message( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + source: impl Into>, + message: impl Into, + send_to_source: std::option::Option, + ) -> Result<(), Box> { + crate::command::Command::broadcast_command_message(jni, source, message, send_to_source) + } + + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let temp_clone = crate::command::Command::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::command::Command = temp_clone.into(); + real.internal_to_string() + } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for HelpCommand<'mc> { - fn into(self) -> crate::command::defaults::BukkitCommand<'mc> { - crate::command::defaults::BukkitCommand::from_raw(&self.jni_ref(), self.1) - .expect("Error converting HelpCommand into crate::command::defaults::BukkitCommand") +impl<'mc> Into> for BukkitCommand<'mc> { + fn into(self) -> crate::command::Command<'mc> { + crate::command::Command::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BukkitCommand into crate::command::Command") } } #[repr(C)] -pub struct TimingsCommand<'mc>( +pub struct ReloadCommand<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for TimingsCommand<'mc> { +impl<'mc> JNIRaw<'mc> for ReloadCommand<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -895,21 +898,18 @@ impl<'mc> JNIRaw<'mc> for TimingsCommand<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for TimingsCommand<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ReloadCommand<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate TimingsCommand from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate ReloadCommand from null object.").into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/command/defaults/TimingsCommand")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/command/defaults/ReloadCommand")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a TimingsCommand object, got {}", + "Invalid argument passed. Expected a ReloadCommand object, got {}", name ) .into()) @@ -919,16 +919,16 @@ impl<'mc> JNIInstantiatable<'mc> for TimingsCommand<'mc> { } } -impl<'mc> TimingsCommand<'mc> { +impl<'mc> ReloadCommand<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, name: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let sig = String::from("(Ljava/lang/String;)V"); let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( jni.new_string(name.into())?, )); - let cls = jni.find_class("org/bukkit/command/defaults/TimingsCommand"); + let cls = jni.find_class("org/bukkit/command/defaults/ReloadCommand"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -936,7 +936,7 @@ impl<'mc> TimingsCommand<'mc> { vec![jni::objects::JValueGen::from(val_1)], ); let res = jni.translate_error_no_gen(res)?; - crate::command::defaults::TimingsCommand::from_raw(&jni, res) + crate::command::defaults::ReloadCommand::from_raw(&jni, res) } pub fn execute( @@ -1019,9 +1019,9 @@ impl<'mc> TimingsCommand<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for TimingsCommand<'mc> { +impl<'mc> Into> for ReloadCommand<'mc> { fn into(self) -> crate::command::defaults::BukkitCommand<'mc> { crate::command::defaults::BukkitCommand::from_raw(&self.jni_ref(), self.1) - .expect("Error converting TimingsCommand into crate::command::defaults::BukkitCommand") + .expect("Error converting ReloadCommand into crate::command::defaults::BukkitCommand") } } diff --git a/blackboxmc-rs-bukkit/src/command/mod.rs b/blackboxmc-rs-bukkit/src/command/mod.rs index 7cba2ed..c83a6a8 100644 --- a/blackboxmc-rs-bukkit/src/command/mod.rs +++ b/blackboxmc-rs-bukkit/src/command/mod.rs @@ -3,127 +3,12 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] -pub struct RemoteConsoleCommandSender<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for RemoteConsoleCommandSender<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for RemoteConsoleCommandSender<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate RemoteConsoleCommandSender from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/command/RemoteConsoleCommandSender")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a RemoteConsoleCommandSender object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> RemoteConsoleCommandSender<'mc> { - /// Gets the socket address of this remote sender. - pub fn address(&self) -> Result, Box> { - let sig = String::from("()Ljava/net/SocketAddress;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAddress", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) - } - /// Sends this sender multiple messages - pub fn send_message( - &self, - sender: impl Into>, - messages: std::option::Option>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = messages { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns the server instance that this command is running on - pub fn server(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Server;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Server::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the name of this command sender - pub fn name(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/lang/String;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for RemoteConsoleCommandSender<'mc> { - fn into(self) -> crate::command::CommandSender<'mc> { - crate::command::CommandSender::from_raw(&self.jni_ref(), self.1).expect( - "Error converting RemoteConsoleCommandSender into crate::command::CommandSender", - ) - } -} -#[repr(C)] -pub struct ConsoleCommandSender<'mc>( +pub struct SimpleCommandMap<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ConsoleCommandSender<'mc> { +impl<'mc> JNIRaw<'mc> for SimpleCommandMap<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -131,20 +16,20 @@ impl<'mc> JNIRaw<'mc> for ConsoleCommandSender<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ConsoleCommandSender<'mc> { +impl<'mc> JNIInstantiatable<'mc> for SimpleCommandMap<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate ConsoleCommandSender from null object.").into(), + eyre::eyre!("Tried to instantiate SimpleCommandMap from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/command/ConsoleCommandSender")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/command/SimpleCommandMap")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ConsoleCommandSender object, got {}", + "Invalid argument passed. Expected a SimpleCommandMap object, got {}", name ) .into()) @@ -154,163 +39,238 @@ impl<'mc> JNIInstantiatable<'mc> for ConsoleCommandSender<'mc> { } } -impl<'mc> ConsoleCommandSender<'mc> { - /// Sends this sender multiple messages - pub fn send_message( - &self, - sender: impl Into>, - messages: std::option::Option>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; +impl<'mc> SimpleCommandMap<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + server: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/Server;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + jni::objects::JObject::from_raw(server.into().jni_object().clone()) }); - args.push(val_1); - if let Some(a) = messages { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); + let cls = jni.find_class("org/bukkit/command/SimpleCommandMap"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error_no_gen(res)?; + crate::command::SimpleCommandMap::from_raw(&jni, res) + } + + pub fn set_fallback_commands(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFallbackCommands", + sig.as_str(), + vec![], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the server instance that this command is running on - pub fn server(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Server;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Server::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the name of this command sender - pub fn name(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/lang/String;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Tests to see of a Conversable object is actively engaged in a - /// conversation. - pub fn is_conversing(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isConversing", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Accepts input into the active conversation. If no conversation is in - /// progress, this method does nothing. - pub fn accept_conversation_input( + /// {@inheritDoc} + pub fn register_all( &self, - input: impl Into, + fallback_prefix: impl Into, + commands: Vec>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); + let sig = String::from("(Ljava/lang/String;Ljava/util/List;)V"); let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(input.into())?, + self.jni_ref().new_string(fallback_prefix.into())?, )); + let raw_val_2 = self + .jni_ref() + .new_object("java/util/ArrayList", "()V", vec![])?; + for v in commands { + let map_val_0 = jni::objects::JValueGen::Object(v); + self.jni_ref().call_method( + &raw_val_2, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_2 = jni::objects::JValueGen::Object(raw_val_2); let res = self.jni_ref().call_method( &self.jni_object(), - "acceptConversationInput", + "registerAll", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Enters into a dialog with a Conversation object. - pub fn begin_conversation( + /// {@inheritDoc} + pub fn register( &self, - conversation: impl Into>, + label: impl Into, + fallback_prefix: impl Into, + command: std::option::Option>>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/conversations/Conversation;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(conversation.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "beginConversation", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Abandons an active conversation. - pub fn abandon_conversation( - &self, - conversation: impl Into>, - details: std::option::Option< - impl Into>, - >, - ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/conversations/Conversation;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(conversation.into().jni_object().clone()) - }); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(label.into())?, + )); args.push(val_1); - if let Some(a) = details { - sig += "Lorg/bukkit/conversations/ConversationAbandonedEvent;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(fallback_prefix.into())?, + )); + args.push(val_2); + if let Some(a) = command { + sig += "Lorg/bukkit/command/Command;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); - args.push(val_2); + args.push(val_3); } - sig += ")V"; + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "register", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// {@inheritDoc} + pub fn dispatch( + &self, + sender: impl Into>, + command_line: impl Into, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/command/CommandSender;Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(command_line.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "abandonConversation", + "dispatch", sig.as_str(), - args, + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn clear_commands(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "clearCommands", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sends this sender a message raw - pub fn send_raw_message( + + pub fn get_command( &self, - sender: impl Into>, - message: std::option::Option>, - ) -> Result<(), Box> { + name: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/command/Command;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCommand", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::command::Command::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + + pub fn tab_complete( + &self, + sender: impl Into>, + cmd_line: impl Into, + location: std::option::Option>>, + ) -> Result>, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; + sig += "Lorg/bukkit/command/CommandSender;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(sender.into().jni_object().clone()) }); args.push(val_1); - if let Some(a) = message { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_2); + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(cmd_line.into())?, + )); + args.push(val_2); + if let Some(a) = location { + sig += "Lorg/bukkit/Location;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_3); } - sig += ")V"; + sig += ")Ljava/util/List;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "tabComplete", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); + } + Ok(Some(new_vec)) + } + + pub fn commands( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "sendRawMessage", sig.as_str(), args); + .call_method(&self.jni_object(), "getCommands", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::command::Command::from_raw(&self.0, obj)?); + } + Ok(new_vec) + } + + pub fn register_server_aliases(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "registerServerAliases", + sig.as_str(), + vec![], + ); self.jni_ref().translate_error(res)?; Ok(()) } @@ -320,25 +280,19 @@ impl<'mc> ConsoleCommandSender<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for ConsoleCommandSender<'mc> { - fn into(self) -> crate::command::CommandSender<'mc> { - crate::command::CommandSender::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ConsoleCommandSender into crate::command::CommandSender") - } -} -impl<'mc> Into> for ConsoleCommandSender<'mc> { - fn into(self) -> crate::conversations::Conversable<'mc> { - crate::conversations::Conversable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ConsoleCommandSender into crate::conversations::Conversable") +impl<'mc> Into> for SimpleCommandMap<'mc> { + fn into(self) -> crate::command::CommandMap<'mc> { + crate::command::CommandMap::from_raw(&self.jni_ref(), self.1) + .expect("Error converting SimpleCommandMap into crate::command::CommandMap") } } #[repr(C)] -pub struct PluginCommand<'mc>( +pub struct PluginCommandYamlParser<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PluginCommand<'mc> { +impl<'mc> JNIRaw<'mc> for PluginCommandYamlParser<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -346,18 +300,22 @@ impl<'mc> JNIRaw<'mc> for PluginCommand<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PluginCommand<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PluginCommandYamlParser<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate PluginCommand from null object.").into()); + return Err(eyre::eyre!( + "Tried to instantiate PluginCommandYamlParser from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/command/PluginCommand")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/command/PluginCommandYamlParser")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PluginCommand object, got {}", + "Invalid argument passed. Expected a PluginCommandYamlParser object, got {}", name ) .into()) @@ -367,34 +325,113 @@ impl<'mc> JNIInstantiatable<'mc> for PluginCommand<'mc> { } } -impl<'mc> PluginCommand<'mc> { - /// Executes the command, returning its success - pub fn execute( - &self, - sender: impl Into>, - command_label: impl Into, - val_args: impl Into, - ) -> Result> { - let sig = String::from( - "(Lorg/bukkit/command/CommandSender;Ljava/lang/String;Ljava/lang/String;)Z", - ); +impl<'mc> PluginCommandYamlParser<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()V"); + let cls = jni.find_class("org/bukkit/command/PluginCommandYamlParser"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), vec![]); + let res = jni.translate_error_no_gen(res)?; + crate::command::PluginCommandYamlParser::from_raw(&jni, res) + } + + pub fn parse( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + plugin: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;)Ljava/util/List;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(command_label.into())?, - )); - let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(val_args.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "execute", + let cls = jni.find_class("org/bukkit/command/PluginCommandYamlParser"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "parse", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&jni, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::command::Command::from_raw(&jni, obj)?); + } + Ok(new_vec) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct PluginCommand<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PluginCommand<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PluginCommand<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate PluginCommand from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/command/PluginCommand")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PluginCommand object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> PluginCommand<'mc> { + /// Executes the command, returning its success + pub fn execute( + &self, + sender: impl Into>, + command_label: impl Into, + val_args: impl Into, + ) -> Result> { + let sig = String::from( + "(Lorg/bukkit/command/CommandSender;Ljava/lang/String;Ljava/lang/String;)Z", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(command_label.into())?, + )); + let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(val_args.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "execute", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), ], ); let res = self.jni_ref().translate_error(res)?; @@ -1197,95 +1234,12 @@ impl<'mc> Into> for FormattedCommandAlias<'mc> { } } #[repr(C)] -pub struct PluginCommandYamlParser<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PluginCommandYamlParser<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PluginCommandYamlParser<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PluginCommandYamlParser from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/command/PluginCommandYamlParser")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PluginCommandYamlParser object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> PluginCommandYamlParser<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/command/PluginCommandYamlParser"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), vec![]); - let res = jni.translate_error_no_gen(res)?; - crate::command::PluginCommandYamlParser::from_raw(&jni, res) - } - - pub fn parse( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - plugin: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/command/PluginCommandYamlParser"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "parse", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&jni, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::command::Command::from_raw(&jni, obj)?); - } - Ok(new_vec) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct TabCompleter<'mc>( +pub struct Command<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for TabCompleter<'mc> { +impl<'mc> JNIRaw<'mc> for Command<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1293,18 +1247,18 @@ impl<'mc> JNIRaw<'mc> for TabCompleter<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for TabCompleter<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Command<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate TabCompleter from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Command from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/command/TabCompleter")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/command/Command")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a TabCompleter object, got {}", + "Invalid argument passed. Expected a Command object, got {}", name ) .into()) @@ -1314,55 +1268,47 @@ impl<'mc> JNIInstantiatable<'mc> for TabCompleter<'mc> { } } -impl<'mc> TabCompleter<'mc> { - pub fn from_extendable( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - plugin: &'mc crate::plugin::Plugin, - address: i32, - lib_name: String, - name: String, - ) -> Result> { - let obj = unsafe { plugin.new_extendable(address, "TabCompleter", name, lib_name) }?; - Self::from_raw(env, obj) - } - /// Requests a list of possible completions for a command argument. - pub fn on_tab_complete( +impl<'mc> Command<'mc> { + /// Executed on tab completion for this command, returning a list of + /// options the player can tab through. + pub fn tab_complete( &self, sender: impl Into>, - command: impl Into>, - label: impl Into, + alias: impl Into, val_args: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/command/CommandSender;Lorg/bukkit/command/Command;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;"); + location: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/command/CommandSender;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(sender.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(command.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(label.into())?, + args.push(val_1); + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(alias.into())?, )); - let val_4 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + args.push(val_2); + sig += "Ljava/lang/String;"; + let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( self.jni_ref().new_string(val_args.into())?, )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "onTabComplete", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - ], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + args.push(val_3); + if let Some(a) = location { + sig += "Lorg/bukkit/Location;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_4); } + sig += ")Ljava/util/List;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "tabComplete", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; @@ -1373,101 +1319,7 @@ impl<'mc> TabCompleter<'mc> { .to_string(), ); } - Ok(Some(new_vec)) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct Command<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Command<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Command<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Command from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/command/Command")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Command object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Command<'mc> { - /// Executed on tab completion for this command, returning a list of - /// options the player can tab through. - pub fn tab_complete( - &self, - sender: impl Into>, - alias: impl Into, - val_args: impl Into, - location: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/command/CommandSender;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(alias.into())?, - )); - args.push(val_2); - sig += "Ljava/lang/String;"; - let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(val_args.into())?, - )); - args.push(val_3); - if let Some(a) = location { - sig += "Lorg/bukkit/Location;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_4); - } - sig += ")Ljava/util/List;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "tabComplete", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), - ); - } - Ok(new_vec) + Ok(new_vec) } /// Returns the name of this command pub fn name(&self) -> Result> { @@ -1886,12 +1738,12 @@ impl<'mc> std::string::ToString for Command<'mc> { } #[repr(C)] -pub struct TabExecutor<'mc>( +pub struct ConsoleCommandSender<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for TabExecutor<'mc> { +impl<'mc> JNIRaw<'mc> for ConsoleCommandSender<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1899,18 +1751,20 @@ impl<'mc> JNIRaw<'mc> for TabExecutor<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for TabExecutor<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ConsoleCommandSender<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate TabExecutor from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate ConsoleCommandSender from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/command/TabExecutor")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/command/ConsoleCommandSender")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a TabExecutor object, got {}", + "Invalid argument passed. Expected a ConsoleCommandSender object, got {}", name ) .into()) @@ -1920,177 +1774,144 @@ impl<'mc> JNIInstantiatable<'mc> for TabExecutor<'mc> { } } -impl<'mc> TabExecutor<'mc> { - pub fn from_extendable( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - plugin: &'mc crate::plugin::Plugin, - address: i32, - lib_name: String, - name: String, - ) -> Result> { - let obj = unsafe { plugin.new_extendable(address, "TabExecutor", name, lib_name) }?; - Self::from_raw(env, obj) - } - /// Requests a list of possible completions for a command argument. - pub fn on_tab_complete( +impl<'mc> ConsoleCommandSender<'mc> { + /// Sends this sender multiple messages + pub fn send_message( &self, - sender: impl Into>, - command: impl Into>, - label: impl Into, - val_args: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/command/CommandSender;Lorg/bukkit/command/Command;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;"); + sender: impl Into>, + messages: std::option::Option>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/util/UUID;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(sender.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(command.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(label.into())?, - )); - let val_4 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(val_args.into())?, + args.push(val_1); + if let Some(a) = messages { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_2); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the server instance that this command is running on + pub fn server(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Server;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Server::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the name of this command sender + pub fn name(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/lang/String;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Tests to see of a Conversable object is actively engaged in a + /// conversation. + pub fn is_conversing(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isConversing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Accepts input into the active conversation. If no conversation is in + /// progress, this method does nothing. + pub fn accept_conversation_input( + &self, + input: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(input.into())?, )); let res = self.jni_ref().call_method( &self.jni_object(), - "onTabComplete", + "acceptConversationInput", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), - ); - } - Ok(Some(new_vec)) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Executes the given command, returning its success. - /// - /// If false is returned, then the "usage" plugin.yml entry for this command - /// (if defined) will be sent to the player. - pub fn on_command( + /// Enters into a dialog with a Conversation object. + pub fn begin_conversation( &self, - sender: impl Into>, - command: impl Into>, - label: impl Into, - val_args: impl Into, + conversation: impl Into>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/command/CommandSender;Lorg/bukkit/command/Command;Ljava/lang/String;Ljava/lang/String;)Z"); + let sig = String::from("(Lorg/bukkit/conversations/Conversation;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(command.into().jni_object().clone()) + jni::objects::JObject::from_raw(conversation.into().jni_object().clone()) }); - let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(label.into())?, - )); - let val_4 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(val_args.into())?, - )); let res = self.jni_ref().call_method( &self.jni_object(), - "onCommand", + "beginConversation", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for TabExecutor<'mc> { - fn into(self) -> crate::command::TabCompleter<'mc> { - crate::command::TabCompleter::from_raw(&self.jni_ref(), self.1) - .expect("Error converting TabExecutor into crate::command::TabCompleter") - } -} -impl<'mc> Into> for TabExecutor<'mc> { - fn into(self) -> crate::command::CommandExecutor<'mc> { - crate::command::CommandExecutor::from_raw(&self.jni_ref(), self.1) - .expect("Error converting TabExecutor into crate::command::CommandExecutor") - } -} -#[repr(C)] -pub struct BlockCommandSender<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for BlockCommandSender<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for BlockCommandSender<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate BlockCommandSender from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/command/BlockCommandSender")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockCommandSender object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + /// Abandons an active conversation. + pub fn abandon_conversation( + &self, + conversation: impl Into>, + details: std::option::Option< + impl Into>, + >, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/conversations/Conversation;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(conversation.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = details { + sig += "Lorg/bukkit/conversations/ConversationAbandonedEvent;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); } + sig += ")V"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "abandonConversation", + sig.as_str(), + args, + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> BlockCommandSender<'mc> { - /// Returns the block this command sender belongs to - pub fn block(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sends this sender multiple messages - pub fn send_message( + /// Sends this sender a message raw + pub fn send_raw_message( &self, sender: impl Into>, - messages: std::option::Option>, + message: std::option::Option>, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); @@ -2099,7 +1920,7 @@ impl<'mc> BlockCommandSender<'mc> { jni::objects::JObject::from_raw(sender.into().jni_object().clone()) }); args.push(val_1); - if let Some(a) = messages { + if let Some(a) = message { sig += "Ljava/lang/String;"; let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( self.jni_ref().new_string(a.into())?, @@ -2107,57 +1928,37 @@ impl<'mc> BlockCommandSender<'mc> { args.push(val_2); } sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "sendRawMessage", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the server instance that this command is running on - pub fn server(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Server;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Server::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the name of this command sender - pub fn name(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/lang/String;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockCommandSender<'mc> { +impl<'mc> Into> for ConsoleCommandSender<'mc> { fn into(self) -> crate::command::CommandSender<'mc> { crate::command::CommandSender::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockCommandSender into crate::command::CommandSender") + .expect("Error converting ConsoleCommandSender into crate::command::CommandSender") + } +} +impl<'mc> Into> for ConsoleCommandSender<'mc> { + fn into(self) -> crate::conversations::Conversable<'mc> { + crate::conversations::Conversable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ConsoleCommandSender into crate::conversations::Conversable") } } #[repr(C)] -pub struct CommandExecutor<'mc>( +pub struct TabCompleter<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for CommandExecutor<'mc> { +impl<'mc> JNIRaw<'mc> for TabCompleter<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2165,20 +1966,18 @@ impl<'mc> JNIRaw<'mc> for CommandExecutor<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for CommandExecutor<'mc> { +impl<'mc> JNIInstantiatable<'mc> for TabCompleter<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate CommandExecutor from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate TabCompleter from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/command/CommandExecutor")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/command/TabCompleter")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a CommandExecutor object, got {}", + "Invalid argument passed. Expected a TabCompleter object, got {}", name ) .into()) @@ -2188,7 +1987,7 @@ impl<'mc> JNIInstantiatable<'mc> for CommandExecutor<'mc> { } } -impl<'mc> CommandExecutor<'mc> { +impl<'mc> TabCompleter<'mc> { pub fn from_extendable( env: &blackboxmc_general::SharedJNIEnv<'mc>, plugin: &'mc crate::plugin::Plugin, @@ -2196,21 +1995,18 @@ impl<'mc> CommandExecutor<'mc> { lib_name: String, name: String, ) -> Result> { - let obj = unsafe { plugin.new_extendable(address, "CommandExecutor", name, lib_name) }?; + let obj = unsafe { plugin.new_extendable(address, "TabCompleter", name, lib_name) }?; Self::from_raw(env, obj) } - /// Executes the given command, returning its success. - /// - /// If false is returned, then the "usage" plugin.yml entry for this command - /// (if defined) will be sent to the player. - pub fn on_command( + /// Requests a list of possible completions for a command argument. + pub fn on_tab_complete( &self, sender: impl Into>, command: impl Into>, label: impl Into, val_args: impl Into, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/command/CommandSender;Lorg/bukkit/command/Command;Ljava/lang/String;Ljava/lang/String;)Z"); + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/command/CommandSender;Lorg/bukkit/command/Command;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(sender.into().jni_object().clone()) }); @@ -2225,7 +2021,7 @@ impl<'mc> CommandExecutor<'mc> { )); let res = self.jni_ref().call_method( &self.jni_object(), - "onCommand", + "onTabComplete", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), @@ -2235,7 +2031,22 @@ impl<'mc> CommandExecutor<'mc> { ], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); + } + Ok(Some(new_vec)) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -2244,12 +2055,12 @@ impl<'mc> CommandExecutor<'mc> { } } #[repr(C)] -pub struct ProxiedCommandSender<'mc>( +pub struct TabExecutor<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ProxiedCommandSender<'mc> { +impl<'mc> JNIRaw<'mc> for TabExecutor<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2257,20 +2068,18 @@ impl<'mc> JNIRaw<'mc> for ProxiedCommandSender<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ProxiedCommandSender<'mc> { +impl<'mc> JNIInstantiatable<'mc> for TabExecutor<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate ProxiedCommandSender from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate TabExecutor from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/command/ProxiedCommandSender")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/command/TabExecutor")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ProxiedCommandSender object, got {}", + "Invalid argument passed. Expected a TabExecutor object, got {}", name ) .into()) @@ -2280,42 +2089,185 @@ impl<'mc> JNIInstantiatable<'mc> for ProxiedCommandSender<'mc> { } } -impl<'mc> ProxiedCommandSender<'mc> { - /// Returns the CommandSender which triggered this proxied command - pub fn caller(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/command/CommandSender;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getCaller", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::command::CommandSender::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns the CommandSender which is being used to call the command - pub fn callee(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/command/CommandSender;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getCallee", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::command::CommandSender::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +impl<'mc> TabExecutor<'mc> { + pub fn from_extendable( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + plugin: &'mc crate::plugin::Plugin, + address: i32, + lib_name: String, + name: String, + ) -> Result> { + let obj = unsafe { plugin.new_extendable(address, "TabExecutor", name, lib_name) }?; + Self::from_raw(env, obj) } - /// Sends this sender multiple messages - pub fn send_message( + /// Requests a list of possible completions for a command argument. + pub fn on_tab_complete( &self, - sender: impl Into>, - messages: std::option::Option>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; + sender: impl Into>, + command: impl Into>, + label: impl Into, + val_args: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/command/CommandSender;Lorg/bukkit/command/Command;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(sender.into().jni_object().clone()) }); - args.push(val_1); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(command.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(label.into())?, + )); + let val_4 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(val_args.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "onTabComplete", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + ], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); + } + Ok(Some(new_vec)) + } + /// Executes the given command, returning its success. + /// + /// If false is returned, then the "usage" plugin.yml entry for this command + /// (if defined) will be sent to the player. + pub fn on_command( + &self, + sender: impl Into>, + command: impl Into>, + label: impl Into, + val_args: impl Into, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/command/CommandSender;Lorg/bukkit/command/Command;Ljava/lang/String;Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(command.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(label.into())?, + )); + let val_4 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(val_args.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "onCommand", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for TabExecutor<'mc> { + fn into(self) -> crate::command::TabCompleter<'mc> { + crate::command::TabCompleter::from_raw(&self.jni_ref(), self.1) + .expect("Error converting TabExecutor into crate::command::TabCompleter") + } +} +impl<'mc> Into> for TabExecutor<'mc> { + fn into(self) -> crate::command::CommandExecutor<'mc> { + crate::command::CommandExecutor::from_raw(&self.jni_ref(), self.1) + .expect("Error converting TabExecutor into crate::command::CommandExecutor") + } +} +#[repr(C)] +pub struct BlockCommandSender<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for BlockCommandSender<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for BlockCommandSender<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate BlockCommandSender from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/command/BlockCommandSender")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BlockCommandSender object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> BlockCommandSender<'mc> { + /// Returns the block this command sender belongs to + pub fn block(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sends this sender multiple messages + pub fn send_message( + &self, + sender: impl Into>, + messages: std::option::Option>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/util/UUID;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + }); + args.push(val_1); if let Some(a) = messages { sig += "Ljava/lang/String;"; let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( @@ -2362,19 +2314,19 @@ impl<'mc> ProxiedCommandSender<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for ProxiedCommandSender<'mc> { +impl<'mc> Into> for BlockCommandSender<'mc> { fn into(self) -> crate::command::CommandSender<'mc> { crate::command::CommandSender::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ProxiedCommandSender into crate::command::CommandSender") + .expect("Error converting BlockCommandSender into crate::command::CommandSender") } } #[repr(C)] -pub struct SimpleCommandMap<'mc>( +pub struct CommandExecutor<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for SimpleCommandMap<'mc> { +impl<'mc> JNIRaw<'mc> for CommandExecutor<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2382,20 +2334,20 @@ impl<'mc> JNIRaw<'mc> for SimpleCommandMap<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for SimpleCommandMap<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CommandExecutor<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate SimpleCommandMap from null object.").into(), + eyre::eyre!("Tried to instantiate CommandExecutor from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/command/SimpleCommandMap")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/command/CommandExecutor")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SimpleCommandMap object, got {}", + "Invalid argument passed. Expected a CommandExecutor object, got {}", name ) .into()) @@ -2405,240 +2357,288 @@ impl<'mc> JNIInstantiatable<'mc> for SimpleCommandMap<'mc> { } } -impl<'mc> SimpleCommandMap<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - server: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/Server;)V"); +impl<'mc> CommandExecutor<'mc> { + pub fn from_extendable( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + plugin: &'mc crate::plugin::Plugin, + address: i32, + lib_name: String, + name: String, + ) -> Result> { + let obj = unsafe { plugin.new_extendable(address, "CommandExecutor", name, lib_name) }?; + Self::from_raw(env, obj) + } + /// Executes the given command, returning its success. + /// + /// If false is returned, then the "usage" plugin.yml entry for this command + /// (if defined) will be sent to the player. + pub fn on_command( + &self, + sender: impl Into>, + command: impl Into>, + label: impl Into, + val_args: impl Into, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/command/CommandSender;Lorg/bukkit/command/Command;Ljava/lang/String;Ljava/lang/String;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(server.into().jni_object().clone()) + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/command/SimpleCommandMap"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error_no_gen(res)?; - crate::command::SimpleCommandMap::from_raw(&jni, res) - } - - pub fn set_fallback_commands(&self) -> Result<(), Box> { - let sig = String::from("()V"); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(command.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(label.into())?, + )); + let val_4 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(val_args.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setFallbackCommands", + "onCommand", sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// {@inheritDoc} - pub fn register_all( - &self, - fallback_prefix: impl Into, - commands: Vec>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Ljava/util/List;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(fallback_prefix.into())?, - )); - let raw_val_2 = self - .jni_ref() - .new_object("java/util/ArrayList", "()V", vec![])?; - for v in commands { - let map_val_0 = jni::objects::JValueGen::Object(v); - self.jni_ref().call_method( - &raw_val_2, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct RemoteConsoleCommandSender<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for RemoteConsoleCommandSender<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for RemoteConsoleCommandSender<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate RemoteConsoleCommandSender from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/command/RemoteConsoleCommandSender")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a RemoteConsoleCommandSender object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - let val_2 = jni::objects::JValueGen::Object(raw_val_2); - let res = self.jni_ref().call_method( - &self.jni_object(), - "registerAll", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) } - /// {@inheritDoc} - pub fn register( +} + +impl<'mc> RemoteConsoleCommandSender<'mc> { + /// Gets the socket address of this remote sender. + pub fn address(&self) -> Result, Box> { + let sig = String::from("()Ljava/net/SocketAddress;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAddress", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) + } + /// Sends this sender multiple messages + pub fn send_message( &self, - label: impl Into, - fallback_prefix: impl Into, - command: std::option::Option>>, - ) -> Result> { + sender: impl Into>, + messages: std::option::Option>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(label.into())?, - )); + sig += "Ljava/util/UUID;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + }); args.push(val_1); - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(fallback_prefix.into())?, - )); - args.push(val_2); - if let Some(a) = command { - sig += "Lorg/bukkit/command/Command;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_3); + if let Some(a) = messages { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_2); } - sig += ")Z"; + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "register", sig.as_str(), args); + .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the server instance that this command is running on + pub fn server(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Server;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Server::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// {@inheritDoc} - pub fn dispatch( - &self, - sender: impl Into>, - command_line: impl Into, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/command/CommandSender;Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(command_line.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "dispatch", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + /// Gets the name of this command sender + pub fn name(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/lang/String;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - pub fn clear_commands(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "clearCommands", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for RemoteConsoleCommandSender<'mc> { + fn into(self) -> crate::command::CommandSender<'mc> { + crate::command::CommandSender::from_raw(&self.jni_ref(), self.1).expect( + "Error converting RemoteConsoleCommandSender into crate::command::CommandSender", + ) } +} +#[repr(C)] +pub struct ProxiedCommandSender<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); - pub fn get_command( - &self, - name: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/command/Command;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCommand", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); +impl<'mc> JNIRaw<'mc> for ProxiedCommandSender<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for ProxiedCommandSender<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate ProxiedCommandSender from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/command/ProxiedCommandSender")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ProxiedCommandSender object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - Ok(Some(crate::command::Command::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) } +} - pub fn tab_complete( +impl<'mc> ProxiedCommandSender<'mc> { + /// Returns the CommandSender which triggered this proxied command + pub fn caller(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/command/CommandSender;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCaller", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::command::CommandSender::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns the CommandSender which is being used to call the command + pub fn callee(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/command/CommandSender;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCallee", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::command::CommandSender::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sends this sender multiple messages + pub fn send_message( &self, - sender: impl Into>, - cmd_line: impl Into, - location: std::option::Option>>, - ) -> Result>, Box> { + sender: impl Into>, + messages: std::option::Option>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/command/CommandSender;"; + sig += "Ljava/util/UUID;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(sender.into().jni_object().clone()) }); args.push(val_1); - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(cmd_line.into())?, - )); - args.push(val_2); - if let Some(a) = location { - sig += "Lorg/bukkit/Location;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_3); + if let Some(a) = messages { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_2); } - sig += ")Ljava/util/List;"; + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "tabComplete", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), - ); - } - Ok(Some(new_vec)) + .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - - pub fn commands( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCommands", sig.as_str(), vec![]); + /// Returns the server instance that this command is running on + pub fn server(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Server;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::command::Command::from_raw(&self.0, obj)?); - } - Ok(new_vec) + crate::Server::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - - pub fn register_server_aliases(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "registerServerAliases", - sig.as_str(), - vec![], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Gets the name of this command sender + pub fn name(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/lang/String;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -2646,10 +2646,10 @@ impl<'mc> SimpleCommandMap<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for SimpleCommandMap<'mc> { - fn into(self) -> crate::command::CommandMap<'mc> { - crate::command::CommandMap::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SimpleCommandMap into crate::command::CommandMap") +impl<'mc> Into> for ProxiedCommandSender<'mc> { + fn into(self) -> crate::command::CommandSender<'mc> { + crate::command::CommandSender::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ProxiedCommandSender into crate::command::CommandSender") } } #[repr(C)] diff --git a/blackboxmc-rs-bukkit/src/configuration/file/mod.rs b/blackboxmc-rs-bukkit/src/configuration/file/mod.rs index 3c30cca..2bad8fd 100644 --- a/blackboxmc-rs-bukkit/src/configuration/file/mod.rs +++ b/blackboxmc-rs-bukkit/src/configuration/file/mod.rs @@ -3,6 +3,191 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] +pub struct YamlConstructor<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for YamlConstructor<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for YamlConstructor<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate YamlConstructor from null object.").into(), + ); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/configuration/file/YamlConstructor")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a YamlConstructor object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> YamlConstructor<'mc> { + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct YamlConfiguration<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for YamlConfiguration<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for YamlConfiguration<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate YamlConfiguration from null object.").into(), + ); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/configuration/file/YamlConfiguration")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a YamlConfiguration object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> YamlConfiguration<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> + { + let sig = String::from("()V"); + let cls = jni.find_class("org/bukkit/configuration/file/YamlConfiguration"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), vec![]); + let res = jni.translate_error_no_gen(res)?; + crate::configuration::file::YamlConfiguration::from_raw(&jni, res) + } + + pub fn save_to_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "saveToString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + + pub fn load_from_string( + &self, + contents: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(contents.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "loadFromString", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn options( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/configuration/file/YamlConfigurationOptions;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "options", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::configuration::file::YamlConfigurationOptions::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + // SUPER CLASS: org.bukkit.configuration.file.FileConfiguration ( ['saveToString', 'loadFromString', 'options', 'loadConfiguration']) + /// Saves this {@link FileConfiguration} to the specified location. + /// + /// If the file does not exist, it will be created. If already exists, it + /// will be overwritten. If it cannot be overwritten or created, an + /// exception will be thrown. + /// + /// This method will save using the system default encoding, or possibly + /// using UTF8. + pub fn save(&self, file: impl Into) -> Result<(), Box> { + let temp_clone = + crate::configuration::file::FileConfiguration::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::file::FileConfiguration = temp_clone.into(); + real.save(file) + } + /// Loads this {@link FileConfiguration} from the specified location. + /// + /// All the values contained within this configuration will be removed, + /// leaving only settings and defaults, and the new values will be loaded + /// from the given file. + /// + /// If the file cannot be loaded for any reason, an exception will be + /// thrown. + pub fn load(&self, file: impl Into) -> Result<(), Box> { + let temp_clone = + crate::configuration::file::FileConfiguration::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::file::FileConfiguration = temp_clone.into(); + real.load(file) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for YamlConfiguration<'mc> { + fn into(self) -> crate::configuration::file::FileConfiguration<'mc> { + crate::configuration::file::FileConfiguration::from_raw(&self.jni_ref(), self.1).expect( + "Error converting YamlConfiguration into crate::configuration::file::FileConfiguration", + ) + } +} +#[repr(C)] pub struct FileConfiguration<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, @@ -543,147 +728,6 @@ impl<'mc> Into> } } #[repr(C)] -pub struct YamlConfiguration<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for YamlConfiguration<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for YamlConfiguration<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate YamlConfiguration from null object.").into(), - ); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/configuration/file/YamlConfiguration")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a YamlConfiguration object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> YamlConfiguration<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> - { - let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/configuration/file/YamlConfiguration"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), vec![]); - let res = jni.translate_error_no_gen(res)?; - crate::configuration::file::YamlConfiguration::from_raw(&jni, res) - } - - pub fn save_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "saveToString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - - pub fn load_from_string( - &self, - contents: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(contents.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "loadFromString", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn options( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/configuration/file/YamlConfigurationOptions;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "options", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::configuration::file::YamlConfigurationOptions::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - // SUPER CLASS: org.bukkit.configuration.file.FileConfiguration ( ['saveToString', 'loadFromString', 'options', 'loadConfiguration']) - /// Saves this {@link FileConfiguration} to the specified location. - /// - /// If the file does not exist, it will be created. If already exists, it - /// will be overwritten. If it cannot be overwritten or created, an - /// exception will be thrown. - /// - /// This method will save using the system default encoding, or possibly - /// using UTF8. - pub fn save(&self, file: impl Into) -> Result<(), Box> { - let temp_clone = - crate::configuration::file::FileConfiguration::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::file::FileConfiguration = temp_clone.into(); - real.save(file) - } - /// Loads this {@link FileConfiguration} from the specified location. - /// - /// All the values contained within this configuration will be removed, - /// leaving only settings and defaults, and the new values will be loaded - /// from the given file. - /// - /// If the file cannot be loaded for any reason, an exception will be - /// thrown. - pub fn load(&self, file: impl Into) -> Result<(), Box> { - let temp_clone = - crate::configuration::file::FileConfiguration::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::file::FileConfiguration = temp_clone.into(); - real.load(file) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for YamlConfiguration<'mc> { - fn into(self) -> crate::configuration::file::FileConfiguration<'mc> { - crate::configuration::file::FileConfiguration::from_raw(&self.jni_ref(), self.1).expect( - "Error converting YamlConfiguration into crate::configuration::file::FileConfiguration", - ) - } -} -#[repr(C)] pub struct YamlRepresenter<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, @@ -728,50 +772,6 @@ impl<'mc> YamlRepresenter<'mc> { } } #[repr(C)] -pub struct YamlConstructor<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for YamlConstructor<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for YamlConstructor<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate YamlConstructor from null object.").into(), - ); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/configuration/file/YamlConstructor")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a YamlConstructor object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> YamlConstructor<'mc> { - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] pub struct YamlConfigurationOptions<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, diff --git a/blackboxmc-rs-bukkit/src/configuration/mod.rs b/blackboxmc-rs-bukkit/src/configuration/mod.rs index 4f78a20..2550507 100644 --- a/blackboxmc-rs-bukkit/src/configuration/mod.rs +++ b/blackboxmc-rs-bukkit/src/configuration/mod.rs @@ -3,12 +3,12 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] -pub struct MemoryConfiguration<'mc>( +pub struct MemorySection<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for MemoryConfiguration<'mc> { +impl<'mc> JNIRaw<'mc> for MemorySection<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -16,21 +16,18 @@ impl<'mc> JNIRaw<'mc> for MemoryConfiguration<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for MemoryConfiguration<'mc> { +impl<'mc> JNIInstantiatable<'mc> for MemorySection<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate MemoryConfiguration from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate MemorySection from null object.").into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/configuration/MemoryConfiguration")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/configuration/MemorySection")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a MemoryConfiguration object, got {}", + "Invalid argument passed. Expected a MemorySection object, got {}", name ) .into()) @@ -40,74 +37,116 @@ impl<'mc> JNIInstantiatable<'mc> for MemoryConfiguration<'mc> { } } -impl<'mc> MemoryConfiguration<'mc> { - /// Creates an empty {@link MemoryConfiguration} using the specified {@link - /// Configuration} as a source for all default values. - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - defaults: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = defaults { - sig += "Lorg/bukkit/configuration/Configuration;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/configuration/MemoryConfiguration"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::configuration::MemoryConfiguration::from_raw(&jni, res) +impl<'mc> MemorySection<'mc> { + pub fn get_keys( + &self, + deep: bool, + ) -> Result, Box> { + let sig = String::from("(Z)Ljava/util/Set;"); + let val_1 = jni::objects::JValueGen::Bool(deep.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getKeys", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - pub fn add_defaults( + pub fn get_values( &self, - defaults: impl Into>, - ) -> Result<(), Box> { + deep: bool, + ) -> Result, Box> { + let sig = String::from("(Z)Ljava/util/Map;"); + let val_1 = jni::objects::JValueGen::Bool(deep.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getValues", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn contains( + &self, + path: impl Into, + ignore_default: std::option::Option, + ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/configuration/Configuration;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(defaults.into().jni_object().clone()) - }); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); args.push(val_1); - sig += ")V"; + if let Some(a) = ignore_default { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "addDefaults", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "contains", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - pub fn set_defaults( - &self, - defaults: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/configuration/Configuration;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(defaults.into().jni_object().clone()) - }); + pub fn is_set(&self, path: impl Into) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setDefaults", + "isSet", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - pub fn defaults( + pub fn current_path(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCurrentPath", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + + pub fn root( &self, ) -> Result>, Box> { let sig = String::from("()Lorg/bukkit/configuration/Configuration;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDefaults", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRoot", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); @@ -136,27 +175,6 @@ impl<'mc> MemoryConfiguration<'mc> { )?)) } - pub fn options( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/configuration/MemoryConfigurationOptions;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "options", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::configuration::MemoryConfigurationOptions::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the default value of the given path as provided. - /// - /// If no source {@link Configuration} was provided as a default - /// collection, then a new {@link MemoryConfiguration} will be created to - /// hold the new default value. - /// - /// If value is null, the value will be removed from the default - /// Configuration source. pub fn add_default( &self, path: impl Into, @@ -179,49 +197,56 @@ impl<'mc> MemoryConfiguration<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - // SUPER CLASS: org.bukkit.configuration.MemorySection ( ['addDefaults', 'setDefaults', 'getDefaults', 'getParent', 'options', 'addDefault']) - pub fn get_keys( + pub fn default_section( &self, - deep: bool, - ) -> Result, Box> { - let sig = String::from("(Z)Ljava/util/Set;"); - let val_1 = jni::objects::JValueGen::Bool(deep.into()); + ) -> Result>, Box> + { + let sig = String::from("()Lorg/bukkit/configuration/ConfigurationSection;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getKeys", + "getDefaultSection", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::configuration::ConfigurationSection::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - pub fn get_values( + pub fn set( &self, - deep: bool, - ) -> Result, Box> { - let sig = String::from("(Z)Ljava/util/Map;"); - let val_1 = jni::objects::JValueGen::Bool(deep.into()); + path: impl Into, + value: jni::objects::JObject<'mc>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;Ljava/lang/Object;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(value); let res = self.jni_ref().call_method( &self.jni_object(), - "getValues", + "set", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - pub fn contains( + pub fn get( &self, path: impl Into, - ignore_default: std::option::Option, - ) -> Result> { + def: std::option::Option>, + ) -> Result>, Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "Ljava/lang/String;"; @@ -229,86 +254,20 @@ impl<'mc> MemoryConfiguration<'mc> { self.jni_ref().new_string(path.into())?, )); args.push(val_1); - if let Some(a) = ignore_default { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); + if let Some(a) = def { + sig += "Ljava/lang/Object;"; + let val_2 = jni::objects::JValueGen::Object(a); args.push(val_2); } - sig += ")Z"; + sig += ")Ljava/lang/Object;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "contains", sig.as_str(), args); + .call_method(&self.jni_object(), "get", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn is_set(&self, path: impl Into) -> Result> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.is_set(path) - } - - pub fn current_path(&self) -> Result> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.current_path() - } - - pub fn name(&self) -> Result> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.name() - } - - pub fn root( - &self, - ) -> Result>, Box> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.root() - } - - pub fn default_section( - &self, - ) -> Result>, Box> - { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.default_section() - } - - pub fn set( - &self, - path: impl Into, - value: jni::objects::JObject<'mc>, - ) -> Result<(), Box> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.set(path, value) - } - - pub fn get( - &self, - path: impl Into, - def: std::option::Option>, - ) -> Result>, Box> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.get(path, def) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) } pub fn create_section( @@ -316,11 +275,28 @@ impl<'mc> MemoryConfiguration<'mc> { path: impl Into, map: std::option::Option>>, ) -> Result, Box> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.create_section(path, map) + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + args.push(val_1); + if let Some(a) = map { + sig += "Ljava/util/Map;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/configuration/ConfigurationSection;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createSection", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::configuration::ConfigurationSection::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn get_string( @@ -328,19 +304,49 @@ impl<'mc> MemoryConfiguration<'mc> { path: impl Into, def: std::option::Option>, ) -> Result, Box> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.get_string(path, def) + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + args.push(val_1); + if let Some(a) = def { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_2); + } + sig += ")Ljava/lang/String;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getString", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } pub fn is_string(&self, path: impl Into) -> Result> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.is_string(path) + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isString", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } pub fn get_int( @@ -348,19 +354,39 @@ impl<'mc> MemoryConfiguration<'mc> { path: impl Into, def: std::option::Option, ) -> Result> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.get_int(path, def) + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + args.push(val_1); + if let Some(a) = def { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + sig += ")I"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getInt", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } pub fn is_int(&self, path: impl Into) -> Result> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.is_int(path) + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isInt", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } pub fn get_boolean( @@ -368,19 +394,39 @@ impl<'mc> MemoryConfiguration<'mc> { path: impl Into, def: std::option::Option, ) -> Result> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.get_boolean(path, def) + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + args.push(val_1); + if let Some(a) = def { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBoolean", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } pub fn is_boolean(&self, path: impl Into) -> Result> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.is_boolean(path) + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isBoolean", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } pub fn get_double( @@ -388,19 +434,39 @@ impl<'mc> MemoryConfiguration<'mc> { path: impl Into, def: std::option::Option, ) -> Result> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.get_double(path, def) + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + args.push(val_1); + if let Some(a) = def { + sig += "D"; + let val_2 = jni::objects::JValueGen::Double(a); + args.push(val_2); + } + sig += ")D"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getDouble", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } pub fn is_double(&self, path: impl Into) -> Result> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.is_double(path) + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isDouble", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } pub fn get_long( @@ -408,38 +474,84 @@ impl<'mc> MemoryConfiguration<'mc> { path: impl Into, def: std::option::Option, ) -> Result> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.get_long(path, def) + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + args.push(val_1); + if let Some(a) = def { + sig += "J"; + let val_2 = jni::objects::JValueGen::Long(a); + args.push(val_2); + } + sig += ")J"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLong", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.j()?) } pub fn is_long(&self, path: impl Into) -> Result> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.is_long(path) + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isLong", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } pub fn is_list(&self, path: impl Into) -> Result> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.is_list(path) + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isList", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } pub fn get_string_list( &self, path: impl Into, ) -> Result, Box> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.get_string_list(path) + let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getStringList", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); + } + Ok(new_vec) } pub fn get_object( @@ -448,11 +560,30 @@ impl<'mc> MemoryConfiguration<'mc> { clazz: jni::objects::JClass<'mc>, def: std::option::Option>, ) -> Result>, Box> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.get_object(path, clazz, def) + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + args.push(val_1); + sig += "Ljava/lang/Class;"; + let val_2 = jni::objects::JValueGen::Object(clazz.into()); + args.push(val_2); + if let Some(a) = def { + sig += "LT;"; + let val_3 = jni::objects::JValueGen::Object(a); + args.push(val_3); + } + sig += ")LT;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getObject", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) } pub fn get_serializable( @@ -461,11 +592,30 @@ impl<'mc> MemoryConfiguration<'mc> { clazz: jni::objects::JClass<'mc>, def: std::option::Option>, ) -> Result>, Box> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.get_serializable(path, clazz, def) + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + args.push(val_1); + sig += "Ljava/lang/Class;"; + let val_2 = jni::objects::JValueGen::Object(clazz.into()); + args.push(val_2); + if let Some(a) = def { + sig += "LT;"; + let val_3 = jni::objects::JValueGen::Object(a); + args.push(val_3); + } + sig += ")LT;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSerializable", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) } pub fn get_vector( @@ -473,19 +623,47 @@ impl<'mc> MemoryConfiguration<'mc> { path: impl Into, def: std::option::Option>>, ) -> Result>, Box> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.get_vector(path, def) + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + args.push(val_1); + if let Some(a) = def { + sig += "Lorg/bukkit/util/Vector;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/util/Vector;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getVector", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::util::Vector::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } pub fn is_vector(&self, path: impl Into) -> Result> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.is_vector(path) + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isVector", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } pub fn get_offline_player( @@ -493,22 +671,50 @@ impl<'mc> MemoryConfiguration<'mc> { path: impl Into, def: std::option::Option>>, ) -> Result>, Box> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.get_offline_player(path, def) + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + args.push(val_1); + if let Some(a) = def { + sig += "Lorg/bukkit/OfflinePlayer;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/OfflinePlayer;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getOfflinePlayer", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::OfflinePlayer::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } pub fn is_offline_player( &self, path: impl Into, ) -> Result> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.is_offline_player(path) + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isOfflinePlayer", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } pub fn get_item_stack( @@ -516,22 +722,50 @@ impl<'mc> MemoryConfiguration<'mc> { path: impl Into, def: std::option::Option>>, ) -> Result>, Box> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.get_item_stack(path, def) + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + args.push(val_1); + if let Some(a) = def { + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/inventory/ItemStack;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemStack", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } pub fn is_item_stack( &self, path: impl Into, ) -> Result> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.is_item_stack(path) + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isItemStack", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } pub fn get_color( @@ -539,19 +773,46 @@ impl<'mc> MemoryConfiguration<'mc> { path: impl Into, def: std::option::Option>>, ) -> Result>, Box> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.get_color(path, def) + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + args.push(val_1); + if let Some(a) = def { + sig += "Lorg/bukkit/Color;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/Color;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getColor", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Color::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } pub fn is_color(&self, path: impl Into) -> Result> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.is_color(path) + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isColor", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } pub fn get_location( @@ -559,19 +820,46 @@ impl<'mc> MemoryConfiguration<'mc> { path: impl Into, def: std::option::Option>>, ) -> Result>, Box> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.get_location(path, def) + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + args.push(val_1); + if let Some(a) = def { + sig += "Lorg/bukkit/Location;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/Location;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLocation", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } pub fn is_location(&self, path: impl Into) -> Result> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.is_location(path) + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isLocation", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } pub fn get_configuration_section( @@ -579,22 +867,43 @@ impl<'mc> MemoryConfiguration<'mc> { path: impl Into, ) -> Result>, Box> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.get_configuration_section(path) + let sig = + String::from("(Ljava/lang/String;)Lorg/bukkit/configuration/ConfigurationSection;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getConfigurationSection", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::configuration::ConfigurationSection::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } pub fn is_configuration_section( &self, path: impl Into, ) -> Result> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.is_configuration_section(path) + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isConfigurationSection", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } /// Creates a relative path to the given {@link ConfigurationSection} from /// the given relative section. @@ -609,7 +918,34 @@ impl<'mc> MemoryConfiguration<'mc> { impl Into>, >, ) -> Result> { - crate::configuration::MemorySection::create_path(jni, section, key, relative_to) + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/configuration/ConfigurationSection;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(section.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(key.into())?, + )); + args.push(val_2); + if let Some(a) = relative_to { + sig += "Lorg/bukkit/configuration/ConfigurationSection;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_3); + } + sig += ")Ljava/lang/String;"; + let cls = jni.find_class("org/bukkit/configuration/MemorySection"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "createPath", sig.as_str(), args); + let res = jni.translate_error(res)?; + Ok(jni + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } pub fn get_comments( @@ -744,11 +1080,16 @@ impl<'mc> MemoryConfiguration<'mc> { #[doc(hidden)] pub fn internal_to_string(&self) -> Result> { - let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::configuration::MemorySection = temp_clone.into(); - real.internal_to_string() + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -756,72 +1097,30 @@ impl<'mc> MemoryConfiguration<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for MemoryConfiguration<'mc> { - fn into(self) -> crate::configuration::Configuration<'mc> { - crate::configuration::Configuration::from_raw(&self.jni_ref(), self.1) - .expect("Error converting MemoryConfiguration into crate::configuration::Configuration") - } -} -impl<'mc> Into> for MemoryConfiguration<'mc> { - fn into(self) -> crate::configuration::MemorySection<'mc> { - crate::configuration::MemorySection::from_raw(&self.jni_ref(), self.1) - .expect("Error converting MemoryConfiguration into crate::configuration::MemorySection") - } -} -#[repr(C)] -pub struct InvalidConfigurationException<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); -impl<'mc> JNIRaw<'mc> for InvalidConfigurationException<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for InvalidConfigurationException<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate InvalidConfigurationException from null object." - ) - .into()); - } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/configuration/InvalidConfigurationException", - )?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a InvalidConfigurationException object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) +impl<'mc> std::string::ToString for MemorySection<'mc> { + fn to_string(&self) -> String { + match &self.internal_to_string() { + Ok(a) => a.clone(), + Err(err) => format!("Error calling MemorySection.toString: {}", err), } } } -impl<'mc> InvalidConfigurationException<'mc> { - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) +impl<'mc> Into> for MemorySection<'mc> { + fn into(self) -> crate::configuration::ConfigurationSection<'mc> { + crate::configuration::ConfigurationSection::from_raw(&self.jni_ref(), self.1).expect( + "Error converting MemorySection into crate::configuration::ConfigurationSection", + ) } } #[repr(C)] -pub struct MemorySection<'mc>( +pub struct MemoryConfiguration<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for MemorySection<'mc> { +impl<'mc> JNIRaw<'mc> for MemoryConfiguration<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -829,137 +1128,98 @@ impl<'mc> JNIRaw<'mc> for MemorySection<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for MemorySection<'mc> { +impl<'mc> JNIInstantiatable<'mc> for MemoryConfiguration<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate MemorySection from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/configuration/MemorySection")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a MemorySection object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> MemorySection<'mc> { - pub fn get_keys( - &self, - deep: bool, - ) -> Result, Box> { - let sig = String::from("(Z)Ljava/util/Set;"); - let val_1 = jni::objects::JValueGen::Bool(deep.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getKeys", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn get_values( - &self, - deep: bool, - ) -> Result, Box> { - let sig = String::from("(Z)Ljava/util/Map;"); - let val_1 = jni::objects::JValueGen::Bool(deep.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getValues", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + return Err( + eyre::eyre!("Tried to instantiate MemoryConfiguration from null object.").into(), + ); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/configuration/MemoryConfiguration")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a MemoryConfiguration object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } +} - pub fn contains( +impl<'mc> MemoryConfiguration<'mc> { + /// Creates an empty {@link MemoryConfiguration} using the specified {@link + /// Configuration} as a source for all default values. + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + defaults: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = defaults { + sig += "Lorg/bukkit/configuration/Configuration;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/configuration/MemoryConfiguration"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::configuration::MemoryConfiguration::from_raw(&jni, res) + } + + pub fn add_defaults( &self, - path: impl Into, - ignore_default: std::option::Option, - ) -> Result> { + defaults: impl Into>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); + sig += "Lorg/bukkit/configuration/Configuration;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(defaults.into().jni_object().clone()) + }); args.push(val_1); - if let Some(a) = ignore_default { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")Z"; + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "contains", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + .call_method(&self.jni_object(), "addDefaults", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - pub fn is_set(&self, path: impl Into) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); + pub fn set_defaults( + &self, + defaults: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/configuration/Configuration;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(defaults.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "isSet", + "setDefaults", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn current_path(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCurrentPath", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + self.jni_ref().translate_error(res)?; + Ok(()) } - pub fn root( + pub fn defaults( &self, ) -> Result>, Box> { let sig = String::from("()Lorg/bukkit/configuration/Configuration;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getRoot", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDefaults", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); @@ -988,6 +1248,27 @@ impl<'mc> MemorySection<'mc> { )?)) } + pub fn options( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/configuration/MemoryConfigurationOptions;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "options", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::configuration::MemoryConfigurationOptions::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the default value of the given path as provided. + /// + /// If no source {@link Configuration} was provided as a default + /// collection, then a new {@link MemoryConfiguration} will be created to + /// hold the new default value. + /// + /// If value is null, the value will be removed from the default + /// Configuration source. pub fn add_default( &self, path: impl Into, @@ -1010,56 +1291,49 @@ impl<'mc> MemorySection<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } + // SUPER CLASS: org.bukkit.configuration.MemorySection ( ['addDefaults', 'setDefaults', 'getDefaults', 'getParent', 'options', 'addDefault']) - pub fn default_section( + pub fn get_keys( &self, - ) -> Result>, Box> - { - let sig = String::from("()Lorg/bukkit/configuration/ConfigurationSection;"); + deep: bool, + ) -> Result, Box> { + let sig = String::from("(Z)Ljava/util/Set;"); + let val_1 = jni::objects::JValueGen::Bool(deep.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getDefaultSection", + "getKeys", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::configuration::ConfigurationSection::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - pub fn set( + pub fn get_values( &self, - path: impl Into, - value: jni::objects::JObject<'mc>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Ljava/lang/Object;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(value); + deep: bool, + ) -> Result, Box> { + let sig = String::from("(Z)Ljava/util/Map;"); + let val_1 = jni::objects::JValueGen::Bool(deep.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "set", + "getValues", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - pub fn get( + pub fn contains( &self, path: impl Into, - def: std::option::Option>, - ) -> Result>, Box> { + ignore_default: std::option::Option, + ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "Ljava/lang/String;"; @@ -1067,20 +1341,86 @@ impl<'mc> MemorySection<'mc> { self.jni_ref().new_string(path.into())?, )); args.push(val_1); - if let Some(a) = def { - sig += "Ljava/lang/Object;"; - let val_2 = jni::objects::JValueGen::Object(a); + if let Some(a) = ignore_default { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); args.push(val_2); } - sig += ")Ljava/lang/Object;"; + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "get", sig.as_str(), args); + .call_method(&self.jni_object(), "contains", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(res.l()?)) + Ok(res.z()?) + } + + pub fn is_set(&self, path: impl Into) -> Result> { + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.is_set(path) + } + + pub fn current_path(&self) -> Result> { + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.current_path() + } + + pub fn name(&self) -> Result> { + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.name() + } + + pub fn root( + &self, + ) -> Result>, Box> { + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.root() + } + + pub fn default_section( + &self, + ) -> Result>, Box> + { + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.default_section() + } + + pub fn set( + &self, + path: impl Into, + value: jni::objects::JObject<'mc>, + ) -> Result<(), Box> { + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.set(path, value) + } + + pub fn get( + &self, + path: impl Into, + def: std::option::Option>, + ) -> Result>, Box> { + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.get(path, def) } pub fn create_section( @@ -1088,28 +1428,11 @@ impl<'mc> MemorySection<'mc> { path: impl Into, map: std::option::Option>>, ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - args.push(val_1); - if let Some(a) = map { - sig += "Ljava/util/Map;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/configuration/ConfigurationSection;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "createSection", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::configuration::ConfigurationSection::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.create_section(path, map) } pub fn get_string( @@ -1117,49 +1440,19 @@ impl<'mc> MemorySection<'mc> { path: impl Into, def: std::option::Option>, ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - args.push(val_1); - if let Some(a) = def { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_2); - } - sig += ")Ljava/lang/String;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getString", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.get_string(path, def) } pub fn is_string(&self, path: impl Into) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isString", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.is_string(path) } pub fn get_int( @@ -1167,39 +1460,19 @@ impl<'mc> MemorySection<'mc> { path: impl Into, def: std::option::Option, ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - args.push(val_1); - if let Some(a) = def { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - sig += ")I"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getInt", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.get_int(path, def) } pub fn is_int(&self, path: impl Into) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isInt", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.is_int(path) } pub fn get_boolean( @@ -1207,39 +1480,19 @@ impl<'mc> MemorySection<'mc> { path: impl Into, def: std::option::Option, ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - args.push(val_1); - if let Some(a) = def { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBoolean", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.get_boolean(path, def) } pub fn is_boolean(&self, path: impl Into) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isBoolean", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.is_boolean(path) } pub fn get_double( @@ -1247,39 +1500,19 @@ impl<'mc> MemorySection<'mc> { path: impl Into, def: std::option::Option, ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - args.push(val_1); - if let Some(a) = def { - sig += "D"; - let val_2 = jni::objects::JValueGen::Double(a); - args.push(val_2); - } - sig += ")D"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getDouble", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.get_double(path, def) } pub fn is_double(&self, path: impl Into) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isDouble", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.is_double(path) } pub fn get_long( @@ -1287,84 +1520,38 @@ impl<'mc> MemorySection<'mc> { path: impl Into, def: std::option::Option, ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - args.push(val_1); - if let Some(a) = def { - sig += "J"; - let val_2 = jni::objects::JValueGen::Long(a); - args.push(val_2); - } - sig += ")J"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getLong", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) - } - - pub fn is_long(&self, path: impl Into) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isLong", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.get_long(path, def) + } + + pub fn is_long(&self, path: impl Into) -> Result> { + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.is_long(path) } pub fn is_list(&self, path: impl Into) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isList", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.is_list(path) } pub fn get_string_list( &self, path: impl Into, ) -> Result, Box> { - let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getStringList", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), - ); - } - Ok(new_vec) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.get_string_list(path) } pub fn get_object( @@ -1373,30 +1560,11 @@ impl<'mc> MemorySection<'mc> { clazz: jni::objects::JClass<'mc>, def: std::option::Option>, ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - args.push(val_1); - sig += "Ljava/lang/Class;"; - let val_2 = jni::objects::JValueGen::Object(clazz.into()); - args.push(val_2); - if let Some(a) = def { - sig += "LT;"; - let val_3 = jni::objects::JValueGen::Object(a); - args.push(val_3); - } - sig += ")LT;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getObject", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(res.l()?)) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.get_object(path, clazz, def) } pub fn get_serializable( @@ -1405,30 +1573,11 @@ impl<'mc> MemorySection<'mc> { clazz: jni::objects::JClass<'mc>, def: std::option::Option>, ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - args.push(val_1); - sig += "Ljava/lang/Class;"; - let val_2 = jni::objects::JValueGen::Object(clazz.into()); - args.push(val_2); - if let Some(a) = def { - sig += "LT;"; - let val_3 = jni::objects::JValueGen::Object(a); - args.push(val_3); - } - sig += ")LT;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSerializable", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(res.l()?)) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.get_serializable(path, clazz, def) } pub fn get_vector( @@ -1436,47 +1585,19 @@ impl<'mc> MemorySection<'mc> { path: impl Into, def: std::option::Option>>, ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - args.push(val_1); - if let Some(a) = def { - sig += "Lorg/bukkit/util/Vector;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/util/Vector;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getVector", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::util::Vector::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.get_vector(path, def) } pub fn is_vector(&self, path: impl Into) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isVector", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.is_vector(path) } pub fn get_offline_player( @@ -1484,50 +1605,22 @@ impl<'mc> MemorySection<'mc> { path: impl Into, def: std::option::Option>>, ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - args.push(val_1); - if let Some(a) = def { - sig += "Lorg/bukkit/OfflinePlayer;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/OfflinePlayer;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getOfflinePlayer", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::OfflinePlayer::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.get_offline_player(path, def) } pub fn is_offline_player( &self, path: impl Into, ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isOfflinePlayer", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.is_offline_player(path) } pub fn get_item_stack( @@ -1535,50 +1628,22 @@ impl<'mc> MemorySection<'mc> { path: impl Into, def: std::option::Option>>, ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - args.push(val_1); - if let Some(a) = def { - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/inventory/ItemStack;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemStack", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - - pub fn is_item_stack( - &self, - path: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isItemStack", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.get_item_stack(path, def) + } + + pub fn is_item_stack( + &self, + path: impl Into, + ) -> Result> { + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.is_item_stack(path) } pub fn get_color( @@ -1586,46 +1651,19 @@ impl<'mc> MemorySection<'mc> { path: impl Into, def: std::option::Option>>, ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - args.push(val_1); - if let Some(a) = def { - sig += "Lorg/bukkit/Color;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/Color;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getColor", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Color::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.get_color(path, def) } pub fn is_color(&self, path: impl Into) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isColor", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.is_color(path) } pub fn get_location( @@ -1633,46 +1671,19 @@ impl<'mc> MemorySection<'mc> { path: impl Into, def: std::option::Option>>, ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - args.push(val_1); - if let Some(a) = def { - sig += "Lorg/bukkit/Location;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/Location;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getLocation", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.get_location(path, def) } pub fn is_location(&self, path: impl Into) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isLocation", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.is_location(path) } pub fn get_configuration_section( @@ -1680,43 +1691,22 @@ impl<'mc> MemorySection<'mc> { path: impl Into, ) -> Result>, Box> { - let sig = - String::from("(Ljava/lang/String;)Lorg/bukkit/configuration/ConfigurationSection;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getConfigurationSection", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::configuration::ConfigurationSection::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.get_configuration_section(path) } pub fn is_configuration_section( &self, path: impl Into, ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isConfigurationSection", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.is_configuration_section(path) } /// Creates a relative path to the given {@link ConfigurationSection} from /// the given relative section. @@ -1731,34 +1721,7 @@ impl<'mc> MemorySection<'mc> { impl Into>, >, ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/configuration/ConfigurationSection;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(section.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(key.into())?, - )); - args.push(val_2); - if let Some(a) = relative_to { - sig += "Lorg/bukkit/configuration/ConfigurationSection;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_3); - } - sig += ")Ljava/lang/String;"; - let cls = jni.find_class("org/bukkit/configuration/MemorySection"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "createPath", sig.as_str(), args); - let res = jni.translate_error(res)?; - Ok(jni - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + crate::configuration::MemorySection::create_path(jni, section, key, relative_to) } pub fn get_comments( @@ -1893,16 +1856,11 @@ impl<'mc> MemorySection<'mc> { #[doc(hidden)] pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + let temp_clone = crate::configuration::MemorySection::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::configuration::MemorySection = temp_clone.into(); + real.internal_to_string() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1910,21 +1868,63 @@ impl<'mc> MemorySection<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for MemoryConfiguration<'mc> { + fn into(self) -> crate::configuration::Configuration<'mc> { + crate::configuration::Configuration::from_raw(&self.jni_ref(), self.1) + .expect("Error converting MemoryConfiguration into crate::configuration::Configuration") + } +} +impl<'mc> Into> for MemoryConfiguration<'mc> { + fn into(self) -> crate::configuration::MemorySection<'mc> { + crate::configuration::MemorySection::from_raw(&self.jni_ref(), self.1) + .expect("Error converting MemoryConfiguration into crate::configuration::MemorySection") + } +} +#[repr(C)] +pub struct InvalidConfigurationException<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); -impl<'mc> std::string::ToString for MemorySection<'mc> { - fn to_string(&self) -> String { - match &self.internal_to_string() { - Ok(a) => a.clone(), - Err(err) => format!("Error calling MemorySection.toString: {}", err), +impl<'mc> JNIRaw<'mc> for InvalidConfigurationException<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for InvalidConfigurationException<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate InvalidConfigurationException from null object." + ) + .into()); + } + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/configuration/InvalidConfigurationException", + )?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a InvalidConfigurationException object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } } } -impl<'mc> Into> for MemorySection<'mc> { - fn into(self) -> crate::configuration::ConfigurationSection<'mc> { - crate::configuration::ConfigurationSection::from_raw(&self.jni_ref(), self.1).expect( - "Error converting MemorySection into crate::configuration::ConfigurationSection", - ) +impl<'mc> InvalidConfigurationException<'mc> { + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } } #[repr(C)] diff --git a/blackboxmc-rs-bukkit/src/configuration/serialization/mod.rs b/blackboxmc-rs-bukkit/src/configuration/serialization/mod.rs index b714f43..47aa7a6 100644 --- a/blackboxmc-rs-bukkit/src/configuration/serialization/mod.rs +++ b/blackboxmc-rs-bukkit/src/configuration/serialization/mod.rs @@ -3,128 +3,6 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] -pub struct ConfigurationSerializable<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for ConfigurationSerializable<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for ConfigurationSerializable<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate ConfigurationSerializable from null object." - ) - .into()); - } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/configuration/serialization/ConfigurationSerializable", - )?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ConfigurationSerializable object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> ConfigurationSerializable<'mc> { - pub fn from_extendable( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - plugin: &'mc crate::plugin::Plugin, - address: i32, - lib_name: String, - name: String, - ) -> Result> { - let obj = unsafe { plugin.new_extendable(address, "ConfigSerializable", name, lib_name) }?; - Self::from_raw(env, obj) - } - /// Creates a Map representation of this class. - /// - /// This class must provide a method to restore this class, as defined in - /// the {@link ConfigurationSerializable} interface javadocs. - pub fn serialize( - &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/Map;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct SerializableAs<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for SerializableAs<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for SerializableAs<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate SerializableAs from null object.").into(), - ); - } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/configuration/serialization/SerializableAs", - )?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a SerializableAs object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> SerializableAs<'mc> { - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] pub struct ConfigurationSerialization<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, @@ -342,6 +220,126 @@ impl<'mc> ConfigurationSerialization<'mc> { } } #[repr(C)] +pub struct ConfigurationSerializable<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ConfigurationSerializable<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for ConfigurationSerializable<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate ConfigurationSerializable from null object." + ) + .into()); + } + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/configuration/serialization/ConfigurationSerializable", + )?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ConfigurationSerializable object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> ConfigurationSerializable<'mc> { + pub fn from_extendable( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + plugin: &'mc crate::plugin::Plugin, + address: i32, + lib_name: String, + name: String, + ) -> Result> { + let obj = unsafe { plugin.new_extendable(address, "ConfigSerializable", name, lib_name) }?; + Self::from_raw(env, obj) + } + /// Creates a Map representation of this class. + /// + /// This class must provide a method to restore this class, as defined in + /// the {@link ConfigurationSerializable} interface javadocs. + pub fn serialize( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Map;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct SerializableAs<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for SerializableAs<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for SerializableAs<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate SerializableAs from null object.").into(), + ); + } + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/configuration/serialization/SerializableAs", + )?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a SerializableAs object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> SerializableAs<'mc> { + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] pub struct DelegateDeserialization<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, diff --git a/blackboxmc-rs-bukkit/src/conversations/mod.rs b/blackboxmc-rs-bukkit/src/conversations/mod.rs index 8d6b259..d2e3c13 100644 --- a/blackboxmc-rs-bukkit/src/conversations/mod.rs +++ b/blackboxmc-rs-bukkit/src/conversations/mod.rs @@ -3,12 +3,12 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] -pub struct BooleanPrompt<'mc>( +pub struct ValidatingPrompt<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BooleanPrompt<'mc> { +impl<'mc> JNIRaw<'mc> for ValidatingPrompt<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -16,18 +16,20 @@ impl<'mc> JNIRaw<'mc> for BooleanPrompt<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BooleanPrompt<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ValidatingPrompt<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate BooleanPrompt from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate ValidatingPrompt from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/conversations/BooleanPrompt")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/conversations/ValidatingPrompt")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BooleanPrompt object, got {}", + "Invalid argument passed. Expected a ValidatingPrompt object, got {}", name ) .into()) @@ -37,18 +39,17 @@ impl<'mc> JNIInstantiatable<'mc> for BooleanPrompt<'mc> { } } -impl<'mc> BooleanPrompt<'mc> { +impl<'mc> ValidatingPrompt<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { + ) -> Result, Box> { let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/conversations/BooleanPrompt"); + let cls = jni.find_class("org/bukkit/conversations/ValidatingPrompt"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), vec![]); let res = jni.translate_error_no_gen(res)?; - crate::conversations::BooleanPrompt::from_raw(&jni, res) + crate::conversations::ValidatingPrompt::from_raw(&jni, res) } - // SUPER CLASS: org.bukkit.conversations.ValidatingPrompt ( []) /// Accepts and processes input from the user and validates it. If /// validation fails, this prompt is returned for re-execution, otherwise /// the next Prompt in the prompt graph is returned. @@ -57,114 +58,52 @@ impl<'mc> BooleanPrompt<'mc> { context: impl Into>, input: impl Into, ) -> Result>, Box> { - let temp_clone = crate::conversations::ValidatingPrompt::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::conversations::ValidatingPrompt = temp_clone.into(); - real.accept_input(context, input) + let sig = String::from("(Lorg/bukkit/conversations/ConversationContext;Ljava/lang/String;)Lorg/bukkit/conversations/Prompt;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(context.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(input.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "acceptInput", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::conversations::Prompt::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } /// Ensures that the prompt waits for the user to provide input. pub fn blocks_for_input( &self, context: impl Into>, ) -> Result> { - let temp_clone = crate::conversations::ValidatingPrompt::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::conversations::ValidatingPrompt = temp_clone.into(); - real.blocks_for_input(context) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for BooleanPrompt<'mc> { - fn into(self) -> crate::conversations::ValidatingPrompt<'mc> { - crate::conversations::ValidatingPrompt::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BooleanPrompt into crate::conversations::ValidatingPrompt") - } -} -#[repr(C)] -pub struct PluginNameConversationPrefix<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PluginNameConversationPrefix<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PluginNameConversationPrefix<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PluginNameConversationPrefix from null object." - ) - .into()); - } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/conversations/PluginNameConversationPrefix", - )?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PluginNameConversationPrefix object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> PluginNameConversationPrefix<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - plugin: impl Into>, - separator: std::option::Option>, - prefix_color: std::option::Option>>, - ) -> Result, Box> - { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/plugin/Plugin;"; + let sig = String::from("(Lorg/bukkit/conversations/ConversationContext;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + jni::objects::JObject::from_raw(context.into().jni_object().clone()) }); - args.push(val_1); - if let Some(a) = separator { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(a.into())?, - )); - args.push(val_2); - } - if let Some(a) = prefix_color { - sig += "Lorg/bukkit/ChatColor;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_3); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/conversations/PluginNameConversationPrefix"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::conversations::PluginNameConversationPrefix::from_raw(&jni, res) + let res = self.jni_ref().call_method( + &self.jni_object(), + "blocksForInput", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Prepends each conversation message with the plugin name. - pub fn get_prefix( + /// Gets the text to display to the user when this prompt is first + /// presented. + pub fn get_prompt_text( &self, context: impl Into>, ) -> Result> { @@ -175,7 +114,7 @@ impl<'mc> PluginNameConversationPrefix<'mc> { }); let res = self.jni_ref().call_method( &self.jni_object(), - "getPrefix", + "getPromptText", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -192,20 +131,19 @@ impl<'mc> PluginNameConversationPrefix<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> - for PluginNameConversationPrefix<'mc> -{ - fn into(self) -> crate::conversations::ConversationPrefix<'mc> { - crate::conversations::ConversationPrefix::from_raw(&self.jni_ref(), self.1).expect("Error converting PluginNameConversationPrefix into crate::conversations::ConversationPrefix") +impl<'mc> Into> for ValidatingPrompt<'mc> { + fn into(self) -> crate::conversations::Prompt<'mc> { + crate::conversations::Prompt::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ValidatingPrompt into crate::conversations::Prompt") } } #[repr(C)] -pub struct PlayerNamePrompt<'mc>( +pub struct NumericPrompt<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerNamePrompt<'mc> { +impl<'mc> JNIRaw<'mc> for NumericPrompt<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -213,20 +151,18 @@ impl<'mc> JNIRaw<'mc> for PlayerNamePrompt<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerNamePrompt<'mc> { +impl<'mc> JNIInstantiatable<'mc> for NumericPrompt<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate PlayerNamePrompt from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate NumericPrompt from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/conversations/PlayerNamePrompt")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/conversations/NumericPrompt")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerNamePrompt object, got {}", + "Invalid argument passed. Expected a NumericPrompt object, got {}", name ) .into()) @@ -236,24 +172,16 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerNamePrompt<'mc> { } } -impl<'mc> PlayerNamePrompt<'mc> { +impl<'mc> NumericPrompt<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - plugin: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/conversations/PlayerNamePrompt"); + ) -> Result, Box> { + let sig = String::from("()V"); + let cls = jni.find_class("org/bukkit/conversations/NumericPrompt"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + let res = jni.new_object(cls, sig.as_str(), vec![]); let res = jni.translate_error_no_gen(res)?; - crate::conversations::PlayerNamePrompt::from_raw(&jni, res) + crate::conversations::NumericPrompt::from_raw(&jni, res) } // SUPER CLASS: org.bukkit.conversations.ValidatingPrompt ( []) /// Accepts and processes input from the user and validates it. If @@ -281,25 +209,37 @@ impl<'mc> PlayerNamePrompt<'mc> { let real: crate::conversations::ValidatingPrompt = temp_clone.into(); real.blocks_for_input(context) } + /// Gets the text to display to the user when this prompt is first + /// presented. + pub fn get_prompt_text( + &self, + context: impl Into>, + ) -> Result> { + let temp_clone = crate::conversations::ValidatingPrompt::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::conversations::ValidatingPrompt = temp_clone.into(); + real.get_prompt_text(context) + } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerNamePrompt<'mc> { +impl<'mc> Into> for NumericPrompt<'mc> { fn into(self) -> crate::conversations::ValidatingPrompt<'mc> { crate::conversations::ValidatingPrompt::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerNamePrompt into crate::conversations::ValidatingPrompt") + .expect("Error converting NumericPrompt into crate::conversations::ValidatingPrompt") } } #[repr(C)] -pub struct StringPrompt<'mc>( +pub struct InactivityConversationCanceller<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for StringPrompt<'mc> { +impl<'mc> JNIRaw<'mc> for InactivityConversationCanceller<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -307,178 +247,60 @@ impl<'mc> JNIRaw<'mc> for StringPrompt<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for StringPrompt<'mc> { +impl<'mc> JNIInstantiatable<'mc> for InactivityConversationCanceller<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate StringPrompt from null object.").into()); + return Err(eyre::eyre!( + "Tried to instantiate InactivityConversationCanceller from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/conversations/StringPrompt")?; + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/conversations/InactivityConversationCanceller", + )?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a StringPrompt object, got {}", - name - ) - .into()) + "Invalid argument passed. Expected a InactivityConversationCanceller object, got {}", + name + ) + .into()) } else { Ok(Self(env.clone(), obj)) } } } -impl<'mc> StringPrompt<'mc> { +impl<'mc> InactivityConversationCanceller<'mc> { + /// Creates an InactivityConversationCanceller. pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/conversations/StringPrompt"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), vec![]); - let res = jni.translate_error_no_gen(res)?; - crate::conversations::StringPrompt::from_raw(&jni, res) - } - /// Ensures that the prompt waits for the user to provide input. - pub fn blocks_for_input( - &self, - context: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/conversations/ConversationContext;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(context.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "blocksForInput", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the text to display to the user when this prompt is first - /// presented. - pub fn get_prompt_text( - &self, - context: impl Into>, - ) -> Result> { - let sig = - String::from("(Lorg/bukkit/conversations/ConversationContext;)Ljava/lang/String;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(context.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPromptText", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Accepts and processes input from the user. Using the input, the next - /// Prompt in the prompt graph is returned. - pub fn accept_input( - &self, - context: impl Into>, - input: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/conversations/ConversationContext;Ljava/lang/String;)Lorg/bukkit/conversations/Prompt;"); + plugin: impl Into>, + timeout_seconds: i32, + ) -> Result< + crate::conversations::InactivityConversationCanceller<'mc>, + Box, + > { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;I)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(context.into().jni_object().clone()) + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(input.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "acceptInput", + let val_2 = jni::objects::JValueGen::Int(timeout_seconds); + let cls = jni.find_class("org/bukkit/conversations/InactivityConversationCanceller"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), ], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::conversations::Prompt::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for StringPrompt<'mc> { - fn into(self) -> crate::conversations::Prompt<'mc> { - crate::conversations::Prompt::from_raw(&self.jni_ref(), self.1) - .expect("Error converting StringPrompt into crate::conversations::Prompt") - } -} -#[repr(C)] -pub struct ManuallyAbandonedConversationCanceller<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for ManuallyAbandonedConversationCanceller<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for ManuallyAbandonedConversationCanceller<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate ManuallyAbandonedConversationCanceller from null object." - ) - .into()); - } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/conversations/ManuallyAbandonedConversationCanceller", - )?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ManuallyAbandonedConversationCanceller object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> ManuallyAbandonedConversationCanceller<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result< - crate::conversations::ManuallyAbandonedConversationCanceller<'mc>, - Box, - > { - let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/conversations/ManuallyAbandonedConversationCanceller"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), vec![]); let res = jni.translate_error_no_gen(res)?; - crate::conversations::ManuallyAbandonedConversationCanceller::from_raw(&jni, res) + crate::conversations::InactivityConversationCanceller::from_raw(&jni, res) } pub fn set_conversation( @@ -544,19 +366,19 @@ impl<'mc> ManuallyAbandonedConversationCanceller<'mc> { } } impl<'mc> Into> - for ManuallyAbandonedConversationCanceller<'mc> + for InactivityConversationCanceller<'mc> { fn into(self) -> crate::conversations::ConversationCanceller<'mc> { - crate::conversations::ConversationCanceller::from_raw(&self.jni_ref(), self.1).expect("Error converting ManuallyAbandonedConversationCanceller into crate::conversations::ConversationCanceller") + crate::conversations::ConversationCanceller::from_raw(&self.jni_ref(), self.1).expect("Error converting InactivityConversationCanceller into crate::conversations::ConversationCanceller") } } #[repr(C)] -pub struct ExactMatchConversationCanceller<'mc>( +pub struct ConversationFactory<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ExactMatchConversationCanceller<'mc> { +impl<'mc> JNIRaw<'mc> for ConversationFactory<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -564,47 +386,41 @@ impl<'mc> JNIRaw<'mc> for ExactMatchConversationCanceller<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ExactMatchConversationCanceller<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ConversationFactory<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate ExactMatchConversationCanceller from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate ConversationFactory from null object.").into(), + ); } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/conversations/ExactMatchConversationCanceller", - )?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/conversations/ConversationFactory")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ExactMatchConversationCanceller object, got {}", - name - ) - .into()) + "Invalid argument passed. Expected a ConversationFactory object, got {}", + name + ) + .into()) } else { Ok(Self(env.clone(), obj)) } } } -impl<'mc> ExactMatchConversationCanceller<'mc> { - /// Builds an ExactMatchConversationCanceller. +impl<'mc> ConversationFactory<'mc> { + /// Constructs a ConversationFactory. pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - escape_sequence: impl Into, - ) -> Result< - crate::conversations::ExactMatchConversationCanceller<'mc>, - Box, - > { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(escape_sequence.into())?, - )); - let cls = jni.find_class("org/bukkit/conversations/ExactMatchConversationCanceller"); + plugin: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/conversations/ConversationFactory"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -612,385 +428,737 @@ impl<'mc> ExactMatchConversationCanceller<'mc> { vec![jni::objects::JValueGen::from(val_1)], ); let res = jni.translate_error_no_gen(res)?; - crate::conversations::ExactMatchConversationCanceller::from_raw(&jni, res) + crate::conversations::ConversationFactory::from_raw(&jni, res) } - - pub fn set_conversation( + /// Sets the modality of all {@link Conversation}s created by this factory. + /// If a conversation is modal, all messages directed to the player are + /// suppressed for the duration of the conversation. + /// + /// The default is True. + pub fn with_modality( &self, - conversation: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/conversations/Conversation;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(conversation.into().jni_object().clone()) - }); + modal: bool, + ) -> Result, Box> { + let sig = String::from("(Z)Lorg/bukkit/conversations/ConversationFactory;"); + let val_1 = jni::objects::JValueGen::Bool(modal.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setConversation", + "withModality", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::conversations::ConversationFactory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - - pub fn cancel_based_on_input( + /// Sets the local echo status for all {@link Conversation}s created by + /// this factory. If local echo is enabled, any text submitted to a + /// conversation gets echoed back into the submitter's chat window. + pub fn with_local_echo( &self, - context: impl Into>, - input: impl Into, - ) -> Result> { - let sig = - String::from("(Lorg/bukkit/conversations/ConversationContext;Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(context.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(input.into())?, - )); + local_echo_enabled: bool, + ) -> Result, Box> { + let sig = String::from("(Z)Lorg/bukkit/conversations/ConversationFactory;"); + let val_1 = jni::objects::JValueGen::Bool(local_echo_enabled.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "cancelBasedOnInput", + "withLocalEcho", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::conversations::ConversationFactory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the {@link ConversationPrefix} that prepends all output from all + /// generated conversations. + /// + /// The default is a {@link NullConversationPrefix}; + pub fn with_prefix( + &self, + prefix: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/conversations/ConversationPrefix;)Lorg/bukkit/conversations/ConversationFactory;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(prefix.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "withPrefix", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::conversations::ConversationFactory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the number of inactive seconds to wait before automatically + /// abandoning all generated conversations. + /// + /// The default is 600 seconds (5 minutes). + pub fn with_timeout( + &self, + timeout_seconds: i32, + ) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/conversations/ConversationFactory;"); + let val_1 = jni::objects::JValueGen::Int(timeout_seconds); + let res = self.jni_ref().call_method( + &self.jni_object(), + "withTimeout", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::conversations::ConversationFactory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the first prompt to use in all generated conversations. + /// + /// The default is Prompt.END_OF_CONVERSATION. + pub fn with_first_prompt( + &self, + first_prompt: impl Into>, + ) -> Result, Box> { + let sig = String::from( + "(Lorg/bukkit/conversations/Prompt;)Lorg/bukkit/conversations/ConversationFactory;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(first_prompt.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "withFirstPrompt", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::conversations::ConversationFactory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets any initial data with which to populate the conversation context + /// sessionData map. + pub fn with_initial_session_data( + &self, + initial_session_data: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Ljava/util/Map;)Lorg/bukkit/conversations/ConversationFactory;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(initial_session_data.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "withInitialSessionData", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::conversations::ConversationFactory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the player input that, when received, will immediately terminate + /// the conversation. + pub fn with_escape_sequence( + &self, + escape_sequence: impl Into, + ) -> Result, Box> { + let sig = + String::from("(Ljava/lang/String;)Lorg/bukkit/conversations/ConversationFactory;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(escape_sequence.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "withEscapeSequence", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::conversations::ConversationFactory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Adds a {@link ConversationCanceller} to constructed conversations. + pub fn with_conversation_canceller( + &self, + canceller: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/conversations/ConversationCanceller;)Lorg/bukkit/conversations/ConversationFactory;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(canceller.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "withConversationCanceller", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::conversations::ConversationFactory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Prevents this factory from creating a conversation for non-player + /// {@link Conversable} objects. + pub fn that_excludes_non_players_with_message( + &self, + player_only_message: impl Into, + ) -> Result, Box> { + let sig = + String::from("(Ljava/lang/String;)Lorg/bukkit/conversations/ConversationFactory;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(player_only_message.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "thatExcludesNonPlayersWithMessage", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::conversations::ConversationFactory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Adds a {@link ConversationAbandonedListener} to all conversations + /// constructed by this factory. + pub fn add_conversation_abandoned_listener( + &self, + listener: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/conversations/ConversationAbandonedListener;)Lorg/bukkit/conversations/ConversationFactory;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(listener.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addConversationAbandonedListener", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::conversations::ConversationFactory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Constructs a {@link Conversation} in accordance with the defaults set + /// for this factory. + pub fn build_conversation( + &self, + for_whom: impl Into>, + ) -> Result, Box> { + let sig = String::from( + "(Lorg/bukkit/conversations/Conversable;)Lorg/bukkit/conversations/Conversation;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(for_whom.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "buildConversation", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::conversations::Conversation::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - pub fn clone( + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct Conversation<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Conversation<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Conversation<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Conversation from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/conversations/Conversation")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Conversation object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Conversation<'mc> { + /// Initializes a new Conversation. + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + plugin: impl Into>, + for_whom: impl Into>, + first_prompt: impl Into>, + initial_session_data: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/plugin/Plugin;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Lorg/bukkit/conversations/Conversable;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(for_whom.into().jni_object().clone()) + }); + args.push(val_2); + sig += "Lorg/bukkit/conversations/Prompt;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(first_prompt.into().jni_object().clone()) + }); + args.push(val_3); + if let Some(a) = initial_session_data { + sig += "Ljava/util/Map;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_4); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/conversations/Conversation"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::conversations::Conversation::from_raw(&jni, res) + } + /// Gets the entity for whom this conversation is mediating. + pub fn for_whom( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/conversations/Conversable;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getForWhom", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::conversations::Conversable::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the modality of this conversation. If a conversation is modal, all + /// messages directed to the player are suppressed for the duration of the + /// conversation. + pub fn is_modal(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isModal", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the status of local echo for this conversation. If local echo is + /// enabled, any text submitted to a conversation gets echoed back into the + /// submitter's chat window. + pub fn is_local_echo_enabled(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isLocalEchoEnabled", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the status of local echo for this conversation. If local echo is + /// enabled, any text submitted to a conversation gets echoed back into the + /// submitter's chat window. + pub fn set_local_echo_enabled( + &self, + local_echo_enabled: bool, + ) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(local_echo_enabled.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLocalEchoEnabled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the {@link ConversationPrefix} that prepends all output from this + /// conversation. + pub fn prefix( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/conversations/ConversationCanceller;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/conversations/ConversationPrefix;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPrefix", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::conversations::ConversationCanceller::from_raw(&self.jni_ref(), unsafe { + crate::conversations::ConversationPrefix::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> - for ExactMatchConversationCanceller<'mc> -{ - fn into(self) -> crate::conversations::ConversationCanceller<'mc> { - crate::conversations::ConversationCanceller::from_raw(&self.jni_ref(), self.1).expect("Error converting ExactMatchConversationCanceller into crate::conversations::ConversationCanceller") - } -} -#[repr(C)] -pub struct Conversable<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Conversable<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Conversable<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Conversable from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/conversations/Conversable")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Conversable object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + /// Gets the list of {@link ConversationCanceller}s + pub fn cancellers( + &self, + ) -> Result>, Box> + { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCancellers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::conversations::ConversationCanceller::from_raw( + &self.0, obj, + )?); } + Ok(new_vec) } -} - -impl<'mc> Conversable<'mc> { - /// Tests to see of a Conversable object is actively engaged in a - /// conversation. - pub fn is_conversing(&self) -> Result> { - let sig = String::from("()Z"); + /// Returns the Conversation's {@link ConversationContext}. + pub fn context( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/conversations/ConversationContext;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isConversing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getContext", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::conversations::ConversationContext::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Accepts input into the active conversation. If no conversation is in - /// progress, this method does nothing. - pub fn accept_conversation_input( + /// Displays the first prompt of this conversation and begins redirecting + /// the user's chat responses. + pub fn begin(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "begin", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns Returns the current state of the conversation. + pub fn state( &self, - input: impl Into, - ) -> Result<(), Box> { + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/conversations/Conversation/ConversationState;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getState", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::conversations::ConversationConversationState::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Passes player input into the current prompt. The next prompt (as + /// determined by the current prompt) is then displayed to the user. + pub fn accept_input(&self, input: impl Into) -> Result<(), Box> { let sig = String::from("(Ljava/lang/String;)V"); let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( self.jni_ref().new_string(input.into())?, )); let res = self.jni_ref().call_method( &self.jni_object(), - "acceptConversationInput", + "acceptInput", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Enters into a dialog with a Conversation object. - pub fn begin_conversation( + /// Adds a {@link ConversationAbandonedListener}. + pub fn add_conversation_abandoned_listener( &self, - conversation: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/conversations/Conversation;)Z"); + listener: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/conversations/ConversationAbandonedListener;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(conversation.into().jni_object().clone()) + jni::objects::JObject::from_raw(listener.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "beginConversation", + "addConversationAbandonedListener", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Abandons an active conversation. - pub fn abandon_conversation( + /// Removes a {@link ConversationAbandonedListener}. + pub fn remove_conversation_abandoned_listener( + &self, + listener: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/conversations/ConversationAbandonedListener;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(listener.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeConversationAbandonedListener", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Abandons and resets the current conversation. Restores the user's + /// normal chat behavior. + pub fn abandon( &self, - conversation: impl Into>, details: std::option::Option< impl Into>, >, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/conversations/Conversation;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(conversation.into().jni_object().clone()) - }); - args.push(val_1); if let Some(a) = details { sig += "Lorg/bukkit/conversations/ConversationAbandonedEvent;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { + let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); - args.push(val_2); + args.push(val_1); } sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "abandon", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Displays the next user prompt and abandons the conversation if the next + /// prompt is null. + pub fn output_next_prompt(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref().call_method( &self.jni_object(), - "abandonConversation", + "outputNextPrompt", sig.as_str(), - args, + vec![], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sends this sender a message raw - pub fn send_raw_message( - &self, - sender: impl Into>, - message: std::option::Option>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = message { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_2); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +pub enum ConversationConversationState<'mc> { + Unstarted { + inner: ConversationConversationStateStruct<'mc>, + }, + Started { + inner: ConversationConversationStateStruct<'mc>, + }, + Abandoned { + inner: ConversationConversationStateStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for ConversationConversationState<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ConversationConversationState::Unstarted { .. } => f.write_str("UNSTARTED"), + ConversationConversationState::Started { .. } => f.write_str("STARTED"), + ConversationConversationState::Abandoned { .. } => f.write_str("ABANDONED"), } - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "sendRawMessage", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) } +} +impl<'mc> std::ops::Deref for ConversationConversationState<'mc> { + type Target = ConversationConversationStateStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + ConversationConversationState::Unstarted { inner } => inner, + ConversationConversationState::Started { inner } => inner, + ConversationConversationState::Abandoned { inner } => inner, + } + } +} + +impl<'mc> ConversationConversationState<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/conversations/Conversation/ConversationState"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/conversations/Conversation/ConversationState;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "UNSTARTED" => Ok(ConversationConversationState::Unstarted { + inner: ConversationConversationStateStruct::from_raw(env, obj)?, + }), + "STARTED" => Ok(ConversationConversationState::Started { + inner: ConversationConversationStateStruct::from_raw(env, obj)?, + }), + "ABANDONED" => Ok(ConversationConversationState::Abandoned { + inner: ConversationConversationStateStruct::from_raw(env, obj)?, + }), - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } + #[repr(C)] -pub struct ConversationContext<'mc>( +pub struct ConversationConversationStateStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ConversationContext<'mc> { +impl<'mc> JNIRaw<'mc> for ConversationConversationState<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + match self { + Self::Unstarted { inner } => inner.0.clone(), + Self::Started { inner } => inner.0.clone(), + Self::Abandoned { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + match self { + Self::Unstarted { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Started { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Abandoned { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } -impl<'mc> JNIInstantiatable<'mc> for ConversationContext<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ConversationConversationState<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate ConversationContext from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate ConversationConversationState from null object." + ) + .into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/conversations/ConversationContext")?; + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/conversations/Conversation/ConversationState", + )?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ConversationContext object, got {}", + "Invalid argument passed. Expected a ConversationConversationState object, got {}", name ) .into()) } else { - Ok(Self(env.clone(), obj)) + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "UNSTARTED" => Ok(ConversationConversationState::Unstarted { + inner: ConversationConversationStateStruct::from_raw(env, obj)?, + }), + "STARTED" => Ok(ConversationConversationState::Started { + inner: ConversationConversationStateStruct::from_raw(env, obj)?, + }), + "ABANDONED" => Ok(ConversationConversationState::Abandoned { + inner: ConversationConversationStateStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } } -impl<'mc> ConversationContext<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - plugin: impl Into>, - for_whom: impl Into>, - initial_session_data: impl Into>, - ) -> Result, Box> { - let sig = String::from( - "(Lorg/bukkit/plugin/Plugin;Lorg/bukkit/conversations/Conversable;Ljava/util/Map;)V", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(for_whom.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(initial_session_data.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/conversations/ConversationContext"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = jni.translate_error_no_gen(res)?; - crate::conversations::ConversationContext::from_raw(&jni, res) - } - /// Gets the plugin that owns this conversation. - pub fn plugin(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/plugin/Plugin;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPlugin", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::plugin::Plugin::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Gets the subject of the conversation. - pub fn for_whom( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/conversations/Conversable;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getForWhom", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::conversations::Conversable::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +impl<'mc> JNIRaw<'mc> for ConversationConversationStateStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Gets the underlying sessionData map. - /// May be directly modified to manipulate session data. - pub fn all_session_data( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAllSessionData", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Gets session data shared between all {@link Prompt} invocations. Use - /// this as a way to pass data through each Prompt as the conversation - /// develops. - pub fn get_session_data( - &self, - key: jni::objects::JObject<'mc>, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/Object;)Ljava/lang/Object;"); - let val_1 = jni::objects::JValueGen::Object(key); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSessionData", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); +} +impl<'mc> JNIInstantiatable<'mc> for ConversationConversationStateStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate ConversationConversationStateStruct from null object." + ) + .into()); + } + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/conversations/Conversation/ConversationState", + )?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ConversationConversationStateStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - Ok(Some(res.l()?)) } - /// Sets session data shared between all {@link Prompt} invocations. Use - /// this as a way to pass data through each prompt as the conversation - /// develops. - pub fn set_session_data( - &self, - key: jni::objects::JObject<'mc>, - value: jni::objects::JObject<'mc>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/Object;Ljava/lang/Object;)V"); - let val_1 = jni::objects::JValueGen::Object(key); - let val_2 = jni::objects::JValueGen::Object(value); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSessionData", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +} + +impl<'mc> ConversationConversationStateStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/conversations/Conversation/ConversationState;"); + let cls = jni.find_class("org/bukkit/conversations/Conversation/ConversationState"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::conversations::ConversationConversationState::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -999,12 +1167,12 @@ impl<'mc> ConversationContext<'mc> { } } #[repr(C)] -pub struct RegexPrompt<'mc>( +pub struct BooleanPrompt<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for RegexPrompt<'mc> { +impl<'mc> JNIRaw<'mc> for BooleanPrompt<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1012,18 +1180,18 @@ impl<'mc> JNIRaw<'mc> for RegexPrompt<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for RegexPrompt<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BooleanPrompt<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate RegexPrompt from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate BooleanPrompt from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/conversations/RegexPrompt")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/conversations/BooleanPrompt")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a RegexPrompt object, got {}", + "Invalid argument passed. Expected a BooleanPrompt object, got {}", name ) .into()) @@ -1033,24 +1201,16 @@ impl<'mc> JNIInstantiatable<'mc> for RegexPrompt<'mc> { } } -impl<'mc> RegexPrompt<'mc> { +impl<'mc> BooleanPrompt<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - pattern: impl Into>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/util/regex/Pattern;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(pattern.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")V"; - let cls = jni.find_class("org/bukkit/conversations/RegexPrompt"); + ) -> Result, Box> { + let sig = String::from("()V"); + let cls = jni.find_class("org/bukkit/conversations/BooleanPrompt"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.new_object(cls, sig.as_str(), vec![]); let res = jni.translate_error_no_gen(res)?; - crate::conversations::RegexPrompt::from_raw(&jni, res) + crate::conversations::BooleanPrompt::from_raw(&jni, res) } // SUPER CLASS: org.bukkit.conversations.ValidatingPrompt ( []) /// Accepts and processes input from the user and validates it. If @@ -1078,25 +1238,37 @@ impl<'mc> RegexPrompt<'mc> { let real: crate::conversations::ValidatingPrompt = temp_clone.into(); real.blocks_for_input(context) } + /// Gets the text to display to the user when this prompt is first + /// presented. + pub fn get_prompt_text( + &self, + context: impl Into>, + ) -> Result> { + let temp_clone = crate::conversations::ValidatingPrompt::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::conversations::ValidatingPrompt = temp_clone.into(); + real.get_prompt_text(context) + } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for RegexPrompt<'mc> { +impl<'mc> Into> for BooleanPrompt<'mc> { fn into(self) -> crate::conversations::ValidatingPrompt<'mc> { crate::conversations::ValidatingPrompt::from_raw(&self.jni_ref(), self.1) - .expect("Error converting RegexPrompt into crate::conversations::ValidatingPrompt") + .expect("Error converting BooleanPrompt into crate::conversations::ValidatingPrompt") } } #[repr(C)] -pub struct Prompt<'mc>( +pub struct PluginNameConversationPrefix<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Prompt<'mc> { +impl<'mc> JNIRaw<'mc> for PluginNameConversationPrefix<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1104,18 +1276,24 @@ impl<'mc> JNIRaw<'mc> for Prompt<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Prompt<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PluginNameConversationPrefix<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Prompt from null object.").into()); + return Err(eyre::eyre!( + "Tried to instantiate PluginNameConversationPrefix from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/conversations/Prompt")?; + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/conversations/PluginNameConversationPrefix", + )?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Prompt object, got {}", + "Invalid argument passed. Expected a PluginNameConversationPrefix object, got {}", name ) .into()) @@ -1125,20 +1303,44 @@ impl<'mc> JNIInstantiatable<'mc> for Prompt<'mc> { } } -impl<'mc> Prompt<'mc> { - pub fn from_extendable( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - plugin: &'mc crate::plugin::Plugin, - address: i32, - lib_name: String, - name: String, - ) -> Result> { - let obj = unsafe { plugin.new_extendable(address, "Prompt", name, lib_name) }?; - Self::from_raw(env, obj) +impl<'mc> PluginNameConversationPrefix<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + plugin: impl Into>, + separator: std::option::Option>, + prefix_color: std::option::Option>>, + ) -> Result, Box> + { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/plugin/Plugin;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = separator { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(a.into())?, + )); + args.push(val_2); + } + if let Some(a) = prefix_color { + sig += "Lorg/bukkit/ChatColor;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_3); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/conversations/PluginNameConversationPrefix"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::conversations::PluginNameConversationPrefix::from_raw(&jni, res) } - /// Gets the text to display to the user when this prompt is first - /// presented. - pub fn get_prompt_text( + /// Prepends each conversation message with the plugin name. + pub fn get_prefix( &self, context: impl Into>, ) -> Result> { @@ -1149,7 +1351,7 @@ impl<'mc> Prompt<'mc> { }); let res = self.jni_ref().call_method( &self.jni_object(), - "getPromptText", + "getPrefix", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -1160,70 +1362,26 @@ impl<'mc> Prompt<'mc> { .to_string_lossy() .to_string()) } - /// Checks to see if this prompt implementation should wait for user input - /// or immediately display the next prompt. - pub fn blocks_for_input( - &self, - context: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/conversations/ConversationContext;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(context.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "blocksForInput", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Accepts and processes input from the user. Using the input, the next - /// Prompt in the prompt graph is returned. - pub fn accept_input( - &self, - context: impl Into>, - input: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/conversations/ConversationContext;Ljava/lang/String;)Lorg/bukkit/conversations/Prompt;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(context.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(input.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "acceptInput", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::conversations::Prompt::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> + for PluginNameConversationPrefix<'mc> +{ + fn into(self) -> crate::conversations::ConversationPrefix<'mc> { + crate::conversations::ConversationPrefix::from_raw(&self.jni_ref(), self.1).expect("Error converting PluginNameConversationPrefix into crate::conversations::ConversationPrefix") + } +} #[repr(C)] -pub struct ConversationFactory<'mc>( +pub struct PlayerNamePrompt<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ConversationFactory<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerNamePrompt<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1231,21 +1389,20 @@ impl<'mc> JNIRaw<'mc> for ConversationFactory<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ConversationFactory<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerNamePrompt<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate ConversationFactory from null object.").into(), + eyre::eyre!("Tried to instantiate PlayerNamePrompt from null object.").into(), ); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/conversations/ConversationFactory")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/conversations/PlayerNamePrompt")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ConversationFactory object, got {}", + "Invalid argument passed. Expected a PlayerNamePrompt object, got {}", name ) .into()) @@ -1253,266 +1410,196 @@ impl<'mc> JNIInstantiatable<'mc> for ConversationFactory<'mc> { Ok(Self(env.clone(), obj)) } } -} - -impl<'mc> ConversationFactory<'mc> { - /// Constructs a ConversationFactory. - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - plugin: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/conversations/ConversationFactory"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error_no_gen(res)?; - crate::conversations::ConversationFactory::from_raw(&jni, res) - } - /// Sets the modality of all {@link Conversation}s created by this factory. - /// If a conversation is modal, all messages directed to the player are - /// suppressed for the duration of the conversation. - /// - /// The default is True. - pub fn with_modality( - &self, - modal: bool, - ) -> Result, Box> { - let sig = String::from("(Z)Lorg/bukkit/conversations/ConversationFactory;"); - let val_1 = jni::objects::JValueGen::Bool(modal.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "withModality", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::conversations::ConversationFactory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the local echo status for all {@link Conversation}s created by - /// this factory. If local echo is enabled, any text submitted to a - /// conversation gets echoed back into the submitter's chat window. - pub fn with_local_echo( - &self, - local_echo_enabled: bool, - ) -> Result, Box> { - let sig = String::from("(Z)Lorg/bukkit/conversations/ConversationFactory;"); - let val_1 = jni::objects::JValueGen::Bool(local_echo_enabled.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "withLocalEcho", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::conversations::ConversationFactory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the {@link ConversationPrefix} that prepends all output from all - /// generated conversations. - /// - /// The default is a {@link NullConversationPrefix}; - pub fn with_prefix( - &self, - prefix: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/conversations/ConversationPrefix;)Lorg/bukkit/conversations/ConversationFactory;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(prefix.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "withPrefix", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::conversations::ConversationFactory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the number of inactive seconds to wait before automatically - /// abandoning all generated conversations. - /// - /// The default is 600 seconds (5 minutes). - pub fn with_timeout( - &self, - timeout_seconds: i32, - ) -> Result, Box> { - let sig = String::from("(I)Lorg/bukkit/conversations/ConversationFactory;"); - let val_1 = jni::objects::JValueGen::Int(timeout_seconds); - let res = self.jni_ref().call_method( - &self.jni_object(), - "withTimeout", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::conversations::ConversationFactory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the first prompt to use in all generated conversations. - /// - /// The default is Prompt.END_OF_CONVERSATION. - pub fn with_first_prompt( - &self, - first_prompt: impl Into>, - ) -> Result, Box> { - let sig = String::from( - "(Lorg/bukkit/conversations/Prompt;)Lorg/bukkit/conversations/ConversationFactory;", - ); +} + +impl<'mc> PlayerNamePrompt<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + plugin: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(first_prompt.into().jni_object().clone()) + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "withFirstPrompt", + let cls = jni.find_class("org/bukkit/conversations/PlayerNamePrompt"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::conversations::ConversationFactory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let res = jni.translate_error_no_gen(res)?; + crate::conversations::PlayerNamePrompt::from_raw(&jni, res) } - /// Sets any initial data with which to populate the conversation context - /// sessionData map. - pub fn with_initial_session_data( + // SUPER CLASS: org.bukkit.conversations.ValidatingPrompt ( []) + /// Accepts and processes input from the user and validates it. If + /// validation fails, this prompt is returned for re-execution, otherwise + /// the next Prompt in the prompt graph is returned. + pub fn accept_input( &self, - initial_session_data: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Ljava/util/Map;)Lorg/bukkit/conversations/ConversationFactory;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(initial_session_data.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "withInitialSessionData", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::conversations::ConversationFactory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + context: impl Into>, + input: impl Into, + ) -> Result>, Box> { + let temp_clone = crate::conversations::ValidatingPrompt::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::conversations::ValidatingPrompt = temp_clone.into(); + real.accept_input(context, input) } - /// Sets the player input that, when received, will immediately terminate - /// the conversation. - pub fn with_escape_sequence( + /// Ensures that the prompt waits for the user to provide input. + pub fn blocks_for_input( &self, - escape_sequence: impl Into, - ) -> Result, Box> { - let sig = - String::from("(Ljava/lang/String;)Lorg/bukkit/conversations/ConversationFactory;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(escape_sequence.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "withEscapeSequence", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::conversations::ConversationFactory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + context: impl Into>, + ) -> Result> { + let temp_clone = crate::conversations::ValidatingPrompt::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::conversations::ValidatingPrompt = temp_clone.into(); + real.blocks_for_input(context) } - /// Adds a {@link ConversationCanceller} to constructed conversations. - pub fn with_conversation_canceller( + /// Gets the text to display to the user when this prompt is first + /// presented. + pub fn get_prompt_text( &self, - canceller: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/conversations/ConversationCanceller;)Lorg/bukkit/conversations/ConversationFactory;"); + context: impl Into>, + ) -> Result> { + let temp_clone = crate::conversations::ValidatingPrompt::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::conversations::ValidatingPrompt = temp_clone.into(); + real.get_prompt_text(context) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for PlayerNamePrompt<'mc> { + fn into(self) -> crate::conversations::ValidatingPrompt<'mc> { + crate::conversations::ValidatingPrompt::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerNamePrompt into crate::conversations::ValidatingPrompt") + } +} +#[repr(C)] +pub struct StringPrompt<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for StringPrompt<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for StringPrompt<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate StringPrompt from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/conversations/StringPrompt")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a StringPrompt object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> StringPrompt<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()V"); + let cls = jni.find_class("org/bukkit/conversations/StringPrompt"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), vec![]); + let res = jni.translate_error_no_gen(res)?; + crate::conversations::StringPrompt::from_raw(&jni, res) + } + /// Ensures that the prompt waits for the user to provide input. + pub fn blocks_for_input( + &self, + context: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/conversations/ConversationContext;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(canceller.into().jni_object().clone()) + jni::objects::JObject::from_raw(context.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "withConversationCanceller", + "blocksForInput", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::conversations::ConversationFactory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Prevents this factory from creating a conversation for non-player - /// {@link Conversable} objects. - pub fn that_excludes_non_players_with_message( + /// Gets the text to display to the user when this prompt is first + /// presented. + pub fn get_prompt_text( &self, - player_only_message: impl Into, - ) -> Result, Box> { + context: impl Into>, + ) -> Result> { let sig = - String::from("(Ljava/lang/String;)Lorg/bukkit/conversations/ConversationFactory;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(player_only_message.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "thatExcludesNonPlayersWithMessage", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::conversations::ConversationFactory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Adds a {@link ConversationAbandonedListener} to all conversations - /// constructed by this factory. - pub fn add_conversation_abandoned_listener( - &self, - listener: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/conversations/ConversationAbandonedListener;)Lorg/bukkit/conversations/ConversationFactory;"); + String::from("(Lorg/bukkit/conversations/ConversationContext;)Ljava/lang/String;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(listener.into().jni_object().clone()) + jni::objects::JObject::from_raw(context.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "addConversationAbandonedListener", + "getPromptText", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::conversations::ConversationFactory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Constructs a {@link Conversation} in accordance with the defaults set - /// for this factory. - pub fn build_conversation( + /// Accepts and processes input from the user. Using the input, the next + /// Prompt in the prompt graph is returned. + pub fn accept_input( &self, - for_whom: impl Into>, - ) -> Result, Box> { - let sig = String::from( - "(Lorg/bukkit/conversations/Conversable;)Lorg/bukkit/conversations/Conversation;", - ); + context: impl Into>, + input: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/conversations/ConversationContext;Ljava/lang/String;)Lorg/bukkit/conversations/Prompt;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(for_whom.into().jni_object().clone()) + jni::objects::JObject::from_raw(context.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(input.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "buildConversation", + "acceptInput", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; - crate::conversations::Conversation::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::conversations::Prompt::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1520,13 +1607,19 @@ impl<'mc> ConversationFactory<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for StringPrompt<'mc> { + fn into(self) -> crate::conversations::Prompt<'mc> { + crate::conversations::Prompt::from_raw(&self.jni_ref(), self.1) + .expect("Error converting StringPrompt into crate::conversations::Prompt") + } +} #[repr(C)] -pub struct ConversationCanceller<'mc>( +pub struct ManuallyAbandonedConversationCanceller<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ConversationCanceller<'mc> { +impl<'mc> JNIRaw<'mc> for ManuallyAbandonedConversationCanceller<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1534,44 +1627,48 @@ impl<'mc> JNIRaw<'mc> for ConversationCanceller<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ConversationCanceller<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ManuallyAbandonedConversationCanceller<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate ConversationCanceller from null object." + "Tried to instantiate ManuallyAbandonedConversationCanceller from null object." ) .into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/conversations/ConversationCanceller")?; + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/conversations/ManuallyAbandonedConversationCanceller", + )?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ConversationCanceller object, got {}", - name - ) - .into()) + "Invalid argument passed. Expected a ManuallyAbandonedConversationCanceller object, got {}", + name + ) + .into()) } else { Ok(Self(env.clone(), obj)) } } } -impl<'mc> ConversationCanceller<'mc> { - pub fn from_extendable( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - plugin: &'mc crate::plugin::Plugin, - address: i32, - lib_name: String, - name: String, - ) -> Result> { - let obj = - unsafe { plugin.new_extendable(address, "ConversationCanceller", name, lib_name) }?; - Self::from_raw(env, obj) +impl<'mc> ManuallyAbandonedConversationCanceller<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result< + crate::conversations::ManuallyAbandonedConversationCanceller<'mc>, + Box, + > { + let sig = String::from("()V"); + let cls = jni.find_class("org/bukkit/conversations/ManuallyAbandonedConversationCanceller"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), vec![]); + let res = jni.translate_error_no_gen(res)?; + crate::conversations::ManuallyAbandonedConversationCanceller::from_raw(&jni, res) } - /// Sets the conversation this ConversationCanceller can optionally cancel. + pub fn set_conversation( &self, conversation: impl Into>, @@ -1589,7 +1686,7 @@ impl<'mc> ConversationCanceller<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Cancels a conversation based on user input. + pub fn cancel_based_on_input( &self, context: impl Into>, @@ -1615,10 +1712,7 @@ impl<'mc> ConversationCanceller<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Allows the {@link ConversationFactory} to duplicate this - /// ConversationCanceller when creating a new {@link Conversation}. - /// - /// Implementing this method should reset any internal object state. + pub fn clone( &self, ) -> Result, Box> { @@ -1637,13 +1731,20 @@ impl<'mc> ConversationCanceller<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> + for ManuallyAbandonedConversationCanceller<'mc> +{ + fn into(self) -> crate::conversations::ConversationCanceller<'mc> { + crate::conversations::ConversationCanceller::from_raw(&self.jni_ref(), self.1).expect("Error converting ManuallyAbandonedConversationCanceller into crate::conversations::ConversationCanceller") + } +} #[repr(C)] -pub struct InactivityConversationCanceller<'mc>( +pub struct ExactMatchConversationCanceller<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for InactivityConversationCanceller<'mc> { +impl<'mc> JNIRaw<'mc> for ExactMatchConversationCanceller<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1651,24 +1752,24 @@ impl<'mc> JNIRaw<'mc> for InactivityConversationCanceller<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for InactivityConversationCanceller<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ExactMatchConversationCanceller<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate InactivityConversationCanceller from null object." + "Tried to instantiate ExactMatchConversationCanceller from null object." ) .into()); } let (valid, name) = env.validate_name( &obj, - "org/bukkit/conversations/InactivityConversationCanceller", + "org/bukkit/conversations/ExactMatchConversationCanceller", )?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a InactivityConversationCanceller object, got {}", + "Invalid argument passed. Expected a ExactMatchConversationCanceller object, got {}", name ) .into()) @@ -1678,33 +1779,28 @@ impl<'mc> JNIInstantiatable<'mc> for InactivityConversationCanceller<'mc> { } } -impl<'mc> InactivityConversationCanceller<'mc> { - /// Creates an InactivityConversationCanceller. +impl<'mc> ExactMatchConversationCanceller<'mc> { + /// Builds an ExactMatchConversationCanceller. pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - plugin: impl Into>, - timeout_seconds: i32, + escape_sequence: impl Into, ) -> Result< - crate::conversations::InactivityConversationCanceller<'mc>, + crate::conversations::ExactMatchConversationCanceller<'mc>, Box, > { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;I)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(timeout_seconds); - let cls = jni.find_class("org/bukkit/conversations/InactivityConversationCanceller"); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(escape_sequence.into())?, + )); + let cls = jni.find_class("org/bukkit/conversations/ExactMatchConversationCanceller"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = jni.translate_error_no_gen(res)?; - crate::conversations::InactivityConversationCanceller::from_raw(&jni, res) + crate::conversations::ExactMatchConversationCanceller::from_raw(&jni, res) } pub fn set_conversation( @@ -1769,20 +1865,168 @@ impl<'mc> InactivityConversationCanceller<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> - for InactivityConversationCanceller<'mc> -{ - fn into(self) -> crate::conversations::ConversationCanceller<'mc> { - crate::conversations::ConversationCanceller::from_raw(&self.jni_ref(), self.1).expect("Error converting InactivityConversationCanceller into crate::conversations::ConversationCanceller") - } -} +impl<'mc> Into> + for ExactMatchConversationCanceller<'mc> +{ + fn into(self) -> crate::conversations::ConversationCanceller<'mc> { + crate::conversations::ConversationCanceller::from_raw(&self.jni_ref(), self.1).expect("Error converting ExactMatchConversationCanceller into crate::conversations::ConversationCanceller") + } +} +#[repr(C)] +pub struct Conversable<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Conversable<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Conversable<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Conversable from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/conversations/Conversable")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Conversable object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Conversable<'mc> { + /// Tests to see of a Conversable object is actively engaged in a + /// conversation. + pub fn is_conversing(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isConversing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Accepts input into the active conversation. If no conversation is in + /// progress, this method does nothing. + pub fn accept_conversation_input( + &self, + input: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(input.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "acceptConversationInput", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Enters into a dialog with a Conversation object. + pub fn begin_conversation( + &self, + conversation: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/conversations/Conversation;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(conversation.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "beginConversation", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Abandons an active conversation. + pub fn abandon_conversation( + &self, + conversation: impl Into>, + details: std::option::Option< + impl Into>, + >, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/conversations/Conversation;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(conversation.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = details { + sig += "Lorg/bukkit/conversations/ConversationAbandonedEvent;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "abandonConversation", + sig.as_str(), + args, + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sends this sender a message raw + pub fn send_raw_message( + &self, + sender: impl Into>, + message: std::option::Option>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/util/UUID;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = message { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_2); + } + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "sendRawMessage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} #[repr(C)] -pub struct FixedSetPrompt<'mc>( +pub struct ConversationContext<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for FixedSetPrompt<'mc> { +impl<'mc> JNIRaw<'mc> for ConversationContext<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1790,20 +2034,21 @@ impl<'mc> JNIRaw<'mc> for FixedSetPrompt<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for FixedSetPrompt<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ConversationContext<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate FixedSetPrompt from null object.").into(), + eyre::eyre!("Tried to instantiate ConversationContext from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/conversations/FixedSetPrompt")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/conversations/ConversationContext")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a FixedSetPrompt object, got {}", + "Invalid argument passed. Expected a ConversationContext object, got {}", name ) .into()) @@ -1813,53 +2058,127 @@ impl<'mc> JNIInstantiatable<'mc> for FixedSetPrompt<'mc> { } } -impl<'mc> FixedSetPrompt<'mc> { - /// Creates a FixedSetPrompt from a set of strings. - /// - /// foo = new FixedSetPrompt("bar", "cheese", "panda"); +impl<'mc> ConversationContext<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - fixed_set: impl Into, - ) -> Result, Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(fixed_set.into())?, - )); - let cls = jni.find_class("org/bukkit/conversations/FixedSetPrompt"); + plugin: impl Into>, + for_whom: impl Into>, + initial_session_data: impl Into>, + ) -> Result, Box> { + let sig = String::from( + "(Lorg/bukkit/plugin/Plugin;Lorg/bukkit/conversations/Conversable;Ljava/util/Map;)V", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(for_whom.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(initial_session_data.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/conversations/ConversationContext"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); let res = jni.translate_error_no_gen(res)?; - crate::conversations::FixedSetPrompt::from_raw(&jni, res) + crate::conversations::ConversationContext::from_raw(&jni, res) } - // SUPER CLASS: org.bukkit.conversations.ValidatingPrompt ( []) - /// Accepts and processes input from the user and validates it. If - /// validation fails, this prompt is returned for re-execution, otherwise - /// the next Prompt in the prompt graph is returned. - pub fn accept_input( + /// Gets the plugin that owns this conversation. + pub fn plugin(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/plugin/Plugin;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPlugin", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::plugin::Plugin::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the subject of the conversation. + pub fn for_whom( &self, - context: impl Into>, - input: impl Into, - ) -> Result>, Box> { - let temp_clone = crate::conversations::ValidatingPrompt::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::conversations::ValidatingPrompt = temp_clone.into(); - real.accept_input(context, input) + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/conversations/Conversable;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getForWhom", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::conversations::Conversable::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Ensures that the prompt waits for the user to provide input. - pub fn blocks_for_input( + /// Gets the underlying sessionData map. + /// May be directly modified to manipulate session data. + pub fn all_session_data( &self, - context: impl Into>, - ) -> Result> { - let temp_clone = crate::conversations::ValidatingPrompt::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::conversations::ValidatingPrompt = temp_clone.into(); - real.blocks_for_input(context) + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Map;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAllSessionData", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets session data shared between all {@link Prompt} invocations. Use + /// this as a way to pass data through each Prompt as the conversation + /// develops. + pub fn get_session_data( + &self, + key: jni::objects::JObject<'mc>, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/Object;)Ljava/lang/Object;"); + let val_1 = jni::objects::JValueGen::Object(key); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSessionData", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) + } + /// Sets session data shared between all {@link Prompt} invocations. Use + /// this as a way to pass data through each prompt as the conversation + /// develops. + pub fn set_session_data( + &self, + key: jni::objects::JObject<'mc>, + value: jni::objects::JObject<'mc>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/Object;Ljava/lang/Object;)V"); + let val_1 = jni::objects::JValueGen::Object(key); + let val_2 = jni::objects::JValueGen::Object(value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSessionData", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1867,19 +2186,13 @@ impl<'mc> FixedSetPrompt<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for FixedSetPrompt<'mc> { - fn into(self) -> crate::conversations::ValidatingPrompt<'mc> { - crate::conversations::ValidatingPrompt::from_raw(&self.jni_ref(), self.1) - .expect("Error converting FixedSetPrompt into crate::conversations::ValidatingPrompt") - } -} #[repr(C)] -pub struct ConversationAbandonedEvent<'mc>( +pub struct RegexPrompt<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ConversationAbandonedEvent<'mc> { +impl<'mc> JNIRaw<'mc> for RegexPrompt<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1887,22 +2200,18 @@ impl<'mc> JNIRaw<'mc> for ConversationAbandonedEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ConversationAbandonedEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for RegexPrompt<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate ConversationAbandonedEvent from null object." - ) - .into()); + return Err(eyre::eyre!("Tried to instantiate RegexPrompt from null object.").into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/conversations/ConversationAbandonedEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/conversations/RegexPrompt")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ConversationAbandonedEvent object, got {}", + "Invalid argument passed. Expected a RegexPrompt object, got {}", name ) .into()) @@ -1912,74 +2221,62 @@ impl<'mc> JNIInstantiatable<'mc> for ConversationAbandonedEvent<'mc> { } } -impl<'mc> ConversationAbandonedEvent<'mc> { +impl<'mc> RegexPrompt<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - conversation: impl Into>, - canceller: std::option::Option>>, - ) -> Result, Box> - { + pattern: impl Into>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/conversations/Conversation;"; + sig += "Ljava/util/regex/Pattern;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(conversation.into().jni_object().clone()) + jni::objects::JObject::from_raw(pattern.into().jni_object().clone()) }); args.push(val_1); - if let Some(a) = canceller { - sig += "Lorg/bukkit/conversations/ConversationCanceller;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } sig += ")V"; - let cls = jni.find_class("org/bukkit/conversations/ConversationAbandonedEvent"); + let cls = jni.find_class("org/bukkit/conversations/RegexPrompt"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::conversations::ConversationAbandonedEvent::from_raw(&jni, res) + crate::conversations::RegexPrompt::from_raw(&jni, res) } - /// Gets the object that caused the conversation to be abandoned. - pub fn canceller( + // SUPER CLASS: org.bukkit.conversations.ValidatingPrompt ( []) + /// Accepts and processes input from the user and validates it. If + /// validation fails, this prompt is returned for re-execution, otherwise + /// the next Prompt in the prompt graph is returned. + pub fn accept_input( &self, - ) -> Result>, Box> - { - let sig = String::from("()Lorg/bukkit/conversations/ConversationCanceller;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCanceller", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::conversations::ConversationCanceller::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + context: impl Into>, + input: impl Into, + ) -> Result>, Box> { + let temp_clone = crate::conversations::ValidatingPrompt::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::conversations::ValidatingPrompt = temp_clone.into(); + real.accept_input(context, input) } - /// Gets the abandoned conversation's conversation context. - pub fn context( + /// Ensures that the prompt waits for the user to provide input. + pub fn blocks_for_input( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/conversations/ConversationContext;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getContext", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::conversations::ConversationContext::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + context: impl Into>, + ) -> Result> { + let temp_clone = crate::conversations::ValidatingPrompt::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::conversations::ValidatingPrompt = temp_clone.into(); + real.blocks_for_input(context) } - /// Indicates how the conversation was abandoned - naturally as part of the - /// prompt chain or prematurely via a {@link ConversationCanceller}. - pub fn graceful_exit(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "gracefulExit", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Gets the text to display to the user when this prompt is first + /// presented. + pub fn get_prompt_text( + &self, + context: impl Into>, + ) -> Result> { + let temp_clone = crate::conversations::ValidatingPrompt::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::conversations::ValidatingPrompt = temp_clone.into(); + real.get_prompt_text(context) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1987,13 +2284,19 @@ impl<'mc> ConversationAbandonedEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for RegexPrompt<'mc> { + fn into(self) -> crate::conversations::ValidatingPrompt<'mc> { + crate::conversations::ValidatingPrompt::from_raw(&self.jni_ref(), self.1) + .expect("Error converting RegexPrompt into crate::conversations::ValidatingPrompt") + } +} #[repr(C)] -pub struct MessagePrompt<'mc>( +pub struct Prompt<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for MessagePrompt<'mc> { +impl<'mc> JNIRaw<'mc> for Prompt<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2001,18 +2304,18 @@ impl<'mc> JNIRaw<'mc> for MessagePrompt<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for MessagePrompt<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Prompt<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate MessagePrompt from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Prompt from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/conversations/MessagePrompt")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/conversations/Prompt")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a MessagePrompt object, got {}", + "Invalid argument passed. Expected a Prompt object, got {}", name ) .into()) @@ -2022,18 +2325,43 @@ impl<'mc> JNIInstantiatable<'mc> for MessagePrompt<'mc> { } } -impl<'mc> MessagePrompt<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/conversations/MessagePrompt"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), vec![]); - let res = jni.translate_error_no_gen(res)?; - crate::conversations::MessagePrompt::from_raw(&jni, res) +impl<'mc> Prompt<'mc> { + pub fn from_extendable( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + plugin: &'mc crate::plugin::Plugin, + address: i32, + lib_name: String, + name: String, + ) -> Result> { + let obj = unsafe { plugin.new_extendable(address, "Prompt", name, lib_name) }?; + Self::from_raw(env, obj) } - /// Message prompts never wait for user input before continuing. + /// Gets the text to display to the user when this prompt is first + /// presented. + pub fn get_prompt_text( + &self, + context: impl Into>, + ) -> Result> { + let sig = + String::from("(Lorg/bukkit/conversations/ConversationContext;)Ljava/lang/String;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(context.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPromptText", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Checks to see if this prompt implementation should wait for user input + /// or immediately display the next prompt. pub fn blocks_for_input( &self, context: impl Into>, @@ -2051,8 +2379,8 @@ impl<'mc> MessagePrompt<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Accepts and ignores any user input, returning the next prompt in the - /// prompt graph instead. + /// Accepts and processes input from the user. Using the input, the next + /// Prompt in the prompt graph is returned. pub fn accept_input( &self, context: impl Into>, @@ -2083,49 +2411,19 @@ impl<'mc> MessagePrompt<'mc> { unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Gets the text to display to the user when this prompt is first - /// presented. - pub fn get_prompt_text( - &self, - context: impl Into>, - ) -> Result> { - let sig = - String::from("(Lorg/bukkit/conversations/ConversationContext;)Ljava/lang/String;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(context.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPromptText", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for MessagePrompt<'mc> { - fn into(self) -> crate::conversations::Prompt<'mc> { - crate::conversations::Prompt::from_raw(&self.jni_ref(), self.1) - .expect("Error converting MessagePrompt into crate::conversations::Prompt") - } -} #[repr(C)] -pub struct ConversationPrefix<'mc>( +pub struct ConversationCanceller<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ConversationPrefix<'mc> { +impl<'mc> JNIRaw<'mc> for ConversationCanceller<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2133,21 +2431,22 @@ impl<'mc> JNIRaw<'mc> for ConversationPrefix<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ConversationPrefix<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ConversationCanceller<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate ConversationPrefix from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate ConversationCanceller from null object." + ) + .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/conversations/ConversationPrefix")?; + env.validate_name(&obj, "org/bukkit/conversations/ConversationCanceller")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ConversationPrefix object, got {}", + "Invalid argument passed. Expected a ConversationCanceller object, got {}", name ) .into()) @@ -2157,7 +2456,7 @@ impl<'mc> JNIInstantiatable<'mc> for ConversationPrefix<'mc> { } } -impl<'mc> ConversationPrefix<'mc> { +impl<'mc> ConversationCanceller<'mc> { pub fn from_extendable( env: &blackboxmc_general::SharedJNIEnv<'mc>, plugin: &'mc crate::plugin::Plugin, @@ -2165,160 +2464,69 @@ impl<'mc> ConversationPrefix<'mc> { lib_name: String, name: String, ) -> Result> { - let obj = unsafe { plugin.new_extendable(address, "ConversationPrefix", name, lib_name) }?; - Self::from_raw(env, obj) - } - /// Gets the prefix to use before each message to the player. - pub fn get_prefix( - &self, - context: impl Into>, - ) -> Result> { - let sig = - String::from("(Lorg/bukkit/conversations/ConversationContext;)Ljava/lang/String;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(context.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPrefix", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct ValidatingPrompt<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for ValidatingPrompt<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for ValidatingPrompt<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate ValidatingPrompt from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/conversations/ValidatingPrompt")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ValidatingPrompt object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> ValidatingPrompt<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/conversations/ValidatingPrompt"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), vec![]); - let res = jni.translate_error_no_gen(res)?; - crate::conversations::ValidatingPrompt::from_raw(&jni, res) - } - /// Accepts and processes input from the user and validates it. If - /// validation fails, this prompt is returned for re-execution, otherwise - /// the next Prompt in the prompt graph is returned. - pub fn accept_input( - &self, - context: impl Into>, - input: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/conversations/ConversationContext;Ljava/lang/String;)Lorg/bukkit/conversations/Prompt;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(context.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(input.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "acceptInput", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::conversations::Prompt::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + let obj = + unsafe { plugin.new_extendable(address, "ConversationCanceller", name, lib_name) }?; + Self::from_raw(env, obj) } - /// Ensures that the prompt waits for the user to provide input. - pub fn blocks_for_input( + /// Sets the conversation this ConversationCanceller can optionally cancel. + pub fn set_conversation( &self, - context: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/conversations/ConversationContext;)Z"); + conversation: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/conversations/Conversation;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(context.into().jni_object().clone()) + jni::objects::JObject::from_raw(conversation.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "blocksForInput", + "setConversation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the text to display to the user when this prompt is first - /// presented. - pub fn get_prompt_text( + /// Cancels a conversation based on user input. + pub fn cancel_based_on_input( &self, context: impl Into>, - ) -> Result> { + input: impl Into, + ) -> Result> { let sig = - String::from("(Lorg/bukkit/conversations/ConversationContext;)Ljava/lang/String;"); + String::from("(Lorg/bukkit/conversations/ConversationContext;Ljava/lang/String;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(context.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(input.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "getPromptText", + "cancelBasedOnInput", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; - Ok(self + Ok(res.z()?) + } + /// Allows the {@link ConversationFactory} to duplicate this + /// ConversationCanceller when creating a new {@link Conversation}. + /// + /// Implementing this method should reset any internal object state. + pub fn clone( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/conversations/ConversationCanceller;"); + let res = self .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::conversations::ConversationCanceller::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -2326,19 +2534,13 @@ impl<'mc> ValidatingPrompt<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for ValidatingPrompt<'mc> { - fn into(self) -> crate::conversations::Prompt<'mc> { - crate::conversations::Prompt::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ValidatingPrompt into crate::conversations::Prompt") - } -} #[repr(C)] -pub struct Conversation<'mc>( +pub struct FixedSetPrompt<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Conversation<'mc> { +impl<'mc> JNIRaw<'mc> for FixedSetPrompt<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2346,18 +2548,20 @@ impl<'mc> JNIRaw<'mc> for Conversation<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Conversation<'mc> { +impl<'mc> JNIInstantiatable<'mc> for FixedSetPrompt<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Conversation from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate FixedSetPrompt from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/conversations/Conversation")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/conversations/FixedSetPrompt")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Conversation object, got {}", + "Invalid argument passed. Expected a FixedSetPrompt object, got {}", name ) .into()) @@ -2367,262 +2571,65 @@ impl<'mc> JNIInstantiatable<'mc> for Conversation<'mc> { } } -impl<'mc> Conversation<'mc> { - /// Initializes a new Conversation. - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - plugin: impl Into>, - for_whom: impl Into>, - first_prompt: impl Into>, - initial_session_data: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/plugin/Plugin;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/conversations/Conversable;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(for_whom.into().jni_object().clone()) - }); - args.push(val_2); - sig += "Lorg/bukkit/conversations/Prompt;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(first_prompt.into().jni_object().clone()) - }); - args.push(val_3); - if let Some(a) = initial_session_data { - sig += "Ljava/util/Map;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_4); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/conversations/Conversation"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::conversations::Conversation::from_raw(&jni, res) - } - /// Gets the entity for whom this conversation is mediating. - pub fn for_whom( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/conversations/Conversable;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getForWhom", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::conversations::Conversable::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the modality of this conversation. If a conversation is modal, all - /// messages directed to the player are suppressed for the duration of the - /// conversation. - pub fn is_modal(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isModal", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the status of local echo for this conversation. If local echo is - /// enabled, any text submitted to a conversation gets echoed back into the - /// submitter's chat window. - pub fn is_local_echo_enabled(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isLocalEchoEnabled", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets the status of local echo for this conversation. If local echo is - /// enabled, any text submitted to a conversation gets echoed back into the - /// submitter's chat window. - pub fn set_local_echo_enabled( - &self, - local_echo_enabled: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(local_echo_enabled.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLocalEchoEnabled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the {@link ConversationPrefix} that prepends all output from this - /// conversation. - pub fn prefix( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/conversations/ConversationPrefix;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPrefix", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::conversations::ConversationPrefix::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the list of {@link ConversationCanceller}s - pub fn cancellers( - &self, - ) -> Result>, Box> - { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCancellers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::conversations::ConversationCanceller::from_raw( - &self.0, obj, - )?); - } - Ok(new_vec) - } - /// Returns the Conversation's {@link ConversationContext}. - pub fn context( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/conversations/ConversationContext;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getContext", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::conversations::ConversationContext::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Displays the first prompt of this conversation and begins redirecting - /// the user's chat responses. - pub fn begin(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "begin", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns Returns the current state of the conversation. - pub fn state( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/conversations/Conversation/ConversationState;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getState", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::conversations::ConversationConversationState::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Passes player input into the current prompt. The next prompt (as - /// determined by the current prompt) is then displayed to the user. - pub fn accept_input(&self, input: impl Into) -> Result<(), Box> { +impl<'mc> FixedSetPrompt<'mc> { + /// Creates a FixedSetPrompt from a set of strings. + /// + /// foo = new FixedSetPrompt("bar", "cheese", "panda"); + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + fixed_set: impl Into, + ) -> Result, Box> { let sig = String::from("(Ljava/lang/String;)V"); let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(input.into())?, + jni.new_string(fixed_set.into())?, )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "acceptInput", + let cls = jni.find_class("org/bukkit/conversations/FixedSetPrompt"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = jni.translate_error_no_gen(res)?; + crate::conversations::FixedSetPrompt::from_raw(&jni, res) } - /// Adds a {@link ConversationAbandonedListener}. - pub fn add_conversation_abandoned_listener( + // SUPER CLASS: org.bukkit.conversations.ValidatingPrompt ( []) + /// Accepts and processes input from the user and validates it. If + /// validation fails, this prompt is returned for re-execution, otherwise + /// the next Prompt in the prompt graph is returned. + pub fn accept_input( &self, - listener: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/conversations/ConversationAbandonedListener;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(listener.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addConversationAbandonedListener", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + context: impl Into>, + input: impl Into, + ) -> Result>, Box> { + let temp_clone = crate::conversations::ValidatingPrompt::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::conversations::ValidatingPrompt = temp_clone.into(); + real.accept_input(context, input) } - /// Removes a {@link ConversationAbandonedListener}. - pub fn remove_conversation_abandoned_listener( + /// Ensures that the prompt waits for the user to provide input. + pub fn blocks_for_input( &self, - listener: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/conversations/ConversationAbandonedListener;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(listener.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removeConversationAbandonedListener", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + context: impl Into>, + ) -> Result> { + let temp_clone = crate::conversations::ValidatingPrompt::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::conversations::ValidatingPrompt = temp_clone.into(); + real.blocks_for_input(context) } - /// Abandons and resets the current conversation. Restores the user's - /// normal chat behavior. - pub fn abandon( + /// Gets the text to display to the user when this prompt is first + /// presented. + pub fn get_prompt_text( &self, - details: std::option::Option< - impl Into>, - >, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = details { - sig += "Lorg/bukkit/conversations/ConversationAbandonedEvent;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "abandon", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Displays the next user prompt and abandons the conversation if the next - /// prompt is null. - pub fn output_next_prompt(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "outputNextPrompt", - sig.as_str(), - vec![], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + context: impl Into>, + ) -> Result> { + let temp_clone = crate::conversations::ValidatingPrompt::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::conversations::ValidatingPrompt = temp_clone.into(); + real.get_prompt_text(context) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -2630,91 +2637,133 @@ impl<'mc> Conversation<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum ConversationConversationState<'mc> {} -impl<'mc> std::fmt::Display for ConversationConversationState<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> ConversationConversationState<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/conversations/Conversation/ConversationState"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/conversations/Conversation/ConversationState;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } +impl<'mc> Into> for FixedSetPrompt<'mc> { + fn into(self) -> crate::conversations::ValidatingPrompt<'mc> { + crate::conversations::ValidatingPrompt::from_raw(&self.jni_ref(), self.1) + .expect("Error converting FixedSetPrompt into crate::conversations::ValidatingPrompt") } } - #[repr(C)] -pub struct ConversationConversationStateStruct<'mc>( +pub struct ConversationAbandonedEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ConversationConversationState<'mc> { +impl<'mc> JNIRaw<'mc> for ConversationAbandonedEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + self.0.clone() } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ConversationConversationState<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ConversationAbandonedEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate ConversationConversationState from null object." + "Tried to instantiate ConversationAbandonedEvent from null object." ) .into()); } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/conversations/Conversation/ConversationState", - )?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/conversations/ConversationAbandonedEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ConversationConversationState object, got {}", + "Invalid argument passed. Expected a ConversationAbandonedEvent object, got {}", name ) .into()) } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> ConversationAbandonedEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + conversation: impl Into>, + canceller: std::option::Option>>, + ) -> Result, Box> + { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/conversations/Conversation;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(conversation.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = canceller { + sig += "Lorg/bukkit/conversations/ConversationCanceller;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/conversations/ConversationAbandonedEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::conversations::ConversationAbandonedEvent::from_raw(&jni, res) + } + /// Gets the object that caused the conversation to be abandoned. + pub fn canceller( + &self, + ) -> Result>, Box> + { + let sig = String::from("()Lorg/bukkit/conversations/ConversationCanceller;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCanceller", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some(crate::conversations::ConversationCanceller::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the abandoned conversation's conversation context. + pub fn context( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/conversations/ConversationContext;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getContext", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::conversations::ConversationContext::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Indicates how the conversation was abandoned - naturally as part of the + /// prompt chain or prematurely via a {@link ConversationCanceller}. + pub fn graceful_exit(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "gracefulExit", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +#[repr(C)] +pub struct MessagePrompt<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); -impl<'mc> JNIRaw<'mc> for ConversationConversationStateStruct<'mc> { +impl<'mc> JNIRaw<'mc> for MessagePrompt<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2722,45 +2771,111 @@ impl<'mc> JNIRaw<'mc> for ConversationConversationStateStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ConversationConversationStateStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for MessagePrompt<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate ConversationConversationStateStruct from null object." - ) - .into()); + return Err(eyre::eyre!("Tried to instantiate MessagePrompt from null object.").into()); } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/conversations/Conversation/ConversationState", - )?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/conversations/MessagePrompt")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ConversationConversationStateStruct object, got {}", - name - ) - .into()) + "Invalid argument passed. Expected a MessagePrompt object, got {}", + name + ) + .into()) } else { Ok(Self(env.clone(), obj)) } } } -impl<'mc> ConversationConversationStateStruct<'mc> { - pub fn values( +impl<'mc> MessagePrompt<'mc> { + pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/conversations/Conversation/ConversationState;"); - let cls = jni.find_class("org/bukkit/conversations/Conversation/ConversationState"); + ) -> Result, Box> { + let sig = String::from("()V"); + let cls = jni.find_class("org/bukkit/conversations/MessagePrompt"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::conversations::ConversationConversationState::from_raw(&jni, obj) + let res = jni.new_object(cls, sig.as_str(), vec![]); + let res = jni.translate_error_no_gen(res)?; + crate::conversations::MessagePrompt::from_raw(&jni, res) + } + /// Message prompts never wait for user input before continuing. + pub fn blocks_for_input( + &self, + context: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/conversations/ConversationContext;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(context.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "blocksForInput", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Accepts and ignores any user input, returning the next prompt in the + /// prompt graph instead. + pub fn accept_input( + &self, + context: impl Into>, + input: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/conversations/ConversationContext;Ljava/lang/String;)Lorg/bukkit/conversations/Prompt;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(context.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(input.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "acceptInput", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::conversations::Prompt::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the text to display to the user when this prompt is first + /// presented. + pub fn get_prompt_text( + &self, + context: impl Into>, + ) -> Result> { + let sig = + String::from("(Lorg/bukkit/conversations/ConversationContext;)Ljava/lang/String;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(context.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPromptText", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -2768,13 +2883,19 @@ impl<'mc> ConversationConversationStateStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for MessagePrompt<'mc> { + fn into(self) -> crate::conversations::Prompt<'mc> { + crate::conversations::Prompt::from_raw(&self.jni_ref(), self.1) + .expect("Error converting MessagePrompt into crate::conversations::Prompt") + } +} #[repr(C)] -pub struct NullConversationPrefix<'mc>( +pub struct ConversationPrefix<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for NullConversationPrefix<'mc> { +impl<'mc> JNIRaw<'mc> for ConversationPrefix<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2782,22 +2903,21 @@ impl<'mc> JNIRaw<'mc> for NullConversationPrefix<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for NullConversationPrefix<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ConversationPrefix<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate NullConversationPrefix from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate ConversationPrefix from null object.").into(), + ); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/conversations/NullConversationPrefix")?; + env.validate_name(&obj, "org/bukkit/conversations/ConversationPrefix")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a NullConversationPrefix object, got {}", + "Invalid argument passed. Expected a ConversationPrefix object, got {}", name ) .into()) @@ -2807,18 +2927,18 @@ impl<'mc> JNIInstantiatable<'mc> for NullConversationPrefix<'mc> { } } -impl<'mc> NullConversationPrefix<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/conversations/NullConversationPrefix"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), vec![]); - let res = jni.translate_error_no_gen(res)?; - crate::conversations::NullConversationPrefix::from_raw(&jni, res) +impl<'mc> ConversationPrefix<'mc> { + pub fn from_extendable( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + plugin: &'mc crate::plugin::Plugin, + address: i32, + lib_name: String, + name: String, + ) -> Result> { + let obj = unsafe { plugin.new_extendable(address, "ConversationPrefix", name, lib_name) }?; + Self::from_raw(env, obj) } - /// Prepends each conversation message with an empty string. + /// Gets the prefix to use before each message to the player. pub fn get_prefix( &self, context: impl Into>, @@ -2847,20 +2967,13 @@ impl<'mc> NullConversationPrefix<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for NullConversationPrefix<'mc> { - fn into(self) -> crate::conversations::ConversationPrefix<'mc> { - crate::conversations::ConversationPrefix::from_raw(&self.jni_ref(), self.1).expect( - "Error converting NullConversationPrefix into crate::conversations::ConversationPrefix", - ) - } -} #[repr(C)] -pub struct NumericPrompt<'mc>( +pub struct NullConversationPrefix<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for NumericPrompt<'mc> { +impl<'mc> JNIRaw<'mc> for NullConversationPrefix<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2868,18 +2981,22 @@ impl<'mc> JNIRaw<'mc> for NumericPrompt<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for NumericPrompt<'mc> { +impl<'mc> JNIInstantiatable<'mc> for NullConversationPrefix<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate NumericPrompt from null object.").into()); + return Err(eyre::eyre!( + "Tried to instantiate NullConversationPrefix from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/conversations/NumericPrompt")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/conversations/NullConversationPrefix")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a NumericPrompt object, got {}", + "Invalid argument passed. Expected a NullConversationPrefix object, got {}", name ) .into()) @@ -2889,54 +3006,39 @@ impl<'mc> JNIInstantiatable<'mc> for NumericPrompt<'mc> { } } -impl<'mc> NumericPrompt<'mc> { +impl<'mc> NullConversationPrefix<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { + ) -> Result, Box> { let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/conversations/NumericPrompt"); + let cls = jni.find_class("org/bukkit/conversations/NullConversationPrefix"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), vec![]); let res = jni.translate_error_no_gen(res)?; - crate::conversations::NumericPrompt::from_raw(&jni, res) - } - // SUPER CLASS: org.bukkit.conversations.ValidatingPrompt ( []) - /// Accepts and processes input from the user and validates it. If - /// validation fails, this prompt is returned for re-execution, otherwise - /// the next Prompt in the prompt graph is returned. - pub fn accept_input( - &self, - context: impl Into>, - input: impl Into, - ) -> Result>, Box> { - let temp_clone = crate::conversations::ValidatingPrompt::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::conversations::ValidatingPrompt = temp_clone.into(); - real.accept_input(context, input) - } - /// Ensures that the prompt waits for the user to provide input. - pub fn blocks_for_input( - &self, - context: impl Into>, - ) -> Result> { - let temp_clone = crate::conversations::ValidatingPrompt::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::conversations::ValidatingPrompt = temp_clone.into(); - real.blocks_for_input(context) + crate::conversations::NullConversationPrefix::from_raw(&jni, res) } - /// Gets the text to display to the user when this prompt is first - /// presented. - pub fn get_prompt_text( + /// Prepends each conversation message with an empty string. + pub fn get_prefix( &self, context: impl Into>, ) -> Result> { - let temp_clone = crate::conversations::ValidatingPrompt::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::conversations::ValidatingPrompt = temp_clone.into(); - real.get_prompt_text(context) + let sig = + String::from("(Lorg/bukkit/conversations/ConversationContext;)Ljava/lang/String;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(context.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPrefix", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -2944,10 +3046,11 @@ impl<'mc> NumericPrompt<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for NumericPrompt<'mc> { - fn into(self) -> crate::conversations::ValidatingPrompt<'mc> { - crate::conversations::ValidatingPrompt::from_raw(&self.jni_ref(), self.1) - .expect("Error converting NumericPrompt into crate::conversations::ValidatingPrompt") +impl<'mc> Into> for NullConversationPrefix<'mc> { + fn into(self) -> crate::conversations::ConversationPrefix<'mc> { + crate::conversations::ConversationPrefix::from_raw(&self.jni_ref(), self.1).expect( + "Error converting NullConversationPrefix into crate::conversations::ConversationPrefix", + ) } } #[repr(C)] diff --git a/blackboxmc-rs-bukkit/src/damage/mod.rs b/blackboxmc-rs-bukkit/src/damage/mod.rs index e7918e1..01ef09c 100644 --- a/blackboxmc-rs-bukkit/src/damage/mod.rs +++ b/blackboxmc-rs-bukkit/src/damage/mod.rs @@ -143,10 +143,30 @@ impl<'mc> Into> for DamageType<'mc> { .expect("Error converting DamageType into crate::Translatable") } } -pub enum DeathMessageType<'mc> {} +pub enum DeathMessageType<'mc> { + Default { inner: DeathMessageTypeStruct<'mc> }, + FallVariants { inner: DeathMessageTypeStruct<'mc> }, + IntentionalGameDesign { inner: DeathMessageTypeStruct<'mc> }, +} impl<'mc> std::fmt::Display for DeathMessageType<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + DeathMessageType::Default { .. } => f.write_str("DEFAULT"), + DeathMessageType::FallVariants { .. } => f.write_str("FALL_VARIANTS"), + DeathMessageType::IntentionalGameDesign { .. } => { + f.write_str("INTENTIONAL_GAME_DESIGN") + } + } + } +} +impl<'mc> std::ops::Deref for DeathMessageType<'mc> { + type Target = DeathMessageTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + DeathMessageType::Default { inner } => inner, + DeathMessageType::FallVariants { inner } => inner, + DeathMessageType::IntentionalGameDesign { inner } => inner, + } } } @@ -173,6 +193,16 @@ impl<'mc> DeathMessageType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "DEFAULT" => Ok(DeathMessageType::Default { + inner: DeathMessageTypeStruct::from_raw(env, obj)?, + }), + "FALL_VARIANTS" => Ok(DeathMessageType::FallVariants { + inner: DeathMessageTypeStruct::from_raw(env, obj)?, + }), + "INTENTIONAL_GAME_DESIGN" => Ok(DeathMessageType::IntentionalGameDesign { + inner: DeathMessageTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -186,10 +216,22 @@ pub struct DeathMessageTypeStruct<'mc>( impl<'mc> JNIRaw<'mc> for DeathMessageType<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Default { inner } => inner.0.clone(), + Self::FallVariants { inner } => inner.0.clone(), + Self::IntentionalGameDesign { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Default { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::FallVariants { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IntentionalGameDesign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } impl<'mc> JNIInstantiatable<'mc> for DeathMessageType<'mc> { @@ -217,6 +259,15 @@ impl<'mc> JNIInstantiatable<'mc> for DeathMessageType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "DEFAULT" => Ok(DeathMessageType::Default { + inner: DeathMessageTypeStruct::from_raw(env, obj)?, + }), + "FALL_VARIANTS" => Ok(DeathMessageType::FallVariants { + inner: DeathMessageTypeStruct::from_raw(env, obj)?, + }), + "INTENTIONAL_GAME_DESIGN" => Ok(DeathMessageType::IntentionalGameDesign { + inner: DeathMessageTypeStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -273,10 +324,30 @@ impl<'mc> DeathMessageTypeStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum DamageScaling<'mc> {} +pub enum DamageScaling<'mc> { + Never { inner: DamageScalingStruct<'mc> }, + WhenCausedByLivingNonPlayer { inner: DamageScalingStruct<'mc> }, + Always { inner: DamageScalingStruct<'mc> }, +} impl<'mc> std::fmt::Display for DamageScaling<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + DamageScaling::Never { .. } => f.write_str("NEVER"), + DamageScaling::WhenCausedByLivingNonPlayer { .. } => { + f.write_str("WHEN_CAUSED_BY_LIVING_NON_PLAYER") + } + DamageScaling::Always { .. } => f.write_str("ALWAYS"), + } + } +} +impl<'mc> std::ops::Deref for DamageScaling<'mc> { + type Target = DamageScalingStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + DamageScaling::Never { inner } => inner, + DamageScaling::WhenCausedByLivingNonPlayer { inner } => inner, + DamageScaling::Always { inner } => inner, + } } } @@ -303,6 +374,16 @@ impl<'mc> DamageScaling<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NEVER" => Ok(DamageScaling::Never { + inner: DamageScalingStruct::from_raw(env, obj)?, + }), + "WHEN_CAUSED_BY_LIVING_NON_PLAYER" => Ok(DamageScaling::WhenCausedByLivingNonPlayer { + inner: DamageScalingStruct::from_raw(env, obj)?, + }), + "ALWAYS" => Ok(DamageScaling::Always { + inner: DamageScalingStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -316,10 +397,20 @@ pub struct DamageScalingStruct<'mc>( impl<'mc> JNIRaw<'mc> for DamageScaling<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Never { inner } => inner.0.clone(), + Self::WhenCausedByLivingNonPlayer { inner } => inner.0.clone(), + Self::Always { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Never { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::WhenCausedByLivingNonPlayer { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Always { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for DamageScaling<'mc> { @@ -345,6 +436,17 @@ impl<'mc> JNIInstantiatable<'mc> for DamageScaling<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NEVER" => Ok(DamageScaling::Never { + inner: DamageScalingStruct::from_raw(env, obj)?, + }), + "WHEN_CAUSED_BY_LIVING_NON_PLAYER" => { + Ok(DamageScaling::WhenCausedByLivingNonPlayer { + inner: DamageScalingStruct::from_raw(env, obj)?, + }) + } + "ALWAYS" => Ok(DamageScaling::Always { + inner: DamageScalingStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } diff --git a/blackboxmc-rs-bukkit/src/enchantments/mod.rs b/blackboxmc-rs-bukkit/src/enchantments/mod.rs index 0b2f82f..d07a304 100644 --- a/blackboxmc-rs-bukkit/src/enchantments/mod.rs +++ b/blackboxmc-rs-bukkit/src/enchantments/mod.rs @@ -2,6 +2,345 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; +pub enum EnchantmentTarget<'mc> { + All { inner: EnchantmentTargetStruct<'mc> }, + Armor { inner: EnchantmentTargetStruct<'mc> }, + ArmorFeet { inner: EnchantmentTargetStruct<'mc> }, + ArmorLegs { inner: EnchantmentTargetStruct<'mc> }, + ArmorTorso { inner: EnchantmentTargetStruct<'mc> }, + ArmorHead { inner: EnchantmentTargetStruct<'mc> }, + Weapon { inner: EnchantmentTargetStruct<'mc> }, + Tool { inner: EnchantmentTargetStruct<'mc> }, + Bow { inner: EnchantmentTargetStruct<'mc> }, + FishingRod { inner: EnchantmentTargetStruct<'mc> }, + Breakable { inner: EnchantmentTargetStruct<'mc> }, + Wearable { inner: EnchantmentTargetStruct<'mc> }, + Trident { inner: EnchantmentTargetStruct<'mc> }, + Crossbow { inner: EnchantmentTargetStruct<'mc> }, + Vanishable { inner: EnchantmentTargetStruct<'mc> }, +} +impl<'mc> std::fmt::Display for EnchantmentTarget<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + EnchantmentTarget::All { .. } => f.write_str("ALL"), + EnchantmentTarget::Armor { .. } => f.write_str("ARMOR"), + EnchantmentTarget::ArmorFeet { .. } => f.write_str("ARMOR_FEET"), + EnchantmentTarget::ArmorLegs { .. } => f.write_str("ARMOR_LEGS"), + EnchantmentTarget::ArmorTorso { .. } => f.write_str("ARMOR_TORSO"), + EnchantmentTarget::ArmorHead { .. } => f.write_str("ARMOR_HEAD"), + EnchantmentTarget::Weapon { .. } => f.write_str("WEAPON"), + EnchantmentTarget::Tool { .. } => f.write_str("TOOL"), + EnchantmentTarget::Bow { .. } => f.write_str("BOW"), + EnchantmentTarget::FishingRod { .. } => f.write_str("FISHING_ROD"), + EnchantmentTarget::Breakable { .. } => f.write_str("BREAKABLE"), + EnchantmentTarget::Wearable { .. } => f.write_str("WEARABLE"), + EnchantmentTarget::Trident { .. } => f.write_str("TRIDENT"), + EnchantmentTarget::Crossbow { .. } => f.write_str("CROSSBOW"), + EnchantmentTarget::Vanishable { .. } => f.write_str("VANISHABLE"), + } + } +} +impl<'mc> std::ops::Deref for EnchantmentTarget<'mc> { + type Target = EnchantmentTargetStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + EnchantmentTarget::All { inner } => inner, + EnchantmentTarget::Armor { inner } => inner, + EnchantmentTarget::ArmorFeet { inner } => inner, + EnchantmentTarget::ArmorLegs { inner } => inner, + EnchantmentTarget::ArmorTorso { inner } => inner, + EnchantmentTarget::ArmorHead { inner } => inner, + EnchantmentTarget::Weapon { inner } => inner, + EnchantmentTarget::Tool { inner } => inner, + EnchantmentTarget::Bow { inner } => inner, + EnchantmentTarget::FishingRod { inner } => inner, + EnchantmentTarget::Breakable { inner } => inner, + EnchantmentTarget::Wearable { inner } => inner, + EnchantmentTarget::Trident { inner } => inner, + EnchantmentTarget::Crossbow { inner } => inner, + EnchantmentTarget::Vanishable { inner } => inner, + } + } +} + +impl<'mc> EnchantmentTarget<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/enchantments/EnchantmentTarget"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/enchantments/EnchantmentTarget;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "ALL" => Ok(EnchantmentTarget::All { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "ARMOR" => Ok(EnchantmentTarget::Armor { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "ARMOR_FEET" => Ok(EnchantmentTarget::ArmorFeet { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "ARMOR_LEGS" => Ok(EnchantmentTarget::ArmorLegs { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "ARMOR_TORSO" => Ok(EnchantmentTarget::ArmorTorso { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "ARMOR_HEAD" => Ok(EnchantmentTarget::ArmorHead { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "WEAPON" => Ok(EnchantmentTarget::Weapon { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "TOOL" => Ok(EnchantmentTarget::Tool { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "BOW" => Ok(EnchantmentTarget::Bow { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "FISHING_ROD" => Ok(EnchantmentTarget::FishingRod { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "BREAKABLE" => Ok(EnchantmentTarget::Breakable { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "WEARABLE" => Ok(EnchantmentTarget::Wearable { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "TRIDENT" => Ok(EnchantmentTarget::Trident { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "CROSSBOW" => Ok(EnchantmentTarget::Crossbow { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "VANISHABLE" => Ok(EnchantmentTarget::Vanishable { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct EnchantmentTargetStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for EnchantmentTarget<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::All { inner } => inner.0.clone(), + Self::Armor { inner } => inner.0.clone(), + Self::ArmorFeet { inner } => inner.0.clone(), + Self::ArmorLegs { inner } => inner.0.clone(), + Self::ArmorTorso { inner } => inner.0.clone(), + Self::ArmorHead { inner } => inner.0.clone(), + Self::Weapon { inner } => inner.0.clone(), + Self::Tool { inner } => inner.0.clone(), + Self::Bow { inner } => inner.0.clone(), + Self::FishingRod { inner } => inner.0.clone(), + Self::Breakable { inner } => inner.0.clone(), + Self::Wearable { inner } => inner.0.clone(), + Self::Trident { inner } => inner.0.clone(), + Self::Crossbow { inner } => inner.0.clone(), + Self::Vanishable { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::All { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Armor { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ArmorFeet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ArmorLegs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ArmorTorso { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ArmorHead { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Weapon { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Tool { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Bow { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::FishingRod { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Breakable { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Wearable { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Trident { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Crossbow { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Vanishable { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for EnchantmentTarget<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate EnchantmentTarget from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/enchantments/EnchantmentTarget")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EnchantmentTarget object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "ALL" => Ok(EnchantmentTarget::All { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "ARMOR" => Ok(EnchantmentTarget::Armor { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "ARMOR_FEET" => Ok(EnchantmentTarget::ArmorFeet { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "ARMOR_LEGS" => Ok(EnchantmentTarget::ArmorLegs { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "ARMOR_TORSO" => Ok(EnchantmentTarget::ArmorTorso { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "ARMOR_HEAD" => Ok(EnchantmentTarget::ArmorHead { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "WEAPON" => Ok(EnchantmentTarget::Weapon { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "TOOL" => Ok(EnchantmentTarget::Tool { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "BOW" => Ok(EnchantmentTarget::Bow { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "FISHING_ROD" => Ok(EnchantmentTarget::FishingRod { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "BREAKABLE" => Ok(EnchantmentTarget::Breakable { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "WEARABLE" => Ok(EnchantmentTarget::Wearable { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "TRIDENT" => Ok(EnchantmentTarget::Trident { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "CROSSBOW" => Ok(EnchantmentTarget::Crossbow { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + "VANISHABLE" => Ok(EnchantmentTarget::Vanishable { + inner: EnchantmentTargetStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for EnchantmentTargetStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for EnchantmentTargetStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate EnchantmentTargetStruct from null object." + ) + .into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/enchantments/EnchantmentTarget")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EnchantmentTargetStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> EnchantmentTargetStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/enchantments/EnchantmentTarget;"); + let cls = jni.find_class("org/bukkit/enchantments/EnchantmentTarget"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::enchantments::EnchantmentTarget::from_raw(&jni, obj) + } + /// Check whether this target includes the specified item. + pub fn includes( + &self, + item: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "includes", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} pub enum Enchantment<'mc> { Protection { inner: EnchantmentStruct<'mc> }, FireProtection { inner: EnchantmentStruct<'mc> }, @@ -94,6 +433,55 @@ impl<'mc> std::fmt::Display for Enchantment<'mc> { } } } +impl<'mc> std::ops::Deref for Enchantment<'mc> { + type Target = EnchantmentStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + Enchantment::Protection { inner } => inner, + Enchantment::FireProtection { inner } => inner, + Enchantment::FeatherFalling { inner } => inner, + Enchantment::BlastProtection { inner } => inner, + Enchantment::ProjectileProtection { inner } => inner, + Enchantment::Respiration { inner } => inner, + Enchantment::AquaAffinity { inner } => inner, + Enchantment::Thorns { inner } => inner, + Enchantment::DepthStrider { inner } => inner, + Enchantment::FrostWalker { inner } => inner, + Enchantment::BindingCurse { inner } => inner, + Enchantment::Sharpness { inner } => inner, + Enchantment::Smite { inner } => inner, + Enchantment::BaneOfArthropods { inner } => inner, + Enchantment::Knockback { inner } => inner, + Enchantment::FireAspect { inner } => inner, + Enchantment::Looting { inner } => inner, + Enchantment::SweepingEdge { inner } => inner, + Enchantment::Efficiency { inner } => inner, + Enchantment::SilkTouch { inner } => inner, + Enchantment::Unbreaking { inner } => inner, + Enchantment::Fortune { inner } => inner, + Enchantment::Power { inner } => inner, + Enchantment::Punch { inner } => inner, + Enchantment::Flame { inner } => inner, + Enchantment::Infinity { inner } => inner, + Enchantment::LuckOfTheSea { inner } => inner, + Enchantment::Lure { inner } => inner, + Enchantment::Loyalty { inner } => inner, + Enchantment::Impaling { inner } => inner, + Enchantment::Riptide { inner } => inner, + Enchantment::Channeling { inner } => inner, + Enchantment::Multishot { inner } => inner, + Enchantment::QuickCharge { inner } => inner, + Enchantment::Piercing { inner } => inner, + Enchantment::Density { inner } => inner, + Enchantment::Breach { inner } => inner, + Enchantment::WindBurst { inner } => inner, + Enchantment::Mending { inner } => inner, + Enchantment::VanishingCurse { inner } => inner, + Enchantment::SoulSpeed { inner } => inner, + Enchantment::SwiftSneak { inner } => inner, + } + } +} impl<'mc> Enchantment<'mc> { pub fn value_of( @@ -743,14 +1131,14 @@ impl<'mc> EnchantmentWrapper<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, key: impl Into>, ) -> Result>, Box> { - crate::enchantments::Enchantment::get_by_key(jni, key) + crate::enchantments::EnchantmentStruct::get_by_key(jni, key) } /// Gets the Enchantment at the specified name pub fn get_by_name( jni: &blackboxmc_general::SharedJNIEnv<'mc>, name: impl Into, ) -> Result>, Box> { - crate::enchantments::Enchantment::get_by_name(jni, name) + crate::enchantments::EnchantmentStruct::get_by_name(jni, name) } #[deprecated] /// Gets an array of all the registered {@link Enchantment}s @@ -793,154 +1181,6 @@ impl<'mc> Into> for EnchantmentWrapper<'mc .expect("Error converting EnchantmentWrapper into crate::enchantments::Enchantment") } } -pub enum EnchantmentTarget<'mc> {} -impl<'mc> std::fmt::Display for EnchantmentTarget<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> EnchantmentTarget<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/enchantments/EnchantmentTarget"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/enchantments/EnchantmentTarget;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct EnchantmentTargetStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for EnchantmentTarget<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for EnchantmentTarget<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate EnchantmentTarget from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/enchantments/EnchantmentTarget")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EnchantmentTarget object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for EnchantmentTargetStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for EnchantmentTargetStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate EnchantmentTargetStruct from null object." - ) - .into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/enchantments/EnchantmentTarget")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EnchantmentTargetStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> EnchantmentTargetStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/enchantments/EnchantmentTarget;"); - let cls = jni.find_class("org/bukkit/enchantments/EnchantmentTarget"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::enchantments::EnchantmentTarget::from_raw(&jni, obj) - } - /// Check whether this target includes the specified item. - pub fn includes( - &self, - item: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "includes", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} #[repr(C)] pub struct EnchantmentOffer<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, diff --git a/blackboxmc-rs-bukkit/src/entity/memory/mod.rs b/blackboxmc-rs-bukkit/src/entity/memory/mod.rs index ff5266e..bf25917 100644 --- a/blackboxmc-rs-bukkit/src/entity/memory/mod.rs +++ b/blackboxmc-rs-bukkit/src/entity/memory/mod.rs @@ -60,6 +60,37 @@ impl<'mc> std::fmt::Display for MemoryKey<'mc> { } } } +impl<'mc> std::ops::Deref for MemoryKey<'mc> { + type Target = MemoryKeyStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + MemoryKey::Home { inner } => inner, + MemoryKey::PotentialJobSite { inner } => inner, + MemoryKey::JobSite { inner } => inner, + MemoryKey::MeetingPoint { inner } => inner, + MemoryKey::GolemDetectedRecently { inner } => inner, + MemoryKey::LastSlept { inner } => inner, + MemoryKey::LastWoken { inner } => inner, + MemoryKey::LastWorkedAtPoi { inner } => inner, + MemoryKey::UniversalAnger { inner } => inner, + MemoryKey::AngryAt { inner } => inner, + MemoryKey::AdmiringItem { inner } => inner, + MemoryKey::AdmiringDisabled { inner } => inner, + MemoryKey::HuntedRecently { inner } => inner, + MemoryKey::PlayDeadTicks { inner } => inner, + MemoryKey::TemptationCooldownTicks { inner } => inner, + MemoryKey::IsTempted { inner } => inner, + MemoryKey::LongJumpCoolingDown { inner } => inner, + MemoryKey::HasHuntingCooldown { inner } => inner, + MemoryKey::RamCooldownTicks { inner } => inner, + MemoryKey::LikedPlayer { inner } => inner, + MemoryKey::LikedNoteblockPosition { inner } => inner, + MemoryKey::LikedNoteblockCooldownTicks { inner } => inner, + MemoryKey::ItemPickupCooldownTicks { inner } => inner, + MemoryKey::SnifferExploredPositions { inner } => inner, + } + } +} impl<'mc> MemoryKey<'mc> { pub fn value_of( diff --git a/blackboxmc-rs-bukkit/src/entity/minecart/mod.rs b/blackboxmc-rs-bukkit/src/entity/minecart/mod.rs index 8e4206e..87bd28c 100644 --- a/blackboxmc-rs-bukkit/src/entity/minecart/mod.rs +++ b/blackboxmc-rs-bukkit/src/entity/minecart/mod.rs @@ -3510,6 +3510,151 @@ impl<'mc> SpawnerMinecart<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } + /// {@inheritDoc} + /// + /// If set to -1, the spawn delay will be reset to a random value between + /// {@link #getMinSpawnDelay} and {@link #getMaxSpawnDelay()}. + pub fn set_delay(&self, delay: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(delay); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDelay", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// The minimum spawn delay amount (in ticks). + /// + /// This value is used when the spawner resets its delay (for any reason). + /// It will choose a random number between {@link #getMinSpawnDelay()} + /// and {@link #getMaxSpawnDelay()} for its next {@link #getDelay()}. + /// + /// Default value is 200 ticks. + pub fn min_spawn_delay(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMinSpawnDelay", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the minimum spawn delay amount (in ticks). + pub fn set_min_spawn_delay(&self, delay: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(delay); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMinSpawnDelay", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// The maximum spawn delay amount (in ticks). + /// + /// This value is used when the spawner resets its delay (for any reason). + /// It will choose a random number between {@link #getMinSpawnDelay()} + /// and {@link #getMaxSpawnDelay()} for its next {@link #getDelay()}. + /// + /// This value must be greater than 0 and less than or equal to + /// {@link #getMaxSpawnDelay()}. + /// + /// Default value is 800 ticks. + pub fn max_spawn_delay(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaxSpawnDelay", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the maximum spawn delay amount (in ticks). + /// + /// This value must be greater than 0, as well as greater than or + /// equal to {@link #getMinSpawnDelay()} + pub fn set_max_spawn_delay(&self, delay: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(delay); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaxSpawnDelay", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get how many mobs attempt to spawn. + /// + /// Default value is 4. + pub fn spawn_count(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSpawnCount", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set how many mobs attempt to spawn. + pub fn set_spawn_count(&self, spawn_count: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(spawn_count); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSpawnCount", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Set the new maximum amount of similar entities that are allowed to be + /// within spawning range of this spawner. + /// + /// If more than the maximum number of entities are within range, the spawner + /// will not spawn and try again with a new {@link #getDelay()}. + /// + /// Default value is 16. + pub fn max_nearby_entities(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaxNearbyEntities", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the maximum number of similar entities that are allowed to be within + /// spawning range of this spawner. + /// + /// Similar entities are entities that are of the same {@link EntityType} + pub fn set_max_nearby_entities( + &self, + max_nearby_entities: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(max_nearby_entities); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaxNearbyEntities", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; @@ -3522,6 +3667,12 @@ impl<'mc> Into> for SpawnerMinecart<'mc> { .expect("Error converting SpawnerMinecart into crate::entity::Minecart") } } +impl<'mc> Into> for SpawnerMinecart<'mc> { + fn into(self) -> crate::spawner::Spawner<'mc> { + crate::spawner::Spawner::from_raw(&self.jni_ref(), self.1) + .expect("Error converting SpawnerMinecart into crate::spawner::Spawner") + } +} #[repr(C)] pub struct StorageMinecart<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, diff --git a/blackboxmc-rs-bukkit/src/entity/mod.rs b/blackboxmc-rs-bukkit/src/entity/mod.rs index 83f336d..f77bc85 100644 --- a/blackboxmc-rs-bukkit/src/entity/mod.rs +++ b/blackboxmc-rs-bukkit/src/entity/mod.rs @@ -2,85 +2,13 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; -pub enum EntityType<'mc> {} -impl<'mc> std::fmt::Display for EntityType<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> EntityType<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/EntityType"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/EntityType;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - #[repr(C)] -pub struct EntityTypeStruct<'mc>( +pub struct Panda<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EntityType<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for EntityType<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate EntityType from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EntityType")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityType object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for EntityTypeStruct<'mc> { +impl<'mc> JNIRaw<'mc> for Panda<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -88,20 +16,18 @@ impl<'mc> JNIRaw<'mc> for EntityTypeStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EntityTypeStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Panda<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate EntityTypeStruct from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate Panda from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EntityType")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Panda")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityTypeStruct object, got {}", + "Invalid argument passed. Expected a Panda object, got {}", name ) .into()) @@ -111,3278 +37,8893 @@ impl<'mc> JNIInstantiatable<'mc> for EntityTypeStruct<'mc> { } } -impl<'mc> EntityTypeStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); - let cls = jni.find_class("org/bukkit/entity/EntityType"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::EntityType::from_raw(&jni, obj) - } - #[deprecated] - /// Gets the entity type name. - pub fn name(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( +impl<'mc> Panda<'mc> { + /// Gets this Panda's main gene. + pub fn main_gene(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Panda/Gene;"); + let res = self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMainGene", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + crate::entity::PandaGene::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn entity_class( + /// Sets this Panda's main gene. + pub fn set_main_gene( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/lang/Class;"); + gene: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Panda/Gene;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(gene.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMainGene", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets this Panda's hidden gene. + pub fn hidden_gene(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Panda/Gene;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getEntityClass", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(unsafe { - jni::objects::JClass::from_raw(res.as_jni().l) - })) - } - #[deprecated] - /// Gets the entity type id. - pub fn type_id(&self) -> Result> { - let sig = String::from("()S"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTypeId", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getHiddenGene", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.s()?) + crate::entity::PandaGene::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - /// Gets an entity type from its name. - pub fn from_name( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - name: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/entity/EntityType;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(name.into())?, - )); - let cls = jni.find_class("org/bukkit/entity/EntityType"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "fromName", + /// Sets this Panda's hidden gene. + pub fn set_hidden_gene( + &self, + gene: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Panda/Gene;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(gene.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setHiddenGene", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::entity::EntityType::from_raw(&jni, obj)?)) + self.jni_ref().translate_error(res)?; + Ok(()) } - #[deprecated] - /// Gets an entity from its id. - pub fn from_id( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - id: i32, - ) -> Result>, Box> { - let sig = String::from("(I)Lorg/bukkit/entity/EntityType;"); - let val_1 = jni::objects::JValueGen::Int(id); - let cls = jni.find_class("org/bukkit/entity/EntityType"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "fromId", + /// Gets whether the Panda is rolling + pub fn is_rolling(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isRolling", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the Panda is rolling + pub fn set_rolling(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRolling", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::entity::EntityType::from_raw(&jni, obj)?)) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Some entities cannot be spawned using {@link - /// World#spawnEntity(Location, EntityType)} or {@link - /// World#spawn(Location, Class)}, usually because they require additional - /// information in order to spawn. - pub fn is_spawnable(&self) -> Result> { + /// Gets whether the Panda is sneezing + pub fn is_sneezing(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isSpawnable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn is_alive(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isAlive", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSneezing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - - pub fn translation_key(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Sets whether the Panda is sneezing + pub fn set_sneezing(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getTranslationKey", + "setSneezing", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(self + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether the Panda is on its back + pub fn is_on_back(&self) -> Result> { + let sig = String::from("()Z"); + let res = self .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + .call_method(&self.jni_object(), "isOnBack", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets if this EntityType is enabled by feature in a world. - pub fn is_enabled_by_feature( - &self, - world: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/World;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); + /// Sets whether the Panda is on its back + pub fn set_on_back(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "isEnabledByFeature", + "setOnBack", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct Bogged<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Bogged<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Bogged<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Bogged from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Bogged")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Bogged object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> Bogged<'mc> { - #[deprecated] - /// Gets the current type of this skeleton. - pub fn skeleton_type( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Skeleton/SkeletonType;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSkeletonType", sig.as_str(), vec![]); + /// Gets whether the Panda is eating + pub fn is_eating(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEating", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::SkeletonSkeletonType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - #[deprecated] - - pub fn set_skeleton_type( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Skeleton/SkeletonType;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Sets the Panda's eating status. The panda must be holding food for this to work + pub fn set_eating(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setSkeletonType", + "setEating", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Bogged<'mc> { - fn into(self) -> crate::entity::AbstractSkeleton<'mc> { - crate::entity::AbstractSkeleton::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Bogged into crate::entity::AbstractSkeleton") - } -} -#[repr(C)] -pub struct OminousItemSpawner<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for OminousItemSpawner<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets whether the Panda is scared + pub fn is_scared(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isScared", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for OminousItemSpawner<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate OminousItemSpawner from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/OminousItemSpawner")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a OminousItemSpawner object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Gets how many ticks the panda will be unhappy for + pub fn unhappy_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getUnhappyTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} - -impl<'mc> OminousItemSpawner<'mc> { - /// Gets the item which will be spawned by this spawner. - pub fn item( + /// Get the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn breed_cause( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::ItemStack::from_raw( + Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets the item which will be spawned by this spawner. - pub fn set_item( + /// Set the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn set_breed_cause( &self, - item: impl Into>, + uuid: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let sig = String::from("(Ljava/util/UUID;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setItem", + "setBreedCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the ticks after which this item will be spawned. - pub fn spawn_item_after_ticks(&self) -> Result> { - let sig = String::from("()J"); + /// Get whether or not this entity is in love mode and will produce + /// offspring with another entity in love mode. Will return true if + /// and only if {@link #getLoveModeTicks()} is greater than 0. + pub fn is_love_mode(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the amount of ticks remaining for this entity in love mode. + /// If the entity is not in love mode, 0 will be returned. + pub fn love_mode_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getSpawnItemAfterTicks", + "getLoveModeTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + Ok(res.i()?) } - /// Sets the ticks after which this item will be spawned. - pub fn set_spawn_item_after_ticks(&self, ticks: i64) -> Result<(), Box> { - let sig = String::from("(J)V"); - let val_1 = jni::objects::JValueGen::Long(ticks); + /// Set the amount of ticks for which this entity should be in love mode. + /// Setting the love mode ticks to 600 is the equivalent of a player + /// feeding the entity their breeding item of choice. + pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setSpawnItemAfterTicks", + "setLoveModeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Stores the entity's current position in the provided Location object. - /// - /// If the provided Location is null this method does nothing and returns - /// null. - pub fn get_location( + /// Check if the provided ItemStack is the correct item used for breeding + /// this entity.. + pub fn is_breed_item( &self, - loc: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + material: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + jni::objects::JObject::from_raw(material.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLocation", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.z()?) } - /// Sets this entity's velocity in meters per tick - pub fn set_velocity( - &self, - velocity: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) - }); + /// Checks if this animal is sitting + pub fn is_sitting(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSitting", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets if this animal is sitting. Will remove any path that the animal + /// was following beforehand. + pub fn set_sitting(&self, sitting: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(sitting.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setVelocity", + "setSitting", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets this entity's current velocity - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Gets the entity's height - pub fn height(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) +} +impl<'mc> Into> for Panda<'mc> { + fn into(self) -> crate::entity::Animals<'mc> { + crate::entity::Animals::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Panda into crate::entity::Animals") } - /// Gets the entity's width - pub fn width(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) +} +impl<'mc> Into> for Panda<'mc> { + fn into(self) -> crate::entity::Sittable<'mc> { + crate::entity::Sittable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Panda into crate::entity::Sittable") } - /// Gets the entity's current bounding box. - /// - /// The returned bounding box reflects the entity's current location and - /// size. - pub fn bounding_box( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} +pub enum PandaGene<'mc> { + Normal { inner: PandaGeneStruct<'mc> }, + Lazy { inner: PandaGeneStruct<'mc> }, + Worried { inner: PandaGeneStruct<'mc> }, + Playful { inner: PandaGeneStruct<'mc> }, + Brown { inner: PandaGeneStruct<'mc> }, + Weak { inner: PandaGeneStruct<'mc> }, + Aggressive { inner: PandaGeneStruct<'mc> }, +} +impl<'mc> std::fmt::Display for PandaGene<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PandaGene::Normal { .. } => f.write_str("NORMAL"), + PandaGene::Lazy { .. } => f.write_str("LAZY"), + PandaGene::Worried { .. } => f.write_str("WORRIED"), + PandaGene::Playful { .. } => f.write_str("PLAYFUL"), + PandaGene::Brown { .. } => f.write_str("BROWN"), + PandaGene::Weak { .. } => f.write_str("WEAK"), + PandaGene::Aggressive { .. } => f.write_str("AGGRESSIVE"), + } } - /// Returns true if the entity is supported by a block. This value is a - /// state updated by the server and is not recalculated unless the entity - /// moves. - pub fn is_on_ground(&self) -> Result> { +} +impl<'mc> std::ops::Deref for PandaGene<'mc> { + type Target = PandaGeneStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + PandaGene::Normal { inner } => inner, + PandaGene::Lazy { inner } => inner, + PandaGene::Worried { inner } => inner, + PandaGene::Playful { inner } => inner, + PandaGene::Brown { inner } => inner, + PandaGene::Weak { inner } => inner, + PandaGene::Aggressive { inner } => inner, + } + } +} + +impl<'mc> PandaGene<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/Panda/Gene"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/Panda/Gene;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "NORMAL" => Ok(PandaGene::Normal { + inner: PandaGeneStruct::from_raw(env, obj)?, + }), + "LAZY" => Ok(PandaGene::Lazy { + inner: PandaGeneStruct::from_raw(env, obj)?, + }), + "WORRIED" => Ok(PandaGene::Worried { + inner: PandaGeneStruct::from_raw(env, obj)?, + }), + "PLAYFUL" => Ok(PandaGene::Playful { + inner: PandaGeneStruct::from_raw(env, obj)?, + }), + "BROWN" => Ok(PandaGene::Brown { + inner: PandaGeneStruct::from_raw(env, obj)?, + }), + "WEAK" => Ok(PandaGene::Weak { + inner: PandaGeneStruct::from_raw(env, obj)?, + }), + "AGGRESSIVE" => Ok(PandaGene::Aggressive { + inner: PandaGeneStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct PandaGeneStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PandaGene<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Normal { inner } => inner.0.clone(), + Self::Lazy { inner } => inner.0.clone(), + Self::Worried { inner } => inner.0.clone(), + Self::Playful { inner } => inner.0.clone(), + Self::Brown { inner } => inner.0.clone(), + Self::Weak { inner } => inner.0.clone(), + Self::Aggressive { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Normal { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Lazy { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Worried { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Playful { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Brown { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Weak { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Aggressive { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for PandaGene<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate PandaGene from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Panda/Gene")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PandaGene object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "NORMAL" => Ok(PandaGene::Normal { + inner: PandaGeneStruct::from_raw(env, obj)?, + }), + "LAZY" => Ok(PandaGene::Lazy { + inner: PandaGeneStruct::from_raw(env, obj)?, + }), + "WORRIED" => Ok(PandaGene::Worried { + inner: PandaGeneStruct::from_raw(env, obj)?, + }), + "PLAYFUL" => Ok(PandaGene::Playful { + inner: PandaGeneStruct::from_raw(env, obj)?, + }), + "BROWN" => Ok(PandaGene::Brown { + inner: PandaGeneStruct::from_raw(env, obj)?, + }), + "WEAK" => Ok(PandaGene::Weak { + inner: PandaGeneStruct::from_raw(env, obj)?, + }), + "AGGRESSIVE" => Ok(PandaGene::Aggressive { + inner: PandaGeneStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for PandaGeneStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PandaGeneStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate PandaGeneStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Panda/Gene")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PandaGeneStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> PandaGeneStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Panda/Gene;"); + let cls = jni.find_class("org/bukkit/entity/Panda/Gene"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::PandaGene::from_raw(&jni, obj) + } + /// Gets whether this gene is recessive, i.e. required in both parents to + /// propagate to children. + pub fn is_recessive(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isRecessive", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns true if the entity is in water. - pub fn is_in_water(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Gets the current world this entity resides in - pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} +#[repr(C)] +pub struct Ocelot<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Ocelot<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Sets the entity's rotation. - /// - /// Note that if the entity is affected by AI, it may override this rotation. - pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { - let sig = String::from("(FF)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); - let val_2 = jni::objects::JValueGen::Float(pitch); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRotation", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Teleports this entity to the given location. If this entity is riding a - /// vehicle, it will be dismounted prior to teleportation. - pub fn teleport( - &self, - location: impl Into>, - cause: std::option::Option< - impl Into>, - >, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = cause { - sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); +} +impl<'mc> JNIInstantiatable<'mc> for Ocelot<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Ocelot from null object.").into()); } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "teleport", sig.as_str(), args); + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Ocelot")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Ocelot object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Ocelot<'mc> { + /// Checks if this ocelot trusts players. + pub fn is_trusting(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isTrusting", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns a list of entities within a bounding box centered around this - /// entity - pub fn get_nearby_entities( - &self, - x: f64, - y: f64, - z: f64, - ) -> Result>, Box> { - let sig = String::from("(DDD)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Double(x); - let val_2 = jni::objects::JValueGen::Double(y); - let val_3 = jni::objects::JValueGen::Double(z); + /// Sets if this ocelot trusts players. + pub fn set_trusting(&self, trust: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(trust.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getNearbyEntities", + "setTrusting", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Returns a unique id for this entity - pub fn entity_id(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn fire_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns the entity's maximum fire ticks. - pub fn max_fire_ticks(&self) -> Result> { - let sig = String::from("()I"); + #[deprecated] + /// Gets the current type of this cat. + pub fn cat_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Ocelot/Type;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCatType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::entity::OcelotType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + #[deprecated] + /// Sets the current type of this cat. + pub fn set_cat_type( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Ocelot/Type;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setFireTicks", + "setCatType", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets if the entity has visual fire (it will always appear to be on fire). - pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire.into()); + /// Get the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn breed_cause( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Set the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn set_breed_cause( + &self, + uuid: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/UUID;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisualFire", + "setBreedCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity has visual fire (it will always appear to be on fire). - pub fn is_visual_fire(&self) -> Result> { + /// Get whether or not this entity is in love mode and will produce + /// offspring with another entity in love mode. Will return true if + /// and only if {@link #getLoveModeTicks()} is greater than 0. + pub fn is_love_mode(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the entity's maximum freeze ticks (amount of ticks before it will - /// be fully frozen) - pub fn max_freeze_ticks(&self) -> Result> { + /// Get the amount of ticks remaining for this entity in love mode. + /// If the entity is not in love mode, 0 will be returned. + pub fn love_mode_ticks(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getMaxFreezeTicks", + "getLoveModeTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Set the amount of ticks for which this entity should be in love mode. + /// Setting the love mode ticks to 600 is the equivalent of a player + /// feeding the entity their breeding item of choice. + pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setFreezeTicks", + "setLoveModeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity is fully frozen (it has been in powdered snow for max - /// freeze ticks). - pub fn is_frozen(&self) -> Result> { - let sig = String::from("()Z"); - let res = self + /// Check if the provided ItemStack is the correct item used for breeding + /// this entity.. + pub fn is_breed_item( + &self, + material: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; + let res = self .jni_ref() - .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Mark the entity's removal. - pub fn remove(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Returns true if this entity has been marked for removal. - pub fn is_dead(&self) -> Result> { - let sig = String::from("()Z"); +} +impl<'mc> Into> for Ocelot<'mc> { + fn into(self) -> crate::entity::Animals<'mc> { + crate::entity::Animals::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Ocelot into crate::entity::Animals") + } +} +pub enum OcelotType<'mc> { + WildOcelot { inner: OcelotTypeStruct<'mc> }, + BlackCat { inner: OcelotTypeStruct<'mc> }, + RedCat { inner: OcelotTypeStruct<'mc> }, + SiameseCat { inner: OcelotTypeStruct<'mc> }, +} +impl<'mc> std::fmt::Display for OcelotType<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + OcelotType::WildOcelot { .. } => f.write_str("WILD_OCELOT"), + OcelotType::BlackCat { .. } => f.write_str("BLACK_CAT"), + OcelotType::RedCat { .. } => f.write_str("RED_CAT"), + OcelotType::SiameseCat { .. } => f.write_str("SIAMESE_CAT"), + } + } +} +impl<'mc> std::ops::Deref for OcelotType<'mc> { + type Target = OcelotTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + OcelotType::WildOcelot { inner } => inner, + OcelotType::BlackCat { inner } => inner, + OcelotType::RedCat { inner } => inner, + OcelotType::SiameseCat { inner } => inner, + } + } +} + +impl<'mc> OcelotType<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/Ocelot/Type"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/Ocelot/Type;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "WILD_OCELOT" => Ok(OcelotType::WildOcelot { + inner: OcelotTypeStruct::from_raw(env, obj)?, + }), + "BLACK_CAT" => Ok(OcelotType::BlackCat { + inner: OcelotTypeStruct::from_raw(env, obj)?, + }), + "RED_CAT" => Ok(OcelotType::RedCat { + inner: OcelotTypeStruct::from_raw(env, obj)?, + }), + "SIAMESE_CAT" => Ok(OcelotType::SiameseCat { + inner: OcelotTypeStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct OcelotTypeStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for OcelotType<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::WildOcelot { inner } => inner.0.clone(), + Self::BlackCat { inner } => inner.0.clone(), + Self::RedCat { inner } => inner.0.clone(), + Self::SiameseCat { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::WildOcelot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlackCat { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::RedCat { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SiameseCat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for OcelotType<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate OcelotType from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Ocelot/Type")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a OcelotType object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "WILD_OCELOT" => Ok(OcelotType::WildOcelot { + inner: OcelotTypeStruct::from_raw(env, obj)?, + }), + "BLACK_CAT" => Ok(OcelotType::BlackCat { + inner: OcelotTypeStruct::from_raw(env, obj)?, + }), + "RED_CAT" => Ok(OcelotType::RedCat { + inner: OcelotTypeStruct::from_raw(env, obj)?, + }), + "SIAMESE_CAT" => Ok(OcelotType::SiameseCat { + inner: OcelotTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for OcelotTypeStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for OcelotTypeStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate OcelotTypeStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Ocelot/Type")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a OcelotTypeStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> OcelotTypeStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Ocelot/Type;"); + let cls = jni.find_class("org/bukkit/entity/Ocelot/Type"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::OcelotType::from_raw(&jni, obj) + } + #[deprecated] + /// Gets the ID of this cat type. + pub fn id(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getId", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Returns false if the entity has died, been despawned for some other - /// reason, or has not been added to the world. - pub fn is_valid(&self) -> Result> { - let sig = String::from("()Z"); + #[deprecated] + /// Gets a cat type by its ID. + pub fn get_type( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + id: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/entity/Ocelot/Type;"); + let val_1 = jni::objects::JValueGen::Int(id); + let cls = jni.find_class("org/bukkit/entity/Ocelot/Type"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::entity::OcelotType::from_raw(&jni, obj)?)) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +pub enum EntityType<'mc> { + Item { inner: EntityTypeStruct<'mc> }, + ExperienceOrb { inner: EntityTypeStruct<'mc> }, + AreaEffectCloud { inner: EntityTypeStruct<'mc> }, + ElderGuardian { inner: EntityTypeStruct<'mc> }, + WitherSkeleton { inner: EntityTypeStruct<'mc> }, + Stray { inner: EntityTypeStruct<'mc> }, + Egg { inner: EntityTypeStruct<'mc> }, + LeashKnot { inner: EntityTypeStruct<'mc> }, + Painting { inner: EntityTypeStruct<'mc> }, + Arrow { inner: EntityTypeStruct<'mc> }, + Snowball { inner: EntityTypeStruct<'mc> }, + Fireball { inner: EntityTypeStruct<'mc> }, + SmallFireball { inner: EntityTypeStruct<'mc> }, + EnderPearl { inner: EntityTypeStruct<'mc> }, + EyeOfEnder { inner: EntityTypeStruct<'mc> }, + Potion { inner: EntityTypeStruct<'mc> }, + ExperienceBottle { inner: EntityTypeStruct<'mc> }, + ItemFrame { inner: EntityTypeStruct<'mc> }, + WitherSkull { inner: EntityTypeStruct<'mc> }, + Tnt { inner: EntityTypeStruct<'mc> }, + FallingBlock { inner: EntityTypeStruct<'mc> }, + FireworkRocket { inner: EntityTypeStruct<'mc> }, + Husk { inner: EntityTypeStruct<'mc> }, + SpectralArrow { inner: EntityTypeStruct<'mc> }, + ShulkerBullet { inner: EntityTypeStruct<'mc> }, + DragonFireball { inner: EntityTypeStruct<'mc> }, + ZombieVillager { inner: EntityTypeStruct<'mc> }, + SkeletonHorse { inner: EntityTypeStruct<'mc> }, + ZombieHorse { inner: EntityTypeStruct<'mc> }, + ArmorStand { inner: EntityTypeStruct<'mc> }, + Donkey { inner: EntityTypeStruct<'mc> }, + Mule { inner: EntityTypeStruct<'mc> }, + EvokerFangs { inner: EntityTypeStruct<'mc> }, + Evoker { inner: EntityTypeStruct<'mc> }, + Vex { inner: EntityTypeStruct<'mc> }, + Vindicator { inner: EntityTypeStruct<'mc> }, + Illusioner { inner: EntityTypeStruct<'mc> }, + CommandBlockMinecart { inner: EntityTypeStruct<'mc> }, + Boat { inner: EntityTypeStruct<'mc> }, + Minecart { inner: EntityTypeStruct<'mc> }, + ChestMinecart { inner: EntityTypeStruct<'mc> }, + FurnaceMinecart { inner: EntityTypeStruct<'mc> }, + TntMinecart { inner: EntityTypeStruct<'mc> }, + HopperMinecart { inner: EntityTypeStruct<'mc> }, + SpawnerMinecart { inner: EntityTypeStruct<'mc> }, + Creeper { inner: EntityTypeStruct<'mc> }, + Skeleton { inner: EntityTypeStruct<'mc> }, + Spider { inner: EntityTypeStruct<'mc> }, + Giant { inner: EntityTypeStruct<'mc> }, + Zombie { inner: EntityTypeStruct<'mc> }, + Slime { inner: EntityTypeStruct<'mc> }, + Ghast { inner: EntityTypeStruct<'mc> }, + ZombifiedPiglin { inner: EntityTypeStruct<'mc> }, + Enderman { inner: EntityTypeStruct<'mc> }, + CaveSpider { inner: EntityTypeStruct<'mc> }, + Silverfish { inner: EntityTypeStruct<'mc> }, + Blaze { inner: EntityTypeStruct<'mc> }, + MagmaCube { inner: EntityTypeStruct<'mc> }, + EnderDragon { inner: EntityTypeStruct<'mc> }, + Wither { inner: EntityTypeStruct<'mc> }, + Bat { inner: EntityTypeStruct<'mc> }, + Witch { inner: EntityTypeStruct<'mc> }, + Endermite { inner: EntityTypeStruct<'mc> }, + Guardian { inner: EntityTypeStruct<'mc> }, + Shulker { inner: EntityTypeStruct<'mc> }, + Pig { inner: EntityTypeStruct<'mc> }, + Sheep { inner: EntityTypeStruct<'mc> }, + Cow { inner: EntityTypeStruct<'mc> }, + Chicken { inner: EntityTypeStruct<'mc> }, + Squid { inner: EntityTypeStruct<'mc> }, + Wolf { inner: EntityTypeStruct<'mc> }, + Mooshroom { inner: EntityTypeStruct<'mc> }, + SnowGolem { inner: EntityTypeStruct<'mc> }, + Ocelot { inner: EntityTypeStruct<'mc> }, + IronGolem { inner: EntityTypeStruct<'mc> }, + Horse { inner: EntityTypeStruct<'mc> }, + Rabbit { inner: EntityTypeStruct<'mc> }, + PolarBear { inner: EntityTypeStruct<'mc> }, + Llama { inner: EntityTypeStruct<'mc> }, + LlamaSpit { inner: EntityTypeStruct<'mc> }, + Parrot { inner: EntityTypeStruct<'mc> }, + Villager { inner: EntityTypeStruct<'mc> }, + EndCrystal { inner: EntityTypeStruct<'mc> }, + Turtle { inner: EntityTypeStruct<'mc> }, + Phantom { inner: EntityTypeStruct<'mc> }, + Trident { inner: EntityTypeStruct<'mc> }, + Cod { inner: EntityTypeStruct<'mc> }, + Salmon { inner: EntityTypeStruct<'mc> }, + Pufferfish { inner: EntityTypeStruct<'mc> }, + TropicalFish { inner: EntityTypeStruct<'mc> }, + Drowned { inner: EntityTypeStruct<'mc> }, + Dolphin { inner: EntityTypeStruct<'mc> }, + Cat { inner: EntityTypeStruct<'mc> }, + Panda { inner: EntityTypeStruct<'mc> }, + Pillager { inner: EntityTypeStruct<'mc> }, + Ravager { inner: EntityTypeStruct<'mc> }, + TraderLlama { inner: EntityTypeStruct<'mc> }, + WanderingTrader { inner: EntityTypeStruct<'mc> }, + Fox { inner: EntityTypeStruct<'mc> }, + Bee { inner: EntityTypeStruct<'mc> }, + Hoglin { inner: EntityTypeStruct<'mc> }, + Piglin { inner: EntityTypeStruct<'mc> }, + Strider { inner: EntityTypeStruct<'mc> }, + Zoglin { inner: EntityTypeStruct<'mc> }, + PiglinBrute { inner: EntityTypeStruct<'mc> }, + Axolotl { inner: EntityTypeStruct<'mc> }, + GlowItemFrame { inner: EntityTypeStruct<'mc> }, + GlowSquid { inner: EntityTypeStruct<'mc> }, + Goat { inner: EntityTypeStruct<'mc> }, + Marker { inner: EntityTypeStruct<'mc> }, + Allay { inner: EntityTypeStruct<'mc> }, + ChestBoat { inner: EntityTypeStruct<'mc> }, + Frog { inner: EntityTypeStruct<'mc> }, + Tadpole { inner: EntityTypeStruct<'mc> }, + Warden { inner: EntityTypeStruct<'mc> }, + Camel { inner: EntityTypeStruct<'mc> }, + BlockDisplay { inner: EntityTypeStruct<'mc> }, + Interaction { inner: EntityTypeStruct<'mc> }, + ItemDisplay { inner: EntityTypeStruct<'mc> }, + Sniffer { inner: EntityTypeStruct<'mc> }, + TextDisplay { inner: EntityTypeStruct<'mc> }, + Breeze { inner: EntityTypeStruct<'mc> }, + WindCharge { inner: EntityTypeStruct<'mc> }, + BreezeWindCharge { inner: EntityTypeStruct<'mc> }, + Armadillo { inner: EntityTypeStruct<'mc> }, + Bogged { inner: EntityTypeStruct<'mc> }, + OminousItemSpawner { inner: EntityTypeStruct<'mc> }, + FishingBobber { inner: EntityTypeStruct<'mc> }, + LightningBolt { inner: EntityTypeStruct<'mc> }, + Player { inner: EntityTypeStruct<'mc> }, + Unknown { inner: EntityTypeStruct<'mc> }, +} +impl<'mc> std::fmt::Display for EntityType<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + EntityType::Item { .. } => f.write_str("ITEM"), + EntityType::ExperienceOrb { .. } => f.write_str("EXPERIENCE_ORB"), + EntityType::AreaEffectCloud { .. } => f.write_str("AREA_EFFECT_CLOUD"), + EntityType::ElderGuardian { .. } => f.write_str("ELDER_GUARDIAN"), + EntityType::WitherSkeleton { .. } => f.write_str("WITHER_SKELETON"), + EntityType::Stray { .. } => f.write_str("STRAY"), + EntityType::Egg { .. } => f.write_str("EGG"), + EntityType::LeashKnot { .. } => f.write_str("LEASH_KNOT"), + EntityType::Painting { .. } => f.write_str("PAINTING"), + EntityType::Arrow { .. } => f.write_str("ARROW"), + EntityType::Snowball { .. } => f.write_str("SNOWBALL"), + EntityType::Fireball { .. } => f.write_str("FIREBALL"), + EntityType::SmallFireball { .. } => f.write_str("SMALL_FIREBALL"), + EntityType::EnderPearl { .. } => f.write_str("ENDER_PEARL"), + EntityType::EyeOfEnder { .. } => f.write_str("EYE_OF_ENDER"), + EntityType::Potion { .. } => f.write_str("POTION"), + EntityType::ExperienceBottle { .. } => f.write_str("EXPERIENCE_BOTTLE"), + EntityType::ItemFrame { .. } => f.write_str("ITEM_FRAME"), + EntityType::WitherSkull { .. } => f.write_str("WITHER_SKULL"), + EntityType::Tnt { .. } => f.write_str("TNT"), + EntityType::FallingBlock { .. } => f.write_str("FALLING_BLOCK"), + EntityType::FireworkRocket { .. } => f.write_str("FIREWORK_ROCKET"), + EntityType::Husk { .. } => f.write_str("HUSK"), + EntityType::SpectralArrow { .. } => f.write_str("SPECTRAL_ARROW"), + EntityType::ShulkerBullet { .. } => f.write_str("SHULKER_BULLET"), + EntityType::DragonFireball { .. } => f.write_str("DRAGON_FIREBALL"), + EntityType::ZombieVillager { .. } => f.write_str("ZOMBIE_VILLAGER"), + EntityType::SkeletonHorse { .. } => f.write_str("SKELETON_HORSE"), + EntityType::ZombieHorse { .. } => f.write_str("ZOMBIE_HORSE"), + EntityType::ArmorStand { .. } => f.write_str("ARMOR_STAND"), + EntityType::Donkey { .. } => f.write_str("DONKEY"), + EntityType::Mule { .. } => f.write_str("MULE"), + EntityType::EvokerFangs { .. } => f.write_str("EVOKER_FANGS"), + EntityType::Evoker { .. } => f.write_str("EVOKER"), + EntityType::Vex { .. } => f.write_str("VEX"), + EntityType::Vindicator { .. } => f.write_str("VINDICATOR"), + EntityType::Illusioner { .. } => f.write_str("ILLUSIONER"), + EntityType::CommandBlockMinecart { .. } => f.write_str("COMMAND_BLOCK_MINECART"), + EntityType::Boat { .. } => f.write_str("BOAT"), + EntityType::Minecart { .. } => f.write_str("MINECART"), + EntityType::ChestMinecart { .. } => f.write_str("CHEST_MINECART"), + EntityType::FurnaceMinecart { .. } => f.write_str("FURNACE_MINECART"), + EntityType::TntMinecart { .. } => f.write_str("TNT_MINECART"), + EntityType::HopperMinecart { .. } => f.write_str("HOPPER_MINECART"), + EntityType::SpawnerMinecart { .. } => f.write_str("SPAWNER_MINECART"), + EntityType::Creeper { .. } => f.write_str("CREEPER"), + EntityType::Skeleton { .. } => f.write_str("SKELETON"), + EntityType::Spider { .. } => f.write_str("SPIDER"), + EntityType::Giant { .. } => f.write_str("GIANT"), + EntityType::Zombie { .. } => f.write_str("ZOMBIE"), + EntityType::Slime { .. } => f.write_str("SLIME"), + EntityType::Ghast { .. } => f.write_str("GHAST"), + EntityType::ZombifiedPiglin { .. } => f.write_str("ZOMBIFIED_PIGLIN"), + EntityType::Enderman { .. } => f.write_str("ENDERMAN"), + EntityType::CaveSpider { .. } => f.write_str("CAVE_SPIDER"), + EntityType::Silverfish { .. } => f.write_str("SILVERFISH"), + EntityType::Blaze { .. } => f.write_str("BLAZE"), + EntityType::MagmaCube { .. } => f.write_str("MAGMA_CUBE"), + EntityType::EnderDragon { .. } => f.write_str("ENDER_DRAGON"), + EntityType::Wither { .. } => f.write_str("WITHER"), + EntityType::Bat { .. } => f.write_str("BAT"), + EntityType::Witch { .. } => f.write_str("WITCH"), + EntityType::Endermite { .. } => f.write_str("ENDERMITE"), + EntityType::Guardian { .. } => f.write_str("GUARDIAN"), + EntityType::Shulker { .. } => f.write_str("SHULKER"), + EntityType::Pig { .. } => f.write_str("PIG"), + EntityType::Sheep { .. } => f.write_str("SHEEP"), + EntityType::Cow { .. } => f.write_str("COW"), + EntityType::Chicken { .. } => f.write_str("CHICKEN"), + EntityType::Squid { .. } => f.write_str("SQUID"), + EntityType::Wolf { .. } => f.write_str("WOLF"), + EntityType::Mooshroom { .. } => f.write_str("MOOSHROOM"), + EntityType::SnowGolem { .. } => f.write_str("SNOW_GOLEM"), + EntityType::Ocelot { .. } => f.write_str("OCELOT"), + EntityType::IronGolem { .. } => f.write_str("IRON_GOLEM"), + EntityType::Horse { .. } => f.write_str("HORSE"), + EntityType::Rabbit { .. } => f.write_str("RABBIT"), + EntityType::PolarBear { .. } => f.write_str("POLAR_BEAR"), + EntityType::Llama { .. } => f.write_str("LLAMA"), + EntityType::LlamaSpit { .. } => f.write_str("LLAMA_SPIT"), + EntityType::Parrot { .. } => f.write_str("PARROT"), + EntityType::Villager { .. } => f.write_str("VILLAGER"), + EntityType::EndCrystal { .. } => f.write_str("END_CRYSTAL"), + EntityType::Turtle { .. } => f.write_str("TURTLE"), + EntityType::Phantom { .. } => f.write_str("PHANTOM"), + EntityType::Trident { .. } => f.write_str("TRIDENT"), + EntityType::Cod { .. } => f.write_str("COD"), + EntityType::Salmon { .. } => f.write_str("SALMON"), + EntityType::Pufferfish { .. } => f.write_str("PUFFERFISH"), + EntityType::TropicalFish { .. } => f.write_str("TROPICAL_FISH"), + EntityType::Drowned { .. } => f.write_str("DROWNED"), + EntityType::Dolphin { .. } => f.write_str("DOLPHIN"), + EntityType::Cat { .. } => f.write_str("CAT"), + EntityType::Panda { .. } => f.write_str("PANDA"), + EntityType::Pillager { .. } => f.write_str("PILLAGER"), + EntityType::Ravager { .. } => f.write_str("RAVAGER"), + EntityType::TraderLlama { .. } => f.write_str("TRADER_LLAMA"), + EntityType::WanderingTrader { .. } => f.write_str("WANDERING_TRADER"), + EntityType::Fox { .. } => f.write_str("FOX"), + EntityType::Bee { .. } => f.write_str("BEE"), + EntityType::Hoglin { .. } => f.write_str("HOGLIN"), + EntityType::Piglin { .. } => f.write_str("PIGLIN"), + EntityType::Strider { .. } => f.write_str("STRIDER"), + EntityType::Zoglin { .. } => f.write_str("ZOGLIN"), + EntityType::PiglinBrute { .. } => f.write_str("PIGLIN_BRUTE"), + EntityType::Axolotl { .. } => f.write_str("AXOLOTL"), + EntityType::GlowItemFrame { .. } => f.write_str("GLOW_ITEM_FRAME"), + EntityType::GlowSquid { .. } => f.write_str("GLOW_SQUID"), + EntityType::Goat { .. } => f.write_str("GOAT"), + EntityType::Marker { .. } => f.write_str("MARKER"), + EntityType::Allay { .. } => f.write_str("ALLAY"), + EntityType::ChestBoat { .. } => f.write_str("CHEST_BOAT"), + EntityType::Frog { .. } => f.write_str("FROG"), + EntityType::Tadpole { .. } => f.write_str("TADPOLE"), + EntityType::Warden { .. } => f.write_str("WARDEN"), + EntityType::Camel { .. } => f.write_str("CAMEL"), + EntityType::BlockDisplay { .. } => f.write_str("BLOCK_DISPLAY"), + EntityType::Interaction { .. } => f.write_str("INTERACTION"), + EntityType::ItemDisplay { .. } => f.write_str("ITEM_DISPLAY"), + EntityType::Sniffer { .. } => f.write_str("SNIFFER"), + EntityType::TextDisplay { .. } => f.write_str("TEXT_DISPLAY"), + EntityType::Breeze { .. } => f.write_str("BREEZE"), + EntityType::WindCharge { .. } => f.write_str("WIND_CHARGE"), + EntityType::BreezeWindCharge { .. } => f.write_str("BREEZE_WIND_CHARGE"), + EntityType::Armadillo { .. } => f.write_str("ARMADILLO"), + EntityType::Bogged { .. } => f.write_str("BOGGED"), + EntityType::OminousItemSpawner { .. } => f.write_str("OMINOUS_ITEM_SPAWNER"), + EntityType::FishingBobber { .. } => f.write_str("FISHING_BOBBER"), + EntityType::LightningBolt { .. } => f.write_str("LIGHTNING_BOLT"), + EntityType::Player { .. } => f.write_str("PLAYER"), + EntityType::Unknown { .. } => f.write_str("UNKNOWN"), + } + } +} +impl<'mc> std::ops::Deref for EntityType<'mc> { + type Target = EntityTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + EntityType::Item { inner } => inner, + EntityType::ExperienceOrb { inner } => inner, + EntityType::AreaEffectCloud { inner } => inner, + EntityType::ElderGuardian { inner } => inner, + EntityType::WitherSkeleton { inner } => inner, + EntityType::Stray { inner } => inner, + EntityType::Egg { inner } => inner, + EntityType::LeashKnot { inner } => inner, + EntityType::Painting { inner } => inner, + EntityType::Arrow { inner } => inner, + EntityType::Snowball { inner } => inner, + EntityType::Fireball { inner } => inner, + EntityType::SmallFireball { inner } => inner, + EntityType::EnderPearl { inner } => inner, + EntityType::EyeOfEnder { inner } => inner, + EntityType::Potion { inner } => inner, + EntityType::ExperienceBottle { inner } => inner, + EntityType::ItemFrame { inner } => inner, + EntityType::WitherSkull { inner } => inner, + EntityType::Tnt { inner } => inner, + EntityType::FallingBlock { inner } => inner, + EntityType::FireworkRocket { inner } => inner, + EntityType::Husk { inner } => inner, + EntityType::SpectralArrow { inner } => inner, + EntityType::ShulkerBullet { inner } => inner, + EntityType::DragonFireball { inner } => inner, + EntityType::ZombieVillager { inner } => inner, + EntityType::SkeletonHorse { inner } => inner, + EntityType::ZombieHorse { inner } => inner, + EntityType::ArmorStand { inner } => inner, + EntityType::Donkey { inner } => inner, + EntityType::Mule { inner } => inner, + EntityType::EvokerFangs { inner } => inner, + EntityType::Evoker { inner } => inner, + EntityType::Vex { inner } => inner, + EntityType::Vindicator { inner } => inner, + EntityType::Illusioner { inner } => inner, + EntityType::CommandBlockMinecart { inner } => inner, + EntityType::Boat { inner } => inner, + EntityType::Minecart { inner } => inner, + EntityType::ChestMinecart { inner } => inner, + EntityType::FurnaceMinecart { inner } => inner, + EntityType::TntMinecart { inner } => inner, + EntityType::HopperMinecart { inner } => inner, + EntityType::SpawnerMinecart { inner } => inner, + EntityType::Creeper { inner } => inner, + EntityType::Skeleton { inner } => inner, + EntityType::Spider { inner } => inner, + EntityType::Giant { inner } => inner, + EntityType::Zombie { inner } => inner, + EntityType::Slime { inner } => inner, + EntityType::Ghast { inner } => inner, + EntityType::ZombifiedPiglin { inner } => inner, + EntityType::Enderman { inner } => inner, + EntityType::CaveSpider { inner } => inner, + EntityType::Silverfish { inner } => inner, + EntityType::Blaze { inner } => inner, + EntityType::MagmaCube { inner } => inner, + EntityType::EnderDragon { inner } => inner, + EntityType::Wither { inner } => inner, + EntityType::Bat { inner } => inner, + EntityType::Witch { inner } => inner, + EntityType::Endermite { inner } => inner, + EntityType::Guardian { inner } => inner, + EntityType::Shulker { inner } => inner, + EntityType::Pig { inner } => inner, + EntityType::Sheep { inner } => inner, + EntityType::Cow { inner } => inner, + EntityType::Chicken { inner } => inner, + EntityType::Squid { inner } => inner, + EntityType::Wolf { inner } => inner, + EntityType::Mooshroom { inner } => inner, + EntityType::SnowGolem { inner } => inner, + EntityType::Ocelot { inner } => inner, + EntityType::IronGolem { inner } => inner, + EntityType::Horse { inner } => inner, + EntityType::Rabbit { inner } => inner, + EntityType::PolarBear { inner } => inner, + EntityType::Llama { inner } => inner, + EntityType::LlamaSpit { inner } => inner, + EntityType::Parrot { inner } => inner, + EntityType::Villager { inner } => inner, + EntityType::EndCrystal { inner } => inner, + EntityType::Turtle { inner } => inner, + EntityType::Phantom { inner } => inner, + EntityType::Trident { inner } => inner, + EntityType::Cod { inner } => inner, + EntityType::Salmon { inner } => inner, + EntityType::Pufferfish { inner } => inner, + EntityType::TropicalFish { inner } => inner, + EntityType::Drowned { inner } => inner, + EntityType::Dolphin { inner } => inner, + EntityType::Cat { inner } => inner, + EntityType::Panda { inner } => inner, + EntityType::Pillager { inner } => inner, + EntityType::Ravager { inner } => inner, + EntityType::TraderLlama { inner } => inner, + EntityType::WanderingTrader { inner } => inner, + EntityType::Fox { inner } => inner, + EntityType::Bee { inner } => inner, + EntityType::Hoglin { inner } => inner, + EntityType::Piglin { inner } => inner, + EntityType::Strider { inner } => inner, + EntityType::Zoglin { inner } => inner, + EntityType::PiglinBrute { inner } => inner, + EntityType::Axolotl { inner } => inner, + EntityType::GlowItemFrame { inner } => inner, + EntityType::GlowSquid { inner } => inner, + EntityType::Goat { inner } => inner, + EntityType::Marker { inner } => inner, + EntityType::Allay { inner } => inner, + EntityType::ChestBoat { inner } => inner, + EntityType::Frog { inner } => inner, + EntityType::Tadpole { inner } => inner, + EntityType::Warden { inner } => inner, + EntityType::Camel { inner } => inner, + EntityType::BlockDisplay { inner } => inner, + EntityType::Interaction { inner } => inner, + EntityType::ItemDisplay { inner } => inner, + EntityType::Sniffer { inner } => inner, + EntityType::TextDisplay { inner } => inner, + EntityType::Breeze { inner } => inner, + EntityType::WindCharge { inner } => inner, + EntityType::BreezeWindCharge { inner } => inner, + EntityType::Armadillo { inner } => inner, + EntityType::Bogged { inner } => inner, + EntityType::OminousItemSpawner { inner } => inner, + EntityType::FishingBobber { inner } => inner, + EntityType::LightningBolt { inner } => inner, + EntityType::Player { inner } => inner, + EntityType::Unknown { inner } => inner, + } + } +} + +impl<'mc> EntityType<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/EntityType"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/EntityType;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "ITEM" => Ok(EntityType::Item { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "EXPERIENCE_ORB" => Ok(EntityType::ExperienceOrb { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "AREA_EFFECT_CLOUD" => Ok(EntityType::AreaEffectCloud { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ELDER_GUARDIAN" => Ok(EntityType::ElderGuardian { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "WITHER_SKELETON" => Ok(EntityType::WitherSkeleton { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "STRAY" => Ok(EntityType::Stray { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "EGG" => Ok(EntityType::Egg { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "LEASH_KNOT" => Ok(EntityType::LeashKnot { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "PAINTING" => Ok(EntityType::Painting { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ARROW" => Ok(EntityType::Arrow { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SNOWBALL" => Ok(EntityType::Snowball { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "FIREBALL" => Ok(EntityType::Fireball { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SMALL_FIREBALL" => Ok(EntityType::SmallFireball { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ENDER_PEARL" => Ok(EntityType::EnderPearl { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "EYE_OF_ENDER" => Ok(EntityType::EyeOfEnder { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "POTION" => Ok(EntityType::Potion { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "EXPERIENCE_BOTTLE" => Ok(EntityType::ExperienceBottle { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ITEM_FRAME" => Ok(EntityType::ItemFrame { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "WITHER_SKULL" => Ok(EntityType::WitherSkull { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "TNT" => Ok(EntityType::Tnt { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "FALLING_BLOCK" => Ok(EntityType::FallingBlock { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "FIREWORK_ROCKET" => Ok(EntityType::FireworkRocket { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "HUSK" => Ok(EntityType::Husk { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SPECTRAL_ARROW" => Ok(EntityType::SpectralArrow { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SHULKER_BULLET" => Ok(EntityType::ShulkerBullet { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "DRAGON_FIREBALL" => Ok(EntityType::DragonFireball { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ZOMBIE_VILLAGER" => Ok(EntityType::ZombieVillager { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SKELETON_HORSE" => Ok(EntityType::SkeletonHorse { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ZOMBIE_HORSE" => Ok(EntityType::ZombieHorse { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ARMOR_STAND" => Ok(EntityType::ArmorStand { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "DONKEY" => Ok(EntityType::Donkey { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "MULE" => Ok(EntityType::Mule { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "EVOKER_FANGS" => Ok(EntityType::EvokerFangs { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "EVOKER" => Ok(EntityType::Evoker { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "VEX" => Ok(EntityType::Vex { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "VINDICATOR" => Ok(EntityType::Vindicator { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ILLUSIONER" => Ok(EntityType::Illusioner { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "COMMAND_BLOCK_MINECART" => Ok(EntityType::CommandBlockMinecart { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "BOAT" => Ok(EntityType::Boat { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "MINECART" => Ok(EntityType::Minecart { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "CHEST_MINECART" => Ok(EntityType::ChestMinecart { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "FURNACE_MINECART" => Ok(EntityType::FurnaceMinecart { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "TNT_MINECART" => Ok(EntityType::TntMinecart { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "HOPPER_MINECART" => Ok(EntityType::HopperMinecart { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SPAWNER_MINECART" => Ok(EntityType::SpawnerMinecart { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "CREEPER" => Ok(EntityType::Creeper { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SKELETON" => Ok(EntityType::Skeleton { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SPIDER" => Ok(EntityType::Spider { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "GIANT" => Ok(EntityType::Giant { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ZOMBIE" => Ok(EntityType::Zombie { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SLIME" => Ok(EntityType::Slime { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "GHAST" => Ok(EntityType::Ghast { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ZOMBIFIED_PIGLIN" => Ok(EntityType::ZombifiedPiglin { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ENDERMAN" => Ok(EntityType::Enderman { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "CAVE_SPIDER" => Ok(EntityType::CaveSpider { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SILVERFISH" => Ok(EntityType::Silverfish { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "BLAZE" => Ok(EntityType::Blaze { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "MAGMA_CUBE" => Ok(EntityType::MagmaCube { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ENDER_DRAGON" => Ok(EntityType::EnderDragon { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "WITHER" => Ok(EntityType::Wither { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "BAT" => Ok(EntityType::Bat { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "WITCH" => Ok(EntityType::Witch { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ENDERMITE" => Ok(EntityType::Endermite { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "GUARDIAN" => Ok(EntityType::Guardian { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SHULKER" => Ok(EntityType::Shulker { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "PIG" => Ok(EntityType::Pig { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SHEEP" => Ok(EntityType::Sheep { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "COW" => Ok(EntityType::Cow { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "CHICKEN" => Ok(EntityType::Chicken { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SQUID" => Ok(EntityType::Squid { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "WOLF" => Ok(EntityType::Wolf { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "MOOSHROOM" => Ok(EntityType::Mooshroom { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SNOW_GOLEM" => Ok(EntityType::SnowGolem { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "OCELOT" => Ok(EntityType::Ocelot { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "IRON_GOLEM" => Ok(EntityType::IronGolem { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "HORSE" => Ok(EntityType::Horse { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "RABBIT" => Ok(EntityType::Rabbit { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "POLAR_BEAR" => Ok(EntityType::PolarBear { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "LLAMA" => Ok(EntityType::Llama { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "LLAMA_SPIT" => Ok(EntityType::LlamaSpit { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "PARROT" => Ok(EntityType::Parrot { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "VILLAGER" => Ok(EntityType::Villager { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "END_CRYSTAL" => Ok(EntityType::EndCrystal { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "TURTLE" => Ok(EntityType::Turtle { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "PHANTOM" => Ok(EntityType::Phantom { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "TRIDENT" => Ok(EntityType::Trident { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "COD" => Ok(EntityType::Cod { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SALMON" => Ok(EntityType::Salmon { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "PUFFERFISH" => Ok(EntityType::Pufferfish { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "TROPICAL_FISH" => Ok(EntityType::TropicalFish { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "DROWNED" => Ok(EntityType::Drowned { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "DOLPHIN" => Ok(EntityType::Dolphin { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "CAT" => Ok(EntityType::Cat { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "PANDA" => Ok(EntityType::Panda { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "PILLAGER" => Ok(EntityType::Pillager { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "RAVAGER" => Ok(EntityType::Ravager { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "TRADER_LLAMA" => Ok(EntityType::TraderLlama { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "WANDERING_TRADER" => Ok(EntityType::WanderingTrader { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "FOX" => Ok(EntityType::Fox { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "BEE" => Ok(EntityType::Bee { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "HOGLIN" => Ok(EntityType::Hoglin { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "PIGLIN" => Ok(EntityType::Piglin { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "STRIDER" => Ok(EntityType::Strider { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ZOGLIN" => Ok(EntityType::Zoglin { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "PIGLIN_BRUTE" => Ok(EntityType::PiglinBrute { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "AXOLOTL" => Ok(EntityType::Axolotl { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "GLOW_ITEM_FRAME" => Ok(EntityType::GlowItemFrame { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "GLOW_SQUID" => Ok(EntityType::GlowSquid { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "GOAT" => Ok(EntityType::Goat { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "MARKER" => Ok(EntityType::Marker { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ALLAY" => Ok(EntityType::Allay { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "CHEST_BOAT" => Ok(EntityType::ChestBoat { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "FROG" => Ok(EntityType::Frog { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "TADPOLE" => Ok(EntityType::Tadpole { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "WARDEN" => Ok(EntityType::Warden { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "CAMEL" => Ok(EntityType::Camel { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "BLOCK_DISPLAY" => Ok(EntityType::BlockDisplay { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "INTERACTION" => Ok(EntityType::Interaction { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ITEM_DISPLAY" => Ok(EntityType::ItemDisplay { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SNIFFER" => Ok(EntityType::Sniffer { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "TEXT_DISPLAY" => Ok(EntityType::TextDisplay { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "BREEZE" => Ok(EntityType::Breeze { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "WIND_CHARGE" => Ok(EntityType::WindCharge { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "BREEZE_WIND_CHARGE" => Ok(EntityType::BreezeWindCharge { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ARMADILLO" => Ok(EntityType::Armadillo { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "BOGGED" => Ok(EntityType::Bogged { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "OMINOUS_ITEM_SPAWNER" => Ok(EntityType::OminousItemSpawner { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "FISHING_BOBBER" => Ok(EntityType::FishingBobber { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "LIGHTNING_BOLT" => Ok(EntityType::LightningBolt { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "PLAYER" => Ok(EntityType::Player { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(EntityType::Unknown { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct EntityTypeStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for EntityType<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Item { inner } => inner.0.clone(), + Self::ExperienceOrb { inner } => inner.0.clone(), + Self::AreaEffectCloud { inner } => inner.0.clone(), + Self::ElderGuardian { inner } => inner.0.clone(), + Self::WitherSkeleton { inner } => inner.0.clone(), + Self::Stray { inner } => inner.0.clone(), + Self::Egg { inner } => inner.0.clone(), + Self::LeashKnot { inner } => inner.0.clone(), + Self::Painting { inner } => inner.0.clone(), + Self::Arrow { inner } => inner.0.clone(), + Self::Snowball { inner } => inner.0.clone(), + Self::Fireball { inner } => inner.0.clone(), + Self::SmallFireball { inner } => inner.0.clone(), + Self::EnderPearl { inner } => inner.0.clone(), + Self::EyeOfEnder { inner } => inner.0.clone(), + Self::Potion { inner } => inner.0.clone(), + Self::ExperienceBottle { inner } => inner.0.clone(), + Self::ItemFrame { inner } => inner.0.clone(), + Self::WitherSkull { inner } => inner.0.clone(), + Self::Tnt { inner } => inner.0.clone(), + Self::FallingBlock { inner } => inner.0.clone(), + Self::FireworkRocket { inner } => inner.0.clone(), + Self::Husk { inner } => inner.0.clone(), + Self::SpectralArrow { inner } => inner.0.clone(), + Self::ShulkerBullet { inner } => inner.0.clone(), + Self::DragonFireball { inner } => inner.0.clone(), + Self::ZombieVillager { inner } => inner.0.clone(), + Self::SkeletonHorse { inner } => inner.0.clone(), + Self::ZombieHorse { inner } => inner.0.clone(), + Self::ArmorStand { inner } => inner.0.clone(), + Self::Donkey { inner } => inner.0.clone(), + Self::Mule { inner } => inner.0.clone(), + Self::EvokerFangs { inner } => inner.0.clone(), + Self::Evoker { inner } => inner.0.clone(), + Self::Vex { inner } => inner.0.clone(), + Self::Vindicator { inner } => inner.0.clone(), + Self::Illusioner { inner } => inner.0.clone(), + Self::CommandBlockMinecart { inner } => inner.0.clone(), + Self::Boat { inner } => inner.0.clone(), + Self::Minecart { inner } => inner.0.clone(), + Self::ChestMinecart { inner } => inner.0.clone(), + Self::FurnaceMinecart { inner } => inner.0.clone(), + Self::TntMinecart { inner } => inner.0.clone(), + Self::HopperMinecart { inner } => inner.0.clone(), + Self::SpawnerMinecart { inner } => inner.0.clone(), + Self::Creeper { inner } => inner.0.clone(), + Self::Skeleton { inner } => inner.0.clone(), + Self::Spider { inner } => inner.0.clone(), + Self::Giant { inner } => inner.0.clone(), + Self::Zombie { inner } => inner.0.clone(), + Self::Slime { inner } => inner.0.clone(), + Self::Ghast { inner } => inner.0.clone(), + Self::ZombifiedPiglin { inner } => inner.0.clone(), + Self::Enderman { inner } => inner.0.clone(), + Self::CaveSpider { inner } => inner.0.clone(), + Self::Silverfish { inner } => inner.0.clone(), + Self::Blaze { inner } => inner.0.clone(), + Self::MagmaCube { inner } => inner.0.clone(), + Self::EnderDragon { inner } => inner.0.clone(), + Self::Wither { inner } => inner.0.clone(), + Self::Bat { inner } => inner.0.clone(), + Self::Witch { inner } => inner.0.clone(), + Self::Endermite { inner } => inner.0.clone(), + Self::Guardian { inner } => inner.0.clone(), + Self::Shulker { inner } => inner.0.clone(), + Self::Pig { inner } => inner.0.clone(), + Self::Sheep { inner } => inner.0.clone(), + Self::Cow { inner } => inner.0.clone(), + Self::Chicken { inner } => inner.0.clone(), + Self::Squid { inner } => inner.0.clone(), + Self::Wolf { inner } => inner.0.clone(), + Self::Mooshroom { inner } => inner.0.clone(), + Self::SnowGolem { inner } => inner.0.clone(), + Self::Ocelot { inner } => inner.0.clone(), + Self::IronGolem { inner } => inner.0.clone(), + Self::Horse { inner } => inner.0.clone(), + Self::Rabbit { inner } => inner.0.clone(), + Self::PolarBear { inner } => inner.0.clone(), + Self::Llama { inner } => inner.0.clone(), + Self::LlamaSpit { inner } => inner.0.clone(), + Self::Parrot { inner } => inner.0.clone(), + Self::Villager { inner } => inner.0.clone(), + Self::EndCrystal { inner } => inner.0.clone(), + Self::Turtle { inner } => inner.0.clone(), + Self::Phantom { inner } => inner.0.clone(), + Self::Trident { inner } => inner.0.clone(), + Self::Cod { inner } => inner.0.clone(), + Self::Salmon { inner } => inner.0.clone(), + Self::Pufferfish { inner } => inner.0.clone(), + Self::TropicalFish { inner } => inner.0.clone(), + Self::Drowned { inner } => inner.0.clone(), + Self::Dolphin { inner } => inner.0.clone(), + Self::Cat { inner } => inner.0.clone(), + Self::Panda { inner } => inner.0.clone(), + Self::Pillager { inner } => inner.0.clone(), + Self::Ravager { inner } => inner.0.clone(), + Self::TraderLlama { inner } => inner.0.clone(), + Self::WanderingTrader { inner } => inner.0.clone(), + Self::Fox { inner } => inner.0.clone(), + Self::Bee { inner } => inner.0.clone(), + Self::Hoglin { inner } => inner.0.clone(), + Self::Piglin { inner } => inner.0.clone(), + Self::Strider { inner } => inner.0.clone(), + Self::Zoglin { inner } => inner.0.clone(), + Self::PiglinBrute { inner } => inner.0.clone(), + Self::Axolotl { inner } => inner.0.clone(), + Self::GlowItemFrame { inner } => inner.0.clone(), + Self::GlowSquid { inner } => inner.0.clone(), + Self::Goat { inner } => inner.0.clone(), + Self::Marker { inner } => inner.0.clone(), + Self::Allay { inner } => inner.0.clone(), + Self::ChestBoat { inner } => inner.0.clone(), + Self::Frog { inner } => inner.0.clone(), + Self::Tadpole { inner } => inner.0.clone(), + Self::Warden { inner } => inner.0.clone(), + Self::Camel { inner } => inner.0.clone(), + Self::BlockDisplay { inner } => inner.0.clone(), + Self::Interaction { inner } => inner.0.clone(), + Self::ItemDisplay { inner } => inner.0.clone(), + Self::Sniffer { inner } => inner.0.clone(), + Self::TextDisplay { inner } => inner.0.clone(), + Self::Breeze { inner } => inner.0.clone(), + Self::WindCharge { inner } => inner.0.clone(), + Self::BreezeWindCharge { inner } => inner.0.clone(), + Self::Armadillo { inner } => inner.0.clone(), + Self::Bogged { inner } => inner.0.clone(), + Self::OminousItemSpawner { inner } => inner.0.clone(), + Self::FishingBobber { inner } => inner.0.clone(), + Self::LightningBolt { inner } => inner.0.clone(), + Self::Player { inner } => inner.0.clone(), + Self::Unknown { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Item { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ExperienceOrb { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AreaEffectCloud { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ElderGuardian { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WitherSkeleton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Stray { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Egg { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::LeashKnot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Painting { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Arrow { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Snowball { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Fireball { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SmallFireball { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnderPearl { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EyeOfEnder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Potion { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ExperienceBottle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemFrame { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WitherSkull { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Tnt { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::FallingBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FireworkRocket { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Husk { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SpectralArrow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ShulkerBullet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DragonFireball { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ZombieVillager { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SkeletonHorse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ZombieHorse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ArmorStand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Donkey { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Mule { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::EvokerFangs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Evoker { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Vex { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Vindicator { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Illusioner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CommandBlockMinecart { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Boat { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Minecart { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ChestMinecart { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FurnaceMinecart { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TntMinecart { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HopperMinecart { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SpawnerMinecart { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Creeper { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Skeleton { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Spider { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Giant { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Zombie { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Slime { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Ghast { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ZombifiedPiglin { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Enderman { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CaveSpider { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Silverfish { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Blaze { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::MagmaCube { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnderDragon { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Wither { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Bat { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Witch { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Endermite { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Guardian { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Shulker { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Pig { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Sheep { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Cow { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Chicken { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Squid { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Wolf { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Mooshroom { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SnowGolem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Ocelot { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::IronGolem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Horse { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Rabbit { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PolarBear { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Llama { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::LlamaSpit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Parrot { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Villager { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::EndCrystal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Turtle { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Phantom { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Trident { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Cod { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Salmon { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Pufferfish { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TropicalFish { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Drowned { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Dolphin { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Cat { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Panda { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Pillager { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Ravager { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::TraderLlama { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WanderingTrader { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Fox { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Bee { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Hoglin { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Piglin { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Strider { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Zoglin { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PiglinBrute { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Axolotl { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::GlowItemFrame { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GlowSquid { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Goat { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Marker { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Allay { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ChestBoat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Frog { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Tadpole { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Warden { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Camel { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BlockDisplay { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Interaction { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemDisplay { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Sniffer { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::TextDisplay { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Breeze { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::WindCharge { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BreezeWindCharge { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Armadillo { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Bogged { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::OminousItemSpawner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FishingBobber { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightningBolt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Player { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Unknown { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for EntityType<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate EntityType from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EntityType")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EntityType object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "ITEM" => Ok(EntityType::Item { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "EXPERIENCE_ORB" => Ok(EntityType::ExperienceOrb { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "AREA_EFFECT_CLOUD" => Ok(EntityType::AreaEffectCloud { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ELDER_GUARDIAN" => Ok(EntityType::ElderGuardian { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "WITHER_SKELETON" => Ok(EntityType::WitherSkeleton { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "STRAY" => Ok(EntityType::Stray { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "EGG" => Ok(EntityType::Egg { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "LEASH_KNOT" => Ok(EntityType::LeashKnot { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "PAINTING" => Ok(EntityType::Painting { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ARROW" => Ok(EntityType::Arrow { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SNOWBALL" => Ok(EntityType::Snowball { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "FIREBALL" => Ok(EntityType::Fireball { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SMALL_FIREBALL" => Ok(EntityType::SmallFireball { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ENDER_PEARL" => Ok(EntityType::EnderPearl { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "EYE_OF_ENDER" => Ok(EntityType::EyeOfEnder { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "POTION" => Ok(EntityType::Potion { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "EXPERIENCE_BOTTLE" => Ok(EntityType::ExperienceBottle { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ITEM_FRAME" => Ok(EntityType::ItemFrame { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "WITHER_SKULL" => Ok(EntityType::WitherSkull { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "TNT" => Ok(EntityType::Tnt { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "FALLING_BLOCK" => Ok(EntityType::FallingBlock { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "FIREWORK_ROCKET" => Ok(EntityType::FireworkRocket { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "HUSK" => Ok(EntityType::Husk { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SPECTRAL_ARROW" => Ok(EntityType::SpectralArrow { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SHULKER_BULLET" => Ok(EntityType::ShulkerBullet { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "DRAGON_FIREBALL" => Ok(EntityType::DragonFireball { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ZOMBIE_VILLAGER" => Ok(EntityType::ZombieVillager { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SKELETON_HORSE" => Ok(EntityType::SkeletonHorse { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ZOMBIE_HORSE" => Ok(EntityType::ZombieHorse { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ARMOR_STAND" => Ok(EntityType::ArmorStand { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "DONKEY" => Ok(EntityType::Donkey { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "MULE" => Ok(EntityType::Mule { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "EVOKER_FANGS" => Ok(EntityType::EvokerFangs { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "EVOKER" => Ok(EntityType::Evoker { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "VEX" => Ok(EntityType::Vex { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "VINDICATOR" => Ok(EntityType::Vindicator { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ILLUSIONER" => Ok(EntityType::Illusioner { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "COMMAND_BLOCK_MINECART" => Ok(EntityType::CommandBlockMinecart { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "BOAT" => Ok(EntityType::Boat { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "MINECART" => Ok(EntityType::Minecart { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "CHEST_MINECART" => Ok(EntityType::ChestMinecart { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "FURNACE_MINECART" => Ok(EntityType::FurnaceMinecart { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "TNT_MINECART" => Ok(EntityType::TntMinecart { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "HOPPER_MINECART" => Ok(EntityType::HopperMinecart { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SPAWNER_MINECART" => Ok(EntityType::SpawnerMinecart { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "CREEPER" => Ok(EntityType::Creeper { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SKELETON" => Ok(EntityType::Skeleton { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SPIDER" => Ok(EntityType::Spider { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "GIANT" => Ok(EntityType::Giant { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ZOMBIE" => Ok(EntityType::Zombie { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SLIME" => Ok(EntityType::Slime { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "GHAST" => Ok(EntityType::Ghast { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ZOMBIFIED_PIGLIN" => Ok(EntityType::ZombifiedPiglin { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ENDERMAN" => Ok(EntityType::Enderman { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "CAVE_SPIDER" => Ok(EntityType::CaveSpider { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SILVERFISH" => Ok(EntityType::Silverfish { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "BLAZE" => Ok(EntityType::Blaze { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "MAGMA_CUBE" => Ok(EntityType::MagmaCube { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ENDER_DRAGON" => Ok(EntityType::EnderDragon { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "WITHER" => Ok(EntityType::Wither { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "BAT" => Ok(EntityType::Bat { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "WITCH" => Ok(EntityType::Witch { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ENDERMITE" => Ok(EntityType::Endermite { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "GUARDIAN" => Ok(EntityType::Guardian { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SHULKER" => Ok(EntityType::Shulker { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "PIG" => Ok(EntityType::Pig { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SHEEP" => Ok(EntityType::Sheep { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "COW" => Ok(EntityType::Cow { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "CHICKEN" => Ok(EntityType::Chicken { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SQUID" => Ok(EntityType::Squid { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "WOLF" => Ok(EntityType::Wolf { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "MOOSHROOM" => Ok(EntityType::Mooshroom { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SNOW_GOLEM" => Ok(EntityType::SnowGolem { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "OCELOT" => Ok(EntityType::Ocelot { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "IRON_GOLEM" => Ok(EntityType::IronGolem { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "HORSE" => Ok(EntityType::Horse { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "RABBIT" => Ok(EntityType::Rabbit { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "POLAR_BEAR" => Ok(EntityType::PolarBear { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "LLAMA" => Ok(EntityType::Llama { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "LLAMA_SPIT" => Ok(EntityType::LlamaSpit { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "PARROT" => Ok(EntityType::Parrot { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "VILLAGER" => Ok(EntityType::Villager { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "END_CRYSTAL" => Ok(EntityType::EndCrystal { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "TURTLE" => Ok(EntityType::Turtle { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "PHANTOM" => Ok(EntityType::Phantom { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "TRIDENT" => Ok(EntityType::Trident { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "COD" => Ok(EntityType::Cod { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SALMON" => Ok(EntityType::Salmon { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "PUFFERFISH" => Ok(EntityType::Pufferfish { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "TROPICAL_FISH" => Ok(EntityType::TropicalFish { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "DROWNED" => Ok(EntityType::Drowned { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "DOLPHIN" => Ok(EntityType::Dolphin { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "CAT" => Ok(EntityType::Cat { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "PANDA" => Ok(EntityType::Panda { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "PILLAGER" => Ok(EntityType::Pillager { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "RAVAGER" => Ok(EntityType::Ravager { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "TRADER_LLAMA" => Ok(EntityType::TraderLlama { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "WANDERING_TRADER" => Ok(EntityType::WanderingTrader { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "FOX" => Ok(EntityType::Fox { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "BEE" => Ok(EntityType::Bee { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "HOGLIN" => Ok(EntityType::Hoglin { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "PIGLIN" => Ok(EntityType::Piglin { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "STRIDER" => Ok(EntityType::Strider { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ZOGLIN" => Ok(EntityType::Zoglin { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "PIGLIN_BRUTE" => Ok(EntityType::PiglinBrute { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "AXOLOTL" => Ok(EntityType::Axolotl { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "GLOW_ITEM_FRAME" => Ok(EntityType::GlowItemFrame { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "GLOW_SQUID" => Ok(EntityType::GlowSquid { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "GOAT" => Ok(EntityType::Goat { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "MARKER" => Ok(EntityType::Marker { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ALLAY" => Ok(EntityType::Allay { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "CHEST_BOAT" => Ok(EntityType::ChestBoat { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "FROG" => Ok(EntityType::Frog { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "TADPOLE" => Ok(EntityType::Tadpole { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "WARDEN" => Ok(EntityType::Warden { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "CAMEL" => Ok(EntityType::Camel { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "BLOCK_DISPLAY" => Ok(EntityType::BlockDisplay { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "INTERACTION" => Ok(EntityType::Interaction { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ITEM_DISPLAY" => Ok(EntityType::ItemDisplay { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "SNIFFER" => Ok(EntityType::Sniffer { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "TEXT_DISPLAY" => Ok(EntityType::TextDisplay { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "BREEZE" => Ok(EntityType::Breeze { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "WIND_CHARGE" => Ok(EntityType::WindCharge { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "BREEZE_WIND_CHARGE" => Ok(EntityType::BreezeWindCharge { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "ARMADILLO" => Ok(EntityType::Armadillo { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "BOGGED" => Ok(EntityType::Bogged { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "OMINOUS_ITEM_SPAWNER" => Ok(EntityType::OminousItemSpawner { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "FISHING_BOBBER" => Ok(EntityType::FishingBobber { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "LIGHTNING_BOLT" => Ok(EntityType::LightningBolt { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "PLAYER" => Ok(EntityType::Player { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(EntityType::Unknown { + inner: EntityTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for EntityTypeStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for EntityTypeStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate EntityTypeStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EntityType")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EntityTypeStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> EntityTypeStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + let cls = jni.find_class("org/bukkit/entity/EntityType"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::EntityType::from_raw(&jni, obj) + } + #[deprecated] + /// Gets the entity type name. + pub fn name(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Gets the {@link Server} that contains this Entity - pub fn server(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Server;"); + + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Server::from_raw(&self.jni_ref(), unsafe { + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns true if the entity gets persisted. - /// - /// By default all entities are persistent. An entity will also not get - /// persisted, if it is riding an entity that is not persistent. - /// - /// The persistent flag on players controls whether or not to save their - /// playerdata file when they quit. If a player is directly or indirectly - /// riding a non-persistent entity, the vehicle at the root and all its - /// passengers won't get persisted. - /// - /// This should not be confused with - /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls - /// despawning of living entities. - pub fn is_persistent(&self) -> Result> { - let sig = String::from("()Z"); + + pub fn entity_class( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/lang/Class;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEntityClass", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(unsafe { + jni::objects::JClass::from_raw(res.as_jni().l) + })) } - /// Sets whether or not the entity gets persisted. - pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(persistent.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPersistent", + #[deprecated] + /// Gets the entity type id. + pub fn type_id(&self) -> Result> { + let sig = String::from("()S"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTypeId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.s()?) + } + #[deprecated] + /// Gets an entity type from its name. + pub fn from_name( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + name: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/entity/EntityType;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(name.into())?, + )); + let cls = jni.find_class("org/bukkit/entity/EntityType"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "fromName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::entity::EntityType::from_raw(&jni, obj)?)) } #[deprecated] - /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. - pub fn passenger( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; + /// Gets an entity from its id. + pub fn from_id( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + id: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/entity/EntityType;"); + let val_1 = jni::objects::JValueGen::Int(id); + let cls = jni.find_class("org/bukkit/entity/EntityType"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "fromId", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + let obj = res.l()?; + Ok(Some(crate::entity::EntityType::from_raw(&jni, obj)?)) } - #[deprecated] - /// Set the passenger of a vehicle. - pub fn set_passenger( + /// Some entities cannot be spawned using {@link + /// World#spawnEntity(Location, EntityType)} or {@link + /// World#spawn(Location, Class)}, usually because they require additional + /// information in order to spawn. + pub fn is_spawnable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isSpawnable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn is_alive(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isAlive", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn translation_key(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTranslationKey", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gets if this EntityType is enabled by feature in a world. + pub fn is_enabled_by_feature( &self, - passenger: impl Into>, + world: impl Into>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let sig = String::from("(Lorg/bukkit/World;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(world.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPassenger", + "isEnabledByFeature", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets a list of passengers of this vehicle. - /// - /// The returned list will not be directly linked to the entity's current - /// passengers, and no guarantees are made as to its mutability. - pub fn passengers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct Display<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Display<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Display<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Display from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Display")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Display object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - Ok(new_vec) } - /// Add a passenger to the vehicle. - pub fn add_passenger( +} + +impl<'mc> Display<'mc> { + /// Gets the transformation applied to this display. + pub fn transformation( &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Transformation;"); let res = self.jni_ref().call_method( &self.jni_object(), - "addPassenger", + "getTransformation", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::util::Transformation::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Remove a passenger from the vehicle. - pub fn remove_passenger( + /// Sets the transformation applied to this display + pub fn set_transformation( &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + transformation: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Transformation;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(transformation.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removePassenger", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Check if a vehicle has passengers. - pub fn is_empty(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Eject any passenger. - pub fn eject(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the distance this entity has fallen - pub fn fall_distance(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Sets the fall distance for this entity - pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(distance); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFallDistance", + "setTransformation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Record the last {@link EntityDamageEvent} inflicted on this entity - pub fn set_last_damage_cause( + /// Sets the raw transformation matrix applied to this display + pub fn set_transformation_matrix( &self, - event: impl Into>, + transformation_matrix: jni::objects::JObject<'mc>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(event.into().jni_object().clone()) - }); + let sig = String::from("(Lorg/joml/Matrix4f;)V"); + let val_1 = jni::objects::JValueGen::Object(transformation_matrix); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDamageCause", + "setTransformationMatrix", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. - /// This event may have been cancelled. - pub fn last_damage_cause( - &self, - ) -> Result>, Box> - { - let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + /// Gets the interpolation duration of this display. + pub fn interpolation_duration(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLastDamageCause", + "getInterpolationDuration", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Returns a unique and persistent id for this entity - pub fn unique_id( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. - pub fn ticks_lived(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. May not be less than one - /// tick. - pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(value); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTicksLived", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Performs the specified {@link EntityEffect} for this entity. - /// - /// This will be viewable to all players near the entity. - /// - /// If the effect is not applicable to this class of entity, it will not play. - pub fn play_effect( + /// Sets the interpolation duration of this display. + pub fn set_interpolation_duration( &self, - val_type: impl Into>, + duration: i32, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(duration); let res = self.jni_ref().call_method( &self.jni_object(), - "playEffect", + "setInterpolationDuration", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the type of the entity. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity makes while swimming. - pub fn swim_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity makes when splashing in water. For most - /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_splash_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Gets the teleport duration of this display. + ///
    + ///
  • 0 means that updates are applied immediately.
  • + ///
  • 1 means that the display entity will move from current position to the updated one over one tick.
  • + ///
  • Higher values spread the movement over multiple ticks.
  • + ///
+ pub fn teleport_duration(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimSplashSound", + "getTeleportDuration", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Get the {@link Sound} this entity makes when splashing in water at high - /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_high_speed_splash_sound( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Sets the teleport duration of this display. + pub fn set_teleport_duration(&self, duration: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(duration); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimHighSpeedSplashSound", + "setTeleportDuration", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns whether this entity is inside a vehicle. - pub fn is_inside_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Leave the current vehicle. If the entity is currently in a vehicle (and - /// is removed from it), true will be returned, otherwise false will be - /// returned. - pub fn leave_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the vehicle that this entity is inside. If there is no vehicle, - /// null will be returned. - pub fn vehicle( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + /// Gets the view distance/range of this display. + pub fn view_range(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getViewRange", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.f()?) } - /// Sets whether or not to display the mob's custom name client side. The - /// name will be displayed above the mob similarly to a player. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Sets the view distance/range of this display. + pub fn set_view_range(&self, range: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(range); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomNameVisible", + "setViewRange", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not the mob's custom name is displayed client side. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn is_custom_name_visible(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isCustomNameVisible", - sig.as_str(), - vec![], - ); + /// Gets the shadow radius of this display. + pub fn shadow_radius(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getShadowRadius", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.f()?) } - /// Sets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(visible.into()); + /// Sets the shadow radius of this display. + pub fn set_shadow_radius(&self, radius: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(radius); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisibleByDefault", + "setShadowRadius", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn is_visible_by_default(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the shadow strength of this display. + pub fn shadow_strength(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref().call_method( &self.jni_object(), - "isVisibleByDefault", + "getShadowStrength", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get all players that are currently tracking this entity. - /// - /// 'Tracking' means that this entity has been sent to the player and that - /// they are receiving updates on its state. Note that the client's {@code - /// 'Entity Distance'} setting does not affect the range at which entities - /// are tracked. - pub fn tracked_by( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.f()?) } - /// Sets whether the entity has a team colored (default: white) glow. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Sets the shadow strength of this display. + pub fn set_shadow_strength(&self, strength: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(strength); let res = self.jni_ref().call_method( &self.jni_object(), - "setGlowing", + "setShadowStrength", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is glowing or not. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn is_glowing(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); + /// Gets the width of this display. + pub fn display_width(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDisplayWidth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.f()?) } - /// Sets whether the entity is invulnerable or not. - /// - /// When an entity is invulnerable it can only be damaged by players in - /// creative mode. - pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Sets the width of this display. + pub fn set_display_width(&self, width: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(width); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvulnerable", + "setDisplayWidth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invulnerable or not. - pub fn is_invulnerable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets whether the entity is silent or not. - pub fn is_silent(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether the entity is silent or not. - /// - /// When an entity is silent it will not produce any sound. - pub fn set_silent(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Gets the height of this display. + pub fn display_height(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref().call_method( &self.jni_object(), - "setSilent", + "getDisplayHeight", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns whether gravity applies to this entity. - pub fn has_gravity(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.f()?) } - /// Sets whether gravity applies to this entity. - pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gravity.into()); + /// Sets the height if this display. + pub fn set_display_height(&self, height: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(height); let res = self.jni_ref().call_method( &self.jni_object(), - "setGravity", + "setDisplayHeight", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the period of time (in ticks) before this entity can use a portal. - pub fn portal_cooldown(&self) -> Result> { + /// Gets the amount of ticks before client-side interpolation will commence. + pub fn interpolation_delay(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPortalCooldown", + "getInterpolationDelay", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the period of time (in ticks) before this entity can use a portal. - pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { + /// Sets the amount of ticks before client-side interpolation will commence. + pub fn set_interpolation_delay(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(cooldown); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setPortalCooldown", + "setInterpolationDelay", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a set of tags for this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn scoreboard_tags( + /// Gets the billboard setting of this entity. + /// The billboard setting controls the automatic rotation of the entity to + /// face the player. + pub fn billboard( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getScoreboardTags", - sig.as_str(), - vec![], - ); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Display/Billboard;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBillboard", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + crate::entity::DisplayBillboard::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Add a tag to this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn add_scoreboard_tag( - &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addScoreboardTag", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Removes a given tag from this entity. - pub fn remove_scoreboard_tag( + /// Sets the billboard setting of this entity. + /// The billboard setting controls the automatic rotation of the entity to + /// face the player. + pub fn set_billboard( &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); + billboard: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Display/Billboard;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(billboard.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeScoreboardTag", + "setBillboard", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns the reaction of the entity when moved by a piston. - pub fn piston_move_reaction( + /// Gets the scoreboard team overridden glow color of this display. + pub fn glow_color_override( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Color;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPistonMoveReaction", + "getGlowColorOverride", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the closest cardinal {@link BlockFace} direction an entity is - /// currently facing. - /// - /// This will not return any non-cardinal directions such as - /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. - /// - /// {@link Hanging} entities will override this call and thus their behavior - /// may be different. - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the entity's current pose. - /// Note that the pose is only updated at the end of a tick, so may be - /// inconsistent with other methods. eg {@link Player#isSneaking()} being - /// true does not imply the current pose will be {@link Pose#SNEAKING} - pub fn pose(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Pose;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Color::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) + })?)) } - /// Get the category of spawn to which this entity belongs. - pub fn spawn_category( + /// Sets the scoreboard team overridden glow color of this display. + pub fn set_glow_color_override( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); + color: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Color;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(color.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getSpawnCategory", + "setGlowColorOverride", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Checks if this entity has been spawned in a world. - /// - /// Entities not spawned in a world will not tick, be sent to players, or be - /// saved to the server files. - pub fn is_in_world(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get this entity as an NBT string. - /// - /// This string should not be relied upon as a serializable value. - pub fn as_string(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Crates an {@link EntitySnapshot} representing the current state of this entity. - pub fn create_snapshot( + /// Gets the brightness override of the entity. + pub fn brightness( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Display/Brightness;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBrightness", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::EntitySnapshot::from_raw( + Ok(Some(crate::entity::DisplayBrightness::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Creates a copy of this entity and all its data. Spawns the copy at the given location. - /// - /// Note: Players cannot be copied. - pub fn copy( + /// Sets the brightness override of the entity. + pub fn set_brightness( &self, - to: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = to { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")Lorg/bukkit/entity/Entity;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for OminousItemSpawner<'mc> { - fn into(self) -> crate::entity::Entity<'mc> { - crate::entity::Entity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting OminousItemSpawner into crate::entity::Entity") - } -} -#[repr(C)] -pub struct WindCharge<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for WindCharge<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for WindCharge<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate WindCharge from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/WindCharge")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a WindCharge object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> WindCharge<'mc> { - /// Immediately explode this WindCharge. - pub fn explode(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "explode", sig.as_str(), vec![]); + brightness: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Display/Brightness;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(brightness.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBrightness", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for WindCharge<'mc> { - fn into(self) -> crate::entity::AbstractWindCharge<'mc> { - crate::entity::AbstractWindCharge::from_raw(&self.jni_ref(), self.1) - .expect("Error converting WindCharge into crate::entity::AbstractWindCharge") - } -} -#[repr(C)] -pub struct Breeze<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Breeze<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Breeze<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Breeze from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Breeze")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Breeze object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Breeze<'mc> { - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Breeze<'mc> { - fn into(self) -> crate::entity::Monster<'mc> { - crate::entity::Monster::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Breeze into crate::entity::Monster") - } -} -#[repr(C)] -pub struct AbstractArrow<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for AbstractArrow<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for AbstractArrow<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate AbstractArrow from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/AbstractArrow")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a AbstractArrow object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> AbstractArrow<'mc> { - /// Gets the knockback strength for an arrow, which is the - /// {@link org.bukkit.enchantments.Enchantment#KNOCKBACK KnockBack} level - /// of the bow that shot it. - pub fn knockback_strength(&self) -> Result> { - let sig = String::from("()I"); + /// Stores the entity's current position in the provided Location object. + /// + /// If the provided Location is null this method does nothing and returns + /// null. + pub fn get_location( + &self, + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getKnockbackStrength", + "getLocation", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Sets the knockback strength for an arrow. - pub fn set_knockback_strength( + /// Sets this entity's velocity in meters per tick + pub fn set_velocity( &self, - knockback_strength: i32, + velocity: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(knockback_strength); + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setKnockbackStrength", + "setVelocity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the base amount of damage this arrow will do. - /// Defaults to 2.0 for a normal arrow with - /// 0.5 * (1 + power level) added for arrows fired from - /// enchanted bows. - pub fn damage(&self) -> Result> { + /// Gets this entity's current velocity + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the entity's height + pub fn height(&self) -> Result> { let sig = String::from("()D"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getDamage", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.d()?) } - /// Sets the base amount of damage this arrow will do. - pub fn set_damage(&self, damage: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(damage); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setDamage", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Gets the entity's width + pub fn width(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } - /// Gets the number of times this arrow can pierce through an entity. - pub fn pierce_level(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the entity's current bounding box. + /// + /// The returned bounding box reflects the entity's current location and + /// size. + pub fn bounding_box( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPierceLevel", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the number of times this arrow can pierce through an entity. - /// Must be between 0 and 127 times. - pub fn set_pierce_level(&self, pierce_level: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(pierce_level); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPierceLevel", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets whether this arrow is critical. - /// - /// Critical arrows have increased damage and cause particle effects. - /// - /// Critical arrows generally occur when a player fully draws a bow before - /// firing. - pub fn is_critical(&self) -> Result> { + /// Returns true if the entity is supported by a block. This value is a + /// state updated by the server and is not recalculated unless the entity + /// moves. + pub fn is_on_ground(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCritical", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not this arrow should be critical. - pub fn set_critical(&self, critical: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(critical.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCritical", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether this arrow is in a block or not. - /// - /// Arrows in a block are motionless and may be picked up by players. - pub fn is_in_block(&self) -> Result> { + /// Returns true if the entity is in water. + pub fn is_in_water(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isInBlock", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the block to which this arrow is attached. - pub fn attached_block( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAttachedBlock", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::block::Block::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Gets the current pickup status of this arrow. - pub fn pickup_status( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/AbstractArrow/PickupStatus;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPickupStatus", sig.as_str(), vec![]); + /// Gets the current world this entity resides in + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::AbstractArrowPickupStatus::from_raw(&self.jni_ref(), unsafe { + crate::World::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the current pickup status of this arrow. - pub fn set_pickup_status( + /// Sets the entity's rotation. + /// + /// Note that if the entity is affected by AI, it may override this rotation. + pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { + let sig = String::from("(FF)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); + let val_2 = jni::objects::JValueGen::Float(pitch); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRotation", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Teleports this entity to the given location. If this entity is riding a + /// vehicle, it will be dismounted prior to teleportation. + pub fn teleport( &self, - status: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/AbstractArrow/PickupStatus;)V"); + location: impl Into>, + cause: std::option::Option< + impl Into>, + >, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(status.into().jni_object().clone()) + jni::objects::JObject::from_raw(location.into().jni_object().clone()) }); + args.push(val_1); + if let Some(a) = cause { + sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "teleport", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns a list of entities within a bounding box centered around this + /// entity + pub fn get_nearby_entities( + &self, + x: f64, + y: f64, + z: f64, + ) -> Result>, Box> { + let sig = String::from("(DDD)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Double(x); + let val_2 = jni::objects::JValueGen::Double(y); + let val_3 = jni::objects::JValueGen::Double(z); let res = self.jni_ref().call_method( &self.jni_object(), - "setPickupStatus", + "getNearbyEntities", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Returns a unique id for this entity + pub fn entity_id(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's maximum fire ticks. + pub fn max_fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFireTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if this arrow was shot from a crossbow. - pub fn is_shot_from_crossbow(&self) -> Result> { + /// Sets if the entity has visual fire (it will always appear to be on fire). + pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVisualFire", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the entity has visual fire (it will always appear to be on fire). + pub fn is_visual_fire(&self) -> Result> { let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's maximum freeze ticks (amount of ticks before it will + /// be fully frozen) + pub fn max_freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "isShotFromCrossbow", + "getMaxFreezeTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets if this arrow was shot from a crossbow. - pub fn set_shot_from_crossbow( - &self, - shot_from_crossbow: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(shot_from_crossbow.into()); + /// Sets the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setShotFromCrossbow", + "setFreezeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the ItemStack which will be picked up from this arrow. - pub fn item(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + /// Gets if the entity is fully frozen (it has been in powdered snow for max + /// freeze ticks). + pub fn is_frozen(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + Ok(res.z()?) + } + /// Mark the entity's removal. + pub fn remove(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns true if this entity has been marked for removal. + pub fn is_dead(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns false if the entity has died, been despawned for some other + /// reason, or has not been added to the world. + pub fn is_valid(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the {@link Server} that contains this Entity + pub fn server(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Server;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Server::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the ItemStack which will be picked up from this arrow. - pub fn set_item( - &self, - item: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); + /// Returns true if the entity gets persisted. + /// + /// By default all entities are persistent. An entity will also not get + /// persisted, if it is riding an entity that is not persistent. + /// + /// The persistent flag on players controls whether or not to save their + /// playerdata file when they quit. If a player is directly or indirectly + /// riding a non-persistent entity, the vehicle at the root and all its + /// passengers won't get persisted. + /// + /// This should not be confused with + /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls + /// despawning of living entities. + pub fn is_persistent(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether or not the entity gets persisted. + pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(persistent.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setItem", + "setPersistent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the shooter of this projectile. - pub fn shooter( + #[deprecated] + /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. + pub fn passenger( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/projectiles/ProjectileSource;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getShooter", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::projectiles::ProjectileSource::from_raw( + Ok(Some(crate::entity::Entity::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Set the shooter of this projectile. - pub fn set_shooter( + #[deprecated] + /// Set the passenger of a vehicle. + pub fn set_passenger( &self, - source: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/projectiles/ProjectileSource;)V"); + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(source.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setShooter", + "setPassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - #[deprecated] - /// Determine if this projectile should bounce or not when it hits. - pub fn does_bounce(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets a list of passengers of this vehicle. + /// + /// The returned list will not be directly linked to the entity's current + /// passengers, and no guarantees are made as to its mutability. + pub fn passengers( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "doesBounce", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Add a passenger to the vehicle. + pub fn add_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addPassenger", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Set whether or not this projectile should bounce or not when it hits something. - pub fn set_bounce(&self, does_bounce: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(does_bounce.into()); + /// Remove a passenger from the vehicle. + pub fn remove_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBounce", + "removePassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + /// Check if a vehicle has passengers. + pub fn is_empty(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> Into> for AbstractArrow<'mc> { - fn into(self) -> crate::entity::Projectile<'mc> { - crate::entity::Projectile::from_raw(&self.jni_ref(), self.1) - .expect("Error converting AbstractArrow into crate::entity::Projectile") + /// Eject any passenger. + pub fn eject(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -pub enum AbstractArrowPickupStatus<'mc> {} -impl<'mc> std::fmt::Display for AbstractArrowPickupStatus<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + /// Returns the distance this entity has fallen + pub fn fall_distance(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) } -} - -impl<'mc> AbstractArrowPickupStatus<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/AbstractArrow/PickupStatus"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/AbstractArrow/PickupStatus;", + /// Sets the fall distance for this entity + pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(distance); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFallDistance", + sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct AbstractArrowPickupStatusStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for AbstractArrowPickupStatus<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + self.jni_ref().translate_error(res)?; + Ok(()) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + #[deprecated] + /// Record the last {@link EntityDamageEvent} inflicted on this entity + pub fn set_last_damage_cause( + &self, + event: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(event.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLastDamageCause", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -impl<'mc> JNIInstantiatable<'mc> for AbstractArrowPickupStatus<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate AbstractArrowPickupStatus from null object." - ) - .into()); + /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. + /// This event may have been cancelled. + pub fn last_damage_cause( + &self, + ) -> Result>, Box> + { + let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLastDamageCause", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/entity/AbstractArrow/PickupStatus")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a AbstractArrowPickupStatus object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for AbstractArrowPickupStatusStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for AbstractArrowPickupStatusStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate AbstractArrowPickupStatusStruct from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/entity/AbstractArrow/PickupStatus")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a AbstractArrowPickupStatusStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> AbstractArrowPickupStatusStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/AbstractArrow/PickupStatus;"); - let cls = jni.find_class("org/bukkit/entity/AbstractArrow/PickupStatus"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::AbstractArrowPickupStatus::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct BreezeWindCharge<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for BreezeWindCharge<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for BreezeWindCharge<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate BreezeWindCharge from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/BreezeWindCharge")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a BreezeWindCharge object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> BreezeWindCharge<'mc> { - /// Immediately explode this WindCharge. - pub fn explode(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "explode", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for BreezeWindCharge<'mc> { - fn into(self) -> crate::entity::AbstractWindCharge<'mc> { - crate::entity::AbstractWindCharge::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BreezeWindCharge into crate::entity::AbstractWindCharge") - } -} -#[repr(C)] -pub struct AbstractWindCharge<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for AbstractWindCharge<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Returns a unique and persistent id for this entity + pub fn unique_id( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> JNIInstantiatable<'mc> for AbstractWindCharge<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate AbstractWindCharge from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/AbstractWindCharge")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a AbstractWindCharge object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Gets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. + pub fn ticks_lived(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} - -impl<'mc> AbstractWindCharge<'mc> { - /// Immediately explode this WindCharge. - pub fn explode(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "explode", sig.as_str(), vec![]); + /// Sets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. May not be less than one + /// tick. + pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTicksLived", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets the direction the fireball should be flying towards. - /// - /// This is a convenience method, it will change the velocity direction and - /// acceleration direction, while keeping the power the same. + /// Performs the specified {@link EntityEffect} for this entity. /// - /// Note: This method only uses the direction of the vector and will - /// normalize (a copy of) it. + /// This will be viewable to all players near the entity. /// - /// Special Case: When the given direction is - /// {@link Vector#isZero() zero}, the velocity and acceleration will also be - /// set to zero without keeping the power. - pub fn set_direction( + /// If the effect is not applicable to this class of entity, it will not play. + pub fn play_effect( &self, - direction: impl Into>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(direction.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setDirection", + "playEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Retrieve the direction this fireball is heading toward. The returned vector is not normalized. - pub fn direction(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); + /// Get the type of the entity. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes while swimming. + pub fn swim_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the acceleration of the fireball. - /// The acceleration gets applied to the velocity every tick, depending on - /// the specific type of the fireball a damping / drag factor is applied so - /// that the velocity does not grow into infinity. - /// - /// Note: that the client may not respect non-default acceleration - /// power and will therefore mispredict the location of the fireball, causing - /// visual stutter. - pub fn set_acceleration( - &self, - acceleration: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(acceleration.into().jni_object().clone()) - }); + /// Get the {@link Sound} this entity makes when splashing in water. For most + /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_splash_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setAcceleration", + "getSwimSplashSound", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Retrieve the acceleration of this fireball. - pub fn acceleration(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAcceleration", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for AbstractWindCharge<'mc> { - fn into(self) -> crate::entity::Fireball<'mc> { - crate::entity::Fireball::from_raw(&self.jni_ref(), self.1) - .expect("Error converting AbstractWindCharge into crate::entity::Fireball") - } -} -#[repr(C)] -pub struct Player<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Player<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Get the {@link Sound} this entity makes when splashing in water at high + /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_high_speed_splash_sound( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSwimHighSpeedSplashSound", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Returns whether this entity is inside a vehicle. + pub fn is_inside_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for Player<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Player from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Player")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Player object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Leave the current vehicle. If the entity is currently in a vehicle (and + /// is removed from it), true will be returned, otherwise false will be + /// returned. + pub fn leave_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} - -impl<'mc> Player<'mc> { - /// Gets the "friendly" name to display of this player. This may include - /// color. - /// - /// Note that this name will not be displayed in game, only in chat and - /// places defined by plugins. - pub fn display_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Get the vehicle that this entity is inside. If there is no vehicle, + /// null will be returned. + pub fn vehicle( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDisplayName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the "friendly" name to display of this player. This may include - /// color. + /// Sets whether or not to display the mob's custom name client side. The + /// name will be displayed above the mob similarly to a player. /// - /// Note that this name will not be displayed in game, only in chat and - /// places defined by plugins. - pub fn set_display_name( - &self, - name: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + /// This value has no effect on players, they will always display their + /// name. + pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setDisplayName", + "setCustomNameVisible", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the name that is shown on the player list. - pub fn player_list_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Gets whether or not the mob's custom name is displayed client side. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn is_custom_name_visible(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPlayerListName", + "isCustomNameVisible", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - /// Sets the name that is shown on the in-game player list. - /// - /// If the value is null, the name will be identical to {@link #getName()}. - pub fn set_player_list_name( - &self, - name: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + /// Sets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(visible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setPlayerListName", + "setVisibleByDefault", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the currently displayed player list header for this player. - pub fn player_list_header(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); + /// Gets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn is_visible_by_default(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPlayerListHeader", + "isVisibleByDefault", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( + Ok(res.z()?) + } + /// Get all players that are currently tracking this entity. + /// + /// 'Tracking' means that this entity has been sent to the player and that + /// they are receiving updates on its state. Note that the client's {@code + /// 'Entity Distance'} setting does not affect the range at which entities + /// are tracked. + pub fn tracked_by( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the currently displayed player list footer for this player. - pub fn player_list_footer(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); + /// Sets whether the entity has a team colored (default: white) glow. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getPlayerListFooter", + "setGlowing", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the currently displayed player list header for this player. - pub fn set_player_list_header( - &self, - header: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(header.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPlayerListHeader", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Gets whether the entity is glowing or not. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn is_glowing(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Sets the currently displayed player list footer for this player. - pub fn set_player_list_footer( - &self, - footer: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(footer.into())?, - )); + /// Sets whether the entity is invulnerable or not. + /// + /// When an entity is invulnerable it can only be damaged by players in + /// creative mode. + pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setPlayerListFooter", + "setInvulnerable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets the currently displayed player list header and footer for this - /// player. - pub fn set_player_list_header_footer( - &self, - header: impl Into, - footer: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(header.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(footer.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPlayerListHeaderFooter", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Gets whether the entity is invulnerable or not. + pub fn is_invulnerable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Set the target of the player's compass. - pub fn set_compass_target( - &self, - loc: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Location;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) - }); + /// Gets whether the entity is silent or not. + pub fn is_silent(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the entity is silent or not. + /// + /// When an entity is silent it will not produce any sound. + pub fn set_silent(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCompassTarget", + "setSilent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the previously set compass target. - pub fn compass_target(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCompassTarget", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the socket address of this player - pub fn address( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/net/InetSocketAddress;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAddress", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(res.l()?)) - } - /// Gets if this connection has been transferred from another server. - pub fn is_transferred(&self) -> Result> { + /// Returns whether gravity applies to this entity. + pub fn has_gravity(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isTransferred", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Stores a cookie in this player's client. - pub fn store_cookie( - &self, - key: impl Into>, - value: i8, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;B)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Byte(value); + /// Sets whether gravity applies to this entity. + pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gravity.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "storeCookie", + "setGravity", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Requests this player to connect to a different server specified by host - /// and port. - pub fn transfer( - &self, - host: impl Into, - port: i32, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;I)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(host.into())?, - )); - let val_2 = jni::objects::JValueGen::Int(port); + /// Gets the period of time (in ticks) before this entity can use a portal. + pub fn portal_cooldown(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "transfer", + "getPortalCooldown", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Sends this sender a message raw - pub fn send_raw_message( - &self, - message: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(message.into())?, - )); + /// Sets the period of time (in ticks) before this entity can use a portal. + pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(cooldown); let res = self.jni_ref().call_method( &self.jni_object(), - "sendRawMessage", + "setPortalCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Kicks player with custom kick message. - pub fn kick_player( + /// Returns a set of tags for this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn scoreboard_tags( &self, - message: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(message.into())?, - )); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref().call_method( &self.jni_object(), - "kickPlayer", + "getScoreboardTags", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Adds this user to the {@link ProfileBanList}. If a previous ban exists, this will - /// update the entry. - pub fn ban( - &self, - reason: impl Into, - duration: jni::objects::JObject<'mc>, - source: impl Into, - kick_player: std::option::Option, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(reason.into())?, - )); - args.push(val_1); - sig += "Ljava/time/Duration;"; - let val_2 = jni::objects::JValueGen::Object(duration); - args.push(val_2); - sig += "Ljava/lang/String;"; - let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(source.into())?, - )); - args.push(val_3); - if let Some(a) = kick_player { - sig += "Z"; - let val_4 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_4); - } - sig += ")Lorg/bukkit/BanEntry;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "ban", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::BanEntry::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + }) } - /// Adds this user's current IP address to the {@link IpBanList}. If a previous ban exists, this will - /// update the entry. If {@link #getAddress()} is null this method will throw an exception. - pub fn ban_ip( + /// Add a tag to this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn add_scoreboard_tag( &self, - reason: impl Into, - duration: jni::objects::JObject<'mc>, - source: impl Into, - kick_player: bool, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(reason.into())?, - )); - args.push(val_1); - sig += "Ljava/time/Duration;"; - let val_2 = jni::objects::JValueGen::Object(duration); - args.push(val_2); - sig += "Ljava/lang/String;"; - let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(source.into())?, - )); - args.push(val_3); - sig += "Z"; - let val_4 = jni::objects::JValueGen::Bool(kick_player.into()); - args.push(val_4); - sig += ")Lorg/bukkit/BanEntry;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "banIp", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::BanEntry::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Says a message (or runs a command). - pub fn chat(&self, msg: impl Into) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(msg.into())?, + self.jni_ref().new_string(tag.into())?, )); let res = self.jni_ref().call_method( &self.jni_object(), - "chat", + "addScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Makes the player perform the given command - pub fn perform_command( + /// Removes a given tag from this entity. + pub fn remove_scoreboard_tag( &self, - command: impl Into, + tag: impl Into, ) -> Result> { let sig = String::from("(Ljava/lang/String;)Z"); let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(command.into())?, + self.jni_ref().new_string(tag.into())?, )); let res = self.jni_ref().call_method( &self.jni_object(), - "performCommand", + "removeScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Returns true if the entity is supported by a block. This value is a state updated by the client after each movement. - pub fn is_on_ground(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns if the player is in sneak mode - pub fn is_sneaking(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isSneaking", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets the sneak mode the player - pub fn set_sneaking(&self, sneak: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(sneak.into()); + /// Returns the reaction of the entity when moved by a piston. + pub fn piston_move_reaction( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setSneaking", + "getPistonMoveReaction", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether the player is sprinting or not. - pub fn is_sprinting(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isSprinting", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether the player is sprinting or not. - pub fn set_sprinting(&self, sprinting: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(sprinting.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSprinting", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Saves the players current location, health, inventory, motion, and - /// other information into the username.dat file, in the world/player - /// folder - pub fn save_data(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Get the closest cardinal {@link BlockFace} direction an entity is + /// currently facing. + /// + /// This will not return any non-cardinal directions such as + /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// + /// {@link Hanging} entities will override this call and thus their behavior + /// may be different. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "saveData", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Loads the players current location, health, inventory, motion, and - /// other information from the username.dat file, in the world/player - /// folder. - /// - /// Note: This will overwrite the players current inventory, health, - /// motion, etc, with the state from the saved dat file. - pub fn load_data(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Gets the entity's current pose. + /// Note that the pose is only updated at the end of a tick, so may be + /// inconsistent with other methods. eg {@link Player#isSneaking()} being + /// true does not imply the current pose will be {@link Pose#SNEAKING} + pub fn pose(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Pose;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "loadData", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets whether the player is ignored as not sleeping. If everyone is - /// either sleeping or has this flag set, then time will advance to the - /// next day. If everyone has this flag set but no one is actually in bed, - /// then nothing will happen. - pub fn set_sleeping_ignored( + /// Get the category of spawn to which this entity belongs. + pub fn spawn_category( &self, - is_sleeping: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(is_sleeping.into()); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setSleepingIgnored", + "getSpawnCategory", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns whether the player is sleeping ignored. - pub fn is_sleeping_ignored(&self) -> Result> { + /// Checks if this entity has been spawned in a world. + /// + /// Entities not spawned in a world will not tick, be sent to players, or be + /// saved to the server files. + pub fn is_in_world(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isSleepingIgnored", - sig.as_str(), - vec![], - ); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Gets the Location where the player will spawn at their bed, null if they have not slept in one or their current bed spawn is invalid. - pub fn bed_spawn_location( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getBedSpawnLocation", - sig.as_str(), - vec![], - ); + /// Get this entity as an NBT string. + /// + /// This string should not be relied upon as a serializable value. + pub fn as_string(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Gets the Location where the player will spawn at, null if they - /// don't have a valid respawn point. - pub fn respawn_location( + /// Crates an {@link EntitySnapshot} representing the current state of this entity. + pub fn create_snapshot( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getRespawnLocation", - sig.as_str(), - vec![], - ); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) + Ok(Some(crate::entity::EntitySnapshot::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// + /// Note: Players cannot be copied. + pub fn copy( + &self, + to: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = to { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Lorg/bukkit/entity/Entity;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Display<'mc> { + fn into(self) -> crate::entity::Entity<'mc> { + crate::entity::Entity::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Display into crate::entity::Entity") + } +} +pub enum DisplayBillboard<'mc> { + Fixed { inner: DisplayBillboardStruct<'mc> }, + Vertical { inner: DisplayBillboardStruct<'mc> }, + Horizontal { inner: DisplayBillboardStruct<'mc> }, + Center { inner: DisplayBillboardStruct<'mc> }, +} +impl<'mc> std::fmt::Display for DisplayBillboard<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + DisplayBillboard::Fixed { .. } => f.write_str("FIXED"), + DisplayBillboard::Vertical { .. } => f.write_str("VERTICAL"), + DisplayBillboard::Horizontal { .. } => f.write_str("HORIZONTAL"), + DisplayBillboard::Center { .. } => f.write_str("CENTER"), + } + } +} +impl<'mc> std::ops::Deref for DisplayBillboard<'mc> { + type Target = DisplayBillboardStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + DisplayBillboard::Fixed { inner } => inner, + DisplayBillboard::Vertical { inner } => inner, + DisplayBillboard::Horizontal { inner } => inner, + DisplayBillboard::Center { inner } => inner, + } + } +} + +impl<'mc> DisplayBillboard<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/Display/Billboard"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/Display/Billboard;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "FIXED" => Ok(DisplayBillboard::Fixed { + inner: DisplayBillboardStruct::from_raw(env, obj)?, + }), + "VERTICAL" => Ok(DisplayBillboard::Vertical { + inner: DisplayBillboardStruct::from_raw(env, obj)?, + }), + "HORIZONTAL" => Ok(DisplayBillboard::Horizontal { + inner: DisplayBillboardStruct::from_raw(env, obj)?, + }), + "CENTER" => Ok(DisplayBillboard::Center { + inner: DisplayBillboardStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct DisplayBillboardStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for DisplayBillboard<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Fixed { inner } => inner.0.clone(), + Self::Vertical { inner } => inner.0.clone(), + Self::Horizontal { inner } => inner.0.clone(), + Self::Center { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Fixed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Vertical { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Horizontal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Center { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for DisplayBillboard<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate DisplayBillboard from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Display/Billboard")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a DisplayBillboard object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "FIXED" => Ok(DisplayBillboard::Fixed { + inner: DisplayBillboardStruct::from_raw(env, obj)?, + }), + "VERTICAL" => Ok(DisplayBillboard::Vertical { + inner: DisplayBillboardStruct::from_raw(env, obj)?, + }), + "HORIZONTAL" => Ok(DisplayBillboard::Horizontal { + inner: DisplayBillboardStruct::from_raw(env, obj)?, + }), + "CENTER" => Ok(DisplayBillboard::Center { + inner: DisplayBillboardStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for DisplayBillboardStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for DisplayBillboardStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate DisplayBillboardStruct from null object." + ) + .into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Display/Billboard")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a DisplayBillboardStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> DisplayBillboardStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Display/Billboard;"); + let cls = jni.find_class("org/bukkit/entity/Display/Billboard"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::DisplayBillboard::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct DisplayBrightness<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for DisplayBrightness<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for DisplayBrightness<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate DisplayBrightness from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Display/Brightness")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a DisplayBrightness object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> DisplayBrightness<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + block_light: i32, + sky_light: i32, + ) -> Result, Box> { + let sig = String::from("(II)V"); + let val_1 = jni::objects::JValueGen::Int(block_light); + let val_2 = jni::objects::JValueGen::Int(sky_light); + let cls = jni.find_class("org/bukkit/entity/Display/Brightness"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::entity::DisplayBrightness::from_raw(&jni, res) + } + /// Gets the block lighting component of this brightness. + pub fn block_light(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBlockLight", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the sky lighting component of this brightness. + pub fn sky_light(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSkyLight", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + + pub fn hash_code(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + + pub fn equals( + &self, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(Ljava/lang/Object;)Z"); + let val_1 = jni::objects::JValueGen::Object(obj); + let res = self.jni_ref().call_method( + &self.jni_object(), + "equals", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} + +impl<'mc> std::string::ToString for DisplayBrightness<'mc> { + fn to_string(&self) -> String { + match &self.internal_to_string() { + Ok(a) => a.clone(), + Err(err) => format!("Error calling DisplayBrightness.toString: {}", err), + } + } +} + +#[repr(C)] +pub struct Boat<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Boat<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Boat<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Boat from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Boat")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Boat object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Boat<'mc> { + #[deprecated] + /// Gets the wood type of the boat. + pub fn wood_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/TreeSpecies;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getWoodType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::TreeSpecies::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + #[deprecated] + /// Sets the wood type of the boat. + pub fn set_wood_type( + &self, + species: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/TreeSpecies;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(species.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setWoodType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the type of the boat. + pub fn boat_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Boat/Type;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBoatType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::BoatType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the type of the boat. + pub fn set_boat_type( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Boat/Type;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBoatType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the maximum speed of a boat. The speed is unrelated to the velocity. + pub fn max_speed(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxSpeed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + #[deprecated] + /// Sets the maximum speed of a boat. Must be nonnegative. Default is 0.4D. + pub fn set_max_speed(&self, speed: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(speed); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaxSpeed", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the deceleration rate (newSpeed = curSpeed * rate) of occupied boats. The default is 0.2. + pub fn occupied_deceleration(&self) -> Result> { + let sig = String::from("()D"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getOccupiedDeceleration", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + #[deprecated] + /// Sets the deceleration rate (newSpeed = curSpeed * rate) of occupied boats. Setting this to a higher value allows for quicker acceleration. The default is 0.2. + pub fn set_occupied_deceleration(&self, rate: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(rate); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setOccupiedDeceleration", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the deceleration rate (newSpeed = curSpeed * rate) of unoccupied boats. The default is -1. Values below 0 indicate that no additional deceleration is imposed. + pub fn unoccupied_deceleration(&self) -> Result> { + let sig = String::from("()D"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getUnoccupiedDeceleration", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + #[deprecated] + /// Sets the deceleration rate (newSpeed = curSpeed * rate) of unoccupied boats. Setting this to a higher value allows for quicker deceleration of boats when a player disembarks. The default is -1. Values below 0 indicate that no additional deceleration is imposed. + pub fn set_unoccupied_deceleration(&self, rate: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(rate); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setUnoccupiedDeceleration", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Get whether boats can work on land. + pub fn work_on_land(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getWorkOnLand", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Set whether boats can work on land. + pub fn set_work_on_land(&self, work_on_land: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(work_on_land.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setWorkOnLand", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the status of the boat. + pub fn status(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Boat/Status;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getStatus", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::BoatStatus::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the vehicle's velocity. + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the vehicle's velocity in meters per tick. + pub fn set_velocity( + &self, + vel: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(vel.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVelocity", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Boat<'mc> { + fn into(self) -> crate::entity::Vehicle<'mc> { + crate::entity::Vehicle::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Boat into crate::entity::Vehicle") + } +} +pub enum BoatType<'mc> { + Oak { inner: BoatTypeStruct<'mc> }, + Spruce { inner: BoatTypeStruct<'mc> }, + Birch { inner: BoatTypeStruct<'mc> }, + Jungle { inner: BoatTypeStruct<'mc> }, + Acacia { inner: BoatTypeStruct<'mc> }, + Cherry { inner: BoatTypeStruct<'mc> }, + DarkOak { inner: BoatTypeStruct<'mc> }, + Mangrove { inner: BoatTypeStruct<'mc> }, + Bamboo { inner: BoatTypeStruct<'mc> }, +} +impl<'mc> std::fmt::Display for BoatType<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + BoatType::Oak { .. } => f.write_str("OAK"), + BoatType::Spruce { .. } => f.write_str("SPRUCE"), + BoatType::Birch { .. } => f.write_str("BIRCH"), + BoatType::Jungle { .. } => f.write_str("JUNGLE"), + BoatType::Acacia { .. } => f.write_str("ACACIA"), + BoatType::Cherry { .. } => f.write_str("CHERRY"), + BoatType::DarkOak { .. } => f.write_str("DARK_OAK"), + BoatType::Mangrove { .. } => f.write_str("MANGROVE"), + BoatType::Bamboo { .. } => f.write_str("BAMBOO"), + } + } +} +impl<'mc> std::ops::Deref for BoatType<'mc> { + type Target = BoatTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + BoatType::Oak { inner } => inner, + BoatType::Spruce { inner } => inner, + BoatType::Birch { inner } => inner, + BoatType::Jungle { inner } => inner, + BoatType::Acacia { inner } => inner, + BoatType::Cherry { inner } => inner, + BoatType::DarkOak { inner } => inner, + BoatType::Mangrove { inner } => inner, + BoatType::Bamboo { inner } => inner, + } + } +} + +impl<'mc> BoatType<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/Boat/Type"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/Boat/Type;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "OAK" => Ok(BoatType::Oak { + inner: BoatTypeStruct::from_raw(env, obj)?, + }), + "SPRUCE" => Ok(BoatType::Spruce { + inner: BoatTypeStruct::from_raw(env, obj)?, + }), + "BIRCH" => Ok(BoatType::Birch { + inner: BoatTypeStruct::from_raw(env, obj)?, + }), + "JUNGLE" => Ok(BoatType::Jungle { + inner: BoatTypeStruct::from_raw(env, obj)?, + }), + "ACACIA" => Ok(BoatType::Acacia { + inner: BoatTypeStruct::from_raw(env, obj)?, + }), + "CHERRY" => Ok(BoatType::Cherry { + inner: BoatTypeStruct::from_raw(env, obj)?, + }), + "DARK_OAK" => Ok(BoatType::DarkOak { + inner: BoatTypeStruct::from_raw(env, obj)?, + }), + "MANGROVE" => Ok(BoatType::Mangrove { + inner: BoatTypeStruct::from_raw(env, obj)?, + }), + "BAMBOO" => Ok(BoatType::Bamboo { + inner: BoatTypeStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct BoatTypeStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for BoatType<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Oak { inner } => inner.0.clone(), + Self::Spruce { inner } => inner.0.clone(), + Self::Birch { inner } => inner.0.clone(), + Self::Jungle { inner } => inner.0.clone(), + Self::Acacia { inner } => inner.0.clone(), + Self::Cherry { inner } => inner.0.clone(), + Self::DarkOak { inner } => inner.0.clone(), + Self::Mangrove { inner } => inner.0.clone(), + Self::Bamboo { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Oak { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Spruce { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Birch { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Jungle { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Acacia { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Cherry { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DarkOak { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Mangrove { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Bamboo { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for BoatType<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate BoatType from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Boat/Type")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BoatType object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "OAK" => Ok(BoatType::Oak { + inner: BoatTypeStruct::from_raw(env, obj)?, + }), + "SPRUCE" => Ok(BoatType::Spruce { + inner: BoatTypeStruct::from_raw(env, obj)?, + }), + "BIRCH" => Ok(BoatType::Birch { + inner: BoatTypeStruct::from_raw(env, obj)?, + }), + "JUNGLE" => Ok(BoatType::Jungle { + inner: BoatTypeStruct::from_raw(env, obj)?, + }), + "ACACIA" => Ok(BoatType::Acacia { + inner: BoatTypeStruct::from_raw(env, obj)?, + }), + "CHERRY" => Ok(BoatType::Cherry { + inner: BoatTypeStruct::from_raw(env, obj)?, + }), + "DARK_OAK" => Ok(BoatType::DarkOak { + inner: BoatTypeStruct::from_raw(env, obj)?, + }), + "MANGROVE" => Ok(BoatType::Mangrove { + inner: BoatTypeStruct::from_raw(env, obj)?, + }), + "BAMBOO" => Ok(BoatType::Bamboo { + inner: BoatTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for BoatTypeStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for BoatTypeStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate BoatTypeStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Boat/Type")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BoatTypeStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> BoatTypeStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Boat/Type;"); + let cls = jni.find_class("org/bukkit/entity/Boat/Type"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::BoatType::from_raw(&jni, obj) + } + /// Gets the material of the boat type. + pub fn material(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaterial", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +pub enum BoatStatus<'mc> { + InWater { inner: BoatStatusStruct<'mc> }, + UnderWater { inner: BoatStatusStruct<'mc> }, + UnderFlowingWater { inner: BoatStatusStruct<'mc> }, + OnLand { inner: BoatStatusStruct<'mc> }, + InAir { inner: BoatStatusStruct<'mc> }, +} +impl<'mc> std::fmt::Display for BoatStatus<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + BoatStatus::InWater { .. } => f.write_str("IN_WATER"), + BoatStatus::UnderWater { .. } => f.write_str("UNDER_WATER"), + BoatStatus::UnderFlowingWater { .. } => f.write_str("UNDER_FLOWING_WATER"), + BoatStatus::OnLand { .. } => f.write_str("ON_LAND"), + BoatStatus::InAir { .. } => f.write_str("IN_AIR"), + } + } +} +impl<'mc> std::ops::Deref for BoatStatus<'mc> { + type Target = BoatStatusStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + BoatStatus::InWater { inner } => inner, + BoatStatus::UnderWater { inner } => inner, + BoatStatus::UnderFlowingWater { inner } => inner, + BoatStatus::OnLand { inner } => inner, + BoatStatus::InAir { inner } => inner, + } + } +} + +impl<'mc> BoatStatus<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/Boat/Status"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/Boat/Status;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "IN_WATER" => Ok(BoatStatus::InWater { + inner: BoatStatusStruct::from_raw(env, obj)?, + }), + "UNDER_WATER" => Ok(BoatStatus::UnderWater { + inner: BoatStatusStruct::from_raw(env, obj)?, + }), + "UNDER_FLOWING_WATER" => Ok(BoatStatus::UnderFlowingWater { + inner: BoatStatusStruct::from_raw(env, obj)?, + }), + "ON_LAND" => Ok(BoatStatus::OnLand { + inner: BoatStatusStruct::from_raw(env, obj)?, + }), + "IN_AIR" => Ok(BoatStatus::InAir { + inner: BoatStatusStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct BoatStatusStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for BoatStatus<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::InWater { inner } => inner.0.clone(), + Self::UnderWater { inner } => inner.0.clone(), + Self::UnderFlowingWater { inner } => inner.0.clone(), + Self::OnLand { inner } => inner.0.clone(), + Self::InAir { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::InWater { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::UnderWater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::UnderFlowingWater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OnLand { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::InAir { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for BoatStatus<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate BoatStatus from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Boat/Status")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BoatStatus object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "IN_WATER" => Ok(BoatStatus::InWater { + inner: BoatStatusStruct::from_raw(env, obj)?, + }), + "UNDER_WATER" => Ok(BoatStatus::UnderWater { + inner: BoatStatusStruct::from_raw(env, obj)?, + }), + "UNDER_FLOWING_WATER" => Ok(BoatStatus::UnderFlowingWater { + inner: BoatStatusStruct::from_raw(env, obj)?, + }), + "ON_LAND" => Ok(BoatStatus::OnLand { + inner: BoatStatusStruct::from_raw(env, obj)?, + }), + "IN_AIR" => Ok(BoatStatus::InAir { + inner: BoatStatusStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for BoatStatusStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for BoatStatusStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate BoatStatusStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Boat/Status")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BoatStatusStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> BoatStatusStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Boat/Status;"); + let cls = jni.find_class("org/bukkit/entity/Boat/Status"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::BoatStatus::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct Golem<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Golem<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Golem<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Golem from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Golem")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Golem object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Golem<'mc> { + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Golem<'mc> { + fn into(self) -> crate::entity::Creature<'mc> { + crate::entity::Creature::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Golem into crate::entity::Creature") + } +} +#[repr(C)] +pub struct ThrownExpBottle<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ThrownExpBottle<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for ThrownExpBottle<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate ThrownExpBottle from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ThrownExpBottle")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ThrownExpBottle object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> ThrownExpBottle<'mc> { + /// Gets the ItemStack the thrown projectile will display. + pub fn item(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the display ItemStack for the thrown projectile. + pub fn set_item( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for ThrownExpBottle<'mc> { + fn into(self) -> crate::entity::ThrowableProjectile<'mc> { + crate::entity::ThrowableProjectile::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ThrownExpBottle into crate::entity::ThrowableProjectile") + } +} +pub enum EntityCategory<'mc> { + None { inner: EntityCategoryStruct<'mc> }, + Undead { inner: EntityCategoryStruct<'mc> }, + Arthropod { inner: EntityCategoryStruct<'mc> }, + Illager { inner: EntityCategoryStruct<'mc> }, + Water { inner: EntityCategoryStruct<'mc> }, +} +impl<'mc> std::fmt::Display for EntityCategory<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + EntityCategory::None { .. } => f.write_str("NONE"), + EntityCategory::Undead { .. } => f.write_str("UNDEAD"), + EntityCategory::Arthropod { .. } => f.write_str("ARTHROPOD"), + EntityCategory::Illager { .. } => f.write_str("ILLAGER"), + EntityCategory::Water { .. } => f.write_str("WATER"), + } + } +} +impl<'mc> std::ops::Deref for EntityCategory<'mc> { + type Target = EntityCategoryStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + EntityCategory::None { inner } => inner, + EntityCategory::Undead { inner } => inner, + EntityCategory::Arthropod { inner } => inner, + EntityCategory::Illager { inner } => inner, + EntityCategory::Water { inner } => inner, + } + } +} + +impl<'mc> EntityCategory<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/EntityCategory"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/EntityCategory;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "NONE" => Ok(EntityCategory::None { + inner: EntityCategoryStruct::from_raw(env, obj)?, + }), + "UNDEAD" => Ok(EntityCategory::Undead { + inner: EntityCategoryStruct::from_raw(env, obj)?, + }), + "ARTHROPOD" => Ok(EntityCategory::Arthropod { + inner: EntityCategoryStruct::from_raw(env, obj)?, + }), + "ILLAGER" => Ok(EntityCategory::Illager { + inner: EntityCategoryStruct::from_raw(env, obj)?, + }), + "WATER" => Ok(EntityCategory::Water { + inner: EntityCategoryStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct EntityCategoryStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for EntityCategory<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::None { inner } => inner.0.clone(), + Self::Undead { inner } => inner.0.clone(), + Self::Arthropod { inner } => inner.0.clone(), + Self::Illager { inner } => inner.0.clone(), + Self::Water { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::None { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Undead { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Arthropod { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Illager { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Water { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for EntityCategory<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate EntityCategory from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EntityCategory")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EntityCategory object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "NONE" => Ok(EntityCategory::None { + inner: EntityCategoryStruct::from_raw(env, obj)?, + }), + "UNDEAD" => Ok(EntityCategory::Undead { + inner: EntityCategoryStruct::from_raw(env, obj)?, + }), + "ARTHROPOD" => Ok(EntityCategory::Arthropod { + inner: EntityCategoryStruct::from_raw(env, obj)?, + }), + "ILLAGER" => Ok(EntityCategory::Illager { + inner: EntityCategoryStruct::from_raw(env, obj)?, + }), + "WATER" => Ok(EntityCategory::Water { + inner: EntityCategoryStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for EntityCategoryStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for EntityCategoryStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate EntityCategoryStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EntityCategory")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EntityCategoryStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> EntityCategoryStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); + let cls = jni.find_class("org/bukkit/entity/EntityCategory"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::EntityCategory::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct Evoker<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Evoker<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Evoker<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Evoker from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Evoker")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Evoker object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Evoker<'mc> { + #[deprecated] + /// Gets the {@link Spell} the Evoker is currently using. + pub fn current_spell( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Evoker/Spell;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCurrentSpell", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EvokerSpell::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + #[deprecated] + /// Sets the {@link Spell} the Evoker is currently using. + pub fn set_current_spell( + &self, + spell: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Evoker/Spell;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(spell.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCurrentSpell", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the {@link Spell} the entity is currently using. + pub fn spell( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Spellcaster/Spell;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSpell", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::SpellcasterSpell::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the {@link Spell} the entity is currently using. + pub fn set_spell( + &self, + spell: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Spellcaster/Spell;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(spell.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSpell", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Evoker<'mc> { + fn into(self) -> crate::entity::Spellcaster<'mc> { + crate::entity::Spellcaster::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Evoker into crate::entity::Spellcaster") + } +} +pub enum EvokerSpell<'mc> { + None { inner: EvokerSpellStruct<'mc> }, + Summon { inner: EvokerSpellStruct<'mc> }, + Fangs { inner: EvokerSpellStruct<'mc> }, + Wololo { inner: EvokerSpellStruct<'mc> }, + Disappear { inner: EvokerSpellStruct<'mc> }, + Blindness { inner: EvokerSpellStruct<'mc> }, +} +impl<'mc> std::fmt::Display for EvokerSpell<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + EvokerSpell::None { .. } => f.write_str("NONE"), + EvokerSpell::Summon { .. } => f.write_str("SUMMON"), + EvokerSpell::Fangs { .. } => f.write_str("FANGS"), + EvokerSpell::Wololo { .. } => f.write_str("WOLOLO"), + EvokerSpell::Disappear { .. } => f.write_str("DISAPPEAR"), + EvokerSpell::Blindness { .. } => f.write_str("BLINDNESS"), + } + } +} +impl<'mc> std::ops::Deref for EvokerSpell<'mc> { + type Target = EvokerSpellStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + EvokerSpell::None { inner } => inner, + EvokerSpell::Summon { inner } => inner, + EvokerSpell::Fangs { inner } => inner, + EvokerSpell::Wololo { inner } => inner, + EvokerSpell::Disappear { inner } => inner, + EvokerSpell::Blindness { inner } => inner, + } + } +} + +impl<'mc> EvokerSpell<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/Evoker/Spell"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/Evoker/Spell;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "NONE" => Ok(EvokerSpell::None { + inner: EvokerSpellStruct::from_raw(env, obj)?, + }), + "SUMMON" => Ok(EvokerSpell::Summon { + inner: EvokerSpellStruct::from_raw(env, obj)?, + }), + "FANGS" => Ok(EvokerSpell::Fangs { + inner: EvokerSpellStruct::from_raw(env, obj)?, + }), + "WOLOLO" => Ok(EvokerSpell::Wololo { + inner: EvokerSpellStruct::from_raw(env, obj)?, + }), + "DISAPPEAR" => Ok(EvokerSpell::Disappear { + inner: EvokerSpellStruct::from_raw(env, obj)?, + }), + "BLINDNESS" => Ok(EvokerSpell::Blindness { + inner: EvokerSpellStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct EvokerSpellStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for EvokerSpell<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::None { inner } => inner.0.clone(), + Self::Summon { inner } => inner.0.clone(), + Self::Fangs { inner } => inner.0.clone(), + Self::Wololo { inner } => inner.0.clone(), + Self::Disappear { inner } => inner.0.clone(), + Self::Blindness { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::None { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Summon { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Fangs { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Wololo { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Disappear { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Blindness { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for EvokerSpell<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate EvokerSpell from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Evoker/Spell")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EvokerSpell object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "NONE" => Ok(EvokerSpell::None { + inner: EvokerSpellStruct::from_raw(env, obj)?, + }), + "SUMMON" => Ok(EvokerSpell::Summon { + inner: EvokerSpellStruct::from_raw(env, obj)?, + }), + "FANGS" => Ok(EvokerSpell::Fangs { + inner: EvokerSpellStruct::from_raw(env, obj)?, + }), + "WOLOLO" => Ok(EvokerSpell::Wololo { + inner: EvokerSpellStruct::from_raw(env, obj)?, + }), + "DISAPPEAR" => Ok(EvokerSpell::Disappear { + inner: EvokerSpellStruct::from_raw(env, obj)?, + }), + "BLINDNESS" => Ok(EvokerSpell::Blindness { + inner: EvokerSpellStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for EvokerSpellStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for EvokerSpellStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate EvokerSpellStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Evoker/Spell")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EvokerSpellStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> EvokerSpellStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Evoker/Spell;"); + let cls = jni.find_class("org/bukkit/entity/Evoker/Spell"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::EvokerSpell::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct Piglin<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Piglin<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Piglin<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Piglin from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Piglin")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Piglin object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Piglin<'mc> { + /// Get whether the piglin is able to hunt hoglins. + pub fn is_able_to_hunt(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isAbleToHunt", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the piglin is able to hunt hoglins. + pub fn set_is_able_to_hunt(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setIsAbleToHunt", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Adds a material to the allowed list of materials to barter with. + pub fn add_barter_material( + &self, + material: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/Material;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addBarterMaterial", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Removes a material from the allowed list of materials to barter with. + /// Note: It's not possible to override the default + /// bartering item gold_ingots as payment. To block gold_ingots see + /// {@link org.bukkit.event.entity.PiglinBarterEvent}. + pub fn remove_barter_material( + &self, + material: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/Material;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeBarterMaterial", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Adds a material the piglin will pickup and store in his inventory. + pub fn add_material_of_interest( + &self, + material: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/Material;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addMaterialOfInterest", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Removes a material from the list of materials the piglin will pickup. + /// Note: It's not possible to override the default list of + /// item the piglin will pickup. To cancel pickup see + /// {@link org.bukkit.event.entity.EntityPickupItemEvent}. + pub fn remove_material_of_interest( + &self, + material: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/Material;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeMaterialOfInterest", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns a immutable set of materials the piglins will pickup. + /// + /// Note: This set will not include the items that are set + /// by default. To interact with those items see + /// {@link org.bukkit.event.entity.EntityPickupItemEvent}. + pub fn interest_list( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInterestList", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns a immutable set of materials the piglins will barter with. + /// Note: This set will not include the items that are set + /// by default. To interact with those items see + /// {@link org.bukkit.event.entity.PiglinBarterEvent}. + pub fn barter_list( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBarterList", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets whether the piglin is immune to zombification. + pub fn is_immune_to_zombification(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isImmuneToZombification", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the piglin is immune to zombification. + pub fn set_immune_to_zombification( + &self, + flag: bool, + ) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setImmuneToZombification", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the amount of ticks until this entity will be converted to a + /// Zombified Piglin. + /// When this reaches 300, the entity will be converted. + pub fn conversion_time(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getConversionTime", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the amount of ticks until this entity will be converted to a + /// Zombified Piglin. + /// When this reaches 0, the entity will be converted. A value of less than 0 + /// will stop the current conversion process without converting the current + /// entity. + pub fn set_conversion_time(&self, time: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(time); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setConversionTime", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get if this entity is in the process of converting to a Zombified Piglin. + pub fn is_converting(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isConverting", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Gets whether the piglin is a baby + pub fn is_baby(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isBaby", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Sets whether the piglin is a baby + pub fn set_baby(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBaby", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the object's inventory. + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Piglin<'mc> { + fn into(self) -> crate::entity::PiglinAbstract<'mc> { + crate::entity::PiglinAbstract::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Piglin into crate::entity::PiglinAbstract") + } +} +impl<'mc> Into> for Piglin<'mc> { + fn into(self) -> crate::inventory::InventoryHolder<'mc> { + crate::inventory::InventoryHolder::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Piglin into crate::inventory::InventoryHolder") + } +} +#[repr(C)] +pub struct AnimalTamer<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for AnimalTamer<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for AnimalTamer<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate AnimalTamer from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/AnimalTamer")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a AnimalTamer object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> AnimalTamer<'mc> { + /// This is the name of the specified AnimalTamer. + pub fn name(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// This is the UUID of the specified AnimalTamer. + pub fn unique_id( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct PufferFish<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PufferFish<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PufferFish<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate PufferFish from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/PufferFish")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PufferFish object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> PufferFish<'mc> { + /// Returns the current puff state of this fish (i.e. how inflated it is). + pub fn puff_state(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPuffState", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the current puff state of this fish (i.e. how inflated it is). + pub fn set_puff_state(&self, state: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(state); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPuffState", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for PufferFish<'mc> { + fn into(self) -> crate::entity::Fish<'mc> { + crate::entity::Fish::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PufferFish into crate::entity::Fish") + } +} +#[repr(C)] +pub struct Steerable<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Steerable<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Steerable<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Steerable from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Steerable")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Steerable object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Steerable<'mc> { + /// Check if the pig has a saddle. + pub fn has_saddle(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasSaddle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets if the pig has a saddle or not + pub fn set_saddle(&self, saddled: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(saddled.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSaddle", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the time in ticks this entity's movement is being increased. + /// Movement speed is often increased as a result of using the + /// {@link #getSteerMaterial()}. + pub fn boost_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBoostTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the time in ticks this entity's movement will be increased. + /// This will reset the current boost ticks to 0 + /// ({@link #getCurrentBoostTicks()}). + pub fn set_boost_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBoostTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the time in ticks this entity's movement has been increased as of the + /// most recent boost. + /// Current boost ticks will never be {@literal >} {@link #getBoostTicks()}. + pub fn current_boost_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCurrentBoostTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the time in ticks this entity's movement has been increased relative + /// to the most recent boost. + pub fn set_current_boost_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCurrentBoostTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the material used to steer this entity when ridden by a player. + pub fn steer_material(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSteerMaterial", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn breed_cause( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Set the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn set_breed_cause( + &self, + uuid: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/UUID;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBreedCause", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get whether or not this entity is in love mode and will produce + /// offspring with another entity in love mode. Will return true if + /// and only if {@link #getLoveModeTicks()} is greater than 0. + pub fn is_love_mode(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the amount of ticks remaining for this entity in love mode. + /// If the entity is not in love mode, 0 will be returned. + pub fn love_mode_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLoveModeTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the amount of ticks for which this entity should be in love mode. + /// Setting the love mode ticks to 600 is the equivalent of a player + /// feeding the entity their breeding item of choice. + pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLoveModeTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Check if the provided ItemStack is the correct item used for breeding + /// this entity.. + pub fn is_breed_item( + &self, + material: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Steerable<'mc> { + fn into(self) -> crate::entity::Animals<'mc> { + crate::entity::Animals::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Steerable into crate::entity::Animals") + } +} +#[repr(C)] +pub struct Dolphin<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Dolphin<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Dolphin<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Dolphin from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Dolphin")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Dolphin object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Dolphin<'mc> { + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Dolphin<'mc> { + fn into(self) -> crate::entity::WaterMob<'mc> { + crate::entity::WaterMob::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Dolphin into crate::entity::WaterMob") + } +} +#[repr(C)] +pub struct Tadpole<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Tadpole<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Tadpole<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Tadpole from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Tadpole")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Tadpole object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Tadpole<'mc> { + /// Gets the age of this mob. + pub fn age(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getAge", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the age of this mob. + pub fn set_age(&self, age: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(age); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAge", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Tadpole<'mc> { + fn into(self) -> crate::entity::Fish<'mc> { + crate::entity::Fish::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Tadpole into crate::entity::Fish") + } +} +#[repr(C)] +pub struct ThrownPotion<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ThrownPotion<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for ThrownPotion<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate ThrownPotion from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ThrownPotion")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ThrownPotion object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> ThrownPotion<'mc> { + /// Returns the effects that are applied by this potion. + pub fn effects( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEffects", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Gets the ItemStack the thrown projectile will display. + pub fn item(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/inventory/ItemStack;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getItem", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the display ItemStack for the thrown projectile. + pub fn set_item( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setItem", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for ThrownPotion<'mc> { + fn into(self) -> crate::entity::ThrowableProjectile<'mc> { + crate::entity::ThrowableProjectile::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ThrownPotion into crate::entity::ThrowableProjectile") + } +} +#[repr(C)] +pub struct BreezeWindCharge<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for BreezeWindCharge<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for BreezeWindCharge<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate BreezeWindCharge from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/BreezeWindCharge")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BreezeWindCharge object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> BreezeWindCharge<'mc> { + /// Immediately explode this WindCharge. + pub fn explode(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "explode", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for BreezeWindCharge<'mc> { + fn into(self) -> crate::entity::AbstractWindCharge<'mc> { + crate::entity::AbstractWindCharge::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BreezeWindCharge into crate::entity::AbstractWindCharge") + } +} +#[repr(C)] +pub struct EnderPearl<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for EnderPearl<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for EnderPearl<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate EnderPearl from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EnderPearl")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EnderPearl object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> EnderPearl<'mc> { + /// Gets the ItemStack the thrown projectile will display. + pub fn item(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/inventory/ItemStack;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getItem", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the display ItemStack for the thrown projectile. + pub fn set_item( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setItem", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for EnderPearl<'mc> { + fn into(self) -> crate::entity::ThrowableProjectile<'mc> { + crate::entity::ThrowableProjectile::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EnderPearl into crate::entity::ThrowableProjectile") + } +} +#[repr(C)] +pub struct ThrowableProjectile<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ThrowableProjectile<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for ThrowableProjectile<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate ThrowableProjectile from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ThrowableProjectile")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ThrowableProjectile object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> ThrowableProjectile<'mc> { + /// Gets the ItemStack the thrown projectile will display. + pub fn item(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/inventory/ItemStack;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getItem", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the display ItemStack for the thrown projectile. + pub fn set_item( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setItem", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Retrieve the shooter of this projectile. + pub fn shooter( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/projectiles/ProjectileSource;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getShooter", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::projectiles::ProjectileSource::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Set the shooter of this projectile. + pub fn set_shooter( + &self, + source: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/projectiles/ProjectileSource;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(source.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setShooter", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Determine if this projectile should bounce or not when it hits. + pub fn does_bounce(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "doesBounce", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Set whether or not this projectile should bounce or not when it hits something. + pub fn set_bounce(&self, does_bounce: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(does_bounce.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBounce", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for ThrowableProjectile<'mc> { + fn into(self) -> crate::entity::Projectile<'mc> { + crate::entity::Projectile::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ThrowableProjectile into crate::entity::Projectile") + } +} +#[repr(C)] +pub struct Blaze<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Blaze<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Blaze<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Blaze from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Blaze")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Blaze object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Blaze<'mc> { + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Blaze<'mc> { + fn into(self) -> crate::entity::Monster<'mc> { + crate::entity::Monster::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Blaze into crate::entity::Monster") + } +} +#[repr(C)] +pub struct Slime<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Slime<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Slime<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Slime from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Slime")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Slime object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Slime<'mc> { + pub fn size(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + + pub fn set_size(&self, sz: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(sz); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSize", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Instructs this Mob to set the specified LivingEntity as its target. + /// + /// Hostile creatures may attack their target, and friendly creatures may + /// follow their target. + pub fn set_target( + &self, + target: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(target.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTarget", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the current target of this Mob + pub fn target( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTarget", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::LivingEntity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets whether this mob is aware of its surroundings. + /// Unaware mobs will still move if pushed, attacked, etc. but will not move + /// or perform any actions on their own. Unaware mobs may also have other + /// unspecified behaviours disabled, such as drowning. + pub fn set_aware(&self, aware: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(aware.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAware", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether this mob is aware of its surroundings. + /// Unaware mobs will still move if pushed, attacked, etc. but will not move + /// or perform any actions on their own. Unaware mobs may also have other + /// unspecified behaviours disabled, such as drowning. + pub fn is_aware(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isAware", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the {@link Sound} this mob makes while ambiently existing. This sound + /// may change depending on the current state of the entity, and may also + /// return null under specific conditions. This sound is not constant. + /// For instance, villagers will make different passive noises depending + /// on whether or not they are actively trading with a player, or make no + /// ambient noise while sleeping. + pub fn ambient_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAmbientSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Slime<'mc> { + fn into(self) -> crate::entity::Mob<'mc> { + crate::entity::Mob::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Slime into crate::entity::Mob") + } +} +impl<'mc> Into> for Slime<'mc> { + fn into(self) -> crate::entity::Enemy<'mc> { + crate::entity::Enemy::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Slime into crate::entity::Enemy") + } +} +#[repr(C)] +pub struct PiglinBrute<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PiglinBrute<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PiglinBrute<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate PiglinBrute from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/PiglinBrute")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PiglinBrute object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> PiglinBrute<'mc> { + /// Gets whether the piglin is immune to zombification. + pub fn is_immune_to_zombification(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isImmuneToZombification", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the piglin is immune to zombification. + pub fn set_immune_to_zombification( + &self, + flag: bool, + ) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setImmuneToZombification", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the amount of ticks until this entity will be converted to a + /// Zombified Piglin. + /// When this reaches 300, the entity will be converted. + pub fn conversion_time(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getConversionTime", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the amount of ticks until this entity will be converted to a + /// Zombified Piglin. + /// When this reaches 0, the entity will be converted. A value of less than 0 + /// will stop the current conversion process without converting the current + /// entity. + pub fn set_conversion_time(&self, time: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(time); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setConversionTime", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get if this entity is in the process of converting to a Zombified Piglin. + pub fn is_converting(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isConverting", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Gets whether the piglin is a baby + pub fn is_baby(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isBaby", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Sets whether the piglin is a baby + pub fn set_baby(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBaby", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for PiglinBrute<'mc> { + fn into(self) -> crate::entity::PiglinAbstract<'mc> { + crate::entity::PiglinAbstract::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PiglinBrute into crate::entity::PiglinAbstract") + } +} +#[repr(C)] +pub struct EvokerFangs<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for EvokerFangs<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for EvokerFangs<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate EvokerFangs from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EvokerFangs")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EvokerFangs object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> EvokerFangs<'mc> { + /// Gets the {@link LivingEntity} which summoned the fangs. + pub fn owner( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::LivingEntity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets the {@link LivingEntity} which summoned the fangs. + pub fn set_owner( + &self, + owner: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owner.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setOwner", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the delay in ticks until the fang attacks. + pub fn attack_delay(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAttackDelay", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the delay in ticks until the fang attacks. + pub fn set_attack_delay(&self, delay: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(delay); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAttackDelay", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Stores the entity's current position in the provided Location object. + /// + /// If the provided Location is null this method does nothing and returns + /// null. + pub fn get_location( + &self, + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLocation", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) })?)) } - #[deprecated] - /// Sets the Location where the player will spawn at their bed. - pub fn set_bed_spawn_location( + /// Sets this entity's velocity in meters per tick + pub fn set_velocity( + &self, + velocity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVelocity", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets this entity's current velocity + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the entity's height + pub fn height(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the entity's width + pub fn width(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the entity's current bounding box. + /// + /// The returned bounding box reflects the entity's current location and + /// size. + pub fn bounding_box( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns true if the entity is supported by a block. This value is a + /// state updated by the server and is not recalculated unless the entity + /// moves. + pub fn is_on_ground(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns true if the entity is in water. + pub fn is_in_water(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the current world this entity resides in + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the entity's rotation. + /// + /// Note that if the entity is affected by AI, it may override this rotation. + pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { + let sig = String::from("(FF)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); + let val_2 = jni::objects::JValueGen::Float(pitch); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRotation", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Teleports this entity to the given location. If this entity is riding a + /// vehicle, it will be dismounted prior to teleportation. + pub fn teleport( + &self, + location: impl Into>, + cause: std::option::Option< + impl Into>, + >, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = cause { + sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "teleport", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns a list of entities within a bounding box centered around this + /// entity + pub fn get_nearby_entities( + &self, + x: f64, + y: f64, + z: f64, + ) -> Result>, Box> { + let sig = String::from("(DDD)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Double(x); + let val_2 = jni::objects::JValueGen::Double(y); + let val_3 = jni::objects::JValueGen::Double(z); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNearbyEntities", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Returns a unique id for this entity + pub fn entity_id(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's maximum fire ticks. + pub fn max_fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFireTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets if the entity has visual fire (it will always appear to be on fire). + pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVisualFire", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the entity has visual fire (it will always appear to be on fire). + pub fn is_visual_fire(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's maximum freeze ticks (amount of ticks before it will + /// be fully frozen) + pub fn max_freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaxFreezeTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFreezeTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the entity is fully frozen (it has been in powdered snow for max + /// freeze ticks). + pub fn is_frozen(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Mark the entity's removal. + pub fn remove(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns true if this entity has been marked for removal. + pub fn is_dead(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns false if the entity has died, been despawned for some other + /// reason, or has not been added to the world. + pub fn is_valid(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the {@link Server} that contains this Entity + pub fn server(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Server;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Server::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns true if the entity gets persisted. + /// + /// By default all entities are persistent. An entity will also not get + /// persisted, if it is riding an entity that is not persistent. + /// + /// The persistent flag on players controls whether or not to save their + /// playerdata file when they quit. If a player is directly or indirectly + /// riding a non-persistent entity, the vehicle at the root and all its + /// passengers won't get persisted. + /// + /// This should not be confused with + /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls + /// despawning of living entities. + pub fn is_persistent(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether or not the entity gets persisted. + pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(persistent.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPersistent", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. + pub fn passenger( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + #[deprecated] + /// Set the passenger of a vehicle. + pub fn set_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPassenger", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets a list of passengers of this vehicle. + /// + /// The returned list will not be directly linked to the entity's current + /// passengers, and no guarantees are made as to its mutability. + pub fn passengers( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Add a passenger to the vehicle. + pub fn add_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addPassenger", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Remove a passenger from the vehicle. + pub fn remove_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removePassenger", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Check if a vehicle has passengers. + pub fn is_empty(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Eject any passenger. + pub fn eject(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the distance this entity has fallen + pub fn fall_distance(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the fall distance for this entity + pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(distance); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFallDistance", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Record the last {@link EntityDamageEvent} inflicted on this entity + pub fn set_last_damage_cause( + &self, + event: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(event.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLastDamageCause", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. + /// This event may have been cancelled. + pub fn last_damage_cause( + &self, + ) -> Result>, Box> + { + let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLastDamageCause", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Returns a unique and persistent id for this entity + pub fn unique_id( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. + pub fn ticks_lived(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. May not be less than one + /// tick. + pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTicksLived", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Performs the specified {@link EntityEffect} for this entity. + /// + /// This will be viewable to all players near the entity. + /// + /// If the effect is not applicable to this class of entity, it will not play. + pub fn play_effect( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "playEffect", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the type of the entity. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes while swimming. + pub fn swim_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes when splashing in water. For most + /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_splash_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSwimSplashSound", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes when splashing in water at high + /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_high_speed_splash_sound( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSwimHighSpeedSplashSound", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns whether this entity is inside a vehicle. + pub fn is_inside_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Leave the current vehicle. If the entity is currently in a vehicle (and + /// is removed from it), true will be returned, otherwise false will be + /// returned. + pub fn leave_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the vehicle that this entity is inside. If there is no vehicle, + /// null will be returned. + pub fn vehicle( &self, - location: impl Into>, - force: std::option::Option, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = force { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - sig += ")V"; + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets whether or not to display the mob's custom name client side. The + /// name will be displayed above the mob similarly to a player. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setBedSpawnLocation", + "setCustomNameVisible", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets the Location where the player will respawn. - pub fn set_respawn_location( - &self, - location: impl Into>, - force: std::option::Option, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = force { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")V"; + /// Gets whether or not the mob's custom name is displayed client side. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn is_custom_name_visible(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "setRespawnLocation", + "isCustomNameVisible", sig.as_str(), - args, + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(visible.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVisibleByDefault", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Play a note for the player at a location. - /// - /// This will work with cake. + /// Gets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn is_visible_by_default(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isVisibleByDefault", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get all players that are currently tracking this entity. /// - /// This method will fail silently when called with {@link Instrument#CUSTOM_HEAD}. - pub fn play_note( + /// 'Tracking' means that this entity has been sent to the player and that + /// they are receiving updates on its state. Note that the client's {@code + /// 'Entity Distance'} setting does not affect the range at which entities + /// are tracked. + pub fn tracked_by( &self, - loc: impl Into>, - instrument: impl Into>, - note: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/Instrument;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(instrument.into().jni_object().clone()) - }); - args.push(val_2); - sig += "Lorg/bukkit/Note;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(note.into().jni_object().clone()) - }); - args.push(val_3); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "playNote", sig.as_str(), args); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets whether the entity has a team colored (default: white) glow. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setGlowing", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Play a sound for a player at the location. For sounds with multiple - /// variations passing the same seed will always play the same variation. - /// - /// This function will fail silently if Location or Sound are null. No sound - /// will be heard by the player if their client does not have the respective - /// sound for the value passed. - pub fn play_sound( - &self, - location: impl Into>, - sound: impl Into, - category: impl Into>, - volume: f32, - pitch: std::option::Option, - seed: std::option::Option, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(sound.into())?, - )); - args.push(val_2); - sig += "Lorg/bukkit/SoundCategory;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(category.into().jni_object().clone()) - }); - args.push(val_3); - sig += "F"; - let val_4 = jni::objects::JValueGen::Float(volume); - args.push(val_4); - if let Some(a) = pitch { - sig += "F"; - let val_5 = jni::objects::JValueGen::Float(a); - args.push(val_5); - } - if let Some(a) = seed { - sig += "J"; - let val_6 = jni::objects::JValueGen::Long(a); - args.push(val_6); - } - sig += ")V"; + /// Gets whether the entity is glowing or not. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn is_glowing(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "playSound", sig.as_str(), args); + .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the entity is invulnerable or not. + /// + /// When an entity is invulnerable it can only be damaged by players in + /// creative mode. + pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setInvulnerable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Stop the specified sound from playing. - pub fn stop_sound( - &self, - sound: impl Into, - category: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(sound.into())?, - )); - args.push(val_1); - if let Some(a) = category { - sig += "Lorg/bukkit/SoundCategory;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; + /// Gets whether the entity is invulnerable or not. + pub fn is_invulnerable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets whether the entity is silent or not. + pub fn is_silent(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "stopSound", sig.as_str(), args); + .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the entity is silent or not. + /// + /// When an entity is silent it will not produce any sound. + pub fn set_silent(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSilent", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Stop all sounds from playing. - pub fn stop_all_sounds(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Returns whether gravity applies to this entity. + pub fn has_gravity(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "stopAllSounds", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether gravity applies to this entity. + pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gravity.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setGravity", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Plays an effect to just this player. - pub fn play_effect( - &self, - loc: impl Into>, - effect: impl Into>, - data: jni::objects::JObject<'mc>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/Effect;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(effect.into().jni_object().clone()) - }); - args.push(val_2); - sig += "LT;"; - let val_3 = jni::objects::JValueGen::Object(data); - args.push(val_3); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "playEffect", sig.as_str(), args); + /// Gets the period of time (in ticks) before this entity can use a portal. + pub fn portal_cooldown(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPortalCooldown", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the period of time (in ticks) before this entity can use a portal. + pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(cooldown); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPortalCooldown", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Force this player to break a Block using the item in their main hand. - /// This method will respect enchantments, handle item durability (if - /// applicable) and drop experience and the correct items according to the - /// tool/item in the player's hand. - /// - /// Note that this method will call a {@link BlockBreakEvent}, meaning that - /// this method may not be successful in breaking the block if the event was - /// cancelled by a third party plugin. Care should be taken if running this - /// method in a BlockBreakEvent listener as recursion may be possible if it - /// is invoked on the same {@link Block} being broken in the event. + /// Returns a set of tags for this entity. /// - /// Additionally, a {@link BlockDropItemEvent} is called for the items - /// dropped by this method (if successful). + /// Entities can have no more than 1024 tags. + pub fn scoreboard_tags( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getScoreboardTags", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Add a tag to this entity. /// - /// The block must be in the same world as the player. - pub fn break_block( + /// Entities can have no more than 1024 tags. + pub fn add_scoreboard_tag( &self, - block: impl Into>, + tag: impl Into, ) -> Result> { - let sig = String::from("(Lorg/bukkit/block/Block;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) - }); + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addScoreboardTag", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Removes a given tag from this entity. + pub fn remove_scoreboard_tag( + &self, + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeScoreboardTag", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the reaction of the entity when moved by a piston. + pub fn piston_move_reaction( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPistonMoveReaction", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the closest cardinal {@link BlockFace} direction an entity is + /// currently facing. + /// + /// This will not return any non-cardinal directions such as + /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// + /// {@link Hanging} entities will override this call and thus their behavior + /// may be different. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the entity's current pose. + /// Note that the pose is only updated at the end of a tick, so may be + /// inconsistent with other methods. eg {@link Player#isSneaking()} being + /// true does not imply the current pose will be {@link Pose#SNEAKING} + pub fn pose(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Pose;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the category of spawn to which this entity belongs. + pub fn spawn_category( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); let res = self.jni_ref().call_method( &self.jni_object(), - "breakBlock", + "getSpawnCategory", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; + crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Checks if this entity has been spawned in a world. + /// + /// Entities not spawned in a world will not tick, be sent to players, or be + /// saved to the server files. + pub fn is_in_world(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Send a block change. This fakes a block change packet for a user at a certain location. This will not actually change the world in any way. - pub fn send_block_change( + /// Get this entity as an NBT string. + /// + /// This string should not be relied upon as a serializable value. + pub fn as_string(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Crates an {@link EntitySnapshot} representing the current state of this entity. + pub fn create_snapshot( &self, - loc: impl Into>, - material: impl Into>, - data: std::option::Option, - ) -> Result<(), Box> { + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntitySnapshot::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// + /// Note: Players cannot be copied. + pub fn copy( + &self, + to: std::option::Option>>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/Material;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - args.push(val_2); - if let Some(a) = data { - sig += "B"; - let val_3 = jni::objects::JValueGen::Byte(a); - args.push(val_3); + if let Some(a) = to { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); } - sig += ")V"; + sig += ")Lorg/bukkit/entity/Entity;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for EvokerFangs<'mc> { + fn into(self) -> crate::entity::Entity<'mc> { + crate::entity::Entity::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EvokerFangs into crate::entity::Entity") + } +} +#[repr(C)] +pub struct Boss<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Boss<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Boss<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Boss from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Boss")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Boss object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Boss<'mc> { + /// Returns the {@link BossBar} of the {@link Boss} + pub fn boss_bar( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/boss/BossBar;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "sendBlockChange", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getBossBar", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::boss::BossBar::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Send block damage. This fakes block break progress at a certain location - /// sourced by the provided entity id. This will not actually change the block's - /// break progress in any way. + /// Stores the entity's current position in the provided Location object. /// - /// At the same location for each unique damage source sent to the player, a - /// separate damage overlay will be displayed with the given progress. This allows - /// for block damage at different progress from multiple entities at once. - pub fn send_block_damage( + /// If the provided Location is null this method does nothing and returns + /// null. + pub fn get_location( &self, loc: impl Into>, - progress: f32, - source_id: std::option::Option, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(loc.into().jni_object().clone()) }); - args.push(val_1); - sig += "F"; - let val_2 = jni::objects::JValueGen::Float(progress); - args.push(val_2); - if let Some(a) = source_id { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLocation", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "sendBlockDamage", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Send an equipment change for the target entity. This will not - /// actually change the entity's equipment in any way. - pub fn send_equipment_change( + /// Sets this entity's velocity in meters per tick + pub fn set_velocity( &self, - entity: impl Into>, - slot: impl Into>, - item: std::option::Option>>, + velocity: impl Into>, ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/LivingEntity;"; + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/inventory/EquipmentSlot;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(slot.into().jni_object().clone()) + jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) }); - args.push(val_2); - if let Some(a) = item { - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_3); - } - sig += ")V"; let res = self.jni_ref().call_method( &self.jni_object(), - "sendEquipmentChange", + "setVelocity", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Send a sign change. This fakes a sign change packet for a user at - /// a certain location. This will not actually change the world in any way. - /// This method will use a sign at the location's block or a faked sign - /// sent via - /// {@link #sendBlockChange(org.bukkit.Location, org.bukkit.block.data.BlockData)}. - /// - /// If the client does not have a sign at the given location it will - /// display an error message to the user. + /// Gets this entity's current velocity + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the entity's height + pub fn height(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the entity's width + pub fn width(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the entity's current bounding box. /// - /// To change all attributes of a sign, including the back Side, use - /// {@link #sendBlockUpdate(org.bukkit.Location, org.bukkit.block.TileState)}. - pub fn send_sign_change( + /// The returned bounding box reflects the entity's current location and + /// size. + pub fn bounding_box( &self, - loc: impl Into>, - lines: impl Into, - dye_color: std::option::Option>>, - has_glowing_text: std::option::Option, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(lines.into())?, - )); - args.push(val_2); - if let Some(a) = dye_color { - sig += "Lorg/bukkit/DyeColor;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_3); - } - if let Some(a) = has_glowing_text { - sig += "Z"; - let val_4 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_4); - } - sig += ")V"; + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "sendSignChange", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Send a TileState change. This fakes a TileState change for a user at - /// the given location. This will not actually change the world in any way. - /// This method will use a TileState at the location's block or a faked TileState - /// sent via - /// {@link #sendBlockChange(org.bukkit.Location, org.bukkit.block.data.BlockData)}. - /// - /// If the client does not have an appropriate tile at the given location it - /// may display an error message to the user. + /// Returns true if the entity is supported by a block. This value is a + /// state updated by the server and is not recalculated unless the entity + /// moves. + pub fn is_on_ground(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns true if the entity is in water. + pub fn is_in_water(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the current world this entity resides in + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the entity's rotation. /// - /// {@link BlockData#createBlockState()} can be used to create a {@link BlockState}. - pub fn send_block_update( - &self, - loc: impl Into>, - tile_state: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Location;Lorg/bukkit/block/TileState;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tile_state.into().jni_object().clone()) - }); + /// Note that if the entity is affected by AI, it may override this rotation. + pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { + let sig = String::from("(FF)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); + let val_2 = jni::objects::JValueGen::Float(pitch); let res = self.jni_ref().call_method( &self.jni_object(), - "sendBlockUpdate", + "setRotation", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), @@ -3392,233 +8933,415 @@ impl<'mc> Player<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Change a potion effect for the target entity. This will not actually - /// change the entity's potion effects in any way. - /// - /// Note: Sending an effect change to a player for themselves may - /// cause unexpected behavior on the client. Effects sent this way will also - /// not be removed when their timer reaches 0, they can be removed with - /// {@link #sendPotionEffectChangeRemove(LivingEntity, PotionEffectType)} - pub fn send_potion_effect_change( + /// Teleports this entity to the given location. If this entity is riding a + /// vehicle, it will be dismounted prior to teleportation. + pub fn teleport( &self, - entity: impl Into>, - effect: impl Into>, - ) -> Result<(), Box> { - let sig = - String::from("(Lorg/bukkit/entity/LivingEntity;Lorg/bukkit/potion/PotionEffect;)V"); + location: impl Into>, + cause: std::option::Option< + impl Into>, + >, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(effect.into().jni_object().clone()) + jni::objects::JObject::from_raw(location.into().jni_object().clone()) }); + args.push(val_1); + if let Some(a) = cause { + sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "teleport", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns a list of entities within a bounding box centered around this + /// entity + pub fn get_nearby_entities( + &self, + x: f64, + y: f64, + z: f64, + ) -> Result>, Box> { + let sig = String::from("(DDD)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Double(x); + let val_2 = jni::objects::JValueGen::Double(y); + let val_3 = jni::objects::JValueGen::Double(z); let res = self.jni_ref().call_method( &self.jni_object(), - "sendPotionEffectChange", + "getNearbyEntities", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Remove a potion effect for the target entity. This will not actually - /// change the entity's potion effects in any way. - /// - /// Note: Sending an effect change to a player for themselves may - /// cause unexpected behavior on the client. - pub fn send_potion_effect_change_remove( - &self, - entity: impl Into>, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = - String::from("(Lorg/bukkit/entity/LivingEntity;Lorg/bukkit/potion/PotionEffectType;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Returns a unique id for this entity + pub fn entity_id(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's maximum fire ticks. + pub fn max_fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "sendPotionEffectChangeRemove", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + "setFireTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Render a map and send it to the player in its entirety. This may be - /// used when streaming the map in the normal manner is not desirable. - pub fn send_map( - &self, - map: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/map/MapView;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(map.into().jni_object().clone()) - }); + /// Sets if the entity has visual fire (it will always appear to be on fire). + pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "sendMap", + "setVisualFire", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Send a hurt animation. This fakes incoming damage towards the player from - /// the given yaw relative to the player's direction. - pub fn send_hurt_animation(&self, yaw: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); + /// Gets if the entity has visual fire (it will always appear to be on fire). + pub fn is_visual_fire(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's maximum freeze ticks (amount of ticks before it will + /// be fully frozen) + pub fn max_freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "sendHurtAnimation", + "getMaxFreezeTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFreezeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Forces an update of the player's entire inventory. - pub fn update_inventory(&self) -> Result<(), Box> { + /// Gets if the entity is fully frozen (it has been in powdered snow for max + /// freeze ticks). + pub fn is_frozen(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Mark the entity's removal. + pub fn remove(&self) -> Result<(), Box> { let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "updateInventory", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets this player's previous {@link GameMode} - pub fn previous_game_mode( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/GameMode;"); + /// Returns true if this entity has been marked for removal. + pub fn is_dead(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns false if the entity has died, been despawned for some other + /// reason, or has not been added to the world. + pub fn is_valid(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the {@link Server} that contains this Entity + pub fn server(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Server;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Server::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns true if the entity gets persisted. + /// + /// By default all entities are persistent. An entity will also not get + /// persisted, if it is riding an entity that is not persistent. + /// + /// The persistent flag on players controls whether or not to save their + /// playerdata file when they quit. If a player is directly or indirectly + /// riding a non-persistent entity, the vehicle at the root and all its + /// passengers won't get persisted. + /// + /// This should not be confused with + /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls + /// despawning of living entities. + pub fn is_persistent(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether or not the entity gets persisted. + pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(persistent.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getPreviousGameMode", + "setPersistent", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. + pub fn passenger( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::GameMode::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the current time on the player's client. When relative is true the - /// player's time will be kept synchronized to its world time with the - /// specified offset. - /// - /// When using non relative time the player's time will stay fixed at the - /// specified time parameter. It's up to the caller to continue updating - /// the player's time. To restore player time to normal use - /// resetPlayerTime(). - pub fn set_player_time( + #[deprecated] + /// Set the passenger of a vehicle. + pub fn set_passenger( &self, - time: i64, - relative: bool, - ) -> Result<(), Box> { - let sig = String::from("(JZ)V"); - let val_1 = jni::objects::JValueGen::Long(time); - let val_2 = jni::objects::JValueGen::Bool(relative.into()); + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPlayerTime", + "setPassenger", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Returns the player's current timestamp. - pub fn player_time(&self) -> Result> { - let sig = String::from("()J"); + /// Gets a list of passengers of this vehicle. + /// + /// The returned list will not be directly linked to the entity's current + /// passengers, and no guarantees are made as to its mutability. + pub fn passengers( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPlayerTime", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Returns the player's current time offset relative to server time, or - /// the current player's fixed time if the player's time is absolute. - pub fn player_time_offset(&self) -> Result> { - let sig = String::from("()J"); + /// Add a passenger to the vehicle. + pub fn add_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getPlayerTimeOffset", + "addPassenger", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + Ok(res.z()?) } - /// Returns true if the player's time is relative to the server time, - /// otherwise the player's time is absolute and will not change its current - /// time unless done so with setPlayerTime(). - pub fn is_player_time_relative(&self) -> Result> { - let sig = String::from("()Z"); + /// Remove a passenger from the vehicle. + pub fn remove_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "isPlayerTimeRelative", + "removePassenger", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Restores the normal condition where the player's time is synchronized - /// with the server time. - /// - /// Equivalent to calling setPlayerTime(0, true). - pub fn reset_player_time(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Check if a vehicle has passengers. + pub fn is_empty(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Eject any passenger. + pub fn eject(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the distance this entity has fallen + pub fn fall_distance(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "resetPlayerTime", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the fall distance for this entity + pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(distance); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFallDistance", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets the type of weather the player will see.When used, the weather - /// status of the player is locked until {@link #resetPlayerWeather()} is - /// used. - pub fn set_player_weather( + #[deprecated] + /// Record the last {@link EntityDamageEvent} inflicted on this entity + pub fn set_last_damage_cause( &self, - val_type: impl Into>, + event: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/WeatherType;)V"); + let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(event.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPlayerWeather", + "setLastDamageCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the type of weather the player is currently experiencing. - pub fn player_weather( + /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. + /// This event may have been cancelled. + pub fn last_damage_cause( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/WeatherType;"); + ) -> Result>, Box> + { + let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPlayerWeather", + "getLastDamageCause", sig.as_str(), vec![], ); @@ -3626,1702 +9349,1810 @@ impl<'mc> Player<'mc> { if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::WeatherType::from_raw( + Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Restores the normal condition where the player's weather is controlled - /// by server conditions. - pub fn reset_player_weather(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "resetPlayerWeather", - sig.as_str(), - vec![], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Returns a unique and persistent id for this entity + pub fn unique_id( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the player's cooldown between picking up experience orbs. - pub fn exp_cooldown(&self) -> Result> { + /// Gets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. + pub fn ticks_lived(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getExpCooldown", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the player's cooldown between picking up experience orbs.. - /// Note: Setting this to 0 allows the player to pick up - /// instantly, but setting this to a negative value will cause the player to - /// be unable to pick up xp-orbs. - /// Calling this Method will result in {@link PlayerExpCooldownChangeEvent} - /// being called. - pub fn set_exp_cooldown(&self, ticks: i32) -> Result<(), Box> { + /// Sets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. May not be less than one + /// tick. + pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + let val_1 = jni::objects::JValueGen::Int(value); let res = self.jni_ref().call_method( &self.jni_object(), - "setExpCooldown", + "setTicksLived", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gives the player the amount of experience specified. - pub fn give_exp(&self, amount: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(amount); + /// Performs the specified {@link EntityEffect} for this entity. + /// + /// This will be viewable to all players near the entity. + /// + /// If the effect is not applicable to this class of entity, it will not play. + pub fn play_effect( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "giveExp", + "playEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gives the player the amount of experience levels specified. Levels can - /// be taken by specifying a negative amount. - pub fn give_exp_levels(&self, amount: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(amount); + /// Get the type of the entity. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes while swimming. + pub fn swim_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes when splashing in water. For most + /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_splash_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "giveExpLevels", + "getSwimSplashSound", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the players current experience points towards the next level. - /// - /// This is a percentage value. 0 is "no progress" and 1 is "next level". - pub fn exp(&self) -> Result> { - let sig = String::from("()F"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getExp", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the players current experience points towards the next level - /// - /// This is a percentage value. 0 is "no progress" and 1 is "next level". - pub fn set_exp(&self, exp: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(exp); + /// Get the {@link Sound} this entity makes when splashing in water at high + /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_high_speed_splash_sound( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setExp", + "getSwimHighSpeedSplashSound", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the players current experience level - pub fn level(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getLevel", sig.as_str(), vec![]); + /// Returns whether this entity is inside a vehicle. + pub fn is_inside_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) + } + /// Leave the current vehicle. If the entity is currently in a vehicle (and + /// is removed from it), true will be returned, otherwise false will be + /// returned. + pub fn leave_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the vehicle that this entity is inside. If there is no vehicle, + /// null will be returned. + pub fn vehicle( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the players current experience level - pub fn set_level(&self, level: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(level); + /// Sets whether or not to display the mob's custom name client side. The + /// name will be displayed above the mob similarly to a player. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLevel", + "setCustomNameVisible", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the players total experience points. + /// Gets whether or not the mob's custom name is displayed client side. /// - /// This refers to the total amount of experience the player has collected - /// over time and is not currently displayed to the client. - pub fn total_experience(&self) -> Result> { - let sig = String::from("()I"); + /// This value has no effect on players, they will always display their + /// name. + pub fn is_custom_name_visible(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getTotalExperience", + "isCustomNameVisible", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the players current experience points. - /// - /// This refers to the total amount of experience the player has collected - /// over time and is not currently displayed to the client. - pub fn set_total_experience(&self, exp: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(exp); + /// Sets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(visible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setTotalExperience", + "setVisibleByDefault", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Send an experience change. - /// This fakes an experience change packet for a user. This will not actually - /// change the experience points in any way. - pub fn send_experience_change( - &self, - progress: f32, - level: std::option::Option, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "F"; - let val_1 = jni::objects::JValueGen::Float(progress); - args.push(val_1); - if let Some(a) = level { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - sig += ")V"; + /// Gets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn is_visible_by_default(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "sendExperienceChange", + "isVisibleByDefault", sig.as_str(), - args, + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Determines if the Player is allowed to fly via jump key double-tap like - /// in creative mode. - pub fn allow_flight(&self) -> Result> { - let sig = String::from("()Z"); + /// Get all players that are currently tracking this entity. + /// + /// 'Tracking' means that this entity has been sent to the player and that + /// they are receiving updates on its state. Note that the client's {@code + /// 'Entity Distance'} setting does not affect the range at which entities + /// are tracked. + pub fn tracked_by( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAllowFlight", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets if the Player is allowed to fly via jump key double-tap like in - /// creative mode. - pub fn set_allow_flight(&self, flight: bool) -> Result<(), Box> { + /// Sets whether the entity has a team colored (default: white) glow. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flight.into()); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setAllowFlight", + "setGlowing", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Hides a player from this player - pub fn hide_player( - &self, - plugin: impl Into>, - player: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/plugin/Plugin;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = player { - sig += "Lorg/bukkit/entity/Player;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hidePlayer", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Allows this player to see a player that was previously hidden. If - /// another another plugin had hidden the player too, then the player will - /// remain hidden until the other plugin calls this method too. - pub fn show_player( - &self, - plugin: impl Into>, - player: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/plugin/Plugin;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = player { - sig += "Lorg/bukkit/entity/Player;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "showPlayer", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks to see if an entity has been visually hidden from this player. - pub fn can_see( - &self, - entity: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Entity;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Z"; + /// Gets whether the entity is glowing or not. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn is_glowing(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "canSee", sig.as_str(), args); + .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Visually hides an entity from this player. - pub fn hide_entity( - &self, - plugin: impl Into>, - entity: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;Lorg/bukkit/entity/Entity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) - }); + /// Sets whether the entity is invulnerable or not. + /// + /// When an entity is invulnerable it can only be damaged by players in + /// creative mode. + pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "hideEntity", + "setInvulnerable", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Allows this player to see an entity that was previously hidden. If - /// another another plugin had hidden the entity too, then the entity will - /// remain hidden until the other plugin calls this method too. - pub fn show_entity( - &self, - plugin: impl Into>, - entity: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;Lorg/bukkit/entity/Entity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "showEntity", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Gets whether the entity is invulnerable or not. + pub fn is_invulnerable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Checks to see if this player is currently flying or not. - pub fn is_flying(&self) -> Result> { + /// Gets whether the entity is silent or not. + pub fn is_silent(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isFlying", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Makes this player start or stop flying. - pub fn set_flying(&self, value: bool) -> Result<(), Box> { + /// Sets whether the entity is silent or not. + /// + /// When an entity is silent it will not produce any sound. + pub fn set_silent(&self, flag: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(value.into()); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setFlying", + "setSilent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets the speed at which a client will fly. Negative values indicate - /// reverse directions. - pub fn set_fly_speed(&self, value: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(value); + /// Returns whether gravity applies to this entity. + pub fn has_gravity(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether gravity applies to this entity. + pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gravity.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setFlySpeed", + "setGravity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets the speed at which a client will walk. Negative values indicate - /// reverse directions. - pub fn set_walk_speed(&self, value: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(value); + /// Gets the period of time (in ticks) before this entity can use a portal. + pub fn portal_cooldown(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "setWalkSpeed", + "getPortalCooldown", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the current allowed speed that a client can fly. - pub fn fly_speed(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFlySpeed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Gets the current allowed speed that a client can walk. - pub fn walk_speed(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getWalkSpeed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + Ok(res.i()?) } - #[deprecated] - /// Request that the player's client download and switch texture packs.The player's client will download the new texture pack asynchronously in the background, and will automatically switch to it once the download is complete. If the client has downloaded and cached the same texture pack in the past, it will perform a file size check against the response content to determine if the texture pack has changed and needs to be downloaded again. When this request is sent for the very first time from a given server, the client will first display a confirmation GUI to the player before proceeding with the download.Notes:
  • Players can disable server textures on their client, in which case this method will have no affect on them. Use the {@link PlayerResourcePackStatusEvent} to figure out whether or not the player loaded the pack!
  • There is no concept of resetting texture packs back to default within Minecraft, so players will have to relog to do so or you have to send an empty pack.
  • The request is send with "null" as the hash. This might result in newer versions not loading the pack correctly.
- pub fn set_texture_pack( - &self, - url: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(url.into())?, - )); + /// Sets the period of time (in ticks) before this entity can use a portal. + pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(cooldown); let res = self.jni_ref().call_method( &self.jni_object(), - "setTexturePack", + "setPortalCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Request that the player's client download and switch resource packs. - /// - /// The player's client will download the new resource pack asynchronously - /// in the background, and will automatically switch to it once the - /// download is complete. If the client has downloaded and cached a - /// resource pack with the same hash in the past it will not download but - /// directly apply the cached pack. If the hash is null and the client has - /// downloaded and cached the same resource pack in the past, it will - /// perform a file size check against the response content to determine if - /// the resource pack has changed and needs to be downloaded again. When - /// this request is sent for the very first time from a given server, the - /// client will first display a confirmation GUI to the player before - /// proceeding with the download. + /// Returns a set of tags for this entity. /// - /// Notes: - ///
    - ///
  • Players can disable server resources on their client, in which - /// case this method will have no affect on them. Use the - /// {@link PlayerResourcePackStatusEvent} to figure out whether or not - /// the player loaded the pack! - ///
  • To remove a resource pack you can use - /// {@link #removeResourcePack(UUID)} or {@link #removeResourcePacks()}. - ///
  • The request is sent with empty string as the hash when the hash is - /// not provided. This might result in newer versions not loading the - /// pack correctly. - ///
- pub fn set_resource_pack( + /// Entities can have no more than 1024 tags. + pub fn scoreboard_tags( &self, - id: impl Into>, - url: std::option::Option>, - hash: std::option::Option, - prompt: std::option::Option>, - force: std::option::Option, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(id.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = url { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_2); - } - if let Some(a) = hash { - sig += "B"; - let val_3 = jni::objects::JValueGen::Byte(a); - args.push(val_3); - } - if let Some(a) = prompt { - sig += "Ljava/lang/String;"; - let val_4 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_4); - } - if let Some(a) = force { - sig += "Z"; - let val_5 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_5); - } - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setResourcePack", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getScoreboardTags", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Request that the player's client download and include another resource pack. - /// - /// The player's client will download the new resource pack asynchronously - /// in the background, and will automatically add to it once the - /// download is complete. If the client has downloaded and cached a - /// resource pack with the same hash in the past it will not download but - /// directly apply the cached pack. If the hash is null and the client has - /// downloaded and cached the same resource pack in the past, it will - /// perform a file size check against the response content to determine if - /// the resource pack has changed and needs to be downloaded again. When - /// this request is sent for the very first time from a given server, the - /// client will first display a confirmation GUI to the player before - /// proceeding with the download. + /// Add a tag to this entity. /// - /// Notes: - ///
    - ///
  • Players can disable server resources on their client, in which - /// case this method will have no affect on them. Use the - /// {@link PlayerResourcePackStatusEvent} to figure out whether or not - /// the player loaded the pack! - ///
  • To remove a resource pack you can use - /// {@link #removeResourcePack(UUID)} or {@link #removeResourcePacks()}. - ///
  • The request is sent with empty string as the hash when the hash is - /// not provided. This might result in newer versions not loading the - /// pack correctly. - ///
- pub fn add_resource_pack( + /// Entities can have no more than 1024 tags. + pub fn add_scoreboard_tag( &self, - id: impl Into>, - url: impl Into, - hash: i8, - prompt: impl Into, - force: bool, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/UUID;Ljava/lang/String;BLjava/lang/String;Z)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(id.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(url.into())?, - )); - let val_3 = jni::objects::JValueGen::Byte(hash); - let val_4 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(prompt.into())?, + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, )); - let val_5 = jni::objects::JValueGen::Bool(force.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "addResourcePack", + "addScoreboardTag", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - jni::objects::JValueGen::from(val_5), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Request that the player's client remove a resource pack sent by the - /// server. - pub fn remove_resource_pack( + /// Removes a given tag from this entity. + pub fn remove_scoreboard_tag( &self, - id: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/UUID;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(id.into().jni_object().clone()) - }); + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "removeResourcePack", + "removeScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Request that the player's client remove all loaded resource pack sent by - /// the server. - pub fn remove_resource_packs(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Returns the reaction of the entity when moved by a piston. + pub fn piston_move_reaction( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); let res = self.jni_ref().call_method( &self.jni_object(), - "removeResourcePacks", + "getPistonMoveReaction", sig.as_str(), vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the Scoreboard displayed to this player - pub fn scoreboard( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/scoreboard/Scoreboard;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getScoreboard", sig.as_str(), vec![]); + /// Get the closest cardinal {@link BlockFace} direction an entity is + /// currently facing. + /// + /// This will not return any non-cardinal directions such as + /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// + /// {@link Hanging} entities will override this call and thus their behavior + /// may be different. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::scoreboard::Scoreboard::from_raw(&self.jni_ref(), unsafe { + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the player's visible Scoreboard. - pub fn set_scoreboard( + /// Gets the entity's current pose. + /// Note that the pose is only updated at the end of a tick, so may be + /// inconsistent with other methods. eg {@link Player#isSneaking()} being + /// true does not imply the current pose will be {@link Pose#SNEAKING} + pub fn pose(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Pose;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the category of spawn to which this entity belongs. + pub fn spawn_category( &self, - scoreboard: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/scoreboard/Scoreboard;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(scoreboard.into().jni_object().clone()) - }); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setScoreboard", + "getSpawnCategory", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the {@link WorldBorder} visible to this Player, or null if viewing - /// the world's world border. - pub fn world_border( + /// Checks if this entity has been spawned in a world. + /// + /// Entities not spawned in a world will not tick, be sent to players, or be + /// saved to the server files. + pub fn is_in_world(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get this entity as an NBT string. + /// + /// This string should not be relied upon as a serializable value. + pub fn as_string(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Crates an {@link EntitySnapshot} representing the current state of this entity. + pub fn create_snapshot( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/WorldBorder;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getWorldBorder", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::WorldBorder::from_raw( + Ok(Some(crate::entity::EntitySnapshot::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets the {@link WorldBorder} visible to this Player. - pub fn set_world_border( - &self, - border: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/WorldBorder;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(border.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setWorldBorder", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Send a health update to the player. This will adjust the health, food, and - /// saturation on the client and will not affect the player's actual values on - /// the server. As soon as any of these values change on the server, changes sent - /// by this method will no longer be visible. - pub fn send_health_update( + /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// + /// Note: Players cannot be copied. + pub fn copy( &self, - health: std::option::Option, - food_level: std::option::Option, - saturation: std::option::Option, - ) -> Result<(), Box> { + to: std::option::Option>>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = health { - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(a); + if let Some(a) = to { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); args.push(val_1); } - if let Some(a) = food_level { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); + sig += ")Lorg/bukkit/entity/Entity;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Boss<'mc> { + fn into(self) -> crate::entity::Entity<'mc> { + crate::entity::Entity::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Boss into crate::entity::Entity") + } +} +#[repr(C)] +pub struct Sheep<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Sheep<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Sheep<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Sheep from null object.").into()); } - if let Some(a) = saturation { - sig += "F"; - let val_3 = jni::objects::JValueGen::Float(a); - args.push(val_3); + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Sheep")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Sheep object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "sendHealthUpdate", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) } - /// Gets if the client is displayed a 'scaled' health, that is, health on a - /// scale from 0-{@link #getHealthScale()}. - pub fn is_health_scaled(&self) -> Result> { - let sig = String::from("()Z"); +} + +impl<'mc> Sheep<'mc> { + /// Get the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn breed_cause( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/UUID;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isHealthScaled", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets if the client is displayed a 'scaled' health, that is, health on a - /// scale from 0-{@link #getHealthScale()}. - /// - /// Displayed health follows a simple formula displayedHealth = - /// getHealth() / getMaxHealth() * getHealthScale(). - pub fn set_health_scaled(&self, scale: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(scale.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setHealthScaled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the number to scale health to for the client; this will also - /// {@link #setHealthScaled(boolean) setHealthScaled(true)}. - /// - /// Displayed health follows a simple formula displayedHealth = - /// getHealth() / getMaxHealth() * getHealthScale(). - pub fn set_health_scale(&self, scale: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(scale); + /// Set the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn set_breed_cause( + &self, + uuid: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/UUID;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setHealthScale", + "setBreedCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the number that health is scaled to for the client. - pub fn health_scale(&self) -> Result> { - let sig = String::from("()D"); + /// Get whether or not this entity is in love mode and will produce + /// offspring with another entity in love mode. Will return true if + /// and only if {@link #getLoveModeTicks()} is greater than 0. + pub fn is_love_mode(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getHealthScale", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Gets the entity which is followed by the camera when in - /// {@link GameMode#SPECTATOR}. - pub fn spectator_target( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + /// Get the amount of ticks remaining for this entity in love mode. + /// If the entity is not in love mode, 0 will be returned. + pub fn love_mode_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getSpectatorTarget", + "getLoveModeTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - /// Sets the entity which is followed by the camera when in - /// {@link GameMode#SPECTATOR}. - pub fn set_spectator_target( - &self, - entity: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) - }); + /// Set the amount of ticks for which this entity should be in love mode. + /// Setting the love mode ticks to 600 is the equivalent of a player + /// feeding the entity their breeding item of choice. + pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setSpectatorTarget", + "setLoveModeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sends a title and a subtitle message to the player. If either of these - /// values are null, they will not be sent and the display will remain - /// unchanged. If they are empty strings, the display will be updated as - /// such. If the strings contain a new line, only the first line will be - /// sent. All timings values may take a value of -1 to indicate that they - /// will use the last value sent (or the defaults if no title has been - /// displayed). - pub fn send_title( - &self, - title: impl Into, - subtitle: impl Into, - fade_in: std::option::Option, - stay: std::option::Option, - fade_out: std::option::Option, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(title.into())?, - )); - args.push(val_1); - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(subtitle.into())?, - )); - args.push(val_2); - if let Some(a) = fade_in { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - if let Some(a) = stay { - sig += "I"; - let val_4 = jni::objects::JValueGen::Int(a); - args.push(val_4); - } - if let Some(a) = fade_out { - sig += "I"; - let val_5 = jni::objects::JValueGen::Int(a); - args.push(val_5); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "sendTitle", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Resets the title displayed to the player. This will clear the displayed - /// title / subtitle and reset timings to their default values. - pub fn reset_title(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "resetTitle", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Spawns the particle (the number of times specified by count) - /// at the target location. The position of each particle will be - /// randomized positively and negatively by the offset parameters - /// on each axis. - pub fn spawn_particle( + /// Check if the provided ItemStack is the correct item used for breeding + /// this entity.. + pub fn is_breed_item( &self, - particle: impl Into>, - x: f64, - y: f64, - z: std::option::Option, - count: std::option::Option, - offset_x: std::option::Option, - offset_y: std::option::Option, - offset_z: std::option::Option, - extra: std::option::Option, - data: std::option::Option>, - force: std::option::Option, - ) -> Result<(), Box> { + material: impl Into>, + ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Particle;"; + sig += "Lorg/bukkit/Material;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(particle.into().jni_object().clone()) + jni::objects::JObject::from_raw(material.into().jni_object().clone()) }); args.push(val_1); - sig += "D"; - let val_2 = jni::objects::JValueGen::Double(x); - args.push(val_2); - sig += "D"; - let val_3 = jni::objects::JValueGen::Double(y); - args.push(val_3); - if let Some(a) = z { - sig += "D"; - let val_4 = jni::objects::JValueGen::Double(a); - args.push(val_4); - } - if let Some(a) = count { - sig += "I"; - let val_5 = jni::objects::JValueGen::Int(a); - args.push(val_5); - } - if let Some(a) = offset_x { - sig += "D"; - let val_6 = jni::objects::JValueGen::Double(a); - args.push(val_6); - } - if let Some(a) = offset_y { - sig += "D"; - let val_7 = jni::objects::JValueGen::Double(a); - args.push(val_7); - } - if let Some(a) = offset_z { - sig += "D"; - let val_8 = jni::objects::JValueGen::Double(a); - args.push(val_8); - } - if let Some(a) = extra { - sig += "D"; - let val_9 = jni::objects::JValueGen::Double(a); - args.push(val_9); - } - if let Some(a) = data { - sig += "LT;"; - let val_10 = jni::objects::JValueGen::Object(a); - args.push(val_10); - } - if let Some(a) = force { - sig += "Z"; - let val_11 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_11); - } - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "spawnParticle", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Return the player's progression on the specified advancement. - pub fn get_advancement_progress( - &self, - advancement: impl Into>, - ) -> Result, Box> { - let sig = String::from( - "(Lorg/bukkit/advancement/Advancement;)Lorg/bukkit/advancement/AdvancementProgress;", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(advancement.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAdvancementProgress", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Gets the color of this object. + /// + /// This may be null to represent the default color of an object, if the + /// object has a special default color (e.g Shulkers). + pub fn color(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/DyeColor;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::advancement::AdvancementProgress::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::DyeColor::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) + })?)) } - /// Get the player's current client side view distance. + /// Sets the color of this object to the specified DyeColor. /// - /// Will default to the server view distance if the client has not yet - /// communicated this information, - pub fn client_view_distance(&self) -> Result> { - let sig = String::from("()I"); + /// This may be null to represent the default color of an object, if the + /// object has a special default color (e.g Shulkers). + pub fn set_color( + &self, + color: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/DyeColor;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(color.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getClientViewDistance", + "setColor", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the player's estimated ping in milliseconds. - /// In Vanilla this value represents a weighted average of the response time - /// to application layer ping packets sent. This value does not represent the - /// network round trip time and as such may have less granularity and be - /// impacted by other sources. For these reasons it should not be used - /// for anti-cheat purposes. Its recommended use is only as a - /// qualitative indicator of connection quality (Vanilla uses it for - /// this purpose in the tab list). - pub fn ping(&self) -> Result> { - let sig = String::from("()I"); + /// Gets whether the entity is in its sheared state. + pub fn is_sheared(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getPing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSheared", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Gets the player's current locale. - /// The value of the locale String is not defined properly. - /// - /// The vanilla Minecraft client will use lowercase language / country pairs - /// separated by an underscore, but custom resource packs may use any format - /// they wish. - pub fn locale(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Sets whether the entity is in its sheared state. + pub fn set_sheared(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSheared", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Sheep<'mc> { + fn into(self) -> crate::entity::Animals<'mc> { + crate::entity::Animals::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Sheep into crate::entity::Animals") + } +} +impl<'mc> Into> for Sheep<'mc> { + fn into(self) -> crate::material::Colorable<'mc> { + crate::material::Colorable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Sheep into crate::material::Colorable") + } +} +impl<'mc> Into> for Sheep<'mc> { + fn into(self) -> crate::entity::Shearable<'mc> { + crate::entity::Shearable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Sheep into crate::entity::Shearable") + } +} +#[repr(C)] +pub struct ShulkerBullet<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ShulkerBullet<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for ShulkerBullet<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate ShulkerBullet from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ShulkerBullet")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ShulkerBullet object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> ShulkerBullet<'mc> { + /// Retrieve the target of this bullet. + pub fn target(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getLocale", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTarget", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Update the list of commands sent to the client. - /// - /// Generally useful to ensure the client has a complete list of commands - /// after permission changes are done. - pub fn update_commands(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "updateCommands", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Open a {@link Material#WRITTEN_BOOK} for a Player - pub fn open_book( + /// Sets the target of this bullet + pub fn set_target( &self, - book: impl Into>, + target: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(book.into().jni_object().clone()) + jni::objects::JObject::from_raw(target.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "openBook", + "setTarget", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Open a Sign for editing by the Player. - /// The Sign must be placed in the same world as the player. - pub fn open_sign( + /// Retrieve the shooter of this projectile. + pub fn shooter( &self, - sign: impl Into>, - side: std::option::Option>>, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/projectiles/ProjectileSource;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getShooter", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::projectiles::ProjectileSource::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Set the shooter of this projectile. + pub fn set_shooter( + &self, + source: impl Into>, ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/block/Sign;"; + let sig = String::from("(Lorg/bukkit/projectiles/ProjectileSource;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sign.into().jni_object().clone()) + jni::objects::JObject::from_raw(source.into().jni_object().clone()) }); - args.push(val_1); - if let Some(a) = side { - sig += "Lorg/bukkit/block/sign/Side;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "openSign", sig.as_str(), args); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setShooter", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Shows the demo screen to the player, this screen is normally only seen in - /// the demo version of the game. - /// - /// Servers can modify the text on this screen using a resource pack. - pub fn show_demo_screen(&self) -> Result<(), Box> { - let sig = String::from("()V"); + #[deprecated] + /// Determine if this projectile should bounce or not when it hits. + pub fn does_bounce(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "showDemoScreen", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "doesBounce", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets whether the player has the "Allow Server Listings" setting enabled. - pub fn is_allowing_server_listings(&self) -> Result> { - let sig = String::from("()Z"); + #[deprecated] + /// Set whether or not this projectile should bounce or not when it hits something. + pub fn set_bounce(&self, does_bounce: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(does_bounce.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "isAllowingServerListings", + "setBounce", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the player's inventory. - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/PlayerInventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::PlayerInventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Get the player's EnderChest inventory - pub fn ender_chest( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEnderChest", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} +impl<'mc> Into> for ShulkerBullet<'mc> { + fn into(self) -> crate::entity::Projectile<'mc> { + crate::entity::Projectile::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ShulkerBullet into crate::entity::Projectile") } - /// Gets the player's selected main hand - pub fn main_hand(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/MainHand;"); +} +#[repr(C)] +pub struct SizedFireball<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for SizedFireball<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for SizedFireball<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate SizedFireball from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/SizedFireball")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a SizedFireball object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> SizedFireball<'mc> { + /// Gets the display {@link ItemStack}. + pub fn display_item( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMainHand", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDisplayItem", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::MainHand::from_raw(&self.jni_ref(), unsafe { + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// If the player currently has an inventory window open, this method will - /// set a property of that window, such as the state of a progress bar. - pub fn set_window_property( + /// Sets the display {@link ItemStack} for the fireball. + pub fn set_display_item( &self, - prop: impl Into>, - value: i32, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/InventoryView/Property;I)Z"); + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(prop.into().jni_object().clone()) + jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(value); let res = self.jni_ref().call_method( &self.jni_object(), - "setWindowProperty", + "setDisplayItem", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the player's current enchantment seed. - /// The Seed is used to generate enchantment options in the enchanting table - /// for the player. - pub fn enchantment_seed(&self) -> Result> { - let sig = String::from("()I"); + /// Sets the direction the fireball should be flying towards. + /// + /// This is a convenience method, it will change the velocity direction and + /// acceleration direction, while keeping the power the same. + /// + /// Note: This method only uses the direction of the vector and will + /// normalize (a copy of) it. + /// + /// Special Case: When the given direction is + /// {@link Vector#isZero() zero}, the velocity and acceleration will also be + /// set to zero without keeping the power. + pub fn set_direction( + &self, + direction: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(direction.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getEnchantmentSeed", + "setDirection", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Retrieve the direction this fireball is heading toward. The returned vector is not normalized. + pub fn direction(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the player's enchantment seed. - /// The Seed is used to generate enchantment options in the enchanting table - /// for the player. - pub fn set_enchantment_seed(&self, seed: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(seed); + /// Sets the acceleration of the fireball. + /// The acceleration gets applied to the velocity every tick, depending on + /// the specific type of the fireball a damping / drag factor is applied so + /// that the velocity does not grow into infinity. + /// + /// Note: that the client may not respect non-default acceleration + /// power and will therefore mispredict the location of the fireball, causing + /// visual stutter. + pub fn set_acceleration( + &self, + acceleration: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(acceleration.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setEnchantmentSeed", + "setAcceleration", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Opens an inventory window to the specified inventory view. - pub fn open_inventory( - &self, - inventory: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = inventory { - sig += "Lorg/bukkit/inventory/InventoryView;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")V"; + /// Retrieve the acceleration of this fireball. + pub fn acceleration(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getOpenInventory", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getAcceleration", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Opens an inventory window to the specified inventory view. - pub fn open_inventory_with_inventory( - &self, - inventory: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = inventory { - sig += "Lorg/bukkit/inventory/InventoryView;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for SizedFireball<'mc> { + fn into(self) -> crate::entity::Fireball<'mc> { + crate::entity::Fireball::from_raw(&self.jni_ref(), self.1) + .expect("Error converting SizedFireball into crate::entity::Fireball") + } +} +#[repr(C)] +pub struct Firework<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Firework<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Firework<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Firework from null object.").into()); } - sig += ")V"; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Firework")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Firework object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Firework<'mc> { + /// Get a copy of the fireworks meta + pub fn firework_meta( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/FireworkMeta;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "openInventory", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getFireworkMeta", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::FireworkMeta::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Opens an empty workbench inventory window with the player's inventory - /// on the bottom. - pub fn open_workbench( + /// Apply the provided meta to the fireworks + pub fn set_firework_meta( &self, - location: impl Into>, - force: bool, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;Z)Lorg/bukkit/inventory/InventoryView;"); + meta: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/FireworkMeta;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) + jni::objects::JObject::from_raw(meta.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Bool(force.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "openWorkbench", + "setFireworkMeta", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::InventoryView::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Opens an empty enchanting inventory window with the player's inventory - /// on the bottom. - pub fn open_enchanting( + /// Set the {@link LivingEntity} to which this firework is attached. + /// + /// When attached to an entity, the firework effect will act as normal but + /// remain positioned on the entity. If the entity {@code LivingEntity#isGliding() + /// is gliding}, then the entity will receive a boost in the direction that + /// they are looking. + pub fn set_attached_to( &self, - location: impl Into>, - force: bool, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;Z)Lorg/bukkit/inventory/InventoryView;"); + entity: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Bool(force.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "openEnchanting", + "setAttachedTo", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::InventoryView::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Starts a trade between the player and the merchant. - /// Note that only one player may trade with a merchant at once. You must use - /// the force parameter for this. - pub fn open_merchant( + /// Get the {@link LivingEntity} to which this firework is attached. + /// + /// When attached to an entity, the firework effect will act as normal but + /// remain positioned on the entity. If the entity {@code LivingEntity#isGliding() + /// is gliding}, then the entity will receive a boost in the direction that + /// they are looking. + pub fn attached_to( &self, - merchant: impl Into>, - force: bool, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/Merchant;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(merchant.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(force.into()); - args.push(val_2); - sig += ")Lorg/bukkit/inventory/InventoryView;"; + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "openMerchant", sig.as_str(), args); + .call_method(&self.jni_object(), "getAttachedTo", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::InventoryView::from_raw( + Ok(Some(crate::entity::LivingEntity::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Force-closes the currently open inventory view for this player, if any. - pub fn close_inventory(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Set the ticks that this firework has been alive. If this value exceeds + /// {@link #getMaxLife()}, the firework will detonate. + pub fn set_life(&self, ticks: i32) -> Result> { + let sig = String::from("(I)Z"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLife", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the ticks that this firework has been alive. When this value reaches + /// {@link #getMaxLife()}, the firework will detonate. + pub fn life(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLife", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the time in ticks this firework will exist until it is detonated. + pub fn set_max_life(&self, ticks: i32) -> Result> { + let sig = String::from("(I)Z"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaxLife", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the time in ticks this firework will exist until it is detonated. + pub fn max_life(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "closeInventory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxLife", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Cause this firework to explode at earliest opportunity, as if it has no + /// remaining fuse. + pub fn detonate(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "detonate", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Returns the ItemStack currently in your hand, can be empty. - pub fn item_in_hand( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + /// Check whether or not this firework has detonated. + pub fn is_detonated(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemInHand", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isDetonated", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - #[deprecated] - /// Sets the item to the given ItemStack, this will replace whatever the user was holding. - pub fn set_item_in_hand( - &self, - item: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); + /// Gets if the firework was shot at an angle (i.e. from a crossbow). + /// A firework which was not shot at an angle will fly straight upwards. + pub fn is_shot_at_angle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isShotAtAngle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets if the firework was shot at an angle (i.e. from a crossbow). + /// A firework which was not shot at an angle will fly straight upwards. + pub fn set_shot_at_angle(&self, shot_at_angle: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(shot_at_angle.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemInHand", + "setShotAtAngle", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the ItemStack currently on your cursor, can be empty. Will - /// always be empty if the player currently has no open window. - pub fn item_on_cursor( + /// Retrieve the shooter of this projectile. + pub fn shooter( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/projectiles/ProjectileSource;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemOnCursor", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getShooter", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::projectiles::ProjectileSource::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the item to the given ItemStack, this will replace whatever the - /// user was moving. Will always be empty if the player currently has no - /// open window. - pub fn set_item_on_cursor( + /// Set the shooter of this projectile. + pub fn set_shooter( &self, - item: impl Into>, + source: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let sig = String::from("(Lorg/bukkit/projectiles/ProjectileSource;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(source.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemOnCursor", + "setShooter", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check whether a cooldown is active on the specified material. - pub fn has_cooldown( - &self, - material: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/Material;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasCooldown", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + #[deprecated] + /// Determine if this projectile should bounce or not when it hits. + pub fn does_bounce(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "doesBounce", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get the cooldown time in ticks remaining for the specified material. - pub fn get_cooldown( - &self, - material: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/Material;)I"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); + #[deprecated] + /// Set whether or not this projectile should bounce or not when it hits something. + pub fn set_bounce(&self, does_bounce: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(does_bounce.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getCooldown", + "setBounce", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Firework<'mc> { + fn into(self) -> crate::entity::Projectile<'mc> { + crate::entity::Projectile::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Firework into crate::entity::Projectile") + } +} +#[repr(C)] +pub struct ItemFrame<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ItemFrame<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for ItemFrame<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate ItemFrame from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ItemFrame")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ItemFrame object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> ItemFrame<'mc> { + /// Get the item in this frame + pub fn item(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set a cooldown on the specified material for a certain amount of ticks. - /// ticks. 0 ticks will result in the removal of the cooldown. - /// - /// Cooldowns are used by the server for items such as ender pearls and - /// shields to prevent them from being used repeatedly. - /// - /// Note that cooldowns will not by themselves stop an item from being used - /// for attacking. - pub fn set_cooldown( + /// Set the item in this frame + pub fn set_item( &self, - material: impl Into>, - ticks: i32, + item: impl Into>, + play_sound: std::option::Option, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Material;I)V"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) + jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCooldown", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + args.push(val_1); + if let Some(a) = play_sound { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setItem", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the sleep ticks of the player. This value may be capped. - pub fn sleep_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSleepTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Attempts to make the entity sleep at the given location. - /// - /// The location must be in the current world and have a bed placed at the - /// location. The game may also enforce other requirements such as proximity - /// to bed, monsters, and dimension type if force is not set. - pub fn sleep( - &self, - location: impl Into>, - force: bool, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/Location;Z)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Bool(force.into()); + /// Gets the chance of the item being dropped upon this frame's destruction. + ///
    + ///
  • A drop chance of 0.0F will never drop + ///
  • A drop chance of 1.0F will always drop + ///
+ pub fn item_drop_chance(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref().call_method( &self.jni_object(), - "sleep", + "getItemDropChance", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.f()?) } - /// Causes the player to wakeup if they are currently sleeping. - pub fn wakeup(&self, set_spawn_location: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(set_spawn_location.into()); + /// Sets the chance of the off hand item being dropped upon this frame's + /// destruction. + ///
    + ///
  • A drop chance of 0.0F will never drop + ///
  • A drop chance of 1.0F will always drop + ///
+ pub fn set_item_drop_chance(&self, chance: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(chance); let res = self.jni_ref().call_method( &self.jni_object(), - "wakeup", + "setItemDropChance", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the location of the bed the player is currently sleeping in - pub fn bed_location(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBedLocation", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets this human's current {@link GameMode} - pub fn game_mode(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/GameMode;"); + /// Get the rotation of the frame's item + pub fn rotation(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Rotation;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getGameMode", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getRotation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::GameMode::from_raw(&self.jni_ref(), unsafe { + crate::Rotation::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets this human's current {@link GameMode} - pub fn set_game_mode( + /// Set the rotation of the frame's item + pub fn set_rotation( &self, - mode: impl Into>, + rotation: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/GameMode;)V"); + let sig = String::from("(Lorg/bukkit/Rotation;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(mode.into().jni_object().clone()) + jni::objects::JObject::from_raw(rotation.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setGameMode", + "setRotation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check if the player is currently blocking (ie with a shield). - pub fn is_blocking(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isBlocking", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Check if the player currently has their hand raised (ie about to begin - /// blocking). - pub fn is_hand_raised(&self) -> Result> { + /// Returns whether the item frame is be visible or not. + pub fn is_visible(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isHandRaised", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isVisible", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get the total amount of experience required for the player to level - pub fn exp_to_level(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getExpToLevel", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the current cooldown for a player's attack. - /// This is used to calculate damage, with 1.0 representing a fully charged - /// attack and 0.0 representing a non-charged attack - pub fn attack_cooldown(&self) -> Result> { - let sig = String::from("()F"); + /// Sets whether the item frame should be visible or not. + pub fn set_visible(&self, visible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(visible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getAttackCooldown", + "setVisible", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Discover a recipe for this player such that it has not already been - /// discovered. This method will add the key's associated recipe to the - /// player's recipe book. - pub fn discover_recipe( - &self, - recipe: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) - }); + /// Returns whether the item frame is "fixed" or not. + /// When true it's not possible to destroy/move the frame (e.g. by damage, + /// interaction, pistons, or missing supporting blocks), rotate the item or + /// place/remove items. + pub fn is_fixed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFixed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the item frame should be fixed or not. + /// When set to true it's not possible to destroy/move the frame (e.g. by + /// damage, interaction, pistons, or missing supporting blocks), rotate the + /// item or place/remove items. + pub fn set_fixed(&self, fixed: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fixed.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "discoverRecipe", + "setFixed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Undiscover a recipe for this player such that it has already been - /// discovered. This method will remove the key's associated recipe from the - /// player's recipe book. - pub fn undiscover_recipe( + /// Sets the direction of the hanging entity, potentially overriding rules + /// of placement. Note that if the result is not valid the object would + /// normally drop as an item. + pub fn set_facing_direction( &self, - recipe: impl Into>, + face: impl Into>, + force: bool, ) -> Result> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)Z"); + let sig = String::from("(Lorg/bukkit/block/BlockFace;Z)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) + jni::objects::JObject::from_raw(face.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Bool(force.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "undiscoverRecipe", + "setFacingDirection", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Check whether or not this entity has discovered the specified recipe. - pub fn has_discovered_recipe( - &self, - recipe: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) - }); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for ItemFrame<'mc> { + fn into(self) -> crate::entity::Hanging<'mc> { + crate::entity::Hanging::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ItemFrame into crate::entity::Hanging") + } +} +#[repr(C)] +pub struct Guardian<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Guardian<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Guardian<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Guardian from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Guardian")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Guardian object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Guardian<'mc> { + /// Sets whether the guardian laser should show or not. + /// A target must be present. If no target is present the laser will not show + /// and the method will return false. + pub fn set_laser(&self, activated: bool) -> Result> { + let sig = String::from("(Z)Z"); + let val_1 = jni::objects::JValueGen::Bool(activated.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "hasDiscoveredRecipe", + "setLaser", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get an immutable set of recipes this entity has discovered. - pub fn discovered_recipes( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Gets whether the guardian laser is active or not. + pub fn has_laser(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasLaser", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the duration (in ticks) that a laser attack takes. + pub fn laser_duration(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getDiscoveredRecipes", + "getLaserDuration", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - #[deprecated] - /// Gets the entity currently perched on the left shoulder or null if no entity. + /// Set the amount of ticks that have elapsed since this guardian has initiated + /// a laser attack. If set to {@link #getLaserDuration()} or greater, the guardian + /// will inflict damage upon its target and the laser attack will complete. /// - /// The returned entity will not be spawned within the world, so most operations are invalid unless the entity is first spawned in. - pub fn shoulder_entity_left( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + /// For this value to have any effect, the guardian must have an active target + /// (see {@link #setTarget(LivingEntity)}) and be charging a laser attack (where + /// {@link #hasLaser()} is true). The client may display a different animation of + /// the guardian laser than the set ticks. + pub fn set_laser_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "getShoulderEntityLeft", + "setLaserTicks", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the amount of ticks that have elapsed since this guardian has initiated + /// a laser attack. + /// + /// This value may or may not be significant depending on whether or not the guardian + /// has an active target ({@link #getTarget()}) and is charging a laser attack + /// ({@link #hasLaser()}). This value is not reset after a successful attack nor used + /// in the next and will be reset to the minimum value when the guardian initiates a + /// new one. + pub fn laser_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLaserTicks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } #[deprecated] - /// Sets the entity currently perched on the left shoulder, or null to remove. This method will remove the entity from the world. - /// - /// Note that only a copy of the entity will be set to display on the shoulder. - /// - /// Also note that the client will currently only render {@link Parrot} entities. - pub fn set_shoulder_entity_left( - &self, - entity: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) - }); + /// Check if the Guardian is an elder Guardian + pub fn is_elder(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isElder", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + + pub fn set_elder(&self, should_be_elder: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(should_be_elder.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setShoulderEntityLeft", + "setElder", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the entity currently perched on the right shoulder or null if no entity. + /// Check whether or not this guardian is moving. /// - /// The returned entity will not be spawned within the world, so most operations are invalid unless the entity is first spawned in. - pub fn shoulder_entity_right( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + /// While moving, the guardian's spikes are retracted and will not inflict thorns + /// damage upon entities that attack it. Additionally, a moving guardian cannot + /// attack another entity. If stationary (i.e. this method returns {@code false}), + /// thorns damage is guaranteed and the guardian may initiate laser attacks. + pub fn is_moving(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isMoving", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Guardian<'mc> { + fn into(self) -> crate::entity::Monster<'mc> { + crate::entity::Monster::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Guardian into crate::entity::Monster") + } +} +#[repr(C)] +pub struct TNTPrimed<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for TNTPrimed<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for TNTPrimed<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate TNTPrimed from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/TNTPrimed")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a TNTPrimed object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> TNTPrimed<'mc> { + /// Set the number of ticks until the TNT blows up after being primed. + pub fn set_fuse_ticks(&self, fuse_ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(fuse_ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "getShoulderEntityRight", + "setFuseTicks", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Retrieve the number of ticks until the explosion of this TNTPrimed + /// entity + pub fn fuse_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFuseTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the source of this primed TNT. The source is the entity + /// responsible for the creation of this primed TNT. (I.E. player ignites + /// TNT with flint and steel.) Take note that this can be null if there is + /// no suitable source. (created by the {@link + /// org.bukkit.World#spawn(Location, Class)} method, for example.) + /// + /// The source will become null if the chunk this primed TNT is in is + /// unloaded then reloaded. The source entity may be invalid if for example + /// it has since died or been unloaded. Callers should check + /// {@link Entity#isValid()}. + pub fn source(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSource", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); @@ -5331,694 +11162,658 @@ impl<'mc> Player<'mc> { unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - #[deprecated] - /// Sets the entity currently perched on the right shoulder, or null to remove. This method will remove the entity from the world. - /// - /// Note that only a copy of the entity will be set to display on the shoulder. + /// Sets the source of this primed TNT. + /// The source is the entity responsible for the creation of this primed TNT. /// - /// Also note that the client will currently only render {@link Parrot} entities. - pub fn set_shoulder_entity_right( + /// Must be instance of {@link org.bukkit.entity.LivingEntity} otherwise will + /// be set to null. The parameter is typed {@link + /// org.bukkit.entity.Entity} to be consistent with {@link + /// org.bukkit.entity.TNTPrimed#getSource()} method. + pub fn set_source( &self, - entity: impl Into>, + source: impl Into>, ) -> Result<(), Box> { let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + jni::objects::JObject::from_raw(source.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setShoulderEntityRight", + "setSource", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Make the entity drop the item in their hand. - /// - /// This will force the entity to drop the item they are holding with - /// an option to drop the entire {@link ItemStack} or just 1 of the items. - pub fn drop_item(&self, drop_all: bool) -> Result> { - let sig = String::from("(Z)Z"); - let val_1 = jni::objects::JValueGen::Bool(drop_all.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "dropItem", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the players current exhaustion level. - /// - /// Exhaustion controls how fast the food level drops. While you have a - /// certain amount of exhaustion, your saturation will drop to zero, and - /// then your food will drop to zero. - pub fn exhaustion(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getExhaustion", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Sets the players current exhaustion level - pub fn set_exhaustion(&self, value: f32) -> Result<(), Box> { + /// Set the radius affected by this explosive's explosion + pub fn set_yield(&self, val_yield: f32) -> Result<(), Box> { let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(value); + let val_1 = jni::objects::JValueGen::Float(val_yield); let res = self.jni_ref().call_method( &self.jni_object(), - "setExhaustion", + "setYield", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the players current saturation level. - /// - /// Saturation is a buffer for food level. Your food level will not drop if - /// you are saturated {@literal >} 0. - pub fn saturation(&self) -> Result> { + /// Return the radius or yield of this explosive's explosion + pub fn get_yield(&self) -> Result> { let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSaturation", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getYield", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.f()?) } - /// Sets the players current saturation level - pub fn set_saturation(&self, value: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(value); + /// Set whether or not this explosive's explosion causes fire + pub fn set_is_incendiary(&self, is_incendiary: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(is_incendiary.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setSaturation", + "setIsIncendiary", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the players current food level - pub fn food_level(&self) -> Result> { - let sig = String::from("()I"); + /// Return whether or not this explosive creates a fire when exploding + pub fn is_incendiary(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFoodLevel", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isIncendiary", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the players current food level - pub fn set_food_level(&self, value: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(value); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFoodLevel", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.z()?) } - /// Get the regeneration rate (1 health per x ticks) of - /// the HumanEntity when they have saturation and - /// their food level is {@literal >=} 20. Default is 10. - pub fn saturated_regen_rate(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSaturatedRegenRate", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Set the regeneration rate (1 health per x ticks) of - /// the HumanEntity when they have saturation and - /// their food level is {@literal >=} 20. Default is 10. - /// Not affected if the world's difficulty is peaceful. - pub fn set_saturated_regen_rate(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSaturatedRegenRate", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +} +impl<'mc> Into> for TNTPrimed<'mc> { + fn into(self) -> crate::entity::Explosive<'mc> { + crate::entity::Explosive::from_raw(&self.jni_ref(), self.1) + .expect("Error converting TNTPrimed into crate::entity::Explosive") } - /// Get the regeneration rate (1 health per x ticks) of - /// the HumanEntity when they have no saturation and - /// their food level is {@literal >=} 18. Default is 80. - pub fn unsaturated_regen_rate(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getUnsaturatedRegenRate", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) +} +#[repr(C)] +pub struct Bat<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Bat<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Get the regeneration rate (1 health per x ticks) of - /// the HumanEntity when they have no saturation and - /// their food level is {@literal >=} 18. Default is 80. - /// Not affected if the world's difficulty is peaceful. - pub fn set_unsaturated_regen_rate(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setUnsaturatedRegenRate", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Get the starvation rate (1 health per x ticks) of - /// the HumanEntity. Default is 80. - pub fn starvation_rate(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getStarvationRate", - sig.as_str(), - vec![], - ); +} +impl<'mc> JNIInstantiatable<'mc> for Bat<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Bat from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Bat")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Bat object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Bat<'mc> { + /// Checks the current waking state of this bat. + /// + /// This does not imply any persistence of state past the method call. + pub fn is_awake(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isAwake", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Get the starvation rate (1 health per x ticks) of - /// the HumanEntity. Default is 80. - pub fn set_starvation_rate(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// This method modifies the current waking state of this bat. + /// + /// This does not prevent a bat from spontaneously awaking itself, or from + /// reattaching itself to a block. + pub fn set_awake(&self, state: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(state.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setStarvationRate", + "setAwake", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the player's last death location. - pub fn last_death_location( - &self, - ) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/Location;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLastDeathLocation", - sig.as_str(), - args, - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Bat<'mc> { + fn into(self) -> crate::entity::Ambient<'mc> { + crate::entity::Ambient::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Bat into crate::entity::Ambient") + } +} +#[repr(C)] +pub struct Allay<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Allay<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Allay<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Allay from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Allay")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Allay object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) } - /// Sets the player's last death location. +} + +impl<'mc> Allay<'mc> { + /// Gets if the allay can duplicate. /// - /// Note: This data is updated in the player's client only when the - /// player respawns. - pub fn set_last_death_location( - &self, - location: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Location;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); + /// Note: Duplication is based when the + /// {@link #getDuplicationCooldown} its lower than zero. + pub fn can_duplicate(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "canDuplicate", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets if the allay can duplicate. + /// + /// Note: this value can be overridden later by + /// {@link #getDuplicationCooldown} if is lower than zero. You can also use + /// {@link #setDuplicationCooldown} to allow the allay to duplicate + pub fn set_can_duplicate(&self, can_duplicate: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(can_duplicate.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDeathLocation", + "setCanDuplicate", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Perform a firework boost. - /// - /// This method will only work such that {@link #isGliding()} is true and - /// the entity is actively gliding with an elytra. Additionally, the supplied - /// {@code fireworkItemStack} must be a firework rocket. The power of the boost - /// will directly correlate to {@link FireworkMeta#getPower()}. - pub fn firework_boost( - &self, - firework_item_stack: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/entity/Firework;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(firework_item_stack.into().jni_object().clone()) - }); + /// Gets the cooldown for duplicating the allay. + pub fn duplication_cooldown(&self) -> Result> { + let sig = String::from("()J"); let res = self.jni_ref().call_method( &self.jni_object(), - "fireworkBoost", + "getDuplicationCooldown", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Firework::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Tests to see of a Conversable object is actively engaged in a - /// conversation. - pub fn is_conversing(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isConversing", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.j()?) } - /// Accepts input into the active conversation. If no conversation is in - /// progress, this method does nothing. - pub fn accept_conversation_input( + /// Sets the cooldown before the allay can duplicate again. + pub fn set_duplication_cooldown( &self, - input: impl Into, + cooldown: i64, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(input.into())?, - )); + let sig = String::from("(J)V"); + let val_1 = jni::objects::JValueGen::Long(cooldown); let res = self.jni_ref().call_method( &self.jni_object(), - "acceptConversationInput", + "setDuplicationCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Enters into a dialog with a Conversation object. - pub fn begin_conversation( - &self, - conversation: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/conversations/Conversation;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(conversation.into().jni_object().clone()) - }); + /// Reset the cooldown for duplication. + /// This will set the cooldown ticks to the same value as is set after an + /// Allay has duplicated. + pub fn reset_duplication_cooldown(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref().call_method( &self.jni_object(), - "beginConversation", + "resetDuplicationCooldown", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the allay is dancing. + pub fn is_dancing(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isDancing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Abandons an active conversation. - pub fn abandon_conversation( + /// Causes the allay to start dancing because of the provided jukebox + /// location. + pub fn start_dancing( &self, - conversation: impl Into>, - details: std::option::Option< - impl Into>, - >, + location: std::option::Option>>, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/conversations/Conversation;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(conversation.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = details { - sig += "Lorg/bukkit/conversations/ConversationAbandonedEvent;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { + if let Some(a) = location { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); - args.push(val_2); + args.push(val_1); } sig += ")V"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "abandonConversation", - sig.as_str(), - args, - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "startDancing", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if this player is currently online - pub fn is_online(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isOnline", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Makes the allay stop dancing. + pub fn stop_dancing(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "stopDancing", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns the name of this player - /// - /// Names are no longer unique past a single game session. For persistent storage - /// it is recommended that you use {@link #getUniqueId()} instead. - pub fn name(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + /// This make the current allay duplicate itself without dance or item + /// necessary. + /// Note: this will fire a {@link CreatureSpawnEvent} + pub fn duplicate_allay( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Allay;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "duplicateAllay", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(Some(crate::entity::Allay::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Returns the UUID of this player - pub fn unique_id( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); + /// Gets the jukebox the allay is set to dance to. + pub fn jukebox(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getJukebox", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) + })?)) } - /// Gets a copy of the player's profile. - /// - /// If the player is online, the returned profile will be complete. - /// Otherwise, only the unique id is guaranteed to be present. You can use - /// {@link PlayerProfile#update()} to complete the returned profile. - pub fn player_profile( + /// Get the object's inventory. + pub fn inventory( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/profile/PlayerProfile;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPlayerProfile", - sig.as_str(), - vec![], - ); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::profile::PlayerProfile::from_raw(&self.jni_ref(), unsafe { + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Checks if this player has had their profile banned. - pub fn is_banned(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isBanned", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Checks if this player is whitelisted or not - pub fn is_whitelisted(&self) -> Result> { - let sig = String::from("()Z"); +} +impl<'mc> Into> for Allay<'mc> { + fn into(self) -> crate::entity::Creature<'mc> { + crate::entity::Creature::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Allay into crate::entity::Creature") + } +} +impl<'mc> Into> for Allay<'mc> { + fn into(self) -> crate::inventory::InventoryHolder<'mc> { + crate::inventory::InventoryHolder::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Allay into crate::inventory::InventoryHolder") + } +} +#[repr(C)] +pub struct Stray<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Stray<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Stray<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Stray from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Stray")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Stray object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Stray<'mc> { + #[deprecated] + /// Gets the current type of this skeleton. + pub fn skeleton_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Skeleton/SkeletonType;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isWhitelisted", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSkeletonType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::SkeletonSkeletonType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets if this player is whitelisted or not - pub fn set_whitelisted(&self, value: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(value.into()); + #[deprecated] + + pub fn set_skeleton_type( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Skeleton/SkeletonType;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setWhitelisted", + "setSkeletonType", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets a {@link Player} object that this represents, if there is one - /// - /// If the player is online, this will return that player. Otherwise, - /// it will return null. - pub fn player(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Player;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Player::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Gets the first date and time that this player was witnessed on this - /// server. - /// - /// If the player has never played before, this will return 0. Otherwise, - /// it will be the amount of milliseconds since midnight, January 1, 1970 - /// UTC. - pub fn first_played(&self) -> Result> { - let sig = String::from("()J"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFirstPlayed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) +} +impl<'mc> Into> for Stray<'mc> { + fn into(self) -> crate::entity::AbstractSkeleton<'mc> { + crate::entity::AbstractSkeleton::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Stray into crate::entity::AbstractSkeleton") } - /// Gets the last date and time that this player was witnessed on this - /// server. - /// - /// If the player has never played before, this will return 0. Otherwise, - /// it will be the amount of milliseconds since midnight, January 1, 1970 - /// UTC. - pub fn last_played(&self) -> Result> { - let sig = String::from("()J"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLastPlayed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) +} +#[repr(C)] +pub struct ZombieHorse<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ZombieHorse<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Checks if this player has played on this server before. - pub fn has_played_before(&self) -> Result> { - let sig = String::from("()Z"); + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for ZombieHorse<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate ZombieHorse from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ZombieHorse")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ZombieHorse object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> ZombieHorse<'mc> { + #[deprecated] + /// Gets the horse's variant.A horse's variant defines its physical appearance and capabilities. Whether a horse is a regular horse, donkey, mule, or other kind of horse is determined using the variant. + pub fn variant(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Horse/Variant;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasPlayedBefore", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::HorseVariant::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Increments the given statistic for this player for the given entity. - pub fn increment_statistic( + #[deprecated] + + pub fn set_variant( &self, - statistic: impl Into>, - entity_type: std::option::Option>>, - amount: std::option::Option, + variant: impl Into>, ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Statistic;"; + let sig = String::from("(Lorg/bukkit/entity/Horse/Variant;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(statistic.into().jni_object().clone()) + jni::objects::JObject::from_raw(variant.into().jni_object().clone()) }); - args.push(val_1); - if let Some(a) = entity_type { - sig += "Lorg/bukkit/entity/EntityType;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - if let Some(a) = amount { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - sig += ")V"; let res = self.jni_ref().call_method( &self.jni_object(), - "incrementStatistic", + "setVariant", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Decrements the given statistic for this player for the given entity. - pub fn decrement_statistic( - &self, - statistic: impl Into>, - entity_type: std::option::Option>>, - amount: std::option::Option, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Statistic;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(statistic.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = entity_type { - sig += "Lorg/bukkit/entity/EntityType;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - if let Some(a) = amount { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - sig += ")V"; + /// Gets the domestication level of this horse. + /// + /// A higher domestication level indicates that the horse is closer to + /// becoming tame. As the domestication level gets closer to the max + /// domestication level, the chance of the horse becoming tame increases. + pub fn domestication(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "decrementStatistic", + "getDomestication", sig.as_str(), - args, + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Sets the given statistic for this player for the given entity. - pub fn set_statistic( - &self, - statistic: impl Into>, - entity_type: impl Into>, - new_value: std::option::Option, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Statistic;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(statistic.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/entity/EntityType;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity_type.into().jni_object().clone()) - }); - args.push(val_2); - if let Some(a) = new_value { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setStatistic", sig.as_str(), args); + /// Sets the domestication level of this horse. + /// + /// Setting the domestication level to a high value will increase the + /// horse's chances of becoming tame. + /// + /// Domestication level must be greater than zero and no greater than + /// the max domestication level of the horse, determined with + /// {@link #getMaxDomestication()} + pub fn set_domestication(&self, level: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(level); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDomestication", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the value of the given statistic for this player. - pub fn get_statistic( - &self, - statistic: impl Into>, - entity_type: std::option::Option>>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Statistic;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(statistic.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = entity_type { - sig += "Lorg/bukkit/entity/EntityType;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")I"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getStatistic", sig.as_str(), args); + /// Gets the maximum domestication level of this horse. + /// + /// The higher this level is, the longer it will likely take + /// for the horse to be tamed. + pub fn max_domestication(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaxDomestication", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Gets the player's current location. - pub fn location(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); + /// Sets the maximum domestication level of this horse. + /// + /// Setting a higher max domestication will increase the amount of + /// domesticating (feeding, riding, etc.) necessary in order to tame it, + /// while setting a lower max value will have the opposite effect. + /// + /// Maximum domestication must be greater than zero. + pub fn set_max_domestication(&self, level: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(level); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaxDomestication", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the jump strength of this horse. + /// + /// Jump strength defines how high the horse can jump. A higher jump strength + /// increases how high a jump will go. + pub fn jump_strength(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getJumpStrength", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.d()?) } - /// Sends this recipient a Plugin Message on the specified outgoing - /// channel. + /// Sets the jump strength of this horse. /// - /// The message may not be larger than {@link Messenger#MAX_MESSAGE_SIZE} - /// bytes, and the plugin must be registered to send messages on the - /// specified channel. - pub fn send_plugin_message( - &self, - source: impl Into>, - channel: impl Into, - message: i8, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;Ljava/lang/String;B)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(source.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(channel.into())?, - )); - let val_3 = jni::objects::JValueGen::Byte(message); + /// A higher jump strength increases how high a jump will go. + /// Setting a jump strength to 0 will result in no jump. + /// You cannot set a jump strength to a value below 0 or + /// above 2. + pub fn set_jump_strength(&self, strength: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(strength); let res = self.jni_ref().call_method( &self.jni_object(), - "sendPluginMessage", + "setJumpStrength", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets a set containing all the Plugin Channels that this client is - /// listening on. - pub fn listening_plugin_channels( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Gets whether the horse is currently grazing hay. + pub fn is_eating_haystack(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getListeningPluginChannels", + "isEatingHaystack", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + Ok(res.z()?) + } + /// Sets whether the horse is grazing hay. + pub fn set_eating_haystack( + &self, + eating_haystack: bool, + ) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(eating_haystack.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setEatingHaystack", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/AbstractHorseInventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::AbstractHorseInventory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -6028,37 +11823,117 @@ impl<'mc> Player<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Player<'mc> { - fn into(self) -> crate::entity::HumanEntity<'mc> { - crate::entity::HumanEntity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Player into crate::entity::HumanEntity") +impl<'mc> Into> for ZombieHorse<'mc> { + fn into(self) -> crate::entity::AbstractHorse<'mc> { + crate::entity::AbstractHorse::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ZombieHorse into crate::entity::AbstractHorse") } } -impl<'mc> Into> for Player<'mc> { - fn into(self) -> crate::conversations::Conversable<'mc> { - crate::conversations::Conversable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Player into crate::conversations::Conversable") +#[repr(C)] +pub struct SplashPotion<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for SplashPotion<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> Into> for Player<'mc> { - fn into(self) -> crate::OfflinePlayer<'mc> { - crate::OfflinePlayer::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Player into crate::OfflinePlayer") +impl<'mc> JNIInstantiatable<'mc> for SplashPotion<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate SplashPotion from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/SplashPotion")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a SplashPotion object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } } -impl<'mc> Into> for Player<'mc> { - fn into(self) -> crate::plugin::messaging::PluginMessageRecipient<'mc> { - crate::plugin::messaging::PluginMessageRecipient::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Player into crate::plugin::messaging::PluginMessageRecipient") + +impl<'mc> SplashPotion<'mc> { + /// Returns the effects that are applied by this potion. + pub fn effects( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEffects", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Gets the ItemStack the thrown projectile will display. + pub fn item(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/inventory/ItemStack;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getItem", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the display ItemStack for the thrown projectile. + pub fn set_item( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setItem", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for SplashPotion<'mc> { + fn into(self) -> crate::entity::ThrownPotion<'mc> { + crate::entity::ThrownPotion::from_raw(&self.jni_ref(), self.1) + .expect("Error converting SplashPotion into crate::entity::ThrownPotion") } } #[repr(C)] -pub struct Golem<'mc>( +pub struct LeashHitch<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Golem<'mc> { +impl<'mc> JNIRaw<'mc> for LeashHitch<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6066,18 +11941,18 @@ impl<'mc> JNIRaw<'mc> for Golem<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Golem<'mc> { +impl<'mc> JNIInstantiatable<'mc> for LeashHitch<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Golem from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate LeashHitch from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Golem")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/LeashHitch")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Golem object, got {}", + "Invalid argument passed. Expected a LeashHitch object, got {}", name ) .into()) @@ -6087,25 +11962,51 @@ impl<'mc> JNIInstantiatable<'mc> for Golem<'mc> { } } -impl<'mc> Golem<'mc> { +impl<'mc> LeashHitch<'mc> { + /// Sets the direction of the hanging entity, potentially overriding rules + /// of placement. Note that if the result is not valid the object would + /// normally drop as an item. + pub fn set_facing_direction( + &self, + face: impl Into>, + force: bool, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;Z)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Bool(force.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFacingDirection", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Golem<'mc> { - fn into(self) -> crate::entity::Creature<'mc> { - crate::entity::Creature::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Golem into crate::entity::Creature") +impl<'mc> Into> for LeashHitch<'mc> { + fn into(self) -> crate::entity::Hanging<'mc> { + crate::entity::Hanging::from_raw(&self.jni_ref(), self.1) + .expect("Error converting LeashHitch into crate::entity::Hanging") } } #[repr(C)] -pub struct ThrownExpBottle<'mc>( +pub struct Spellcaster<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ThrownExpBottle<'mc> { +impl<'mc> JNIRaw<'mc> for Spellcaster<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6113,20 +12014,18 @@ impl<'mc> JNIRaw<'mc> for ThrownExpBottle<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ThrownExpBottle<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Spellcaster<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate ThrownExpBottle from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate Spellcaster from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ThrownExpBottle")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Spellcaster")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ThrownExpBottle object, got {}", + "Invalid argument passed. Expected a Spellcaster object, got {}", name ) .into()) @@ -6136,30 +12035,32 @@ impl<'mc> JNIInstantiatable<'mc> for ThrownExpBottle<'mc> { } } -impl<'mc> ThrownExpBottle<'mc> { - /// Gets the ItemStack the thrown projectile will display. - pub fn item(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); +impl<'mc> Spellcaster<'mc> { + /// Gets the {@link Spell} the entity is currently using. + pub fn spell( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Spellcaster/Spell;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSpell", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + crate::entity::SpellcasterSpell::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the display ItemStack for the thrown projectile. - pub fn set_item( + /// Sets the {@link Spell} the entity is currently using. + pub fn set_spell( &self, - item: impl Into>, + spell: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let sig = String::from("(Lorg/bukkit/entity/Spellcaster/Spell;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(spell.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setItem", + "setSpell", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -6172,31 +12073,58 @@ impl<'mc> ThrownExpBottle<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for ThrownExpBottle<'mc> { - fn into(self) -> crate::entity::ThrowableProjectile<'mc> { - crate::entity::ThrowableProjectile::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ThrownExpBottle into crate::entity::ThrowableProjectile") +impl<'mc> Into> for Spellcaster<'mc> { + fn into(self) -> crate::entity::Illager<'mc> { + crate::entity::Illager::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Spellcaster into crate::entity::Illager") } } -pub enum EntityCategory<'mc> {} -impl<'mc> std::fmt::Display for EntityCategory<'mc> { +pub enum SpellcasterSpell<'mc> { + None { inner: SpellcasterSpellStruct<'mc> }, + SummonVex { inner: SpellcasterSpellStruct<'mc> }, + Fangs { inner: SpellcasterSpellStruct<'mc> }, + Wololo { inner: SpellcasterSpellStruct<'mc> }, + Disappear { inner: SpellcasterSpellStruct<'mc> }, + Blindness { inner: SpellcasterSpellStruct<'mc> }, +} +impl<'mc> std::fmt::Display for SpellcasterSpell<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + SpellcasterSpell::None { .. } => f.write_str("NONE"), + SpellcasterSpell::SummonVex { .. } => f.write_str("SUMMON_VEX"), + SpellcasterSpell::Fangs { .. } => f.write_str("FANGS"), + SpellcasterSpell::Wololo { .. } => f.write_str("WOLOLO"), + SpellcasterSpell::Disappear { .. } => f.write_str("DISAPPEAR"), + SpellcasterSpell::Blindness { .. } => f.write_str("BLINDNESS"), + } + } +} +impl<'mc> std::ops::Deref for SpellcasterSpell<'mc> { + type Target = SpellcasterSpellStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + SpellcasterSpell::None { inner } => inner, + SpellcasterSpell::SummonVex { inner } => inner, + SpellcasterSpell::Fangs { inner } => inner, + SpellcasterSpell::Wololo { inner } => inner, + SpellcasterSpell::Disappear { inner } => inner, + SpellcasterSpell::Blindness { inner } => inner, + } } } -impl<'mc> EntityCategory<'mc> { +impl<'mc> SpellcasterSpell<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/EntityCategory"); + let cls = env.find_class("org/bukkit/entity/Spellcaster/Spell"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/EntityCategory;", + "(Ljava/lang/String;)Lorg/bukkit/entity/Spellcaster/Spell;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -6208,39 +12136,78 @@ impl<'mc> EntityCategory<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NONE" => Ok(SpellcasterSpell::None { + inner: SpellcasterSpellStruct::from_raw(env, obj)?, + }), + "SUMMON_VEX" => Ok(SpellcasterSpell::SummonVex { + inner: SpellcasterSpellStruct::from_raw(env, obj)?, + }), + "FANGS" => Ok(SpellcasterSpell::Fangs { + inner: SpellcasterSpellStruct::from_raw(env, obj)?, + }), + "WOLOLO" => Ok(SpellcasterSpell::Wololo { + inner: SpellcasterSpellStruct::from_raw(env, obj)?, + }), + "DISAPPEAR" => Ok(SpellcasterSpell::Disappear { + inner: SpellcasterSpellStruct::from_raw(env, obj)?, + }), + "BLINDNESS" => Ok(SpellcasterSpell::Blindness { + inner: SpellcasterSpellStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct EntityCategoryStruct<'mc>( +pub struct SpellcasterSpellStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EntityCategory<'mc> { +impl<'mc> JNIRaw<'mc> for SpellcasterSpell<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::None { inner } => inner.0.clone(), + Self::SummonVex { inner } => inner.0.clone(), + Self::Fangs { inner } => inner.0.clone(), + Self::Wololo { inner } => inner.0.clone(), + Self::Disappear { inner } => inner.0.clone(), + Self::Blindness { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::None { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SummonVex { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Fangs { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Wololo { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Disappear { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Blindness { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } -impl<'mc> JNIInstantiatable<'mc> for EntityCategory<'mc> { +impl<'mc> JNIInstantiatable<'mc> for SpellcasterSpell<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate EntityCategory from null object.").into(), + eyre::eyre!("Tried to instantiate SpellcasterSpell from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EntityCategory")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Spellcaster/Spell")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityCategory object, got {}", + "Invalid argument passed. Expected a SpellcasterSpell object, got {}", name ) .into()) @@ -6252,13 +12219,31 @@ impl<'mc> JNIInstantiatable<'mc> for EntityCategory<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NONE" => Ok(SpellcasterSpell::None { + inner: SpellcasterSpellStruct::from_raw(env, obj)?, + }), + "SUMMON_VEX" => Ok(SpellcasterSpell::SummonVex { + inner: SpellcasterSpellStruct::from_raw(env, obj)?, + }), + "FANGS" => Ok(SpellcasterSpell::Fangs { + inner: SpellcasterSpellStruct::from_raw(env, obj)?, + }), + "WOLOLO" => Ok(SpellcasterSpell::Wololo { + inner: SpellcasterSpellStruct::from_raw(env, obj)?, + }), + "DISAPPEAR" => Ok(SpellcasterSpell::Disappear { + inner: SpellcasterSpellStruct::from_raw(env, obj)?, + }), + "BLINDNESS" => Ok(SpellcasterSpell::Blindness { + inner: SpellcasterSpellStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for EntityCategoryStruct<'mc> { +impl<'mc> JNIRaw<'mc> for SpellcasterSpellStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6266,20 +12251,21 @@ impl<'mc> JNIRaw<'mc> for EntityCategoryStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EntityCategoryStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for SpellcasterSpellStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate EntityCategoryStruct from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate SpellcasterSpellStruct from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EntityCategory")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Spellcaster/Spell")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityCategoryStruct object, got {}", + "Invalid argument passed. Expected a SpellcasterSpellStruct object, got {}", name ) .into()) @@ -6289,17 +12275,17 @@ impl<'mc> JNIInstantiatable<'mc> for EntityCategoryStruct<'mc> { } } -impl<'mc> EntityCategoryStruct<'mc> { +impl<'mc> SpellcasterSpellStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); - let cls = jni.find_class("org/bukkit/entity/EntityCategory"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Spellcaster/Spell;"); + let cls = jni.find_class("org/bukkit/entity/Spellcaster/Spell"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::entity::EntityCategory::from_raw(&jni, obj) + crate::entity::SpellcasterSpell::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -6308,12 +12294,12 @@ impl<'mc> EntityCategoryStruct<'mc> { } } #[repr(C)] -pub struct Evoker<'mc>( +pub struct Interaction<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Evoker<'mc> { +impl<'mc> JNIRaw<'mc> for Interaction<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6321,18 +12307,18 @@ impl<'mc> JNIRaw<'mc> for Evoker<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Evoker<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Interaction<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Evoker from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Interaction from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Evoker")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Interaction")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Evoker object, got {}", + "Invalid argument passed. Expected a Interaction object, got {}", name ) .into()) @@ -6342,865 +12328,1235 @@ impl<'mc> JNIInstantiatable<'mc> for Evoker<'mc> { } } -impl<'mc> Evoker<'mc> { - #[deprecated] - /// Gets the {@link Spell} the Evoker is currently using. - pub fn current_spell( +impl<'mc> Interaction<'mc> { + /// Gets the width of this interaction entity. + pub fn interaction_width(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getInteractionWidth", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the width of this interaction entity. + pub fn set_interaction_width(&self, width: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(width); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setInteractionWidth", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the height of this interaction entity. + pub fn interaction_height(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getInteractionHeight", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the height of this interaction entity. + pub fn set_interaction_height(&self, height: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(height); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setInteractionHeight", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if this interaction entity should trigger a response when interacted + /// with. + pub fn is_responsive(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isResponsive", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets if this interaction entity should trigger a response when interacted + /// with. + pub fn set_responsive(&self, response: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(response.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setResponsive", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the last attack on this interaction entity. + pub fn last_attack( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Evoker/Spell;"); + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/entity/Interaction/PreviousInteraction;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getCurrentSpell", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLastAttack", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::EvokerSpell::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::entity::InteractionPreviousInteraction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?, + )) + } + /// Gets the last interaction on this entity. + pub fn last_interaction( + &self, + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/entity/Interaction/PreviousInteraction;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLastInteraction", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::entity::InteractionPreviousInteraction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?, + )) + } + /// Stores the entity's current position in the provided Location object. + /// + /// If the provided Location is null this method does nothing and returns + /// null. + pub fn get_location( + &self, + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLocation", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) + })?)) } - #[deprecated] - /// Sets the {@link Spell} the Evoker is currently using. - pub fn set_current_spell( + /// Sets this entity's velocity in meters per tick + pub fn set_velocity( &self, - spell: impl Into>, + velocity: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Evoker/Spell;)V"); + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(spell.into().jni_object().clone()) + jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCurrentSpell", + "setVelocity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the {@link Spell} the entity is currently using. - pub fn spell( + /// Gets this entity's current velocity + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the entity's height + pub fn height(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the entity's width + pub fn width(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the entity's current bounding box. + /// + /// The returned bounding box reflects the entity's current location and + /// size. + pub fn bounding_box( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Spellcaster/Spell;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns true if the entity is supported by a block. This value is a + /// state updated by the server and is not recalculated unless the entity + /// moves. + pub fn is_on_ground(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns true if the entity is in water. + pub fn is_in_water(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getSpell", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::SpellcasterSpell::from_raw(&self.jni_ref(), unsafe { + Ok(res.z()?) + } + /// Gets the current world this entity resides in + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::World::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the {@link Spell} the entity is currently using. - pub fn set_spell( + /// Sets the entity's rotation. + /// + /// Note that if the entity is affected by AI, it may override this rotation. + pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { + let sig = String::from("(FF)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); + let val_2 = jni::objects::JValueGen::Float(pitch); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRotation", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Teleports this entity to the given location. If this entity is riding a + /// vehicle, it will be dismounted prior to teleportation. + pub fn teleport( &self, - spell: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Spellcaster/Spell;)V"); + location: impl Into>, + cause: std::option::Option< + impl Into>, + >, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(spell.into().jni_object().clone()) + jni::objects::JObject::from_raw(location.into().jni_object().clone()) }); + args.push(val_1); + if let Some(a) = cause { + sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "teleport", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns a list of entities within a bounding box centered around this + /// entity + pub fn get_nearby_entities( + &self, + x: f64, + y: f64, + z: f64, + ) -> Result>, Box> { + let sig = String::from("(DDD)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Double(x); + let val_2 = jni::objects::JValueGen::Double(y); + let val_3 = jni::objects::JValueGen::Double(z); let res = self.jni_ref().call_method( &self.jni_object(), - "setSpell", + "getNearbyEntities", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + /// Returns a unique id for this entity + pub fn entity_id(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} -impl<'mc> Into> for Evoker<'mc> { - fn into(self) -> crate::entity::Spellcaster<'mc> { - crate::entity::Spellcaster::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Evoker into crate::entity::Spellcaster") + /// Returns the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} -pub enum EvokerSpell<'mc> {} -impl<'mc> std::fmt::Display for EvokerSpell<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + /// Returns the entity's maximum fire ticks. + pub fn max_fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} - -impl<'mc> EvokerSpell<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/Evoker/Spell"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/Evoker/Spell;", + /// Sets the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFireTicks", + sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct EvokerSpellStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for EvokerSpell<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + self.jni_ref().translate_error(res)?; + Ok(()) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + /// Sets if the entity has visual fire (it will always appear to be on fire). + pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVisualFire", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -impl<'mc> JNIInstantiatable<'mc> for EvokerSpell<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate EvokerSpell from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Evoker/Spell")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EvokerSpell object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } + /// Gets if the entity has visual fire (it will always appear to be on fire). + pub fn is_visual_fire(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} - -impl<'mc> JNIRaw<'mc> for EvokerSpellStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Returns the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Returns the entity's maximum freeze ticks (amount of ticks before it will + /// be fully frozen) + pub fn max_freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaxFreezeTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} -impl<'mc> JNIInstantiatable<'mc> for EvokerSpellStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate EvokerSpellStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Evoker/Spell")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EvokerSpellStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Sets the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFreezeTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> EvokerSpellStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Evoker/Spell;"); - let cls = jni.find_class("org/bukkit/entity/Evoker/Spell"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::EvokerSpell::from_raw(&jni, obj) + /// Gets if the entity is fully frozen (it has been in powdered snow for max + /// freeze ticks). + pub fn is_frozen(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + /// Mark the entity's removal. + pub fn remove(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -#[repr(C)] -pub struct Piglin<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Piglin<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Returns true if this entity has been marked for removal. + pub fn is_dead(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Returns false if the entity has died, been despawned for some other + /// reason, or has not been added to the world. + pub fn is_valid(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for Piglin<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Piglin from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Piglin")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Piglin object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Gets the {@link Server} that contains this Entity + pub fn server(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Server;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Server::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} - -impl<'mc> Piglin<'mc> { - /// Get whether the piglin is able to hunt hoglins. - pub fn is_able_to_hunt(&self) -> Result> { + /// Returns true if the entity gets persisted. + /// + /// By default all entities are persistent. An entity will also not get + /// persisted, if it is riding an entity that is not persistent. + /// + /// The persistent flag on players controls whether or not to save their + /// playerdata file when they quit. If a player is directly or indirectly + /// riding a non-persistent entity, the vehicle at the root and all its + /// passengers won't get persisted. + /// + /// This should not be confused with + /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls + /// despawning of living entities. + pub fn is_persistent(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isAbleToHunt", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the piglin is able to hunt hoglins. - pub fn set_is_able_to_hunt(&self, flag: bool) -> Result<(), Box> { + /// Sets whether or not the entity gets persisted. + pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(persistent.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setIsAbleToHunt", + "setPersistent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Adds a material to the allowed list of materials to barter with. - pub fn add_barter_material( + #[deprecated] + /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. + pub fn passenger( &self, - material: impl Into>, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + #[deprecated] + /// Set the passenger of a vehicle. + pub fn set_passenger( + &self, + passenger: impl Into>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/Material;)Z"); + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "addBarterMaterial", + "setPassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes a material from the allowed list of materials to barter with. - /// Note: It's not possible to override the default - /// bartering item gold_ingots as payment. To block gold_ingots see - /// {@link org.bukkit.event.entity.PiglinBarterEvent}. - pub fn remove_barter_material( + /// Gets a list of passengers of this vehicle. + /// + /// The returned list will not be directly linked to the entity's current + /// passengers, and no guarantees are made as to its mutability. + pub fn passengers( &self, - material: impl Into>, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Add a passenger to the vehicle. + pub fn add_passenger( + &self, + passenger: impl Into>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/Material;)Z"); + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeBarterMaterial", + "addPassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Adds a material the piglin will pickup and store in his inventory. - pub fn add_material_of_interest( + /// Remove a passenger from the vehicle. + pub fn remove_passenger( &self, - material: impl Into>, + passenger: impl Into>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/Material;)Z"); + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "addMaterialOfInterest", + "removePassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes a material from the list of materials the piglin will pickup. - /// Note: It's not possible to override the default list of - /// item the piglin will pickup. To cancel pickup see - /// {@link org.bukkit.event.entity.EntityPickupItemEvent}. - pub fn remove_material_of_interest( + /// Check if a vehicle has passengers. + pub fn is_empty(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Eject any passenger. + pub fn eject(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the distance this entity has fallen + pub fn fall_distance(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the fall distance for this entity + pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(distance); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFallDistance", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Record the last {@link EntityDamageEvent} inflicted on this entity + pub fn set_last_damage_cause( &self, - material: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/Material;)Z"); + event: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) + jni::objects::JObject::from_raw(event.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeMaterialOfInterest", + "setLastDamageCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. + /// This event may have been cancelled. + pub fn last_damage_cause( + &self, + ) -> Result>, Box> + { + let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLastDamageCause", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Returns a immutable set of materials the piglins will pickup. - /// - /// Note: This set will not include the items that are set - /// by default. To interact with those items see - /// {@link org.bukkit.event.entity.EntityPickupItemEvent}. - pub fn interest_list( + /// Returns a unique and persistent id for this entity + pub fn unique_id( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getInterestList", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns a immutable set of materials the piglins will barter with. - /// Note: This set will not include the items that are set - /// by default. To interact with those items see - /// {@link org.bukkit.event.entity.PiglinBarterEvent}. - pub fn barter_list( + /// Gets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. + pub fn ticks_lived(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. May not be less than one + /// tick. + pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTicksLived", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Performs the specified {@link EntityEffect} for this entity. + /// + /// This will be viewable to all players near the entity. + /// + /// If the effect is not applicable to this class of entity, it will not play. + pub fn play_effect( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "playEffect", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the type of the entity. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes while swimming. + pub fn swim_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBarterList", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets whether the piglin is immune to zombification. - pub fn is_immune_to_zombification(&self) -> Result> { - let sig = String::from("()Z"); + /// Get the {@link Sound} this entity makes when splashing in water. For most + /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_splash_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "isImmuneToZombification", + "getSwimSplashSound", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes when splashing in water at high + /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_high_speed_splash_sound( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSwimHighSpeedSplashSound", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns whether this entity is inside a vehicle. + pub fn is_inside_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the piglin is immune to zombification. - pub fn set_immune_to_zombification( + /// Leave the current vehicle. If the entity is currently in a vehicle (and + /// is removed from it), true will be returned, otherwise false will be + /// returned. + pub fn leave_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the vehicle that this entity is inside. If there is no vehicle, + /// null will be returned. + pub fn vehicle( &self, - flag: bool, - ) -> Result<(), Box> { + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets whether or not to display the mob's custom name client side. The + /// name will be displayed above the mob similarly to a player. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCustomNameVisible", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether or not the mob's custom name is displayed client side. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn is_custom_name_visible(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isCustomNameVisible", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(visible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setImmuneToZombification", + "setVisibleByDefault", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the amount of ticks until this entity will be converted to a - /// Zombified Piglin. - /// When this reaches 300, the entity will be converted. - pub fn conversion_time(&self) -> Result> { - let sig = String::from("()I"); + /// Gets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn is_visible_by_default(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getConversionTime", + "isVisibleByDefault", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the amount of ticks until this entity will be converted to a - /// Zombified Piglin. - /// When this reaches 0, the entity will be converted. A value of less than 0 - /// will stop the current conversion process without converting the current - /// entity. - pub fn set_conversion_time(&self, time: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(time); + /// Get all players that are currently tracking this entity. + /// + /// 'Tracking' means that this entity has been sent to the player and that + /// they are receiving updates on its state. Note that the client's {@code + /// 'Entity Distance'} setting does not affect the range at which entities + /// are tracked. + pub fn tracked_by( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets whether the entity has a team colored (default: white) glow. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setConversionTime", + "setGlowing", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get if this entity is in the process of converting to a Zombified Piglin. - pub fn is_converting(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isConverting", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Gets whether the piglin is a baby - pub fn is_baby(&self) -> Result> { + /// Gets whether the entity is glowing or not. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn is_glowing(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isBaby", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Sets whether the piglin is a baby - pub fn set_baby(&self, flag: bool) -> Result<(), Box> { + /// Sets whether the entity is invulnerable or not. + /// + /// When an entity is invulnerable it can only be damaged by players in + /// creative mode. + pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setBaby", + "setInvulnerable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the object's inventory. - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + /// Gets whether the entity is invulnerable or not. + pub fn is_invulnerable(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Piglin<'mc> { - fn into(self) -> crate::entity::PiglinAbstract<'mc> { - crate::entity::PiglinAbstract::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Piglin into crate::entity::PiglinAbstract") - } -} -impl<'mc> Into> for Piglin<'mc> { - fn into(self) -> crate::inventory::InventoryHolder<'mc> { - crate::inventory::InventoryHolder::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Piglin into crate::inventory::InventoryHolder") - } -} -#[repr(C)] -pub struct AnimalTamer<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for AnimalTamer<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for AnimalTamer<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate AnimalTamer from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/AnimalTamer")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a AnimalTamer object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + Ok(res.z()?) } -} - -impl<'mc> AnimalTamer<'mc> { - /// This is the name of the specified AnimalTamer. - pub fn name(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); + /// Gets whether the entity is silent or not. + pub fn is_silent(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// This is the UUID of the specified AnimalTamer. - pub fn unique_id( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct PufferFish<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PufferFish<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PufferFish<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate PufferFish from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/PufferFish")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PufferFish object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> PufferFish<'mc> { - /// Returns the current puff state of this fish (i.e. how inflated it is). - pub fn puff_state(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPuffState", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the current puff state of this fish (i.e. how inflated it is). - pub fn set_puff_state(&self, state: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(state); + /// Sets whether the entity is silent or not. + /// + /// When an entity is silent it will not produce any sound. + pub fn set_silent(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setPuffState", + "setSilent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for PufferFish<'mc> { - fn into(self) -> crate::entity::Fish<'mc> { - crate::entity::Fish::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PufferFish into crate::entity::Fish") - } -} -#[repr(C)] -pub struct Steerable<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Steerable<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Steerable<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Steerable from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Steerable")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Steerable object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Steerable<'mc> { - /// Check if the pig has a saddle. - pub fn has_saddle(&self) -> Result> { + /// Returns whether gravity applies to this entity. + pub fn has_gravity(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasSaddle", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets if the pig has a saddle or not - pub fn set_saddle(&self, saddled: bool) -> Result<(), Box> { + /// Sets whether gravity applies to this entity. + pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(saddled.into()); + let val_1 = jni::objects::JValueGen::Bool(gravity.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setSaddle", + "setGravity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the time in ticks this entity's movement is being increased. - /// Movement speed is often increased as a result of using the - /// {@link #getSteerMaterial()}. - pub fn boost_ticks(&self) -> Result> { + /// Gets the period of time (in ticks) before this entity can use a portal. + pub fn portal_cooldown(&self) -> Result> { let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBoostTicks", sig.as_str(), vec![]); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPortalCooldown", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Set the time in ticks this entity's movement will be increased. - /// This will reset the current boost ticks to 0 - /// ({@link #getCurrentBoostTicks()}). - pub fn set_boost_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Sets the period of time (in ticks) before this entity can use a portal. + pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + let val_1 = jni::objects::JValueGen::Int(cooldown); let res = self.jni_ref().call_method( &self.jni_object(), - "setBoostTicks", + "setPortalCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the time in ticks this entity's movement has been increased as of the - /// most recent boost. - /// Current boost ticks will never be {@literal >} {@link #getBoostTicks()}. - pub fn current_boost_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Returns a set of tags for this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn scoreboard_tags( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCurrentBoostTicks", + "getScoreboardTags", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the time in ticks this entity's movement has been increased relative - /// to the most recent boost. - pub fn set_current_boost_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Add a tag to this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn add_scoreboard_tag( + &self, + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setCurrentBoostTicks", + "addScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Get the material used to steer this entity when ridden by a player. - pub fn steer_material(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); + /// Removes a given tag from this entity. + pub fn remove_scoreboard_tag( + &self, + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "getSteerMaterial", + "removeScoreboardTag", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the reaction of the entity when moved by a piston. + pub fn piston_move_reaction( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPistonMoveReaction", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn breed_cause( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); + /// Get the closest cardinal {@link BlockFace} direction an entity is + /// currently facing. + /// + /// This will not return any non-cardinal directions such as + /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// + /// {@link Hanging} entities will override this call and thus their behavior + /// may be different. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn set_breed_cause( + /// Gets the entity's current pose. + /// Note that the pose is only updated at the end of a tick, so may be + /// inconsistent with other methods. eg {@link Player#isSneaking()} being + /// true does not imply the current pose will be {@link Pose#SNEAKING} + pub fn pose(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Pose;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the category of spawn to which this entity belongs. + pub fn spawn_category( &self, - uuid: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/UUID;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) - }); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreedCause", + "getSpawnCategory", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get whether or not this entity is in love mode and will produce - /// offspring with another entity in love mode. Will return true if - /// and only if {@link #getLoveModeTicks()} is greater than 0. - pub fn is_love_mode(&self) -> Result> { + /// Checks if this entity has been spawned in a world. + /// + /// Entities not spawned in a world will not tick, be sent to players, or be + /// saved to the server files. + pub fn is_in_world(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get the amount of ticks remaining for this entity in love mode. - /// If the entity is not in love mode, 0 will be returned. - pub fn love_mode_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLoveModeTicks", - sig.as_str(), - vec![], - ); + /// Get this entity as an NBT string. + /// + /// This string should not be relied upon as a serializable value. + pub fn as_string(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Set the amount of ticks for which this entity should be in love mode. - /// Setting the love mode ticks to 600 is the equivalent of a player - /// feeding the entity their breeding item of choice. - pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLoveModeTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Crates an {@link EntitySnapshot} representing the current state of this entity. + pub fn create_snapshot( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntitySnapshot::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Check if the provided ItemStack is the correct item used for breeding - /// this entity.. - pub fn is_breed_item( + /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// + /// Note: Players cannot be copied. + pub fn copy( &self, - material: impl Into>, - ) -> Result> { + to: std::option::Option>>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Z"; + if let Some(a) = to { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Lorg/bukkit/entity/Entity;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); + .call_method(&self.jni_object(), "copy", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -7208,19 +13564,19 @@ impl<'mc> Steerable<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Steerable<'mc> { - fn into(self) -> crate::entity::Animals<'mc> { - crate::entity::Animals::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Steerable into crate::entity::Animals") +impl<'mc> Into> for Interaction<'mc> { + fn into(self) -> crate::entity::Entity<'mc> { + crate::entity::Entity::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Interaction into crate::entity::Entity") } } #[repr(C)] -pub struct Dolphin<'mc>( +pub struct InteractionPreviousInteraction<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Dolphin<'mc> { +impl<'mc> JNIRaw<'mc> for InteractionPreviousInteraction<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -7228,18 +13584,22 @@ impl<'mc> JNIRaw<'mc> for Dolphin<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Dolphin<'mc> { +impl<'mc> JNIInstantiatable<'mc> for InteractionPreviousInteraction<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Dolphin from null object.").into()); + return Err(eyre::eyre!( + "Tried to instantiate InteractionPreviousInteraction from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Dolphin")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/entity/Interaction/PreviousInteraction")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Dolphin object, got {}", + "Invalid argument passed. Expected a InteractionPreviousInteraction object, got {}", name ) .into()) @@ -7249,25 +13609,40 @@ impl<'mc> JNIInstantiatable<'mc> for Dolphin<'mc> { } } -impl<'mc> Dolphin<'mc> { +impl<'mc> InteractionPreviousInteraction<'mc> { + /// Get the previous interacting player. + pub fn player(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/OfflinePlayer;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::OfflinePlayer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the Unix timestamp at when this interaction occurred. + pub fn timestamp(&self) -> Result> { + let sig = String::from("()J"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTimestamp", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.j()?) + } + pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Dolphin<'mc> { - fn into(self) -> crate::entity::WaterMob<'mc> { - crate::entity::WaterMob::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Dolphin into crate::entity::WaterMob") - } -} #[repr(C)] -pub struct Tadpole<'mc>( +pub struct Salmon<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Tadpole<'mc> { +impl<'mc> JNIRaw<'mc> for Salmon<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -7275,18 +13650,18 @@ impl<'mc> JNIRaw<'mc> for Tadpole<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Tadpole<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Salmon<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Tadpole from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Salmon from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Tadpole")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Salmon")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Tadpole object, got {}", + "Invalid argument passed. Expected a Salmon object, got {}", name ) .into()) @@ -7296,48 +13671,72 @@ impl<'mc> JNIInstantiatable<'mc> for Tadpole<'mc> { } } -impl<'mc> Tadpole<'mc> { - /// Gets the age of this mob. - pub fn age(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getAge", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) +impl<'mc> Salmon<'mc> { + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Sets the age of this mob. - pub fn set_age(&self, age: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(age); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAge", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +} +impl<'mc> Into> for Salmon<'mc> { + fn into(self) -> crate::entity::Fish<'mc> { + crate::entity::Fish::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Salmon into crate::entity::Fish") + } +} +#[repr(C)] +pub struct Fish<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Fish<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Fish<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Fish from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Fish")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Fish object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } +} +impl<'mc> Fish<'mc> { pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Tadpole<'mc> { - fn into(self) -> crate::entity::Fish<'mc> { - crate::entity::Fish::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Tadpole into crate::entity::Fish") +impl<'mc> Into> for Fish<'mc> { + fn into(self) -> crate::entity::WaterMob<'mc> { + crate::entity::WaterMob::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Fish into crate::entity::WaterMob") } } #[repr(C)] -pub struct Panda<'mc>( +pub struct TraderLlama<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Panda<'mc> { +impl<'mc> JNIRaw<'mc> for TraderLlama<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -7345,18 +13744,18 @@ impl<'mc> JNIRaw<'mc> for Panda<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Panda<'mc> { +impl<'mc> JNIInstantiatable<'mc> for TraderLlama<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Panda from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate TraderLlama from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Panda")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/TraderLlama")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Panda object, got {}", + "Invalid argument passed. Expected a TraderLlama object, got {}", name ) .into()) @@ -7366,327 +13765,310 @@ impl<'mc> JNIInstantiatable<'mc> for Panda<'mc> { } } -impl<'mc> Panda<'mc> { - /// Gets this Panda's main gene. - pub fn main_gene(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Panda/Gene;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMainGene", sig.as_str(), vec![]); +impl<'mc> TraderLlama<'mc> { + /// Gets the llama's color. + pub fn color(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Llama/Color;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::PandaGene::from_raw(&self.jni_ref(), unsafe { + crate::entity::LlamaColor::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets this Panda's main gene. - pub fn set_main_gene( + /// Sets the llama's color. + pub fn set_color( &self, - gene: impl Into>, + color: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Panda/Gene;)V"); + let sig = String::from("(Lorg/bukkit/entity/Llama/Color;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(gene.into().jni_object().clone()) + jni::objects::JObject::from_raw(color.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setMainGene", + "setColor", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets this Panda's hidden gene. - pub fn hidden_gene(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Panda/Gene;"); + /// Gets the llama's strength. A higher strength llama will have more + /// inventory slots and be more threatening to entities. + pub fn strength(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getHiddenGene", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::PandaGene::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets this Panda's hidden gene. - pub fn set_hidden_gene( - &self, - gene: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Panda/Gene;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(gene.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setHiddenGene", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether the Panda is rolling - pub fn is_rolling(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isRolling", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getStrength", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets whether the Panda is rolling - pub fn set_rolling(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Sets the llama's strength. A higher strength llama will have more + /// inventory slots and be more threatening to entities. Inventory slots are + /// equal to strength * 3. + pub fn set_strength(&self, strength: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(strength); let res = self.jni_ref().call_method( &self.jni_object(), - "setRolling", + "setStrength", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the Panda is sneezing - pub fn is_sneezing(&self) -> Result> { - let sig = String::from("()Z"); + + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/LlamaInventory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isSneezing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::LlamaInventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets whether the Panda is sneezing - pub fn set_sneezing(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSneezing", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Gets whether the Panda is on its back - pub fn is_on_back(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isOnBack", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} +impl<'mc> Into> for TraderLlama<'mc> { + fn into(self) -> crate::entity::Llama<'mc> { + crate::entity::Llama::from_raw(&self.jni_ref(), self.1) + .expect("Error converting TraderLlama into crate::entity::Llama") } - /// Sets whether the Panda is on its back - pub fn set_on_back(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); +} +#[repr(C)] +pub struct Warden<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Warden<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Warden<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Warden from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Warden")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Warden object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Warden<'mc> { + /// Gets the anger level of this warden. + /// Anger is an integer from 0 to 150. Once a Warden reaches 80 anger at a + /// target it will actively pursue it. + pub fn get_anger( + &self, + entity: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)I"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setOnBack", + "getAnger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether the Panda is eating - pub fn is_eating(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isEating", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets the Panda's eating status. The panda must be holding food for this to work - pub fn set_eating(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Increases the anger level of this warden. + /// Anger is an integer from 0 to 150. Once a Warden reaches 80 anger at a + /// target it will actively pursue it. + pub fn increase_anger( + &self, + entity: impl Into>, + increase: i32, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;I)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(increase); let res = self.jni_ref().call_method( &self.jni_object(), - "setEating", + "increaseAnger", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the Panda is scared - pub fn is_scared(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isScared", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets how many ticks the panda will be unhappy for - pub fn unhappy_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getUnhappyTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Get the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn breed_cause( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Set the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn set_breed_cause( + /// Sets the anger level of this warden. + /// Anger is an integer from 0 to 150. Once a Warden reaches 80 anger at a + /// target it will actively pursue it. + pub fn set_anger( &self, - uuid: impl Into>, + entity: impl Into>, + anger: i32, ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/UUID;)V"); + let sig = String::from("(Lorg/bukkit/entity/Entity;I)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Int(anger); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreedCause", + "setAnger", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get whether or not this entity is in love mode and will produce - /// offspring with another entity in love mode. Will return true if - /// and only if {@link #getLoveModeTicks()} is greater than 0. - pub fn is_love_mode(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the amount of ticks remaining for this entity in love mode. - /// If the entity is not in love mode, 0 will be returned. - pub fn love_mode_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Clears the anger level of this warden. + pub fn clear_anger( + &self, + entity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getLoveModeTicks", + "clearAnger", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Set the amount of ticks for which this entity should be in love mode. - /// Setting the love mode ticks to 600 is the equivalent of a player - /// feeding the entity their breeding item of choice. - pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Gets the {@link LivingEntity} at which this warden is most angry. + pub fn entity_angry_at( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setLoveModeTicks", + "getEntityAngryAt", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::LivingEntity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Check if the provided ItemStack is the correct item used for breeding - /// this entity.. - pub fn is_breed_item( + /// Make the warden sense a disturbance in the force at the location given. + pub fn set_disturbance_location( &self, - material: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; + location: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Location;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) + jni::objects::JObject::from_raw(location.into().jni_object().clone()) }); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Checks if this animal is sitting - pub fn is_sitting(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSitting", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets if this animal is sitting. Will remove any path that the animal - /// was following beforehand. - pub fn set_sitting(&self, sitting: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(sitting.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setSitting", + "setDisturbanceLocation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } + /// Get the level of anger of this warden. + pub fn anger_level( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Warden/AngerLevel;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAngerLevel", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::WardenAngerLevel::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Panda<'mc> { - fn into(self) -> crate::entity::Animals<'mc> { - crate::entity::Animals::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Panda into crate::entity::Animals") +impl<'mc> Into> for Warden<'mc> { + fn into(self) -> crate::entity::Monster<'mc> { + crate::entity::Monster::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Warden into crate::entity::Monster") } } -impl<'mc> Into> for Panda<'mc> { - fn into(self) -> crate::entity::Sittable<'mc> { - crate::entity::Sittable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Panda into crate::entity::Sittable") - } +pub enum WardenAngerLevel<'mc> { + Calm { inner: WardenAngerLevelStruct<'mc> }, + Agitated { inner: WardenAngerLevelStruct<'mc> }, + Angry { inner: WardenAngerLevelStruct<'mc> }, } -pub enum PandaGene<'mc> {} -impl<'mc> std::fmt::Display for PandaGene<'mc> { +impl<'mc> std::fmt::Display for WardenAngerLevel<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + WardenAngerLevel::Calm { .. } => f.write_str("CALM"), + WardenAngerLevel::Agitated { .. } => f.write_str("AGITATED"), + WardenAngerLevel::Angry { .. } => f.write_str("ANGRY"), + } + } +} +impl<'mc> std::ops::Deref for WardenAngerLevel<'mc> { + type Target = WardenAngerLevelStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + WardenAngerLevel::Calm { inner } => inner, + WardenAngerLevel::Agitated { inner } => inner, + WardenAngerLevel::Angry { inner } => inner, + } } } -impl<'mc> PandaGene<'mc> { +impl<'mc> WardenAngerLevel<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/Panda/Gene"); + let cls = env.find_class("org/bukkit/entity/Warden/AngerLevel"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/Panda/Gene;", + "(Ljava/lang/String;)Lorg/bukkit/entity/Warden/AngerLevel;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -7698,37 +14080,57 @@ impl<'mc> PandaGene<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "CALM" => Ok(WardenAngerLevel::Calm { + inner: WardenAngerLevelStruct::from_raw(env, obj)?, + }), + "AGITATED" => Ok(WardenAngerLevel::Agitated { + inner: WardenAngerLevelStruct::from_raw(env, obj)?, + }), + "ANGRY" => Ok(WardenAngerLevel::Angry { + inner: WardenAngerLevelStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct PandaGeneStruct<'mc>( +pub struct WardenAngerLevelStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PandaGene<'mc> { +impl<'mc> JNIRaw<'mc> for WardenAngerLevel<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Calm { inner } => inner.0.clone(), + Self::Agitated { inner } => inner.0.clone(), + Self::Angry { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Calm { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Agitated { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Angry { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for PandaGene<'mc> { +impl<'mc> JNIInstantiatable<'mc> for WardenAngerLevel<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate PandaGene from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate WardenAngerLevel from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Panda/Gene")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Warden/AngerLevel")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PandaGene object, got {}", + "Invalid argument passed. Expected a WardenAngerLevel object, got {}", name ) .into()) @@ -7740,13 +14142,22 @@ impl<'mc> JNIInstantiatable<'mc> for PandaGene<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "CALM" => Ok(WardenAngerLevel::Calm { + inner: WardenAngerLevelStruct::from_raw(env, obj)?, + }), + "AGITATED" => Ok(WardenAngerLevel::Agitated { + inner: WardenAngerLevelStruct::from_raw(env, obj)?, + }), + "ANGRY" => Ok(WardenAngerLevel::Angry { + inner: WardenAngerLevelStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for PandaGeneStruct<'mc> { +impl<'mc> JNIRaw<'mc> for WardenAngerLevelStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -7754,20 +14165,21 @@ impl<'mc> JNIRaw<'mc> for PandaGeneStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PandaGeneStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for WardenAngerLevelStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate PandaGeneStruct from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate WardenAngerLevelStruct from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Panda/Gene")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Warden/AngerLevel")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PandaGeneStruct object, got {}", + "Invalid argument passed. Expected a WardenAngerLevelStruct object, got {}", name ) .into()) @@ -7777,27 +14189,17 @@ impl<'mc> JNIInstantiatable<'mc> for PandaGeneStruct<'mc> { } } -impl<'mc> PandaGeneStruct<'mc> { +impl<'mc> WardenAngerLevelStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Panda/Gene;"); - let cls = jni.find_class("org/bukkit/entity/Panda/Gene"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Warden/AngerLevel;"); + let cls = jni.find_class("org/bukkit/entity/Warden/AngerLevel"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::entity::PandaGene::from_raw(&jni, obj) - } - /// Gets whether this gene is recessive, i.e. required in both parents to - /// propagate to children. - pub fn is_recessive(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isRecessive", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::WardenAngerLevel::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -7806,12 +14208,12 @@ impl<'mc> PandaGeneStruct<'mc> { } } #[repr(C)] -pub struct ThrownPotion<'mc>( +pub struct AreaEffectCloud<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ThrownPotion<'mc> { +impl<'mc> JNIRaw<'mc> for AreaEffectCloud<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -7819,18 +14221,20 @@ impl<'mc> JNIRaw<'mc> for ThrownPotion<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ThrownPotion<'mc> { +impl<'mc> JNIInstantiatable<'mc> for AreaEffectCloud<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ThrownPotion from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate AreaEffectCloud from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ThrownPotion")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/AreaEffectCloud")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ThrownPotion object, got {}", + "Invalid argument passed. Expected a AreaEffectCloud object, got {}", name ) .into()) @@ -7840,248 +14244,225 @@ impl<'mc> JNIInstantiatable<'mc> for ThrownPotion<'mc> { } } -impl<'mc> ThrownPotion<'mc> { - /// Returns the effects that are applied by this potion. - pub fn effects( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); +impl<'mc> AreaEffectCloud<'mc> { + /// Gets the duration which this cloud will exist for (in ticks). + pub fn duration(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getEffects", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDuration", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(res.i()?) } - /// Gets the ItemStack the thrown projectile will display. - pub fn item(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/inventory/ItemStack;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), args); + /// Sets the duration which this cloud will exist for (in ticks). + pub fn set_duration(&self, duration: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(duration); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDuration", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the time which an entity has to be exposed to the cloud before the + /// effect is applied. + pub fn wait_time(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getWaitTime", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Sets the display ItemStack for the thrown projectile. - pub fn set_item( - &self, - item: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setItem", sig.as_str(), args); + /// Sets the time which an entity has to be exposed to the cloud before the + /// effect is applied. + pub fn set_wait_time(&self, wait_time: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(wait_time); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setWaitTime", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for ThrownPotion<'mc> { - fn into(self) -> crate::entity::ThrowableProjectile<'mc> { - crate::entity::ThrowableProjectile::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ThrownPotion into crate::entity::ThrowableProjectile") + /// Gets the time that an entity will be immune from subsequent exposure. + pub fn reapplication_delay(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getReapplicationDelay", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} -#[repr(C)] -pub struct EnderPearl<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for EnderPearl<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Sets the time that an entity will be immune from subsequent exposure. + pub fn set_reapplication_delay(&self, delay: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(delay); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setReapplicationDelay", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets the amount that the duration of this cloud will decrease by when it + /// applies an effect to an entity. + pub fn duration_on_use(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDurationOnUse", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} -impl<'mc> JNIInstantiatable<'mc> for EnderPearl<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate EnderPearl from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EnderPearl")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EnderPearl object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Sets the amount that the duration of this cloud will decrease by when it + /// applies an effect to an entity. + pub fn set_duration_on_use(&self, duration: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(duration); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDurationOnUse", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> EnderPearl<'mc> { - /// Gets the ItemStack the thrown projectile will display. - pub fn item(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/inventory/ItemStack;"; + /// Gets the initial radius of the cloud. + pub fn radius(&self) -> Result> { + let sig = String::from("()F"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), args); + .call_method(&self.jni_object(), "getRadius", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.f()?) } - /// Sets the display ItemStack for the thrown projectile. - pub fn set_item( - &self, - item: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setItem", sig.as_str(), args); + /// Sets the initial radius of the cloud. + pub fn set_radius(&self, radius: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(radius); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRadius", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for EnderPearl<'mc> { - fn into(self) -> crate::entity::ThrowableProjectile<'mc> { - crate::entity::ThrowableProjectile::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EnderPearl into crate::entity::ThrowableProjectile") + /// Gets the amount that the radius of this cloud will decrease by when it + /// applies an effect to an entity. + pub fn radius_on_use(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRadiusOnUse", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) } -} -#[repr(C)] -pub struct ThrowableProjectile<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for ThrowableProjectile<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Sets the amount that the radius of this cloud will decrease by when it + /// applies an effect to an entity. + pub fn set_radius_on_use(&self, radius: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(radius); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRadiusOnUse", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets the amount that the radius of this cloud will decrease by each tick. + pub fn radius_per_tick(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getRadiusPerTick", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) } -} -impl<'mc> JNIInstantiatable<'mc> for ThrowableProjectile<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate ThrowableProjectile from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ThrowableProjectile")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ThrowableProjectile object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Gets the amount that the radius of this cloud will decrease by each tick. + pub fn set_radius_per_tick(&self, radius: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(radius); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRadiusPerTick", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> ThrowableProjectile<'mc> { - /// Gets the ItemStack the thrown projectile will display. - pub fn item(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/inventory/ItemStack;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), args); + /// Gets the particle which this cloud will be composed of + pub fn particle(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Particle;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getParticle", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + crate::Particle::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the display ItemStack for the thrown projectile. - pub fn set_item( + /// Sets the particle which this cloud will be composed of + pub fn set_particle( &self, - item: impl Into>, + particle: impl Into>, + data: std::option::Option>, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; + sig += "Lorg/bukkit/Particle;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(particle.into().jni_object().clone()) }); args.push(val_1); + if let Some(a) = data { + sig += "LT;"; + let val_2 = jni::objects::JValueGen::Object(a); + args.push(val_2); + } sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "setItem", sig.as_str(), args); + .call_method(&self.jni_object(), "setParticle", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the shooter of this projectile. - pub fn shooter( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/projectiles/ProjectileSource;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getShooter", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::projectiles::ProjectileSource::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Set the shooter of this projectile. - pub fn set_shooter( + #[deprecated] + /// Sets the underlying potion data + pub fn set_base_potion_data( &self, - source: impl Into>, + data: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/projectiles/ProjectileSource;)V"); + let sig = String::from("(Lorg/bukkit/potion/PotionData;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(source.into().jni_object().clone()) + jni::objects::JObject::from_raw(data.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setShooter", + "setBasePotionData", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -8089,475 +14470,230 @@ impl<'mc> ThrowableProjectile<'mc> { Ok(()) } #[deprecated] - /// Determine if this projectile should bounce or not when it hits. - pub fn does_bounce(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "doesBounce", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Set whether or not this projectile should bounce or not when it hits something. - pub fn set_bounce(&self, does_bounce: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(does_bounce.into()); + /// Returns the potion data about the base potion + pub fn base_potion_data( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/potion/PotionData;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setBounce", + "getBasePotionData", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for ThrowableProjectile<'mc> { - fn into(self) -> crate::entity::Projectile<'mc> { - crate::entity::Projectile::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ThrowableProjectile into crate::entity::Projectile") - } -} -#[repr(C)] -pub struct Blaze<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Blaze<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Blaze<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Blaze from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Blaze")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Blaze object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Blaze<'mc> { - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Blaze<'mc> { - fn into(self) -> crate::entity::Monster<'mc> { - crate::entity::Monster::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Blaze into crate::entity::Monster") - } -} -#[repr(C)] -pub struct Slime<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Slime<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Slime<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Slime from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Slime")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Slime object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Slime<'mc> { - pub fn size(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - - pub fn set_size(&self, sz: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(sz); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSize", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::potion::PotionData::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Instructs this Mob to set the specified LivingEntity as its target. - /// - /// Hostile creatures may attack their target, and friendly creatures may - /// follow their target. - pub fn set_target( + /// Sets the underlying potion type + pub fn set_base_potion_type( &self, - target: impl Into>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)V"); + let sig = String::from("(Lorg/bukkit/potion/PotionType;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setTarget", + "setBasePotionType", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the current target of this Mob - pub fn target( + /// Returns the potion type about the base potion + pub fn base_potion_type( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTarget", sig.as_str(), vec![]); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/potion/PotionType;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBasePotionType", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::LivingEntity::from_raw( + Ok(Some(crate::potion::PotionType::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets whether this mob is aware of its surroundings. - /// Unaware mobs will still move if pushed, attacked, etc. but will not move - /// or perform any actions on their own. Unaware mobs may also have other - /// unspecified behaviours disabled, such as drowning. - pub fn set_aware(&self, aware: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(aware.into()); + /// Checks for the presence of custom potion effects. + pub fn has_custom_effects(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "setAware", + "hasCustomEffects", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether this mob is aware of its surroundings. - /// Unaware mobs will still move if pushed, attacked, etc. but will not move - /// or perform any actions on their own. Unaware mobs may also have other - /// unspecified behaviours disabled, such as drowning. - pub fn is_aware(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isAware", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get the {@link Sound} this mob makes while ambiently existing. This sound - /// may change depending on the current state of the entity, and may also - /// return null under specific conditions. This sound is not constant. - /// For instance, villagers will make different passive noises depending - /// on whether or not they are actively trading with a player, or make no - /// ambient noise while sleeping. - pub fn ambient_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAmbientSound", sig.as_str(), vec![]); + /// Gets an immutable list containing all custom potion effects applied to + /// this cloud. + /// + /// Plugins should check that hasCustomEffects() returns true before calling + /// this method. + pub fn custom_effects( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCustomEffects", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Slime<'mc> { - fn into(self) -> crate::entity::Mob<'mc> { - crate::entity::Mob::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Slime into crate::entity::Mob") - } -} -impl<'mc> Into> for Slime<'mc> { - fn into(self) -> crate::entity::Enemy<'mc> { - crate::entity::Enemy::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Slime into crate::entity::Enemy") - } -} -#[repr(C)] -pub struct PiglinBrute<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PiglinBrute<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PiglinBrute<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate PiglinBrute from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/PiglinBrute")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PiglinBrute object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); } + Ok(new_vec) } -} - -impl<'mc> PiglinBrute<'mc> { - /// Gets whether the piglin is immune to zombification. - pub fn is_immune_to_zombification(&self) -> Result> { - let sig = String::from("()Z"); + /// Adds a custom potion effect to this cloud. + pub fn add_custom_effect( + &self, + effect: impl Into>, + overwrite: bool, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffect;Z)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Bool(overwrite.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "isImmuneToZombification", + "addCustomEffect", sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the piglin is immune to zombification. - pub fn set_immune_to_zombification( + /// Removes a custom potion effect from this cloud. + pub fn remove_custom_effect( &self, - flag: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + val_type: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setImmuneToZombification", + "removeCustomEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the amount of ticks until this entity will be converted to a - /// Zombified Piglin. - /// When this reaches 300, the entity will be converted. - pub fn conversion_time(&self) -> Result> { - let sig = String::from("()I"); + /// Checks for a specific custom potion effect type on this cloud. + pub fn has_custom_effect( + &self, + val_type: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getConversionTime", + "hasCustomEffect", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the amount of ticks until this entity will be converted to a - /// Zombified Piglin. - /// When this reaches 0, the entity will be converted. A value of less than 0 - /// will stop the current conversion process without converting the current - /// entity. - pub fn set_conversion_time(&self, time: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(time); + /// Removes all custom potion effects from this cloud. + pub fn clear_custom_effects(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref().call_method( &self.jni_object(), - "setConversionTime", + "clearCustomEffects", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get if this entity is in the process of converting to a Zombified Piglin. - pub fn is_converting(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isConverting", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Gets whether the piglin is a baby - pub fn is_baby(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the color of this cloud. Will be applied as a tint to its particles. + pub fn color(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Color;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isBaby", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Color::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - /// Sets whether the piglin is a baby - pub fn set_baby(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Sets the color of this cloud. Will be applied as a tint to its particles. + pub fn set_color( + &self, + color: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Color;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(color.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBaby", + "setColor", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for PiglinBrute<'mc> { - fn into(self) -> crate::entity::PiglinAbstract<'mc> { - crate::entity::PiglinAbstract::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PiglinBrute into crate::entity::PiglinAbstract") - } -} -#[repr(C)] -pub struct EvokerFangs<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for EvokerFangs<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for EvokerFangs<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate EvokerFangs from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EvokerFangs")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EvokerFangs object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> EvokerFangs<'mc> { - /// Gets the {@link LivingEntity} which summoned the fangs. - pub fn owner( + /// Retrieve the original source of this cloud. + pub fn source( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/projectiles/ProjectileSource;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSource", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::LivingEntity::from_raw( + Ok(Some(crate::projectiles::ProjectileSource::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets the {@link LivingEntity} which summoned the fangs. - pub fn set_owner( + /// Set the original source of this cloud. + pub fn set_source( &self, - owner: impl Into>, + source: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)V"); + let sig = String::from("(Lorg/bukkit/projectiles/ProjectileSource;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owner.into().jni_object().clone()) + jni::objects::JObject::from_raw(source.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setOwner", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the delay in ticks until the fang attacks. - pub fn attack_delay(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAttackDelay", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the delay in ticks until the fang attacks. - pub fn set_attack_delay(&self, delay: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(delay); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAttackDelay", + "setSource", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -8793,325 +14929,1007 @@ impl<'mc> EvokerFangs<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFireTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets if the entity has visual fire (it will always appear to be on fire). + pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVisualFire", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the entity has visual fire (it will always appear to be on fire). + pub fn is_visual_fire(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's maximum freeze ticks (amount of ticks before it will + /// be fully frozen) + pub fn max_freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaxFreezeTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFreezeTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the entity is fully frozen (it has been in powdered snow for max + /// freeze ticks). + pub fn is_frozen(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Mark the entity's removal. + pub fn remove(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns true if this entity has been marked for removal. + pub fn is_dead(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns false if the entity has died, been despawned for some other + /// reason, or has not been added to the world. + pub fn is_valid(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the {@link Server} that contains this Entity + pub fn server(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Server;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Server::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns true if the entity gets persisted. + /// + /// By default all entities are persistent. An entity will also not get + /// persisted, if it is riding an entity that is not persistent. + /// + /// The persistent flag on players controls whether or not to save their + /// playerdata file when they quit. If a player is directly or indirectly + /// riding a non-persistent entity, the vehicle at the root and all its + /// passengers won't get persisted. + /// + /// This should not be confused with + /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls + /// despawning of living entities. + pub fn is_persistent(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether or not the entity gets persisted. + pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(persistent.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPersistent", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. + pub fn passenger( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + #[deprecated] + /// Set the passenger of a vehicle. + pub fn set_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPassenger", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets a list of passengers of this vehicle. + /// + /// The returned list will not be directly linked to the entity's current + /// passengers, and no guarantees are made as to its mutability. + pub fn passengers( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Add a passenger to the vehicle. + pub fn add_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addPassenger", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Remove a passenger from the vehicle. + pub fn remove_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removePassenger", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Check if a vehicle has passengers. + pub fn is_empty(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Eject any passenger. + pub fn eject(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the distance this entity has fallen + pub fn fall_distance(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the fall distance for this entity + pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(distance); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFallDistance", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Record the last {@link EntityDamageEvent} inflicted on this entity + pub fn set_last_damage_cause( + &self, + event: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(event.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLastDamageCause", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. + /// This event may have been cancelled. + pub fn last_damage_cause( + &self, + ) -> Result>, Box> + { + let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLastDamageCause", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Returns a unique and persistent id for this entity + pub fn unique_id( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. + pub fn ticks_lived(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. May not be less than one + /// tick. + pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTicksLived", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Performs the specified {@link EntityEffect} for this entity. + /// + /// This will be viewable to all players near the entity. + /// + /// If the effect is not applicable to this class of entity, it will not play. + pub fn play_effect( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "playEffect", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the type of the entity. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes while swimming. + pub fn swim_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes when splashing in water. For most + /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_splash_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSwimSplashSound", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes when splashing in water at high + /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_high_speed_splash_sound( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSwimHighSpeedSplashSound", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns whether this entity is inside a vehicle. + pub fn is_inside_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Leave the current vehicle. If the entity is currently in a vehicle (and + /// is removed from it), true will be returned, otherwise false will be + /// returned. + pub fn leave_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the vehicle that this entity is inside. If there is no vehicle, + /// null will be returned. + pub fn vehicle( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets whether or not to display the mob's custom name client side. The + /// name will be displayed above the mob similarly to a player. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setFireTicks", + "setCustomNameVisible", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets if the entity has visual fire (it will always appear to be on fire). - pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { + /// Gets whether or not the mob's custom name is displayed client side. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn is_custom_name_visible(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isCustomNameVisible", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire.into()); + let val_1 = jni::objects::JValueGen::Bool(visible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisualFire", + "setVisibleByDefault", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity has visual fire (it will always appear to be on fire). - pub fn is_visual_fire(&self) -> Result> { + /// Gets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn is_visible_by_default(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the entity's maximum freeze ticks (amount of ticks before it will - /// be fully frozen) - pub fn max_freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getMaxFreezeTicks", + "isVisibleByDefault", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Get all players that are currently tracking this entity. + /// + /// 'Tracking' means that this entity has been sent to the player and that + /// they are receiving updates on its state. Note that the client's {@code + /// 'Entity Distance'} setting does not affect the range at which entities + /// are tracked. + pub fn tracked_by( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets whether the entity has a team colored (default: white) glow. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setFreezeTicks", + "setGlowing", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity is fully frozen (it has been in powdered snow for max - /// freeze ticks). - pub fn is_frozen(&self) -> Result> { + /// Gets whether the entity is glowing or not. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn is_glowing(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Mark the entity's removal. - pub fn remove(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); + /// Sets whether the entity is invulnerable or not. + /// + /// When an entity is invulnerable it can only be damaged by players in + /// creative mode. + pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setInvulnerable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns true if this entity has been marked for removal. - pub fn is_dead(&self) -> Result> { + /// Gets whether the entity is invulnerable or not. + pub fn is_invulnerable(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns false if the entity has died, been despawned for some other - /// reason, or has not been added to the world. - pub fn is_valid(&self) -> Result> { + /// Gets whether the entity is silent or not. + pub fn is_silent(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the {@link Server} that contains this Entity - pub fn server(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Server;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Server::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns true if the entity gets persisted. - /// - /// By default all entities are persistent. An entity will also not get - /// persisted, if it is riding an entity that is not persistent. - /// - /// The persistent flag on players controls whether or not to save their - /// playerdata file when they quit. If a player is directly or indirectly - /// riding a non-persistent entity, the vehicle at the root and all its - /// passengers won't get persisted. + /// Sets whether the entity is silent or not. /// - /// This should not be confused with - /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls - /// despawning of living entities. - pub fn is_persistent(&self) -> Result> { + /// When an entity is silent it will not produce any sound. + pub fn set_silent(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSilent", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns whether gravity applies to this entity. + pub fn has_gravity(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not the entity gets persisted. - pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { + /// Sets whether gravity applies to this entity. + pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(persistent.into()); + let val_1 = jni::objects::JValueGen::Bool(gravity.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setPersistent", + "setGravity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. - pub fn passenger( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); + /// Gets the period of time (in ticks) before this entity can use a portal. + pub fn portal_cooldown(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPortalCooldown", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - #[deprecated] - /// Set the passenger of a vehicle. - pub fn set_passenger( - &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); + /// Sets the period of time (in ticks) before this entity can use a portal. + pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(cooldown); let res = self.jni_ref().call_method( &self.jni_object(), - "setPassenger", + "setPortalCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets a list of passengers of this vehicle. + /// Returns a set of tags for this entity. /// - /// The returned list will not be directly linked to the entity's current - /// passengers, and no guarantees are made as to its mutability. - pub fn passengers( + /// Entities can have no more than 1024 tags. + pub fn scoreboard_tags( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getScoreboardTags", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Add a passenger to the vehicle. - pub fn add_passenger( + /// Add a tag to this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn add_scoreboard_tag( &self, - passenger: impl Into>, + tag: impl Into, ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "addPassenger", + "addScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Remove a passenger from the vehicle. - pub fn remove_passenger( + /// Removes a given tag from this entity. + pub fn remove_scoreboard_tag( &self, - passenger: impl Into>, + tag: impl Into, ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "removePassenger", + "removeScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Check if a vehicle has passengers. - pub fn is_empty(&self) -> Result> { + /// Returns the reaction of the entity when moved by a piston. + pub fn piston_move_reaction( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPistonMoveReaction", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the closest cardinal {@link BlockFace} direction an entity is + /// currently facing. + /// + /// This will not return any non-cardinal directions such as + /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// + /// {@link Hanging} entities will override this call and thus their behavior + /// may be different. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the entity's current pose. + /// Note that the pose is only updated at the end of a tick, so may be + /// inconsistent with other methods. eg {@link Player#isSneaking()} being + /// true does not imply the current pose will be {@link Pose#SNEAKING} + pub fn pose(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Pose;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the category of spawn to which this entity belongs. + pub fn spawn_category( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSpawnCategory", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Checks if this entity has been spawned in a world. + /// + /// Entities not spawned in a world will not tick, be sent to players, or be + /// saved to the server files. + pub fn is_in_world(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Eject any passenger. - pub fn eject(&self) -> Result> { + /// Get this entity as an NBT string. + /// + /// This string should not be relied upon as a serializable value. + pub fn as_string(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Crates an {@link EntitySnapshot} representing the current state of this entity. + pub fn create_snapshot( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntitySnapshot::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// + /// Note: Players cannot be copied. + pub fn copy( + &self, + to: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = to { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Lorg/bukkit/entity/Entity;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for AreaEffectCloud<'mc> { + fn into(self) -> crate::entity::Entity<'mc> { + crate::entity::Entity::from_raw(&self.jni_ref(), self.1) + .expect("Error converting AreaEffectCloud into crate::entity::Entity") + } +} +#[repr(C)] +pub struct Fox<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Fox<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Fox<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Fox from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Fox")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Fox object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Fox<'mc> { + /// Gets the current type of this fox. + pub fn fox_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Fox/Type;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFoxType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::FoxType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the current type of this fox. + pub fn set_fox_type( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Fox/Type;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFoxType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if this animal is crouching + pub fn is_crouching(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the distance this entity has fallen - pub fn fall_distance(&self) -> Result> { - let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCrouching", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + Ok(res.z()?) } - /// Sets the fall distance for this entity - pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(distance); + /// Sets if this animal is crouching. + pub fn set_crouching(&self, crouching: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(crouching.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setFallDistance", + "setCrouching", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Record the last {@link EntityDamageEvent} inflicted on this entity - pub fn set_last_damage_cause( - &self, - event: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(event.into().jni_object().clone()) - }); + /// Sets if this animal is sleeping. + pub fn set_sleeping(&self, sleeping: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(sleeping.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDamageCause", + "setSleeping", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. - /// This event may have been cancelled. - pub fn last_damage_cause( + /// Gets the first trusted player. + pub fn first_trusted_player( &self, - ) -> Result>, Box> - { - let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/AnimalTamer;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLastDamageCause", + "getFirstTrustedPlayer", sig.as_str(), vec![], ); @@ -9119,560 +15937,578 @@ impl<'mc> EvokerFangs<'mc> { if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( + Ok(Some(crate::entity::AnimalTamer::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Returns a unique and persistent id for this entity - pub fn unique_id( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. - pub fn ticks_lived(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. May not be less than one - /// tick. - pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(value); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTicksLived", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Performs the specified {@link EntityEffect} for this entity. - /// - /// This will be viewable to all players near the entity. + /// Set the first trusted player. /// - /// If the effect is not applicable to this class of entity, it will not play. - pub fn play_effect( + /// The first trusted player may only be removed after the second. + pub fn set_first_trusted_player( &self, - val_type: impl Into>, + player: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); + let sig = String::from("(Lorg/bukkit/entity/AnimalTamer;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "playEffect", + "setFirstTrustedPlayer", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the type of the entity. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity makes while swimming. - pub fn swim_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity makes when splashing in water. For most - /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_splash_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Gets the second trusted player. + pub fn second_trusted_player( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/AnimalTamer;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimSplashSound", + "getSecondTrustedPlayer", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::AnimalTamer::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Get the {@link Sound} this entity makes when splashing in water at high - /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_high_speed_splash_sound( + /// Set the second trusted player. + /// + /// The second trusted player may only be added after the first. + pub fn set_second_trusted_player( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + player: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/AnimalTamer;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(player.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimHighSpeedSplashSound", + "setSecondTrustedPlayer", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns whether this entity is inside a vehicle. - pub fn is_inside_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Leave the current vehicle. If the entity is currently in a vehicle (and - /// is removed from it), true will be returned, otherwise false will be - /// returned. - pub fn leave_vehicle(&self) -> Result> { + /// Gets whether the fox is faceplanting the ground + pub fn is_faceplanted(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isFaceplanted", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get the vehicle that this entity is inside. If there is no vehicle, - /// null will be returned. - pub fn vehicle( + /// Get the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn breed_cause( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/UUID;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Entity::from_raw( + Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets whether or not to display the mob's custom name client side. The - /// name will be displayed above the mob similarly to a player. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Set the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn set_breed_cause( + &self, + uuid: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/UUID;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomNameVisible", + "setBreedCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not the mob's custom name is displayed client side. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn is_custom_name_visible(&self) -> Result> { + /// Get whether or not this entity is in love mode and will produce + /// offspring with another entity in love mode. Will return true if + /// and only if {@link #getLoveModeTicks()} is greater than 0. + pub fn is_love_mode(&self) -> Result> { let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the amount of ticks remaining for this entity in love mode. + /// If the entity is not in love mode, 0 will be returned. + pub fn love_mode_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "isCustomNameVisible", + "getLoveModeTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(visible.into()); + /// Set the amount of ticks for which this entity should be in love mode. + /// Setting the love mode ticks to 600 is the equivalent of a player + /// feeding the entity their breeding item of choice. + pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisibleByDefault", + "setLoveModeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn is_visible_by_default(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isVisibleByDefault", - sig.as_str(), - vec![], - ); + /// Check if the provided ItemStack is the correct item used for breeding + /// this entity.. + pub fn is_breed_item( + &self, + material: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get all players that are currently tracking this entity. - /// - /// 'Tracking' means that this entity has been sent to the player and that - /// they are receiving updates on its state. Note that the client's {@code - /// 'Entity Distance'} setting does not affect the range at which entities - /// are tracked. - pub fn tracked_by( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); + /// Checks if this animal is sitting + pub fn is_sitting(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSitting", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets whether the entity has a team colored (default: white) glow. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { + /// Sets if this animal is sitting. Will remove any path that the animal + /// was following beforehand. + pub fn set_sitting(&self, sitting: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(sitting.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setGlowing", + "setSitting", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is glowing or not. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn is_glowing(&self) -> Result> { + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Fox<'mc> { + fn into(self) -> crate::entity::Animals<'mc> { + crate::entity::Animals::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Fox into crate::entity::Animals") + } +} +impl<'mc> Into> for Fox<'mc> { + fn into(self) -> crate::entity::Sittable<'mc> { + crate::entity::Sittable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Fox into crate::entity::Sittable") + } +} +pub enum FoxType<'mc> { + Red { inner: FoxTypeStruct<'mc> }, + Snow { inner: FoxTypeStruct<'mc> }, +} +impl<'mc> std::fmt::Display for FoxType<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + FoxType::Red { .. } => f.write_str("RED"), + FoxType::Snow { .. } => f.write_str("SNOW"), + } + } +} +impl<'mc> std::ops::Deref for FoxType<'mc> { + type Target = FoxTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + FoxType::Red { inner } => inner, + FoxType::Snow { inner } => inner, + } + } +} + +impl<'mc> FoxType<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/Fox/Type"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/Fox/Type;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "RED" => Ok(FoxType::Red { + inner: FoxTypeStruct::from_raw(env, obj)?, + }), + "SNOW" => Ok(FoxType::Snow { + inner: FoxTypeStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct FoxTypeStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for FoxType<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Red { inner } => inner.0.clone(), + Self::Snow { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Red { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Snow { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for FoxType<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate FoxType from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Fox/Type")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a FoxType object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "RED" => Ok(FoxType::Red { + inner: FoxTypeStruct::from_raw(env, obj)?, + }), + "SNOW" => Ok(FoxType::Snow { + inner: FoxTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for FoxTypeStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for FoxTypeStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate FoxTypeStruct from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Fox/Type")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a FoxTypeStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> FoxTypeStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Fox/Type;"); + let cls = jni.find_class("org/bukkit/entity/Fox/Type"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::FoxType::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct Donkey<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Donkey<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Donkey<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Donkey from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Donkey")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Donkey object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Donkey<'mc> { + /// Gets whether the horse has a chest equipped. + pub fn is_carrying_chest(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCarryingChest", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the entity is invulnerable or not. - /// - /// When an entity is invulnerable it can only be damaged by players in - /// creative mode. - pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { + /// Sets whether the horse has a chest equipped. Removing a chest will also + /// clear the chest's inventory. + pub fn set_carrying_chest(&self, chest: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(chest.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvulnerable", + "setCarryingChest", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invulnerable or not. - pub fn is_invulnerable(&self) -> Result> { - let sig = String::from("()Z"); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Donkey<'mc> { + fn into(self) -> crate::entity::ChestedHorse<'mc> { + crate::entity::ChestedHorse::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Donkey into crate::entity::ChestedHorse") + } +} +#[repr(C)] +pub struct Chicken<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Chicken<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Chicken<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Chicken from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Chicken")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Chicken object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Chicken<'mc> { + /// Get the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn breed_cause( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/UUID;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets whether the entity is silent or not. - pub fn is_silent(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets whether the entity is silent or not. - /// - /// When an entity is silent it will not produce any sound. - pub fn set_silent(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Set the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn set_breed_cause( + &self, + uuid: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/UUID;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setSilent", + "setBreedCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether gravity applies to this entity. - pub fn has_gravity(&self) -> Result> { + /// Get whether or not this entity is in love mode and will produce + /// offspring with another entity in love mode. Will return true if + /// and only if {@link #getLoveModeTicks()} is greater than 0. + pub fn is_love_mode(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether gravity applies to this entity. - pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gravity.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setGravity", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the period of time (in ticks) before this entity can use a portal. - pub fn portal_cooldown(&self) -> Result> { + /// Get the amount of ticks remaining for this entity in love mode. + /// If the entity is not in love mode, 0 will be returned. + pub fn love_mode_ticks(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPortalCooldown", + "getLoveModeTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the period of time (in ticks) before this entity can use a portal. - pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { + /// Set the amount of ticks for which this entity should be in love mode. + /// Setting the love mode ticks to 600 is the equivalent of a player + /// feeding the entity their breeding item of choice. + pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(cooldown); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setPortalCooldown", + "setLoveModeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a set of tags for this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn scoreboard_tags( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getScoreboardTags", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Add a tag to this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn add_scoreboard_tag( - &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addScoreboardTag", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Removes a given tag from this entity. - pub fn remove_scoreboard_tag( + /// Check if the provided ItemStack is the correct item used for breeding + /// this entity.. + pub fn is_breed_item( &self, - tag: impl Into, + material: impl Into>, ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removeScoreboardTag", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the reaction of the entity when moved by a piston. - pub fn piston_move_reaction( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPistonMoveReaction", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the closest cardinal {@link BlockFace} direction an entity is - /// currently facing. - /// - /// This will not return any non-cardinal directions such as - /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. - /// - /// {@link Hanging} entities will override this call and thus their behavior - /// may be different. - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the entity's current pose. - /// Note that the pose is only updated at the end of a tick, so may be - /// inconsistent with other methods. eg {@link Player#isSneaking()} being - /// true does not imply the current pose will be {@link Pose#SNEAKING} - pub fn pose(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Pose;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the category of spawn to which this entity belongs. - pub fn spawn_category( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSpawnCategory", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Checks if this entity has been spawned in a world. - /// - /// Entities not spawned in a world will not tick, be sent to players, or be - /// saved to the server files. - pub fn is_in_world(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get this entity as an NBT string. - /// - /// This string should not be relied upon as a serializable value. - pub fn as_string(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// Crates an {@link EntitySnapshot} representing the current state of this entity. - pub fn create_snapshot( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::EntitySnapshot::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Creates a copy of this entity and all its data. Spawns the copy at the given location. - /// - /// Note: Players cannot be copied. - pub fn copy( - &self, - to: std::option::Option>>, - ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = to { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")Lorg/bukkit/entity/Entity;"; + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); + .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -9680,19 +16516,19 @@ impl<'mc> EvokerFangs<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for EvokerFangs<'mc> { - fn into(self) -> crate::entity::Entity<'mc> { - crate::entity::Entity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EvokerFangs into crate::entity::Entity") +impl<'mc> Into> for Chicken<'mc> { + fn into(self) -> crate::entity::Animals<'mc> { + crate::entity::Animals::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Chicken into crate::entity::Animals") } } #[repr(C)] -pub struct Boss<'mc>( +pub struct EnderSignal<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Boss<'mc> { +impl<'mc> JNIRaw<'mc> for EnderSignal<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -9700,18 +16536,18 @@ impl<'mc> JNIRaw<'mc> for Boss<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Boss<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EnderSignal<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Boss from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate EnderSignal from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Boss")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EnderSignal")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Boss object, got {}", + "Invalid argument passed. Expected a EnderSignal object, got {}", name ) .into()) @@ -9721,23 +16557,123 @@ impl<'mc> JNIInstantiatable<'mc> for Boss<'mc> { } } -impl<'mc> Boss<'mc> { - /// Returns the {@link BossBar} of the {@link Boss} - pub fn boss_bar( +impl<'mc> EnderSignal<'mc> { + /// Get the location this EnderSignal is moving towards. + pub fn tarlocation(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTargetLocation", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Set the {@link Location} this EnderSignal is moving towards. + /// + /// When setting a new target location, the {@link #getDropItem()} resets to + /// a random value and the despawn timer gets set back to 0. + pub fn set_target_location( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/boss/BossBar;"); + location: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Location;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTargetLocation", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the EnderSignal should drop an item on death. + /// + /// If {@code true}, it will drop an item. If {@code false}, it will shatter. + pub fn drop_item(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBossBar", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDropItem", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::boss::BossBar::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) + } + /// Sets if the EnderSignal should drop an item on death; or if it should + /// shatter. + pub fn set_drop_item(&self, drop: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(drop.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDropItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the {@link ItemStack} to be displayed while in the air and to be + /// dropped on death. + pub fn item(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Set the {@link ItemStack} to be displayed while in the air and to be + /// dropped on death. + pub fn set_item( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the amount of time this entity has been alive (in ticks). + /// + /// When this number is greater than 80, it will despawn on the next tick. + pub fn despawn_timer(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDespawnTimer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set how long this entity has been alive (in ticks). + /// + /// When this number is greater than 80, it will despawn on the next tick. + pub fn set_despawn_timer(&self, timer: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(timer); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDespawnTimer", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } /// Stores the entity's current position in the provided Location object. /// @@ -10720,483 +17656,134 @@ impl<'mc> Boss<'mc> { let res = self.jni_ref().call_method( &self.jni_object(), "getPistonMoveReaction", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the closest cardinal {@link BlockFace} direction an entity is - /// currently facing. - /// - /// This will not return any non-cardinal directions such as - /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. - /// - /// {@link Hanging} entities will override this call and thus their behavior - /// may be different. - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the entity's current pose. - /// Note that the pose is only updated at the end of a tick, so may be - /// inconsistent with other methods. eg {@link Player#isSneaking()} being - /// true does not imply the current pose will be {@link Pose#SNEAKING} - pub fn pose(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Pose;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the category of spawn to which this entity belongs. - pub fn spawn_category( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSpawnCategory", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Checks if this entity has been spawned in a world. - /// - /// Entities not spawned in a world will not tick, be sent to players, or be - /// saved to the server files. - pub fn is_in_world(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get this entity as an NBT string. - /// - /// This string should not be relied upon as a serializable value. - pub fn as_string(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// Crates an {@link EntitySnapshot} representing the current state of this entity. - pub fn create_snapshot( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::EntitySnapshot::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Creates a copy of this entity and all its data. Spawns the copy at the given location. - /// - /// Note: Players cannot be copied. - pub fn copy( - &self, - to: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = to { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")Lorg/bukkit/entity/Entity;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Boss<'mc> { - fn into(self) -> crate::entity::Entity<'mc> { - crate::entity::Entity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Boss into crate::entity::Entity") - } -} -#[repr(C)] -pub struct Sheep<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Sheep<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Sheep<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Sheep from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Sheep")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Sheep object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Sheep<'mc> { - pub fn is_sheared(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSheared", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_sheared(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSheared", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn breed_cause( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Set the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn set_breed_cause( - &self, - uuid: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/UUID;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setBreedCause", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get whether or not this entity is in love mode and will produce - /// offspring with another entity in love mode. Will return true if - /// and only if {@link #getLoveModeTicks()} is greater than 0. - pub fn is_love_mode(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the amount of ticks remaining for this entity in love mode. - /// If the entity is not in love mode, 0 will be returned. - pub fn love_mode_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLoveModeTicks", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the amount of ticks for which this entity should be in love mode. - /// Setting the love mode ticks to 600 is the equivalent of a player - /// feeding the entity their breeding item of choice. - pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLoveModeTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Check if the provided ItemStack is the correct item used for breeding - /// this entity.. - pub fn is_breed_item( - &self, - material: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the color of this object. - /// - /// This may be null to represent the default color of an object, if the - /// object has a special default color (e.g Shulkers). - pub fn color(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/DyeColor;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::DyeColor::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Sets the color of this object to the specified DyeColor. - /// - /// This may be null to represent the default color of an object, if the - /// object has a special default color (e.g Shulkers). - pub fn set_color( - &self, - color: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/DyeColor;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setColor", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Sheep<'mc> { - fn into(self) -> crate::entity::Animals<'mc> { - crate::entity::Animals::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Sheep into crate::entity::Animals") - } -} -impl<'mc> Into> for Sheep<'mc> { - fn into(self) -> crate::material::Colorable<'mc> { - crate::material::Colorable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Sheep into crate::material::Colorable") - } -} -#[repr(C)] -pub struct ShulkerBullet<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for ShulkerBullet<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for ShulkerBullet<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ShulkerBullet from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ShulkerBullet")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ShulkerBullet object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} - -impl<'mc> ShulkerBullet<'mc> { - /// Retrieve the target of this bullet. - pub fn target(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + /// Get the closest cardinal {@link BlockFace} direction an entity is + /// currently facing. + /// + /// This will not return any non-cardinal directions such as + /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// + /// {@link Hanging} entities will override this call and thus their behavior + /// may be different. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getTarget", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the target of this bullet - pub fn set_target( + /// Gets the entity's current pose. + /// Note that the pose is only updated at the end of a tick, so may be + /// inconsistent with other methods. eg {@link Player#isSneaking()} being + /// true does not imply the current pose will be {@link Pose#SNEAKING} + pub fn pose(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Pose;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the category of spawn to which this entity belongs. + pub fn spawn_category( &self, - target: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) - }); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setTarget", + "getSpawnCategory", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Retrieve the shooter of this projectile. - pub fn shooter( + /// Checks if this entity has been spawned in a world. + /// + /// Entities not spawned in a world will not tick, be sent to players, or be + /// saved to the server files. + pub fn is_in_world(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get this entity as an NBT string. + /// + /// This string should not be relied upon as a serializable value. + pub fn as_string(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Crates an {@link EntitySnapshot} representing the current state of this entity. + pub fn create_snapshot( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/projectiles/ProjectileSource;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getShooter", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::projectiles::ProjectileSource::from_raw( + Ok(Some(crate::entity::EntitySnapshot::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Set the shooter of this projectile. - pub fn set_shooter( + /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// + /// Note: Players cannot be copied. + pub fn copy( &self, - source: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/projectiles/ProjectileSource;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(source.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setShooter", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Determine if this projectile should bounce or not when it hits. - pub fn does_bounce(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "doesBounce", sig.as_str(), vec![]); + to: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = to { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Lorg/bukkit/entity/Entity;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Set whether or not this projectile should bounce or not when it hits something. - pub fn set_bounce(&self, does_bounce: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(does_bounce.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setBounce", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -11204,19 +17791,19 @@ impl<'mc> ShulkerBullet<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for ShulkerBullet<'mc> { - fn into(self) -> crate::entity::Projectile<'mc> { - crate::entity::Projectile::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ShulkerBullet into crate::entity::Projectile") +impl<'mc> Into> for EnderSignal<'mc> { + fn into(self) -> crate::entity::Entity<'mc> { + crate::entity::Entity::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EnderSignal into crate::entity::Entity") } } #[repr(C)] -pub struct SizedFireball<'mc>( +pub struct ElderGuardian<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for SizedFireball<'mc> { +impl<'mc> JNIRaw<'mc> for ElderGuardian<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -11224,18 +17811,18 @@ impl<'mc> JNIRaw<'mc> for SizedFireball<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for SizedFireball<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ElderGuardian<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate SizedFireball from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate ElderGuardian from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/SizedFireball")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ElderGuardian")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SizedFireball object, got {}", + "Invalid argument passed. Expected a ElderGuardian object, got {}", name ) .into()) @@ -11245,113 +17832,116 @@ impl<'mc> JNIInstantiatable<'mc> for SizedFireball<'mc> { } } -impl<'mc> SizedFireball<'mc> { - /// Gets the display {@link ItemStack}. - pub fn display_item( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDisplayItem", sig.as_str(), vec![]); +impl<'mc> ElderGuardian<'mc> { + /// Sets whether the guardian laser should show or not. + /// A target must be present. If no target is present the laser will not show + /// and the method will return false. + pub fn set_laser(&self, activated: bool) -> Result> { + let sig = String::from("(Z)Z"); + let val_1 = jni::objects::JValueGen::Bool(activated.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLaser", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets the display {@link ItemStack} for the fireball. - pub fn set_display_item( - &self, - item: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); + /// Gets whether the guardian laser is active or not. + pub fn has_laser(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasLaser", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the duration (in ticks) that a laser attack takes. + pub fn laser_duration(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "setDisplayItem", + "getLaserDuration", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Sets the direction the fireball should be flying towards. - /// - /// This is a convenience method, it will change the velocity direction and - /// acceleration direction, while keeping the power the same. - /// - /// Note: This method only uses the direction of the vector and will - /// normalize (a copy of) it. + /// Set the amount of ticks that have elapsed since this guardian has initiated + /// a laser attack. If set to {@link #getLaserDuration()} or greater, the guardian + /// will inflict damage upon its target and the laser attack will complete. /// - /// Special Case: When the given direction is - /// {@link Vector#isZero() zero}, the velocity and acceleration will also be - /// set to zero without keeping the power. - pub fn set_direction( - &self, - direction: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(direction.into().jni_object().clone()) - }); + /// For this value to have any effect, the guardian must have an active target + /// (see {@link #setTarget(LivingEntity)}) and be charging a laser attack (where + /// {@link #hasLaser()} is true). The client may display a different animation of + /// the guardian laser than the set ticks. + pub fn set_laser_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setDirection", + "setLaserTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Retrieve the direction this fireball is heading toward. The returned vector is not normalized. - pub fn direction(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); + /// Get the amount of ticks that have elapsed since this guardian has initiated + /// a laser attack. + /// + /// This value may or may not be significant depending on whether or not the guardian + /// has an active target ({@link #getTarget()}) and is charging a laser attack + /// ({@link #hasLaser()}). This value is not reset after a successful attack nor used + /// in the next and will be reset to the minimum value when the guardian initiates a + /// new one. + pub fn laser_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLaserTicks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Sets the acceleration of the fireball. - /// The acceleration gets applied to the velocity every tick, depending on - /// the specific type of the fireball a damping / drag factor is applied so - /// that the velocity does not grow into infinity. - /// - /// Note: that the client may not respect non-default acceleration - /// power and will therefore mispredict the location of the fireball, causing - /// visual stutter. - pub fn set_acceleration( - &self, - acceleration: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(acceleration.into().jni_object().clone()) - }); + #[deprecated] + /// Check if the Guardian is an elder Guardian + pub fn is_elder(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isElder", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + + pub fn set_elder(&self, should_be_elder: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(should_be_elder.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setAcceleration", + "setElder", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the acceleration of this fireball. - pub fn acceleration(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAcceleration", sig.as_str(), vec![]); + /// Check whether or not this guardian is moving. + /// + /// While moving, the guardian's spikes are retracted and will not inflict thorns + /// damage upon entities that attack it. Additionally, a moving guardian cannot + /// attack another entity. If stationary (i.e. this method returns {@code false}), + /// thorns damage is guaranteed and the guardian may initiate laser attacks. + pub fn is_moving(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isMoving", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -11359,19 +17949,19 @@ impl<'mc> SizedFireball<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for SizedFireball<'mc> { - fn into(self) -> crate::entity::Fireball<'mc> { - crate::entity::Fireball::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SizedFireball into crate::entity::Fireball") +impl<'mc> Into> for ElderGuardian<'mc> { + fn into(self) -> crate::entity::Guardian<'mc> { + crate::entity::Guardian::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ElderGuardian into crate::entity::Guardian") } } #[repr(C)] -pub struct Firework<'mc>( +pub struct Ghast<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Firework<'mc> { +impl<'mc> JNIRaw<'mc> for Ghast<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -11379,18 +17969,18 @@ impl<'mc> JNIRaw<'mc> for Firework<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Firework<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Ghast<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Firework from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Ghast from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Firework")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Ghast")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Firework object, got {}", + "Invalid argument passed. Expected a Ghast object, got {}", name ) .into()) @@ -11400,250 +17990,197 @@ impl<'mc> JNIInstantiatable<'mc> for Firework<'mc> { } } -impl<'mc> Firework<'mc> { - /// Get a copy of the fireworks meta - pub fn firework_meta( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/FireworkMeta;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFireworkMeta", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::FireworkMeta::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Apply the provided meta to the fireworks - pub fn set_firework_meta( - &self, - meta: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/FireworkMeta;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(meta.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFireworkMeta", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Set the {@link LivingEntity} to which this firework is attached. - /// - /// When attached to an entity, the firework effect will act as normal but - /// remain positioned on the entity. If the entity {@code LivingEntity#isGliding() - /// is gliding}, then the entity will receive a boost in the direction that - /// they are looking. - pub fn set_attached_to( - &self, - entity: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAttachedTo", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the {@link LivingEntity} to which this firework is attached. - /// - /// When attached to an entity, the firework effect will act as normal but - /// remain positioned on the entity. If the entity {@code LivingEntity#isGliding() - /// is gliding}, then the entity will receive a boost in the direction that - /// they are looking. - pub fn attached_to( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAttachedTo", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::LivingEntity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Set the ticks that this firework has been alive. If this value exceeds - /// {@link #getMaxLife()}, the firework will detonate. - pub fn set_life(&self, ticks: i32) -> Result> { - let sig = String::from("(I)Z"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLife", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the ticks that this firework has been alive. When this value reaches - /// {@link #getMaxLife()}, the firework will detonate. - pub fn life(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getLife", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the time in ticks this firework will exist until it is detonated. - pub fn set_max_life(&self, ticks: i32) -> Result> { - let sig = String::from("(I)Z"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaxLife", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the time in ticks this firework will exist until it is detonated. - pub fn max_life(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaxLife", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Cause this firework to explode at earliest opportunity, as if it has no - /// remaining fuse. - pub fn detonate(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "detonate", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Check whether or not this firework has detonated. - pub fn is_detonated(&self) -> Result> { +impl<'mc> Ghast<'mc> { + /// Gets whether the Ghast is charging + pub fn is_charging(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isDetonated", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCharging", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets if the firework was shot at an angle (i.e. from a crossbow). - /// A firework which was not shot at an angle will fly straight upwards. - pub fn is_shot_at_angle(&self) -> Result> { + /// Sets whether the Ghast is charging + pub fn set_charging(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCharging", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Ghast<'mc> { + fn into(self) -> crate::entity::Flying<'mc> { + crate::entity::Flying::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Ghast into crate::entity::Flying") + } +} +impl<'mc> Into> for Ghast<'mc> { + fn into(self) -> crate::entity::Enemy<'mc> { + crate::entity::Enemy::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Ghast into crate::entity::Enemy") + } +} +#[repr(C)] +pub struct Vex<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Vex<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Vex<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Vex from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Vex")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Vex object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Vex<'mc> { + /// Gets the charging state of this entity. + /// When this entity is charging it will having a glowing red texture. + pub fn is_charging(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isShotAtAngle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCharging", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets if the firework was shot at an angle (i.e. from a crossbow). - /// A firework which was not shot at an angle will fly straight upwards. - pub fn set_shot_at_angle(&self, shot_at_angle: bool) -> Result<(), Box> { + /// Sets the charging state of this entity. + /// When this entity is charging it will having a glowing red texture. + pub fn set_charging(&self, charging: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(shot_at_angle.into()); + let val_1 = jni::objects::JValueGen::Bool(charging.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setShotAtAngle", + "setCharging", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the shooter of this projectile. - pub fn shooter( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/projectiles/ProjectileSource;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getShooter", sig.as_str(), vec![]); + /// Gets the bound of this entity. + /// An idle vex will navigate a 15x11x15 area centered around its bound + /// location. + /// When summoned by an Evoker, this location will be set to that of the + /// summoner. + pub fn bound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::projectiles::ProjectileSource::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Set the shooter of this projectile. - pub fn set_shooter( + /// Sets the bound of this entity. + /// An idle vex will navigate a 15x11x15 area centered around its bound + /// location. + /// When summoned by an Evoker, this location will be set to that of the + /// summoner. + pub fn set_bound( &self, - source: impl Into>, + location: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/projectiles/ProjectileSource;)V"); + let sig = String::from("(Lorg/bukkit/Location;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(source.into().jni_object().clone()) + jni::objects::JObject::from_raw(location.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setShooter", + "setBound", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Determine if this projectile should bounce or not when it hits. - pub fn does_bounce(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the remaining lifespan of this entity. + pub fn life_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "doesBounce", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLifeTicks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - #[deprecated] - /// Set whether or not this projectile should bounce or not when it hits something. - pub fn set_bounce(&self, does_bounce: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(does_bounce.into()); + /// Sets the remaining lifespan of this entity. + pub fn set_life_ticks(&self, life_ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(life_ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setBounce", + "setLifeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } + /// Gets if the entity has a limited life. + pub fn has_limited_life(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasLimitedLife", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Firework<'mc> { - fn into(self) -> crate::entity::Projectile<'mc> { - crate::entity::Projectile::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Firework into crate::entity::Projectile") +impl<'mc> Into> for Vex<'mc> { + fn into(self) -> crate::entity::Monster<'mc> { + crate::entity::Monster::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Vex into crate::entity::Monster") } } #[repr(C)] -pub struct ItemFrame<'mc>( +pub struct ItemDisplay<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ItemFrame<'mc> { +impl<'mc> JNIRaw<'mc> for ItemDisplay<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -11651,18 +18188,18 @@ impl<'mc> JNIRaw<'mc> for ItemFrame<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ItemFrame<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ItemDisplay<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ItemFrame from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate ItemDisplay from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ItemFrame")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ItemDisplay")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ItemFrame object, got {}", + "Invalid argument passed. Expected a ItemDisplay object, got {}", name ) .into()) @@ -11672,1853 +18209,1544 @@ impl<'mc> JNIInstantiatable<'mc> for ItemFrame<'mc> { } } -impl<'mc> ItemFrame<'mc> { - /// Get the item in this frame - pub fn item(&self) -> Result, Box> { +impl<'mc> ItemDisplay<'mc> { + /// Gets the displayed item stack. + pub fn item_stack( + &self, + ) -> Result>, Box> { let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemStack", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Set the item in this frame - pub fn set_item( + /// Sets the displayed item stack. + pub fn set_item_stack( &self, item: impl Into>, - play_sound: std::option::Option, ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); - args.push(val_1); - if let Some(a) = play_sound { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setItem", sig.as_str(), args); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItemStack", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the chance of the item being dropped upon this frame's destruction. - ///
    - ///
  • A drop chance of 0.0F will never drop - ///
  • A drop chance of 1.0F will always drop - ///
- pub fn item_drop_chance(&self) -> Result> { - let sig = String::from("()F"); + /// Gets the item display transform for this entity. + /// Defaults to {@link ItemDisplayTransform#FIXED}. + pub fn item_display_transform( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/entity/ItemDisplay/ItemDisplayTransform;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getItemDropChance", + "getItemDisplayTransform", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + crate::entity::ItemDisplayItemDisplayTransform::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the chance of the off hand item being dropped upon this frame's - /// destruction. - ///
    - ///
  • A drop chance of 0.0F will never drop - ///
  • A drop chance of 1.0F will always drop - ///
- pub fn set_item_drop_chance(&self, chance: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(chance); + /// Sets the item display transform for this entity. + /// Defaults to {@link ItemDisplayTransform#FIXED}. + pub fn set_item_display_transform( + &self, + display: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/ItemDisplay/ItemDisplayTransform;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(display.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemDropChance", + "setItemDisplayTransform", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the rotation of the frame's item - pub fn rotation(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Rotation;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRotation", sig.as_str(), vec![]); + /// Gets the transformation applied to this display. + pub fn transformation( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Transformation;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTransformation", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::Rotation::from_raw(&self.jni_ref(), unsafe { + crate::util::Transformation::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Set the rotation of the frame's item - pub fn set_rotation( + /// Sets the transformation applied to this display + pub fn set_transformation( &self, - rotation: impl Into>, + transformation: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Rotation;)V"); + let sig = String::from("(Lorg/bukkit/util/Transformation;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(rotation.into().jni_object().clone()) + jni::objects::JObject::from_raw(transformation.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setRotation", + "setTransformation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether the item frame is be visible or not. - pub fn is_visible(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isVisible", sig.as_str(), vec![]); + /// Sets the raw transformation matrix applied to this display + pub fn set_transformation_matrix( + &self, + transformation_matrix: jni::objects::JObject<'mc>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/joml/Matrix4f;)V"); + let val_1 = jni::objects::JValueGen::Object(transformation_matrix); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTransformationMatrix", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the interpolation duration of this display. + pub fn interpolation_duration(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getInterpolationDuration", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets whether the item frame should be visible or not. - pub fn set_visible(&self, visible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(visible.into()); + /// Sets the interpolation duration of this display. + pub fn set_interpolation_duration( + &self, + duration: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(duration); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisible", + "setInterpolationDuration", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether the item frame is "fixed" or not. - /// When true it's not possible to destroy/move the frame (e.g. by damage, - /// interaction, pistons, or missing supporting blocks), rotate the item or - /// place/remove items. - pub fn is_fixed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isFixed", sig.as_str(), vec![]); + /// Gets the teleport duration of this display. + ///
    + ///
  • 0 means that updates are applied immediately.
  • + ///
  • 1 means that the display entity will move from current position to the updated one over one tick.
  • + ///
  • Higher values spread the movement over multiple ticks.
  • + ///
+ pub fn teleport_duration(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTeleportDuration", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets whether the item frame should be fixed or not. - /// When set to true it's not possible to destroy/move the frame (e.g. by - /// damage, interaction, pistons, or missing supporting blocks), rotate the - /// item or place/remove items. - pub fn set_fixed(&self, fixed: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fixed.into()); + /// Sets the teleport duration of this display. + pub fn set_teleport_duration(&self, duration: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(duration); let res = self.jni_ref().call_method( &self.jni_object(), - "setFixed", + "setTeleportDuration", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets the direction of the hanging entity, potentially overriding rules - /// of placement. Note that if the result is not valid the object would - /// normally drop as an item. - pub fn set_facing_direction( - &self, - face: impl Into>, - force: bool, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;Z)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Bool(force.into()); + /// Gets the view distance/range of this display. + pub fn view_range(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getViewRange", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the view distance/range of this display. + pub fn set_view_range(&self, range: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(range); let res = self.jni_ref().call_method( &self.jni_object(), - "setFacingDirection", + "setViewRange", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + /// Gets the shadow radius of this display. + pub fn shadow_radius(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getShadowRadius", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) } -} -impl<'mc> Into> for ItemFrame<'mc> { - fn into(self) -> crate::entity::Hanging<'mc> { - crate::entity::Hanging::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ItemFrame into crate::entity::Hanging") + /// Sets the shadow radius of this display. + pub fn set_shadow_radius(&self, radius: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(radius); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setShadowRadius", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -#[repr(C)] -pub struct Guardian<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Guardian<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Gets the shadow strength of this display. + pub fn shadow_strength(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getShadowStrength", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Sets the shadow strength of this display. + pub fn set_shadow_strength(&self, strength: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(strength); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setShadowStrength", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -impl<'mc> JNIInstantiatable<'mc> for Guardian<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Guardian from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Guardian")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Guardian object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Gets the width of this display. + pub fn display_width(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDisplayWidth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) } -} - -impl<'mc> Guardian<'mc> { - /// Sets whether the guardian laser should show or not. - /// A target must be present. If no target is present the laser will not show - /// and the method will return false. - pub fn set_laser(&self, activated: bool) -> Result> { - let sig = String::from("(Z)Z"); - let val_1 = jni::objects::JValueGen::Bool(activated.into()); + /// Sets the width of this display. + pub fn set_display_width(&self, width: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(width); let res = self.jni_ref().call_method( &self.jni_object(), - "setLaser", + "setDisplayWidth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets whether the guardian laser is active or not. - pub fn has_laser(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasLaser", sig.as_str(), vec![]); + /// Gets the height of this display. + pub fn display_height(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDisplayHeight", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.f()?) } - /// Get the duration (in ticks) that a laser attack takes. - pub fn laser_duration(&self) -> Result> { + /// Sets the height if this display. + pub fn set_display_height(&self, height: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(height); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDisplayHeight", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the amount of ticks before client-side interpolation will commence. + pub fn interpolation_delay(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLaserDuration", + "getInterpolationDelay", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Set the amount of ticks that have elapsed since this guardian has initiated - /// a laser attack. If set to {@link #getLaserDuration()} or greater, the guardian - /// will inflict damage upon its target and the laser attack will complete. - /// - /// For this value to have any effect, the guardian must have an active target - /// (see {@link #setTarget(LivingEntity)}) and be charging a laser attack (where - /// {@link #hasLaser()} is true). The client may display a different animation of - /// the guardian laser than the set ticks. - pub fn set_laser_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Sets the amount of ticks before client-side interpolation will commence. + pub fn set_interpolation_delay(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setLaserTicks", + "setInterpolationDelay", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the amount of ticks that have elapsed since this guardian has initiated - /// a laser attack. - /// - /// This value may or may not be significant depending on whether or not the guardian - /// has an active target ({@link #getTarget()}) and is charging a laser attack - /// ({@link #hasLaser()}). This value is not reset after a successful attack nor used - /// in the next and will be reset to the minimum value when the guardian initiates a - /// new one. - pub fn laser_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the billboard setting of this entity. + /// The billboard setting controls the automatic rotation of the entity to + /// face the player. + pub fn billboard( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Display/Billboard;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLaserTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - #[deprecated] - /// Check if the Guardian is an elder Guardian - pub fn is_elder(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isElder", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBillboard", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::DisplayBillboard::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - - pub fn set_elder(&self, should_be_elder: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(should_be_elder.into()); + /// Sets the billboard setting of this entity. + /// The billboard setting controls the automatic rotation of the entity to + /// face the player. + pub fn set_billboard( + &self, + billboard: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Display/Billboard;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(billboard.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setElder", + "setBillboard", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check whether or not this guardian is moving. - /// - /// While moving, the guardian's spikes are retracted and will not inflict thorns - /// damage upon entities that attack it. Additionally, a moving guardian cannot - /// attack another entity. If stationary (i.e. this method returns {@code false}), - /// thorns damage is guaranteed and the guardian may initiate laser attacks. - pub fn is_moving(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isMoving", sig.as_str(), vec![]); + /// Gets the scoreboard team overridden glow color of this display. + pub fn glow_color_override( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Color;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getGlowColorOverride", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Guardian<'mc> { - fn into(self) -> crate::entity::Monster<'mc> { - crate::entity::Monster::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Guardian into crate::entity::Monster") - } -} -#[repr(C)] -pub struct TNTPrimed<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for TNTPrimed<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for TNTPrimed<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate TNTPrimed from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/TNTPrimed")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a TNTPrimed object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some(crate::Color::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } -} - -impl<'mc> TNTPrimed<'mc> { - /// Set the number of ticks until the TNT blows up after being primed. - pub fn set_fuse_ticks(&self, fuse_ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(fuse_ticks); + /// Sets the scoreboard team overridden glow color of this display. + pub fn set_glow_color_override( + &self, + color: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Color;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(color.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setFuseTicks", + "setGlowColorOverride", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the number of ticks until the explosion of this TNTPrimed - /// entity - pub fn fuse_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the brightness override of the entity. + pub fn brightness( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Display/Brightness;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFuseTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the source of this primed TNT. The source is the entity - /// responsible for the creation of this primed TNT. (I.E. player ignites - /// TNT with flint and steel.) Take note that this can be null if there is - /// no suitable source. (created by the {@link - /// org.bukkit.World#spawn(Location, Class)} method, for example.) - /// - /// The source will become null if the chunk this primed TNT is in is - /// unloaded then reloaded. The source entity may be invalid if for example - /// it has since died or been unloaded. Callers should check - /// {@link Entity#isValid()}. - pub fn source(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSource", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBrightness", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Entity::from_raw( + Ok(Some(crate::entity::DisplayBrightness::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets the source of this primed TNT. - /// The source is the entity responsible for the creation of this primed TNT. - /// - /// Must be instance of {@link org.bukkit.entity.LivingEntity} otherwise will - /// be set to null. The parameter is typed {@link - /// org.bukkit.entity.Entity} to be consistent with {@link - /// org.bukkit.entity.TNTPrimed#getSource()} method. - pub fn set_source( + /// Sets the brightness override of the entity. + pub fn set_brightness( &self, - source: impl Into>, + brightness: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + let sig = String::from("(Lorg/bukkit/entity/Display/Brightness;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(source.into().jni_object().clone()) + jni::objects::JObject::from_raw(brightness.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setSource", + "setBrightness", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Set the radius affected by this explosive's explosion - pub fn set_yield(&self, val_yield: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(val_yield); + /// Stores the entity's current position in the provided Location object. + /// + /// If the provided Location is null this method does nothing and returns + /// null. + pub fn get_location( + &self, + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setYield", + "getLocation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Return the radius or yield of this explosive's explosion - pub fn get_yield(&self) -> Result> { - let sig = String::from("()F"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getYield", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Set whether or not this explosive's explosion causes fire - pub fn set_is_incendiary(&self, is_incendiary: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(is_incendiary.into()); + /// Sets this entity's velocity in meters per tick + pub fn set_velocity( + &self, + velocity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setIsIncendiary", + "setVelocity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Return whether or not this explosive creates a fire when exploding - pub fn is_incendiary(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets this entity's current velocity + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isIncendiary", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> Into> for TNTPrimed<'mc> { - fn into(self) -> crate::entity::Explosive<'mc> { - crate::entity::Explosive::from_raw(&self.jni_ref(), self.1) - .expect("Error converting TNTPrimed into crate::entity::Explosive") + /// Gets the entity's height + pub fn height(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } -} -#[repr(C)] -pub struct Bat<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Bat<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Gets the entity's width + pub fn width(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets the entity's current bounding box. + /// + /// The returned bounding box reflects the entity's current location and + /// size. + pub fn bounding_box( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> JNIInstantiatable<'mc> for Bat<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Bat from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Bat")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Bat object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Returns true if the entity is supported by a block. This value is a + /// state updated by the server and is not recalculated unless the entity + /// moves. + pub fn is_on_ground(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} - -impl<'mc> Bat<'mc> { - /// Checks the current waking state of this bat. - /// - /// This does not imply any persistence of state past the method call. - pub fn is_awake(&self) -> Result> { + /// Returns true if the entity is in water. + pub fn is_in_water(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isAwake", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// This method modifies the current waking state of this bat. + /// Gets the current world this entity resides in + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the entity's rotation. /// - /// This does not prevent a bat from spontaneously awaking itself, or from - /// reattaching itself to a block. - pub fn set_awake(&self, state: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(state.into()); + /// Note that if the entity is affected by AI, it may override this rotation. + pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { + let sig = String::from("(FF)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); + let val_2 = jni::objects::JValueGen::Float(pitch); let res = self.jni_ref().call_method( &self.jni_object(), - "setAwake", + "setRotation", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Bat<'mc> { - fn into(self) -> crate::entity::Ambient<'mc> { - crate::entity::Ambient::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Bat into crate::entity::Ambient") + /// Teleports this entity to the given location. If this entity is riding a + /// vehicle, it will be dismounted prior to teleportation. + pub fn teleport( + &self, + location: impl Into>, + cause: std::option::Option< + impl Into>, + >, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = cause { + sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "teleport", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -#[repr(C)] -pub struct Allay<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Allay<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Returns a list of entities within a bounding box centered around this + /// entity + pub fn get_nearby_entities( + &self, + x: f64, + y: f64, + z: f64, + ) -> Result>, Box> { + let sig = String::from("(DDD)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Double(x); + let val_2 = jni::objects::JValueGen::Double(y); + let val_3 = jni::objects::JValueGen::Double(z); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNearbyEntities", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Returns a unique id for this entity + pub fn entity_id(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} -impl<'mc> JNIInstantiatable<'mc> for Allay<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Allay from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Allay")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Allay object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Returns the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} - -impl<'mc> Allay<'mc> { - /// Gets if the allay can duplicate. - /// - /// Note: Duplication is based when the - /// {@link #getDuplicationCooldown} its lower than zero. - pub fn can_duplicate(&self) -> Result> { - let sig = String::from("()Z"); + /// Returns the entity's maximum fire ticks. + pub fn max_fire_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "canDuplicate", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets if the allay can duplicate. - /// - /// Note: this value can be overridden later by - /// {@link #getDuplicationCooldown} if is lower than zero. You can also use - /// {@link #setDuplicationCooldown} to allow the allay to duplicate - pub fn set_can_duplicate(&self, can_duplicate: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(can_duplicate.into()); + /// Sets the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setCanDuplicate", + "setFireTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the cooldown for duplicating the allay. - pub fn duplication_cooldown(&self) -> Result> { - let sig = String::from("()J"); + /// Sets if the entity has visual fire (it will always appear to be on fire). + pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getDuplicationCooldown", + "setVisualFire", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the entity has visual fire (it will always appear to be on fire). + pub fn is_visual_fire(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + Ok(res.z()?) } - /// Sets the cooldown before the allay can duplicate again. - pub fn set_duplication_cooldown( - &self, - cooldown: i64, - ) -> Result<(), Box> { - let sig = String::from("(J)V"); - let val_1 = jni::objects::JValueGen::Long(cooldown); + /// Returns the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's maximum freeze ticks (amount of ticks before it will + /// be fully frozen) + pub fn max_freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "setDuplicationCooldown", + "getMaxFreezeTicks", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Reset the cooldown for duplication. - /// This will set the cooldown ticks to the same value as is set after an - /// Allay has duplicated. - pub fn reset_duplication_cooldown(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Sets the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "resetDuplicationCooldown", + "setFreezeTicks", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the allay is dancing. - pub fn is_dancing(&self) -> Result> { + /// Gets if the entity is fully frozen (it has been in powdered snow for max + /// freeze ticks). + pub fn is_frozen(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isDancing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Causes the allay to start dancing because of the provided jukebox - /// location. - pub fn start_dancing( - &self, - location: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = location { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "startDancing", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Makes the allay stop dancing. - pub fn stop_dancing(&self) -> Result<(), Box> { + /// Mark the entity's removal. + pub fn remove(&self) -> Result<(), Box> { let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "stopDancing", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// This make the current allay duplicate itself without dance or item - /// necessary. - /// Note: this will fire a {@link CreatureSpawnEvent} - pub fn duplicate_allay( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Allay;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "duplicateAllay", sig.as_str(), vec![]); + /// Returns true if this entity has been marked for removal. + pub fn is_dead(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Allay::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Gets the jukebox the allay is set to dance to. - pub fn jukebox(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getJukebox", sig.as_str(), vec![]); + /// Returns false if the entity has died, been despawned for some other + /// reason, or has not been added to the world. + pub fn is_valid(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.z()?) } - /// Get the object's inventory. - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + /// Gets the {@link Server} that contains this Entity + pub fn server(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Server;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + crate::Server::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Allay<'mc> { - fn into(self) -> crate::entity::Creature<'mc> { - crate::entity::Creature::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Allay into crate::entity::Creature") - } -} -impl<'mc> Into> for Allay<'mc> { - fn into(self) -> crate::inventory::InventoryHolder<'mc> { - crate::inventory::InventoryHolder::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Allay into crate::inventory::InventoryHolder") - } -} -#[repr(C)] -pub struct Boat<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Boat<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Boat<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Boat from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Boat")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Boat object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Boat<'mc> { - #[deprecated] - /// Gets the wood type of the boat. - pub fn wood_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/TreeSpecies;"); + /// Returns true if the entity gets persisted. + /// + /// By default all entities are persistent. An entity will also not get + /// persisted, if it is riding an entity that is not persistent. + /// + /// The persistent flag on players controls whether or not to save their + /// playerdata file when they quit. If a player is directly or indirectly + /// riding a non-persistent entity, the vehicle at the root and all its + /// passengers won't get persisted. + /// + /// This should not be confused with + /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls + /// despawning of living entities. + pub fn is_persistent(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getWoodType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::TreeSpecies::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - #[deprecated] - /// Sets the wood type of the boat. - pub fn set_wood_type( - &self, - species: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/TreeSpecies;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(species.into().jni_object().clone()) - }); + /// Sets whether or not the entity gets persisted. + pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(persistent.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setWoodType", + "setPersistent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the type of the boat. - pub fn boat_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Boat/Type;"); + #[deprecated] + /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. + pub fn passenger( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBoatType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::BoatType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the type of the boat. - pub fn set_boat_type( + #[deprecated] + /// Set the passenger of a vehicle. + pub fn set_passenger( &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Boat/Type;)V"); + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBoatType", + "setPassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - #[deprecated] - /// Gets the maximum speed of a boat. The speed is unrelated to the velocity. - pub fn max_speed(&self) -> Result> { - let sig = String::from("()D"); + /// Gets a list of passengers of this vehicle. + /// + /// The returned list will not be directly linked to the entity's current + /// passengers, and no guarantees are made as to its mutability. + pub fn passengers( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxSpeed", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - #[deprecated] - /// Sets the maximum speed of a boat. Must be nonnegative. Default is 0.4D. - pub fn set_max_speed(&self, speed: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(speed); + /// Add a passenger to the vehicle. + pub fn add_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxSpeed", + "addPassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Gets the deceleration rate (newSpeed = curSpeed * rate) of occupied boats. The default is 0.2. - pub fn occupied_deceleration(&self) -> Result> { - let sig = String::from("()D"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getOccupiedDeceleration", - sig.as_str(), - vec![], - ); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - #[deprecated] - /// Sets the deceleration rate (newSpeed = curSpeed * rate) of occupied boats. Setting this to a higher value allows for quicker acceleration. The default is 0.2. - pub fn set_occupied_deceleration(&self, rate: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(rate); + /// Remove a passenger from the vehicle. + pub fn remove_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setOccupiedDeceleration", + "removePassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Gets the deceleration rate (newSpeed = curSpeed * rate) of unoccupied boats. The default is -1. Values below 0 indicate that no additional deceleration is imposed. - pub fn unoccupied_deceleration(&self) -> Result> { - let sig = String::from("()D"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getUnoccupiedDeceleration", - sig.as_str(), - vec![], - ); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - #[deprecated] - /// Sets the deceleration rate (newSpeed = curSpeed * rate) of unoccupied boats. Setting this to a higher value allows for quicker deceleration of boats when a player disembarks. The default is -1. Values below 0 indicate that no additional deceleration is imposed. - pub fn set_unoccupied_deceleration(&self, rate: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(rate); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setUnoccupiedDeceleration", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Check if a vehicle has passengers. + pub fn is_empty(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - #[deprecated] - /// Get whether boats can work on land. - pub fn work_on_land(&self) -> Result> { + /// Eject any passenger. + pub fn eject(&self) -> Result> { let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the distance this entity has fallen + pub fn fall_distance(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getWorkOnLand", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.f()?) } - #[deprecated] - /// Set whether boats can work on land. - pub fn set_work_on_land(&self, work_on_land: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(work_on_land.into()); + /// Sets the fall distance for this entity + pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setWorkOnLand", + "setFallDistance", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the status of the boat. - pub fn status(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Boat/Status;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getStatus", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::BoatStatus::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the vehicle's velocity. - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the vehicle's velocity in meters per tick. - pub fn set_velocity( + #[deprecated] + /// Record the last {@link EntityDamageEvent} inflicted on this entity + pub fn set_last_damage_cause( &self, - vel: impl Into>, + event: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(vel.into().jni_object().clone()) + jni::objects::JObject::from_raw(event.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVelocity", + "setLastDamageCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Boat<'mc> { - fn into(self) -> crate::entity::Vehicle<'mc> { - crate::entity::Vehicle::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Boat into crate::entity::Vehicle") - } -} -pub enum BoatType<'mc> {} -impl<'mc> std::fmt::Display for BoatType<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> BoatType<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/Boat/Type"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/Boat/Type;", - vec![jni::objects::JValueGen::from(val_1)], + /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. + /// This event may have been cancelled. + pub fn last_damage_cause( + &self, + ) -> Result>, Box> + { + let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLastDamageCause", + sig.as_str(), + vec![], ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct BoatTypeStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for BoatType<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for BoatType<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate BoatType from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Boat/Type")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a BoatType object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for BoatTypeStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for BoatTypeStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate BoatTypeStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Boat/Type")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a BoatTypeStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } -} - -impl<'mc> BoatTypeStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Boat/Type;"); - let cls = jni.find_class("org/bukkit/entity/Boat/Type"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::BoatType::from_raw(&jni, obj) - } - /// Gets the material of the boat type. - pub fn material(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); + /// Returns a unique and persistent id for this entity + pub fn unique_id( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaterial", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -pub enum BoatStatus<'mc> {} -impl<'mc> std::fmt::Display for BoatStatus<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> BoatStatus<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/Boat/Status"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/Boat/Status;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct BoatStatusStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for BoatStatus<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for BoatStatus<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate BoatStatus from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Boat/Status")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a BoatStatus object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for BoatStatusStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for BoatStatusStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate BoatStatusStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Boat/Status")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a BoatStatusStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> BoatStatusStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Boat/Status;"); - let cls = jni.find_class("org/bukkit/entity/Boat/Status"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::BoatStatus::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct Stray<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Stray<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Stray<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Stray from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Stray")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Stray object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Stray<'mc> { - #[deprecated] - /// Gets the current type of this skeleton. - pub fn skeleton_type( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Skeleton/SkeletonType;"); + /// Gets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. + pub fn ticks_lived(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getSkeletonType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::SkeletonSkeletonType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - #[deprecated] - - pub fn set_skeleton_type( + /// Sets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. May not be less than one + /// tick. + pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTicksLived", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Performs the specified {@link EntityEffect} for this entity. + /// + /// This will be viewable to all players near the entity. + /// + /// If the effect is not applicable to this class of entity, it will not play. + pub fn play_effect( &self, - val_type: impl Into>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Skeleton/SkeletonType;)V"); + let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setSkeletonType", + "playEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Stray<'mc> { - fn into(self) -> crate::entity::AbstractSkeleton<'mc> { - crate::entity::AbstractSkeleton::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Stray into crate::entity::AbstractSkeleton") + /// Get the type of the entity. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -#[repr(C)] -pub struct ZombieHorse<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for ZombieHorse<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Get the {@link Sound} this entity makes while swimming. + pub fn swim_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Get the {@link Sound} this entity makes when splashing in water. For most + /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_splash_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSwimSplashSound", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> JNIInstantiatable<'mc> for ZombieHorse<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ZombieHorse from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ZombieHorse")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ZombieHorse object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Get the {@link Sound} this entity makes when splashing in water at high + /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_high_speed_splash_sound( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSwimHighSpeedSplashSound", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} - -impl<'mc> ZombieHorse<'mc> { - #[deprecated] - /// Gets the horse's variant.A horse's variant defines its physical appearance and capabilities. Whether a horse is a regular horse, donkey, mule, or other kind of horse is determined using the variant. - pub fn variant(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Horse/Variant;"); + /// Returns whether this entity is inside a vehicle. + pub fn is_inside_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Leave the current vehicle. If the entity is currently in a vehicle (and + /// is removed from it), true will be returned, otherwise false will be + /// returned. + pub fn leave_vehicle(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::HorseVariant::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - #[deprecated] - - pub fn set_variant( + /// Get the vehicle that this entity is inside. If there is no vehicle, + /// null will be returned. + pub fn vehicle( &self, - variant: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Horse/Variant;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(variant.into().jni_object().clone()) - }); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets whether or not to display the mob's custom name client side. The + /// name will be displayed above the mob similarly to a player. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setVariant", + "setCustomNameVisible", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the domestication level of this horse. + /// Gets whether or not the mob's custom name is displayed client side. /// - /// A higher domestication level indicates that the horse is closer to - /// becoming tame. As the domestication level gets closer to the max - /// domestication level, the chance of the horse becoming tame increases. - pub fn domestication(&self) -> Result> { - let sig = String::from("()I"); + /// This value has no effect on players, they will always display their + /// name. + pub fn is_custom_name_visible(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getDomestication", + "isCustomNameVisible", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the domestication level of this horse. - /// - /// Setting the domestication level to a high value will increase the - /// horse's chances of becoming tame. - /// - /// Domestication level must be greater than zero and no greater than - /// the max domestication level of the horse, determined with - /// {@link #getMaxDomestication()} - pub fn set_domestication(&self, level: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(level); + /// Sets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(visible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setDomestication", + "setVisibleByDefault", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the maximum domestication level of this horse. - /// - /// The higher this level is, the longer it will likely take - /// for the horse to be tamed. - pub fn max_domestication(&self) -> Result> { - let sig = String::from("()I"); + /// Gets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn is_visible_by_default(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getMaxDomestication", + "isVisibleByDefault", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the maximum domestication level of this horse. - /// - /// Setting a higher max domestication will increase the amount of - /// domesticating (feeding, riding, etc.) necessary in order to tame it, - /// while setting a lower max value will have the opposite effect. + /// Get all players that are currently tracking this entity. /// - /// Maximum domestication must be greater than zero. - pub fn set_max_domestication(&self, level: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(level); + /// 'Tracking' means that this entity has been sent to the player and that + /// they are receiving updates on its state. Note that the client's {@code + /// 'Entity Distance'} setting does not affect the range at which entities + /// are tracked. + pub fn tracked_by( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets whether the entity has a team colored (default: white) glow. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxDomestication", + "setGlowing", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the jump strength of this horse. - /// - /// Jump strength defines how high the horse can jump. A higher jump strength - /// increases how high a jump will go. - pub fn jump_strength(&self) -> Result> { - let sig = String::from("()D"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getJumpStrength", sig.as_str(), vec![]); + /// Gets whether the entity is glowing or not. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn is_glowing(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Sets the jump strength of this horse. + /// Sets whether the entity is invulnerable or not. /// - /// A higher jump strength increases how high a jump will go. - /// Setting a jump strength to 0 will result in no jump. - /// You cannot set a jump strength to a value below 0 or - /// above 2. - pub fn set_jump_strength(&self, strength: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(strength); + /// When an entity is invulnerable it can only be damaged by players in + /// creative mode. + pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setJumpStrength", + "setInvulnerable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the horse is currently grazing hay. - pub fn is_eating_haystack(&self) -> Result> { + /// Gets whether the entity is invulnerable or not. + pub fn is_invulnerable(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isEatingHaystack", - sig.as_str(), - vec![], - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the horse is grazing hay. - pub fn set_eating_haystack( - &self, - eating_haystack: bool, - ) -> Result<(), Box> { + /// Gets whether the entity is silent or not. + pub fn is_silent(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the entity is silent or not. + /// + /// When an entity is silent it will not produce any sound. + pub fn set_silent(&self, flag: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(eating_haystack.into()); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setEatingHaystack", + "setSilent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/AbstractHorseInventory;"); + /// Returns whether gravity applies to this entity. + pub fn has_gravity(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::AbstractHorseInventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for ZombieHorse<'mc> { - fn into(self) -> crate::entity::AbstractHorse<'mc> { - crate::entity::AbstractHorse::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ZombieHorse into crate::entity::AbstractHorse") + Ok(res.z()?) } -} -#[repr(C)] -pub struct SplashPotion<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for SplashPotion<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Sets whether gravity applies to this entity. + pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gravity.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setGravity", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets the period of time (in ticks) before this entity can use a portal. + pub fn portal_cooldown(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPortalCooldown", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} -impl<'mc> JNIInstantiatable<'mc> for SplashPotion<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate SplashPotion from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/SplashPotion")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a SplashPotion object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Sets the period of time (in ticks) before this entity can use a portal. + pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(cooldown); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPortalCooldown", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> SplashPotion<'mc> { - /// Returns the effects that are applied by this potion. - pub fn effects( + /// Returns a set of tags for this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn scoreboard_tags( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEffects", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Gets the ItemStack the thrown projectile will display. - pub fn item(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/inventory/ItemStack;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), args); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getScoreboardTags", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the display ItemStack for the thrown projectile. - pub fn set_item( + /// Add a tag to this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn add_scoreboard_tag( &self, - item: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setItem", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for SplashPotion<'mc> { - fn into(self) -> crate::entity::ThrownPotion<'mc> { - crate::entity::ThrownPotion::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SplashPotion into crate::entity::ThrownPotion") - } -} -#[repr(C)] -pub struct LeashHitch<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for LeashHitch<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for LeashHitch<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate LeashHitch from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/LeashHitch")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a LeashHitch object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addScoreboardTag", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} - -impl<'mc> LeashHitch<'mc> { - /// Sets the direction of the hanging entity, potentially overriding rules - /// of placement. Note that if the result is not valid the object would - /// normally drop as an item. - pub fn set_facing_direction( + /// Removes a given tag from this entity. + pub fn remove_scoreboard_tag( &self, - face: impl Into>, - force: bool, + tag: impl Into, ) -> Result> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;Z)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Bool(force.into()); + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setFacingDirection", + "removeScoreboardTag", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for LeashHitch<'mc> { - fn into(self) -> crate::entity::Hanging<'mc> { - crate::entity::Hanging::from_raw(&self.jni_ref(), self.1) - .expect("Error converting LeashHitch into crate::entity::Hanging") - } -} -#[repr(C)] -pub struct Spellcaster<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Spellcaster<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Returns the reaction of the entity when moved by a piston. + pub fn piston_move_reaction( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPistonMoveReaction", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> JNIInstantiatable<'mc> for Spellcaster<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Spellcaster from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Spellcaster")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Spellcaster object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Get the closest cardinal {@link BlockFace} direction an entity is + /// currently facing. + /// + /// This will not return any non-cardinal directions such as + /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// + /// {@link Hanging} entities will override this call and thus their behavior + /// may be different. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} - -impl<'mc> Spellcaster<'mc> { - /// Gets the {@link Spell} the entity is currently using. - pub fn spell( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Spellcaster/Spell;"); + /// Gets the entity's current pose. + /// Note that the pose is only updated at the end of a tick, so may be + /// inconsistent with other methods. eg {@link Player#isSneaking()} being + /// true does not imply the current pose will be {@link Pose#SNEAKING} + pub fn pose(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Pose;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getSpell", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::SpellcasterSpell::from_raw(&self.jni_ref(), unsafe { + crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the {@link Spell} the entity is currently using. - pub fn set_spell( + /// Get the category of spawn to which this entity belongs. + pub fn spawn_category( &self, - spell: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Spellcaster/Spell;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(spell.into().jni_object().clone()) - }); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setSpell", + "getSpawnCategory", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Checks if this entity has been spawned in a world. + /// + /// Entities not spawned in a world will not tick, be sent to players, or be + /// saved to the server files. + pub fn is_in_world(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get this entity as an NBT string. + /// + /// This string should not be relied upon as a serializable value. + pub fn as_string(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Crates an {@link EntitySnapshot} representing the current state of this entity. + pub fn create_snapshot( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntitySnapshot::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// + /// Note: Players cannot be copied. + pub fn copy( + &self, + to: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = to { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Lorg/bukkit/entity/Entity;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -13526,31 +19754,93 @@ impl<'mc> Spellcaster<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Spellcaster<'mc> { - fn into(self) -> crate::entity::Illager<'mc> { - crate::entity::Illager::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Spellcaster into crate::entity::Illager") +impl<'mc> Into> for ItemDisplay<'mc> { + fn into(self) -> crate::entity::Display<'mc> { + crate::entity::Display::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ItemDisplay into crate::entity::Display") } } -pub enum SpellcasterSpell<'mc> {} -impl<'mc> std::fmt::Display for SpellcasterSpell<'mc> { +pub enum ItemDisplayItemDisplayTransform<'mc> { + None { + inner: ItemDisplayItemDisplayTransformStruct<'mc>, + }, + ThirdpersonLefthand { + inner: ItemDisplayItemDisplayTransformStruct<'mc>, + }, + ThirdpersonRighthand { + inner: ItemDisplayItemDisplayTransformStruct<'mc>, + }, + FirstpersonLefthand { + inner: ItemDisplayItemDisplayTransformStruct<'mc>, + }, + FirstpersonRighthand { + inner: ItemDisplayItemDisplayTransformStruct<'mc>, + }, + Head { + inner: ItemDisplayItemDisplayTransformStruct<'mc>, + }, + Gui { + inner: ItemDisplayItemDisplayTransformStruct<'mc>, + }, + Ground { + inner: ItemDisplayItemDisplayTransformStruct<'mc>, + }, + Fixed { + inner: ItemDisplayItemDisplayTransformStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for ItemDisplayItemDisplayTransform<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + ItemDisplayItemDisplayTransform::None { .. } => f.write_str("NONE"), + ItemDisplayItemDisplayTransform::ThirdpersonLefthand { .. } => { + f.write_str("THIRDPERSON_LEFTHAND") + } + ItemDisplayItemDisplayTransform::ThirdpersonRighthand { .. } => { + f.write_str("THIRDPERSON_RIGHTHAND") + } + ItemDisplayItemDisplayTransform::FirstpersonLefthand { .. } => { + f.write_str("FIRSTPERSON_LEFTHAND") + } + ItemDisplayItemDisplayTransform::FirstpersonRighthand { .. } => { + f.write_str("FIRSTPERSON_RIGHTHAND") + } + ItemDisplayItemDisplayTransform::Head { .. } => f.write_str("HEAD"), + ItemDisplayItemDisplayTransform::Gui { .. } => f.write_str("GUI"), + ItemDisplayItemDisplayTransform::Ground { .. } => f.write_str("GROUND"), + ItemDisplayItemDisplayTransform::Fixed { .. } => f.write_str("FIXED"), + } + } +} +impl<'mc> std::ops::Deref for ItemDisplayItemDisplayTransform<'mc> { + type Target = ItemDisplayItemDisplayTransformStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + ItemDisplayItemDisplayTransform::None { inner } => inner, + ItemDisplayItemDisplayTransform::ThirdpersonLefthand { inner } => inner, + ItemDisplayItemDisplayTransform::ThirdpersonRighthand { inner } => inner, + ItemDisplayItemDisplayTransform::FirstpersonLefthand { inner } => inner, + ItemDisplayItemDisplayTransform::FirstpersonRighthand { inner } => inner, + ItemDisplayItemDisplayTransform::Head { inner } => inner, + ItemDisplayItemDisplayTransform::Gui { inner } => inner, + ItemDisplayItemDisplayTransform::Ground { inner } => inner, + ItemDisplayItemDisplayTransform::Fixed { inner } => inner, + } } } -impl<'mc> SpellcasterSpell<'mc> { +impl<'mc> ItemDisplayItemDisplayTransform<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/Spellcaster/Spell"); + let cls = env.find_class("org/bukkit/entity/ItemDisplay/ItemDisplayTransform"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/Spellcaster/Spell;", + "(Ljava/lang/String;)Lorg/bukkit/entity/ItemDisplay/ItemDisplayTransform;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -13562,42 +19852,100 @@ impl<'mc> SpellcasterSpell<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NONE" => Ok(ItemDisplayItemDisplayTransform::None { + inner: ItemDisplayItemDisplayTransformStruct::from_raw(env, obj)?, + }), + "THIRDPERSON_LEFTHAND" => Ok(ItemDisplayItemDisplayTransform::ThirdpersonLefthand { + inner: ItemDisplayItemDisplayTransformStruct::from_raw(env, obj)?, + }), + "THIRDPERSON_RIGHTHAND" => Ok(ItemDisplayItemDisplayTransform::ThirdpersonRighthand { + inner: ItemDisplayItemDisplayTransformStruct::from_raw(env, obj)?, + }), + "FIRSTPERSON_LEFTHAND" => Ok(ItemDisplayItemDisplayTransform::FirstpersonLefthand { + inner: ItemDisplayItemDisplayTransformStruct::from_raw(env, obj)?, + }), + "FIRSTPERSON_RIGHTHAND" => Ok(ItemDisplayItemDisplayTransform::FirstpersonRighthand { + inner: ItemDisplayItemDisplayTransformStruct::from_raw(env, obj)?, + }), + "HEAD" => Ok(ItemDisplayItemDisplayTransform::Head { + inner: ItemDisplayItemDisplayTransformStruct::from_raw(env, obj)?, + }), + "GUI" => Ok(ItemDisplayItemDisplayTransform::Gui { + inner: ItemDisplayItemDisplayTransformStruct::from_raw(env, obj)?, + }), + "GROUND" => Ok(ItemDisplayItemDisplayTransform::Ground { + inner: ItemDisplayItemDisplayTransformStruct::from_raw(env, obj)?, + }), + "FIXED" => Ok(ItemDisplayItemDisplayTransform::Fixed { + inner: ItemDisplayItemDisplayTransformStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct SpellcasterSpellStruct<'mc>( +pub struct ItemDisplayItemDisplayTransformStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for SpellcasterSpell<'mc> { +impl<'mc> JNIRaw<'mc> for ItemDisplayItemDisplayTransform<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::None { inner } => inner.0.clone(), + Self::ThirdpersonLefthand { inner } => inner.0.clone(), + Self::ThirdpersonRighthand { inner } => inner.0.clone(), + Self::FirstpersonLefthand { inner } => inner.0.clone(), + Self::FirstpersonRighthand { inner } => inner.0.clone(), + Self::Head { inner } => inner.0.clone(), + Self::Gui { inner } => inner.0.clone(), + Self::Ground { inner } => inner.0.clone(), + Self::Fixed { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::None { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ThirdpersonLefthand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ThirdpersonRighthand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FirstpersonLefthand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FirstpersonRighthand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Head { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Gui { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Ground { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Fixed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for SpellcasterSpell<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ItemDisplayItemDisplayTransform<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate SpellcasterSpell from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate ItemDisplayItemDisplayTransform from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Spellcaster/Spell")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/entity/ItemDisplay/ItemDisplayTransform")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SpellcasterSpell object, got {}", - name - ) - .into()) + "Invalid argument passed. Expected a ItemDisplayItemDisplayTransform object, got {}", + name + ) + .into()) } else { let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); let variant = env.translate_error(variant)?; @@ -13606,13 +19954,48 @@ impl<'mc> JNIInstantiatable<'mc> for SpellcasterSpell<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NONE" => Ok(ItemDisplayItemDisplayTransform::None { + inner: ItemDisplayItemDisplayTransformStruct::from_raw(env, obj)?, + }), + "THIRDPERSON_LEFTHAND" => { + Ok(ItemDisplayItemDisplayTransform::ThirdpersonLefthand { + inner: ItemDisplayItemDisplayTransformStruct::from_raw(env, obj)?, + }) + } + "THIRDPERSON_RIGHTHAND" => { + Ok(ItemDisplayItemDisplayTransform::ThirdpersonRighthand { + inner: ItemDisplayItemDisplayTransformStruct::from_raw(env, obj)?, + }) + } + "FIRSTPERSON_LEFTHAND" => { + Ok(ItemDisplayItemDisplayTransform::FirstpersonLefthand { + inner: ItemDisplayItemDisplayTransformStruct::from_raw(env, obj)?, + }) + } + "FIRSTPERSON_RIGHTHAND" => { + Ok(ItemDisplayItemDisplayTransform::FirstpersonRighthand { + inner: ItemDisplayItemDisplayTransformStruct::from_raw(env, obj)?, + }) + } + "HEAD" => Ok(ItemDisplayItemDisplayTransform::Head { + inner: ItemDisplayItemDisplayTransformStruct::from_raw(env, obj)?, + }), + "GUI" => Ok(ItemDisplayItemDisplayTransform::Gui { + inner: ItemDisplayItemDisplayTransformStruct::from_raw(env, obj)?, + }), + "GROUND" => Ok(ItemDisplayItemDisplayTransform::Ground { + inner: ItemDisplayItemDisplayTransformStruct::from_raw(env, obj)?, + }), + "FIXED" => Ok(ItemDisplayItemDisplayTransform::Fixed { + inner: ItemDisplayItemDisplayTransformStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for SpellcasterSpellStruct<'mc> { +impl<'mc> JNIRaw<'mc> for ItemDisplayItemDisplayTransformStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -13620,41 +20003,43 @@ impl<'mc> JNIRaw<'mc> for SpellcasterSpellStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for SpellcasterSpellStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ItemDisplayItemDisplayTransformStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate SpellcasterSpellStruct from null object." + "Tried to instantiate ItemDisplayItemDisplayTransformStruct from null object." ) .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Spellcaster/Spell")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/entity/ItemDisplay/ItemDisplayTransform")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SpellcasterSpellStruct object, got {}", - name - ) - .into()) + "Invalid argument passed. Expected a ItemDisplayItemDisplayTransformStruct object, got {}", + name + ) + .into()) } else { Ok(Self(env.clone(), obj)) } } } -impl<'mc> SpellcasterSpellStruct<'mc> { +impl<'mc> ItemDisplayItemDisplayTransformStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Spellcaster/Spell;"); - let cls = jni.find_class("org/bukkit/entity/Spellcaster/Spell"); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/entity/ItemDisplay/ItemDisplayTransform;"); + let cls = jni.find_class("org/bukkit/entity/ItemDisplay/ItemDisplayTransform"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::entity::SpellcasterSpell::from_raw(&jni, obj) + crate::entity::ItemDisplayItemDisplayTransform::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -13663,12 +20048,12 @@ impl<'mc> SpellcasterSpellStruct<'mc> { } } #[repr(C)] -pub struct Interaction<'mc>( +pub struct ZombieVillager<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Interaction<'mc> { +impl<'mc> JNIRaw<'mc> for ZombieVillager<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -13676,18 +20061,20 @@ impl<'mc> JNIRaw<'mc> for Interaction<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Interaction<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ZombieVillager<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Interaction from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate ZombieVillager from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Interaction")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ZombieVillager")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Interaction object, got {}", + "Invalid argument passed. Expected a ZombieVillager object, got {}", name ) .into()) @@ -13697,125 +20084,291 @@ impl<'mc> JNIInstantiatable<'mc> for Interaction<'mc> { } } -impl<'mc> Interaction<'mc> { - /// Gets the width of this interaction entity. - pub fn interaction_width(&self) -> Result> { - let sig = String::from("()F"); +impl<'mc> ZombieVillager<'mc> { + /// Sets the villager profession of this zombie. + pub fn set_villager_profession( + &self, + profession: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Villager/Profession;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(profession.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getInteractionWidth", + "setVillagerProfession", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the villager profession of this zombie. + pub fn villager_profession( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Villager/Profession;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getVillagerProfession", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::VillagerProfession::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the width of this interaction entity. - pub fn set_interaction_width(&self, width: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(width); + /// Gets the current type of this villager. + pub fn villager_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Villager/Type;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVillagerType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::VillagerType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the new type of this villager. + pub fn set_villager_type( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Villager/Type;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setInteractionWidth", + "setVillagerType", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the height of this interaction entity. - pub fn interaction_height(&self) -> Result> { - let sig = String::from("()F"); + /// Get if this entity is in the process of converting to a Villager as a + /// result of being cured. + pub fn is_converting(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isConverting", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the amount of ticks until this entity will be converted to a + /// Villager as a result of being cured. + /// When this reaches 0, the entity will be converted. + pub fn conversion_time(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getInteractionHeight", + "getConversionTime", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + Ok(res.i()?) } - /// Sets the height of this interaction entity. - pub fn set_interaction_height(&self, height: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(height); + /// Sets the amount of ticks until this entity will be converted to a + /// Villager as a result of being cured. + /// When this reaches 0, the entity will be converted. A value of less than 0 + /// will stop the current conversion process without converting the current + /// entity. + pub fn set_conversion_time(&self, time: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(time); let res = self.jni_ref().call_method( &self.jni_object(), - "setInteractionHeight", + "setConversionTime", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if this interaction entity should trigger a response when interacted - /// with. - pub fn is_responsive(&self) -> Result> { + /// Gets the player who initiated the conversion. + pub fn conversion_player( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/OfflinePlayer;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getConversionPlayer", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::OfflinePlayer::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets the player who initiated the conversion. + /// + /// This has no effect if this entity isn't converting currently. + pub fn set_conversion_player( + &self, + conversion_player: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/OfflinePlayer;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(conversion_player.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setConversionPlayer", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets whether the zombie is a baby + pub fn is_baby(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isBaby", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Sets whether the zombie is a baby + pub fn set_baby(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBaby", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets whether the zombie is a villager + pub fn is_villager(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isResponsive", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isVillager", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets if this interaction entity should trigger a response when interacted - /// with. - pub fn set_responsive(&self, response: bool) -> Result<(), Box> { + #[deprecated] + + pub fn set_villager(&self, flag: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(response.into()); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setResponsive", + "setVillager", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the last attack on this interaction entity. - pub fn last_attack( - &self, - ) -> Result< - Option>, - Box, - > { - let sig = String::from("()Lorg/bukkit/entity/Interaction/PreviousInteraction;"); + /// Gets whether this zombie can break doors + pub fn can_break_doors(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLastAttack", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "canBreakDoors", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - crate::entity::InteractionPreviousInteraction::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?, - )) + Ok(res.z()?) } - /// Gets the last interaction on this entity. - pub fn last_interaction( - &self, - ) -> Result< - Option>, - Box, - > { - let sig = String::from("()Lorg/bukkit/entity/Interaction/PreviousInteraction;"); + /// Sets whether this zombie can break doors + /// This will be ignored if the entity is a Drowned. Will also stop the action if + /// the entity is currently breaking a door. + pub fn set_can_break_doors(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getLastInteraction", + "setCanBreakDoors", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for ZombieVillager<'mc> { + fn into(self) -> crate::entity::Zombie<'mc> { + crate::entity::Zombie::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ZombieVillager into crate::entity::Zombie") + } +} +#[repr(C)] +pub struct ComplexEntityPart<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ComplexEntityPart<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for ComplexEntityPart<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate ComplexEntityPart from null object.").into(), + ); } - Ok(Some( - crate::entity::InteractionPreviousInteraction::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?, - )) + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ComplexEntityPart")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ComplexEntityPart object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> ComplexEntityPart<'mc> { + /// Gets the parent {@link ComplexLivingEntity} of this part. + pub fn parent( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/ComplexLivingEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getParent", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::ComplexLivingEntity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } /// Stores the entity's current position in the provided Location object. /// @@ -14933,19 +21486,19 @@ impl<'mc> Interaction<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Interaction<'mc> { +impl<'mc> Into> for ComplexEntityPart<'mc> { fn into(self) -> crate::entity::Entity<'mc> { crate::entity::Entity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Interaction into crate::entity::Entity") + .expect("Error converting ComplexEntityPart into crate::entity::Entity") } } #[repr(C)] -pub struct InteractionPreviousInteraction<'mc>( +pub struct Snowball<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for InteractionPreviousInteraction<'mc> { +impl<'mc> JNIRaw<'mc> for Snowball<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -14953,22 +21506,18 @@ impl<'mc> JNIRaw<'mc> for InteractionPreviousInteraction<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for InteractionPreviousInteraction<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Snowball<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate InteractionPreviousInteraction from null object." - ) - .into()); + return Err(eyre::eyre!("Tried to instantiate Snowball from null object.").into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/entity/Interaction/PreviousInteraction")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Snowball")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a InteractionPreviousInteraction object, got {}", + "Invalid argument passed. Expected a Snowball object, got {}", name ) .into()) @@ -14978,26 +21527,97 @@ impl<'mc> JNIInstantiatable<'mc> for InteractionPreviousInteraction<'mc> { } } -impl<'mc> InteractionPreviousInteraction<'mc> { - /// Get the previous interacting player. - pub fn player(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/OfflinePlayer;"); +impl<'mc> Snowball<'mc> { + /// Gets the ItemStack the thrown projectile will display. + pub fn item(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/inventory/ItemStack;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::OfflinePlayer::from_raw(&self.jni_ref(), unsafe { + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the Unix timestamp at when this interaction occurred. - pub fn timestamp(&self) -> Result> { - let sig = String::from("()J"); + /// Sets the display ItemStack for the thrown projectile. + pub fn set_item( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setItem", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Retrieve the shooter of this projectile. + pub fn shooter( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/projectiles/ProjectileSource;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getTimestamp", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getShooter", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::projectiles::ProjectileSource::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Set the shooter of this projectile. + pub fn set_shooter( + &self, + source: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/projectiles/ProjectileSource;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(source.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setShooter", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Determine if this projectile should bounce or not when it hits. + pub fn does_bounce(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "doesBounce", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Set whether or not this projectile should bounce or not when it hits something. + pub fn set_bounce(&self, does_bounce: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(does_bounce.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBounce", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -15005,13 +21625,19 @@ impl<'mc> InteractionPreviousInteraction<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for Snowball<'mc> { + fn into(self) -> crate::entity::ThrowableProjectile<'mc> { + crate::entity::ThrowableProjectile::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Snowball into crate::entity::ThrowableProjectile") + } +} #[repr(C)] -pub struct Salmon<'mc>( +pub struct AbstractVillager<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Salmon<'mc> { +impl<'mc> JNIRaw<'mc> for AbstractVillager<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -15019,18 +21645,20 @@ impl<'mc> JNIRaw<'mc> for Salmon<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Salmon<'mc> { +impl<'mc> JNIInstantiatable<'mc> for AbstractVillager<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Salmon from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate AbstractVillager from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Salmon")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/AbstractVillager")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Salmon object, got {}", + "Invalid argument passed. Expected a AbstractVillager object, got {}", name ) .into()) @@ -15040,72 +21668,236 @@ impl<'mc> JNIInstantiatable<'mc> for Salmon<'mc> { } } -impl<'mc> Salmon<'mc> { - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) +impl<'mc> AbstractVillager<'mc> { + /// Gets this villager's inventory. + /// + /// Note that this inventory is not the Merchant inventory, rather, it is the + /// items that a villager might have collected (from harvesting crops, etc.) + /// {@inheritDoc} + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> Into> for Salmon<'mc> { - fn into(self) -> crate::entity::Fish<'mc> { - crate::entity::Fish::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Salmon into crate::entity::Fish") + /// Lock the age of the animal, setting this will prevent the animal from + /// maturing or getting ready for mating. + pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(lock.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAgeLock", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -#[repr(C)] -pub struct Fish<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Fish<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Gets the current agelock. + pub fn age_lock(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Return the ability to breed of the animal. + pub fn can_breed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for Fish<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Fish from null object.").into()); + /// Set breedability of the animal, if the animal is a baby and set to + /// breed it will instantly grow up. + pub fn set_breed(&self, breed: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(breed.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBreed", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get a list of trades currently available from this merchant. + pub fn recipes( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRecipes", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::inventory::MerchantRecipe::from_raw( + &self.jni_ref(), + obj, + )?); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Fish")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Fish object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + Ok(new_vec) + } + /// Set the list of trades currently available from this merchant. + /// + /// This will not change the selected trades of players currently trading + /// with this merchant. + pub fn set_recipes( + &self, + recipes: Vec>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/List;)V"); + let raw_val_1 = self + .jni_ref() + .new_object("java/util/ArrayList", "()V", vec![])?; + for v in recipes { + let map_val_0 = jni::objects::JValueGen::Object(v); + self.jni_ref().call_method( + &raw_val_1, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; } + let val_1 = jni::objects::JValueGen::Object(raw_val_1); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRecipes", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the recipe at a certain index of this merchant's trade list. + pub fn get_recipe( + &self, + i: i32, + ) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/MerchantRecipe;"); + let val_1 = jni::objects::JValueGen::Int(i); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getRecipe", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::MerchantRecipe::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Set the recipe at a certain index of this merchant's trade list. + pub fn set_recipe( + &self, + i: i32, + recipe: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(ILorg/bukkit/inventory/MerchantRecipe;)V"); + let val_1 = jni::objects::JValueGen::Int(i); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRecipe", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the number of trades this merchant currently has available. + pub fn recipe_count(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRecipeCount", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets whether this merchant is currently trading. + pub fn is_trading(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isTrading", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the player this merchant is trading with, or null if it is not + /// currently trading. + pub fn trader( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTrader", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::HumanEntity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } -} -impl<'mc> Fish<'mc> { pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Fish<'mc> { - fn into(self) -> crate::entity::WaterMob<'mc> { - crate::entity::WaterMob::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Fish into crate::entity::WaterMob") +impl<'mc> Into> for AbstractVillager<'mc> { + fn into(self) -> crate::entity::Breedable<'mc> { + crate::entity::Breedable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting AbstractVillager into crate::entity::Breedable") + } +} +impl<'mc> Into> for AbstractVillager<'mc> { + fn into(self) -> crate::entity::NPC<'mc> { + crate::entity::NPC::from_raw(&self.jni_ref(), self.1) + .expect("Error converting AbstractVillager into crate::entity::NPC") + } +} +impl<'mc> Into> for AbstractVillager<'mc> { + fn into(self) -> crate::inventory::InventoryHolder<'mc> { + crate::inventory::InventoryHolder::from_raw(&self.jni_ref(), self.1) + .expect("Error converting AbstractVillager into crate::inventory::InventoryHolder") + } +} +impl<'mc> Into> for AbstractVillager<'mc> { + fn into(self) -> crate::inventory::Merchant<'mc> { + crate::inventory::Merchant::from_raw(&self.jni_ref(), self.1) + .expect("Error converting AbstractVillager into crate::inventory::Merchant") } } #[repr(C)] -pub struct TraderLlama<'mc>( +pub struct AbstractHorse<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for TraderLlama<'mc> { +impl<'mc> JNIRaw<'mc> for AbstractHorse<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -15113,18 +21905,18 @@ impl<'mc> JNIRaw<'mc> for TraderLlama<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for TraderLlama<'mc> { +impl<'mc> JNIInstantiatable<'mc> for AbstractHorse<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate TraderLlama from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate AbstractHorse from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/TraderLlama")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/AbstractHorse")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a TraderLlama object, got {}", + "Invalid argument passed. Expected a AbstractHorse object, got {}", name ) .into()) @@ -15134,786 +21926,843 @@ impl<'mc> JNIInstantiatable<'mc> for TraderLlama<'mc> { } } -impl<'mc> TraderLlama<'mc> { - /// Gets the llama's color. - pub fn color(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Llama/Color;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); +impl<'mc> AbstractHorse<'mc> { + #[deprecated] + /// Gets the horse's variant.A horse's variant defines its physical appearance and capabilities. Whether a horse is a regular horse, donkey, mule, or other kind of horse is determined using the variant. + pub fn variant(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Horse/Variant;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::LlamaColor::from_raw(&self.jni_ref(), unsafe { + crate::entity::HorseVariant::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the llama's color. - pub fn set_color( + #[deprecated] + + pub fn set_variant( &self, - color: impl Into>, + variant: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Llama/Color;)V"); + let sig = String::from("(Lorg/bukkit/entity/Horse/Variant;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) + jni::objects::JObject::from_raw(variant.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setColor", + "setVariant", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the domestication level of this horse. + /// + /// A higher domestication level indicates that the horse is closer to + /// becoming tame. As the domestication level gets closer to the max + /// domestication level, the chance of the horse becoming tame increases. + pub fn domestication(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDomestication", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the domestication level of this horse. + /// + /// Setting the domestication level to a high value will increase the + /// horse's chances of becoming tame. + /// + /// Domestication level must be greater than zero and no greater than + /// the max domestication level of the horse, determined with + /// {@link #getMaxDomestication()} + pub fn set_domestication(&self, level: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(level); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDomestication", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the maximum domestication level of this horse. + /// + /// The higher this level is, the longer it will likely take + /// for the horse to be tamed. + pub fn max_domestication(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaxDomestication", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the maximum domestication level of this horse. + /// + /// Setting a higher max domestication will increase the amount of + /// domesticating (feeding, riding, etc.) necessary in order to tame it, + /// while setting a lower max value will have the opposite effect. + /// + /// Maximum domestication must be greater than zero. + pub fn set_max_domestication(&self, level: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(level); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaxDomestication", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the llama's strength. A higher strength llama will have more - /// inventory slots and be more threatening to entities. - pub fn strength(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the jump strength of this horse. + /// + /// Jump strength defines how high the horse can jump. A higher jump strength + /// increases how high a jump will go. + pub fn jump_strength(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getStrength", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getJumpStrength", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.d()?) } - /// Sets the llama's strength. A higher strength llama will have more - /// inventory slots and be more threatening to entities. Inventory slots are - /// equal to strength * 3. - pub fn set_strength(&self, strength: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(strength); + /// Sets the jump strength of this horse. + /// + /// A higher jump strength increases how high a jump will go. + /// Setting a jump strength to 0 will result in no jump. + /// You cannot set a jump strength to a value below 0 or + /// above 2. + pub fn set_jump_strength(&self, strength: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(strength); let res = self.jni_ref().call_method( &self.jni_object(), - "setStrength", + "setJumpStrength", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/LlamaInventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::LlamaInventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for TraderLlama<'mc> { - fn into(self) -> crate::entity::Llama<'mc> { - crate::entity::Llama::from_raw(&self.jni_ref(), self.1) - .expect("Error converting TraderLlama into crate::entity::Llama") - } -} -#[repr(C)] -pub struct Warden<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Warden<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Warden<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Warden from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Warden")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Warden object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Warden<'mc> { - /// Gets the anger level of this warden. - /// Anger is an integer from 0 to 150. Once a Warden reaches 80 anger at a - /// target it will actively pursue it. - pub fn get_anger( - &self, - entity: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)I"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) - }); + /// Gets whether the horse is currently grazing hay. + pub fn is_eating_haystack(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getAnger", + "isEatingHaystack", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Increases the anger level of this warden. - /// Anger is an integer from 0 to 150. Once a Warden reaches 80 anger at a - /// target it will actively pursue it. - pub fn increase_anger( + /// Sets whether the horse is grazing hay. + pub fn set_eating_haystack( &self, - entity: impl Into>, - increase: i32, + eating_haystack: bool, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;I)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(increase); + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(eating_haystack.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "increaseAnger", + "setEatingHaystack", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets the anger level of this warden. - /// Anger is an integer from 0 to 150. Once a Warden reaches 80 anger at a - /// target it will actively pursue it. - pub fn set_anger( + + pub fn inventory( &self, - entity: impl Into>, - anger: i32, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/AbstractHorseInventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::AbstractHorseInventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the vehicle's velocity. + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the vehicle's velocity in meters per tick. + pub fn set_velocity( + &self, + vel: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;I)V"); + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + jni::objects::JObject::from_raw(vel.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(anger); let res = self.jni_ref().call_method( &self.jni_object(), - "setAnger", + "setVelocity", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Clears the anger level of this warden. - pub fn clear_anger( - &self, - entity: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) - }); + /// Check if this is tamed + /// + /// If something is tamed then a player can not tame it through normal + /// methods, even if it does not belong to anyone in particular. + pub fn is_tamed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isTamed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets if this has been tamed. Not necessary if the method setOwner has + /// been used, as it tames automatically. + /// + /// If something is tamed then a player can not tame it through normal + /// methods, even if it does not belong to anyone in particular. + pub fn set_tamed(&self, tame: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(tame.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "clearAnger", + "setTamed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the {@link LivingEntity} at which this warden is most angry. - pub fn entity_angry_at( + /// Gets the current owning AnimalTamer + pub fn owner( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getEntityAngryAt", - sig.as_str(), - vec![], - ); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/AnimalTamer;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::LivingEntity::from_raw( + Ok(Some(crate::entity::AnimalTamer::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Make the warden sense a disturbance in the force at the location given. - pub fn set_disturbance_location( + /// Set this to be owned by given AnimalTamer. + /// + /// If the owner is not null, this will be tamed and will have any current + /// path it is following removed. If the owner is set to null, this will be + /// untamed, and the current owner removed. + pub fn set_owner( &self, - location: impl Into>, + tamer: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Location;)V"); + let sig = String::from("(Lorg/bukkit/entity/AnimalTamer;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) + jni::objects::JObject::from_raw(tamer.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setDisturbanceLocation", + "setOwner", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the level of anger of this warden. - pub fn anger_level( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Warden/AngerLevel;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAngerLevel", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::WardenAngerLevel::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Warden<'mc> { - fn into(self) -> crate::entity::Monster<'mc> { - crate::entity::Monster::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Warden into crate::entity::Monster") +impl<'mc> Into> for AbstractHorse<'mc> { + fn into(self) -> crate::entity::Vehicle<'mc> { + crate::entity::Vehicle::from_raw(&self.jni_ref(), self.1) + .expect("Error converting AbstractHorse into crate::entity::Vehicle") } } -pub enum WardenAngerLevel<'mc> {} -impl<'mc> std::fmt::Display for WardenAngerLevel<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} +impl<'mc> Into> for AbstractHorse<'mc> { + fn into(self) -> crate::inventory::InventoryHolder<'mc> { + crate::inventory::InventoryHolder::from_raw(&self.jni_ref(), self.1) + .expect("Error converting AbstractHorse into crate::inventory::InventoryHolder") } } - -impl<'mc> WardenAngerLevel<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/Warden/AngerLevel"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/Warden/AngerLevel;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } +impl<'mc> Into> for AbstractHorse<'mc> { + fn into(self) -> crate::entity::Tameable<'mc> { + crate::entity::Tameable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting AbstractHorse into crate::entity::Tameable") } } - #[repr(C)] -pub struct WardenAngerLevelStruct<'mc>( +pub struct ComplexLivingEntity<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for WardenAngerLevel<'mc> { +impl<'mc> JNIRaw<'mc> for ComplexLivingEntity<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + self.0.clone() } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for WardenAngerLevel<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ComplexLivingEntity<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate WardenAngerLevel from null object.").into(), + eyre::eyre!("Tried to instantiate ComplexLivingEntity from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Warden/AngerLevel")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ComplexLivingEntity")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a WardenAngerLevel object, got {}", + "Invalid argument passed. Expected a ComplexLivingEntity object, got {}", name ) .into()) } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + Ok(Self(env.clone(), obj)) } } } -impl<'mc> JNIRaw<'mc> for WardenAngerLevelStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() +impl<'mc> ComplexLivingEntity<'mc> { + /// Gets a list of parts that belong to this complex entity + pub fn parts(&self) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getParts", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets the height of the living entity's eyes above its Location. + pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { + let sig = String::from("(Z)D"); + let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getEyeHeight", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } -} -impl<'mc> JNIInstantiatable<'mc> for WardenAngerLevelStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate WardenAngerLevelStruct from null object." - ) - .into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Warden/AngerLevel")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a WardenAngerLevelStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Get a Location detailing the current eye position of the living entity. + pub fn eye_location(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} - -impl<'mc> WardenAngerLevelStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Warden/AngerLevel;"); - let cls = jni.find_class("org/bukkit/entity/Warden/AngerLevel"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::WardenAngerLevel::from_raw(&jni, obj) + /// Gets all blocks along the living entity's line of sight. + /// + /// This list contains all blocks from the living entity's eye position to + /// target inclusive. This method considers all blocks as 1x1x1 in size. + pub fn get_line_of_sight( + &self, + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(max_distance); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLineOfSight", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + /// Gets the block that the living entity has targeted. + /// + /// This method considers all blocks as 1x1x1 in size. To take exact block + /// collision shapes into account, see {@link #getTargetBlockExact(int, + /// FluidCollisionMode)}. + pub fn get_target_block( + &self, + transparent: impl Into>, + max_distance: i32, + ) -> Result, Box> { + let sig = String::from("(Ljava/util/Set;I)Lorg/bukkit/block/Block;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(max_distance); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTargetBlock", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -#[repr(C)] -pub struct AreaEffectCloud<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for AreaEffectCloud<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Gets the last two blocks along the living entity's line of sight. + /// + /// The target block will be the last block in the list. This method + /// considers all blocks as 1x1x1 in size. + pub fn get_last_two_target_blocks( + &self, + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(max_distance); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLastTwoTargetBlocks", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets the block that the living entity has targeted. + /// + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn get_target_block_exact( + &self, + max_distance: i32, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/block/Block;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTargetBlockExact", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::block::Block::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } -} -impl<'mc> JNIInstantiatable<'mc> for AreaEffectCloud<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate AreaEffectCloud from null object.").into(), - ); + /// Performs a ray trace that provides information on the targeted block. + /// + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn ray_trace_blocks( + &self, + max_distance: f64, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/AreaEffectCloud")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a AreaEffectCloud object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + sig += ")Lorg/bukkit/util/RayTraceResult;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some(crate::util::RayTraceResult::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } -} - -impl<'mc> AreaEffectCloud<'mc> { - /// Gets the duration which this cloud will exist for (in ticks). - pub fn duration(&self) -> Result> { + /// Returns the amount of air that the living entity has remaining, in + /// ticks. + pub fn remaining_air(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDuration", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the duration which this cloud will exist for (in ticks). - pub fn set_duration(&self, duration: i32) -> Result<(), Box> { + /// Sets the amount of air that the living entity has remaining, in ticks. + pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(duration); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setDuration", + "setRemainingAir", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the time which an entity has to be exposed to the cloud before the - /// effect is applied. - pub fn wait_time(&self) -> Result> { + /// Returns the maximum amount of air the living entity can have, in ticks. + pub fn maximum_air(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getWaitTime", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the time which an entity has to be exposed to the cloud before the - /// effect is applied. - pub fn set_wait_time(&self, wait_time: i32) -> Result<(), Box> { + /// Sets the maximum amount of air the living entity can have, in ticks. + pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(wait_time); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setWaitTime", + "setMaximumAir", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the time that an entity will be immune from subsequent exposure. - pub fn reapplication_delay(&self) -> Result> { + /// Gets the item that the player is using (eating food, drawing back a bow, + /// blocking, etc.) + pub fn item_in_use( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the number of ticks remaining for the current item's usage. + pub fn item_in_use_ticks(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getReapplicationDelay", + "getItemInUseTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the time that an entity will be immune from subsequent exposure. - pub fn set_reapplication_delay(&self, delay: i32) -> Result<(), Box> { + /// Sets the number of ticks that remain for the current item's usage. + /// Applies to items that take time to use, like eating food, drawing a bow, + /// or throwing a trident. + pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(delay); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setReapplicationDelay", + "setItemInUseTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the amount that the duration of this cloud will decrease by when it - /// applies an effect to an entity. - pub fn duration_on_use(&self) -> Result> { + /// Gets the time in ticks until the next arrow leaves the entity's body. + pub fn arrow_cooldown(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getDurationOnUse", + "getArrowCooldown", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the amount that the duration of this cloud will decrease by when it - /// applies an effect to an entity. - pub fn set_duration_on_use(&self, duration: i32) -> Result<(), Box> { + /// Sets the time in ticks until the next arrow leaves the entity's body. + pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(duration); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setDurationOnUse", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the initial radius of the cloud. - pub fn radius(&self) -> Result> { - let sig = String::from("()F"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getRadius", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Sets the initial radius of the cloud. - pub fn set_radius(&self, radius: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(radius); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setRadius", + "setArrowCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the amount that the radius of this cloud will decrease by when it - /// applies an effect to an entity. - pub fn radius_on_use(&self) -> Result> { - let sig = String::from("()F"); + /// Gets the amount of arrows in an entity's body. + pub fn arrows_in_body(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getRadiusOnUse", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + Ok(res.i()?) } - /// Sets the amount that the radius of this cloud will decrease by when it - /// applies an effect to an entity. - pub fn set_radius_on_use(&self, radius: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(radius); + /// Set the amount of arrows in the entity's body. + pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(count); let res = self.jni_ref().call_method( &self.jni_object(), - "setRadiusOnUse", + "setArrowsInBody", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the amount that the radius of this cloud will decrease by each tick. - pub fn radius_per_tick(&self) -> Result> { - let sig = String::from("()F"); + /// Returns the living entity's current maximum no damage ticks. + /// + /// This is the maximum duration in which the living entity will not take + /// damage. + pub fn maximum_no_damage_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getRadiusPerTick", + "getMaximumNoDamageTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + Ok(res.i()?) } - /// Gets the amount that the radius of this cloud will decrease by each tick. - pub fn set_radius_per_tick(&self, radius: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(radius); + /// Sets the living entity's current maximum no damage ticks. + pub fn set_maximum_no_damage_ticks( + &self, + ticks: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setRadiusPerTick", + "setMaximumNoDamageTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the particle which this cloud will be composed of - pub fn particle(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Particle;"); + /// Returns the living entity's last damage taken in the current no damage + /// ticks time. + /// + /// Only damage higher than this amount will further damage the living + /// entity. + pub fn last_damage(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getParticle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Particle::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the particle which this cloud will be composed of - pub fn set_particle( - &self, - particle: impl Into>, - data: std::option::Option>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Particle;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(particle.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = data { - sig += "LT;"; - let val_2 = jni::objects::JValueGen::Object(a); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setParticle", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.d()?) } - #[deprecated] - /// Sets the underlying potion data - pub fn set_base_potion_data( - &self, - data: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/potion/PotionData;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) - }); + /// Sets the damage dealt within the current no damage ticks time period. + pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(damage); let res = self.jni_ref().call_method( &self.jni_object(), - "setBasePotionData", + "setLastDamage", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Returns the potion data about the base potion - pub fn base_potion_data( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/potion/PotionData;"); + /// Returns the living entity's current no damage ticks. + pub fn no_damage_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getBasePotionData", + "getNoDamageTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::potion::PotionData::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - /// Sets the underlying potion type - pub fn set_base_potion_type( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/potion/PotionType;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Sets the living entity's current no damage ticks. + pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setBasePotionType", + "setNoDamageTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the potion type about the base potion - pub fn base_potion_type( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/potion/PotionType;"); + /// Get the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn no_action_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getBasePotionType", + "getNoActionTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::potion::PotionType::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - /// Checks for the presence of custom potion effects. - pub fn has_custom_effects(&self) -> Result> { - let sig = String::from("()Z"); + /// Set the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "hasCustomEffects", + "setNoActionTicks", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets an immutable list containing all custom potion effects applied to - /// this cloud. + /// Gets the player identified as the killer of the living entity. /// - /// Plugins should check that hasCustomEffects() returns true before calling - /// this method. - pub fn custom_effects( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCustomEffects", - sig.as_str(), - vec![], - ); + /// May be null. + pub fn killer(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - Ok(new_vec) + Ok(Some(crate::entity::Player::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Adds a custom potion effect to this cloud. - pub fn add_custom_effect( + #[deprecated] + /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. + pub fn add_potion_effect( &self, effect: impl Into>, - overwrite: bool, + force: std::option::Option, ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffect;Z)Z"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/potion/PotionEffect;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(effect.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Bool(overwrite.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addCustomEffect", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + args.push(val_1); + if let Some(a) = force { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes a custom potion effect from this cloud. - pub fn remove_custom_effect( + /// Returns whether the living entity already has an existing effect of + /// the given {@link PotionEffectType} applied to it. + pub fn has_potion_effect( &self, val_type: impl Into>, ) -> Result> { @@ -15923,758 +22772,570 @@ impl<'mc> AreaEffectCloud<'mc> { }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeCustomEffect", + "hasPotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Checks for a specific custom potion effect type on this cloud. - pub fn has_custom_effect( + /// Returns the active {@link PotionEffect} of the specified type. + /// + /// If the effect is not present on the entity then null will be returned. + pub fn get_potion_effect( &self, val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); + ) -> Result>, Box> { + let sig = + String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasCustomEffect", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Removes all custom potion effects from this cloud. - pub fn clear_custom_effects(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "clearCustomEffects", - sig.as_str(), - vec![], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the color of this cloud. Will be applied as a tint to its particles. - pub fn color(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Color;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Color::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the color of this cloud. Will be applied as a tint to its particles. - pub fn set_color( - &self, - color: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Color;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setColor", + "getPotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Retrieve the original source of this cloud. - pub fn source( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/projectiles/ProjectileSource;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSource", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::projectiles::ProjectileSource::from_raw( + Ok(Some(crate::potion::PotionEffect::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Set the original source of this cloud. - pub fn set_source( + /// Removes any effects present of the given {@link PotionEffectType}. + pub fn remove_potion_effect( &self, - source: impl Into>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/projectiles/ProjectileSource;)V"); + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(source.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setSource", + "removePotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Stores the entity's current position in the provided Location object. - /// - /// If the provided Location is null this method does nothing and returns - /// null. - pub fn get_location( + /// Returns all currently active {@link PotionEffect}s on the living + /// entity. + pub fn active_potion_effects( &self, - loc: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) - }); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocation", + "getActivePotionEffects", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(new_vec) } - /// Sets this entity's velocity in meters per tick - pub fn set_velocity( + /// Checks whether the living entity has block line of sight to another. + /// + /// This uses the same algorithm that hostile mobs use to find the closest + /// player. + pub fn has_line_of_sight( &self, - velocity: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + other: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + jni::objects::JObject::from_raw(other.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVelocity", + "hasLineOfSight", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets this entity's current velocity - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the entity's height - pub fn height(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the entity's width - pub fn width(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the entity's current bounding box. - /// - /// The returned bounding box reflects the entity's current location and - /// size. - pub fn bounding_box( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns true if the entity is supported by a block. This value is a - /// state updated by the server and is not recalculated unless the entity - /// moves. - pub fn is_on_ground(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns true if the entity is in water. - pub fn is_in_water(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the current world this entity resides in - pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the entity's rotation. + /// Returns if the living entity despawns when away from players or not. /// - /// Note that if the entity is affected by AI, it may override this rotation. - pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { - let sig = String::from("(FF)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); - let val_2 = jni::objects::JValueGen::Float(pitch); + /// By default, animals are not removed while other mobs are. + pub fn remove_when_far_away(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "setRotation", + "getRemoveWhenFarAway", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Teleports this entity to the given location. If this entity is riding a - /// vehicle, it will be dismounted prior to teleportation. - pub fn teleport( - &self, - location: impl Into>, - cause: std::option::Option< - impl Into>, - >, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = cause { - sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "teleport", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns a list of entities within a bounding box centered around this - /// entity - pub fn get_nearby_entities( - &self, - x: f64, - y: f64, - z: f64, - ) -> Result>, Box> { - let sig = String::from("(DDD)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Double(x); - let val_2 = jni::objects::JValueGen::Double(y); - let val_3 = jni::objects::JValueGen::Double(z); + /// Sets whether or not the living entity despawns when away from players + /// or not. + pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(remove.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getNearbyEntities", + "setRemoveWhenFarAway", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Returns a unique id for this entity - pub fn entity_id(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn fire_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns the entity's maximum fire ticks. - pub fn max_fire_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the inventory with the equipment worn by the living entity. + pub fn equipment( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::EntityEquipment::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets whether or not the living entity can pick up items. + pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(pickup.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setFireTicks", + "setCanPickupItems", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets if the entity has visual fire (it will always appear to be on fire). - pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire.into()); + /// Gets if the living entity can pick up items. + pub fn can_pickup_items(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisualFire", + "getCanPickupItems", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets if the entity has visual fire (it will always appear to be on fire). - pub fn is_visual_fire(&self) -> Result> { + /// Returns whether the entity is currently leashed. + pub fn is_leashed(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the entity that is currently leading this entity. + pub fn leash_holder(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the entity's maximum freeze ticks (amount of ticks before it will - /// be fully frozen) - pub fn max_freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMaxFreezeTicks", - sig.as_str(), - vec![], - ); + .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets the leash on this entity to be held by the supplied entity. + /// + /// This method has no effect on EnderDragons, Withers, Players, or Bats. + /// Non-living entities excluding leashes will not persist as leash + /// holders. + pub fn set_leash_holder( + &self, + holder: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(holder.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setFreezeTicks", + "setLeashHolder", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets if the entity is fully frozen (it has been in powdered snow for max - /// freeze ticks). - pub fn is_frozen(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Mark the entity's removal. - pub fn remove(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns true if this entity has been marked for removal. - pub fn is_dead(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns false if the entity has died, been despawned for some other - /// reason, or has not been added to the world. - pub fn is_valid(&self) -> Result> { + /// Checks to see if an entity is gliding, such as using an Elytra. + pub fn is_gliding(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the {@link Server} that contains this Entity - pub fn server(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Server;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Server::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Makes entity start or stop gliding. This will work even if an Elytra + /// is not equipped, but will be reverted by the server immediately after + /// unless an event-cancelling mechanism is put in place. + pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gliding.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setGliding", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns true if the entity gets persisted. - /// - /// By default all entities are persistent. An entity will also not get - /// persisted, if it is riding an entity that is not persistent. - /// - /// The persistent flag on players controls whether or not to save their - /// playerdata file when they quit. If a player is directly or indirectly - /// riding a non-persistent entity, the vehicle at the root and all its - /// passengers won't get persisted. - /// - /// This should not be confused with - /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls - /// despawning of living entities. - pub fn is_persistent(&self) -> Result> { + /// Checks to see if an entity is swimming. + pub fn is_swimming(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not the entity gets persisted. - pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { + /// Makes entity start or stop swimming. + /// This may have unexpected results if the entity is not in water. + pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(persistent.into()); + let val_1 = jni::objects::JValueGen::Bool(swimming.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setPersistent", + "setSwimming", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. - pub fn passenger( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + /// Checks to see if an entity is currently riptiding. + pub fn is_riptiding(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - #[deprecated] - /// Set the passenger of a vehicle. - pub fn set_passenger( - &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); + /// Makes entity start or stop riptiding. + /// + /// Note: This does not damage attackable entities. + pub fn set_riptiding(&self, riptiding: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(riptiding.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setPassenger", + "setRiptiding", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets a list of passengers of this vehicle. - /// - /// The returned list will not be directly linked to the entity's current - /// passengers, and no guarantees are made as to its mutability. - pub fn passengers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + /// Returns whether this entity is slumbering. + pub fn is_sleeping(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(res.z()?) } - /// Add a passenger to the vehicle. - pub fn add_passenger( - &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); + /// Gets if the entity is climbing. + pub fn is_climbing(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether an entity will have AI. + /// The entity will be completely unable to move if it has no AI. + pub fn set_ai(&self, ai: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(ai.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "addPassenger", + "setAI", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks whether an entity has AI. + /// The entity will be completely unable to move if it has no AI. + pub fn has_ai(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Remove a passenger from the vehicle. - pub fn remove_passenger( + /// Makes this entity attack the given entity with a melee attack. + /// Attack damage is calculated by the server from the attributes and + /// equipment of this mob, and knockback is applied to {@code target} as + /// appropriate. + pub fn attack( &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + target: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(target.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removePassenger", + "attack", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Check if a vehicle has passengers. - pub fn is_empty(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Eject any passenger. - pub fn eject(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Makes this entity swing their main hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their main hand. + pub fn swing_main_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns the distance this entity has fallen - pub fn fall_distance(&self) -> Result> { - let sig = String::from("()F"); + /// Makes this entity swing their off hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their off hand. + pub fn swing_off_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the fall distance for this entity - pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { + /// Makes this entity flash red as if they were damaged. + pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(distance); + let val_1 = jni::objects::JValueGen::Float(yaw); let res = self.jni_ref().call_method( &self.jni_object(), - "setFallDistance", + "playHurtAnimation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Record the last {@link EntityDamageEvent} inflicted on this entity - pub fn set_last_damage_cause( - &self, - event: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(event.into().jni_object().clone()) - }); + /// Set if this entity will be subject to collisions with other entities. + /// + /// Exemptions to this rule can be managed with + /// {@link #getCollidableExemptions()} + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not working for player collisions. This + /// method should therefore only be used to set the collision status of + /// non-player entities. + /// + /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in + /// combination with a {@link Scoreboard} and a {@link Team}. + pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(collidable.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDamageCause", + "setCollidable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. - /// This event may have been cancelled. - pub fn last_damage_cause( + /// Gets if this entity is subject to collisions with other entities. + /// + /// Some entities might be exempted from the collidable rule of this entity. + /// Use {@link #getCollidableExemptions()} to get these. + /// + /// Please note that this method returns only the custom collidable state, + /// not whether the entity is non-collidable for other reasons such as being + /// dead. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not being accurate for player collisions. + /// This method should therefore only be used to check the collision status + /// of non-player entities. + /// + /// To check the collision behavior for a player, use + /// {@link Team.Option#COLLISION_RULE} in combination with a + /// {@link Scoreboard} and a {@link Team}. + pub fn is_collidable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets a mutable set of UUIDs of the entities which are exempt from the + /// entity's collidable rule and which's collision with this entity will + /// behave the opposite of it. + /// + /// This set can be modified to add or remove exemptions. + /// + /// For example if collidable is true and an entity is in the exemptions set + /// then it will not collide with it. Similarly if collidable is false and an + /// entity is in this set then it will still collide with it. + /// + /// Note these exemptions are not (currently) persistent. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in those exemptions not being accurate for player + /// collisions. This method should therefore only be used to exempt + /// non-player entities. + /// + /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} + /// in combination with a {@link Scoreboard} and a {@link Team}. + pub fn collidable_exemptions( &self, - ) -> Result>, Box> - { - let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLastDamageCause", + "getCollidableExemptions", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Returns a unique and persistent id for this entity - pub fn unique_id( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. - pub fn ticks_lived(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the amount of ticks this entity has lived for. + /// Returns the value of the memory specified. /// - /// This is the equivalent to "age" in entities. May not be less than one - /// tick. - pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(value); + /// Note that the value is null when the specific entity does not have that + /// value by default. + pub fn get_memory( + &self, + memory_key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setTicksLived", + "getMemory", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) } - /// Performs the specified {@link EntityEffect} for this entity. - /// - /// This will be viewable to all players near the entity. + /// Sets the value of the memory specified. /// - /// If the effect is not applicable to this class of entity, it will not play. - pub fn play_effect( + /// Note that the value will not be persisted when the specific entity does + /// not have that value by default. + pub fn set_memory( &self, - val_type: impl Into>, + memory_key: impl Into>, + memory_value: jni::objects::JObject<'mc>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Object(memory_value); let res = self.jni_ref().call_method( &self.jni_object(), - "playEffect", + "setMemory", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the type of the entity. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + /// Get the {@link Sound} this entity will make when damaged. + pub fn hurt_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) + })?)) } - /// Get the {@link Sound} this entity makes while swimming. - pub fn swim_sound(&self) -> Result, Box> { + /// Get the {@link Sound} this entity will make on death. + pub fn death_sound(&self) -> Result>, Box> { let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Get the {@link Sound} this entity will make when falling from the given + /// height (in blocks). The sound will often differ between either a small + /// or a big fall damage sound if the height exceeds 4 blocks. + pub fn get_fall_damage_sound( + &self, + fall_height: i32, + ) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Int(fall_height); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getFallDamageSound", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the {@link Sound} this entity makes when splashing in water. For most - /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_splash_sound(&self) -> Result, Box> { + /// Get the {@link Sound} this entity will make when falling from a small + /// height. + pub fn fall_damage_sound_small(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimSplashSound", + "getFallDamageSoundSmall", sig.as_str(), vec![], ); @@ -16683,15 +23344,13 @@ impl<'mc> AreaEffectCloud<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the {@link Sound} this entity makes when splashing in water at high - /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_high_speed_splash_sound( - &self, - ) -> Result, Box> { + /// Get the {@link Sound} this entity will make when falling from a large + /// height. + pub fn fall_damage_sound_big(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimHighSpeedSplashSound", + "getFallDamageSoundBig", sig.as_str(), vec![], ); @@ -16700,439 +23359,636 @@ impl<'mc> AreaEffectCloud<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns whether this entity is inside a vehicle. - pub fn is_inside_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Leave the current vehicle. If the entity is currently in a vehicle (and - /// is removed from it), true will be returned, otherwise false will be - /// returned. - pub fn leave_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the vehicle that this entity is inside. If there is no vehicle, - /// null will be returned. - pub fn vehicle( + /// Get the {@link Sound} this entity will make when drinking the given + /// {@link ItemStack}. + pub fn get_drinking_sound( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Sets whether or not to display the mob's custom name client side. The - /// name will be displayed above the mob similarly to a player. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomNameVisible", + "getDrinkingSound", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether or not the mob's custom name is displayed client side. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn is_custom_name_visible(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isCustomNameVisible", - sig.as_str(), - vec![], - ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(visible.into()); + /// Get the {@link Sound} this entity will make when eating the given + /// {@link ItemStack}. + pub fn get_eating_sound( + &self, + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisibleByDefault", + "getEatingSound", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn is_visible_by_default(&self) -> Result> { + /// Returns true if this entity can breathe underwater and will not take + /// suffocation damage when its air supply reaches zero. + pub fn can_breathe_underwater(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "isVisibleByDefault", + "canBreatheUnderwater", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get all players that are currently tracking this entity. - /// - /// 'Tracking' means that this entity has been sent to the player and that - /// they are receiving updates on its state. Note that the client's {@code - /// 'Entity Distance'} setting does not affect the range at which entities - /// are tracked. - pub fn tracked_by( + #[deprecated] + /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. + pub fn category( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets whether the entity has a team colored (default: white) glow. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { + /// Sets whether the entity is invisible or not. + pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(invisible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setGlowing", + "setInvisible", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is glowing or not. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn is_glowing(&self) -> Result> { + /// Gets whether the entity is invisible or not. + pub fn is_invisible(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for ComplexLivingEntity<'mc> { + fn into(self) -> crate::entity::LivingEntity<'mc> { + crate::entity::LivingEntity::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ComplexLivingEntity into crate::entity::LivingEntity") + } +} +#[repr(C)] +pub struct Rabbit<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Rabbit<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Rabbit<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Rabbit from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Rabbit")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Rabbit object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Rabbit<'mc> { + pub fn rabbit_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Rabbit/Type;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRabbitType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::RabbitType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets whether the entity is invulnerable or not. - /// - /// When an entity is invulnerable it can only be damaged by players in - /// creative mode. - pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + + pub fn set_rabbit_type( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Rabbit/Type;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvulnerable", + "setRabbitType", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invulnerable or not. - pub fn is_invulnerable(&self) -> Result> { - let sig = String::from("()Z"); + /// Get the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn breed_cause( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/UUID;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets whether the entity is silent or not. - pub fn is_silent(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets whether the entity is silent or not. - /// - /// When an entity is silent it will not produce any sound. - pub fn set_silent(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Set the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn set_breed_cause( + &self, + uuid: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/UUID;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setSilent", + "setBreedCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether gravity applies to this entity. - pub fn has_gravity(&self) -> Result> { + /// Get whether or not this entity is in love mode and will produce + /// offspring with another entity in love mode. Will return true if + /// and only if {@link #getLoveModeTicks()} is greater than 0. + pub fn is_love_mode(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether gravity applies to this entity. - pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gravity.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setGravity", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the period of time (in ticks) before this entity can use a portal. - pub fn portal_cooldown(&self) -> Result> { + /// Get the amount of ticks remaining for this entity in love mode. + /// If the entity is not in love mode, 0 will be returned. + pub fn love_mode_ticks(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPortalCooldown", + "getLoveModeTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the period of time (in ticks) before this entity can use a portal. - pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { + /// Set the amount of ticks for which this entity should be in love mode. + /// Setting the love mode ticks to 600 is the equivalent of a player + /// feeding the entity their breeding item of choice. + pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(cooldown); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setPortalCooldown", + "setLoveModeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a set of tags for this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn scoreboard_tags( + /// Check if the provided ItemStack is the correct item used for breeding + /// this entity.. + pub fn is_breed_item( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getScoreboardTags", - sig.as_str(), - vec![], - ); + material: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Add a tag to this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn add_scoreboard_tag( - &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addScoreboardTag", - sig.as_str(), + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Rabbit<'mc> { + fn into(self) -> crate::entity::Animals<'mc> { + crate::entity::Animals::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Rabbit into crate::entity::Animals") + } +} +pub enum RabbitType<'mc> { + Brown { inner: RabbitTypeStruct<'mc> }, + White { inner: RabbitTypeStruct<'mc> }, + Black { inner: RabbitTypeStruct<'mc> }, + BlackAndWhite { inner: RabbitTypeStruct<'mc> }, + Gold { inner: RabbitTypeStruct<'mc> }, + SaltAndPepper { inner: RabbitTypeStruct<'mc> }, + TheKillerBunny { inner: RabbitTypeStruct<'mc> }, +} +impl<'mc> std::fmt::Display for RabbitType<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + RabbitType::Brown { .. } => f.write_str("BROWN"), + RabbitType::White { .. } => f.write_str("WHITE"), + RabbitType::Black { .. } => f.write_str("BLACK"), + RabbitType::BlackAndWhite { .. } => f.write_str("BLACK_AND_WHITE"), + RabbitType::Gold { .. } => f.write_str("GOLD"), + RabbitType::SaltAndPepper { .. } => f.write_str("SALT_AND_PEPPER"), + RabbitType::TheKillerBunny { .. } => f.write_str("THE_KILLER_BUNNY"), + } + } +} +impl<'mc> std::ops::Deref for RabbitType<'mc> { + type Target = RabbitTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + RabbitType::Brown { inner } => inner, + RabbitType::White { inner } => inner, + RabbitType::Black { inner } => inner, + RabbitType::BlackAndWhite { inner } => inner, + RabbitType::Gold { inner } => inner, + RabbitType::SaltAndPepper { inner } => inner, + RabbitType::TheKillerBunny { inner } => inner, + } + } +} + +impl<'mc> RabbitType<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/Rabbit/Type"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/Rabbit/Type;", vec![jni::objects::JValueGen::from(val_1)], ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "BROWN" => Ok(RabbitType::Brown { + inner: RabbitTypeStruct::from_raw(env, obj)?, + }), + "WHITE" => Ok(RabbitType::White { + inner: RabbitTypeStruct::from_raw(env, obj)?, + }), + "BLACK" => Ok(RabbitType::Black { + inner: RabbitTypeStruct::from_raw(env, obj)?, + }), + "BLACK_AND_WHITE" => Ok(RabbitType::BlackAndWhite { + inner: RabbitTypeStruct::from_raw(env, obj)?, + }), + "GOLD" => Ok(RabbitType::Gold { + inner: RabbitTypeStruct::from_raw(env, obj)?, + }), + "SALT_AND_PEPPER" => Ok(RabbitType::SaltAndPepper { + inner: RabbitTypeStruct::from_raw(env, obj)?, + }), + "THE_KILLER_BUNNY" => Ok(RabbitType::TheKillerBunny { + inner: RabbitTypeStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct RabbitTypeStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for RabbitType<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Brown { inner } => inner.0.clone(), + Self::White { inner } => inner.0.clone(), + Self::Black { inner } => inner.0.clone(), + Self::BlackAndWhite { inner } => inner.0.clone(), + Self::Gold { inner } => inner.0.clone(), + Self::SaltAndPepper { inner } => inner.0.clone(), + Self::TheKillerBunny { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Brown { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::White { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Black { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BlackAndWhite { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Gold { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SaltAndPepper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TheKillerBunny { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for RabbitType<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate RabbitType from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Rabbit/Type")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a RabbitType object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "BROWN" => Ok(RabbitType::Brown { + inner: RabbitTypeStruct::from_raw(env, obj)?, + }), + "WHITE" => Ok(RabbitType::White { + inner: RabbitTypeStruct::from_raw(env, obj)?, + }), + "BLACK" => Ok(RabbitType::Black { + inner: RabbitTypeStruct::from_raw(env, obj)?, + }), + "BLACK_AND_WHITE" => Ok(RabbitType::BlackAndWhite { + inner: RabbitTypeStruct::from_raw(env, obj)?, + }), + "GOLD" => Ok(RabbitType::Gold { + inner: RabbitTypeStruct::from_raw(env, obj)?, + }), + "SALT_AND_PEPPER" => Ok(RabbitType::SaltAndPepper { + inner: RabbitTypeStruct::from_raw(env, obj)?, + }), + "THE_KILLER_BUNNY" => Ok(RabbitType::TheKillerBunny { + inner: RabbitTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for RabbitTypeStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for RabbitTypeStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate RabbitTypeStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Rabbit/Type")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a RabbitTypeStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> RabbitTypeStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Rabbit/Type;"); + let cls = jni.find_class("org/bukkit/entity/Rabbit/Type"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::RabbitType::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct Armadillo<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Armadillo<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Armadillo<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Armadillo from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Armadillo")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Armadillo object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Armadillo<'mc> { + /// Get the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn breed_cause( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Removes a given tag from this entity. - pub fn remove_scoreboard_tag( + /// Set the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn set_breed_cause( &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); + uuid: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/UUID;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeScoreboardTag", + "setBreedCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get whether or not this entity is in love mode and will produce + /// offspring with another entity in love mode. Will return true if + /// and only if {@link #getLoveModeTicks()} is greater than 0. + pub fn is_love_mode(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns the reaction of the entity when moved by a piston. - pub fn piston_move_reaction( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + /// Get the amount of ticks remaining for this entity in love mode. + /// If the entity is not in love mode, 0 will be returned. + pub fn love_mode_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPistonMoveReaction", + "getLoveModeTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the closest cardinal {@link BlockFace} direction an entity is - /// currently facing. - /// - /// This will not return any non-cardinal directions such as - /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. - /// - /// {@link Hanging} entities will override this call and thus their behavior - /// may be different. - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the entity's current pose. - /// Note that the pose is only updated at the end of a tick, so may be - /// inconsistent with other methods. eg {@link Player#isSneaking()} being - /// true does not imply the current pose will be {@link Pose#SNEAKING} - pub fn pose(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Pose;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Get the category of spawn to which this entity belongs. - pub fn spawn_category( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); + /// Set the amount of ticks for which this entity should be in love mode. + /// Setting the love mode ticks to 600 is the equivalent of a player + /// feeding the entity their breeding item of choice. + pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "getSpawnCategory", + "setLoveModeTicks", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Checks if this entity has been spawned in a world. - /// - /// Entities not spawned in a world will not tick, be sent to players, or be - /// saved to the server files. - pub fn is_in_world(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get this entity as an NBT string. - /// - /// This string should not be relied upon as a serializable value. - pub fn as_string(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// Crates an {@link EntitySnapshot} representing the current state of this entity. - pub fn create_snapshot( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::EntitySnapshot::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Creates a copy of this entity and all its data. Spawns the copy at the given location. - /// - /// Note: Players cannot be copied. - pub fn copy( + /// Check if the provided ItemStack is the correct item used for breeding + /// this entity.. + pub fn is_breed_item( &self, - to: std::option::Option>>, - ) -> Result, Box> { + material: impl Into>, + ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = to { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")Lorg/bukkit/entity/Entity;"; + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); + .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -17140,19 +23996,19 @@ impl<'mc> AreaEffectCloud<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for AreaEffectCloud<'mc> { - fn into(self) -> crate::entity::Entity<'mc> { - crate::entity::Entity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting AreaEffectCloud into crate::entity::Entity") +impl<'mc> Into> for Armadillo<'mc> { + fn into(self) -> crate::entity::Animals<'mc> { + crate::entity::Animals::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Armadillo into crate::entity::Animals") } } #[repr(C)] -pub struct Fox<'mc>( +pub struct Snowman<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Fox<'mc> { +impl<'mc> JNIRaw<'mc> for Snowman<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -17160,18 +24016,18 @@ impl<'mc> JNIRaw<'mc> for Fox<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Fox<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Snowman<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Fox from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Snowman from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Fox")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Snowman")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Fox object, got {}", + "Invalid argument passed. Expected a Snowman object, got {}", name ) .into()) @@ -17181,160 +24037,80 @@ impl<'mc> JNIInstantiatable<'mc> for Fox<'mc> { } } -impl<'mc> Fox<'mc> { - /// Gets the current type of this fox. - pub fn fox_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Fox/Type;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFoxType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::FoxType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the current type of this fox. - pub fn set_fox_type( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Fox/Type;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFoxType", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks if this animal is crouching - pub fn is_crouching(&self) -> Result> { +impl<'mc> Snowman<'mc> { + /// Gets whether this snowman is in "derp mode", meaning it is not wearing a + /// pumpkin. + pub fn is_derp(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCrouching", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isDerp", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets if this animal is crouching. - pub fn set_crouching(&self, crouching: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(crouching.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCrouching", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Sets if this animal is sleeping. - pub fn set_sleeping(&self, sleeping: bool) -> Result<(), Box> { + /// Sets whether this snowman is in "derp mode", meaning it is not wearing a + /// pumpkin. NOTE: This value is not persisted to disk and will therefore + /// reset when the chunk is reloaded. + pub fn set_derp(&self, derp_mode: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(sleeping.into()); + let val_1 = jni::objects::JValueGen::Bool(derp_mode.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setSleeping", + "setDerp", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the first trusted player. - pub fn first_trusted_player( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/AnimalTamer;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFirstTrustedPlayer", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::AnimalTamer::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Set the first trusted player. - /// - /// The first trusted player may only be removed after the second. - pub fn set_first_trusted_player( - &self, - player: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/AnimalTamer;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFirstTrustedPlayer", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +} +impl<'mc> Into> for Snowman<'mc> { + fn into(self) -> crate::entity::Golem<'mc> { + crate::entity::Golem::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Snowman into crate::entity::Golem") } - /// Gets the second trusted player. - pub fn second_trusted_player( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/AnimalTamer;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSecondTrustedPlayer", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::AnimalTamer::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) +} +#[repr(C)] +pub struct Animals<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Animals<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Set the second trusted player. - /// - /// The second trusted player may only be added after the first. - pub fn set_second_trusted_player( - &self, - player: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/AnimalTamer;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSecondTrustedPlayer", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Gets whether the fox is faceplanting the ground - pub fn is_faceplanted(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isFaceplanted", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} +impl<'mc> JNIInstantiatable<'mc> for Animals<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Animals from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Animals")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Animals object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } +} + +impl<'mc> Animals<'mc> { /// Get the UUID of the entity that caused this entity to enter the /// {@link #canBreed()} state. pub fn breed_cause( @@ -17431,23 +24207,46 @@ impl<'mc> Fox<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Checks if this animal is sitting - pub fn is_sitting(&self) -> Result> { + /// Lock the age of the animal, setting this will prevent the animal from + /// maturing or getting ready for mating. + pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(lock.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAgeLock", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the current agelock. + pub fn age_lock(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Return the ability to breed of the animal. + pub fn can_breed(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isSitting", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets if this animal is sitting. Will remove any path that the animal - /// was following beforehand. - pub fn set_sitting(&self, sitting: bool) -> Result<(), Box> { + /// Set breedability of the animal, if the animal is a baby and set to + /// breed it will instantly grow up. + pub fn set_breed(&self, breed: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(sitting.into()); + let val_1 = jni::objects::JValueGen::Bool(breed.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setSitting", + "setBreed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -17460,97 +24259,19 @@ impl<'mc> Fox<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Fox<'mc> { - fn into(self) -> crate::entity::Animals<'mc> { - crate::entity::Animals::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Fox into crate::entity::Animals") - } -} -impl<'mc> Into> for Fox<'mc> { - fn into(self) -> crate::entity::Sittable<'mc> { - crate::entity::Sittable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Fox into crate::entity::Sittable") - } -} -pub enum FoxType<'mc> {} -impl<'mc> std::fmt::Display for FoxType<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> FoxType<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/Fox/Type"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/Fox/Type;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } +impl<'mc> Into> for Animals<'mc> { + fn into(self) -> crate::entity::Breedable<'mc> { + crate::entity::Breedable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Animals into crate::entity::Breedable") } } - #[repr(C)] -pub struct FoxTypeStruct<'mc>( +pub struct GlowItemFrame<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for FoxType<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for FoxType<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate FoxType from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Fox/Type")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a FoxType object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for FoxTypeStruct<'mc> { +impl<'mc> JNIRaw<'mc> for GlowItemFrame<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -17558,18 +24279,18 @@ impl<'mc> JNIRaw<'mc> for FoxTypeStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for FoxTypeStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for GlowItemFrame<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate FoxTypeStruct from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate GlowItemFrame from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Fox/Type")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/GlowItemFrame")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a FoxTypeStruct object, got {}", + "Invalid argument passed. Expected a GlowItemFrame object, got {}", name ) .into()) @@ -17579,102 +24300,200 @@ impl<'mc> JNIInstantiatable<'mc> for FoxTypeStruct<'mc> { } } -impl<'mc> FoxTypeStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Fox/Type;"); - let cls = jni.find_class("org/bukkit/entity/Fox/Type"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::FoxType::from_raw(&jni, obj) +impl<'mc> GlowItemFrame<'mc> { + /// Get the item in this frame + pub fn item(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + /// Set the item in this frame + pub fn set_item( + &self, + item: impl Into>, + play_sound: std::option::Option, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = play_sound { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setItem", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -#[repr(C)] -pub struct Donkey<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Donkey<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Gets the chance of the item being dropped upon this frame's destruction. + ///
    + ///
  • A drop chance of 0.0F will never drop + ///
  • A drop chance of 1.0F will always drop + ///
+ pub fn item_drop_chance(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItemDropChance", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Sets the chance of the off hand item being dropped upon this frame's + /// destruction. + ///
    + ///
  • A drop chance of 0.0F will never drop + ///
  • A drop chance of 1.0F will always drop + ///
+ pub fn set_item_drop_chance(&self, chance: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(chance); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItemDropChance", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -impl<'mc> JNIInstantiatable<'mc> for Donkey<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Donkey from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Donkey")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Donkey object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Get the rotation of the frame's item + pub fn rotation(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Rotation;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRotation", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Rotation::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Set the rotation of the frame's item + pub fn set_rotation( + &self, + rotation: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Rotation;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(rotation.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRotation", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> Donkey<'mc> { - /// Gets whether the horse has a chest equipped. - pub fn is_carrying_chest(&self) -> Result> { + /// Returns whether the item frame is be visible or not. + pub fn is_visible(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCarryingChest", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isVisible", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the horse has a chest equipped. Removing a chest will also - /// clear the chest's inventory. - pub fn set_carrying_chest(&self, chest: bool) -> Result<(), Box> { + /// Sets whether the item frame should be visible or not. + pub fn set_visible(&self, visible: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(chest.into()); + let val_1 = jni::objects::JValueGen::Bool(visible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCarryingChest", + "setVisible", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns whether the item frame is "fixed" or not. + /// When true it's not possible to destroy/move the frame (e.g. by damage, + /// interaction, pistons, or missing supporting blocks), rotate the item or + /// place/remove items. + pub fn is_fixed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFixed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the item frame should be fixed or not. + /// When set to true it's not possible to destroy/move the frame (e.g. by + /// damage, interaction, pistons, or missing supporting blocks), rotate the + /// item or place/remove items. + pub fn set_fixed(&self, fixed: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fixed.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFixed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } + /// Sets the direction of the hanging entity, potentially overriding rules + /// of placement. Note that if the result is not valid the object would + /// normally drop as an item. + pub fn set_facing_direction( + &self, + face: impl Into>, + force: bool, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;Z)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Bool(force.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFacingDirection", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Donkey<'mc> { - fn into(self) -> crate::entity::ChestedHorse<'mc> { - crate::entity::ChestedHorse::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Donkey into crate::entity::ChestedHorse") +impl<'mc> Into> for GlowItemFrame<'mc> { + fn into(self) -> crate::entity::ItemFrame<'mc> { + crate::entity::ItemFrame::from_raw(&self.jni_ref(), self.1) + .expect("Error converting GlowItemFrame into crate::entity::ItemFrame") } } #[repr(C)] -pub struct Chicken<'mc>( +pub struct EntitySnapshot<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Chicken<'mc> { +impl<'mc> JNIRaw<'mc> for EntitySnapshot<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -17682,18 +24501,20 @@ impl<'mc> JNIRaw<'mc> for Chicken<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Chicken<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EntitySnapshot<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Chicken from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate EntitySnapshot from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Chicken")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EntitySnapshot")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Chicken object, got {}", + "Invalid argument passed. Expected a EntitySnapshot object, got {}", name ) .into()) @@ -17703,102 +24524,55 @@ impl<'mc> JNIInstantiatable<'mc> for Chicken<'mc> { } } -impl<'mc> Chicken<'mc> { - /// Get the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn breed_cause( +impl<'mc> EntitySnapshot<'mc> { + /// Creates an entity using this template and spawns it at the provided location. + pub fn create_entity( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/UUID;"); + to: impl Into>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(to.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Lorg/bukkit/entity/Entity;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "createEntity", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn set_breed_cause( + /// Gets the type of entity this template holds. + pub fn entity_type( &self, - uuid: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/UUID;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setBreedCause", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get whether or not this entity is in love mode and will produce - /// offspring with another entity in love mode. Will return true if - /// and only if {@link #getLoveModeTicks()} is greater than 0. - pub fn is_love_mode(&self) -> Result> { - let sig = String::from("()Z"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEntityType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get the amount of ticks remaining for this entity in love mode. - /// If the entity is not in love mode, 0 will be returned. - pub fn love_mode_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLoveModeTicks", - sig.as_str(), - vec![], - ); + /// Get this EntitySnapshot as an NBT string. + /// + /// This string should not be relied upon as a serializable value. + pub fn as_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the amount of ticks for which this entity should be in love mode. - /// Setting the love mode ticks to 600 is the equivalent of a player - /// feeding the entity their breeding item of choice. - pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLoveModeTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Check if the provided ItemStack is the correct item used for breeding - /// this entity.. - pub fn is_breed_item( - &self, - material: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Z"; - let res = self + Ok(self .jni_ref() - .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -17806,19 +24580,13 @@ impl<'mc> Chicken<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Chicken<'mc> { - fn into(self) -> crate::entity::Animals<'mc> { - crate::entity::Animals::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Chicken into crate::entity::Animals") - } -} #[repr(C)] -pub struct EnderSignal<'mc>( +pub struct LivingEntity<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EnderSignal<'mc> { +impl<'mc> JNIRaw<'mc> for LivingEntity<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -17826,18 +24594,18 @@ impl<'mc> JNIRaw<'mc> for EnderSignal<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EnderSignal<'mc> { +impl<'mc> JNIInstantiatable<'mc> for LivingEntity<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate EnderSignal from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate LivingEntity from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EnderSignal")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/LivingEntity")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EnderSignal object, got {}", + "Invalid argument passed. Expected a LivingEntity object, got {}", name ) .into()) @@ -17847,1051 +24615,961 @@ impl<'mc> JNIInstantiatable<'mc> for EnderSignal<'mc> { } } -impl<'mc> EnderSignal<'mc> { - /// Get the location this EnderSignal is moving towards. - pub fn tarlocation(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTargetLocation", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Set the {@link Location} this EnderSignal is moving towards. - /// - /// When setting a new target location, the {@link #getDropItem()} resets to - /// a random value and the despawn timer gets set back to 0. - pub fn set_target_location( - &self, - location: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Location;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); +impl<'mc> LivingEntity<'mc> { + /// Gets the height of the living entity's eyes above its Location. + pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { + let sig = String::from("(Z)D"); + let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setTargetLocation", + "getEyeHeight", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } - /// Gets if the EnderSignal should drop an item on death. - /// - /// If {@code true}, it will drop an item. If {@code false}, it will shatter. - pub fn drop_item(&self) -> Result> { - let sig = String::from("()Z"); + /// Get a Location detailing the current eye position of the living entity. + pub fn eye_location(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDropItem", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets if the EnderSignal should drop an item on death; or if it should - /// shatter. - pub fn set_drop_item(&self, drop: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(drop.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setDropItem", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the {@link ItemStack} to be displayed while in the air and to be - /// dropped on death. - pub fn item(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Set the {@link ItemStack} to be displayed while in the air and to be - /// dropped on death. - pub fn set_item( - &self, - item: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setItem", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the amount of time this entity has been alive (in ticks). - /// - /// When this number is greater than 80, it will despawn on the next tick. - pub fn despawn_timer(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDespawnTimer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set how long this entity has been alive (in ticks). - /// - /// When this number is greater than 80, it will despawn on the next tick. - pub fn set_despawn_timer(&self, timer: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(timer); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setDespawnTimer", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Stores the entity's current position in the provided Location object. + /// Gets all blocks along the living entity's line of sight. /// - /// If the provided Location is null this method does nothing and returns - /// null. - pub fn get_location( + /// This list contains all blocks from the living entity's eye position to + /// target inclusive. This method considers all blocks as 1x1x1 in size. + pub fn get_line_of_sight( &self, - loc: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocation", + "getLineOfSight", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(new_vec) } - /// Sets this entity's velocity in meters per tick - pub fn set_velocity( + /// Gets the block that the living entity has targeted. + /// + /// This method considers all blocks as 1x1x1 in size. To take exact block + /// collision shapes into account, see {@link #getTargetBlockExact(int, + /// FluidCollisionMode)}. + pub fn get_target_block( &self, - velocity: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + transparent: impl Into>, + max_distance: i32, + ) -> Result, Box> { + let sig = String::from("(Ljava/util/Set;I)Lorg/bukkit/block/Block;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setVelocity", + "getTargetBlock", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets this entity's current velocity - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + crate::block::Block::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the entity's height - pub fn height(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the entity's width - pub fn width(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the entity's current bounding box. + /// Gets the last two blocks along the living entity's line of sight. /// - /// The returned bounding box reflects the entity's current location and - /// size. - pub fn bounding_box( + /// The target block will be the last block in the list. This method + /// considers all blocks as 1x1x1 in size. + pub fn get_last_two_target_blocks( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns true if the entity is supported by a block. This value is a - /// state updated by the server and is not recalculated unless the entity - /// moves. - pub fn is_on_ground(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns true if the entity is in water. - pub fn is_in_water(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the current world this entity resides in - pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the entity's rotation. - /// - /// Note that if the entity is affected by AI, it may override this rotation. - pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { - let sig = String::from("(FF)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); - let val_2 = jni::objects::JValueGen::Float(pitch); + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setRotation", + "getLastTwoTargetBlocks", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Teleports this entity to the given location. If this entity is riding a - /// vehicle, it will be dismounted prior to teleportation. - pub fn teleport( + /// Gets the block that the living entity has targeted. + /// + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn get_target_block_exact( &self, - location: impl Into>, - cause: std::option::Option< - impl Into>, - >, - ) -> Result> { + max_distance: i32, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(max_distance); args.push(val_1); - if let Some(a) = cause { - sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; let val_2 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); args.push(val_2); } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "teleport", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns a list of entities within a bounding box centered around this - /// entity - pub fn get_nearby_entities( - &self, - x: f64, - y: f64, - z: f64, - ) -> Result>, Box> { - let sig = String::from("(DDD)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Double(x); - let val_2 = jni::objects::JValueGen::Double(y); - let val_3 = jni::objects::JValueGen::Double(z); + sig += ")Lorg/bukkit/block/Block;"; let res = self.jni_ref().call_method( &self.jni_object(), - "getNearbyEntities", + "getTargetBlockExact", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + args, ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - Ok(new_vec) - } - /// Returns a unique id for this entity - pub fn entity_id(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(Some(crate::block::Block::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Returns the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn fire_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Performs a ray trace that provides information on the targeted block. + /// + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn ray_trace_blocks( + &self, + max_distance: f64, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/util/RayTraceResult;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::util::RayTraceResult::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Returns the entity's maximum fire ticks. - pub fn max_fire_ticks(&self) -> Result> { + /// Returns the amount of air that the living entity has remaining, in + /// ticks. + pub fn remaining_air(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Sets the amount of air that the living entity has remaining, in ticks. + pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setFireTicks", + "setRemainingAir", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets if the entity has visual fire (it will always appear to be on fire). - pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire.into()); + /// Returns the maximum amount of air the living entity can have, in ticks. + pub fn maximum_air(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the maximum amount of air the living entity can have, in ticks. + pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisualFire", + "setMaximumAir", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity has visual fire (it will always appear to be on fire). - pub fn is_visual_fire(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the item that the player is using (eating food, drawing back a bow, + /// blocking, etc.) + pub fn item_in_use( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Returns the entity's maximum freeze ticks (amount of ticks before it will - /// be fully frozen) - pub fn max_freeze_ticks(&self) -> Result> { + /// Gets the number of ticks remaining for the current item's usage. + pub fn item_in_use_ticks(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getMaxFreezeTicks", + "getItemInUseTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Sets the number of ticks that remain for the current item's usage. + /// Applies to items that take time to use, like eating food, drawing a bow, + /// or throwing a trident. + pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setFreezeTicks", + "setItemInUseTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity is fully frozen (it has been in powdered snow for max - /// freeze ticks). - pub fn is_frozen(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); + /// Gets the time in ticks until the next arrow leaves the entity's body. + pub fn arrow_cooldown(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getArrowCooldown", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Mark the entity's removal. - pub fn remove(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); + /// Sets the time in ticks until the next arrow leaves the entity's body. + pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setArrowCooldown", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns true if this entity has been marked for removal. - pub fn is_dead(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns false if the entity has died, been despawned for some other - /// reason, or has not been added to the world. - pub fn is_valid(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the {@link Server} that contains this Entity - pub fn server(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Server;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Server::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns true if the entity gets persisted. - /// - /// By default all entities are persistent. An entity will also not get - /// persisted, if it is riding an entity that is not persistent. - /// - /// The persistent flag on players controls whether or not to save their - /// playerdata file when they quit. If a player is directly or indirectly - /// riding a non-persistent entity, the vehicle at the root and all its - /// passengers won't get persisted. - /// - /// This should not be confused with - /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls - /// despawning of living entities. - pub fn is_persistent(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the amount of arrows in an entity's body. + pub fn arrows_in_body(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets whether or not the entity gets persisted. - pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(persistent.into()); + /// Set the amount of arrows in the entity's body. + pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(count); let res = self.jni_ref().call_method( &self.jni_object(), - "setPersistent", + "setArrowsInBody", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. - pub fn passenger( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); + /// Returns the living entity's current maximum no damage ticks. + /// + /// This is the maximum duration in which the living entity will not take + /// damage. + pub fn maximum_no_damage_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaximumNoDamageTicks", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - #[deprecated] - /// Set the passenger of a vehicle. - pub fn set_passenger( + /// Sets the living entity's current maximum no damage ticks. + pub fn set_maximum_no_damage_ticks( &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); + ticks: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setPassenger", + "setMaximumNoDamageTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets a list of passengers of this vehicle. + /// Returns the living entity's last damage taken in the current no damage + /// ticks time. /// - /// The returned list will not be directly linked to the entity's current - /// passengers, and no guarantees are made as to its mutability. - pub fn passengers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + /// Only damage higher than this amount will further damage the living + /// entity. + pub fn last_damage(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(res.d()?) } - /// Add a passenger to the vehicle. - pub fn add_passenger( - &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); + /// Sets the damage dealt within the current no damage ticks time period. + pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(damage); let res = self.jni_ref().call_method( &self.jni_object(), - "addPassenger", + "setLastDamage", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Remove a passenger from the vehicle. - pub fn remove_passenger( - &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); + /// Returns the living entity's current no damage ticks. + pub fn no_damage_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "removePassenger", + "getNoDamageTicks", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Check if a vehicle has passengers. - pub fn is_empty(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Eject any passenger. - pub fn eject(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Sets the living entity's current no damage ticks. + pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setNoDamageTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns the distance this entity has fallen - pub fn fall_distance(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); + /// Get the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn no_action_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNoActionTicks", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + Ok(res.i()?) } - /// Sets the fall distance for this entity - pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(distance); + /// Set the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setFallDistance", + "setNoActionTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Record the last {@link EntityDamageEvent} inflicted on this entity - pub fn set_last_damage_cause( + /// Gets the player identified as the killer of the living entity. + /// + /// May be null. + pub fn killer(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Player::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + #[deprecated] + /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. + pub fn add_potion_effect( + &self, + effect: impl Into>, + force: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/potion/PotionEffect;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = force { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns whether the living entity already has an existing effect of + /// the given {@link PotionEffectType} applied to it. + pub fn has_potion_effect( &self, - event: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); + val_type: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(event.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDamageCause", + "hasPotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. - /// This event may have been cancelled. - pub fn last_damage_cause( + /// Returns the active {@link PotionEffect} of the specified type. + /// + /// If the effect is not present on the entity then null will be returned. + pub fn get_potion_effect( &self, - ) -> Result>, Box> - { - let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + val_type: impl Into>, + ) -> Result>, Box> { + let sig = + String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getLastDamageCause", + "getPotionEffect", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( + Ok(Some(crate::potion::PotionEffect::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Returns a unique and persistent id for this entity - pub fn unique_id( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. - pub fn ticks_lived(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. May not be less than one - /// tick. - pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(value); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTicksLived", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Performs the specified {@link EntityEffect} for this entity. - /// - /// This will be viewable to all players near the entity. - /// - /// If the effect is not applicable to this class of entity, it will not play. - pub fn play_effect( + /// Removes any effects present of the given {@link PotionEffectType}. + pub fn remove_potion_effect( &self, - val_type: impl Into>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "playEffect", + "removePotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the type of the entity. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity makes while swimming. - pub fn swim_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity makes when splashing in water. For most - /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_splash_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Returns all currently active {@link PotionEffect}s on the living + /// entity. + pub fn active_potion_effects( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimSplashSound", + "getActivePotionEffects", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Get the {@link Sound} this entity makes when splashing in water at high - /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_high_speed_splash_sound( + /// Checks whether the living entity has block line of sight to another. + /// + /// This uses the same algorithm that hostile mobs use to find the closest + /// player. + pub fn has_line_of_sight( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + other: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(other.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimHighSpeedSplashSound", + "hasLineOfSight", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns whether this entity is inside a vehicle. - pub fn is_inside_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Leave the current vehicle. If the entity is currently in a vehicle (and - /// is removed from it), true will be returned, otherwise false will be - /// returned. - pub fn leave_vehicle(&self) -> Result> { + /// Returns if the living entity despawns when away from players or not. + /// + /// By default, animals are not removed while other mobs are. + pub fn remove_when_far_away(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getRemoveWhenFarAway", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get the vehicle that this entity is inside. If there is no vehicle, - /// null will be returned. - pub fn vehicle( + /// Sets whether or not the living entity despawns when away from players + /// or not. + pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(remove.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRemoveWhenFarAway", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the inventory with the equipment worn by the living entity. + pub fn equipment( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Entity::from_raw( + Ok(Some(crate::inventory::EntityEquipment::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets whether or not to display the mob's custom name client side. The - /// name will be displayed above the mob similarly to a player. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { + /// Sets whether or not the living entity can pick up items. + pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(pickup.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomNameVisible", + "setCanPickupItems", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not the mob's custom name is displayed client side. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn is_custom_name_visible(&self) -> Result> { + /// Gets if the living entity can pick up items. + pub fn can_pickup_items(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "isCustomNameVisible", + "getCanPickupItems", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(visible.into()); + /// Returns whether the entity is currently leashed. + pub fn is_leashed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the entity that is currently leading this entity. + pub fn leash_holder(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the leash on this entity to be held by the supplied entity. + /// + /// This method has no effect on EnderDragons, Withers, Players, or Bats. + /// Non-living entities excluding leashes will not persist as leash + /// holders. + pub fn set_leash_holder( + &self, + holder: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(holder.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisibleByDefault", + "setLeashHolder", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn is_visible_by_default(&self) -> Result> { + /// Checks to see if an entity is gliding, such as using an Elytra. + pub fn is_gliding(&self) -> Result> { let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Makes entity start or stop gliding. This will work even if an Elytra + /// is not equipped, but will be reverted by the server immediately after + /// unless an event-cancelling mechanism is put in place. + pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gliding.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "isVisibleByDefault", + "setGliding", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get all players that are currently tracking this entity. - /// - /// 'Tracking' means that this entity has been sent to the player and that - /// they are receiving updates on its state. Note that the client's {@code - /// 'Entity Distance'} setting does not affect the range at which entities - /// are tracked. - pub fn tracked_by( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Checks to see if an entity is swimming. + pub fn is_swimming(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets whether the entity has a team colored (default: white) glow. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { + /// Makes entity start or stop swimming. + /// This may have unexpected results if the entity is not in water. + pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(swimming.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setGlowing", + "setSwimming", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is glowing or not. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn is_glowing(&self) -> Result> { + /// Checks to see if an entity is currently riptiding. + pub fn is_riptiding(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the entity is invulnerable or not. + /// Makes entity start or stop riptiding. /// - /// When an entity is invulnerable it can only be damaged by players in - /// creative mode. - pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { + /// Note: This does not damage attackable entities. + pub fn set_riptiding(&self, riptiding: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(riptiding.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvulnerable", + "setRiptiding", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invulnerable or not. - pub fn is_invulnerable(&self) -> Result> { + /// Returns whether this entity is slumbering. + pub fn is_sleeping(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets whether the entity is silent or not. - pub fn is_silent(&self) -> Result> { + /// Gets if the entity is climbing. + pub fn is_climbing(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the entity is silent or not. - /// - /// When an entity is silent it will not produce any sound. - pub fn set_silent(&self, flag: bool) -> Result<(), Box> { + /// Sets whether an entity will have AI. + /// The entity will be completely unable to move if it has no AI. + pub fn set_ai(&self, ai: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(ai.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setSilent", + "setAI", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether gravity applies to this entity. - pub fn has_gravity(&self) -> Result> { + /// Checks whether an entity has AI. + /// The entity will be completely unable to move if it has no AI. + pub fn has_ai(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether gravity applies to this entity. - pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gravity.into()); + /// Makes this entity attack the given entity with a melee attack. + /// Attack damage is calculated by the server from the attributes and + /// equipment of this mob, and knockback is applied to {@code target} as + /// appropriate. + pub fn attack( + &self, + target: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(target.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setGravity", + "attack", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the period of time (in ticks) before this entity can use a portal. - pub fn portal_cooldown(&self) -> Result> { - let sig = String::from("()I"); + /// Makes this entity swing their main hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their main hand. + pub fn swing_main_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Makes this entity swing their off hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their off hand. + pub fn swing_off_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Makes this entity flash red as if they were damaged. + pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); let res = self.jni_ref().call_method( &self.jni_object(), - "getPortalCooldown", + "playHurtAnimation", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the period of time (in ticks) before this entity can use a portal. - pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(cooldown); + /// Set if this entity will be subject to collisions with other entities. + /// + /// Exemptions to this rule can be managed with + /// {@link #getCollidableExemptions()} + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not working for player collisions. This + /// method should therefore only be used to set the collision status of + /// non-player entities. + /// + /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in + /// combination with a {@link Scoreboard} and a {@link Team}. + pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(collidable.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setPortalCooldown", + "setCollidable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a set of tags for this entity. + /// Gets if this entity is subject to collisions with other entities. + /// + /// Some entities might be exempted from the collidable rule of this entity. + /// Use {@link #getCollidableExemptions()} to get these. + /// + /// Please note that this method returns only the custom collidable state, + /// not whether the entity is non-collidable for other reasons such as being + /// dead. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not being accurate for player collisions. + /// This method should therefore only be used to check the collision status + /// of non-player entities. + /// + /// To check the collision behavior for a player, use + /// {@link Team.Option#COLLISION_RULE} in combination with a + /// {@link Scoreboard} and a {@link Team}. + pub fn is_collidable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets a mutable set of UUIDs of the entities which are exempt from the + /// entity's collidable rule and which's collision with this entity will + /// behave the opposite of it. + /// + /// This set can be modified to add or remove exemptions. /// - /// Entities can have no more than 1024 tags. - pub fn scoreboard_tags( + /// For example if collidable is true and an entity is in the exemptions set + /// then it will not collide with it. Similarly if collidable is false and an + /// entity is in this set then it will still collide with it. + /// + /// Note these exemptions are not (currently) persistent. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in those exemptions not being accurate for player + /// collisions. This method should therefore only be used to exempt + /// non-player entities. + /// + /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} + /// in combination with a {@link Scoreboard} and a {@link Team}. + pub fn collidable_exemptions( &self, ) -> Result, Box> { let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getScoreboardTags", + "getCollidableExemptions", sig.as_str(), vec![], ); @@ -18900,557 +25578,389 @@ impl<'mc> EnderSignal<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Add a tag to this entity. + /// Returns the value of the memory specified. /// - /// Entities can have no more than 1024 tags. - pub fn add_scoreboard_tag( - &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addScoreboardTag", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Removes a given tag from this entity. - pub fn remove_scoreboard_tag( + /// Note that the value is null when the specific entity does not have that + /// value by default. + pub fn get_memory( &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); + memory_key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeScoreboardTag", + "getMemory", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the reaction of the entity when moved by a piston. - pub fn piston_move_reaction( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPistonMoveReaction", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) } - /// Get the closest cardinal {@link BlockFace} direction an entity is - /// currently facing. - /// - /// This will not return any non-cardinal directions such as - /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// Sets the value of the memory specified. /// - /// {@link Hanging} entities will override this call and thus their behavior - /// may be different. - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the entity's current pose. - /// Note that the pose is only updated at the end of a tick, so may be - /// inconsistent with other methods. eg {@link Player#isSneaking()} being - /// true does not imply the current pose will be {@link Pose#SNEAKING} - pub fn pose(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Pose;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the category of spawn to which this entity belongs. - pub fn spawn_category( + /// Note that the value will not be persisted when the specific entity does + /// not have that value by default. + pub fn set_memory( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); + memory_key: impl Into>, + memory_value: jni::objects::JObject<'mc>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(memory_value); let res = self.jni_ref().call_method( &self.jni_object(), - "getSpawnCategory", + "setMemory", sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - let res = self.jni_ref().translate_error(res)?; - crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Checks if this entity has been spawned in a world. - /// - /// Entities not spawned in a world will not tick, be sent to players, or be - /// saved to the server files. - pub fn is_in_world(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get this entity as an NBT string. - /// - /// This string should not be relied upon as a serializable value. - pub fn as_string(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); + /// Get the {@link Sound} this entity will make when damaged. + pub fn hurt_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Crates an {@link EntitySnapshot} representing the current state of this entity. - pub fn create_snapshot( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + /// Get the {@link Sound} this entity will make on death. + pub fn death_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::EntitySnapshot::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Creates a copy of this entity and all its data. Spawns the copy at the given location. - /// - /// Note: Players cannot be copied. - pub fn copy( - &self, - to: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = to { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")Lorg/bukkit/entity/Entity;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for EnderSignal<'mc> { - fn into(self) -> crate::entity::Entity<'mc> { - crate::entity::Entity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EnderSignal into crate::entity::Entity") - } -} -#[repr(C)] -pub struct ElderGuardian<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for ElderGuardian<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for ElderGuardian<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ElderGuardian from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ElderGuardian")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ElderGuardian object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + })?)) } -} - -impl<'mc> ElderGuardian<'mc> { - /// Sets whether the guardian laser should show or not. - /// A target must be present. If no target is present the laser will not show - /// and the method will return false. - pub fn set_laser(&self, activated: bool) -> Result> { - let sig = String::from("(Z)Z"); - let val_1 = jni::objects::JValueGen::Bool(activated.into()); + /// Get the {@link Sound} this entity will make when falling from the given + /// height (in blocks). The sound will often differ between either a small + /// or a big fall damage sound if the height exceeds 4 blocks. + pub fn get_fall_damage_sound( + &self, + fall_height: i32, + ) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Int(fall_height); let res = self.jni_ref().call_method( &self.jni_object(), - "setLaser", + "getFallDamageSound", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets whether the guardian laser is active or not. - pub fn has_laser(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasLaser", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get the duration (in ticks) that a laser attack takes. - pub fn laser_duration(&self) -> Result> { - let sig = String::from("()I"); + /// Get the {@link Sound} this entity will make when falling from a small + /// height. + pub fn fall_damage_sound_small(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLaserDuration", + "getFallDamageSoundSmall", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the amount of ticks that have elapsed since this guardian has initiated - /// a laser attack. If set to {@link #getLaserDuration()} or greater, the guardian - /// will inflict damage upon its target and the laser attack will complete. - /// - /// For this value to have any effect, the guardian must have an active target - /// (see {@link #setTarget(LivingEntity)}) and be charging a laser attack (where - /// {@link #hasLaser()} is true). The client may display a different animation of - /// the guardian laser than the set ticks. - pub fn set_laser_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Get the {@link Sound} this entity will make when falling from a large + /// height. + pub fn fall_damage_sound_big(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setLaserTicks", + "getFallDamageSoundBig", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the amount of ticks that have elapsed since this guardian has initiated - /// a laser attack. - /// - /// This value may or may not be significant depending on whether or not the guardian - /// has an active target ({@link #getTarget()}) and is charging a laser attack - /// ({@link #hasLaser()}). This value is not reset after a successful attack nor used - /// in the next and will be reset to the minimum value when the guardian initiates a - /// new one. - pub fn laser_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLaserTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - #[deprecated] - /// Check if the Guardian is an elder Guardian - pub fn is_elder(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isElder", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - - pub fn set_elder(&self, should_be_elder: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(should_be_elder.into()); + /// Get the {@link Sound} this entity will make when drinking the given + /// {@link ItemStack}. + pub fn get_drinking_sound( + &self, + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setElder", + "getDrinkingSound", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Check whether or not this guardian is moving. - /// - /// While moving, the guardian's spikes are retracted and will not inflict thorns - /// damage upon entities that attack it. Additionally, a moving guardian cannot - /// attack another entity. If stationary (i.e. this method returns {@code false}), - /// thorns damage is guaranteed and the guardian may initiate laser attacks. - pub fn is_moving(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isMoving", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for ElderGuardian<'mc> { - fn into(self) -> crate::entity::Guardian<'mc> { - crate::entity::Guardian::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ElderGuardian into crate::entity::Guardian") - } -} -#[repr(C)] -pub struct Ghast<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Ghast<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Ghast<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Ghast from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Ghast")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Ghast object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Ghast<'mc> { - /// Gets whether the Ghast is charging - pub fn is_charging(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCharging", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets whether the Ghast is charging - pub fn set_charging(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Get the {@link Sound} this entity will make when eating the given + /// {@link ItemStack}. + pub fn get_eating_sound( + &self, + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCharging", + "getEatingSound", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Ghast<'mc> { - fn into(self) -> crate::entity::Flying<'mc> { - crate::entity::Flying::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Ghast into crate::entity::Flying") - } -} -impl<'mc> Into> for Ghast<'mc> { - fn into(self) -> crate::entity::Enemy<'mc> { - crate::entity::Enemy::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Ghast into crate::entity::Enemy") - } -} -#[repr(C)] -pub struct Vex<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Vex<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Vex<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Vex from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Vex")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Vex object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} - -impl<'mc> Vex<'mc> { - /// Gets the charging state of this entity. - /// When this entity is charging it will having a glowing red texture. - pub fn is_charging(&self) -> Result> { + /// Returns true if this entity can breathe underwater and will not take + /// suffocation damage when its air supply reaches zero. + pub fn can_breathe_underwater(&self) -> Result> { let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "canBreatheUnderwater", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. + pub fn category( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCharging", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the charging state of this entity. - /// When this entity is charging it will having a glowing red texture. - pub fn set_charging(&self, charging: bool) -> Result<(), Box> { + /// Sets whether the entity is invisible or not. + pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(charging.into()); + let val_1 = jni::objects::JValueGen::Bool(invisible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCharging", + "setInvisible", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the bound of this entity. - /// An idle vex will navigate a 15x11x15 area centered around its bound - /// location. - /// When summoned by an Evoker, this location will be set to that of the - /// summoner. - pub fn bound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBound", sig.as_str(), vec![]); + /// Gets whether the entity is invisible or not. + pub fn is_invisible(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the specified attribute instance from the object. This instance will + /// be backed directly to the object and any changes will be visible at once. + pub fn get_attribute( + &self, + attribute: impl Into>, + ) -> Result>, Box> { + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAttribute", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(Some(crate::attribute::AttributeInstance::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the bound of this entity. - /// An idle vex will navigate a 15x11x15 area centered around its bound - /// location. - /// When summoned by an Evoker, this location will be set to that of the - /// summoner. - pub fn set_bound( + /// Deals the given amount of damage to this entity from a specified + /// {@link DamageSource}. + pub fn damage( &self, - location: impl Into>, + amount: f64, + damage_source: std::option::Option>>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Location;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(amount); + args.push(val_1); + if let Some(a) = damage_source { + sig += "Lorg/bukkit/damage/DamageSource;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "damage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. + pub fn health(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is + /// dead. + pub fn set_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "setBound", + "setHealth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the remaining lifespan of this entity. - pub fn life_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the entity's absorption amount. + pub fn absorption_amount(&self) -> Result> { + let sig = String::from("()D"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAbsorptionAmount", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Sets the entity's absorption amount. + /// + /// Note: The amount is capped to the value of + /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on + /// that attribute is currently unspecified and subject to change. + pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(amount); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAbsorptionAmount", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the maximum health this entity has. + pub fn max_health(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLifeTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.d()?) } - /// Sets the remaining lifespan of this entity. - pub fn set_life_ticks(&self, life_ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(life_ticks); + #[deprecated] + /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. + pub fn set_max_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "setLifeTicks", + "setMaxHealth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity has a limited life. - pub fn has_limited_life(&self) -> Result> { - let sig = String::from("()Z"); + #[deprecated] + /// Resets the max health to the original amount. + pub fn reset_max_health(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasLimitedLife", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Launches a {@link Projectile} from the ProjectileSource with an + /// initial velocity. + pub fn launch_projectile( + &self, + projectile: jni::objects::JClass<'mc>, + velocity: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(projectile.into()); + args.push(val_1); + if let Some(a) = velocity { + sig += "Lorg/bukkit/util/Vector;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")LT;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.l()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -19458,19 +25968,31 @@ impl<'mc> Vex<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Vex<'mc> { - fn into(self) -> crate::entity::Monster<'mc> { - crate::entity::Monster::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Vex into crate::entity::Monster") +impl<'mc> Into> for LivingEntity<'mc> { + fn into(self) -> crate::attribute::Attributable<'mc> { + crate::attribute::Attributable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting LivingEntity into crate::attribute::Attributable") + } +} +impl<'mc> Into> for LivingEntity<'mc> { + fn into(self) -> crate::entity::Damageable<'mc> { + crate::entity::Damageable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting LivingEntity into crate::entity::Damageable") + } +} +impl<'mc> Into> for LivingEntity<'mc> { + fn into(self) -> crate::projectiles::ProjectileSource<'mc> { + crate::projectiles::ProjectileSource::from_raw(&self.jni_ref(), self.1) + .expect("Error converting LivingEntity into crate::projectiles::ProjectileSource") } } #[repr(C)] -pub struct ItemDisplay<'mc>( +pub struct TippedArrow<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ItemDisplay<'mc> { +impl<'mc> JNIRaw<'mc> for TippedArrow<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -19478,18 +26000,18 @@ impl<'mc> JNIRaw<'mc> for ItemDisplay<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ItemDisplay<'mc> { +impl<'mc> JNIInstantiatable<'mc> for TippedArrow<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ItemDisplay from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate TippedArrow from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ItemDisplay")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/TippedArrow")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ItemDisplay object, got {}", + "Invalid argument passed. Expected a TippedArrow object, got {}", name ) .into()) @@ -19499,429 +26021,520 @@ impl<'mc> JNIInstantiatable<'mc> for ItemDisplay<'mc> { } } -impl<'mc> ItemDisplay<'mc> { - /// Gets the displayed item stack. - pub fn item_stack( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemStack", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Sets the displayed item stack. - pub fn set_item_stack( +impl<'mc> TippedArrow<'mc> { + #[deprecated] + /// Sets the underlying potion data + pub fn set_base_potion_data( &self, - item: impl Into>, + data: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let sig = String::from("(Lorg/bukkit/potion/PotionData;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(data.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemStack", + "setBasePotionData", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the item display transform for this entity. - /// Defaults to {@link ItemDisplayTransform#FIXED}. - pub fn item_display_transform( + #[deprecated] + /// Returns the potion data about the base potion + pub fn base_potion_data( &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/entity/ItemDisplay/ItemDisplayTransform;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/potion/PotionData;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getItemDisplayTransform", + "getBasePotionData", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::entity::ItemDisplayItemDisplayTransform::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::potion::PotionData::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the item display transform for this entity. - /// Defaults to {@link ItemDisplayTransform#FIXED}. - pub fn set_item_display_transform( + /// Sets the underlying potion type + pub fn set_base_potion_type( &self, - display: impl Into>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/ItemDisplay/ItemDisplayTransform;)V"); + let sig = String::from("(Lorg/bukkit/potion/PotionType;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(display.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemDisplayTransform", + "setBasePotionType", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the transformation applied to this display. - pub fn transformation( + /// Returns the potion type about the base potion + pub fn base_potion_type( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Transformation;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/potion/PotionType;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getTransformation", + "getBasePotionType", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::util::Transformation::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::potion::PotionType::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the color of this arrow. + pub fn color(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Color;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Color::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) + })?)) } - /// Sets the transformation applied to this display - pub fn set_transformation( + /// Sets the color of this arrow. Will be applied as a tint to its particles. + pub fn set_color( &self, - transformation: impl Into>, + color: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Transformation;)V"); + let sig = String::from("(Lorg/bukkit/Color;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transformation.into().jni_object().clone()) + jni::objects::JObject::from_raw(color.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setTransformation", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Sets the raw transformation matrix applied to this display - pub fn set_transformation_matrix( - &self, - transformation_matrix: jni::objects::JObject<'mc>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/joml/Matrix4f;)V"); - let val_1 = jni::objects::JValueGen::Object(transformation_matrix); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTransformationMatrix", + "setColor", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the interpolation duration of this display. - pub fn interpolation_duration(&self) -> Result> { - let sig = String::from("()I"); + /// Checks for the presence of custom potion effects. + pub fn has_custom_effects(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getInterpolationDuration", + "hasCustomEffects", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the interpolation duration of this display. - pub fn set_interpolation_duration( + /// Gets an immutable list containing all custom potion effects applied to + /// this arrow. + /// + /// Plugins should check that hasCustomEffects() returns true before calling + /// this method. + pub fn custom_effects( &self, - duration: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(duration); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setInterpolationDuration", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the teleport duration of this display. - ///
    - ///
  • 0 means that updates are applied immediately.
  • - ///
  • 1 means that the display entity will move from current position to the updated one over one tick.
  • - ///
  • Higher values spread the movement over multiple ticks.
  • - ///
- pub fn teleport_duration(&self) -> Result> { - let sig = String::from("()I"); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getTeleportDuration", + "getCustomEffects", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the teleport duration of this display. - pub fn set_teleport_duration(&self, duration: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(duration); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTeleportDuration", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the view distance/range of this display. - pub fn view_range(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getViewRange", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Sets the view distance/range of this display. - pub fn set_view_range(&self, range: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(range); + /// Adds a custom potion effect to this arrow. + pub fn add_custom_effect( + &self, + effect: impl Into>, + overwrite: bool, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffect;Z)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Bool(overwrite.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setViewRange", + "addCustomEffect", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the shadow radius of this display. - pub fn shadow_radius(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getShadowRadius", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Sets the shadow radius of this display. - pub fn set_shadow_radius(&self, radius: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(radius); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setShadowRadius", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.z()?) } - /// Gets the shadow strength of this display. - pub fn shadow_strength(&self) -> Result> { - let sig = String::from("()F"); + /// Removes a custom potion effect from this arrow. + pub fn remove_custom_effect( + &self, + val_type: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getShadowStrength", + "removeCustomEffect", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + Ok(res.z()?) } - /// Sets the shadow strength of this display. - pub fn set_shadow_strength(&self, strength: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(strength); + /// Checks for a specific custom potion effect type on this arrow. + pub fn has_custom_effect( + &self, + val_type: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setShadowStrength", + "hasCustomEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the width of this display. - pub fn display_width(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDisplayWidth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + Ok(res.z()?) } - /// Sets the width of this display. - pub fn set_display_width(&self, width: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(width); + /// Removes all custom potion effects from this arrow. + pub fn clear_custom_effects(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref().call_method( &self.jni_object(), - "setDisplayWidth", + "clearCustomEffects", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the height of this display. - pub fn display_height(&self) -> Result> { - let sig = String::from("()F"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getDisplayHeight", - sig.as_str(), - vec![], - ); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for TippedArrow<'mc> { + fn into(self) -> crate::entity::Arrow<'mc> { + crate::entity::Arrow::from_raw(&self.jni_ref(), self.1) + .expect("Error converting TippedArrow into crate::entity::Arrow") + } +} +#[repr(C)] +pub struct Silverfish<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Silverfish<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Silverfish<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Silverfish from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Silverfish")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Silverfish object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Silverfish<'mc> { + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Silverfish<'mc> { + fn into(self) -> crate::entity::Monster<'mc> { + crate::entity::Monster::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Silverfish into crate::entity::Monster") + } +} +#[repr(C)] +pub struct Frog<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Frog<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Frog<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Frog from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Frog")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Frog object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Frog<'mc> { + /// Gets the tongue target of this frog. + pub fn tongue_target( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTongueTarget", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the height if this display. - pub fn set_display_height(&self, height: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(height); + /// Sets the tongue target of this frog. + pub fn set_tongue_target( + &self, + target: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(target.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setDisplayHeight", + "setTongueTarget", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the amount of ticks before client-side interpolation will commence. - pub fn interpolation_delay(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getInterpolationDelay", - sig.as_str(), - vec![], - ); + /// Get the variant of this frog. + pub fn variant(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Frog/Variant;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::entity::FrogVariant::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the amount of ticks before client-side interpolation will commence. - pub fn set_interpolation_delay(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Set the variant of this frog. + pub fn set_variant( + &self, + variant: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Frog/Variant;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(variant.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setInterpolationDelay", + "setVariant", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the billboard setting of this entity. - /// The billboard setting controls the automatic rotation of the entity to - /// face the player. - pub fn billboard( + /// Get the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn breed_cause( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Display/Billboard;"); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/UUID;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBillboard", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::DisplayBillboard::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the billboard setting of this entity. - /// The billboard setting controls the automatic rotation of the entity to - /// face the player. - pub fn set_billboard( + /// Set the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn set_breed_cause( &self, - billboard: impl Into>, + uuid: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Display/Billboard;)V"); + let sig = String::from("(Ljava/util/UUID;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(billboard.into().jni_object().clone()) + jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBillboard", + "setBreedCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the scoreboard team overridden glow color of this display. - pub fn glow_color_override( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Color;"); + /// Get whether or not this entity is in love mode and will produce + /// offspring with another entity in love mode. Will return true if + /// and only if {@link #getLoveModeTicks()} is greater than 0. + pub fn is_love_mode(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the amount of ticks remaining for this entity in love mode. + /// If the entity is not in love mode, 0 will be returned. + pub fn love_mode_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getGlowColorOverride", + "getLoveModeTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Color::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.i()?) } - /// Sets the scoreboard team overridden glow color of this display. - pub fn set_glow_color_override( + /// Set the amount of ticks for which this entity should be in love mode. + /// Setting the love mode ticks to 600 is the equivalent of a player + /// feeding the entity their breeding item of choice. + pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLoveModeTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Check if the provided ItemStack is the correct item used for breeding + /// this entity.. + pub fn is_breed_item( &self, - color: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Color;)V"); + material: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) + jni::objects::JObject::from_raw(material.into().jni_object().clone()) }); + args.push(val_1); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Lock the age of the animal, setting this will prevent the animal from + /// maturing or getting ready for mating. + pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(lock.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setGlowColorOverride", + "setAgeLock", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the brightness override of the entity. - pub fn brightness( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Display/Brightness;"); + /// Gets the current agelock. + pub fn age_lock(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBrightness", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::DisplayBrightness::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Sets the brightness override of the entity. - pub fn set_brightness( - &self, - brightness: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Display/Brightness;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(brightness.into().jni_object().clone()) - }); + /// Return the ability to breed of the animal. + pub fn can_breed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set breedability of the animal, if the animal is a baby and set to + /// breed it will instantly grow up. + pub fn set_breed(&self, breed: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(breed.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setBrightness", + "setBreed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -19934,95 +26547,19 @@ impl<'mc> ItemDisplay<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for ItemDisplay<'mc> { - fn into(self) -> crate::entity::Display<'mc> { - crate::entity::Display::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ItemDisplay into crate::entity::Display") - } -} -pub enum ItemDisplayItemDisplayTransform<'mc> {} -impl<'mc> std::fmt::Display for ItemDisplayItemDisplayTransform<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> ItemDisplayItemDisplayTransform<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/ItemDisplay/ItemDisplayTransform"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/ItemDisplay/ItemDisplayTransform;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } +impl<'mc> Into> for Frog<'mc> { + fn into(self) -> crate::entity::Animals<'mc> { + crate::entity::Animals::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Frog into crate::entity::Animals") } } - #[repr(C)] -pub struct ItemDisplayItemDisplayTransformStruct<'mc>( +pub struct FrogVariant<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ItemDisplayItemDisplayTransform<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for ItemDisplayItemDisplayTransform<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate ItemDisplayItemDisplayTransform from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/entity/ItemDisplay/ItemDisplayTransform")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ItemDisplayItemDisplayTransform object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for ItemDisplayItemDisplayTransformStruct<'mc> { +impl<'mc> JNIRaw<'mc> for FrogVariant<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -20030,43 +26567,92 @@ impl<'mc> JNIRaw<'mc> for ItemDisplayItemDisplayTransformStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ItemDisplayItemDisplayTransformStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for FrogVariant<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate ItemDisplayItemDisplayTransformStruct from null object." - ) - .into()); + return Err(eyre::eyre!("Tried to instantiate FrogVariant from null object.").into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/entity/ItemDisplay/ItemDisplayTransform")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Frog/Variant")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ItemDisplayItemDisplayTransformStruct object, got {}", - name - ) - .into()) + "Invalid argument passed. Expected a FrogVariant object, got {}", + name + ) + .into()) } else { Ok(Self(env.clone(), obj)) } } } -impl<'mc> ItemDisplayItemDisplayTransformStruct<'mc> { +impl<'mc> FrogVariant<'mc> { + #[deprecated] + pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/entity/ItemDisplay/ItemDisplayTransform;"); - let cls = jni.find_class("org/bukkit/entity/ItemDisplay/ItemDisplayTransform"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Frog/Variant;"); + let cls = jni.find_class("org/bukkit/entity/Frog/Variant"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::entity::ItemDisplayItemDisplayTransform::from_raw(&jni, obj) + crate::entity::FrogVariant::from_raw(&jni, obj) + } + #[deprecated] + + pub fn compare_to( + &self, + other: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(LT;)I"); + let val_1 = jni::objects::JValueGen::Object(other); + let res = self.jni_ref().call_method( + &self.jni_object(), + "compareTo", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + #[deprecated] + + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "name", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + #[deprecated] + + pub fn ordinal(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "ordinal", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Return the namespaced identifier for this object. + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -20074,13 +26660,25 @@ impl<'mc> ItemDisplayItemDisplayTransformStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for FrogVariant<'mc> { + fn into(self) -> crate::util::OldEnum<'mc> { + crate::util::OldEnum::from_raw(&self.jni_ref(), self.1) + .expect("Error converting FrogVariant into crate::util::OldEnum") + } +} +impl<'mc> Into> for FrogVariant<'mc> { + fn into(self) -> crate::Keyed<'mc> { + crate::Keyed::from_raw(&self.jni_ref(), self.1) + .expect("Error converting FrogVariant into crate::Keyed") + } +} #[repr(C)] -pub struct Ocelot<'mc>( +pub struct Trident<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Ocelot<'mc> { +impl<'mc> JNIRaw<'mc> for Trident<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -20088,18 +26686,18 @@ impl<'mc> JNIRaw<'mc> for Ocelot<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Ocelot<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Trident<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Ocelot from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Trident from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Ocelot")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Trident")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Ocelot object, got {}", + "Invalid argument passed. Expected a Trident object, got {}", name ) .into()) @@ -20109,321 +26707,322 @@ impl<'mc> JNIInstantiatable<'mc> for Ocelot<'mc> { } } -impl<'mc> Ocelot<'mc> { - /// Checks if this ocelot trusts players. - pub fn is_trusting(&self) -> Result> { - let sig = String::from("()Z"); +impl<'mc> Trident<'mc> { + #[deprecated] + /// Gets the knockback strength for an arrow, which is the {@link org.bukkit.enchantments.Enchantment#KNOCKBACK KnockBack} level of the bow that shot it. + pub fn knockback_strength(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getKnockbackStrength", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + #[deprecated] + /// Sets the knockback strength for an arrow. + pub fn set_knockback_strength( + &self, + knockback_strength: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(knockback_strength); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setKnockbackStrength", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the base amount of damage this arrow will do. + /// Defaults to 2.0 for a normal arrow with + /// 0.5 * (1 + power level) added for arrows fired from + /// enchanted bows. + pub fn damage(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getDamage", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Sets the base amount of damage this arrow will do. + pub fn set_damage(&self, damage: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(damage); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDamage", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the number of times this arrow can pierce through an entity. + pub fn pierce_level(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isTrusting", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPierceLevel", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets if this ocelot trusts players. - pub fn set_trusting(&self, trust: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(trust.into()); + /// Sets the number of times this arrow can pierce through an entity. + /// Must be between 0 and 127 times. + pub fn set_pierce_level(&self, pierce_level: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(pierce_level); let res = self.jni_ref().call_method( &self.jni_object(), - "setTrusting", + "setPierceLevel", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the current type of this cat. - pub fn cat_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Ocelot/Type;"); + /// Gets whether this arrow is critical. + /// + /// Critical arrows have increased damage and cause particle effects. + /// + /// Critical arrows generally occur when a player fully draws a bow before + /// firing. + pub fn is_critical(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getCatType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCritical", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::OcelotType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - #[deprecated] - /// Sets the current type of this cat. - pub fn set_cat_type( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Ocelot/Type;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Sets whether or not this arrow should be critical. + pub fn set_critical(&self, critical: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(critical.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCatType", + "setCritical", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn breed_cause( + /// Gets whether this arrow is in a block or not. + /// + /// Arrows in a block are motionless and may be picked up by players. + pub fn is_in_block(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInBlock", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the block to which this arrow is attached. + pub fn attached_block( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAttachedBlock", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( + Ok(Some(crate::block::Block::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Set the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn set_breed_cause( + /// Gets the current pickup status of this arrow. + pub fn pickup_status( &self, - uuid: impl Into>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/AbstractArrow/PickupStatus;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPickupStatus", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::AbstractArrowPickupStatus::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the current pickup status of this arrow. + pub fn set_pickup_status( + &self, + status: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/UUID;)V"); + let sig = String::from("(Lorg/bukkit/entity/AbstractArrow/PickupStatus;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) + jni::objects::JObject::from_raw(status.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreedCause", + "setPickupStatus", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get whether or not this entity is in love mode and will produce - /// offspring with another entity in love mode. Will return true if - /// and only if {@link #getLoveModeTicks()} is greater than 0. - pub fn is_love_mode(&self) -> Result> { + /// Gets if this arrow was shot from a crossbow. + pub fn is_shot_from_crossbow(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the amount of ticks remaining for this entity in love mode. - /// If the entity is not in love mode, 0 will be returned. - pub fn love_mode_ticks(&self) -> Result> { - let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLoveModeTicks", + "isShotFromCrossbow", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the amount of ticks for which this entity should be in love mode. - /// Setting the love mode ticks to 600 is the equivalent of a player - /// feeding the entity their breeding item of choice. - pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + #[deprecated] + /// Sets if this arrow was shot from a crossbow. + pub fn set_shot_from_crossbow( + &self, + shot_from_crossbow: bool, + ) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(shot_from_crossbow.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLoveModeTicks", + "setShotFromCrossbow", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check if the provided ItemStack is the correct item used for breeding - /// this entity.. - pub fn is_breed_item( + /// Gets the ItemStack the thrown projectile will display. + pub fn item(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/inventory/ItemStack;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getItem", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the display ItemStack for the thrown projectile. + pub fn set_item( &self, - material: impl Into>, - ) -> Result> { + item: impl Into>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; + sig += "Lorg/bukkit/inventory/ItemStack;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) + jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); args.push(val_1); - sig += ")Z"; + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Ocelot<'mc> { - fn into(self) -> crate::entity::Animals<'mc> { - crate::entity::Animals::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Ocelot into crate::entity::Animals") + .call_method(&self.jni_object(), "setItem", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -pub enum OcelotType<'mc> {} -impl<'mc> std::fmt::Display for OcelotType<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + /// Gets the ItemStack which fired this arrow. + pub fn weapon(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWeapon", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} - -impl<'mc> OcelotType<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/Ocelot/Type"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/Ocelot/Type;", + /// Sets the ItemStack which fired this arrow. + pub fn set_weapon( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setWeapon", + sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct OcelotTypeStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for OcelotType<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for OcelotType<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate OcelotType from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Ocelot/Type")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a OcelotType object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for OcelotTypeStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + self.jni_ref().translate_error(res)?; + Ok(()) } -} -impl<'mc> JNIInstantiatable<'mc> for OcelotTypeStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate OcelotTypeStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Ocelot/Type")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a OcelotTypeStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + /// Retrieve the shooter of this projectile. + pub fn shooter( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/projectiles/ProjectileSource;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getShooter", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some(crate::projectiles::ProjectileSource::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } -} - -impl<'mc> OcelotTypeStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Ocelot/Type;"); - let cls = jni.find_class("org/bukkit/entity/Ocelot/Type"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::OcelotType::from_raw(&jni, obj) + /// Set the shooter of this projectile. + pub fn set_shooter( + &self, + source: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/projectiles/ProjectileSource;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(source.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setShooter", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } #[deprecated] - /// Gets the ID of this cat type. - pub fn id(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getId", sig.as_str(), vec![]); + /// Determine if this projectile should bounce or not when it hits. + pub fn does_bounce(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "doesBounce", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } #[deprecated] - /// Gets a cat type by its ID. - pub fn get_type( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - id: i32, - ) -> Result>, Box> { - let sig = String::from("(I)Lorg/bukkit/entity/Ocelot/Type;"); - let val_1 = jni::objects::JValueGen::Int(id); - let cls = jni.find_class("org/bukkit/entity/Ocelot/Type"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getType", + /// Set whether or not this projectile should bounce or not when it hits something. + pub fn set_bounce(&self, does_bounce: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(does_bounce.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBounce", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::entity::OcelotType::from_raw(&jni, obj)?)) + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -20431,13 +27030,25 @@ impl<'mc> OcelotTypeStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for Trident<'mc> { + fn into(self) -> crate::entity::AbstractArrow<'mc> { + crate::entity::AbstractArrow::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Trident into crate::entity::AbstractArrow") + } +} +impl<'mc> Into> for Trident<'mc> { + fn into(self) -> crate::entity::ThrowableProjectile<'mc> { + crate::entity::ThrowableProjectile::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Trident into crate::entity::ThrowableProjectile") + } +} #[repr(C)] -pub struct ZombieVillager<'mc>( +pub struct Sniffer<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ZombieVillager<'mc> { +impl<'mc> JNIRaw<'mc> for Sniffer<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -20445,20 +27056,18 @@ impl<'mc> JNIRaw<'mc> for ZombieVillager<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ZombieVillager<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Sniffer<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate ZombieVillager from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate Sniffer from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ZombieVillager")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Sniffer")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ZombieVillager object, got {}", + "Invalid argument passed. Expected a Sniffer object, got {}", name ) .into()) @@ -20468,223 +27077,268 @@ impl<'mc> JNIInstantiatable<'mc> for ZombieVillager<'mc> { } } -impl<'mc> ZombieVillager<'mc> { - /// Sets the villager profession of this zombie. - pub fn set_villager_profession( +impl<'mc> Sniffer<'mc> { + /// Gets the locations explored by the sniffer. + /// + /// Note: the returned locations use sniffer's current world. + pub fn explored_locations( &self, - profession: impl Into>, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getExploredLocations", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::Location::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Remove a location of the explored locations. + /// + /// Note: the location must be in the sniffer's current world for this + /// method to have any effect. + pub fn remove_explored_location( + &self, + location: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Villager/Profession;)V"); + let sig = String::from("(Lorg/bukkit/Location;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(profession.into().jni_object().clone()) + jni::objects::JObject::from_raw(location.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVillagerProfession", + "removeExploredLocation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the villager profession of this zombie. - pub fn villager_profession( + /// Add a location to the explored locations. + /// + /// Note: the location must be in the sniffer's current world for this + /// method to have any effect. + pub fn add_explored_location( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Villager/Profession;"); + location: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Location;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getVillagerProfession", + "addExploredLocation", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::VillagerProfession::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the current type of this villager. - pub fn villager_type( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Villager/Type;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVillagerType", sig.as_str(), vec![]); + /// Get the current state of the sniffer. + pub fn state(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Sniffer/State;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getState", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::VillagerType::from_raw(&self.jni_ref(), unsafe { + crate::entity::SnifferState::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the new type of this villager. - pub fn set_villager_type( + /// Set a new state for the sniffer. + /// + /// This will also make the sniffer make the transition to the new state. + pub fn set_state( &self, - val_type: impl Into>, + state: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Villager/Type;)V"); + let sig = String::from("(Lorg/bukkit/entity/Sniffer/State;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(state.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVillagerType", + "setState", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get if this entity is in the process of converting to a Villager as a - /// result of being cured. - pub fn is_converting(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isConverting", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the amount of ticks until this entity will be converted to a - /// Villager as a result of being cured. - /// When this reaches 0, the entity will be converted. - pub fn conversion_time(&self) -> Result> { - let sig = String::from("()I"); + /// Try to get a possible location where the sniffer can dig. + pub fn find_possible_dig_location( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getConversionTime", + "findPossibleDigLocation", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Sets the amount of ticks until this entity will be converted to a - /// Villager as a result of being cured. - /// When this reaches 0, the entity will be converted. A value of less than 0 - /// will stop the current conversion process without converting the current - /// entity. - pub fn set_conversion_time(&self, time: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(time); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setConversionTime", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Gets whether the sniffer can dig in the current {@link Location} below + /// its head. + pub fn can_dig(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "canDig", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the player who initiated the conversion. - pub fn conversion_player( + /// Get the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn breed_cause( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/OfflinePlayer;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getConversionPlayer", - sig.as_str(), - vec![], - ); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::OfflinePlayer::from_raw( + Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets the player who initiated the conversion. - /// - /// This has no effect if this entity isn't converting currently. - pub fn set_conversion_player( + /// Set the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn set_breed_cause( &self, - conversion_player: impl Into>, + uuid: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/OfflinePlayer;)V"); + let sig = String::from("(Ljava/util/UUID;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(conversion_player.into().jni_object().clone()) + jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setConversionPlayer", + "setBreedCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets whether the zombie is a baby - pub fn is_baby(&self) -> Result> { + /// Get whether or not this entity is in love mode and will produce + /// offspring with another entity in love mode. Will return true if + /// and only if {@link #getLoveModeTicks()} is greater than 0. + pub fn is_love_mode(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isBaby", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Sets whether the zombie is a baby - pub fn set_baby(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Get the amount of ticks remaining for this entity in love mode. + /// If the entity is not in love mode, 0 will be returned. + pub fn love_mode_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "setBaby", + "getLoveModeTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the amount of ticks for which this entity should be in love mode. + /// Setting the love mode ticks to 600 is the equivalent of a player + /// feeding the entity their breeding item of choice. + pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLoveModeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets whether the zombie is a villager - pub fn is_villager(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isVillager", sig.as_str(), vec![]); + /// Check if the provided ItemStack is the correct item used for breeding + /// this entity.. + pub fn is_breed_item( + &self, + material: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - - pub fn set_villager(&self, flag: bool) -> Result<(), Box> { + /// Lock the age of the animal, setting this will prevent the animal from + /// maturing or getting ready for mating. + pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(lock.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setVillager", + "setAgeLock", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether this zombie can break doors - pub fn can_break_doors(&self) -> Result> { + /// Gets the current agelock. + pub fn age_lock(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "canBreakDoors", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether this zombie can break doors - /// This will be ignored if the entity is a Drowned. Will also stop the action if - /// the entity is currently breaking a door. - pub fn set_can_break_doors(&self, flag: bool) -> Result<(), Box> { + /// Return the ability to breed of the animal. + pub fn can_breed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set breedability of the animal, if the animal is a baby and set to + /// breed it will instantly grow up. + pub fn set_breed(&self, breed: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(breed.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCanBreakDoors", + "setBreed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -20697,19 +27351,184 @@ impl<'mc> ZombieVillager<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for ZombieVillager<'mc> { - fn into(self) -> crate::entity::Zombie<'mc> { - crate::entity::Zombie::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ZombieVillager into crate::entity::Zombie") +impl<'mc> Into> for Sniffer<'mc> { + fn into(self) -> crate::entity::Animals<'mc> { + crate::entity::Animals::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Sniffer into crate::entity::Animals") + } +} +pub enum SnifferState<'mc> { + Idling { inner: SnifferStateStruct<'mc> }, + FeelingHappy { inner: SnifferStateStruct<'mc> }, + Scenting { inner: SnifferStateStruct<'mc> }, + Sniffing { inner: SnifferStateStruct<'mc> }, + Searching { inner: SnifferStateStruct<'mc> }, + Digging { inner: SnifferStateStruct<'mc> }, + Rising { inner: SnifferStateStruct<'mc> }, +} +impl<'mc> std::fmt::Display for SnifferState<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + SnifferState::Idling { .. } => f.write_str("IDLING"), + SnifferState::FeelingHappy { .. } => f.write_str("FEELING_HAPPY"), + SnifferState::Scenting { .. } => f.write_str("SCENTING"), + SnifferState::Sniffing { .. } => f.write_str("SNIFFING"), + SnifferState::Searching { .. } => f.write_str("SEARCHING"), + SnifferState::Digging { .. } => f.write_str("DIGGING"), + SnifferState::Rising { .. } => f.write_str("RISING"), + } + } +} +impl<'mc> std::ops::Deref for SnifferState<'mc> { + type Target = SnifferStateStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + SnifferState::Idling { inner } => inner, + SnifferState::FeelingHappy { inner } => inner, + SnifferState::Scenting { inner } => inner, + SnifferState::Sniffing { inner } => inner, + SnifferState::Searching { inner } => inner, + SnifferState::Digging { inner } => inner, + SnifferState::Rising { inner } => inner, + } + } +} + +impl<'mc> SnifferState<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/Sniffer/State"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/Sniffer/State;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "IDLING" => Ok(SnifferState::Idling { + inner: SnifferStateStruct::from_raw(env, obj)?, + }), + "FEELING_HAPPY" => Ok(SnifferState::FeelingHappy { + inner: SnifferStateStruct::from_raw(env, obj)?, + }), + "SCENTING" => Ok(SnifferState::Scenting { + inner: SnifferStateStruct::from_raw(env, obj)?, + }), + "SNIFFING" => Ok(SnifferState::Sniffing { + inner: SnifferStateStruct::from_raw(env, obj)?, + }), + "SEARCHING" => Ok(SnifferState::Searching { + inner: SnifferStateStruct::from_raw(env, obj)?, + }), + "DIGGING" => Ok(SnifferState::Digging { + inner: SnifferStateStruct::from_raw(env, obj)?, + }), + "RISING" => Ok(SnifferState::Rising { + inner: SnifferStateStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } + #[repr(C)] -pub struct ComplexEntityPart<'mc>( +pub struct SnifferStateStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ComplexEntityPart<'mc> { +impl<'mc> JNIRaw<'mc> for SnifferState<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Idling { inner } => inner.0.clone(), + Self::FeelingHappy { inner } => inner.0.clone(), + Self::Scenting { inner } => inner.0.clone(), + Self::Sniffing { inner } => inner.0.clone(), + Self::Searching { inner } => inner.0.clone(), + Self::Digging { inner } => inner.0.clone(), + Self::Rising { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Idling { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::FeelingHappy { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Scenting { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Sniffing { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Searching { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Digging { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Rising { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for SnifferState<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate SnifferState from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Sniffer/State")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a SnifferState object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "IDLING" => Ok(SnifferState::Idling { + inner: SnifferStateStruct::from_raw(env, obj)?, + }), + "FEELING_HAPPY" => Ok(SnifferState::FeelingHappy { + inner: SnifferStateStruct::from_raw(env, obj)?, + }), + "SCENTING" => Ok(SnifferState::Scenting { + inner: SnifferStateStruct::from_raw(env, obj)?, + }), + "SNIFFING" => Ok(SnifferState::Sniffing { + inner: SnifferStateStruct::from_raw(env, obj)?, + }), + "SEARCHING" => Ok(SnifferState::Searching { + inner: SnifferStateStruct::from_raw(env, obj)?, + }), + "DIGGING" => Ok(SnifferState::Digging { + inner: SnifferStateStruct::from_raw(env, obj)?, + }), + "RISING" => Ok(SnifferState::Rising { + inner: SnifferStateStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for SnifferStateStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -20717,20 +27536,20 @@ impl<'mc> JNIRaw<'mc> for ComplexEntityPart<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ComplexEntityPart<'mc> { +impl<'mc> JNIInstantiatable<'mc> for SnifferStateStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate ComplexEntityPart from null object.").into(), + eyre::eyre!("Tried to instantiate SnifferStateStruct from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ComplexEntityPart")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Sniffer/State")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ComplexEntityPart object, got {}", + "Invalid argument passed. Expected a SnifferStateStruct object, got {}", name ) .into()) @@ -20740,1466 +27559,1172 @@ impl<'mc> JNIInstantiatable<'mc> for ComplexEntityPart<'mc> { } } -impl<'mc> ComplexEntityPart<'mc> { - /// Gets the parent {@link ComplexLivingEntity} of this part. - pub fn parent( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/ComplexLivingEntity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getParent", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::ComplexLivingEntity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Stores the entity's current position in the provided Location object. - /// - /// If the provided Location is null this method does nothing and returns - /// null. - pub fn get_location( - &self, - loc: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLocation", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Sets this entity's velocity in meters per tick - pub fn set_velocity( - &self, - velocity: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setVelocity", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets this entity's current velocity - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the entity's height - pub fn height(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the entity's width - pub fn width(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) +impl<'mc> SnifferStateStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Sniffer/State;"); + let cls = jni.find_class("org/bukkit/entity/Sniffer/State"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::SnifferState::from_raw(&jni, obj) } - /// Gets the entity's current bounding box. - /// - /// The returned bounding box reflects the entity's current location and - /// size. - pub fn bounding_box( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Returns true if the entity is supported by a block. This value is a - /// state updated by the server and is not recalculated unless the entity - /// moves. - pub fn is_on_ground(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} +#[repr(C)] +pub struct Painting<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Painting<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Returns true if the entity is in water. - pub fn is_in_water(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Gets the current world this entity resides in - pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); +} +impl<'mc> JNIInstantiatable<'mc> for Painting<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Painting from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Painting")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Painting object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Painting<'mc> { + /// Get the art on this painting + pub fn art(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Art;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getArt", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { + crate::Art::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the entity's rotation. - /// - /// Note that if the entity is affected by AI, it may override this rotation. - pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { - let sig = String::from("(FF)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); - let val_2 = jni::objects::JValueGen::Float(pitch); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRotation", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Teleports this entity to the given location. If this entity is riding a - /// vehicle, it will be dismounted prior to teleportation. - pub fn teleport( + /// Set the art on this painting + pub fn set_art( &self, - location: impl Into>, - cause: std::option::Option< - impl Into>, - >, + art: impl Into>, + force: std::option::Option, ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; + sig += "Lorg/bukkit/Art;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) + jni::objects::JObject::from_raw(art.into().jni_object().clone()) }); args.push(val_1); - if let Some(a) = cause { - sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); + if let Some(a) = force { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); args.push(val_2); } sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "teleport", sig.as_str(), args); + .call_method(&self.jni_object(), "setArt", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns a list of entities within a bounding box centered around this - /// entity - pub fn get_nearby_entities( + /// Sets the direction of the hanging entity, potentially overriding rules + /// of placement. Note that if the result is not valid the object would + /// normally drop as an item. + pub fn set_facing_direction( &self, - x: f64, - y: f64, - z: f64, - ) -> Result>, Box> { - let sig = String::from("(DDD)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Double(x); - let val_2 = jni::objects::JValueGen::Double(y); - let val_3 = jni::objects::JValueGen::Double(z); + face: impl Into>, + force: bool, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;Z)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Bool(force.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getNearbyEntities", + "setFacingDirection", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), ], ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(res.z()?) } - /// Returns a unique id for this entity - pub fn entity_id(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Returns the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn fire_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) +} +impl<'mc> Into> for Painting<'mc> { + fn into(self) -> crate::entity::Hanging<'mc> { + crate::entity::Hanging::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Painting into crate::entity::Hanging") } - /// Returns the entity's maximum fire ticks. - pub fn max_fire_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) +} +#[repr(C)] +pub struct Enemy<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Enemy<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Sets the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFireTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Sets if the entity has visual fire (it will always appear to be on fire). - pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire.into()); +} +impl<'mc> JNIInstantiatable<'mc> for Enemy<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Enemy from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Enemy")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Enemy object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Enemy<'mc> { + /// Gets the height of the living entity's eyes above its Location. + pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { + let sig = String::from("(Z)D"); + let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisualFire", + "getEyeHeight", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets if the entity has visual fire (it will always appear to be on fire). - pub fn is_visual_fire(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Returns the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Get a Location detailing the current eye position of the living entity. + pub fn eye_location(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the entity's maximum freeze ticks (amount of ticks before it will - /// be fully frozen) - pub fn max_freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMaxFreezeTicks", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFreezeTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets if the entity is fully frozen (it has been in powdered snow for max - /// freeze ticks). - pub fn is_frozen(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Mark the entity's removal. - pub fn remove(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns true if this entity has been marked for removal. - pub fn is_dead(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns false if the entity has died, been despawned for some other - /// reason, or has not been added to the world. - pub fn is_valid(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the {@link Server} that contains this Entity - pub fn server(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Server;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Server::from_raw(&self.jni_ref(), unsafe { + crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns true if the entity gets persisted. - /// - /// By default all entities are persistent. An entity will also not get - /// persisted, if it is riding an entity that is not persistent. - /// - /// The persistent flag on players controls whether or not to save their - /// playerdata file when they quit. If a player is directly or indirectly - /// riding a non-persistent entity, the vehicle at the root and all its - /// passengers won't get persisted. + /// Gets all blocks along the living entity's line of sight. /// - /// This should not be confused with - /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls - /// despawning of living entities. - pub fn is_persistent(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether or not the entity gets persisted. - pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(persistent.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPersistent", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. - pub fn passenger( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - #[deprecated] - /// Set the passenger of a vehicle. - pub fn set_passenger( + /// This list contains all blocks from the living entity's eye position to + /// target inclusive. This method considers all blocks as 1x1x1 in size. + pub fn get_line_of_sight( &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setPassenger", + "getLineOfSight", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets a list of passengers of this vehicle. - /// - /// The returned list will not be directly linked to the entity's current - /// passengers, and no guarantees are made as to its mutability. - pub fn passengers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); } Ok(new_vec) } - /// Add a passenger to the vehicle. - pub fn add_passenger( - &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addPassenger", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Remove a passenger from the vehicle. - pub fn remove_passenger( + /// Gets the block that the living entity has targeted. + /// + /// This method considers all blocks as 1x1x1 in size. To take exact block + /// collision shapes into account, see {@link #getTargetBlockExact(int, + /// FluidCollisionMode)}. + pub fn get_target_block( &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + transparent: impl Into>, + max_distance: i32, + ) -> Result, Box> { + let sig = String::from("(Ljava/util/Set;I)Lorg/bukkit/block/Block;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "removePassenger", + "getTargetBlock", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Check if a vehicle has passengers. - pub fn is_empty(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Eject any passenger. - pub fn eject(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the distance this entity has fallen - pub fn fall_distance(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Sets the fall distance for this entity - pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(distance); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFallDistance", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - /// Record the last {@link EntityDamageEvent} inflicted on this entity - pub fn set_last_damage_cause( + /// Gets the last two blocks along the living entity's line of sight. + /// + /// The target block will be the last block in the list. This method + /// considers all blocks as 1x1x1 in size. + pub fn get_last_two_target_blocks( &self, - event: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(event.into().jni_object().clone()) + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDamageCause", + "getLastTwoTargetBlocks", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. - /// This event may have been cancelled. - pub fn last_damage_cause( + /// Gets the block that the living entity has targeted. + /// + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn get_target_block_exact( &self, - ) -> Result>, Box> - { - let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + max_distance: i32, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/block/Block;"; let res = self.jni_ref().call_method( &self.jni_object(), - "getLastDamageCause", + "getTargetBlockExact", sig.as_str(), - vec![], + args, ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( + Ok(Some(crate::block::Block::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Returns a unique and persistent id for this entity - pub fn unique_id( + /// Performs a ray trace that provides information on the targeted block. + /// + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn ray_trace_blocks( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); + max_distance: f64, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/util/RayTraceResult;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::util::RayTraceResult::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. - pub fn ticks_lived(&self) -> Result> { + /// Returns the amount of air that the living entity has remaining, in + /// ticks. + pub fn remaining_air(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. May not be less than one - /// tick. - pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { + /// Sets the amount of air that the living entity has remaining, in ticks. + pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(value); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setTicksLived", + "setRemainingAir", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Performs the specified {@link EntityEffect} for this entity. - /// - /// This will be viewable to all players near the entity. - /// - /// If the effect is not applicable to this class of entity, it will not play. - pub fn play_effect( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Returns the maximum amount of air the living entity can have, in ticks. + pub fn maximum_air(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the maximum amount of air the living entity can have, in ticks. + pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "playEffect", + "setMaximumAir", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the type of the entity. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity makes while swimming. - pub fn swim_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Gets the item that the player is using (eating food, drawing back a bow, + /// blocking, etc.) + pub fn item_in_use( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Get the {@link Sound} this entity makes when splashing in water. For most - /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_splash_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Gets the number of ticks remaining for the current item's usage. + pub fn item_in_use_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimSplashSound", + "getItemInUseTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Get the {@link Sound} this entity makes when splashing in water at high - /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_high_speed_splash_sound( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Sets the number of ticks that remain for the current item's usage. + /// Applies to items that take time to use, like eating food, drawing a bow, + /// or throwing a trident. + pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimHighSpeedSplashSound", + "setItemInUseTicks", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns whether this entity is inside a vehicle. - pub fn is_inside_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); + /// Gets the time in ticks until the next arrow leaves the entity's body. + pub fn arrow_cooldown(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getArrowCooldown", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Leave the current vehicle. If the entity is currently in a vehicle (and - /// is removed from it), true will be returned, otherwise false will be - /// returned. - pub fn leave_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Sets the time in ticks until the next arrow leaves the entity's body. + pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setArrowCooldown", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the vehicle that this entity is inside. If there is no vehicle, - /// null will be returned. - pub fn vehicle( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + /// Gets the amount of arrows in an entity's body. + pub fn arrows_in_body(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - /// Sets whether or not to display the mob's custom name client side. The - /// name will be displayed above the mob similarly to a player. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Set the amount of arrows in the entity's body. + pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(count); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomNameVisible", + "setArrowsInBody", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not the mob's custom name is displayed client side. + /// Returns the living entity's current maximum no damage ticks. /// - /// This value has no effect on players, they will always display their - /// name. - pub fn is_custom_name_visible(&self) -> Result> { - let sig = String::from("()Z"); + /// This is the maximum duration in which the living entity will not take + /// damage. + pub fn maximum_no_damage_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "isCustomNameVisible", + "getMaximumNoDamageTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(visible.into()); + /// Sets the living entity's current maximum no damage ticks. + pub fn set_maximum_no_damage_ticks( + &self, + ticks: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisibleByDefault", + "setMaximumNoDamageTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn is_visible_by_default(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isVisibleByDefault", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get all players that are currently tracking this entity. + /// Returns the living entity's last damage taken in the current no damage + /// ticks time. /// - /// 'Tracking' means that this entity has been sent to the player and that - /// they are receiving updates on its state. Note that the client's {@code - /// 'Entity Distance'} setting does not affect the range at which entities - /// are tracked. - pub fn tracked_by( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Only damage higher than this amount will further damage the living + /// entity. + pub fn last_damage(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.d()?) } - /// Sets whether the entity has a team colored (default: white) glow. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Sets the damage dealt within the current no damage ticks time period. + pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(damage); let res = self.jni_ref().call_method( &self.jni_object(), - "setGlowing", + "setLastDamage", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is glowing or not. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn is_glowing(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); + /// Returns the living entity's current no damage ticks. + pub fn no_damage_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNoDamageTicks", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets whether the entity is invulnerable or not. - /// - /// When an entity is invulnerable it can only be damaged by players in - /// creative mode. - pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Sets the living entity's current no damage ticks. + pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvulnerable", + "setNoDamageTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invulnerable or not. - pub fn is_invulnerable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets whether the entity is silent or not. - pub fn is_silent(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + /// Get the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn no_action_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNoActionTicks", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets whether the entity is silent or not. + /// Set the ticks that this entity has performed no action. /// - /// When an entity is silent it will not produce any sound. - pub fn set_silent(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setSilent", + "setNoActionTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether gravity applies to this entity. - pub fn has_gravity(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the player identified as the killer of the living entity. + /// + /// May be null. + pub fn killer(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Player::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + #[deprecated] + /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. + pub fn add_potion_effect( + &self, + effect: impl Into>, + force: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/potion/PotionEffect;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = force { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether gravity applies to this entity. - pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gravity.into()); + /// Returns whether the living entity already has an existing effect of + /// the given {@link PotionEffectType} applied to it. + pub fn has_potion_effect( + &self, + val_type: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasPotionEffect", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the active {@link PotionEffect} of the specified type. + /// + /// If the effect is not present on the entity then null will be returned. + pub fn get_potion_effect( + &self, + val_type: impl Into>, + ) -> Result>, Box> { + let sig = + String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setGravity", + "getPotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the period of time (in ticks) before this entity can use a portal. - pub fn portal_cooldown(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPortalCooldown", - sig.as_str(), - vec![], - ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::potion::PotionEffect::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the period of time (in ticks) before this entity can use a portal. - pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(cooldown); + /// Removes any effects present of the given {@link PotionEffectType}. + pub fn remove_potion_effect( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPortalCooldown", + "removePotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a set of tags for this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn scoreboard_tags( + /// Returns all currently active {@link PotionEffect}s on the living + /// entity. + pub fn active_potion_effects( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getScoreboardTags", + "getActivePotionEffects", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Add a tag to this entity. + /// Checks whether the living entity has block line of sight to another. /// - /// Entities can have no more than 1024 tags. - pub fn add_scoreboard_tag( + /// This uses the same algorithm that hostile mobs use to find the closest + /// player. + pub fn has_line_of_sight( &self, - tag: impl Into, + other: impl Into>, ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(other.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "addScoreboardTag", + "hasLineOfSight", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes a given tag from this entity. - pub fn remove_scoreboard_tag( - &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); + /// Returns if the living entity despawns when away from players or not. + /// + /// By default, animals are not removed while other mobs are. + pub fn remove_when_far_away(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "removeScoreboardTag", + "getRemoveWhenFarAway", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns the reaction of the entity when moved by a piston. - pub fn piston_move_reaction( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + /// Sets whether or not the living entity despawns when away from players + /// or not. + pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(remove.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getPistonMoveReaction", + "setRemoveWhenFarAway", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the closest cardinal {@link BlockFace} direction an entity is - /// currently facing. - /// - /// This will not return any non-cardinal directions such as - /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. - /// - /// {@link Hanging} entities will override this call and thus their behavior - /// may be different. - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + /// Gets the inventory with the equipment worn by the living entity. + pub fn equipment( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::EntityEquipment::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets the entity's current pose. - /// Note that the pose is only updated at the end of a tick, so may be - /// inconsistent with other methods. eg {@link Player#isSneaking()} being - /// true does not imply the current pose will be {@link Pose#SNEAKING} - pub fn pose(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Pose;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Sets whether or not the living entity can pick up items. + pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(pickup.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCanPickupItems", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the category of spawn to which this entity belongs. - pub fn spawn_category( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); + /// Gets if the living entity can pick up items. + pub fn can_pickup_items(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getSpawnCategory", + "getCanPickupItems", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Checks if this entity has been spawned in a world. - /// - /// Entities not spawned in a world will not tick, be sent to players, or be - /// saved to the server files. - pub fn is_in_world(&self) -> Result> { + /// Returns whether the entity is currently leashed. + pub fn is_leashed(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get this entity as an NBT string. - /// - /// This string should not be relied upon as a serializable value. - pub fn as_string(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// Crates an {@link EntitySnapshot} representing the current state of this entity. - pub fn create_snapshot( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + /// Gets the entity that is currently leading this entity. + pub fn leash_holder(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::EntitySnapshot::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Creates a copy of this entity and all its data. Spawns the copy at the given location. - /// - /// Note: Players cannot be copied. - pub fn copy( - &self, - to: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = to { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")Lorg/bukkit/entity/Entity;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); + .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for ComplexEntityPart<'mc> { - fn into(self) -> crate::entity::Entity<'mc> { - crate::entity::Entity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ComplexEntityPart into crate::entity::Entity") - } -} -#[repr(C)] -pub struct Snowball<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Snowball<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Snowball<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Snowball from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Snowball")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Snowball object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Snowball<'mc> { - /// Gets the ItemStack the thrown projectile will display. - pub fn item(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/inventory/ItemStack;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the display ItemStack for the thrown projectile. - pub fn set_item( + /// Sets the leash on this entity to be held by the supplied entity. + /// + /// This method has no effect on EnderDragons, Withers, Players, or Bats. + /// Non-living entities excluding leashes will not persist as leash + /// holders. + pub fn set_leash_holder( &self, - item: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; + holder: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(holder.into().jni_object().clone()) }); - args.push(val_1); - sig += ")V"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLeashHolder", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks to see if an entity is gliding, such as using an Elytra. + pub fn is_gliding(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "setItem", sig.as_str(), args); + .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Makes entity start or stop gliding. This will work even if an Elytra + /// is not equipped, but will be reverted by the server immediately after + /// unless an event-cancelling mechanism is put in place. + pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gliding.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setGliding", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the shooter of this projectile. - pub fn shooter( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/projectiles/ProjectileSource;"); + /// Checks to see if an entity is swimming. + pub fn is_swimming(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getShooter", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::projectiles::ProjectileSource::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Set the shooter of this projectile. - pub fn set_shooter( - &self, - source: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/projectiles/ProjectileSource;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(source.into().jni_object().clone()) - }); + /// Makes entity start or stop swimming. + /// This may have unexpected results if the entity is not in water. + pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(swimming.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setShooter", + "setSwimming", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Determine if this projectile should bounce or not when it hits. - pub fn does_bounce(&self) -> Result> { + /// Checks to see if an entity is currently riptiding. + pub fn is_riptiding(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "doesBounce", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Set whether or not this projectile should bounce or not when it hits something. - pub fn set_bounce(&self, does_bounce: bool) -> Result<(), Box> { + /// Makes entity start or stop riptiding. + /// + /// Note: This does not damage attackable entities. + pub fn set_riptiding(&self, riptiding: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(does_bounce.into()); + let val_1 = jni::objects::JValueGen::Bool(riptiding.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setBounce", + "setRiptiding", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Snowball<'mc> { - fn into(self) -> crate::entity::ThrowableProjectile<'mc> { - crate::entity::ThrowableProjectile::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Snowball into crate::entity::ThrowableProjectile") - } -} -#[repr(C)] -pub struct AbstractVillager<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for AbstractVillager<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for AbstractVillager<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate AbstractVillager from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/AbstractVillager")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a AbstractVillager object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Returns whether this entity is slumbering. + pub fn is_sleeping(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} - -impl<'mc> AbstractVillager<'mc> { - /// Gets this villager's inventory. - /// - /// Note that this inventory is not the Merchant inventory, rather, it is the - /// items that a villager might have collected (from harvesting crops, etc.) - /// {@inheritDoc} - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + /// Gets if the entity is climbing. + pub fn is_climbing(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) + } + /// Sets whether an entity will have AI. + /// The entity will be completely unable to move if it has no AI. + pub fn set_ai(&self, ai: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(ai.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAI", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks whether an entity has AI. + /// The entity will be completely unable to move if it has no AI. + pub fn has_ai(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Lock the age of the animal, setting this will prevent the animal from - /// maturing or getting ready for mating. - pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(lock.into()); + /// Makes this entity attack the given entity with a melee attack. + /// Attack damage is calculated by the server from the attributes and + /// equipment of this mob, and knockback is applied to {@code target} as + /// appropriate. + pub fn attack( + &self, + target: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(target.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setAgeLock", + "attack", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the current agelock. - pub fn age_lock(&self) -> Result> { - let sig = String::from("()Z"); + /// Makes this entity swing their main hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their main hand. + pub fn swing_main_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Return the ability to breed of the animal. - pub fn can_breed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Makes this entity swing their off hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their off hand. + pub fn swing_off_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Set breedability of the animal, if the animal is a baby and set to - /// breed it will instantly grow up. - pub fn set_breed(&self, breed: bool) -> Result<(), Box> { + /// Makes this entity flash red as if they were damaged. + pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); + let res = self.jni_ref().call_method( + &self.jni_object(), + "playHurtAnimation", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Set if this entity will be subject to collisions with other entities. + /// + /// Exemptions to this rule can be managed with + /// {@link #getCollidableExemptions()} + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not working for player collisions. This + /// method should therefore only be used to set the collision status of + /// non-player entities. + /// + /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in + /// combination with a {@link Scoreboard} and a {@link Team}. + pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(breed.into()); + let val_1 = jni::objects::JValueGen::Bool(collidable.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreed", + "setCollidable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get a list of trades currently available from this merchant. - pub fn recipes( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + /// Gets if this entity is subject to collisions with other entities. + /// + /// Some entities might be exempted from the collidable rule of this entity. + /// Use {@link #getCollidableExemptions()} to get these. + /// + /// Please note that this method returns only the custom collidable state, + /// not whether the entity is non-collidable for other reasons such as being + /// dead. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not being accurate for player collisions. + /// This method should therefore only be used to check the collision status + /// of non-player entities. + /// + /// To check the collision behavior for a player, use + /// {@link Team.Option#COLLISION_RULE} in combination with a + /// {@link Scoreboard} and a {@link Team}. + pub fn is_collidable(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getRecipes", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::inventory::MerchantRecipe::from_raw( - &self.jni_ref(), - obj, - )?); - } - Ok(new_vec) + Ok(res.z()?) } - /// Set the list of trades currently available from this merchant. + /// Gets a mutable set of UUIDs of the entities which are exempt from the + /// entity's collidable rule and which's collision with this entity will + /// behave the opposite of it. /// - /// This will not change the selected trades of players currently trading - /// with this merchant. - pub fn set_recipes( + /// This set can be modified to add or remove exemptions. + /// + /// For example if collidable is true and an entity is in the exemptions set + /// then it will not collide with it. Similarly if collidable is false and an + /// entity is in this set then it will still collide with it. + /// + /// Note these exemptions are not (currently) persistent. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in those exemptions not being accurate for player + /// collisions. This method should therefore only be used to exempt + /// non-player entities. + /// + /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} + /// in combination with a {@link Scoreboard} and a {@link Team}. + pub fn collidable_exemptions( &self, - recipes: Vec>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/List;)V"); - let raw_val_1 = self - .jni_ref() - .new_object("java/util/ArrayList", "()V", vec![])?; - for v in recipes { - let map_val_0 = jni::objects::JValueGen::Object(v); - self.jni_ref().call_method( - &raw_val_1, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_1 = jni::objects::JValueGen::Object(raw_val_1); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setRecipes", + "getCollidableExemptions", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get the recipe at a certain index of this merchant's trade list. - pub fn get_recipe( + /// Returns the value of the memory specified. + /// + /// Note that the value is null when the specific entity does not have that + /// value by default. + pub fn get_memory( &self, - i: i32, - ) -> Result, Box> { - let sig = String::from("(I)Lorg/bukkit/inventory/MerchantRecipe;"); - let val_1 = jni::objects::JValueGen::Int(i); + memory_key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getRecipe", + "getMemory", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::MerchantRecipe::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) } - /// Set the recipe at a certain index of this merchant's trade list. - pub fn set_recipe( + /// Sets the value of the memory specified. + /// + /// Note that the value will not be persisted when the specific entity does + /// not have that value by default. + pub fn set_memory( &self, - i: i32, - recipe: impl Into>, + memory_key: impl Into>, + memory_value: jni::objects::JObject<'mc>, ) -> Result<(), Box> { - let sig = String::from("(ILorg/bukkit/inventory/MerchantRecipe;)V"); - let val_1 = jni::objects::JValueGen::Int(i); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Object(memory_value); let res = self.jni_ref().call_method( &self.jni_object(), - "setRecipe", + "setMemory", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), @@ -22209,376 +28734,339 @@ impl<'mc> AbstractVillager<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the number of trades this merchant currently has available. - pub fn recipe_count(&self) -> Result> { - let sig = String::from("()I"); + /// Get the {@link Sound} this entity will make when damaged. + pub fn hurt_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getRecipeCount", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets whether this merchant is currently trading. - pub fn is_trading(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isTrading", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Gets the player this merchant is trading with, or null if it is not - /// currently trading. - pub fn trader( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTrader", sig.as_str(), vec![]); + /// Get the {@link Sound} this entity will make on death. + pub fn death_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::HumanEntity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for AbstractVillager<'mc> { - fn into(self) -> crate::entity::Breedable<'mc> { - crate::entity::Breedable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting AbstractVillager into crate::entity::Breedable") - } -} -impl<'mc> Into> for AbstractVillager<'mc> { - fn into(self) -> crate::entity::NPC<'mc> { - crate::entity::NPC::from_raw(&self.jni_ref(), self.1) - .expect("Error converting AbstractVillager into crate::entity::NPC") - } -} -impl<'mc> Into> for AbstractVillager<'mc> { - fn into(self) -> crate::inventory::InventoryHolder<'mc> { - crate::inventory::InventoryHolder::from_raw(&self.jni_ref(), self.1) - .expect("Error converting AbstractVillager into crate::inventory::InventoryHolder") - } -} -impl<'mc> Into> for AbstractVillager<'mc> { - fn into(self) -> crate::inventory::Merchant<'mc> { - crate::inventory::Merchant::from_raw(&self.jni_ref(), self.1) - .expect("Error converting AbstractVillager into crate::inventory::Merchant") + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } -} -#[repr(C)] -pub struct AbstractHorse<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for AbstractHorse<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Get the {@link Sound} this entity will make when falling from the given + /// height (in blocks). The sound will often differ between either a small + /// or a big fall damage sound if the height exceeds 4 blocks. + pub fn get_fall_damage_sound( + &self, + fall_height: i32, + ) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Int(fall_height); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getFallDamageSound", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Get the {@link Sound} this entity will make when falling from a small + /// height. + pub fn fall_damage_sound_small(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getFallDamageSoundSmall", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> JNIInstantiatable<'mc> for AbstractHorse<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate AbstractHorse from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/AbstractHorse")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a AbstractHorse object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Get the {@link Sound} this entity will make when falling from a large + /// height. + pub fn fall_damage_sound_big(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getFallDamageSoundBig", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} - -impl<'mc> AbstractHorse<'mc> { - #[deprecated] - /// Gets the horse's variant.A horse's variant defines its physical appearance and capabilities. Whether a horse is a regular horse, donkey, mule, or other kind of horse is determined using the variant. - pub fn variant(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Horse/Variant;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); + /// Get the {@link Sound} this entity will make when drinking the given + /// {@link ItemStack}. + pub fn get_drinking_sound( + &self, + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDrinkingSound", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - crate::entity::HorseVariant::from_raw(&self.jni_ref(), unsafe { + crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - #[deprecated] - - pub fn set_variant( + /// Get the {@link Sound} this entity will make when eating the given + /// {@link ItemStack}. + pub fn get_eating_sound( &self, - variant: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Horse/Variant;)V"); + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(variant.into().jni_object().clone()) + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVariant", + "getEatingSound", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the domestication level of this horse. - /// - /// A higher domestication level indicates that the horse is closer to - /// becoming tame. As the domestication level gets closer to the max - /// domestication level, the chance of the horse becoming tame increases. - pub fn domestication(&self) -> Result> { - let sig = String::from("()I"); + /// Returns true if this entity can breathe underwater and will not take + /// suffocation damage when its air supply reaches zero. + pub fn can_breathe_underwater(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getDomestication", + "canBreatheUnderwater", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the domestication level of this horse. - /// - /// Setting the domestication level to a high value will increase the - /// horse's chances of becoming tame. - /// - /// Domestication level must be greater than zero and no greater than - /// the max domestication level of the horse, determined with - /// {@link #getMaxDomestication()} - pub fn set_domestication(&self, level: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(level); + #[deprecated] + /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. + pub fn category( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets whether the entity is invisible or not. + pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(invisible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setDomestication", + "setInvisible", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the maximum domestication level of this horse. - /// - /// The higher this level is, the longer it will likely take - /// for the horse to be tamed. - pub fn max_domestication(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMaxDomestication", - sig.as_str(), - vec![], - ); + /// Gets whether the entity is invisible or not. + pub fn is_invisible(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the maximum domestication level of this horse. - /// - /// Setting a higher max domestication will increase the amount of - /// domesticating (feeding, riding, etc.) necessary in order to tame it, - /// while setting a lower max value will have the opposite effect. - /// - /// Maximum domestication must be greater than zero. - pub fn set_max_domestication(&self, level: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(level); + /// Gets the specified attribute instance from the object. This instance will + /// be backed directly to the object and any changes will be visible at once. + pub fn get_attribute( + &self, + attribute: impl Into>, + ) -> Result>, Box> { + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxDomestication", + "getAttribute", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::attribute::AttributeInstance::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Deals the given amount of damage to this entity from a specified + /// {@link DamageSource}. + pub fn damage( + &self, + amount: f64, + damage_source: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(amount); + args.push(val_1); + if let Some(a) = damage_source { + sig += "Lorg/bukkit/damage/DamageSource;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "damage", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the jump strength of this horse. - /// - /// Jump strength defines how high the horse can jump. A higher jump strength - /// increases how high a jump will go. - pub fn jump_strength(&self) -> Result> { + /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. + pub fn health(&self) -> Result> { let sig = String::from("()D"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getJumpStrength", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.d()?) } - /// Sets the jump strength of this horse. - /// - /// A higher jump strength increases how high a jump will go. - /// Setting a jump strength to 0 will result in no jump. - /// You cannot set a jump strength to a value below 0 or - /// above 2. - pub fn set_jump_strength(&self, strength: f64) -> Result<(), Box> { + /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is + /// dead. + pub fn set_health(&self, health: f64) -> Result<(), Box> { let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(strength); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "setJumpStrength", + "setHealth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the horse is currently grazing hay. - pub fn is_eating_haystack(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the entity's absorption amount. + pub fn absorption_amount(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref().call_method( &self.jni_object(), - "isEatingHaystack", + "getAbsorptionAmount", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Sets whether the horse is grazing hay. - pub fn set_eating_haystack( - &self, - eating_haystack: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(eating_haystack.into()); + /// Sets the entity's absorption amount. + /// + /// Note: The amount is capped to the value of + /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on + /// that attribute is currently unspecified and subject to change. + pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "setEatingHaystack", + "setAbsorptionAmount", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/AbstractHorseInventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::AbstractHorseInventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the vehicle's velocity. - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); + #[deprecated] + /// Gets the maximum health this entity has. + pub fn max_health(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.d()?) } - /// Sets the vehicle's velocity in meters per tick. - pub fn set_velocity( - &self, - vel: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(vel.into().jni_object().clone()) - }); + #[deprecated] + /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. + pub fn set_max_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "setVelocity", + "setMaxHealth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check if this is tamed - /// - /// If something is tamed then a player can not tame it through normal - /// methods, even if it does not belong to anyone in particular. - pub fn is_tamed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isTamed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets if this has been tamed. Not necessary if the method setOwner has - /// been used, as it tames automatically. - /// - /// If something is tamed then a player can not tame it through normal - /// methods, even if it does not belong to anyone in particular. - pub fn set_tamed(&self, tame: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(tame.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTamed", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + #[deprecated] + /// Resets the max health to the original amount. + pub fn reset_max_health(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the current owning AnimalTamer - pub fn owner( + /// Launches a {@link Projectile} from the ProjectileSource with an + /// initial velocity. + pub fn launch_projectile( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/AnimalTamer;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + projectile: jni::objects::JClass<'mc>, + velocity: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(projectile.into()); + args.push(val_1); + if let Some(a) = velocity { + sig += "Lorg/bukkit/util/Vector;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); } - Ok(Some(crate::entity::AnimalTamer::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Set this to be owned by given AnimalTamer. - /// - /// If the owner is not null, this will be tamed and will have any current - /// path it is following removed. If the owner is set to null, this will be - /// untamed, and the current owner removed. - pub fn set_owner( - &self, - tamer: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/AnimalTamer;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tamer.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setOwner", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + sig += ")LT;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -22586,31 +29074,19 @@ impl<'mc> AbstractHorse<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for AbstractHorse<'mc> { - fn into(self) -> crate::entity::Vehicle<'mc> { - crate::entity::Vehicle::from_raw(&self.jni_ref(), self.1) - .expect("Error converting AbstractHorse into crate::entity::Vehicle") - } -} -impl<'mc> Into> for AbstractHorse<'mc> { - fn into(self) -> crate::inventory::InventoryHolder<'mc> { - crate::inventory::InventoryHolder::from_raw(&self.jni_ref(), self.1) - .expect("Error converting AbstractHorse into crate::inventory::InventoryHolder") - } -} -impl<'mc> Into> for AbstractHorse<'mc> { - fn into(self) -> crate::entity::Tameable<'mc> { - crate::entity::Tameable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting AbstractHorse into crate::entity::Tameable") +impl<'mc> Into> for Enemy<'mc> { + fn into(self) -> crate::entity::LivingEntity<'mc> { + crate::entity::LivingEntity::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Enemy into crate::entity::LivingEntity") } } #[repr(C)] -pub struct ComplexLivingEntity<'mc>( +pub struct Horse<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ComplexLivingEntity<'mc> { +impl<'mc> JNIRaw<'mc> for Horse<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -22618,20 +29094,18 @@ impl<'mc> JNIRaw<'mc> for ComplexLivingEntity<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ComplexLivingEntity<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Horse<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate ComplexLivingEntity from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate Horse from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ComplexLivingEntity")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Horse")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ComplexLivingEntity object, got {}", + "Invalid argument passed. Expected a Horse object, got {}", name ) .into()) @@ -22641,2113 +29115,2370 @@ impl<'mc> JNIInstantiatable<'mc> for ComplexLivingEntity<'mc> { } } -impl<'mc> ComplexLivingEntity<'mc> { - /// Gets a list of parts that belong to this complex entity - pub fn parts(&self) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); +impl<'mc> Horse<'mc> { + /// Gets the horse's color. + /// + /// Colors only apply to horses, not to donkeys, mules, skeleton horses + /// or undead horses. + pub fn color(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Horse/Color;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getParts", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the height of the living entity's eyes above its Location. - pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { - let sig = String::from("(Z)D"); - let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getEyeHeight", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Get a Location detailing the current eye position of the living entity. - pub fn eye_location(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { + crate::entity::HorseColor::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets all blocks along the living entity's line of sight. + /// Sets the horse's color. /// - /// This list contains all blocks from the living entity's eye position to - /// target inclusive. This method considers all blocks as 1x1x1 in size. - pub fn get_line_of_sight( + /// Attempting to set a color for any donkey, mule, skeleton horse or + /// undead horse will not result in a change. + pub fn set_color( &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { - let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + color: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Horse/Color;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + jni::objects::JObject::from_raw(color.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "getLineOfSight", + "setColor", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the block that the living entity has targeted. + /// Gets the horse's style. + /// Styles determine what kind of markings or patterns a horse has. /// - /// This method considers all blocks as 1x1x1 in size. To take exact block - /// collision shapes into account, see {@link #getTargetBlockExact(int, - /// FluidCollisionMode)}. - pub fn get_target_block( - &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result, Box> { - let sig = String::from("(Ljava/util/Set;I)Lorg/bukkit/block/Block;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(max_distance); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTargetBlock", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + /// Styles only apply to horses, not to donkeys, mules, skeleton horses + /// or undead horses. + pub fn style(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Horse/Style;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getStyle", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { + crate::entity::HorseStyle::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the last two blocks along the living entity's line of sight. + /// Sets the style of this horse. + /// Styles determine what kind of markings or patterns a horse has. /// - /// The target block will be the last block in the list. This method - /// considers all blocks as 1x1x1 in size. - pub fn get_last_two_target_blocks( + /// Attempting to set a style for any donkey, mule, skeleton horse or + /// undead horse will not result in a change. + pub fn set_style( &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { - let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + style: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Horse/Style;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + jni::objects::JObject::from_raw(style.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(max_distance); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLastTwoTargetBlocks", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Gets the block that the living entity has targeted. - /// - /// This takes the blocks' precise collision shapes into account. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn get_target_block_exact( - &self, - max_distance: i32, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(max_distance); - args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/block/Block;"; let res = self.jni_ref().call_method( &self.jni_object(), - "getTargetBlockExact", + "setStyle", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::block::Block::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Performs a ray trace that provides information on the targeted block. - /// - /// This takes the blocks' precise collision shapes into account. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn ray_trace_blocks( - &self, - max_distance: f64, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(max_distance); - args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/util/RayTraceResult;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::util::RayTraceResult::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns the amount of air that the living entity has remaining, in - /// ticks. - pub fn remaining_air(&self) -> Result> { - let sig = String::from("()I"); + #[deprecated] + + pub fn is_carrying_chest(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCarryingChest", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the amount of air that the living entity has remaining, in ticks. - pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + #[deprecated] + + pub fn set_carrying_chest(&self, chest: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(chest.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setRemainingAir", + "setCarryingChest", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the maximum amount of air the living entity can have, in ticks. - pub fn maximum_air(&self) -> Result> { - let sig = String::from("()I"); + #[deprecated] + /// Gets the horse's variant.A horse's variant defines its physical appearance and capabilities. Whether a horse is a regular horse, donkey, mule, or other kind of horse is determined using the variant. + pub fn variant(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Horse/Variant;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::entity::HorseVariant::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the maximum amount of air the living entity can have, in ticks. - pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + #[deprecated] + + pub fn set_variant( + &self, + variant: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Horse/Variant;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(variant.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaximumAir", + "setVariant", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the item that the player is using (eating food, drawing back a bow, - /// blocking, etc.) - pub fn item_in_use( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Gets the number of ticks remaining for the current item's usage. - pub fn item_in_use_ticks(&self) -> Result> { + /// Gets the domestication level of this horse. + /// + /// A higher domestication level indicates that the horse is closer to + /// becoming tame. As the domestication level gets closer to the max + /// domestication level, the chance of the horse becoming tame increases. + pub fn domestication(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getItemInUseTicks", + "getDomestication", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the number of ticks that remain for the current item's usage. - /// Applies to items that take time to use, like eating food, drawing a bow, - /// or throwing a trident. - pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Sets the domestication level of this horse. + /// + /// Setting the domestication level to a high value will increase the + /// horse's chances of becoming tame. + /// + /// Domestication level must be greater than zero and no greater than + /// the max domestication level of the horse, determined with + /// {@link #getMaxDomestication()} + pub fn set_domestication(&self, level: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + let val_1 = jni::objects::JValueGen::Int(level); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemInUseTicks", + "setDomestication", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the time in ticks until the next arrow leaves the entity's body. - pub fn arrow_cooldown(&self) -> Result> { + /// Gets the maximum domestication level of this horse. + /// + /// The higher this level is, the longer it will likely take + /// for the horse to be tamed. + pub fn max_domestication(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getArrowCooldown", + "getMaxDomestication", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the time in ticks until the next arrow leaves the entity's body. - pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { + /// Sets the maximum domestication level of this horse. + /// + /// Setting a higher max domestication will increase the amount of + /// domesticating (feeding, riding, etc.) necessary in order to tame it, + /// while setting a lower max value will have the opposite effect. + /// + /// Maximum domestication must be greater than zero. + pub fn set_max_domestication(&self, level: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + let val_1 = jni::objects::JValueGen::Int(level); let res = self.jni_ref().call_method( &self.jni_object(), - "setArrowCooldown", + "setMaxDomestication", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the amount of arrows in an entity's body. - pub fn arrows_in_body(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the jump strength of this horse. + /// + /// Jump strength defines how high the horse can jump. A higher jump strength + /// increases how high a jump will go. + pub fn jump_strength(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getJumpStrength", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.d()?) } - /// Set the amount of arrows in the entity's body. - pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(count); + /// Sets the jump strength of this horse. + /// + /// A higher jump strength increases how high a jump will go. + /// Setting a jump strength to 0 will result in no jump. + /// You cannot set a jump strength to a value below 0 or + /// above 2. + pub fn set_jump_strength(&self, strength: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(strength); let res = self.jni_ref().call_method( &self.jni_object(), - "setArrowsInBody", + "setJumpStrength", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's current maximum no damage ticks. - /// - /// This is the maximum duration in which the living entity will not take - /// damage. - pub fn maximum_no_damage_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Gets whether the horse is currently grazing hay. + pub fn is_eating_haystack(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getMaximumNoDamageTicks", + "isEatingHaystack", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the living entity's current maximum no damage ticks. - pub fn set_maximum_no_damage_ticks( + /// Sets whether the horse is grazing hay. + pub fn set_eating_haystack( &self, - ticks: i32, + eating_haystack: bool, ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(eating_haystack.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaximumNoDamageTicks", + "setEatingHaystack", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's last damage taken in the current no damage - /// ticks time. - /// - /// Only damage higher than this amount will further damage the living - /// entity. - pub fn last_damage(&self) -> Result> { - let sig = String::from("()D"); + + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/AbstractHorseInventory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + crate::inventory::AbstractHorseInventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the damage dealt within the current no damage ticks time period. - pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(damage); + /// Gets the vehicle's velocity. + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the vehicle's velocity in meters per tick. + pub fn set_velocity( + &self, + vel: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(vel.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDamage", + "setVelocity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's current no damage ticks. - pub fn no_damage_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Check if this is tamed + /// + /// If something is tamed then a player can not tame it through normal + /// methods, even if it does not belong to anyone in particular. + pub fn is_tamed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isTamed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets if this has been tamed. Not necessary if the method setOwner has + /// been used, as it tames automatically. + /// + /// If something is tamed then a player can not tame it through normal + /// methods, even if it does not belong to anyone in particular. + pub fn set_tamed(&self, tame: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(tame.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getNoDamageTicks", + "setTamed", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the current owning AnimalTamer + pub fn owner( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/AnimalTamer;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::AnimalTamer::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Set this to be owned by given AnimalTamer. + /// + /// If the owner is not null, this will be tamed and will have any current + /// path it is following removed. If the owner is set to null, this will be + /// untamed, and the current owner removed. + pub fn set_owner( + &self, + tamer: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/AnimalTamer;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(tamer.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setOwner", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Horse<'mc> { + fn into(self) -> crate::entity::AbstractHorse<'mc> { + crate::entity::AbstractHorse::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Horse into crate::entity::AbstractHorse") + } +} +pub enum HorseVariant<'mc> { + Horse { inner: HorseVariantStruct<'mc> }, + Donkey { inner: HorseVariantStruct<'mc> }, + Mule { inner: HorseVariantStruct<'mc> }, + UndeadHorse { inner: HorseVariantStruct<'mc> }, + SkeletonHorse { inner: HorseVariantStruct<'mc> }, + Llama { inner: HorseVariantStruct<'mc> }, + Camel { inner: HorseVariantStruct<'mc> }, +} +impl<'mc> std::fmt::Display for HorseVariant<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + HorseVariant::Horse { .. } => f.write_str("HORSE"), + HorseVariant::Donkey { .. } => f.write_str("DONKEY"), + HorseVariant::Mule { .. } => f.write_str("MULE"), + HorseVariant::UndeadHorse { .. } => f.write_str("UNDEAD_HORSE"), + HorseVariant::SkeletonHorse { .. } => f.write_str("SKELETON_HORSE"), + HorseVariant::Llama { .. } => f.write_str("LLAMA"), + HorseVariant::Camel { .. } => f.write_str("CAMEL"), + } + } +} +impl<'mc> std::ops::Deref for HorseVariant<'mc> { + type Target = HorseVariantStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + HorseVariant::Horse { inner } => inner, + HorseVariant::Donkey { inner } => inner, + HorseVariant::Mule { inner } => inner, + HorseVariant::UndeadHorse { inner } => inner, + HorseVariant::SkeletonHorse { inner } => inner, + HorseVariant::Llama { inner } => inner, + HorseVariant::Camel { inner } => inner, + } + } +} + +impl<'mc> HorseVariant<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/Horse/Variant"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/Horse/Variant;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "HORSE" => Ok(HorseVariant::Horse { + inner: HorseVariantStruct::from_raw(env, obj)?, + }), + "DONKEY" => Ok(HorseVariant::Donkey { + inner: HorseVariantStruct::from_raw(env, obj)?, + }), + "MULE" => Ok(HorseVariant::Mule { + inner: HorseVariantStruct::from_raw(env, obj)?, + }), + "UNDEAD_HORSE" => Ok(HorseVariant::UndeadHorse { + inner: HorseVariantStruct::from_raw(env, obj)?, + }), + "SKELETON_HORSE" => Ok(HorseVariant::SkeletonHorse { + inner: HorseVariantStruct::from_raw(env, obj)?, + }), + "LLAMA" => Ok(HorseVariant::Llama { + inner: HorseVariantStruct::from_raw(env, obj)?, + }), + "CAMEL" => Ok(HorseVariant::Camel { + inner: HorseVariantStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct HorseVariantStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for HorseVariant<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Horse { inner } => inner.0.clone(), + Self::Donkey { inner } => inner.0.clone(), + Self::Mule { inner } => inner.0.clone(), + Self::UndeadHorse { inner } => inner.0.clone(), + Self::SkeletonHorse { inner } => inner.0.clone(), + Self::Llama { inner } => inner.0.clone(), + Self::Camel { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Horse { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Donkey { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Mule { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::UndeadHorse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SkeletonHorse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Llama { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Camel { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for HorseVariant<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate HorseVariant from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Horse/Variant")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a HorseVariant object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "HORSE" => Ok(HorseVariant::Horse { + inner: HorseVariantStruct::from_raw(env, obj)?, + }), + "DONKEY" => Ok(HorseVariant::Donkey { + inner: HorseVariantStruct::from_raw(env, obj)?, + }), + "MULE" => Ok(HorseVariant::Mule { + inner: HorseVariantStruct::from_raw(env, obj)?, + }), + "UNDEAD_HORSE" => Ok(HorseVariant::UndeadHorse { + inner: HorseVariantStruct::from_raw(env, obj)?, + }), + "SKELETON_HORSE" => Ok(HorseVariant::SkeletonHorse { + inner: HorseVariantStruct::from_raw(env, obj)?, + }), + "LLAMA" => Ok(HorseVariant::Llama { + inner: HorseVariantStruct::from_raw(env, obj)?, + }), + "CAMEL" => Ok(HorseVariant::Camel { + inner: HorseVariantStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for HorseVariantStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for HorseVariantStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate HorseVariantStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Horse/Variant")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a HorseVariantStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> HorseVariantStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Horse/Variant;"); + let cls = jni.find_class("org/bukkit/entity/Horse/Variant"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::HorseVariant::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +pub enum HorseColor<'mc> { + White { inner: HorseColorStruct<'mc> }, + Creamy { inner: HorseColorStruct<'mc> }, + Chestnut { inner: HorseColorStruct<'mc> }, + Brown { inner: HorseColorStruct<'mc> }, + Black { inner: HorseColorStruct<'mc> }, + Gray { inner: HorseColorStruct<'mc> }, + DarkBrown { inner: HorseColorStruct<'mc> }, +} +impl<'mc> std::fmt::Display for HorseColor<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + HorseColor::White { .. } => f.write_str("WHITE"), + HorseColor::Creamy { .. } => f.write_str("CREAMY"), + HorseColor::Chestnut { .. } => f.write_str("CHESTNUT"), + HorseColor::Brown { .. } => f.write_str("BROWN"), + HorseColor::Black { .. } => f.write_str("BLACK"), + HorseColor::Gray { .. } => f.write_str("GRAY"), + HorseColor::DarkBrown { .. } => f.write_str("DARK_BROWN"), + } + } +} +impl<'mc> std::ops::Deref for HorseColor<'mc> { + type Target = HorseColorStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + HorseColor::White { inner } => inner, + HorseColor::Creamy { inner } => inner, + HorseColor::Chestnut { inner } => inner, + HorseColor::Brown { inner } => inner, + HorseColor::Black { inner } => inner, + HorseColor::Gray { inner } => inner, + HorseColor::DarkBrown { inner } => inner, + } + } +} + +impl<'mc> HorseColor<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/Horse/Color"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/Horse/Color;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "WHITE" => Ok(HorseColor::White { + inner: HorseColorStruct::from_raw(env, obj)?, + }), + "CREAMY" => Ok(HorseColor::Creamy { + inner: HorseColorStruct::from_raw(env, obj)?, + }), + "CHESTNUT" => Ok(HorseColor::Chestnut { + inner: HorseColorStruct::from_raw(env, obj)?, + }), + "BROWN" => Ok(HorseColor::Brown { + inner: HorseColorStruct::from_raw(env, obj)?, + }), + "BLACK" => Ok(HorseColor::Black { + inner: HorseColorStruct::from_raw(env, obj)?, + }), + "GRAY" => Ok(HorseColor::Gray { + inner: HorseColorStruct::from_raw(env, obj)?, + }), + "DARK_BROWN" => Ok(HorseColor::DarkBrown { + inner: HorseColorStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct HorseColorStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for HorseColor<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::White { inner } => inner.0.clone(), + Self::Creamy { inner } => inner.0.clone(), + Self::Chestnut { inner } => inner.0.clone(), + Self::Brown { inner } => inner.0.clone(), + Self::Black { inner } => inner.0.clone(), + Self::Gray { inner } => inner.0.clone(), + Self::DarkBrown { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::White { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Creamy { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Chestnut { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Brown { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Black { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Gray { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DarkBrown { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for HorseColor<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate HorseColor from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Horse/Color")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a HorseColor object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "WHITE" => Ok(HorseColor::White { + inner: HorseColorStruct::from_raw(env, obj)?, + }), + "CREAMY" => Ok(HorseColor::Creamy { + inner: HorseColorStruct::from_raw(env, obj)?, + }), + "CHESTNUT" => Ok(HorseColor::Chestnut { + inner: HorseColorStruct::from_raw(env, obj)?, + }), + "BROWN" => Ok(HorseColor::Brown { + inner: HorseColorStruct::from_raw(env, obj)?, + }), + "BLACK" => Ok(HorseColor::Black { + inner: HorseColorStruct::from_raw(env, obj)?, + }), + "GRAY" => Ok(HorseColor::Gray { + inner: HorseColorStruct::from_raw(env, obj)?, + }), + "DARK_BROWN" => Ok(HorseColor::DarkBrown { + inner: HorseColorStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for HorseColorStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for HorseColorStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate HorseColorStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Horse/Color")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a HorseColorStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> HorseColorStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Horse/Color;"); + let cls = jni.find_class("org/bukkit/entity/Horse/Color"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::HorseColor::from_raw(&jni, obj) } - /// Sets the living entity's current no damage ticks. - pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setNoDamageTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Get the ticks that this entity has performed no action. - /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn no_action_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getNoActionTicks", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) +} +pub enum HorseStyle<'mc> { + None { inner: HorseStyleStruct<'mc> }, + White { inner: HorseStyleStruct<'mc> }, + Whitefield { inner: HorseStyleStruct<'mc> }, + WhiteDots { inner: HorseStyleStruct<'mc> }, + BlackDots { inner: HorseStyleStruct<'mc> }, +} +impl<'mc> std::fmt::Display for HorseStyle<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + HorseStyle::None { .. } => f.write_str("NONE"), + HorseStyle::White { .. } => f.write_str("WHITE"), + HorseStyle::Whitefield { .. } => f.write_str("WHITEFIELD"), + HorseStyle::WhiteDots { .. } => f.write_str("WHITE_DOTS"), + HorseStyle::BlackDots { .. } => f.write_str("BLACK_DOTS"), + } } - /// Set the ticks that this entity has performed no action. - /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setNoActionTicks", - sig.as_str(), +} +impl<'mc> std::ops::Deref for HorseStyle<'mc> { + type Target = HorseStyleStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + HorseStyle::None { inner } => inner, + HorseStyle::White { inner } => inner, + HorseStyle::Whitefield { inner } => inner, + HorseStyle::WhiteDots { inner } => inner, + HorseStyle::BlackDots { inner } => inner, + } + } +} + +impl<'mc> HorseStyle<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/Horse/Style"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/Horse/Style;", vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "NONE" => Ok(HorseStyle::None { + inner: HorseStyleStruct::from_raw(env, obj)?, + }), + "WHITE" => Ok(HorseStyle::White { + inner: HorseStyleStruct::from_raw(env, obj)?, + }), + "WHITEFIELD" => Ok(HorseStyle::Whitefield { + inner: HorseStyleStruct::from_raw(env, obj)?, + }), + "WHITE_DOTS" => Ok(HorseStyle::WhiteDots { + inner: HorseStyleStruct::from_raw(env, obj)?, + }), + "BLACK_DOTS" => Ok(HorseStyle::BlackDots { + inner: HorseStyleStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } - /// Gets the player identified as the killer of the living entity. - /// - /// May be null. - pub fn killer(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Player;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); +} + +#[repr(C)] +pub struct HorseStyleStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for HorseStyle<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::None { inner } => inner.0.clone(), + Self::White { inner } => inner.0.clone(), + Self::Whitefield { inner } => inner.0.clone(), + Self::WhiteDots { inner } => inner.0.clone(), + Self::BlackDots { inner } => inner.0.clone(), } - Ok(Some(crate::entity::Player::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) } - #[deprecated] - /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. - pub fn add_potion_effect( - &self, - effect: impl Into>, - force: std::option::Option, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/potion/PotionEffect;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(effect.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = force { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::None { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::White { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Whitefield { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WhiteDots { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlackDots { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, } - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) } - /// Returns whether the living entity already has an existing effect of - /// the given {@link PotionEffectType} applied to it. - pub fn has_potion_effect( - &self, - val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasPotionEffect", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} +impl<'mc> JNIInstantiatable<'mc> for HorseStyle<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate HorseStyle from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Horse/Style")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a HorseStyle object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "NONE" => Ok(HorseStyle::None { + inner: HorseStyleStruct::from_raw(env, obj)?, + }), + "WHITE" => Ok(HorseStyle::White { + inner: HorseStyleStruct::from_raw(env, obj)?, + }), + "WHITEFIELD" => Ok(HorseStyle::Whitefield { + inner: HorseStyleStruct::from_raw(env, obj)?, + }), + "WHITE_DOTS" => Ok(HorseStyle::WhiteDots { + inner: HorseStyleStruct::from_raw(env, obj)?, + }), + "BLACK_DOTS" => Ok(HorseStyle::BlackDots { + inner: HorseStyleStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } } - /// Returns the active {@link PotionEffect} of the specified type. - /// - /// If the effect is not present on the entity then null will be returned. - pub fn get_potion_effect( - &self, - val_type: impl Into>, - ) -> Result>, Box> { - let sig = - String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPotionEffect", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); +} + +impl<'mc> JNIRaw<'mc> for HorseStyleStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for HorseStyleStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate HorseStyleStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Horse/Style")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a HorseStyleStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - Ok(Some(crate::potion::PotionEffect::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) } - /// Removes any effects present of the given {@link PotionEffectType}. - pub fn remove_potion_effect( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removePotionEffect", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +} + +impl<'mc> HorseStyleStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Horse/Style;"); + let cls = jni.find_class("org/bukkit/entity/Horse/Style"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::HorseStyle::from_raw(&jni, obj) } - /// Returns all currently active {@link PotionEffect}s on the living - /// entity. - pub fn active_potion_effects( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getActivePotionEffects", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct Entity<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Entity<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Entity<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Entity from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Entity")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Entity object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - Ok(new_vec) } - /// Checks whether the living entity has block line of sight to another. +} + +impl<'mc> Entity<'mc> { + /// Stores the entity's current position in the provided Location object. /// - /// This uses the same algorithm that hostile mobs use to find the closest - /// player. - pub fn has_line_of_sight( + /// If the provided Location is null this method does nothing and returns + /// null. + pub fn get_location( &self, - other: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasLineOfSight", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns if the living entity despawns when away from players or not. - /// - /// By default, animals are not removed while other mobs are. - pub fn remove_when_far_away(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getRemoveWhenFarAway", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether or not the living entity despawns when away from players - /// or not. - pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(remove.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRemoveWhenFarAway", + "getLocation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the inventory with the equipment worn by the living entity. - pub fn equipment( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::EntityEquipment::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Sets whether or not the living entity can pick up items. - pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(pickup.into()); + /// Sets this entity's velocity in meters per tick + pub fn set_velocity( + &self, + velocity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCanPickupItems", + "setVelocity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the living entity can pick up items. - pub fn can_pickup_items(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCanPickupItems", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns whether the entity is currently leashed. - pub fn is_leashed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the entity that is currently leading this entity. - pub fn leash_holder(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + /// Gets this entity's current velocity + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the leash on this entity to be held by the supplied entity. - /// - /// This method has no effect on EnderDragons, Withers, Players, or Bats. - /// Non-living entities excluding leashes will not persist as leash - /// holders. - pub fn set_leash_holder( - &self, - holder: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(holder.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLeashHolder", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Checks to see if an entity is gliding, such as using an Elytra. - pub fn is_gliding(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the entity's height + pub fn height(&self) -> Result> { + let sig = String::from("()D"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Makes entity start or stop gliding. This will work even if an Elytra - /// is not equipped, but will be reverted by the server immediately after - /// unless an event-cancelling mechanism is put in place. - pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gliding.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setGliding", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.d()?) } - /// Checks to see if an entity is swimming. - pub fn is_swimming(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); + /// Gets the entity's width + pub fn width(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Makes entity start or stop swimming. - /// This may have unexpected results if the entity is not in water. - pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(swimming.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSwimming", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.d()?) } - /// Checks to see if an entity is currently using the Riptide enchantment. - pub fn is_riptiding(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the entity's current bounding box. + /// + /// The returned bounding box reflects the entity's current location and + /// size. + pub fn bounding_box( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns whether this entity is slumbering. - pub fn is_sleeping(&self) -> Result> { + /// Returns true if the entity is supported by a block. This value is a + /// state updated by the server and is not recalculated unless the entity + /// moves. + pub fn is_on_ground(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets if the entity is climbing. - pub fn is_climbing(&self) -> Result> { + /// Returns true if the entity is in water. + pub fn is_in_water(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether an entity will have AI. - /// The entity will be completely unable to move if it has no AI. - pub fn set_ai(&self, ai: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(ai.into()); + /// Gets the current world this entity resides in + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the entity's rotation. + /// + /// Note that if the entity is affected by AI, it may override this rotation. + pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { + let sig = String::from("(FF)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); + let val_2 = jni::objects::JValueGen::Float(pitch); let res = self.jni_ref().call_method( &self.jni_object(), - "setAI", + "setRotation", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks whether an entity has AI. - /// The entity will be completely unable to move if it has no AI. - pub fn has_ai(&self) -> Result> { - let sig = String::from("()Z"); + /// Teleports this entity to the given location. If this entity is riding a + /// vehicle, it will be dismounted prior to teleportation. + pub fn teleport( + &self, + location: impl Into>, + cause: std::option::Option< + impl Into>, + >, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = cause { + sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "teleport", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Makes this entity attack the given entity with a melee attack. - /// Attack damage is calculated by the server from the attributes and - /// equipment of this mob, and knockback is applied to {@code target} as - /// appropriate. - pub fn attack( + /// Returns a list of entities within a bounding box centered around this + /// entity + pub fn get_nearby_entities( &self, - target: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) - }); + x: f64, + y: f64, + z: f64, + ) -> Result>, Box> { + let sig = String::from("(DDD)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Double(x); + let val_2 = jni::objects::JValueGen::Double(y); + let val_3 = jni::objects::JValueGen::Double(z); let res = self.jni_ref().call_method( &self.jni_object(), - "attack", + "getNearbyEntities", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Makes this entity swing their main hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their main hand. - pub fn swing_main_hand(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Returns a unique id for this entity + pub fn entity_id(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Makes this entity swing their off hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their off hand. - pub fn swing_off_hand(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Returns the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn fire_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Makes this entity flash red as if they were damaged. - pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); + /// Returns the entity's maximum fire ticks. + pub fn max_fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "playHurtAnimation", + "setFireTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Set if this entity will be subject to collisions with other entities. - /// - /// Exemptions to this rule can be managed with - /// {@link #getCollidableExemptions()} - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not working for player collisions. This - /// method should therefore only be used to set the collision status of - /// non-player entities. - /// - /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in - /// combination with a {@link Scoreboard} and a {@link Team}. - pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { + /// Sets if the entity has visual fire (it will always appear to be on fire). + pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(collidable.into()); + let val_1 = jni::objects::JValueGen::Bool(fire.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCollidable", + "setVisualFire", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if this entity is subject to collisions with other entities. - /// - /// Some entities might be exempted from the collidable rule of this entity. - /// Use {@link #getCollidableExemptions()} to get these. - /// - /// Please note that this method returns only the custom collidable state, - /// not whether the entity is non-collidable for other reasons such as being - /// dead. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not being accurate for player collisions. - /// This method should therefore only be used to check the collision status - /// of non-player entities. - /// - /// To check the collision behavior for a player, use - /// {@link Team.Option#COLLISION_RULE} in combination with a - /// {@link Scoreboard} and a {@link Team}. - pub fn is_collidable(&self) -> Result> { + /// Gets if the entity has visual fire (it will always appear to be on fire). + pub fn is_visual_fire(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets a mutable set of UUIDs of the entities which are exempt from the - /// entity's collidable rule and which's collision with this entity will - /// behave the opposite of it. - /// - /// This set can be modified to add or remove exemptions. - /// - /// For example if collidable is true and an entity is in the exemptions set - /// then it will not collide with it. Similarly if collidable is false and an - /// entity is in this set then it will still collide with it. - /// - /// Note these exemptions are not (currently) persistent. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in those exemptions not being accurate for player - /// collisions. This method should therefore only be used to exempt - /// non-player entities. - /// - /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} - /// in combination with a {@link Scoreboard} and a {@link Team}. - pub fn collidable_exemptions( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Returns the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's maximum freeze ticks (amount of ticks before it will + /// be fully frozen) + pub fn max_freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCollidableExemptions", + "getMaxFreezeTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Returns the value of the memory specified. - /// - /// Note that the value is null when the specific entity does not have that - /// value by default. - pub fn get_memory( - &self, - memory_key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) - }); + /// Sets the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "getMemory", + "setFreezeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the entity is fully frozen (it has been in powdered snow for max + /// freeze ticks). + pub fn is_frozen(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(res.l()?)) + Ok(res.z()?) } - /// Sets the value of the memory specified. - /// - /// Note that the value will not be persisted when the specific entity does - /// not have that value by default. - pub fn set_memory( - &self, - memory_key: impl Into>, - memory_value: jni::objects::JObject<'mc>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(memory_value); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMemory", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + /// Mark the entity's removal. + pub fn remove(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the {@link Sound} this entity will make when damaged. - pub fn hurt_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); + /// Returns true if this entity has been marked for removal. + pub fn is_dead(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + Ok(res.z()?) + } + /// Returns false if the entity has died, been despawned for some other + /// reason, or has not been added to the world. + pub fn is_valid(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the {@link Server} that contains this Entity + pub fn server(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Server;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Server::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + }) } - /// Get the {@link Sound} this entity will make on death. - pub fn death_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Returns true if the entity gets persisted. + /// + /// By default all entities are persistent. An entity will also not get + /// persisted, if it is riding an entity that is not persistent. + /// + /// The persistent flag on players controls whether or not to save their + /// playerdata file when they quit. If a player is directly or indirectly + /// riding a non-persistent entity, the vehicle at the root and all its + /// passengers won't get persisted. + /// + /// This should not be confused with + /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls + /// despawning of living entities. + pub fn is_persistent(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.z()?) } - /// Get the {@link Sound} this entity will make when falling from the given - /// height (in blocks). The sound will often differ between either a small - /// or a big fall damage sound if the height exceeds 4 blocks. - pub fn get_fall_damage_sound( - &self, - fall_height: i32, - ) -> Result, Box> { - let sig = String::from("(I)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Int(fall_height); + /// Sets whether or not the entity gets persisted. + pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(persistent.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSound", + "setPersistent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. + pub fn passenger( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Get the {@link Sound} this entity will make when falling from a small - /// height. - pub fn fall_damage_sound_small(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + #[deprecated] + /// Set the passenger of a vehicle. + pub fn set_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSoundSmall", + "setPassenger", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Get the {@link Sound} this entity will make when falling from a large - /// height. - pub fn fall_damage_sound_big(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFallDamageSoundBig", - sig.as_str(), - vec![], - ); + /// Gets a list of passengers of this vehicle. + /// + /// The returned list will not be directly linked to the entity's current + /// passengers, and no guarantees are made as to its mutability. + pub fn passengers( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Get the {@link Sound} this entity will make when drinking the given - /// {@link ItemStack}. - pub fn get_drinking_sound( + /// Add a passenger to the vehicle. + pub fn add_passenger( &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getDrinkingSound", + "addPassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Get the {@link Sound} this entity will make when eating the given - /// {@link ItemStack}. - pub fn get_eating_sound( - &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + /// Remove a passenger from the vehicle. + pub fn remove_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getEatingSound", + "removePassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Returns true if this entity can breathe underwater and will not take - /// suffocation damage when its air supply reaches zero. - pub fn can_breathe_underwater(&self) -> Result> { + /// Check if a vehicle has passengers. + pub fn is_empty(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "canBreatheUnderwater", - sig.as_str(), - vec![], - ); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. - pub fn category( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); + /// Eject any passenger. + pub fn eject(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the distance this entity has fallen + pub fn fall_distance(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.f()?) } - /// Sets whether the entity is invisible or not. - pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(invisible.into()); + /// Sets the fall distance for this entity + pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvisible", + "setFallDistance", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invisible or not. - pub fn is_invisible(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for ComplexLivingEntity<'mc> { - fn into(self) -> crate::entity::LivingEntity<'mc> { - crate::entity::LivingEntity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ComplexLivingEntity into crate::entity::LivingEntity") - } -} -#[repr(C)] -pub struct Rabbit<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Rabbit<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Rabbit<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Rabbit from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Rabbit")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Rabbit object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Rabbit<'mc> { - pub fn rabbit_type( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Rabbit/Type;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRabbitType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::RabbitType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn set_rabbit_type( + #[deprecated] + /// Record the last {@link EntityDamageEvent} inflicted on this entity + pub fn set_last_damage_cause( &self, - val_type: impl Into>, + event: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Rabbit/Type;)V"); + let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(event.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setRabbitType", + "setLastDamageCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn breed_cause( + /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. + /// This event may have been cancelled. + pub fn last_damage_cause( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); + ) -> Result>, Box> + { + let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLastDamageCause", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( + Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Set the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn set_breed_cause( + /// Returns a unique and persistent id for this entity + pub fn unique_id( &self, - uuid: impl Into>, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. + pub fn ticks_lived(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. May not be less than one + /// tick. + pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTicksLived", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Performs the specified {@link EntityEffect} for this entity. + /// + /// This will be viewable to all players near the entity. + /// + /// If the effect is not applicable to this class of entity, it will not play. + pub fn play_effect( + &self, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/UUID;)V"); + let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreedCause", + "playEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get whether or not this entity is in love mode and will produce - /// offspring with another entity in love mode. Will return true if - /// and only if {@link #getLoveModeTicks()} is greater than 0. - pub fn is_love_mode(&self) -> Result> { - let sig = String::from("()Z"); + /// Get the type of the entity. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes while swimming. + pub fn swim_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get the amount of ticks remaining for this entity in love mode. - /// If the entity is not in love mode, 0 will be returned. - pub fn love_mode_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Get the {@link Sound} this entity makes when splashing in water. For most + /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_splash_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLoveModeTicks", + "getSwimSplashSound", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the amount of ticks for which this entity should be in love mode. - /// Setting the love mode ticks to 600 is the equivalent of a player - /// feeding the entity their breeding item of choice. - pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Get the {@link Sound} this entity makes when splashing in water at high + /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_high_speed_splash_sound( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setLoveModeTicks", + "getSwimHighSpeedSplashSound", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Check if the provided ItemStack is the correct item used for breeding - /// this entity.. - pub fn is_breed_item( - &self, - material: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); + /// Returns whether this entity is inside a vehicle. + pub fn is_inside_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Rabbit<'mc> { - fn into(self) -> crate::entity::Animals<'mc> { - crate::entity::Animals::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Rabbit into crate::entity::Animals") - } -} -pub enum RabbitType<'mc> {} -impl<'mc> std::fmt::Display for RabbitType<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> RabbitType<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/Rabbit/Type"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/Rabbit/Type;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct RabbitTypeStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for RabbitType<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for RabbitType<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate RabbitType from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Rabbit/Type")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a RabbitType object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for RabbitTypeStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for RabbitTypeStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate RabbitTypeStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Rabbit/Type")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a RabbitTypeStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> RabbitTypeStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Rabbit/Type;"); - let cls = jni.find_class("org/bukkit/entity/Rabbit/Type"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::RabbitType::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct Armadillo<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Armadillo<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Armadillo<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Armadillo from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Armadillo")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Armadillo object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Leave the current vehicle. If the entity is currently in a vehicle (and + /// is removed from it), true will be returned, otherwise false will be + /// returned. + pub fn leave_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} - -impl<'mc> Armadillo<'mc> { - /// Get the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn breed_cause( + /// Get the vehicle that this entity is inside. If there is no vehicle, + /// null will be returned. + pub fn vehicle( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/UUID;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( + Ok(Some(crate::entity::Entity::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Set the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn set_breed_cause( - &self, - uuid: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/UUID;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) - }); + /// Sets whether or not to display the mob's custom name client side. The + /// name will be displayed above the mob similarly to a player. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreedCause", + "setCustomNameVisible", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get whether or not this entity is in love mode and will produce - /// offspring with another entity in love mode. Will return true if - /// and only if {@link #getLoveModeTicks()} is greater than 0. - pub fn is_love_mode(&self) -> Result> { + /// Gets whether or not the mob's custom name is displayed client side. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn is_custom_name_visible(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the amount of ticks remaining for this entity in love mode. - /// If the entity is not in love mode, 0 will be returned. - pub fn love_mode_ticks(&self) -> Result> { - let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLoveModeTicks", + "isCustomNameVisible", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the amount of ticks for which this entity should be in love mode. - /// Setting the love mode ticks to 600 is the equivalent of a player - /// feeding the entity their breeding item of choice. - pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(visible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLoveModeTicks", + "setVisibleByDefault", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check if the provided ItemStack is the correct item used for breeding - /// this entity.. - pub fn is_breed_item( - &self, - material: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); + /// Gets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn is_visible_by_default(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isVisibleByDefault", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Armadillo<'mc> { - fn into(self) -> crate::entity::Animals<'mc> { - crate::entity::Animals::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Armadillo into crate::entity::Animals") - } -} -#[repr(C)] -pub struct Snowman<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Snowman<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Get all players that are currently tracking this entity. + /// + /// 'Tracking' means that this entity has been sent to the player and that + /// they are receiving updates on its state. Note that the client's {@code + /// 'Entity Distance'} setting does not affect the range at which entities + /// are tracked. + pub fn tracked_by( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> JNIInstantiatable<'mc> for Snowman<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Snowman from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Snowman")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Snowman object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Sets whether the entity has a team colored (default: white) glow. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setGlowing", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> Snowman<'mc> { - /// Gets whether this snowman is in "derp mode", meaning it is not wearing a - /// pumpkin. - pub fn is_derp(&self) -> Result> { + /// Gets whether the entity is glowing or not. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn is_glowing(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isDerp", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether this snowman is in "derp mode", meaning it is not wearing a - /// pumpkin. NOTE: This value is not persisted to disk and will therefore - /// reset when the chunk is reloaded. - pub fn set_derp(&self, derp_mode: bool) -> Result<(), Box> { + /// Sets whether the entity is invulnerable or not. + /// + /// When an entity is invulnerable it can only be damaged by players in + /// creative mode. + pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(derp_mode.into()); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setDerp", + "setInvulnerable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Snowman<'mc> { - fn into(self) -> crate::entity::Golem<'mc> { - crate::entity::Golem::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Snowman into crate::entity::Golem") - } -} -#[repr(C)] -pub struct Animals<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Animals<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Animals<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Animals from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Animals")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Animals object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Animals<'mc> { - /// Get the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn breed_cause( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/UUID;"); + /// Gets whether the entity is invulnerable or not. + pub fn is_invulnerable(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Set the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn set_breed_cause( - &self, - uuid: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/UUID;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) - }); + /// Gets whether the entity is silent or not. + pub fn is_silent(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the entity is silent or not. + /// + /// When an entity is silent it will not produce any sound. + pub fn set_silent(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreedCause", + "setSilent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get whether or not this entity is in love mode and will produce - /// offspring with another entity in love mode. Will return true if - /// and only if {@link #getLoveModeTicks()} is greater than 0. - pub fn is_love_mode(&self) -> Result> { + /// Returns whether gravity applies to this entity. + pub fn has_gravity(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get the amount of ticks remaining for this entity in love mode. - /// If the entity is not in love mode, 0 will be returned. - pub fn love_mode_ticks(&self) -> Result> { + /// Sets whether gravity applies to this entity. + pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gravity.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setGravity", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the period of time (in ticks) before this entity can use a portal. + pub fn portal_cooldown(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLoveModeTicks", + "getPortalCooldown", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Set the amount of ticks for which this entity should be in love mode. - /// Setting the love mode ticks to 600 is the equivalent of a player - /// feeding the entity their breeding item of choice. - pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Sets the period of time (in ticks) before this entity can use a portal. + pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + let val_1 = jni::objects::JValueGen::Int(cooldown); let res = self.jni_ref().call_method( &self.jni_object(), - "setLoveModeTicks", + "setPortalCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check if the provided ItemStack is the correct item used for breeding - /// this entity.. - pub fn is_breed_item( + /// Returns a set of tags for this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn scoreboard_tags( &self, - material: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getScoreboardTags", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Lock the age of the animal, setting this will prevent the animal from - /// maturing or getting ready for mating. - pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(lock.into()); + /// Add a tag to this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn add_scoreboard_tag( + &self, + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setAgeLock", + "addScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the current agelock. - pub fn age_lock(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Return the ability to breed of the animal. - pub fn can_breed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); + /// Removes a given tag from this entity. + pub fn remove_scoreboard_tag( + &self, + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeScoreboardTag", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set breedability of the animal, if the animal is a baby and set to - /// breed it will instantly grow up. - pub fn set_breed(&self, breed: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(breed.into()); + /// Returns the reaction of the entity when moved by a piston. + pub fn piston_move_reaction( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreed", + "getPistonMoveReaction", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + /// Get the closest cardinal {@link BlockFace} direction an entity is + /// currently facing. + /// + /// This will not return any non-cardinal directions such as + /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// + /// {@link Hanging} entities will override this call and thus their behavior + /// may be different. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> Into> for Animals<'mc> { - fn into(self) -> crate::entity::Breedable<'mc> { - crate::entity::Breedable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Animals into crate::entity::Breedable") + /// Gets the entity's current pose. + /// Note that the pose is only updated at the end of a tick, so may be + /// inconsistent with other methods. eg {@link Player#isSneaking()} being + /// true does not imply the current pose will be {@link Pose#SNEAKING} + pub fn pose(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Pose;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -#[repr(C)] -pub struct GlowItemFrame<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for GlowItemFrame<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Get the category of spawn to which this entity belongs. + pub fn spawn_category( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSpawnCategory", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Checks if this entity has been spawned in a world. + /// + /// Entities not spawned in a world will not tick, be sent to players, or be + /// saved to the server files. + pub fn is_in_world(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for GlowItemFrame<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate GlowItemFrame from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/GlowItemFrame")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a GlowItemFrame object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + /// Get this entity as an NBT string. + /// + /// This string should not be relied upon as a serializable value. + pub fn as_string(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } -} - -impl<'mc> GlowItemFrame<'mc> { - /// Get the item in this frame - pub fn item(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + /// Crates an {@link EntitySnapshot} representing the current state of this entity. + pub fn create_snapshot( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntitySnapshot::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// + /// Note: Players cannot be copied. + pub fn copy( + &self, + to: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = to { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Lorg/bukkit/entity/Entity;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "copy", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Set the item in this frame - pub fn set_item( + /// Sets a metadata value in the implementing object's metadata store. + pub fn set_metadata( &self, - item: impl Into>, - play_sound: std::option::Option, + metadata_key: impl Into, + new_metadata_value: impl Into>, ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + let sig = String::from("(Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) }); - args.push(val_1); - if let Some(a) = play_sound { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setItem", sig.as_str(), args); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMetadata", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the chance of the item being dropped upon this frame's destruction. - ///
    - ///
  • A drop chance of 0.0F will never drop - ///
  • A drop chance of 1.0F will always drop - ///
- pub fn item_drop_chance(&self) -> Result> { - let sig = String::from("()F"); + /// Returns a list of previously set metadata values from the implementing + /// object's metadata store. + pub fn get_metadata( + &self, + metadata_key: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "getItemDropChance", + "getMetadata", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::metadata::MetadataValue::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(new_vec) } - /// Sets the chance of the off hand item being dropped upon this frame's - /// destruction. - ///
    - ///
  • A drop chance of 0.0F will never drop - ///
  • A drop chance of 1.0F will always drop - ///
- pub fn set_item_drop_chance(&self, chance: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(chance); + /// Tests to see whether the implementing object contains the given + /// metadata value in its metadata store. + pub fn has_metadata( + &self, + metadata_key: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemDropChance", + "hasMetadata", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the rotation of the frame's item - pub fn rotation(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Rotation;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRotation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Rotation::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Set the rotation of the frame's item - pub fn set_rotation( + /// Removes the given metadata value from the implementing object's + /// metadata store. + pub fn remove_metadata( &self, - rotation: impl Into>, + metadata_key: impl Into, + owning_plugin: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Rotation;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(rotation.into().jni_object().clone()) + let sig = String::from("(Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setRotation", + "removeMetadata", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether the item frame is be visible or not. - pub fn is_visible(&self) -> Result> { - let sig = String::from("()Z"); + /// Sends this sender multiple messages + pub fn send_message( + &self, + sender: impl Into>, + messages: std::option::Option>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/util/UUID;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = messages { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_2); + } + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isVisible", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether the item frame should be visible or not. - pub fn set_visible(&self, visible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(visible.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setVisible", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether the item frame is "fixed" or not. - /// When true it's not possible to destroy/move the frame (e.g. by damage, - /// interaction, pistons, or missing supporting blocks), rotate the item or - /// place/remove items. - pub fn is_fixed(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the name of this command sender + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isFixed", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets whether the item frame should be fixed or not. - /// When set to true it's not possible to destroy/move the frame (e.g. by - /// damage, interaction, pistons, or missing supporting blocks), rotate the - /// item or place/remove items. - pub fn set_fixed(&self, fixed: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fixed.into()); + /// Gets the custom name on a mob or block. If there is no name this method + /// will return null. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn custom_name(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCustomName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Sets a custom name on a mob or block. This name will be used in death + /// messages and can be sent to the client as a nameplate over the mob. + /// + /// Setting the name to null or an empty string will clear it. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn set_custom_name( + &self, + name: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setFixed", + "setCustomName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets the direction of the hanging entity, potentially overriding rules - /// of placement. Note that if the result is not valid the object would - /// normally drop as an item. - pub fn set_facing_direction( + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + pub fn persistent_data_container( &self, - face: impl Into>, - force: bool, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;Z)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Bool(force.into()); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setFacingDirection", + "getPersistentDataContainer", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -24755,112 +31486,37 @@ impl<'mc> GlowItemFrame<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for GlowItemFrame<'mc> { - fn into(self) -> crate::entity::ItemFrame<'mc> { - crate::entity::ItemFrame::from_raw(&self.jni_ref(), self.1) - .expect("Error converting GlowItemFrame into crate::entity::ItemFrame") +impl<'mc> Into> for Entity<'mc> { + fn into(self) -> crate::metadata::Metadatable<'mc> { + crate::metadata::Metadatable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Entity into crate::metadata::Metadatable") } } -#[repr(C)] -pub struct EntitySnapshot<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for EntitySnapshot<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } +impl<'mc> Into> for Entity<'mc> { + fn into(self) -> crate::command::CommandSender<'mc> { + crate::command::CommandSender::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Entity into crate::command::CommandSender") } } -impl<'mc> JNIInstantiatable<'mc> for EntitySnapshot<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate EntitySnapshot from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EntitySnapshot")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EntitySnapshot object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } +impl<'mc> Into> for Entity<'mc> { + fn into(self) -> crate::Nameable<'mc> { + crate::Nameable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Entity into crate::Nameable") } } - -impl<'mc> EntitySnapshot<'mc> { - /// Creates an entity using this template and spawns it at the provided location. - pub fn create_entity( - &self, - to: impl Into>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(to.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Lorg/bukkit/entity/Entity;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "createEntity", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the type of entity this template holds. - pub fn entity_type( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEntityType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get this EntitySnapshot as an NBT string. - /// - /// This string should not be relied upon as a serializable value. - pub fn as_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) +impl<'mc> Into> for Entity<'mc> { + fn into(self) -> crate::persistence::PersistentDataHolder<'mc> { + crate::persistence::PersistentDataHolder::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Entity into crate::persistence::PersistentDataHolder") } } #[repr(C)] -pub struct LivingEntity<'mc>( +pub struct Endermite<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for LivingEntity<'mc> { +impl<'mc> JNIRaw<'mc> for Endermite<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -24868,18 +31524,18 @@ impl<'mc> JNIRaw<'mc> for LivingEntity<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for LivingEntity<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Endermite<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate LivingEntity from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Endermite from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/LivingEntity")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Endermite")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a LivingEntity object, got {}", + "Invalid argument passed. Expected a Endermite object, got {}", name ) .into()) @@ -24888,1060 +31544,846 @@ impl<'mc> JNIInstantiatable<'mc> for LivingEntity<'mc> { } } } - -impl<'mc> LivingEntity<'mc> { - /// Gets the height of the living entity's eyes above its Location. - pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { - let sig = String::from("(Z)D"); - let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getEyeHeight", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Get a Location detailing the current eye position of the living entity. - pub fn eye_location(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets all blocks along the living entity's line of sight. - /// - /// This list contains all blocks from the living entity's eye position to - /// target inclusive. This method considers all blocks as 1x1x1 in size. - pub fn get_line_of_sight( - &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { - let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(max_distance); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLineOfSight", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Gets the block that the living entity has targeted. - /// - /// This method considers all blocks as 1x1x1 in size. To take exact block - /// collision shapes into account, see {@link #getTargetBlockExact(int, - /// FluidCollisionMode)}. - pub fn get_target_block( - &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result, Box> { - let sig = String::from("(Ljava/util/Set;I)Lorg/bukkit/block/Block;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(max_distance); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTargetBlock", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + +impl<'mc> Endermite<'mc> { + #[deprecated] + /// Gets whether this Endermite was spawned by a player. An Endermite spawned by a player will be attacked by nearby Enderman. + pub fn is_player_spawned(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isPlayerSpawned", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Gets the last two blocks along the living entity's line of sight. - /// - /// The target block will be the last block in the list. This method - /// considers all blocks as 1x1x1 in size. - pub fn get_last_two_target_blocks( + #[deprecated] + /// Sets whether this Endermite was spawned by a player. An Endermite spawned by a player will be attacked by nearby Enderman. + pub fn set_player_spawned( &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { - let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(max_distance); + player_spawned: bool, + ) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(player_spawned.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getLastTwoTargetBlocks", + "setPlayerSpawned", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the block that the living entity has targeted. - /// - /// This takes the blocks' precise collision shapes into account. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn get_target_block_exact( - &self, - max_distance: i32, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(max_distance); - args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Endermite<'mc> { + fn into(self) -> crate::entity::Monster<'mc> { + crate::entity::Monster::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Endermite into crate::entity::Monster") + } +} +#[repr(C)] +pub struct Damageable<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Damageable<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Damageable<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Damageable from null object.").into()); } - sig += ")Lorg/bukkit/block/Block;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTargetBlockExact", - sig.as_str(), - args, - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Damageable")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Damageable object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - Ok(Some(crate::block::Block::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) } - /// Performs a ray trace that provides information on the targeted block. - /// - /// This takes the blocks' precise collision shapes into account. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn ray_trace_blocks( +} + +impl<'mc> Damageable<'mc> { + /// Deals the given amount of damage to this entity from a specified + /// {@link DamageSource}. + pub fn damage( &self, - max_distance: f64, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { + amount: f64, + damage_source: std::option::Option>>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "D"; - let val_1 = jni::objects::JValueGen::Double(max_distance); + let val_1 = jni::objects::JValueGen::Double(amount); args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; + if let Some(a) = damage_source { + sig += "Lorg/bukkit/damage/DamageSource;"; let val_2 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); args.push(val_2); } - sig += ")Lorg/bukkit/util/RayTraceResult;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::util::RayTraceResult::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Returns the amount of air that the living entity has remaining, in - /// ticks. - pub fn remaining_air(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the amount of air that the living entity has remaining, in ticks. - pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRemainingAir", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "damage", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the maximum amount of air the living entity can have, in ticks. - pub fn maximum_air(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); + /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. + pub fn health(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.d()?) } - /// Sets the maximum amount of air the living entity can have, in ticks. - pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is + /// dead. + pub fn set_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaximumAir", + "setHealth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the item that the player is using (eating food, drawing back a bow, - /// blocking, etc.) - pub fn item_in_use( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Gets the number of ticks remaining for the current item's usage. - pub fn item_in_use_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the entity's absorption amount. + pub fn absorption_amount(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref().call_method( &self.jni_object(), - "getItemInUseTicks", + "getAbsorptionAmount", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.d()?) } - /// Sets the number of ticks that remain for the current item's usage. - /// Applies to items that take time to use, like eating food, drawing a bow, - /// or throwing a trident. - pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets the entity's absorption amount. + /// + /// Note: The amount is capped to the value of + /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on + /// that attribute is currently unspecified and subject to change. + pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemInUseTicks", + "setAbsorptionAmount", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the time in ticks until the next arrow leaves the entity's body. - pub fn arrow_cooldown(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getArrowCooldown", - sig.as_str(), - vec![], - ); + #[deprecated] + /// Gets the maximum health this entity has. + pub fn max_health(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.d()?) } - /// Sets the time in ticks until the next arrow leaves the entity's body. - pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + #[deprecated] + /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. + pub fn set_max_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "setArrowCooldown", + "setMaxHealth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the amount of arrows in an entity's body. - pub fn arrows_in_body(&self) -> Result> { - let sig = String::from("()I"); + #[deprecated] + /// Resets the max health to the original amount. + pub fn reset_max_health(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the amount of arrows in the entity's body. - pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(count); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setArrowsInBody", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's current maximum no damage ticks. + /// Stores the entity's current position in the provided Location object. /// - /// This is the maximum duration in which the living entity will not take - /// damage. - pub fn maximum_no_damage_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// If the provided Location is null this method does nothing and returns + /// null. + pub fn get_location( + &self, + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getMaximumNoDamageTicks", + "getLocation", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Sets the living entity's current maximum no damage ticks. - pub fn set_maximum_no_damage_ticks( + /// Sets this entity's velocity in meters per tick + pub fn set_velocity( &self, - ticks: i32, + velocity: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaximumNoDamageTicks", + "setVelocity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's last damage taken in the current no damage - /// ticks time. - /// - /// Only damage higher than this amount will further damage the living - /// entity. - pub fn last_damage(&self) -> Result> { - let sig = String::from("()D"); + /// Gets this entity's current velocity + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the entity's height + pub fn height(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.d()?) } - /// Sets the damage dealt within the current no damage ticks time period. - pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(damage); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLastDamage", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Gets the entity's width + pub fn width(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } - /// Returns the living entity's current no damage ticks. - pub fn no_damage_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getNoDamageTicks", - sig.as_str(), - vec![], - ); + /// Gets the entity's current bounding box. + /// + /// The returned bounding box reflects the entity's current location and + /// size. + pub fn bounding_box( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the living entity's current no damage ticks. - pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setNoDamageTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Returns true if the entity is supported by a block. This value is a + /// state updated by the server and is not recalculated unless the entity + /// moves. + pub fn is_on_ground(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Get the ticks that this entity has performed no action. - /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn no_action_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getNoActionTicks", - sig.as_str(), - vec![], - ); + /// Returns true if the entity is in water. + pub fn is_in_water(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the ticks that this entity has performed no action. + /// Gets the current world this entity resides in + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the entity's rotation. /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Note that if the entity is affected by AI, it may override this rotation. + pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { + let sig = String::from("(FF)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); + let val_2 = jni::objects::JValueGen::Float(pitch); let res = self.jni_ref().call_method( &self.jni_object(), - "setNoActionTicks", + "setRotation", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the player identified as the killer of the living entity. - /// - /// May be null. - pub fn killer(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Player;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Player::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - #[deprecated] - /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. - pub fn add_potion_effect( + /// Teleports this entity to the given location. If this entity is riding a + /// vehicle, it will be dismounted prior to teleportation. + pub fn teleport( &self, - effect: impl Into>, - force: std::option::Option, + location: impl Into>, + cause: std::option::Option< + impl Into>, + >, ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/potion/PotionEffect;"; + sig += "Lorg/bukkit/Location;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(effect.into().jni_object().clone()) + jni::objects::JObject::from_raw(location.into().jni_object().clone()) }); args.push(val_1); - if let Some(a) = force { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); + if let Some(a) = cause { + sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); args.push(val_2); } sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "teleport", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns whether the living entity already has an existing effect of - /// the given {@link PotionEffectType} applied to it. - pub fn has_potion_effect( + /// Returns a list of entities within a bounding box centered around this + /// entity + pub fn get_nearby_entities( &self, - val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + x: f64, + y: f64, + z: f64, + ) -> Result>, Box> { + let sig = String::from("(DDD)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Double(x); + let val_2 = jni::objects::JValueGen::Double(y); + let val_3 = jni::objects::JValueGen::Double(z); let res = self.jni_ref().call_method( &self.jni_object(), - "hasPotionEffect", + "getNearbyEntities", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Returns the active {@link PotionEffect} of the specified type. - /// - /// If the effect is not present on the entity then null will be returned. - pub fn get_potion_effect( - &self, - val_type: impl Into>, - ) -> Result>, Box> { - let sig = - String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPotionEffect", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Returns a unique id for this entity + pub fn entity_id(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::potion::PotionEffect::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - /// Removes any effects present of the given {@link PotionEffectType}. - pub fn remove_potion_effect( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Returns the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's maximum fire ticks. + pub fn max_fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "removePotionEffect", + "setFireTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns all currently active {@link PotionEffect}s on the living - /// entity. - pub fn active_potion_effects( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getActivePotionEffects", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Checks whether the living entity has block line of sight to another. - /// - /// This uses the same algorithm that hostile mobs use to find the closest - /// player. - pub fn has_line_of_sight( - &self, - other: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) - }); + /// Sets if the entity has visual fire (it will always appear to be on fire). + pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "hasLineOfSight", + "setVisualFire", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the entity has visual fire (it will always appear to be on fire). + pub fn is_visual_fire(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns if the living entity despawns when away from players or not. - /// - /// By default, animals are not removed while other mobs are. - pub fn remove_when_far_away(&self) -> Result> { - let sig = String::from("()Z"); + /// Returns the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's maximum freeze ticks (amount of ticks before it will + /// be fully frozen) + pub fn max_freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getRemoveWhenFarAway", + "getMaxFreezeTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets whether or not the living entity despawns when away from players - /// or not. - pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(remove.into()); + /// Sets the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setRemoveWhenFarAway", + "setFreezeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the inventory with the equipment worn by the living entity. - pub fn equipment( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); + /// Gets if the entity is fully frozen (it has been in powdered snow for max + /// freeze ticks). + pub fn is_frozen(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::EntityEquipment::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Sets whether or not the living entity can pick up items. - pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(pickup.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCanPickupItems", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Mark the entity's removal. + pub fn remove(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the living entity can pick up items. - pub fn can_pickup_items(&self) -> Result> { + /// Returns true if this entity has been marked for removal. + pub fn is_dead(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCanPickupItems", - sig.as_str(), - vec![], - ); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns whether the entity is currently leashed. - pub fn is_leashed(&self) -> Result> { + /// Returns false if the entity has died, been despawned for some other + /// reason, or has not been added to the world. + pub fn is_valid(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the entity that is currently leading this entity. - pub fn leash_holder(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); + /// Gets the {@link Server} that contains this Entity + pub fn server(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Server;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + crate::Server::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the leash on this entity to be held by the supplied entity. + /// Returns true if the entity gets persisted. /// - /// This method has no effect on EnderDragons, Withers, Players, or Bats. - /// Non-living entities excluding leashes will not persist as leash - /// holders. - pub fn set_leash_holder( - &self, - holder: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(holder.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLeashHolder", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Checks to see if an entity is gliding, such as using an Elytra. - pub fn is_gliding(&self) -> Result> { + /// By default all entities are persistent. An entity will also not get + /// persisted, if it is riding an entity that is not persistent. + /// + /// The persistent flag on players controls whether or not to save their + /// playerdata file when they quit. If a player is directly or indirectly + /// riding a non-persistent entity, the vehicle at the root and all its + /// passengers won't get persisted. + /// + /// This should not be confused with + /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls + /// despawning of living entities. + pub fn is_persistent(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Makes entity start or stop gliding. This will work even if an Elytra - /// is not equipped, but will be reverted by the server immediately after - /// unless an event-cancelling mechanism is put in place. - pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { + /// Sets whether or not the entity gets persisted. + pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gliding.into()); + let val_1 = jni::objects::JValueGen::Bool(persistent.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setGliding", + "setPersistent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks to see if an entity is swimming. - pub fn is_swimming(&self) -> Result> { - let sig = String::from("()Z"); + #[deprecated] + /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. + pub fn passenger( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Makes entity start or stop swimming. - /// This may have unexpected results if the entity is not in water. - pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(swimming.into()); + #[deprecated] + /// Set the passenger of a vehicle. + pub fn set_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setSwimming", + "setPassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks to see if an entity is currently using the Riptide enchantment. - pub fn is_riptiding(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns whether this entity is slumbering. - pub fn is_sleeping(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets if the entity is climbing. - pub fn is_climbing(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets a list of passengers of this vehicle. + /// + /// The returned list will not be directly linked to the entity's current + /// passengers, and no guarantees are made as to its mutability. + pub fn passengers( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Sets whether an entity will have AI. - /// The entity will be completely unable to move if it has no AI. - pub fn set_ai(&self, ai: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(ai.into()); + /// Add a passenger to the vehicle. + pub fn add_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setAI", + "addPassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks whether an entity has AI. - /// The entity will be completely unable to move if it has no AI. - pub fn has_ai(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Makes this entity attack the given entity with a melee attack. - /// Attack damage is calculated by the server from the attributes and - /// equipment of this mob, and knockback is applied to {@code target} as - /// appropriate. - pub fn attack( + /// Remove a passenger from the vehicle. + pub fn remove_passenger( &self, - target: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "attack", + "removePassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Makes this entity swing their main hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their main hand. - pub fn swing_main_hand(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Check if a vehicle has passengers. + pub fn is_empty(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Makes this entity swing their off hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their off hand. - pub fn swing_off_hand(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Eject any passenger. + pub fn eject(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the distance this entity has fallen + pub fn fall_distance(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) } - /// Makes this entity flash red as if they were damaged. - pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { + /// Sets the fall distance for this entity + pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); + let val_1 = jni::objects::JValueGen::Float(distance); let res = self.jni_ref().call_method( &self.jni_object(), - "playHurtAnimation", + "setFallDistance", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Set if this entity will be subject to collisions with other entities. - /// - /// Exemptions to this rule can be managed with - /// {@link #getCollidableExemptions()} - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not working for player collisions. This - /// method should therefore only be used to set the collision status of - /// non-player entities. - /// - /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in - /// combination with a {@link Scoreboard} and a {@link Team}. - pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(collidable.into()); + #[deprecated] + /// Record the last {@link EntityDamageEvent} inflicted on this entity + pub fn set_last_damage_cause( + &self, + event: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(event.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCollidable", + "setLastDamageCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if this entity is subject to collisions with other entities. - /// - /// Some entities might be exempted from the collidable rule of this entity. - /// Use {@link #getCollidableExemptions()} to get these. - /// - /// Please note that this method returns only the custom collidable state, - /// not whether the entity is non-collidable for other reasons such as being - /// dead. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not being accurate for player collisions. - /// This method should therefore only be used to check the collision status - /// of non-player entities. - /// - /// To check the collision behavior for a player, use - /// {@link Team.Option#COLLISION_RULE} in combination with a - /// {@link Scoreboard} and a {@link Team}. - pub fn is_collidable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets a mutable set of UUIDs of the entities which are exempt from the - /// entity's collidable rule and which's collision with this entity will - /// behave the opposite of it. - /// - /// This set can be modified to add or remove exemptions. - /// - /// For example if collidable is true and an entity is in the exemptions set - /// then it will not collide with it. Similarly if collidable is false and an - /// entity is in this set then it will still collide with it. - /// - /// Note these exemptions are not (currently) persistent. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in those exemptions not being accurate for player - /// collisions. This method should therefore only be used to exempt - /// non-player entities. - /// - /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} - /// in combination with a {@link Scoreboard} and a {@link Team}. - pub fn collidable_exemptions( + /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. + /// This event may have been cancelled. + pub fn last_damage_cause( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + ) -> Result>, Box> + { + let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCollidableExemptions", + "getLastDamageCause", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Returns a unique and persistent id for this entity + pub fn unique_id( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns the value of the memory specified. + /// Gets the amount of ticks this entity has lived for. /// - /// Note that the value is null when the specific entity does not have that - /// value by default. - pub fn get_memory( - &self, - memory_key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) - }); + /// This is the equivalent to "age" in entities. + pub fn ticks_lived(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. May not be less than one + /// tick. + pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(value); let res = self.jni_ref().call_method( &self.jni_object(), - "getMemory", + "setTicksLived", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(res.l()?)) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the value of the memory specified. + /// Performs the specified {@link EntityEffect} for this entity. /// - /// Note that the value will not be persisted when the specific entity does - /// not have that value by default. - pub fn set_memory( + /// This will be viewable to all players near the entity. + /// + /// If the effect is not applicable to this class of entity, it will not play. + pub fn play_effect( &self, - memory_key: impl Into>, - memory_value: jni::objects::JObject<'mc>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); + let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Object(memory_value); let res = self.jni_ref().call_method( &self.jni_object(), - "setMemory", + "playEffect", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the {@link Sound} this entity will make when damaged. - pub fn hurt_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); + /// Get the type of the entity. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + }) } - /// Get the {@link Sound} this entity will make on death. - pub fn death_sound(&self) -> Result>, Box> { + /// Get the {@link Sound} this entity makes while swimming. + pub fn swim_sound(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Get the {@link Sound} this entity will make when falling from the given - /// height (in blocks). The sound will often differ between either a small - /// or a big fall damage sound if the height exceeds 4 blocks. - pub fn get_fall_damage_sound( - &self, - fall_height: i32, - ) -> Result, Box> { - let sig = String::from("(I)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Int(fall_height); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFallDamageSound", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the {@link Sound} this entity will make when falling from a small - /// height. - pub fn fall_damage_sound_small(&self) -> Result, Box> { + /// Get the {@link Sound} this entity makes when splashing in water. For most + /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_splash_sound(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSoundSmall", + "getSwimSplashSound", sig.as_str(), vec![], ); @@ -25950,13 +32392,15 @@ impl<'mc> LivingEntity<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the {@link Sound} this entity will make when falling from a large - /// height. - pub fn fall_damage_sound_big(&self) -> Result, Box> { + /// Get the {@link Sound} this entity makes when splashing in water at high + /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_high_speed_splash_sound( + &self, + ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSoundBig", + "getSwimHighSpeedSplashSound", sig.as_str(), vec![], ); @@ -25965,458 +32409,480 @@ impl<'mc> LivingEntity<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the {@link Sound} this entity will make when drinking the given - /// {@link ItemStack}. - pub fn get_drinking_sound( + /// Returns whether this entity is inside a vehicle. + pub fn is_inside_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Leave the current vehicle. If the entity is currently in a vehicle (and + /// is removed from it), true will be returned, otherwise false will be + /// returned. + pub fn leave_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the vehicle that this entity is inside. If there is no vehicle, + /// null will be returned. + pub fn vehicle( &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) - }); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets whether or not to display the mob's custom name client side. The + /// name will be displayed above the mob similarly to a player. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getDrinkingSound", + "setCustomNameVisible", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether or not the mob's custom name is displayed client side. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn is_custom_name_visible(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isCustomNameVisible", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Get the {@link Sound} this entity will make when eating the given - /// {@link ItemStack}. - pub fn get_eating_sound( - &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) - }); + /// Sets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(visible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getEatingSound", + "setVisibleByDefault", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns true if this entity can breathe underwater and will not take - /// suffocation damage when its air supply reaches zero. - pub fn can_breathe_underwater(&self) -> Result> { + /// Gets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn is_visible_by_default(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "canBreatheUnderwater", + "isVisibleByDefault", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. - pub fn category( + /// Get all players that are currently tracking this entity. + /// + /// 'Tracking' means that this entity has been sent to the player and that + /// they are receiving updates on its state. Note that the client's {@code + /// 'Entity Distance'} setting does not affect the range at which entities + /// are tracked. + pub fn tracked_by( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets whether the entity is invisible or not. - pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { + /// Sets whether the entity has a team colored (default: white) glow. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(invisible.into()); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvisible", + "setGlowing", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invisible or not. - pub fn is_invisible(&self) -> Result> { + /// Gets whether the entity is glowing or not. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn is_glowing(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the specified attribute instance from the object. This instance will - /// be backed directly to the object and any changes will be visible at once. - pub fn get_attribute( - &self, - attribute: impl Into>, - ) -> Result>, Box> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); + /// Sets whether the entity is invulnerable or not. + /// + /// When an entity is invulnerable it can only be damaged by players in + /// creative mode. + pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getAttribute", + "setInvulnerable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::attribute::AttributeInstance::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Deals the given amount of damage to this entity from a specified - /// {@link DamageSource}. - pub fn damage( - &self, - amount: f64, - damage_source: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(amount); - args.push(val_1); - if let Some(a) = damage_source { - sig += "Lorg/bukkit/damage/DamageSource;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "damage", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. - pub fn health(&self) -> Result> { - let sig = String::from("()D"); + /// Gets whether the entity is invulnerable or not. + pub fn is_invulnerable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets whether the entity is silent or not. + pub fn is_silent(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is - /// dead. - pub fn set_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); + /// Sets whether the entity is silent or not. + /// + /// When an entity is silent it will not produce any sound. + pub fn set_silent(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setHealth", + "setSilent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the entity's absorption amount. - pub fn absorption_amount(&self) -> Result> { - let sig = String::from("()D"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAbsorptionAmount", - sig.as_str(), - vec![], - ); + /// Returns whether gravity applies to this entity. + pub fn has_gravity(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Sets the entity's absorption amount. - /// - /// Note: The amount is capped to the value of - /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on - /// that attribute is currently unspecified and subject to change. - pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(amount); + /// Sets whether gravity applies to this entity. + pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gravity.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setAbsorptionAmount", + "setGravity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the maximum health this entity has. - pub fn max_health(&self) -> Result> { - let sig = String::from("()D"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); + /// Gets the period of time (in ticks) before this entity can use a portal. + pub fn portal_cooldown(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPortalCooldown", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.i()?) } - #[deprecated] - /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. - pub fn set_max_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); + /// Sets the period of time (in ticks) before this entity can use a portal. + pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(cooldown); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxHealth", + "setPortalCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Resets the max health to the original amount. - pub fn reset_max_health(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Launches a {@link Projectile} from the ProjectileSource with an - /// initial velocity. - pub fn launch_projectile( + /// Returns a set of tags for this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn scoreboard_tags( &self, - projectile: jni::objects::JClass<'mc>, - velocity: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/Class;"; - let val_1 = jni::objects::JValueGen::Object(projectile.into()); - args.push(val_1); - if let Some(a) = velocity { - sig += "Lorg/bukkit/util/Vector;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")LT;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getScoreboardTags", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for LivingEntity<'mc> { - fn into(self) -> crate::attribute::Attributable<'mc> { - crate::attribute::Attributable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting LivingEntity into crate::attribute::Attributable") - } -} -impl<'mc> Into> for LivingEntity<'mc> { - fn into(self) -> crate::entity::Damageable<'mc> { - crate::entity::Damageable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting LivingEntity into crate::entity::Damageable") - } -} -impl<'mc> Into> for LivingEntity<'mc> { - fn into(self) -> crate::projectiles::ProjectileSource<'mc> { - crate::projectiles::ProjectileSource::from_raw(&self.jni_ref(), self.1) - .expect("Error converting LivingEntity into crate::projectiles::ProjectileSource") - } -} -#[repr(C)] -pub struct TippedArrow<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for TippedArrow<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for TippedArrow<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate TippedArrow from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/TippedArrow")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a TippedArrow object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} - -impl<'mc> TippedArrow<'mc> { - #[deprecated] - /// Sets the underlying potion data - pub fn set_base_potion_data( + /// Add a tag to this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn add_scoreboard_tag( &self, - data: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/potion/PotionData;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) - }); + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setBasePotionData", + "addScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - #[deprecated] - /// Returns the potion data about the base potion - pub fn base_potion_data( + /// Removes a given tag from this entity. + pub fn remove_scoreboard_tag( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/potion/PotionData;"); + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "getBasePotionData", + "removeScoreboardTag", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::potion::PotionData::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Sets the underlying potion type - pub fn set_base_potion_type( + /// Returns the reaction of the entity when moved by a piston. + pub fn piston_move_reaction( &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/potion/PotionType;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setBasePotionType", + "getPistonMoveReaction", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the potion type about the base potion - pub fn base_potion_type( + /// Get the closest cardinal {@link BlockFace} direction an entity is + /// currently facing. + /// + /// This will not return any non-cardinal directions such as + /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// + /// {@link Hanging} entities will override this call and thus their behavior + /// may be different. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the entity's current pose. + /// Note that the pose is only updated at the end of a tick, so may be + /// inconsistent with other methods. eg {@link Player#isSneaking()} being + /// true does not imply the current pose will be {@link Pose#SNEAKING} + pub fn pose(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Pose;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the category of spawn to which this entity belongs. + pub fn spawn_category( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/potion/PotionType;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getBasePotionType", + "getSpawnCategory", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; + crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Checks if this entity has been spawned in a world. + /// + /// Entities not spawned in a world will not tick, be sent to players, or be + /// saved to the server files. + pub fn is_in_world(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get this entity as an NBT string. + /// + /// This string should not be relied upon as a serializable value. + pub fn as_string(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::potion::PotionType::from_raw( + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Crates an {@link EntitySnapshot} representing the current state of this entity. + pub fn create_snapshot( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntitySnapshot::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Gets the color of this arrow. - pub fn color(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Color;"); + /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// + /// Note: Players cannot be copied. + pub fn copy( + &self, + to: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = to { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Lorg/bukkit/entity/Entity;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "copy", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Color::from_raw(&self.jni_ref(), unsafe { + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + }) } - /// Sets the color of this arrow. Will be applied as a tint to its particles. - pub fn set_color( + /// Sets a metadata value in the implementing object's metadata store. + pub fn set_metadata( &self, - color: impl Into>, + metadata_key: impl Into, + new_metadata_value: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Color;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) + let sig = String::from("(Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setColor", + "setMetadata", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for the presence of custom potion effects. - pub fn has_custom_effects(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasCustomEffects", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets an immutable list containing all custom potion effects applied to - /// this arrow. - /// - /// Plugins should check that hasCustomEffects() returns true before calling - /// this method. - pub fn custom_effects( + /// Returns a list of previously set metadata values from the implementing + /// object's metadata store. + pub fn get_metadata( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + metadata_key: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "getCustomEffects", + "getMetadata", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); @@ -26424,147 +32890,181 @@ impl<'mc> TippedArrow<'mc> { let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); + new_vec.push(crate::metadata::MetadataValue::from_raw( + &self.jni_ref(), + obj, + )?); } Ok(new_vec) } - /// Adds a custom potion effect to this arrow. - pub fn add_custom_effect( + /// Tests to see whether the implementing object contains the given + /// metadata value in its metadata store. + pub fn has_metadata( &self, - effect: impl Into>, - overwrite: bool, + metadata_key: impl Into, ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffect;Z)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(effect.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Bool(overwrite.into()); + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "addCustomEffect", + "hasMetadata", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes a custom potion effect from this arrow. - pub fn remove_custom_effect( + /// Removes the given metadata value from the implementing object's + /// metadata store. + pub fn remove_metadata( &self, - val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + metadata_key: impl Into, + owning_plugin: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeCustomEffect", + "removeMetadata", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Checks for a specific custom potion effect type on this arrow. - pub fn has_custom_effect( + /// Sends this sender multiple messages + pub fn send_message( &self, - val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); + sender: impl Into>, + messages: std::option::Option>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/util/UUID;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) }); + args.push(val_1); + if let Some(a) = messages { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_2); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the name of this command sender + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gets the custom name on a mob or block. If there is no name this method + /// will return null. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn custom_name(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCustomName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Sets a custom name on a mob or block. This name will be used in death + /// messages and can be sent to the client as a nameplate over the mob. + /// + /// Setting the name to null or an empty string will clear it. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn set_custom_name( + &self, + name: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "hasCustomEffect", + "setCustomName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Removes all custom potion effects from this arrow. - pub fn clear_custom_effects(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + pub fn persistent_data_container( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); let res = self.jni_ref().call_method( &self.jni_object(), - "clearCustomEffects", + "getPersistentDataContainer", sig.as_str(), vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for TippedArrow<'mc> { - fn into(self) -> crate::entity::Arrow<'mc> { - crate::entity::Arrow::from_raw(&self.jni_ref(), self.1) - .expect("Error converting TippedArrow into crate::entity::Arrow") - } -} -#[repr(C)] -pub struct Silverfish<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Silverfish<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Silverfish<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Silverfish from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Silverfish")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Silverfish object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + let res = self.jni_ref().translate_error(res)?; + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> Silverfish<'mc> { pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Silverfish<'mc> { - fn into(self) -> crate::entity::Monster<'mc> { - crate::entity::Monster::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Silverfish into crate::entity::Monster") +impl<'mc> Into> for Damageable<'mc> { + fn into(self) -> crate::entity::Entity<'mc> { + crate::entity::Entity::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Damageable into crate::entity::Entity") } } #[repr(C)] -pub struct Frog<'mc>( +pub struct Camel<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Frog<'mc> { +impl<'mc> JNIRaw<'mc> for Camel<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -26572,18 +33072,18 @@ impl<'mc> JNIRaw<'mc> for Frog<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Frog<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Camel<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Frog from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Camel from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Frog")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Camel")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Frog object, got {}", + "Invalid argument passed. Expected a Camel object, got {}", name ) .into()) @@ -26593,59 +33093,48 @@ impl<'mc> JNIInstantiatable<'mc> for Frog<'mc> { } } -impl<'mc> Frog<'mc> { - /// Gets the tongue target of this frog. - pub fn tongue_target( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTongueTarget", sig.as_str(), vec![]); +impl<'mc> Camel<'mc> { + /// Gets whether this camel is dashing (sprinting). + pub fn is_dashing(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isDashing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Sets the tongue target of this frog. - pub fn set_tongue_target( - &self, - target: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) - }); + /// Sets whether this camel is dashing (sprinting). + pub fn set_dashing(&self, dashing: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(dashing.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setTongueTarget", + "setDashing", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the variant of this frog. - pub fn variant(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Frog/Variant;"); + #[deprecated] + /// Gets the horse's variant.A horse's variant defines its physical appearance and capabilities. Whether a horse is a regular horse, donkey, mule, or other kind of horse is determined using the variant. + pub fn variant(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Horse/Variant;"); let res = self.jni_ref() .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::FrogVariant::from_raw(&self.jni_ref(), unsafe { + crate::entity::HorseVariant::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Set the variant of this frog. + #[deprecated] + pub fn set_variant( &self, - variant: impl Into>, + variant: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Frog/Variant;)V"); + let sig = String::from("(Lorg/bukkit/entity/Horse/Variant;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(variant.into().jni_object().clone()) }); @@ -26658,142 +33147,128 @@ impl<'mc> Frog<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn breed_cause( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); + /// Gets the domestication level of this horse. + /// + /// A higher domestication level indicates that the horse is closer to + /// becoming tame. As the domestication level gets closer to the max + /// domestication level, the chance of the horse becoming tame increases. + pub fn domestication(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDomestication", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - /// Set the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn set_breed_cause( - &self, - uuid: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/UUID;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) - }); + /// Sets the domestication level of this horse. + /// + /// Setting the domestication level to a high value will increase the + /// horse's chances of becoming tame. + /// + /// Domestication level must be greater than zero and no greater than + /// the max domestication level of the horse, determined with + /// {@link #getMaxDomestication()} + pub fn set_domestication(&self, level: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(level); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreedCause", + "setDomestication", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get whether or not this entity is in love mode and will produce - /// offspring with another entity in love mode. Will return true if - /// and only if {@link #getLoveModeTicks()} is greater than 0. - pub fn is_love_mode(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the amount of ticks remaining for this entity in love mode. - /// If the entity is not in love mode, 0 will be returned. - pub fn love_mode_ticks(&self) -> Result> { + /// Gets the maximum domestication level of this horse. + /// + /// The higher this level is, the longer it will likely take + /// for the horse to be tamed. + pub fn max_domestication(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLoveModeTicks", + "getMaxDomestication", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Set the amount of ticks for which this entity should be in love mode. - /// Setting the love mode ticks to 600 is the equivalent of a player - /// feeding the entity their breeding item of choice. - pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Sets the maximum domestication level of this horse. + /// + /// Setting a higher max domestication will increase the amount of + /// domesticating (feeding, riding, etc.) necessary in order to tame it, + /// while setting a lower max value will have the opposite effect. + /// + /// Maximum domestication must be greater than zero. + pub fn set_max_domestication(&self, level: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + let val_1 = jni::objects::JValueGen::Int(level); let res = self.jni_ref().call_method( &self.jni_object(), - "setLoveModeTicks", + "setMaxDomestication", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check if the provided ItemStack is the correct item used for breeding - /// this entity.. - pub fn is_breed_item( - &self, - material: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); + /// Gets the jump strength of this horse. + /// + /// Jump strength defines how high the horse can jump. A higher jump strength + /// increases how high a jump will go. + pub fn jump_strength(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getJumpStrength", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Lock the age of the animal, setting this will prevent the animal from - /// maturing or getting ready for mating. - pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(lock.into()); + /// Sets the jump strength of this horse. + /// + /// A higher jump strength increases how high a jump will go. + /// Setting a jump strength to 0 will result in no jump. + /// You cannot set a jump strength to a value below 0 or + /// above 2. + pub fn set_jump_strength(&self, strength: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(strength); let res = self.jni_ref().call_method( &self.jni_object(), - "setAgeLock", + "setJumpStrength", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the current agelock. - pub fn age_lock(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Return the ability to breed of the animal. - pub fn can_breed(&self) -> Result> { + /// Gets whether the horse is currently grazing hay. + pub fn is_eating_haystack(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isEatingHaystack", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set breedability of the animal, if the animal is a baby and set to - /// breed it will instantly grow up. - pub fn set_breed(&self, breed: bool) -> Result<(), Box> { + /// Sets whether the horse is grazing hay. + pub fn set_eating_haystack( + &self, + eating_haystack: bool, + ) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(breed.into()); + let val_1 = jni::objects::JValueGen::Bool(eating_haystack.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreed", + "setEatingHaystack", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -26801,148 +33276,137 @@ impl<'mc> Frog<'mc> { Ok(()) } - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Frog<'mc> { - fn into(self) -> crate::entity::Animals<'mc> { - crate::entity::Animals::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Frog into crate::entity::Animals") + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/AbstractHorseInventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::AbstractHorseInventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -pub enum FrogVariant<'mc> {} -impl<'mc> std::fmt::Display for FrogVariant<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + /// Gets the vehicle's velocity. + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} - -impl<'mc> FrogVariant<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/Frog/Variant"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/Frog/Variant;", + /// Sets the vehicle's velocity in meters per tick. + pub fn set_velocity( + &self, + vel: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(vel.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVelocity", + sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct FrogVariantStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for FrogVariant<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for FrogVariant<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate FrogVariant from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Frog/Variant")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a FrogVariant object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> JNIRaw<'mc> for FrogVariantStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Check if this is tamed + /// + /// If something is tamed then a player can not tame it through normal + /// methods, even if it does not belong to anyone in particular. + pub fn is_tamed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isTamed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Sets if this has been tamed. Not necessary if the method setOwner has + /// been used, as it tames automatically. + /// + /// If something is tamed then a player can not tame it through normal + /// methods, even if it does not belong to anyone in particular. + pub fn set_tamed(&self, tame: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(tame.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTamed", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -impl<'mc> JNIInstantiatable<'mc> for FrogVariantStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate FrogVariantStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Frog/Variant")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a FrogVariantStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + /// Gets the current owning AnimalTamer + pub fn owner( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/AnimalTamer;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some(crate::entity::AnimalTamer::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } -} - -impl<'mc> FrogVariantStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Frog/Variant;"); - let cls = jni.find_class("org/bukkit/entity/Frog/Variant"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::FrogVariant::from_raw(&jni, obj) + /// Set this to be owned by given AnimalTamer. + /// + /// If the owner is not null, this will be tamed and will have any current + /// path it is following removed. If the owner is set to null, this will be + /// untamed, and the current owner removed. + pub fn set_owner( + &self, + tamer: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/AnimalTamer;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(tamer.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setOwner", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + /// Checks if this animal is sitting + pub fn is_sitting(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSitting", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) + } + /// Sets if this animal is sitting. Will remove any path that the animal + /// was following beforehand. + pub fn set_sitting(&self, sitting: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(sitting.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSitting", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -26950,13 +33414,25 @@ impl<'mc> FrogVariantStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for Camel<'mc> { + fn into(self) -> crate::entity::AbstractHorse<'mc> { + crate::entity::AbstractHorse::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Camel into crate::entity::AbstractHorse") + } +} +impl<'mc> Into> for Camel<'mc> { + fn into(self) -> crate::entity::Sittable<'mc> { + crate::entity::Sittable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Camel into crate::entity::Sittable") + } +} #[repr(C)] -pub struct Trident<'mc>( +pub struct Husk<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Trident<'mc> { +impl<'mc> JNIRaw<'mc> for Husk<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -26964,18 +33440,18 @@ impl<'mc> JNIRaw<'mc> for Trident<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Trident<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Husk<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Trident from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Husk from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Trident")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Husk")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Trident object, got {}", + "Invalid argument passed. Expected a Husk object, got {}", name ) .into()) @@ -26985,131 +33461,124 @@ impl<'mc> JNIInstantiatable<'mc> for Trident<'mc> { } } -impl<'mc> Trident<'mc> { - /// Gets the knockback strength for an arrow, which is the - /// {@link org.bukkit.enchantments.Enchantment#KNOCKBACK KnockBack} level - /// of the bow that shot it. - pub fn knockback_strength(&self) -> Result> { +impl<'mc> Husk<'mc> { + /// Get if this entity is in the process of converting to a Zombie as a + /// result of being underwater. + pub fn is_converting(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isConverting", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the amount of ticks until this entity will be converted to a Zombie + /// as a result of being underwater. + /// When this reaches 0, the entity will be converted. + pub fn conversion_time(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getKnockbackStrength", + "getConversionTime", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the knockback strength for an arrow. - pub fn set_knockback_strength( - &self, - knockback_strength: i32, - ) -> Result<(), Box> { + /// Sets the amount of ticks until this entity will be converted to a Zombie + /// as a result of being underwater. + /// When this reaches 0, the entity will be converted. A value of less than 0 + /// will stop the current conversion process without converting the current + /// entity. + pub fn set_conversion_time(&self, time: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(knockback_strength); + let val_1 = jni::objects::JValueGen::Int(time); let res = self.jni_ref().call_method( &self.jni_object(), - "setKnockbackStrength", + "setConversionTime", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the base amount of damage this arrow will do. - /// Defaults to 2.0 for a normal arrow with - /// 0.5 * (1 + power level) added for arrows fired from - /// enchanted bows. - pub fn damage(&self) -> Result> { - let sig = String::from("()D"); + #[deprecated] + /// Gets whether the zombie is a baby + pub fn is_baby(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getDamage", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isBaby", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Sets the base amount of damage this arrow will do. - pub fn set_damage(&self, damage: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(damage); + #[deprecated] + /// Sets whether the zombie is a baby + pub fn set_baby(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setDamage", + "setBaby", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the number of times this arrow can pierce through an entity. - pub fn pierce_level(&self) -> Result> { - let sig = String::from("()I"); + #[deprecated] + /// Gets whether the zombie is a villager + pub fn is_villager(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPierceLevel", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isVillager", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the number of times this arrow can pierce through an entity. - /// Must be between 0 and 127 times. - pub fn set_pierce_level(&self, pierce_level: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(pierce_level); + #[deprecated] + + pub fn set_villager(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setPierceLevel", + "setVillager", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether this arrow is critical. - /// - /// Critical arrows have increased damage and cause particle effects. - /// - /// Critical arrows generally occur when a player fully draws a bow before - /// firing. - pub fn is_critical(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCritical", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether or not this arrow should be critical. - pub fn set_critical(&self, critical: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(critical.into()); + #[deprecated] + + pub fn set_villager_profession( + &self, + profession: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Villager/Profession;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(profession.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCritical", + "setVillagerProfession", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether this arrow is in a block or not. - /// - /// Arrows in a block are motionless and may be picked up by players. - pub fn is_in_block(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInBlock", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the block to which this arrow is attached. - pub fn attached_block( + #[deprecated] + + pub fn villager_profession( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Villager/Profession;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getAttachedBlock", + "getVillagerProfession", sig.as_str(), vec![], ); @@ -27117,192 +33586,54 @@ impl<'mc> Trident<'mc> { if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::block::Block::from_raw( + Ok(Some(crate::entity::VillagerProfession::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Gets the current pickup status of this arrow. - pub fn pickup_status( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/AbstractArrow/PickupStatus;"); + /// Gets whether this zombie can break doors + pub fn can_break_doors(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPickupStatus", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::AbstractArrowPickupStatus::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the current pickup status of this arrow. - pub fn set_pickup_status( - &self, - status: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/AbstractArrow/PickupStatus;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(status.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPickupStatus", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets if this arrow was shot from a crossbow. - pub fn is_shot_from_crossbow(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isShotFromCrossbow", - sig.as_str(), - vec![], - ); + .call_method(&self.jni_object(), "canBreakDoors", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets if this arrow was shot from a crossbow. - pub fn set_shot_from_crossbow( - &self, - shot_from_crossbow: bool, - ) -> Result<(), Box> { + /// Sets whether this zombie can break doors + /// This will be ignored if the entity is a Drowned. Will also stop the action if + /// the entity is currently breaking a door. + pub fn set_can_break_doors(&self, flag: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(shot_from_crossbow.into()); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setShotFromCrossbow", + "setCanBreakDoors", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the ItemStack the thrown projectile will display. - pub fn item(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/inventory/ItemStack;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the display ItemStack for the thrown projectile. - pub fn set_item( - &self, - item: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setItem", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Retrieve the shooter of this projectile. - pub fn shooter( - &self, - ) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/projectiles/ProjectileSource;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getShooter", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::projectiles::ProjectileSource::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Set the shooter of this projectile. - pub fn set_shooter( - &self, - source: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/projectiles/ProjectileSource;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(source.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setShooter", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Determine if this projectile should bounce or not when it hits. - pub fn does_bounce(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "doesBounce", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Set whether or not this projectile should bounce or not when it hits something. - pub fn set_bounce(&self, does_bounce: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(does_bounce.into()); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setBounce", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Trident<'mc> { - fn into(self) -> crate::entity::AbstractArrow<'mc> { - crate::entity::AbstractArrow::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Trident into crate::entity::AbstractArrow") - } -} -impl<'mc> Into> for Trident<'mc> { - fn into(self) -> crate::entity::ThrowableProjectile<'mc> { - crate::entity::ThrowableProjectile::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Trident into crate::entity::ThrowableProjectile") +impl<'mc> Into> for Husk<'mc> { + fn into(self) -> crate::entity::Zombie<'mc> { + crate::entity::Zombie::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Husk into crate::entity::Zombie") } } #[repr(C)] -pub struct Sniffer<'mc>( +pub struct Witch<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Sniffer<'mc> { +impl<'mc> JNIRaw<'mc> for Witch<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -27310,18 +33641,18 @@ impl<'mc> JNIRaw<'mc> for Sniffer<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Sniffer<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Witch<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Sniffer from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Witch from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Sniffer")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Witch")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Sniffer object, got {}", + "Invalid argument passed. Expected a Witch object, got {}", name ) .into()) @@ -27331,1888 +33662,2210 @@ impl<'mc> JNIInstantiatable<'mc> for Sniffer<'mc> { } } -impl<'mc> Sniffer<'mc> { - /// Gets the locations explored by the sniffer. - /// - /// Note: the returned locations use sniffer's current world. - pub fn explored_locations( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); +impl<'mc> Witch<'mc> { + /// Gets whether the witch is drinking a potion + pub fn is_drinking_potion(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getExploredLocations", + "isDrinkingPotion", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::Location::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Remove a location of the explored locations. - /// - /// Note: the location must be in the sniffer's current world for this - /// method to have any effect. - pub fn remove_explored_location( - &self, - location: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Location;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removeExploredLocation", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.z()?) } - /// Add a location to the explored locations. - /// - /// Note: the location must be in the sniffer's current world for this - /// method to have any effect. - pub fn add_explored_location( + /// Set the {@link Raid} that this raider is participating in. + pub fn set_raid( &self, - location: impl Into>, + raid: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Location;)V"); + let sig = String::from("(Lorg/bukkit/Raid;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) + jni::objects::JObject::from_raw(raid.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "addExploredLocation", + "setRaid", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the current state of the sniffer. - pub fn state(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Sniffer/State;"); + /// Get the {@link Raid} that this raider is participating in, if any. + pub fn raid(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Raid;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getState", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::SnifferState::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Set a new state for the sniffer. - /// - /// This will also make the sniffer make the transition to the new state. - pub fn set_state( - &self, - state: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Sniffer/State;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(state.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setState", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Try to get a possible location where the sniffer can dig. - pub fn find_possible_dig_location( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "findPossibleDigLocation", - sig.as_str(), - vec![], - ); + .call_method(&self.jni_object(), "getRaid", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + Ok(Some(crate::Raid::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) })?)) } - /// Gets whether the sniffer can dig in the current {@link Location} below - /// its head. - pub fn can_dig(&self) -> Result> { - let sig = String::from("()Z"); + /// Get the raid wave that this raider spawned as part of. + pub fn wave(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "canDig", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getWave", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Get the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn breed_cause( + /// Set the raid wave that this raider was spawned as part of. + pub fn set_wave(&self, wave: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(wave); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setWave", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the block the raider is targeting to patrol. + pub fn patrol_target( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/UUID;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPatrolTarget", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( + Ok(Some(crate::block::Block::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) - } - /// Set the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn set_breed_cause( + } + /// Sets the block the raider is targeting to patrol. + pub fn set_patrol_target( &self, - uuid: impl Into>, + block: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/UUID;)V"); + let sig = String::from("(Lorg/bukkit/block/Block;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) + jni::objects::JObject::from_raw(block.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreedCause", + "setPatrolTarget", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get whether or not this entity is in love mode and will produce - /// offspring with another entity in love mode. Will return true if - /// and only if {@link #getLoveModeTicks()} is greater than 0. - pub fn is_love_mode(&self) -> Result> { + /// Gets whether this entity is a patrol leader. + pub fn is_patrol_leader(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isPatrolLeader", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get the amount of ticks remaining for this entity in love mode. - /// If the entity is not in love mode, 0 will be returned. - pub fn love_mode_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Sets whether this entity is a patrol leader. + pub fn set_patrol_leader(&self, leader: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(leader.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getLoveModeTicks", + "setPatrolLeader", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether this mob can join an active raid. + pub fn is_can_join_raid(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCanJoinRaid", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the amount of ticks for which this entity should be in love mode. - /// Setting the love mode ticks to 600 is the equivalent of a player - /// feeding the entity their breeding item of choice. - pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets whether this mob can join an active raid. + pub fn set_can_join_raid(&self, join: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(join.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLoveModeTicks", + "setCanJoinRaid", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check if the provided ItemStack is the correct item used for breeding - /// this entity.. - pub fn is_breed_item( - &self, - material: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); + /// Get the amount of ticks that this mob has exited the bounds of a village + /// as a raid participant. + /// + /// This value is increased only when the mob has had no action for 2,400 ticks + /// (according to {@link #getNoActionTicks()}). Once both the no action ticks have + /// reached that value and the ticks outside a raid exceeds 30, the mob will be + /// expelled from the raid. + pub fn ticks_outside_raid(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTicksOutsideRaid", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Lock the age of the animal, setting this will prevent the animal from - /// maturing or getting ready for mating. - pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(lock.into()); + /// Set the amount of ticks that this mob has exited the bounds of a village + /// as a raid participant. + /// + /// This value is considered only when the mob has had no action for 2,400 ticks + /// (according to {@link #getNoActionTicks()}). Once both the no action ticks have + /// reached that value and the ticks outside a raid exceeds 30, the mob will be + /// expelled from the raid. + pub fn set_ticks_outside_raid(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setAgeLock", + "setTicksOutsideRaid", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the current agelock. - pub fn age_lock(&self) -> Result> { + /// Check whether or not this raider is celebrating a raid victory. + pub fn is_celebrating(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Return the ability to breed of the animal. - pub fn can_breed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCelebrating", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set breedability of the animal, if the animal is a baby and set to - /// breed it will instantly grow up. - pub fn set_breed(&self, breed: bool) -> Result<(), Box> { + /// Set whether or not this mob is celebrating a raid victory. + pub fn set_celebrating(&self, celebrating: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(breed.into()); + let val_1 = jni::objects::JValueGen::Bool(celebrating.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreed", + "setCelebrating", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } + /// Get the {@link Sound} this entity will play when celebrating. + pub fn celebration_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCelebrationSound", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Sniffer<'mc> { - fn into(self) -> crate::entity::Animals<'mc> { - crate::entity::Animals::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Sniffer into crate::entity::Animals") - } -} -pub enum SnifferState<'mc> {} -impl<'mc> std::fmt::Display for SnifferState<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> SnifferState<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/Sniffer/State"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/Sniffer/State;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } +impl<'mc> Into> for Witch<'mc> { + fn into(self) -> crate::entity::Raider<'mc> { + crate::entity::Raider::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Witch into crate::entity::Raider") } } - #[repr(C)] -pub struct SnifferStateStruct<'mc>( +pub struct FallingBlock<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for SnifferState<'mc> { +impl<'mc> JNIRaw<'mc> for FallingBlock<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + self.0.clone() } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for SnifferState<'mc> { +impl<'mc> JNIInstantiatable<'mc> for FallingBlock<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate SnifferState from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate FallingBlock from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Sniffer/State")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/FallingBlock")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SnifferState object, got {}", + "Invalid argument passed. Expected a FallingBlock object, got {}", name ) .into()) } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + Ok(Self(env.clone(), obj)) } } } -impl<'mc> JNIRaw<'mc> for SnifferStateStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() +impl<'mc> FallingBlock<'mc> { + #[deprecated] + /// Get the Material of the falling block + pub fn material(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaterial", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Get the data for the falling block + pub fn block_data( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBlockData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> JNIInstantiatable<'mc> for SnifferStateStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate SnifferStateStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Sniffer/State")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a SnifferStateStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + /// Get if the falling block will break into an item if it cannot be placed. + /// + /// Note that if {@link #getCancelDrop()} is {@code true}, the falling block + /// will not drop an item regardless of whether or not the returned value is + /// {@code true}. + pub fn drop_item(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDropItem", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set if the falling block will break into an item if it cannot be placed. + /// + /// Note that if {@link #getCancelDrop()} is {@code true}, the falling block + /// will not drop an item regardless of whether or not the value is set to + /// {@code true}. + pub fn set_drop_item(&self, drop: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(drop.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDropItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get if the falling block will not become a block upon landing and not drop + /// an item. + /// + /// Unlike {@link #getDropItem()}, this property will prevent the block from + /// forming into a block when it lands, causing it to disappear. If this property + /// is true and {@link #getDropItem()} is true, an item will NOT + /// be dropped. + pub fn cancel_drop(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCancelDrop", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get if the falling block will not become a block upon landing and not drop + /// an item. + /// + /// Unlike {@link #setDropItem(boolean)}, this property will prevent the block + /// from forming into a block when it lands, causing it to disappear. If this + /// property is true and {@link #getDropItem()} is true, an item will + /// NOT be dropped. + pub fn set_cancel_drop(&self, cancel_drop: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel_drop.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelDrop", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the HurtEntities state of this block. + pub fn can_hurt_entities(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "canHurtEntities", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set the HurtEntities state of this block. + pub fn set_hurt_entities(&self, hurt_entities: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(hurt_entities.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setHurtEntities", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the amount of damage inflicted upon entities multiplied by the distance + /// that the block had fallen when this falling block lands on them. + pub fn damage_per_block(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDamagePerBlock", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Set the amount of damage inflicted upon entities multiplied by the distance + /// that the block had fallen when this falling block lands on them. + /// + /// If {@code damage} is non-zero, this method will automatically call + /// {@link #setHurtEntities(boolean) setHurtEntities(true)}. + pub fn set_damage_per_block(&self, damage: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(damage); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDamagePerBlock", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the maximum amount of damage that can be inflicted upon entities when + /// this falling block lands on them. + pub fn max_damage(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxDamage", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the maximum amount of damage that can be inflicted upon entities when + /// this falling block lands on them. + /// + /// If {@code damage} is non-zero, this method will automatically call + /// {@link #setHurtEntities(boolean) setHurtEntities(true)}. + pub fn set_max_damage(&self, damage: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(damage); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaxDamage", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Stores the entity's current position in the provided Location object. + /// + /// If the provided Location is null this method does nothing and returns + /// null. + pub fn get_location( + &self, + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLocation", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } -} - -impl<'mc> SnifferStateStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Sniffer/State;"); - let cls = jni.find_class("org/bukkit/entity/Sniffer/State"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::SnifferState::from_raw(&jni, obj) + /// Sets this entity's velocity in meters per tick + pub fn set_velocity( + &self, + velocity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVelocity", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + /// Gets this entity's current velocity + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -#[repr(C)] -pub struct Painting<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Painting<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Gets the entity's height + pub fn height(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets the entity's width + pub fn width(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the entity's current bounding box. + /// + /// The returned bounding box reflects the entity's current location and + /// size. + pub fn bounding_box( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> JNIInstantiatable<'mc> for Painting<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Painting from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Painting")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Painting object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Returns true if the entity is supported by a block. This value is a + /// state updated by the server and is not recalculated unless the entity + /// moves. + pub fn is_on_ground(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} - -impl<'mc> Painting<'mc> { - /// Get the art on this painting - pub fn art(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Art;"); + /// Returns true if the entity is in water. + pub fn is_in_water(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getArt", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Art::from_raw(&self.jni_ref(), unsafe { + Ok(res.z()?) + } + /// Gets the current world this entity resides in + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::World::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Set the art on this painting - pub fn set_art( + /// Sets the entity's rotation. + /// + /// Note that if the entity is affected by AI, it may override this rotation. + pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { + let sig = String::from("(FF)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); + let val_2 = jni::objects::JValueGen::Float(pitch); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRotation", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Teleports this entity to the given location. If this entity is riding a + /// vehicle, it will be dismounted prior to teleportation. + pub fn teleport( &self, - art: impl Into>, - force: std::option::Option, + location: impl Into>, + cause: std::option::Option< + impl Into>, + >, ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Art;"; + sig += "Lorg/bukkit/Location;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(art.into().jni_object().clone()) + jni::objects::JObject::from_raw(location.into().jni_object().clone()) }); args.push(val_1); - if let Some(a) = force { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); + if let Some(a) = cause { + sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); args.push(val_2); } sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "setArt", sig.as_str(), args); + .call_method(&self.jni_object(), "teleport", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the direction of the hanging entity, potentially overriding rules - /// of placement. Note that if the result is not valid the object would - /// normally drop as an item. - pub fn set_facing_direction( + /// Returns a list of entities within a bounding box centered around this + /// entity + pub fn get_nearby_entities( &self, - face: impl Into>, - force: bool, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;Z)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Bool(force.into()); + x: f64, + y: f64, + z: f64, + ) -> Result>, Box> { + let sig = String::from("(DDD)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Double(x); + let val_2 = jni::objects::JValueGen::Double(y); + let val_3 = jni::objects::JValueGen::Double(z); let res = self.jni_ref().call_method( &self.jni_object(), - "setFacingDirection", + "getNearbyEntities", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), ], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } -} -impl<'mc> Into> for Painting<'mc> { - fn into(self) -> crate::entity::Hanging<'mc> { - crate::entity::Hanging::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Painting into crate::entity::Hanging") + /// Returns a unique id for this entity + pub fn entity_id(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} -#[repr(C)] -pub struct Enemy<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Enemy<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Returns the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Returns the entity's maximum fire ticks. + pub fn max_fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} -impl<'mc> JNIInstantiatable<'mc> for Enemy<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Enemy from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Enemy")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Enemy object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Sets the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFireTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> Enemy<'mc> { - /// Gets the height of the living entity's eyes above its Location. - pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { - let sig = String::from("(Z)D"); - let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); + /// Sets if the entity has visual fire (it will always appear to be on fire). + pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getEyeHeight", + "setVisualFire", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the entity has visual fire (it will always appear to be on fire). + pub fn is_visual_fire(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Get a Location detailing the current eye position of the living entity. - pub fn eye_location(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); + /// Returns the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { + Ok(res.i()?) + } + /// Returns the entity's maximum freeze ticks (amount of ticks before it will + /// be fully frozen) + pub fn max_freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaxFreezeTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFreezeTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the entity is fully frozen (it has been in powdered snow for max + /// freeze ticks). + pub fn is_frozen(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Mark the entity's removal. + pub fn remove(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns true if this entity has been marked for removal. + pub fn is_dead(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns false if the entity has died, been despawned for some other + /// reason, or has not been added to the world. + pub fn is_valid(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the {@link Server} that contains this Entity + pub fn server(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Server;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Server::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets all blocks along the living entity's line of sight. + /// Returns true if the entity gets persisted. /// - /// This list contains all blocks from the living entity's eye position to - /// target inclusive. This method considers all blocks as 1x1x1 in size. - pub fn get_line_of_sight( + /// By default all entities are persistent. An entity will also not get + /// persisted, if it is riding an entity that is not persistent. + /// + /// The persistent flag on players controls whether or not to save their + /// playerdata file when they quit. If a player is directly or indirectly + /// riding a non-persistent entity, the vehicle at the root and all its + /// passengers won't get persisted. + /// + /// This should not be confused with + /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls + /// despawning of living entities. + pub fn is_persistent(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether or not the entity gets persisted. + pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(persistent.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPersistent", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. + pub fn passenger( &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { - let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + #[deprecated] + /// Set the passenger of a vehicle. + pub fn set_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "getLineOfSight", + "setPassenger", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets a list of passengers of this vehicle. + /// + /// The returned list will not be directly linked to the entity's current + /// passengers, and no guarantees are made as to its mutability. + pub fn passengers( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); } Ok(new_vec) } - /// Gets the block that the living entity has targeted. - /// - /// This method considers all blocks as 1x1x1 in size. To take exact block - /// collision shapes into account, see {@link #getTargetBlockExact(int, - /// FluidCollisionMode)}. - pub fn get_target_block( + /// Add a passenger to the vehicle. + pub fn add_passenger( &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result, Box> { - let sig = String::from("(Ljava/util/Set;I)Lorg/bukkit/block/Block;"); + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "getTargetBlock", + "addPassenger", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Gets the last two blocks along the living entity's line of sight. - /// - /// The target block will be the last block in the list. This method - /// considers all blocks as 1x1x1 in size. - pub fn get_last_two_target_blocks( + /// Remove a passenger from the vehicle. + pub fn remove_passenger( &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { - let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removePassenger", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Check if a vehicle has passengers. + pub fn is_empty(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Eject any passenger. + pub fn eject(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the distance this entity has fallen + pub fn fall_distance(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the fall distance for this entity + pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(distance); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFallDistance", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Record the last {@link EntityDamageEvent} inflicted on this entity + pub fn set_last_damage_cause( + &self, + event: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(event.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "getLastTwoTargetBlocks", + "setLastDamageCause", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the block that the living entity has targeted. - /// - /// This takes the blocks' precise collision shapes into account. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn get_target_block_exact( + /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. + /// This event may have been cancelled. + pub fn last_damage_cause( &self, - max_distance: i32, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(max_distance); - args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/block/Block;"; + ) -> Result>, Box> + { + let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getTargetBlockExact", + "getLastDamageCause", sig.as_str(), - args, + vec![], ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::block::Block::from_raw( + Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Performs a ray trace that provides information on the targeted block. - /// - /// This takes the blocks' precise collision shapes into account. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn ray_trace_blocks( + /// Returns a unique and persistent id for this entity + pub fn unique_id( &self, - max_distance: f64, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(max_distance); - args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/util/RayTraceResult;"; + ) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::util::RayTraceResult::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the amount of air that the living entity has remaining, in - /// ticks. - pub fn remaining_air(&self) -> Result> { + /// Gets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. + pub fn ticks_lived(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the amount of air that the living entity has remaining, in ticks. - pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { + /// Sets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. May not be less than one + /// tick. + pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + let val_1 = jni::objects::JValueGen::Int(value); let res = self.jni_ref().call_method( &self.jni_object(), - "setRemainingAir", + "setTicksLived", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the maximum amount of air the living entity can have, in ticks. - pub fn maximum_air(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the maximum amount of air the living entity can have, in ticks. - pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Performs the specified {@link EntityEffect} for this entity. + /// + /// This will be viewable to all players near the entity. + /// + /// If the effect is not applicable to this class of entity, it will not play. + pub fn play_effect( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaximumAir", + "playEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the item that the player is using (eating food, drawing back a bow, - /// blocking, etc.) - pub fn item_in_use( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + /// Get the type of the entity. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes while swimming. + pub fn swim_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the number of ticks remaining for the current item's usage. - pub fn item_in_use_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Get the {@link Sound} this entity makes when splashing in water. For most + /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_splash_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getItemInUseTicks", + "getSwimSplashSound", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the number of ticks that remain for the current item's usage. - /// Applies to items that take time to use, like eating food, drawing a bow, - /// or throwing a trident. - pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setItemInUseTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the time in ticks until the next arrow leaves the entity's body. - pub fn arrow_cooldown(&self) -> Result> { - let sig = String::from("()I"); + /// Get the {@link Sound} this entity makes when splashing in water at high + /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_high_speed_splash_sound( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getArrowCooldown", + "getSwimHighSpeedSplashSound", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the time in ticks until the next arrow leaves the entity's body. - pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setArrowCooldown", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Returns whether this entity is inside a vehicle. + pub fn is_inside_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the amount of arrows in an entity's body. - pub fn arrows_in_body(&self) -> Result> { - let sig = String::from("()I"); + /// Leave the current vehicle. If the entity is currently in a vehicle (and + /// is removed from it), true will be returned, otherwise false will be + /// returned. + pub fn leave_vehicle(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the amount of arrows in the entity's body. - pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(count); + /// Get the vehicle that this entity is inside. If there is no vehicle, + /// null will be returned. + pub fn vehicle( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets whether or not to display the mob's custom name client side. The + /// name will be displayed above the mob similarly to a player. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setArrowsInBody", + "setCustomNameVisible", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's current maximum no damage ticks. + /// Gets whether or not the mob's custom name is displayed client side. /// - /// This is the maximum duration in which the living entity will not take - /// damage. - pub fn maximum_no_damage_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// This value has no effect on players, they will always display their + /// name. + pub fn is_custom_name_visible(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getMaximumNoDamageTicks", + "isCustomNameVisible", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the living entity's current maximum no damage ticks. - pub fn set_maximum_no_damage_ticks( - &self, - ticks: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaximumNoDamageTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns the living entity's last damage taken in the current no damage - /// ticks time. - /// - /// Only damage higher than this amount will further damage the living - /// entity. - pub fn last_damage(&self) -> Result> { - let sig = String::from("()D"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Sets the damage dealt within the current no damage ticks time period. - pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(damage); + /// Sets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(visible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDamage", + "setVisibleByDefault", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's current no damage ticks. - pub fn no_damage_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Gets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn is_visible_by_default(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getNoDamageTicks", + "isVisibleByDefault", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the living entity's current no damage ticks. - pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Get all players that are currently tracking this entity. + /// + /// 'Tracking' means that this entity has been sent to the player and that + /// they are receiving updates on its state. Note that the client's {@code + /// 'Entity Distance'} setting does not affect the range at which entities + /// are tracked. + pub fn tracked_by( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets whether the entity has a team colored (default: white) glow. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setNoDamageTicks", + "setGlowing", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the ticks that this entity has performed no action. - /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn no_action_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getNoActionTicks", - sig.as_str(), - vec![], - ); + /// Gets whether the entity is glowing or not. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn is_glowing(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the ticks that this entity has performed no action. + /// Sets whether the entity is invulnerable or not. /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// When an entity is invulnerable it can only be damaged by players in + /// creative mode. + pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setNoActionTicks", + "setInvulnerable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the player identified as the killer of the living entity. - /// - /// May be null. - pub fn killer(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Player;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Player::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - #[deprecated] - /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. - pub fn add_potion_effect( - &self, - effect: impl Into>, - force: std::option::Option, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/potion/PotionEffect;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(effect.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = force { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")Z"; + /// Gets whether the entity is invulnerable or not. + pub fn is_invulnerable(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); + .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns whether the living entity already has an existing effect of - /// the given {@link PotionEffectType} applied to it. - pub fn has_potion_effect( - &self, - val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Gets whether the entity is silent or not. + pub fn is_silent(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the entity is silent or not. + /// + /// When an entity is silent it will not produce any sound. + pub fn set_silent(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "hasPotionEffect", + "setSilent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns the active {@link PotionEffect} of the specified type. - /// - /// If the effect is not present on the entity then null will be returned. - pub fn get_potion_effect( - &self, - val_type: impl Into>, - ) -> Result>, Box> { - let sig = - String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Returns whether gravity applies to this entity. + pub fn has_gravity(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether gravity applies to this entity. + pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gravity.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getPotionEffect", + "setGravity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the period of time (in ticks) before this entity can use a portal. + pub fn portal_cooldown(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPortalCooldown", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::potion::PotionEffect::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - /// Removes any effects present of the given {@link PotionEffectType}. - pub fn remove_potion_effect( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Sets the period of time (in ticks) before this entity can use a portal. + pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(cooldown); let res = self.jni_ref().call_method( &self.jni_object(), - "removePotionEffect", + "setPortalCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns all currently active {@link PotionEffect}s on the living - /// entity. - pub fn active_potion_effects( + /// Returns a set of tags for this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn scoreboard_tags( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getActivePotionEffects", + "getScoreboardTags", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Checks whether the living entity has block line of sight to another. + /// Add a tag to this entity. /// - /// This uses the same algorithm that hostile mobs use to find the closest - /// player. - pub fn has_line_of_sight( + /// Entities can have no more than 1024 tags. + pub fn add_scoreboard_tag( &self, - other: impl Into>, + tag: impl Into, ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) - }); + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "hasLineOfSight", + "addScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns if the living entity despawns when away from players or not. - /// - /// By default, animals are not removed while other mobs are. - pub fn remove_when_far_away(&self) -> Result> { - let sig = String::from("()Z"); + /// Removes a given tag from this entity. + pub fn remove_scoreboard_tag( + &self, + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "getRemoveWhenFarAway", + "removeScoreboardTag", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not the living entity despawns when away from players - /// or not. - pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(remove.into()); + /// Returns the reaction of the entity when moved by a piston. + pub fn piston_move_reaction( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setRemoveWhenFarAway", + "getPistonMoveReaction", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the inventory with the equipment worn by the living entity. - pub fn equipment( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); + /// Get the closest cardinal {@link BlockFace} direction an entity is + /// currently facing. + /// + /// This will not return any non-cardinal directions such as + /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// + /// {@link Hanging} entities will override this call and thus their behavior + /// may be different. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::EntityEquipment::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets whether or not the living entity can pick up items. - pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(pickup.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCanPickupItems", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Gets the entity's current pose. + /// Note that the pose is only updated at the end of a tick, so may be + /// inconsistent with other methods. eg {@link Player#isSneaking()} being + /// true does not imply the current pose will be {@link Pose#SNEAKING} + pub fn pose(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Pose;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets if the living entity can pick up items. - pub fn can_pickup_items(&self) -> Result> { - let sig = String::from("()Z"); + /// Get the category of spawn to which this entity belongs. + pub fn spawn_category( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCanPickupItems", + "getSpawnCategory", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns whether the entity is currently leashed. - pub fn is_leashed(&self) -> Result> { + /// Checks if this entity has been spawned in a world. + /// + /// Entities not spawned in a world will not tick, be sent to players, or be + /// saved to the server files. + pub fn is_in_world(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the entity that is currently leading this entity. - pub fn leash_holder(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + /// Get this entity as an NBT string. + /// + /// This string should not be relied upon as a serializable value. + pub fn as_string(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Crates an {@link EntitySnapshot} representing the current state of this entity. + pub fn create_snapshot( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntitySnapshot::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// + /// Note: Players cannot be copied. + pub fn copy( + &self, + to: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = to { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Lorg/bukkit/entity/Entity;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the leash on this entity to be held by the supplied entity. - /// - /// This method has no effect on EnderDragons, Withers, Players, or Bats. - /// Non-living entities excluding leashes will not persist as leash - /// holders. - pub fn set_leash_holder( + /// Sets a metadata value in the implementing object's metadata store. + pub fn set_metadata( &self, - holder: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(holder.into().jni_object().clone()) + metadata_key: impl Into, + new_metadata_value: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLeashHolder", + "setMetadata", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns a list of previously set metadata values from the implementing + /// object's metadata store. + pub fn get_metadata( + &self, + metadata_key: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMetadata", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::metadata::MetadataValue::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(new_vec) } - /// Checks to see if an entity is gliding, such as using an Elytra. - pub fn is_gliding(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); + /// Tests to see whether the implementing object contains the given + /// metadata value in its metadata store. + pub fn has_metadata( + &self, + metadata_key: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasMetadata", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Makes entity start or stop gliding. This will work even if an Elytra - /// is not equipped, but will be reverted by the server immediately after - /// unless an event-cancelling mechanism is put in place. - pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gliding.into()); + /// Removes the given metadata value from the implementing object's + /// metadata store. + pub fn remove_metadata( + &self, + metadata_key: impl Into, + owning_plugin: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setGliding", + "removeMetadata", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks to see if an entity is swimming. - pub fn is_swimming(&self) -> Result> { - let sig = String::from("()Z"); + /// Sends this sender multiple messages + pub fn send_message( + &self, + sender: impl Into>, + messages: std::option::Option>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/util/UUID;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = messages { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_2); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the name of this command sender + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gets the custom name on a mob or block. If there is no name this method + /// will return null. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn custom_name(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCustomName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Makes entity start or stop swimming. - /// This may have unexpected results if the entity is not in water. - pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(swimming.into()); + /// Sets a custom name on a mob or block. This name will be used in death + /// messages and can be sent to the client as a nameplate over the mob. + /// + /// Setting the name to null or an empty string will clear it. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn set_custom_name( + &self, + name: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setSwimming", + "setCustomName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks to see if an entity is currently using the Riptide enchantment. - pub fn is_riptiding(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + pub fn persistent_data_container( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPersistentDataContainer", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns whether this entity is slumbering. - pub fn is_sleeping(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for FallingBlock<'mc> { + fn into(self) -> crate::entity::Entity<'mc> { + crate::entity::Entity::from_raw(&self.jni_ref(), self.1) + .expect("Error converting FallingBlock into crate::entity::Entity") + } +} +#[repr(C)] +pub struct Creeper<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Creeper<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Creeper<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Creeper from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Creeper")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Creeper object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } - /// Gets if the entity is climbing. - pub fn is_climbing(&self) -> Result> { +} + +impl<'mc> Creeper<'mc> { + /// Checks if this Creeper is powered (Electrocuted) + pub fn is_powered(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether an entity will have AI. - /// The entity will be completely unable to move if it has no AI. - pub fn set_ai(&self, ai: bool) -> Result<(), Box> { + /// Sets the Powered status of this Creeper + pub fn set_powered(&self, value: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(ai.into()); + let val_1 = jni::objects::JValueGen::Bool(value.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setAI", + "setPowered", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks whether an entity has AI. - /// The entity will be completely unable to move if it has no AI. - pub fn has_ai(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Makes this entity attack the given entity with a melee attack. - /// Attack damage is calculated by the server from the attributes and - /// equipment of this mob, and knockback is applied to {@code target} as - /// appropriate. - pub fn attack( - &self, - target: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) - }); + /// Set the maximum fuse ticks for this Creeper, where the maximum ticks + /// is the amount of time in which a creeper is allowed to be in the + /// primed state before exploding. + pub fn set_max_fuse_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "attack", + "setMaxFuseTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Makes this entity swing their main hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their main hand. - pub fn swing_main_hand(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Makes this entity swing their off hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their off hand. - pub fn swing_off_hand(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Get the maximum fuse ticks for this Creeper, where the maximum ticks + /// is the amount of time in which a creeper is allowed to be in the + /// primed state before exploding. + pub fn max_fuse_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getMaxFuseTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Makes this entity flash red as if they were damaged. - pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); + /// Set the fuse ticks for this Creeper, where the ticks is the amount of + /// time in which a creeper has been in the primed state. + pub fn set_fuse_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "playHurtAnimation", + "setFuseTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Set if this entity will be subject to collisions with other entities. - /// - /// Exemptions to this rule can be managed with - /// {@link #getCollidableExemptions()} - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not working for player collisions. This - /// method should therefore only be used to set the collision status of - /// non-player entities. - /// - /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in - /// combination with a {@link Scoreboard} and a {@link Team}. - pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(collidable.into()); + /// Get the maximum fuse ticks for this Creeper, where the ticks is the + /// amount of time in which a creeper has been in the primed state. + pub fn fuse_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFuseTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the explosion radius in which this Creeper's explosion will affect. + pub fn set_explosion_radius(&self, radius: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(radius); let res = self.jni_ref().call_method( &self.jni_object(), - "setCollidable", + "setExplosionRadius", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if this entity is subject to collisions with other entities. - /// - /// Some entities might be exempted from the collidable rule of this entity. - /// Use {@link #getCollidableExemptions()} to get these. - /// - /// Please note that this method returns only the custom collidable state, - /// not whether the entity is non-collidable for other reasons such as being - /// dead. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not being accurate for player collisions. - /// This method should therefore only be used to check the collision status - /// of non-player entities. - /// - /// To check the collision behavior for a player, use - /// {@link Team.Option#COLLISION_RULE} in combination with a - /// {@link Scoreboard} and a {@link Team}. - pub fn is_collidable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets a mutable set of UUIDs of the entities which are exempt from the - /// entity's collidable rule and which's collision with this entity will - /// behave the opposite of it. - /// - /// This set can be modified to add or remove exemptions. - /// - /// For example if collidable is true and an entity is in the exemptions set - /// then it will not collide with it. Similarly if collidable is false and an - /// entity is in this set then it will still collide with it. - /// - /// Note these exemptions are not (currently) persistent. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in those exemptions not being accurate for player - /// collisions. This method should therefore only be used to exempt - /// non-player entities. - /// - /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} - /// in combination with a {@link Scoreboard} and a {@link Team}. - pub fn collidable_exemptions( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Get the explosion radius in which this Creeper's explosion will affect. + pub fn explosion_radius(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCollidableExemptions", + "getExplosionRadius", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Returns the value of the memory specified. + /// Makes this Creeper explode instantly. /// - /// Note that the value is null when the specific entity does not have that - /// value by default. - pub fn get_memory( - &self, - memory_key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMemory", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(res.l()?)) + /// The resulting explosion can be cancelled by an + /// {@link org.bukkit.event.entity.ExplosionPrimeEvent} and obeys the mob + /// griefing gamerule. + pub fn explode(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "explode", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the value of the memory specified. + /// Ignites this Creeper, beginning its fuse. /// - /// Note that the value will not be persisted when the specific entity does - /// not have that value by default. - pub fn set_memory( + /// The amount of time the Creeper takes to explode will depend on what + /// {@link #setMaxFuseTicks} is set as. + /// + /// The resulting explosion can be cancelled by an + /// {@link org.bukkit.event.entity.ExplosionPrimeEvent} and obeys the mob + /// griefing gamerule. + pub fn ignite( &self, - memory_key: impl Into>, - memory_value: jni::objects::JObject<'mc>, + entity: std::option::Option>>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(memory_value); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMemory", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = entity { + sig += "Lorg/bukkit/entity/Entity;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "ignite", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the {@link Sound} this entity will make when damaged. - pub fn hurt_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Gets the entity which ignited the creeper, if available. + pub fn igniter( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getIgniter", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Get the {@link Sound} this entity will make on death. - pub fn death_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Get the {@link Sound} this entity will make when falling from the given - /// height (in blocks). The sound will often differ between either a small - /// or a big fall damage sound if the height exceeds 4 blocks. - pub fn get_fall_damage_sound( - &self, - fall_height: i32, - ) -> Result, Box> { - let sig = String::from("(I)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Int(fall_height); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFallDamageSound", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} +impl<'mc> Into> for Creeper<'mc> { + fn into(self) -> crate::entity::Monster<'mc> { + crate::entity::Monster::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Creeper into crate::entity::Monster") } - /// Get the {@link Sound} this entity will make when falling from a small - /// height. - pub fn fall_damage_sound_small(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFallDamageSoundSmall", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} +#[repr(C)] +pub struct Raider<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Raider<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Get the {@link Sound} this entity will make when falling from a large - /// height. - pub fn fall_damage_sound_big(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFallDamageSoundBig", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Get the {@link Sound} this entity will make when drinking the given - /// {@link ItemStack}. - pub fn get_drinking_sound( +} +impl<'mc> JNIInstantiatable<'mc> for Raider<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Raider from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Raider")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Raider object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Raider<'mc> { + /// Set the {@link Raid} that this raider is participating in. + pub fn set_raid( &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + raid: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Raid;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + jni::objects::JObject::from_raw(raid.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getDrinkingSound", + "setRaid", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the {@link Raid} that this raider is participating in, if any. + pub fn raid(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Raid;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRaid", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Raid::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) + })?)) } - /// Get the {@link Sound} this entity will make when eating the given - /// {@link ItemStack}. - pub fn get_eating_sound( - &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getEatingSound", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Get the raid wave that this raider spawned as part of. + pub fn wave(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWave", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Returns true if this entity can breathe underwater and will not take - /// suffocation damage when its air supply reaches zero. - pub fn can_breathe_underwater(&self) -> Result> { - let sig = String::from("()Z"); + /// Set the raid wave that this raider was spawned as part of. + pub fn set_wave(&self, wave: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(wave); let res = self.jni_ref().call_method( &self.jni_object(), - "canBreatheUnderwater", + "setWave", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - #[deprecated] - /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. - pub fn category( + /// Gets the block the raider is targeting to patrol. + pub fn patrol_target( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPatrolTarget", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::block::Block::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets whether the entity is invisible or not. - pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(invisible.into()); + /// Sets the block the raider is targeting to patrol. + pub fn set_patrol_target( + &self, + block: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/Block;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(block.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvisible", + "setPatrolTarget", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invisible or not. - pub fn is_invisible(&self) -> Result> { + /// Gets whether this entity is a patrol leader. + pub fn is_patrol_leader(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isPatrolLeader", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the specified attribute instance from the object. This instance will - /// be backed directly to the object and any changes will be visible at once. - pub fn get_attribute( - &self, - attribute: impl Into>, - ) -> Result>, Box> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); + /// Sets whether this entity is a patrol leader. + pub fn set_patrol_leader(&self, leader: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(leader.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getAttribute", + "setPatrolLeader", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::attribute::AttributeInstance::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Deals the given amount of damage to this entity from a specified - /// {@link DamageSource}. - pub fn damage( - &self, - amount: f64, - damage_source: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(amount); - args.push(val_1); - if let Some(a) = damage_source { - sig += "Lorg/bukkit/damage/DamageSource;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "damage", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. - pub fn health(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); + /// Gets whether this mob can join an active raid. + pub fn is_can_join_raid(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCanJoinRaid", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is - /// dead. - pub fn set_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); + /// Sets whether this mob can join an active raid. + pub fn set_can_join_raid(&self, join: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(join.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setHealth", + "setCanJoinRaid", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the entity's absorption amount. - pub fn absorption_amount(&self) -> Result> { - let sig = String::from("()D"); + /// Get the amount of ticks that this mob has exited the bounds of a village + /// as a raid participant. + /// + /// This value is increased only when the mob has had no action for 2,400 ticks + /// (according to {@link #getNoActionTicks()}). Once both the no action ticks have + /// reached that value and the ticks outside a raid exceeds 30, the mob will be + /// expelled from the raid. + pub fn ticks_outside_raid(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getAbsorptionAmount", + "getTicksOutsideRaid", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.i()?) } - /// Sets the entity's absorption amount. + /// Set the amount of ticks that this mob has exited the bounds of a village + /// as a raid participant. /// - /// Note: The amount is capped to the value of - /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on - /// that attribute is currently unspecified and subject to change. - pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(amount); + /// This value is considered only when the mob has had no action for 2,400 ticks + /// (according to {@link #getNoActionTicks()}). Once both the no action ticks have + /// reached that value and the ticks outside a raid exceeds 30, the mob will be + /// expelled from the raid. + pub fn set_ticks_outside_raid(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setAbsorptionAmount", + "setTicksOutsideRaid", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the maximum health this entity has. - pub fn max_health(&self) -> Result> { - let sig = String::from("()D"); + /// Check whether or not this raider is celebrating a raid victory. + pub fn is_celebrating(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCelebrating", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - #[deprecated] - /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. - pub fn set_max_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); + /// Set whether or not this mob is celebrating a raid victory. + pub fn set_celebrating(&self, celebrating: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(celebrating.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxHealth", + "setCelebrating", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Resets the max health to the original amount. - pub fn reset_max_health(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Launches a {@link Projectile} from the ProjectileSource with an - /// initial velocity. - pub fn launch_projectile( - &self, - projectile: jni::objects::JClass<'mc>, - velocity: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/Class;"; - let val_1 = jni::objects::JValueGen::Object(projectile.into()); - args.push(val_1); - if let Some(a) = velocity { - sig += "Lorg/bukkit/util/Vector;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")LT;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); + /// Get the {@link Sound} this entity will play when celebrating. + pub fn celebration_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCelebrationSound", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -29220,19 +35873,19 @@ impl<'mc> Enemy<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Enemy<'mc> { - fn into(self) -> crate::entity::LivingEntity<'mc> { - crate::entity::LivingEntity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Enemy into crate::entity::LivingEntity") +impl<'mc> Into> for Raider<'mc> { + fn into(self) -> crate::entity::Monster<'mc> { + crate::entity::Monster::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Raider into crate::entity::Monster") } } #[repr(C)] -pub struct Horse<'mc>( +pub struct Hoglin<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Horse<'mc> { +impl<'mc> JNIRaw<'mc> for Hoglin<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -29240,18 +35893,18 @@ impl<'mc> JNIRaw<'mc> for Horse<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Horse<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Hoglin<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Horse from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Hoglin from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Horse")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Hoglin")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Horse object, got {}", + "Invalid argument passed. Expected a Hoglin object, got {}", name ) .into()) @@ -29261,816 +35914,765 @@ impl<'mc> JNIInstantiatable<'mc> for Horse<'mc> { } } -impl<'mc> Horse<'mc> { - /// Gets the horse's color. - /// - /// Colors only apply to horses, not to donkeys, mules, skeleton horses - /// or undead horses. - pub fn color(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Horse/Color;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); +impl<'mc> Hoglin<'mc> { + /// Gets whether the hoglin is immune to zombification. + pub fn is_immune_to_zombification(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isImmuneToZombification", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::entity::HorseColor::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets the horse's color. - /// - /// Attempting to set a color for any donkey, mule, skeleton horse or - /// undead horse will not result in a change. - pub fn set_color( + /// Sets whether the hoglin is immune to zombification. + pub fn set_immune_to_zombification( &self, - color: impl Into>, + flag: bool, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Horse/Color;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) - }); + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setColor", + "setImmuneToZombification", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the horse's style. - /// Styles determine what kind of markings or patterns a horse has. - /// - /// Styles only apply to horses, not to donkeys, mules, skeleton horses - /// or undead horses. - pub fn style(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Horse/Style;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getStyle", sig.as_str(), vec![]); + /// Get whether the hoglin is able to be hunted by piglins. + pub fn is_able_to_be_hunted(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isAbleToBeHunted", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::entity::HorseStyle::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets the style of this horse. - /// Styles determine what kind of markings or patterns a horse has. - /// - /// Attempting to set a style for any donkey, mule, skeleton horse or - /// undead horse will not result in a change. - pub fn set_style( - &self, - style: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Horse/Style;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(style.into().jni_object().clone()) - }); + /// Sets whether the hoglin is able to be hunted by piglins. + pub fn set_is_able_to_be_hunted(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setStyle", + "setIsAbleToBeHunted", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - - pub fn is_carrying_chest(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCarryingChest", sig.as_str(), vec![]); + /// Gets the amount of ticks until this entity will be converted to a Zoglin. + /// When this reaches 300, the entity will be converted. + pub fn conversion_time(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getConversionTime", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - #[deprecated] - - pub fn set_carrying_chest(&self, chest: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(chest.into()); + /// Sets the amount of ticks until this entity will be converted to a Zoglin. + /// When this reaches 0, the entity will be converted. A value of less than 0 + /// will stop the current conversion process without converting the current + /// entity. + pub fn set_conversion_time(&self, time: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(time); let res = self.jni_ref().call_method( &self.jni_object(), - "setCarryingChest", + "setConversionTime", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the horse's variant.A horse's variant defines its physical appearance and capabilities. Whether a horse is a regular horse, donkey, mule, or other kind of horse is determined using the variant. - pub fn variant(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Horse/Variant;"); + /// Get if this entity is in the process of converting to a Zoglin. + pub fn is_converting(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isConverting", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::HorseVariant::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - #[deprecated] - - pub fn set_variant( + /// Get the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn breed_cause( &self, - variant: impl Into>, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Set the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn set_breed_cause( + &self, + uuid: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Horse/Variant;)V"); + let sig = String::from("(Ljava/util/UUID;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(variant.into().jni_object().clone()) + jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVariant", + "setBreedCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the domestication level of this horse. - /// - /// A higher domestication level indicates that the horse is closer to - /// becoming tame. As the domestication level gets closer to the max - /// domestication level, the chance of the horse becoming tame increases. - pub fn domestication(&self) -> Result> { + /// Get whether or not this entity is in love mode and will produce + /// offspring with another entity in love mode. Will return true if + /// and only if {@link #getLoveModeTicks()} is greater than 0. + pub fn is_love_mode(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the amount of ticks remaining for this entity in love mode. + /// If the entity is not in love mode, 0 will be returned. + pub fn love_mode_ticks(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getDomestication", + "getLoveModeTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the domestication level of this horse. - /// - /// Setting the domestication level to a high value will increase the - /// horse's chances of becoming tame. - /// - /// Domestication level must be greater than zero and no greater than - /// the max domestication level of the horse, determined with - /// {@link #getMaxDomestication()} - pub fn set_domestication(&self, level: i32) -> Result<(), Box> { + /// Set the amount of ticks for which this entity should be in love mode. + /// Setting the love mode ticks to 600 is the equivalent of a player + /// feeding the entity their breeding item of choice. + pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(level); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setDomestication", + "setLoveModeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the maximum domestication level of this horse. - /// - /// The higher this level is, the longer it will likely take - /// for the horse to be tamed. - pub fn max_domestication(&self) -> Result> { - let sig = String::from("()I"); + /// Check if the provided ItemStack is the correct item used for breeding + /// this entity.. + pub fn is_breed_item( + &self, + material: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Lock the age of the animal, setting this will prevent the animal from + /// maturing or getting ready for mating. + pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(lock.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getMaxDomestication", + "setAgeLock", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the current agelock. + pub fn age_lock(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the maximum domestication level of this horse. - /// - /// Setting a higher max domestication will increase the amount of - /// domesticating (feeding, riding, etc.) necessary in order to tame it, - /// while setting a lower max value will have the opposite effect. - /// - /// Maximum domestication must be greater than zero. - pub fn set_max_domestication(&self, level: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(level); + /// Return the ability to breed of the animal. + pub fn can_breed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set breedability of the animal, if the animal is a baby and set to + /// breed it will instantly grow up. + pub fn set_breed(&self, breed: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(breed.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxDomestication", + "setBreed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the jump strength of this horse. - /// - /// Jump strength defines how high the horse can jump. A higher jump strength - /// increases how high a jump will go. - pub fn jump_strength(&self) -> Result> { - let sig = String::from("()D"); + /// Gets the height of the living entity's eyes above its Location. + pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { + let sig = String::from("(Z)D"); + let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getEyeHeight", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Get a Location detailing the current eye position of the living entity. + pub fn eye_location(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getJumpStrength", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets all blocks along the living entity's line of sight. + /// + /// This list contains all blocks from the living entity's eye position to + /// target inclusive. This method considers all blocks as 1x1x1 in size. + pub fn get_line_of_sight( + &self, + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(max_distance); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLineOfSight", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Sets the jump strength of this horse. + /// Gets the block that the living entity has targeted. /// - /// A higher jump strength increases how high a jump will go. - /// Setting a jump strength to 0 will result in no jump. - /// You cannot set a jump strength to a value below 0 or - /// above 2. - pub fn set_jump_strength(&self, strength: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(strength); + /// This method considers all blocks as 1x1x1 in size. To take exact block + /// collision shapes into account, see {@link #getTargetBlockExact(int, + /// FluidCollisionMode)}. + pub fn get_target_block( + &self, + transparent: impl Into>, + max_distance: i32, + ) -> Result, Box> { + let sig = String::from("(Ljava/util/Set;I)Lorg/bukkit/block/Block;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setJumpStrength", + "getTargetBlock", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets whether the horse is currently grazing hay. - pub fn is_eating_haystack(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the last two blocks along the living entity's line of sight. + /// + /// The target block will be the last block in the list. This method + /// considers all blocks as 1x1x1 in size. + pub fn get_last_two_target_blocks( + &self, + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "isEatingHaystack", + "getLastTwoTargetBlocks", sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Sets whether the horse is grazing hay. - pub fn set_eating_haystack( + /// Gets the block that the living entity has targeted. + /// + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn get_target_block_exact( &self, - eating_haystack: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(eating_haystack.into()); + max_distance: i32, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/block/Block;"; let res = self.jni_ref().call_method( &self.jni_object(), - "setEatingHaystack", + "getTargetBlockExact", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::block::Block::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - - pub fn inventory( + /// Performs a ray trace that provides information on the targeted block. + /// + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn ray_trace_blocks( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/AbstractHorseInventory;"); + max_distance: f64, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/util/RayTraceResult;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::inventory::AbstractHorseInventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::util::RayTraceResult::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets the vehicle's velocity. - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); + /// Returns the amount of air that the living entity has remaining, in + /// ticks. + pub fn remaining_air(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Sets the vehicle's velocity in meters per tick. - pub fn set_velocity( - &self, - vel: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(vel.into().jni_object().clone()) - }); + /// Sets the amount of air that the living entity has remaining, in ticks. + pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setVelocity", + "setRemainingAir", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check if this is tamed - /// - /// If something is tamed then a player can not tame it through normal - /// methods, even if it does not belong to anyone in particular. - pub fn is_tamed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isTamed", sig.as_str(), vec![]); + /// Returns the maximum amount of air the living entity can have, in ticks. + pub fn maximum_air(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets if this has been tamed. Not necessary if the method setOwner has - /// been used, as it tames automatically. - /// - /// If something is tamed then a player can not tame it through normal - /// methods, even if it does not belong to anyone in particular. - pub fn set_tamed(&self, tame: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(tame.into()); + /// Sets the maximum amount of air the living entity can have, in ticks. + pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setTamed", + "setMaximumAir", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the current owning AnimalTamer - pub fn owner( + /// Gets the item that the player is using (eating food, drawing back a bow, + /// blocking, etc.) + pub fn item_in_use( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/AnimalTamer;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::AnimalTamer::from_raw( + Ok(Some(crate::inventory::ItemStack::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Set this to be owned by given AnimalTamer. - /// - /// If the owner is not null, this will be tamed and will have any current - /// path it is following removed. If the owner is set to null, this will be - /// untamed, and the current owner removed. - pub fn set_owner( - &self, - tamer: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/AnimalTamer;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tamer.into().jni_object().clone()) - }); + /// Gets the number of ticks remaining for the current item's usage. + pub fn item_in_use_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "setOwner", + "getItemInUseTicks", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Horse<'mc> { - fn into(self) -> crate::entity::AbstractHorse<'mc> { - crate::entity::AbstractHorse::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Horse into crate::entity::AbstractHorse") - } -} -pub enum HorseVariant<'mc> {} -impl<'mc> std::fmt::Display for HorseVariant<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> HorseVariant<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/Horse/Variant"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/Horse/Variant;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct HorseVariantStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for HorseVariant<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for HorseVariant<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate HorseVariant from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Horse/Variant")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a HorseVariant object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for HorseVariantStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for HorseVariantStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate HorseVariantStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Horse/Variant")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a HorseVariantStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> HorseVariantStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Horse/Variant;"); - let cls = jni.find_class("org/bukkit/entity/Horse/Variant"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::HorseVariant::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -pub enum HorseColor<'mc> {} -impl<'mc> std::fmt::Display for HorseColor<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> HorseColor<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/Horse/Color"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/Horse/Color;", - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct HorseColorStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for HorseColor<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for HorseColor<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate HorseColor from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Horse/Color")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a HorseColor object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for HorseColorStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for HorseColorStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate HorseColorStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Horse/Color")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a HorseColorStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> HorseColorStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Horse/Color;"); - let cls = jni.find_class("org/bukkit/entity/Horse/Color"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::HorseColor::from_raw(&jni, obj) + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + /// Sets the number of ticks that remain for the current item's usage. + /// Applies to items that take time to use, like eating food, drawing a bow, + /// or throwing a trident. + pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItemInUseTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -pub enum HorseStyle<'mc> {} -impl<'mc> std::fmt::Display for HorseStyle<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + /// Gets the time in ticks until the next arrow leaves the entity's body. + pub fn arrow_cooldown(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getArrowCooldown", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} - -impl<'mc> HorseStyle<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/Horse/Style"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/Horse/Style;", + /// Sets the time in ticks until the next arrow leaves the entity's body. + pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setArrowCooldown", + sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -#[repr(C)] -pub struct HorseStyleStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for HorseStyle<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + /// Gets the amount of arrows in an entity's body. + pub fn arrows_in_body(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + /// Set the amount of arrows in the entity's body. + pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(count); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setArrowsInBody", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -impl<'mc> JNIInstantiatable<'mc> for HorseStyle<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate HorseStyle from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Horse/Style")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a HorseStyle object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } + /// Returns the living entity's current maximum no damage ticks. + /// + /// This is the maximum duration in which the living entity will not take + /// damage. + pub fn maximum_no_damage_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaximumNoDamageTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} - -impl<'mc> JNIRaw<'mc> for HorseStyleStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Sets the living entity's current maximum no damage ticks. + pub fn set_maximum_no_damage_ticks( + &self, + ticks: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaximumNoDamageTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Returns the living entity's last damage taken in the current no damage + /// ticks time. + /// + /// Only damage higher than this amount will further damage the living + /// entity. + pub fn last_damage(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } -} -impl<'mc> JNIInstantiatable<'mc> for HorseStyleStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate HorseStyleStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Horse/Style")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a HorseStyleStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Sets the damage dealt within the current no damage ticks time period. + pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(damage); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLastDamage", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> HorseStyleStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Horse/Style;"); - let cls = jni.find_class("org/bukkit/entity/Horse/Style"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::HorseStyle::from_raw(&jni, obj) + /// Returns the living entity's current no damage ticks. + pub fn no_damage_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNoDamageTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + /// Sets the living entity's current no damage ticks. + pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setNoDamageTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -#[repr(C)] -pub struct Entity<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Entity<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Get the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn no_action_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNoActionTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Set the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setNoActionTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -impl<'mc> JNIInstantiatable<'mc> for Entity<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Entity from null object.").into()); + /// Gets the player identified as the killer of the living entity. + /// + /// May be null. + pub fn killer(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Entity")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Entity object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + Ok(Some(crate::entity::Player::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + #[deprecated] + /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. + pub fn add_potion_effect( + &self, + effect: impl Into>, + force: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/potion/PotionEffect;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = force { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); } + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} - -impl<'mc> Entity<'mc> { - /// Stores the entity's current position in the provided Location object. + /// Returns whether the living entity already has an existing effect of + /// the given {@link PotionEffectType} applied to it. + pub fn has_potion_effect( + &self, + val_type: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasPotionEffect", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the active {@link PotionEffect} of the specified type. /// - /// If the provided Location is null this method does nothing and returns - /// null. - pub fn get_location( + /// If the effect is not present on the entity then null will be returned. + pub fn get_potion_effect( &self, - loc: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + val_type: impl Into>, + ) -> Result>, Box> { + let sig = + String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocation", + "getPotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -30078,1567 +36680,1773 @@ impl<'mc> Entity<'mc> { if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(Some(crate::potion::PotionEffect::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets this entity's velocity in meters per tick - pub fn set_velocity( + /// Removes any effects present of the given {@link PotionEffectType}. + pub fn remove_potion_effect( &self, - velocity: impl Into>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVelocity", + "removePotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets this entity's current velocity - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + /// Returns all currently active {@link PotionEffect}s on the living + /// entity. + pub fn active_potion_effects( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getActivePotionEffects", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Gets the entity's height - pub fn height(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); + /// Checks whether the living entity has block line of sight to another. + /// + /// This uses the same algorithm that hostile mobs use to find the closest + /// player. + pub fn has_line_of_sight( + &self, + other: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(other.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasLineOfSight", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Gets the entity's width - pub fn width(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); + /// Returns if the living entity despawns when away from players or not. + /// + /// By default, animals are not removed while other mobs are. + pub fn remove_when_far_away(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getRemoveWhenFarAway", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Gets the entity's current bounding box. - /// - /// The returned bounding box reflects the entity's current location and - /// size. - pub fn bounding_box( + /// Sets whether or not the living entity despawns when away from players + /// or not. + pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(remove.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRemoveWhenFarAway", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the inventory with the equipment worn by the living entity. + pub fn equipment( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::EntityEquipment::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets whether or not the living entity can pick up items. + pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(pickup.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCanPickupItems", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns true if the entity is supported by a block. This value is a - /// state updated by the server and is not recalculated unless the entity - /// moves. - pub fn is_on_ground(&self) -> Result> { + /// Gets if the living entity can pick up items. + pub fn can_pickup_items(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCanPickupItems", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns true if the entity is in water. - pub fn is_in_water(&self) -> Result> { + /// Returns whether the entity is currently leashed. + pub fn is_leashed(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the current world this entity resides in - pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + /// Gets the entity that is currently leading this entity. + pub fn leash_holder(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the entity's rotation. + /// Sets the leash on this entity to be held by the supplied entity. /// - /// Note that if the entity is affected by AI, it may override this rotation. - pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { - let sig = String::from("(FF)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); - let val_2 = jni::objects::JValueGen::Float(pitch); + /// This method has no effect on EnderDragons, Withers, Players, or Bats. + /// Non-living entities excluding leashes will not persist as leash + /// holders. + pub fn set_leash_holder( + &self, + holder: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(holder.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setRotation", + "setLeashHolder", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Teleports this entity to the given location. If this entity is riding a - /// vehicle, it will be dismounted prior to teleportation. - pub fn teleport( - &self, - location: impl Into>, - cause: std::option::Option< - impl Into>, - >, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = cause { - sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Z"; + /// Checks to see if an entity is gliding, such as using an Elytra. + pub fn is_gliding(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "teleport", sig.as_str(), args); + .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns a list of entities within a bounding box centered around this - /// entity - pub fn get_nearby_entities( - &self, - x: f64, - y: f64, - z: f64, - ) -> Result>, Box> { - let sig = String::from("(DDD)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Double(x); - let val_2 = jni::objects::JValueGen::Double(y); - let val_3 = jni::objects::JValueGen::Double(z); + /// Makes entity start or stop gliding. This will work even if an Elytra + /// is not equipped, but will be reverted by the server immediately after + /// unless an event-cancelling mechanism is put in place. + pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gliding.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getNearbyEntities", + "setGliding", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Returns a unique id for this entity - pub fn entity_id(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn fire_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns the entity's maximum fire ticks. - pub fn max_fire_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Checks to see if an entity is swimming. + pub fn is_swimming(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Makes entity start or stop swimming. + /// This may have unexpected results if the entity is not in water. + pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(swimming.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setFireTicks", + "setSwimming", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets if the entity has visual fire (it will always appear to be on fire). - pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { + /// Checks to see if an entity is currently riptiding. + pub fn is_riptiding(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Makes entity start or stop riptiding. + /// + /// Note: This does not damage attackable entities. + pub fn set_riptiding(&self, riptiding: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire.into()); + let val_1 = jni::objects::JValueGen::Bool(riptiding.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisualFire", + "setRiptiding", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity has visual fire (it will always appear to be on fire). - pub fn is_visual_fire(&self) -> Result> { + /// Returns whether this entity is slumbering. + pub fn is_sleeping(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Gets if the entity is climbing. + pub fn is_climbing(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the entity's maximum freeze ticks (amount of ticks before it will - /// be fully frozen) - pub fn max_freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMaxFreezeTicks", - sig.as_str(), - vec![], - ); + .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets whether an entity will have AI. + /// The entity will be completely unable to move if it has no AI. + pub fn set_ai(&self, ai: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(ai.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setFreezeTicks", + "setAI", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity is fully frozen (it has been in powdered snow for max - /// freeze ticks). - pub fn is_frozen(&self) -> Result> { + /// Checks whether an entity has AI. + /// The entity will be completely unable to move if it has no AI. + pub fn has_ai(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Mark the entity's removal. - pub fn remove(&self) -> Result<(), Box> { + /// Makes this entity attack the given entity with a melee attack. + /// Attack damage is calculated by the server from the attributes and + /// equipment of this mob, and knockback is applied to {@code target} as + /// appropriate. + pub fn attack( + &self, + target: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(target.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "attack", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Makes this entity swing their main hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their main hand. + pub fn swing_main_hand(&self) -> Result<(), Box> { let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns true if this entity has been marked for removal. - pub fn is_dead(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Makes this entity swing their off hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their off hand. + pub fn swing_off_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns false if the entity has died, been despawned for some other - /// reason, or has not been added to the world. - pub fn is_valid(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Makes this entity flash red as if they were damaged. + pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); + let res = self.jni_ref().call_method( + &self.jni_object(), + "playHurtAnimation", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the {@link Server} that contains this Entity - pub fn server(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Server;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Server::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Set if this entity will be subject to collisions with other entities. + /// + /// Exemptions to this rule can be managed with + /// {@link #getCollidableExemptions()} + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not working for player collisions. This + /// method should therefore only be used to set the collision status of + /// non-player entities. + /// + /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in + /// combination with a {@link Scoreboard} and a {@link Team}. + pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(collidable.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCollidable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns true if the entity gets persisted. + /// Gets if this entity is subject to collisions with other entities. /// - /// By default all entities are persistent. An entity will also not get - /// persisted, if it is riding an entity that is not persistent. + /// Some entities might be exempted from the collidable rule of this entity. + /// Use {@link #getCollidableExemptions()} to get these. /// - /// The persistent flag on players controls whether or not to save their - /// playerdata file when they quit. If a player is directly or indirectly - /// riding a non-persistent entity, the vehicle at the root and all its - /// passengers won't get persisted. + /// Please note that this method returns only the custom collidable state, + /// not whether the entity is non-collidable for other reasons such as being + /// dead. /// - /// This should not be confused with - /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls - /// despawning of living entities. - pub fn is_persistent(&self) -> Result> { + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not being accurate for player collisions. + /// This method should therefore only be used to check the collision status + /// of non-player entities. + /// + /// To check the collision behavior for a player, use + /// {@link Team.Option#COLLISION_RULE} in combination with a + /// {@link Scoreboard} and a {@link Team}. + pub fn is_collidable(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not the entity gets persisted. - pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(persistent.into()); + /// Gets a mutable set of UUIDs of the entities which are exempt from the + /// entity's collidable rule and which's collision with this entity will + /// behave the opposite of it. + /// + /// This set can be modified to add or remove exemptions. + /// + /// For example if collidable is true and an entity is in the exemptions set + /// then it will not collide with it. Similarly if collidable is false and an + /// entity is in this set then it will still collide with it. + /// + /// Note these exemptions are not (currently) persistent. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in those exemptions not being accurate for player + /// collisions. This method should therefore only be used to exempt + /// non-player entities. + /// + /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} + /// in combination with a {@link Scoreboard} and a {@link Team}. + pub fn collidable_exemptions( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setPersistent", + "getCollidableExemptions", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns the value of the memory specified. + /// + /// Note that the value is null when the specific entity does not have that + /// value by default. + pub fn get_memory( + &self, + memory_key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMemory", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) + } + /// Sets the value of the memory specified. + /// + /// Note that the value will not be persisted when the specific entity does + /// not have that value by default. + pub fn set_memory( + &self, + memory_key: impl Into>, + memory_value: jni::objects::JObject<'mc>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(memory_value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMemory", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. - pub fn passenger( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + /// Get the {@link Sound} this entity will make when damaged. + pub fn hurt_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - #[deprecated] - /// Set the passenger of a vehicle. - pub fn set_passenger( + /// Get the {@link Sound} this entity will make on death. + pub fn death_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Get the {@link Sound} this entity will make when falling from the given + /// height (in blocks). The sound will often differ between either a small + /// or a big fall damage sound if the height exceeds 4 blocks. + pub fn get_fall_damage_sound( &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); + fall_height: i32, + ) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Int(fall_height); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getFallDamageSound", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity will make when falling from a small + /// height. + pub fn fall_damage_sound_small(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setPassenger", + "getFallDamageSoundSmall", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets a list of passengers of this vehicle. - /// - /// The returned list will not be directly linked to the entity's current - /// passengers, and no guarantees are made as to its mutability. - pub fn passengers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); + /// Get the {@link Sound} this entity will make when falling from a large + /// height. + pub fn fall_damage_sound_big(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getFallDamageSoundBig", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Add a passenger to the vehicle. - pub fn add_passenger( + /// Get the {@link Sound} this entity will make when drinking the given + /// {@link ItemStack}. + pub fn get_drinking_sound( &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "addPassenger", + "getDrinkingSound", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Remove a passenger from the vehicle. - pub fn remove_passenger( + /// Get the {@link Sound} this entity will make when eating the given + /// {@link ItemStack}. + pub fn get_eating_sound( &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removePassenger", + "getEatingSound", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Check if a vehicle has passengers. - pub fn is_empty(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Eject any passenger. - pub fn eject(&self) -> Result> { + /// Returns true if this entity can breathe underwater and will not take + /// suffocation damage when its air supply reaches zero. + pub fn can_breathe_underwater(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); + let res = self.jni_ref().call_method( + &self.jni_object(), + "canBreatheUnderwater", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns the distance this entity has fallen - pub fn fall_distance(&self) -> Result> { - let sig = String::from("()F"); + #[deprecated] + /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. + pub fn category( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the fall distance for this entity - pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(distance); + /// Sets whether the entity is invisible or not. + pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(invisible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setFallDistance", + "setInvisible", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Record the last {@link EntityDamageEvent} inflicted on this entity - pub fn set_last_damage_cause( + /// Gets whether the entity is invisible or not. + pub fn is_invisible(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the specified attribute instance from the object. This instance will + /// be backed directly to the object and any changes will be visible at once. + pub fn get_attribute( &self, - event: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); + attribute: impl Into>, + ) -> Result>, Box> { + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", + ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(event.into().jni_object().clone()) + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDamageCause", + "getAttribute", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. - /// This event may have been cancelled. - pub fn last_damage_cause( - &self, - ) -> Result>, Box> - { - let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLastDamageCause", - sig.as_str(), - vec![], - ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( + Ok(Some(crate::attribute::AttributeInstance::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Returns a unique and persistent id for this entity - pub fn unique_id( + /// Deals the given amount of damage to this entity from a specified + /// {@link DamageSource}. + pub fn damage( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + amount: f64, + damage_source: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(amount); + args.push(val_1); + if let Some(a) = damage_source { + sig += "Lorg/bukkit/damage/DamageSource;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "damage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. - pub fn ticks_lived(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); + /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. + pub fn health(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.d()?) } - /// Sets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. May not be less than one - /// tick. - pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(value); + /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is + /// dead. + pub fn set_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "setTicksLived", + "setHealth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Performs the specified {@link EntityEffect} for this entity. - /// - /// This will be viewable to all players near the entity. + /// Gets the entity's absorption amount. + pub fn absorption_amount(&self) -> Result> { + let sig = String::from("()D"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAbsorptionAmount", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Sets the entity's absorption amount. /// - /// If the effect is not applicable to this class of entity, it will not play. - pub fn play_effect( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Note: The amount is capped to the value of + /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on + /// that attribute is currently unspecified and subject to change. + pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "playEffect", + "setAbsorptionAmount", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the type of the entity. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity makes while swimming. - pub fn swim_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + #[deprecated] + /// Gets the maximum health this entity has. + pub fn max_health(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.d()?) } - /// Get the {@link Sound} this entity makes when splashing in water. For most - /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_splash_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + #[deprecated] + /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. + pub fn set_max_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimSplashSound", + "setMaxHealth", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the {@link Sound} this entity makes when splashing in water at high - /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_high_speed_splash_sound( + #[deprecated] + /// Resets the max health to the original amount. + pub fn reset_max_health(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Launches a {@link Projectile} from the ProjectileSource with an + /// initial velocity. + pub fn launch_projectile( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSwimHighSpeedSplashSound", - sig.as_str(), - vec![], - ); + projectile: jni::objects::JClass<'mc>, + velocity: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(projectile.into()); + args.push(val_1); + if let Some(a) = velocity { + sig += "Lorg/bukkit/util/Vector;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")LT;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.l()?) } - /// Returns whether this entity is inside a vehicle. - pub fn is_inside_vehicle(&self) -> Result> { - let sig = String::from("()Z"); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Hoglin<'mc> { + fn into(self) -> crate::entity::Animals<'mc> { + crate::entity::Animals::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Hoglin into crate::entity::Animals") + } +} +impl<'mc> Into> for Hoglin<'mc> { + fn into(self) -> crate::entity::Enemy<'mc> { + crate::entity::Enemy::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Hoglin into crate::entity::Enemy") + } +} +#[repr(C)] +pub struct HumanEntity<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for HumanEntity<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for HumanEntity<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate HumanEntity from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/HumanEntity")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a HumanEntity object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> HumanEntity<'mc> { + /// Returns the name of this player + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Get the player's inventory. + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/PlayerInventory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::PlayerInventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Leave the current vehicle. If the entity is currently in a vehicle (and - /// is removed from it), true will be returned, otherwise false will be - /// returned. - pub fn leave_vehicle(&self) -> Result> { - let sig = String::from("()Z"); + /// Get the player's EnderChest inventory + pub fn ender_chest( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEnderChest", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get the vehicle that this entity is inside. If there is no vehicle, - /// null will be returned. - pub fn vehicle( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + /// Gets the player's selected main hand + pub fn main_hand(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/MainHand;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMainHand", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::inventory::MainHand::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets whether or not to display the mob's custom name client side. The - /// name will be displayed above the mob similarly to a player. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + #[deprecated] + /// If the player currently has an inventory window open, this method will set a property of that window, such as the state of a progress bar. + pub fn set_window_property( + &self, + prop: impl Into>, + value: i32, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/InventoryView/Property;I)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(prop.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(value); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomNameVisible", + "setWindowProperty", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets whether or not the mob's custom name is displayed client side. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn is_custom_name_visible(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the player's current enchantment seed. + /// The Seed is used to generate enchantment options in the enchanting table + /// for the player. + pub fn enchantment_seed(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "isCustomNameVisible", + "getEnchantmentSeed", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(visible.into()); + /// Sets the player's enchantment seed. + /// The Seed is used to generate enchantment options in the enchanting table + /// for the player. + pub fn set_enchantment_seed(&self, seed: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(seed); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisibleByDefault", + "setEnchantmentSeed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn is_visible_by_default(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isVisibleByDefault", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Opens an inventory window to the specified inventory view. + /// + /// The player associated with the InventoryView must be the same as this + /// instance of HumanEntity. + /// + /// The player of the InventoryView can be checked using + /// {@link InventoryView#getPlayer()}. + pub fn open_inventory( + &self, + inventory: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = inventory { + sig += "Lorg/bukkit/inventory/InventoryView;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getOpenInventory", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get all players that are currently tracking this entity. + /// Opens an inventory window to the specified inventory view. /// - /// 'Tracking' means that this entity has been sent to the player and that - /// they are receiving updates on its state. Note that the client's {@code - /// 'Entity Distance'} setting does not affect the range at which entities - /// are tracked. - pub fn tracked_by( + /// The player associated with the InventoryView must be the same as this + /// instance of HumanEntity. + /// + /// The player of the InventoryView can be checked using + /// {@link InventoryView#getPlayer()}. + pub fn open_inventory_with_inventory( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + inventory: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = inventory { + sig += "Lorg/bukkit/inventory/InventoryView;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + .call_method(&self.jni_object(), "openInventory", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets whether the entity has a team colored (default: white) glow. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Opens an empty workbench inventory window with the player's inventory + /// on the bottom. + pub fn open_workbench( + &self, + location: impl Into>, + force: bool, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;Z)Lorg/bukkit/inventory/InventoryView;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Bool(force.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setGlowing", + "openWorkbench", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether the entity is glowing or not. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn is_glowing(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::InventoryView::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets whether the entity is invulnerable or not. - /// - /// When an entity is invulnerable it can only be damaged by players in - /// creative mode. - pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Opens an empty enchanting inventory window with the player's inventory + /// on the bottom. + pub fn open_enchanting( + &self, + location: impl Into>, + force: bool, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;Z)Lorg/bukkit/inventory/InventoryView;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Bool(force.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvulnerable", + "openEnchanting", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::InventoryView::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets whether the entity is invulnerable or not. - pub fn is_invulnerable(&self) -> Result> { - let sig = String::from("()Z"); + /// Starts a trade between the player and the merchant. + /// Note that only one player may trade with a merchant at once. You must use + /// the force parameter for this. + pub fn open_merchant( + &self, + merchant: impl Into>, + force: bool, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/Merchant;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(merchant.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(force.into()); + args.push(val_2); + sig += ")Lorg/bukkit/inventory/InventoryView;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "openMerchant", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::InventoryView::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets whether the entity is silent or not. - pub fn is_silent(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + /// Force-closes the currently open inventory view for this player, if any. + pub fn close_inventory(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "closeInventory", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Returns the ItemStack currently in your hand, can be empty. + pub fn item_in_hand( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemInHand", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets whether the entity is silent or not. - /// - /// When an entity is silent it will not produce any sound. - pub fn set_silent(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + #[deprecated] + /// Sets the item to the given ItemStack, this will replace whatever the user was holding. + pub fn set_item_in_hand( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setSilent", + "setItemInHand", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether gravity applies to this entity. - pub fn has_gravity(&self) -> Result> { - let sig = String::from("()Z"); + /// Returns the ItemStack currently on your cursor, can be empty. Will + /// always be empty if the player currently has no open window. + pub fn item_on_cursor( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItemOnCursor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets whether gravity applies to this entity. - pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gravity.into()); + /// Sets the item to the given ItemStack, this will replace whatever the + /// user was moving. Will always be empty if the player currently has no + /// open window. + pub fn set_item_on_cursor( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setGravity", + "setItemOnCursor", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the period of time (in ticks) before this entity can use a portal. - pub fn portal_cooldown(&self) -> Result> { - let sig = String::from("()I"); + /// Check whether a cooldown is active on the specified material. + pub fn has_cooldown( + &self, + material: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/Material;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getPortalCooldown", + "hasCooldown", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the period of time (in ticks) before this entity can use a portal. - pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(cooldown); + /// Get the cooldown time in ticks remaining for the specified material. + pub fn get_cooldown( + &self, + material: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/Material;)I"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPortalCooldown", + "getCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Returns a set of tags for this entity. + /// Set a cooldown on the specified material for a certain amount of ticks. + /// ticks. 0 ticks will result in the removal of the cooldown. /// - /// Entities can have no more than 1024 tags. - pub fn scoreboard_tags( + /// Cooldowns are used by the server for items such as ender pearls and + /// shields to prevent them from being used repeatedly. + /// + /// Note that cooldowns will not by themselves stop an item from being used + /// for attacking. + pub fn set_cooldown( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + material: impl Into>, + ticks: i32, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Material;I)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "getScoreboardTags", + "setCooldown", sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the sleep ticks of the player. This value may be capped. + pub fn sleep_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSleepTicks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Add a tag to this entity. + /// Attempts to make the entity sleep at the given location. /// - /// Entities can have no more than 1024 tags. - pub fn add_scoreboard_tag( + /// The location must be in the current world and have a bed placed at the + /// location. The game may also enforce other requirements such as proximity + /// to bed, monsters, and dimension type if force is not set. + pub fn sleep( &self, - tag: impl Into, + location: impl Into>, + force: bool, ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); + let sig = String::from("(Lorg/bukkit/Location;Z)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Bool(force.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "addScoreboardTag", + "sleep", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes a given tag from this entity. - pub fn remove_scoreboard_tag( - &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); + /// Causes the player to wakeup if they are currently sleeping. + pub fn wakeup(&self, set_spawn_location: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(set_spawn_location.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "removeScoreboardTag", + "wakeup", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns the reaction of the entity when moved by a piston. - pub fn piston_move_reaction( + /// Make the player start a riptide spin attack. + pub fn start_riptide_attack( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + duration: i32, + attack_strength: f32, + attack_item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(IFLorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Int(duration); + let val_2 = jni::objects::JValueGen::Float(attack_strength); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attack_item.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getPistonMoveReaction", + "startRiptideAttack", sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); - let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the closest cardinal {@link BlockFace} direction an entity is - /// currently facing. - /// - /// This will not return any non-cardinal directions such as - /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. - /// - /// {@link Hanging} entities will override this call and thus their behavior - /// may be different. - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + /// Gets the location of the bed the player is currently sleeping in + pub fn bed_location(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBedLocation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the entity's current pose. - /// Note that the pose is only updated at the end of a tick, so may be - /// inconsistent with other methods. eg {@link Player#isSneaking()} being - /// true does not imply the current pose will be {@link Pose#SNEAKING} - pub fn pose(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Pose;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + /// Gets this human's current {@link GameMode} + pub fn game_mode(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/GameMode;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getGameMode", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + crate::GameMode::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the category of spawn to which this entity belongs. - pub fn spawn_category( + /// Sets this human's current {@link GameMode} + pub fn set_game_mode( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); + mode: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/GameMode;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(mode.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getSpawnCategory", + "setGameMode", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Checks if this entity has been spawned in a world. - /// - /// Entities not spawned in a world will not tick, be sent to players, or be - /// saved to the server files. - pub fn is_in_world(&self) -> Result> { + /// Check if the player is currently blocking (ie with a shield). + pub fn is_blocking(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isBlocking", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get this entity as an NBT string. - /// - /// This string should not be relied upon as a serializable value. - pub fn as_string(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); + /// Check if the player currently has their hand raised (ie about to begin + /// blocking). + pub fn is_hand_raised(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isHandRaised", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(res.z()?) } - /// Crates an {@link EntitySnapshot} representing the current state of this entity. - pub fn create_snapshot( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + /// Get the total amount of experience required for the player to level + pub fn exp_to_level(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getExpToLevel", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::EntitySnapshot::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - /// Creates a copy of this entity and all its data. Spawns the copy at the given location. - /// - /// Note: Players cannot be copied. - pub fn copy( - &self, - to: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = to { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")Lorg/bukkit/entity/Entity;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); + /// Gets the current cooldown for a player's attack. + /// This is used to calculate damage, with 1.0 representing a fully charged + /// attack and 0.0 representing a non-charged attack + pub fn attack_cooldown(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAttackCooldown", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.f()?) } - /// Sets a metadata value in the implementing object's metadata store. - pub fn set_metadata( + /// Discover a recipe for this player such that it has not already been + /// discovered. This method will add the key's associated recipe to the + /// player's recipe book. + pub fn discover_recipe( &self, - metadata_key: impl Into, - new_metadata_value: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) + recipe: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setMetadata", + "discoverRecipe", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Returns a list of previously set metadata values from the implementing - /// object's metadata store. - pub fn get_metadata( + /// Undiscover a recipe for this player such that it has already been + /// discovered. This method will remove the key's associated recipe from the + /// player's recipe book. + pub fn undiscover_recipe( &self, - metadata_key: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); + recipe: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getMetadata", + "undiscoverRecipe", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::metadata::MetadataValue::from_raw( - &self.jni_ref(), - obj, - )?); - } - Ok(new_vec) + Ok(res.z()?) } - /// Tests to see whether the implementing object contains the given - /// metadata value in its metadata store. - pub fn has_metadata( + /// Check whether or not this entity has discovered the specified recipe. + pub fn has_discovered_recipe( &self, - metadata_key: impl Into, + recipe: impl Into>, ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); + let sig = String::from("(Lorg/bukkit/NamespacedKey;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasMetadata", + "hasDiscoveredRecipe", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes the given metadata value from the implementing object's - /// metadata store. - pub fn remove_metadata( + /// Get an immutable set of recipes this entity has discovered. + pub fn discovered_recipes( &self, - metadata_key: impl Into, - owning_plugin: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) - }); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref().call_method( &self.jni_object(), - "removeMetadata", + "getDiscoveredRecipes", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sends this sender multiple messages - pub fn send_message( + #[deprecated] + /// Gets the entity currently perched on the left shoulder or null if no entity. + /// + /// The returned entity will not be spawned within the world, so most operations are invalid unless the entity is first spawned in. + pub fn shoulder_entity_left( &self, - sender: impl Into>, - messages: std::option::Option>, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getShoulderEntityLeft", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + #[deprecated] + /// Sets the entity currently perched on the left shoulder, or null to remove. This method will remove the entity from the world. + /// + /// Note that only a copy of the entity will be set to display on the shoulder. + /// + /// Also note that the client will currently only render {@link Parrot} entities. + pub fn set_shoulder_entity_left( + &self, + entity: impl Into>, ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) }); - args.push(val_1); - if let Some(a) = messages { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setShoulderEntityLeft", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the name of this command sender - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Gets the custom name on a mob or block. If there is no name this method - /// will return null. + #[deprecated] + /// Gets the entity currently perched on the right shoulder or null if no entity. /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn custom_name(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCustomName", sig.as_str(), vec![]); + /// The returned entity will not be spawned within the world, so most operations are invalid unless the entity is first spawned in. + pub fn shoulder_entity_right( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getShoulderEntityRight", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets a custom name on a mob or block. This name will be used in death - /// messages and can be sent to the client as a nameplate over the mob. + #[deprecated] + /// Sets the entity currently perched on the right shoulder, or null to remove. This method will remove the entity from the world. /// - /// Setting the name to null or an empty string will clear it. + /// Note that only a copy of the entity will be set to display on the shoulder. /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn set_custom_name( + /// Also note that the client will currently only render {@link Parrot} entities. + pub fn set_shoulder_entity_right( &self, - name: impl Into, + entity: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomName", + "setShoulderEntityRight", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + /// Make the entity drop the item in their hand. + /// + /// This will force the entity to drop the item they are holding with + /// an option to drop the entire {@link ItemStack} or just 1 of the items. + pub fn drop_item(&self, drop_all: bool) -> Result> { + let sig = String::from("(Z)Z"); + let val_1 = jni::objects::JValueGen::Bool(drop_all.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "dropItem", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Entity<'mc> { - fn into(self) -> crate::metadata::Metadatable<'mc> { - crate::metadata::Metadatable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Entity into crate::metadata::Metadatable") - } -} -impl<'mc> Into> for Entity<'mc> { - fn into(self) -> crate::command::CommandSender<'mc> { - crate::command::CommandSender::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Entity into crate::command::CommandSender") - } -} -impl<'mc> Into> for Entity<'mc> { - fn into(self) -> crate::Nameable<'mc> { - crate::Nameable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Entity into crate::Nameable") - } -} -impl<'mc> Into> for Entity<'mc> { - fn into(self) -> crate::persistence::PersistentDataHolder<'mc> { - crate::persistence::PersistentDataHolder::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Entity into crate::persistence::PersistentDataHolder") - } -} -#[repr(C)] -pub struct Endermite<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Endermite<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Endermite<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Endermite from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Endermite")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Endermite object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + Ok(res.z()?) } -} - -impl<'mc> Endermite<'mc> { - #[deprecated] - /// Gets whether this Endermite was spawned by a player. An Endermite spawned by a player will be attacked by nearby Enderman. - pub fn is_player_spawned(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the players current exhaustion level. + /// + /// Exhaustion controls how fast the food level drops. While you have a + /// certain amount of exhaustion, your saturation will drop to zero, and + /// then your food will drop to zero. + pub fn exhaustion(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isPlayerSpawned", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getExhaustion", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.f()?) } - #[deprecated] - /// Sets whether this Endermite was spawned by a player. An Endermite spawned by a player will be attacked by nearby Enderman. - pub fn set_player_spawned( - &self, - player_spawned: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(player_spawned.into()); + /// Sets the players current exhaustion level + pub fn set_exhaustion(&self, value: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(value); let res = self.jni_ref().call_method( &self.jni_object(), - "setPlayerSpawned", + "setExhaustion", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Endermite<'mc> { - fn into(self) -> crate::entity::Monster<'mc> { - crate::entity::Monster::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Endermite into crate::entity::Monster") - } -} -#[repr(C)] -pub struct Damageable<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Damageable<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Damageable<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Damageable from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Damageable")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Damageable object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Damageable<'mc> { - /// Deals the given amount of damage to this entity from a specified - /// {@link DamageSource}. - pub fn damage( - &self, - amount: f64, - damage_source: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(amount); - args.push(val_1); - if let Some(a) = damage_source { - sig += "Lorg/bukkit/damage/DamageSource;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "damage", sig.as_str(), args); + /// Gets the players current saturation level. + /// + /// Saturation is a buffer for food level. Your food level will not drop if + /// you are saturated {@literal >} 0. + pub fn saturation(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSaturation", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the players current saturation level + pub fn set_saturation(&self, value: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSaturation", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. - pub fn health(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); + /// Gets the players current food level + pub fn food_level(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFoodLevel", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.i()?) } - /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is - /// dead. - pub fn set_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); + /// Sets the players current food level + pub fn set_food_level(&self, value: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(value); let res = self.jni_ref().call_method( &self.jni_object(), - "setHealth", + "setFoodLevel", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the entity's absorption amount. - pub fn absorption_amount(&self) -> Result> { - let sig = String::from("()D"); + /// Get the regeneration rate (1 health per x ticks) of + /// the HumanEntity when they have saturation and + /// their food level is {@literal >=} 20. Default is 10. + pub fn saturated_regen_rate(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getAbsorptionAmount", + "getSaturatedRegenRate", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.i()?) } - /// Sets the entity's absorption amount. - /// - /// Note: The amount is capped to the value of - /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on - /// that attribute is currently unspecified and subject to change. - pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(amount); + /// Set the regeneration rate (1 health per x ticks) of + /// the HumanEntity when they have saturation and + /// their food level is {@literal >=} 20. Default is 10. + /// Not affected if the world's difficulty is peaceful. + pub fn set_saturated_regen_rate(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setAbsorptionAmount", + "setSaturatedRegenRate", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the maximum health this entity has. - pub fn max_health(&self) -> Result> { - let sig = String::from("()D"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); + /// Get the regeneration rate (1 health per x ticks) of + /// the HumanEntity when they have no saturation and + /// their food level is {@literal >=} 18. Default is 80. + pub fn unsaturated_regen_rate(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getUnsaturatedRegenRate", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.i()?) } - #[deprecated] - /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. - pub fn set_max_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); + /// Get the regeneration rate (1 health per x ticks) of + /// the HumanEntity when they have no saturation and + /// their food level is {@literal >=} 18. Default is 80. + /// Not affected if the world's difficulty is peaceful. + pub fn set_unsaturated_regen_rate(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxHealth", + "setUnsaturatedRegenRate", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Resets the max health to the original amount. - pub fn reset_max_health(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); + /// Get the starvation rate (1 health per x ticks) of + /// the HumanEntity. Default is 80. + pub fn starvation_rate(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getStarvationRate", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Get the starvation rate (1 health per x ticks) of + /// the HumanEntity. Default is 80. + pub fn set_starvation_rate(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setStarvationRate", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Stores the entity's current position in the provided Location object. - /// - /// If the provided Location is null this method does nothing and returns - /// null. - pub fn get_location( + /// Gets the player's last death location. + pub fn last_death_location( &self, - loc: impl Into>, ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) - }); + let sig = String::from("()Lorg/bukkit/Location;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocation", + "getLastDeathLocation", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { @@ -31648,169 +38456,163 @@ impl<'mc> Damageable<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) })?)) } - /// Sets this entity's velocity in meters per tick - pub fn set_velocity( + /// Sets the player's last death location. + /// + /// Note: This data is updated in the player's client only when the + /// player respawns. + pub fn set_last_death_location( &self, - velocity: impl Into>, + location: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let sig = String::from("(Lorg/bukkit/Location;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + jni::objects::JObject::from_raw(location.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVelocity", + "setLastDeathLocation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets this entity's current velocity - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the entity's height - pub fn height(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); + /// Perform a firework boost. + /// + /// This method will only work such that {@link #isGliding()} is true and + /// the entity is actively gliding with an elytra. Additionally, the supplied + /// {@code fireworkItemStack} must be a firework rocket. The power of the boost + /// will directly correlate to {@link FireworkMeta#getPower()}. + pub fn firework_boost( + &self, + firework_item_stack: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/entity/Firework;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(firework_item_stack.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "fireworkBoost", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Firework::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets the entity's width - pub fn width(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); + /// Gets the height of the living entity's eyes above its Location. + pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { + let sig = String::from("(Z)D"); + let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getEyeHeight", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.d()?) } - /// Gets the entity's current bounding box. - /// - /// The returned bounding box reflects the entity's current location and - /// size. - pub fn bounding_box( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns true if the entity is supported by a block. This value is a - /// state updated by the server and is not recalculated unless the entity - /// moves. - pub fn is_on_ground(&self) -> Result> { - let sig = String::from("()Z"); + /// Get a Location detailing the current eye position of the living entity. + pub fn eye_location(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns true if the entity is in water. - pub fn is_in_water(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the current world this entity resides in - pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { + crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the entity's rotation. + /// Gets all blocks along the living entity's line of sight. /// - /// Note that if the entity is affected by AI, it may override this rotation. - pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { - let sig = String::from("(FF)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); - let val_2 = jni::objects::JValueGen::Float(pitch); + /// This list contains all blocks from the living entity's eye position to + /// target inclusive. This method considers all blocks as 1x1x1 in size. + pub fn get_line_of_sight( + &self, + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setRotation", + "getLineOfSight", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Teleports this entity to the given location. If this entity is riding a - /// vehicle, it will be dismounted prior to teleportation. - pub fn teleport( + /// Gets the block that the living entity has targeted. + /// + /// This method considers all blocks as 1x1x1 in size. To take exact block + /// collision shapes into account, see {@link #getTargetBlockExact(int, + /// FluidCollisionMode)}. + pub fn get_target_block( &self, - location: impl Into>, - cause: std::option::Option< - impl Into>, - >, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; + transparent: impl Into>, + max_distance: i32, + ) -> Result, Box> { + let sig = String::from("(Ljava/util/Set;I)Lorg/bukkit/block/Block;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) }); - args.push(val_1); - if let Some(a) = cause { - sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "teleport", sig.as_str(), args); + let val_2 = jni::objects::JValueGen::Int(max_distance); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTargetBlock", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns a list of entities within a bounding box centered around this - /// entity - pub fn get_nearby_entities( + /// Gets the last two blocks along the living entity's line of sight. + /// + /// The target block will be the last block in the list. This method + /// considers all blocks as 1x1x1 in size. + pub fn get_last_two_target_blocks( &self, - x: f64, - y: f64, - z: f64, - ) -> Result>, Box> { - let sig = String::from("(DDD)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Double(x); - let val_2 = jni::objects::JValueGen::Double(y); - let val_3 = jni::objects::JValueGen::Double(z); + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "getNearbyEntities", + "getLastTwoTargetBlocks", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), ], ); let res = self.jni_ref().translate_error(res)?; @@ -31819,736 +38621,845 @@ impl<'mc> Damageable<'mc> { let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); } Ok(new_vec) } - /// Returns a unique id for this entity - pub fn entity_id(&self) -> Result> { + /// Gets the block that the living entity has targeted. + /// + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn get_target_block_exact( + &self, + max_distance: i32, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/block/Block;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTargetBlockExact", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::block::Block::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Performs a ray trace that provides information on the targeted block. + /// + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn ray_trace_blocks( + &self, + max_distance: f64, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/util/RayTraceResult;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::util::RayTraceResult::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Returns the amount of air that the living entity has remaining, in + /// ticks. + pub fn remaining_air(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Returns the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn fire_ticks(&self) -> Result> { + /// Sets the amount of air that the living entity has remaining, in ticks. + pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRemainingAir", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the maximum amount of air the living entity can have, in ticks. + pub fn maximum_air(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Returns the entity's maximum fire ticks. - pub fn max_fire_ticks(&self) -> Result> { + /// Sets the maximum amount of air the living entity can have, in ticks. + pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaximumAir", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the item that the player is using (eating food, drawing back a bow, + /// blocking, etc.) + pub fn item_in_use( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the number of ticks remaining for the current item's usage. + pub fn item_in_use_ticks(&self) -> Result> { let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItemInUseTicks", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Sets the number of ticks that remain for the current item's usage. + /// Applies to items that take time to use, like eating food, drawing a bow, + /// or throwing a trident. + pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setFireTicks", + "setItemInUseTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets if the entity has visual fire (it will always appear to be on fire). - pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire.into()); + /// Gets the time in ticks until the next arrow leaves the entity's body. + pub fn arrow_cooldown(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisualFire", + "getArrowCooldown", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the time in ticks until the next arrow leaves the entity's body. + pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setArrowCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity has visual fire (it will always appear to be on fire). - pub fn is_visual_fire(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn freeze_ticks(&self) -> Result> { + /// Gets the amount of arrows in an entity's body. + pub fn arrows_in_body(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Returns the entity's maximum freeze ticks (amount of ticks before it will - /// be fully frozen) - pub fn max_freeze_ticks(&self) -> Result> { + /// Set the amount of arrows in the entity's body. + pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(count); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setArrowsInBody", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the living entity's current maximum no damage ticks. + /// + /// This is the maximum duration in which the living entity will not take + /// damage. + pub fn maximum_no_damage_ticks(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getMaxFreezeTicks", + "getMaximumNoDamageTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Sets the living entity's current maximum no damage ticks. + pub fn set_maximum_no_damage_ticks( + &self, + ticks: i32, + ) -> Result<(), Box> { let sig = String::from("(I)V"); let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setFreezeTicks", + "setMaximumNoDamageTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity is fully frozen (it has been in powdered snow for max - /// freeze ticks). - pub fn is_frozen(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); + /// Returns the living entity's last damage taken in the current no damage + /// ticks time. + /// + /// Only damage higher than this amount will further damage the living + /// entity. + pub fn last_damage(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Mark the entity's removal. - pub fn remove(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); + /// Sets the damage dealt within the current no damage ticks time period. + pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(damage); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLastDamage", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns true if this entity has been marked for removal. - pub fn is_dead(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns false if the entity has died, been despawned for some other - /// reason, or has not been added to the world. - pub fn is_valid(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); + /// Returns the living entity's current no damage ticks. + pub fn no_damage_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNoDamageTicks", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Gets the {@link Server} that contains this Entity - pub fn server(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Server;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Server::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Sets the living entity's current no damage ticks. + pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setNoDamageTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns true if the entity gets persisted. - /// - /// By default all entities are persistent. An entity will also not get - /// persisted, if it is riding an entity that is not persistent. - /// - /// The persistent flag on players controls whether or not to save their - /// playerdata file when they quit. If a player is directly or indirectly - /// riding a non-persistent entity, the vehicle at the root and all its - /// passengers won't get persisted. + /// Get the ticks that this entity has performed no action. /// - /// This should not be confused with - /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls - /// despawning of living entities. - pub fn is_persistent(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn no_action_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNoActionTicks", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets whether or not the entity gets persisted. - pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(persistent.into()); + /// Set the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setPersistent", + "setNoActionTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. - pub fn passenger( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); + /// Gets the player identified as the killer of the living entity. + /// + /// May be null. + pub fn killer(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Entity::from_raw( + Ok(Some(crate::entity::Player::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } #[deprecated] - /// Set the passenger of a vehicle. - pub fn set_passenger( + /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. + pub fn add_potion_effect( &self, - passenger: impl Into>, + effect: impl Into>, + force: std::option::Option, ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/potion/PotionEffect;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPassenger", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets a list of passengers of this vehicle. - /// - /// The returned list will not be directly linked to the entity's current - /// passengers, and no guarantees are made as to its mutability. - pub fn passengers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + args.push(val_1); + if let Some(a) = force { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(res.z()?) } - /// Add a passenger to the vehicle. - pub fn add_passenger( + /// Returns whether the living entity already has an existing effect of + /// the given {@link PotionEffectType} applied to it. + pub fn has_potion_effect( &self, - passenger: impl Into>, + val_type: impl Into>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "addPassenger", + "hasPotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Remove a passenger from the vehicle. - pub fn remove_passenger( + /// Returns the active {@link PotionEffect} of the specified type. + /// + /// If the effect is not present on the entity then null will be returned. + pub fn get_potion_effect( &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + val_type: impl Into>, + ) -> Result>, Box> { + let sig = + String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removePassenger", + "getPotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Check if a vehicle has passengers. - pub fn is_empty(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Eject any passenger. - pub fn eject(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the distance this entity has fallen - pub fn fall_distance(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Sets the fall distance for this entity - pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(distance); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFallDistance", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::potion::PotionEffect::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - #[deprecated] - /// Record the last {@link EntityDamageEvent} inflicted on this entity - pub fn set_last_damage_cause( + /// Removes any effects present of the given {@link PotionEffectType}. + pub fn remove_potion_effect( &self, - event: impl Into>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(event.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDamageCause", + "removePotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. - /// This event may have been cancelled. - pub fn last_damage_cause( + /// Returns all currently active {@link PotionEffect}s on the living + /// entity. + pub fn active_potion_effects( &self, - ) -> Result>, Box> - { - let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLastDamageCause", + "getActivePotionEffects", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); } - Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Returns a unique and persistent id for this entity - pub fn unique_id( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. - pub fn ticks_lived(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. May not be less than one - /// tick. - pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(value); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTicksLived", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(new_vec) } - /// Performs the specified {@link EntityEffect} for this entity. - /// - /// This will be viewable to all players near the entity. + /// Checks whether the living entity has block line of sight to another. /// - /// If the effect is not applicable to this class of entity, it will not play. - pub fn play_effect( + /// This uses the same algorithm that hostile mobs use to find the closest + /// player. + pub fn has_line_of_sight( &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); + other: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(other.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "playEffect", + "hasLineOfSight", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the type of the entity. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity makes while swimming. - pub fn swim_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity makes when splashing in water. For most - /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_splash_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSwimSplashSound", - sig.as_str(), - vec![], - ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Get the {@link Sound} this entity makes when splashing in water at high - /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_high_speed_splash_sound( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Returns if the living entity despawns when away from players or not. + /// + /// By default, animals are not removed while other mobs are. + pub fn remove_when_far_away(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimHighSpeedSplashSound", + "getRemoveWhenFarAway", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns whether this entity is inside a vehicle. - pub fn is_inside_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Leave the current vehicle. If the entity is currently in a vehicle (and - /// is removed from it), true will be returned, otherwise false will be - /// returned. - pub fn leave_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Sets whether or not the living entity despawns when away from players + /// or not. + pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(remove.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRemoveWhenFarAway", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the vehicle that this entity is inside. If there is no vehicle, - /// null will be returned. - pub fn vehicle( + /// Gets the inventory with the equipment worn by the living entity. + pub fn equipment( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Entity::from_raw( + Ok(Some(crate::inventory::EntityEquipment::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets whether or not to display the mob's custom name client side. The - /// name will be displayed above the mob similarly to a player. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { + /// Sets whether or not the living entity can pick up items. + pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(pickup.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomNameVisible", + "setCanPickupItems", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not the mob's custom name is displayed client side. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn is_custom_name_visible(&self) -> Result> { + /// Gets if the living entity can pick up items. + pub fn can_pickup_items(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "isCustomNameVisible", + "getCanPickupItems", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(visible.into()); + /// Returns whether the entity is currently leashed. + pub fn is_leashed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the entity that is currently leading this entity. + pub fn leash_holder(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the leash on this entity to be held by the supplied entity. + /// + /// This method has no effect on EnderDragons, Withers, Players, or Bats. + /// Non-living entities excluding leashes will not persist as leash + /// holders. + pub fn set_leash_holder( + &self, + holder: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(holder.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisibleByDefault", + "setLeashHolder", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn is_visible_by_default(&self) -> Result> { + /// Checks to see if an entity is gliding, such as using an Elytra. + pub fn is_gliding(&self) -> Result> { let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Makes entity start or stop gliding. This will work even if an Elytra + /// is not equipped, but will be reverted by the server immediately after + /// unless an event-cancelling mechanism is put in place. + pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gliding.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "isVisibleByDefault", + "setGliding", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get all players that are currently tracking this entity. - /// - /// 'Tracking' means that this entity has been sent to the player and that - /// they are receiving updates on its state. Note that the client's {@code - /// 'Entity Distance'} setting does not affect the range at which entities - /// are tracked. - pub fn tracked_by( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Checks to see if an entity is swimming. + pub fn is_swimming(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets whether the entity has a team colored (default: white) glow. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { + /// Makes entity start or stop swimming. + /// This may have unexpected results if the entity is not in water. + pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(swimming.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setGlowing", + "setSwimming", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is glowing or not. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn is_glowing(&self) -> Result> { + /// Checks to see if an entity is currently riptiding. + pub fn is_riptiding(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the entity is invulnerable or not. + /// Makes entity start or stop riptiding. /// - /// When an entity is invulnerable it can only be damaged by players in - /// creative mode. - pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { + /// Note: This does not damage attackable entities. + pub fn set_riptiding(&self, riptiding: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(riptiding.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvulnerable", + "setRiptiding", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invulnerable or not. - pub fn is_invulnerable(&self) -> Result> { + /// Returns whether this entity is slumbering. + pub fn is_sleeping(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets whether the entity is silent or not. - pub fn is_silent(&self) -> Result> { + /// Gets if the entity is climbing. + pub fn is_climbing(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the entity is silent or not. - /// - /// When an entity is silent it will not produce any sound. - pub fn set_silent(&self, flag: bool) -> Result<(), Box> { + /// Sets whether an entity will have AI. + /// The entity will be completely unable to move if it has no AI. + pub fn set_ai(&self, ai: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(ai.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setSilent", + "setAI", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether gravity applies to this entity. - pub fn has_gravity(&self) -> Result> { + /// Checks whether an entity has AI. + /// The entity will be completely unable to move if it has no AI. + pub fn has_ai(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether gravity applies to this entity. - pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gravity.into()); + /// Makes this entity attack the given entity with a melee attack. + /// Attack damage is calculated by the server from the attributes and + /// equipment of this mob, and knockback is applied to {@code target} as + /// appropriate. + pub fn attack( + &self, + target: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(target.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setGravity", + "attack", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the period of time (in ticks) before this entity can use a portal. - pub fn portal_cooldown(&self) -> Result> { - let sig = String::from("()I"); + /// Makes this entity swing their main hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their main hand. + pub fn swing_main_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Makes this entity swing their off hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their off hand. + pub fn swing_off_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Makes this entity flash red as if they were damaged. + pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); let res = self.jni_ref().call_method( &self.jni_object(), - "getPortalCooldown", + "playHurtAnimation", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the period of time (in ticks) before this entity can use a portal. - pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(cooldown); + /// Set if this entity will be subject to collisions with other entities. + /// + /// Exemptions to this rule can be managed with + /// {@link #getCollidableExemptions()} + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not working for player collisions. This + /// method should therefore only be used to set the collision status of + /// non-player entities. + /// + /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in + /// combination with a {@link Scoreboard} and a {@link Team}. + pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(collidable.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setPortalCooldown", + "setCollidable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a set of tags for this entity. + /// Gets if this entity is subject to collisions with other entities. /// - /// Entities can have no more than 1024 tags. - pub fn scoreboard_tags( + /// Some entities might be exempted from the collidable rule of this entity. + /// Use {@link #getCollidableExemptions()} to get these. + /// + /// Please note that this method returns only the custom collidable state, + /// not whether the entity is non-collidable for other reasons such as being + /// dead. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not being accurate for player collisions. + /// This method should therefore only be used to check the collision status + /// of non-player entities. + /// + /// To check the collision behavior for a player, use + /// {@link Team.Option#COLLISION_RULE} in combination with a + /// {@link Scoreboard} and a {@link Team}. + pub fn is_collidable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets a mutable set of UUIDs of the entities which are exempt from the + /// entity's collidable rule and which's collision with this entity will + /// behave the opposite of it. + /// + /// This set can be modified to add or remove exemptions. + /// + /// For example if collidable is true and an entity is in the exemptions set + /// then it will not collide with it. Similarly if collidable is false and an + /// entity is in this set then it will still collide with it. + /// + /// Note these exemptions are not (currently) persistent. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in those exemptions not being accurate for player + /// collisions. This method should therefore only be used to exempt + /// non-player entities. + /// + /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} + /// in combination with a {@link Scoreboard} and a {@link Team}. + pub fn collidable_exemptions( &self, ) -> Result, Box> { let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getScoreboardTags", + "getCollidableExemptions", sig.as_str(), vec![], ); @@ -32557,381 +39468,482 @@ impl<'mc> Damageable<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Add a tag to this entity. + /// Returns the value of the memory specified. /// - /// Entities can have no more than 1024 tags. - pub fn add_scoreboard_tag( + /// Note that the value is null when the specific entity does not have that + /// value by default. + pub fn get_memory( &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); + memory_key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "addScoreboardTag", + "getMemory", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) } - /// Removes a given tag from this entity. - pub fn remove_scoreboard_tag( + /// Sets the value of the memory specified. + /// + /// Note that the value will not be persisted when the specific entity does + /// not have that value by default. + pub fn set_memory( &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); + memory_key: impl Into>, + memory_value: jni::objects::JObject<'mc>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(memory_value); let res = self.jni_ref().call_method( &self.jni_object(), - "removeScoreboardTag", + "setMemory", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the {@link Sound} this entity will make when damaged. + pub fn hurt_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Returns the reaction of the entity when moved by a piston. - pub fn piston_move_reaction( + /// Get the {@link Sound} this entity will make on death. + pub fn death_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Get the {@link Sound} this entity will make when falling from the given + /// height (in blocks). The sound will often differ between either a small + /// or a big fall damage sound if the height exceeds 4 blocks. + pub fn get_fall_damage_sound( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + fall_height: i32, + ) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Int(fall_height); let res = self.jni_ref().call_method( &self.jni_object(), - "getPistonMoveReaction", + "getFallDamageSound", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity will make when falling from a small + /// height. + pub fn fall_damage_sound_small(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getFallDamageSoundSmall", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the closest cardinal {@link BlockFace} direction an entity is - /// currently facing. - /// - /// This will not return any non-cardinal directions such as - /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. - /// - /// {@link Hanging} entities will override this call and thus their behavior - /// may be different. - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + /// Get the {@link Sound} this entity will make when falling from a large + /// height. + pub fn fall_damage_sound_big(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getFallDamageSoundBig", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the entity's current pose. - /// Note that the pose is only updated at the end of a tick, so may be - /// inconsistent with other methods. eg {@link Player#isSneaking()} being - /// true does not imply the current pose will be {@link Pose#SNEAKING} - pub fn pose(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Pose;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + /// Get the {@link Sound} this entity will make when drinking the given + /// {@link ItemStack}. + pub fn get_drinking_sound( + &self, + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDrinkingSound", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the category of spawn to which this entity belongs. - pub fn spawn_category( + /// Get the {@link Sound} this entity will make when eating the given + /// {@link ItemStack}. + pub fn get_eating_sound( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getSpawnCategory", + "getEatingSound", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Checks if this entity has been spawned in a world. - /// - /// Entities not spawned in a world will not tick, be sent to players, or be - /// saved to the server files. - pub fn is_in_world(&self) -> Result> { + /// Returns true if this entity can breathe underwater and will not take + /// suffocation damage when its air supply reaches zero. + pub fn can_breathe_underwater(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); + let res = self.jni_ref().call_method( + &self.jni_object(), + "canBreatheUnderwater", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get this entity as an NBT string. - /// - /// This string should not be relied upon as a serializable value. - pub fn as_string(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); + #[deprecated] + /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. + pub fn category( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Crates an {@link EntitySnapshot} representing the current state of this entity. - pub fn create_snapshot( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + /// Sets whether the entity is invisible or not. + pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(invisible.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setInvisible", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether the entity is invisible or not. + pub fn is_invisible(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the specified attribute instance from the object. This instance will + /// be backed directly to the object and any changes will be visible at once. + pub fn get_attribute( + &self, + attribute: impl Into>, + ) -> Result>, Box> { + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAttribute", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::EntitySnapshot::from_raw( + Ok(Some(crate::attribute::AttributeInstance::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Creates a copy of this entity and all its data. Spawns the copy at the given location. - /// - /// Note: Players cannot be copied. - pub fn copy( + /// Deals the given amount of damage to this entity from a specified + /// {@link DamageSource}. + pub fn damage( &self, - to: std::option::Option>>, - ) -> Result, Box> { + amount: f64, + damage_source: std::option::Option>>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = to { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(amount); + args.push(val_1); + if let Some(a) = damage_source { + sig += "Lorg/bukkit/damage/DamageSource;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); - args.push(val_1); + args.push(val_2); } - sig += ")Lorg/bukkit/entity/Entity;"; + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); + .call_method(&self.jni_object(), "damage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. + pub fn health(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.d()?) } - /// Sets a metadata value in the implementing object's metadata store. - pub fn set_metadata( - &self, - metadata_key: impl Into, - new_metadata_value: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) - }); + /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is + /// dead. + pub fn set_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "setMetadata", + "setHealth", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a list of previously set metadata values from the implementing - /// object's metadata store. - pub fn get_metadata( - &self, - metadata_key: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); + /// Gets the entity's absorption amount. + pub fn absorption_amount(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref().call_method( &self.jni_object(), - "getMetadata", + "getAbsorptionAmount", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::metadata::MetadataValue::from_raw( - &self.jni_ref(), - obj, - )?); - } - Ok(new_vec) + Ok(res.d()?) } - /// Tests to see whether the implementing object contains the given - /// metadata value in its metadata store. - pub fn has_metadata( - &self, - metadata_key: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); + /// Sets the entity's absorption amount. + /// + /// Note: The amount is capped to the value of + /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on + /// that attribute is currently unspecified and subject to change. + pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "hasMetadata", + "setAbsorptionAmount", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the maximum health this entity has. + pub fn max_health(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Removes the given metadata value from the implementing object's - /// metadata store. - pub fn remove_metadata( - &self, - metadata_key: impl Into, - owning_plugin: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) - }); + #[deprecated] + /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. + pub fn set_max_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "removeMetadata", + "setMaxHealth", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sends this sender multiple messages - pub fn send_message( + #[deprecated] + /// Resets the max health to the original amount. + pub fn reset_max_health(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Launches a {@link Projectile} from the ProjectileSource with an + /// initial velocity. + pub fn launch_projectile( &self, - sender: impl Into>, - messages: std::option::Option>, - ) -> Result<(), Box> { + projectile: jni::objects::JClass<'mc>, + velocity: std::option::Option>>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) - }); + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(projectile.into()); args.push(val_1); - if let Some(a) = messages { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); + if let Some(a) = velocity { + sig += "Lorg/bukkit/util/Vector;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); args.push(val_2); } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the name of this command sender - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + sig += ")LT;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.l()?) } - /// Gets the custom name on a mob or block. If there is no name this method - /// will return null. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn custom_name(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); + /// This is the UUID of the specified AnimalTamer. + pub fn unique_id( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getCustomName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for HumanEntity<'mc> { + fn into(self) -> crate::entity::LivingEntity<'mc> { + crate::entity::LivingEntity::from_raw(&self.jni_ref(), self.1) + .expect("Error converting HumanEntity into crate::entity::LivingEntity") + } +} +impl<'mc> Into> for HumanEntity<'mc> { + fn into(self) -> crate::entity::AnimalTamer<'mc> { + crate::entity::AnimalTamer::from_raw(&self.jni_ref(), self.1) + .expect("Error converting HumanEntity into crate::entity::AnimalTamer") + } +} +impl<'mc> Into> for HumanEntity<'mc> { + fn into(self) -> crate::inventory::InventoryHolder<'mc> { + crate::inventory::InventoryHolder::from_raw(&self.jni_ref(), self.1) + .expect("Error converting HumanEntity into crate::inventory::InventoryHolder") + } +} +#[repr(C)] +pub struct EntityFactory<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for EntityFactory<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for EntityFactory<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate EntityFactory from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EntityFactory")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EntityFactory object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) } - /// Sets a custom name on a mob or block. This name will be used in death - /// messages and can be sent to the client as a nameplate over the mob. - /// - /// Setting the name to null or an empty string will clear it. +} + +impl<'mc> EntityFactory<'mc> { + /// Create a new EntitySnapshot with the supplied input. /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn set_custom_name( + /// Accepts strings in the format output by {@link EntitySnapshot#getAsString()}. + pub fn create_entity_snapshot( &self, - name: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); + input: impl Into, + ) -> Result, Box> { + let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/entity/EntitySnapshot;"); let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, + self.jni_ref().new_string(input.into())?, )); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomName", + "createEntitySnapshot", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPersistentDataContainer", - sig.as_str(), - vec![], - ); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + crate::entity::EntitySnapshot::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -32941,19 +39953,13 @@ impl<'mc> Damageable<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Damageable<'mc> { - fn into(self) -> crate::entity::Entity<'mc> { - crate::entity::Entity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Damageable into crate::entity::Entity") - } -} #[repr(C)] -pub struct Camel<'mc>( +pub struct Shulker<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Camel<'mc> { +impl<'mc> JNIRaw<'mc> for Shulker<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -32961,18 +39967,18 @@ impl<'mc> JNIRaw<'mc> for Camel<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Camel<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Shulker<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Camel from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Shulker from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Camel")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Shulker")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Camel object, got {}", + "Invalid argument passed. Expected a Shulker object, got {}", name ) .into()) @@ -32982,1025 +39988,1075 @@ impl<'mc> JNIInstantiatable<'mc> for Camel<'mc> { } } -impl<'mc> Camel<'mc> { - /// Gets whether this camel is dashing (sprinting). - pub fn is_dashing(&self) -> Result> { - let sig = String::from("()Z"); +impl<'mc> Shulker<'mc> { + /// Gets the peek state of the shulker between 0.0 and 1.0. + pub fn peek(&self) -> Result> { + let sig = String::from("()F"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isDashing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPeek", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.f()?) } - /// Sets whether this camel is dashing (sprinting). - pub fn set_dashing(&self, dashing: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(dashing.into()); + /// Sets the peek state of the shulker, should be in between 0.0 and 1.0. + pub fn set_peek(&self, value: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(value); let res = self.jni_ref().call_method( &self.jni_object(), - "setDashing", + "setPeek", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the horse's variant.A horse's variant defines its physical appearance and capabilities. Whether a horse is a regular horse, donkey, mule, or other kind of horse is determined using the variant. - pub fn variant(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Horse/Variant;"); + /// Gets the face to which the shulker is attached. + pub fn attached_face( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAttachedFace", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::HorseVariant::from_raw(&self.jni_ref(), unsafe { + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - #[deprecated] - - pub fn set_variant( + /// Sets the face to which the shulker is attached. + pub fn set_attached_face( &self, - variant: impl Into>, + face: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Horse/Variant;)V"); + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(variant.into().jni_object().clone()) + jni::objects::JObject::from_raw(face.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVariant", + "setAttachedFace", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the domestication level of this horse. + /// Gets the color of this object. /// - /// A higher domestication level indicates that the horse is closer to - /// becoming tame. As the domestication level gets closer to the max - /// domestication level, the chance of the horse becoming tame increases. - pub fn domestication(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getDomestication", - sig.as_str(), - vec![], - ); + /// This may be null to represent the default color of an object, if the + /// object has a special default color (e.g Shulkers). + pub fn color(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/DyeColor;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::DyeColor::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Sets the domestication level of this horse. - /// - /// Setting the domestication level to a high value will increase the - /// horse's chances of becoming tame. + /// Sets the color of this object to the specified DyeColor. /// - /// Domestication level must be greater than zero and no greater than - /// the max domestication level of the horse, determined with - /// {@link #getMaxDomestication()} - pub fn set_domestication(&self, level: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(level); + /// This may be null to represent the default color of an object, if the + /// object has a special default color (e.g Shulkers). + pub fn set_color( + &self, + color: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/DyeColor;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(color.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setDomestication", + "setColor", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the maximum domestication level of this horse. - /// - /// The higher this level is, the longer it will likely take - /// for the horse to be tamed. - pub fn max_domestication(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMaxDomestication", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the maximum domestication level of this horse. - /// - /// Setting a higher max domestication will increase the amount of - /// domesticating (feeding, riding, etc.) necessary in order to tame it, - /// while setting a lower max value will have the opposite effect. - /// - /// Maximum domestication must be greater than zero. - pub fn set_max_domestication(&self, level: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(level); + /// Gets the height of the living entity's eyes above its Location. + pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { + let sig = String::from("(Z)D"); + let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxDomestication", + "getEyeHeight", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } - /// Gets the jump strength of this horse. - /// - /// Jump strength defines how high the horse can jump. A higher jump strength - /// increases how high a jump will go. - pub fn jump_strength(&self) -> Result> { - let sig = String::from("()D"); + /// Get a Location detailing the current eye position of the living entity. + pub fn eye_location(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getJumpStrength", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the jump strength of this horse. + /// Gets all blocks along the living entity's line of sight. /// - /// A higher jump strength increases how high a jump will go. - /// Setting a jump strength to 0 will result in no jump. - /// You cannot set a jump strength to a value below 0 or - /// above 2. - pub fn set_jump_strength(&self, strength: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(strength); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setJumpStrength", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether the horse is currently grazing hay. - pub fn is_eating_haystack(&self) -> Result> { - let sig = String::from("()Z"); + /// This list contains all blocks from the living entity's eye position to + /// target inclusive. This method considers all blocks as 1x1x1 in size. + pub fn get_line_of_sight( + &self, + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "isEatingHaystack", + "getLineOfSight", sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Sets whether the horse is grazing hay. - pub fn set_eating_haystack( + /// Gets the block that the living entity has targeted. + /// + /// This method considers all blocks as 1x1x1 in size. To take exact block + /// collision shapes into account, see {@link #getTargetBlockExact(int, + /// FluidCollisionMode)}. + pub fn get_target_block( &self, - eating_haystack: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(eating_haystack.into()); + transparent: impl Into>, + max_distance: i32, + ) -> Result, Box> { + let sig = String::from("(Ljava/util/Set;I)Lorg/bukkit/block/Block;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setEatingHaystack", + "getTargetBlock", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/AbstractHorseInventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::AbstractHorseInventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the vehicle's velocity. - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + crate::block::Block::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the vehicle's velocity in meters per tick. - pub fn set_velocity( + /// Gets the last two blocks along the living entity's line of sight. + /// + /// The target block will be the last block in the list. This method + /// considers all blocks as 1x1x1 in size. + pub fn get_last_two_target_blocks( &self, - vel: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(vel.into().jni_object().clone()) + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setVelocity", + "getLastTwoTargetBlocks", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Check if this is tamed - /// - /// If something is tamed then a player can not tame it through normal - /// methods, even if it does not belong to anyone in particular. - pub fn is_tamed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isTamed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Sets if this has been tamed. Not necessary if the method setOwner has - /// been used, as it tames automatically. + /// Gets the block that the living entity has targeted. /// - /// If something is tamed then a player can not tame it through normal - /// methods, even if it does not belong to anyone in particular. - pub fn set_tamed(&self, tame: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(tame.into()); + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn get_target_block_exact( + &self, + max_distance: i32, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/block/Block;"; let res = self.jni_ref().call_method( &self.jni_object(), - "setTamed", + "getTargetBlockExact", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the current owning AnimalTamer - pub fn owner( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/AnimalTamer;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::AnimalTamer::from_raw( + Ok(Some(crate::block::Block::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Set this to be owned by given AnimalTamer. + /// Performs a ray trace that provides information on the targeted block. /// - /// If the owner is not null, this will be tamed and will have any current - /// path it is following removed. If the owner is set to null, this will be - /// untamed, and the current owner removed. - pub fn set_owner( + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn ray_trace_blocks( &self, - tamer: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/AnimalTamer;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tamer.into().jni_object().clone()) - }); + max_distance: f64, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/util/RayTraceResult;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::util::RayTraceResult::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Returns the amount of air that the living entity has remaining, in + /// ticks. + pub fn remaining_air(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the amount of air that the living entity has remaining, in ticks. + pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setOwner", + "setRemainingAir", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if this animal is sitting - pub fn is_sitting(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSitting", sig.as_str(), vec![]); + /// Returns the maximum amount of air the living entity can have, in ticks. + pub fn maximum_air(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets if this animal is sitting. Will remove any path that the animal - /// was following beforehand. - pub fn set_sitting(&self, sitting: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(sitting.into()); + /// Sets the maximum amount of air the living entity can have, in ticks. + pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setSitting", + "setMaximumAir", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Camel<'mc> { - fn into(self) -> crate::entity::AbstractHorse<'mc> { - crate::entity::AbstractHorse::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Camel into crate::entity::AbstractHorse") - } -} -impl<'mc> Into> for Camel<'mc> { - fn into(self) -> crate::entity::Sittable<'mc> { - crate::entity::Sittable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Camel into crate::entity::Sittable") - } -} -#[repr(C)] -pub struct Husk<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Husk<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Husk<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Husk from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Husk")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Husk object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Husk<'mc> { - /// Get if this entity is in the process of converting to a Zombie as a - /// result of being underwater. - pub fn is_converting(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the item that the player is using (eating food, drawing back a bow, + /// blocking, etc.) + pub fn item_in_use( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isConverting", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets the amount of ticks until this entity will be converted to a Zombie - /// as a result of being underwater. - /// When this reaches 0, the entity will be converted. - pub fn conversion_time(&self) -> Result> { + /// Gets the number of ticks remaining for the current item's usage. + pub fn item_in_use_ticks(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getConversionTime", + "getItemInUseTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the amount of ticks until this entity will be converted to a Zombie - /// as a result of being underwater. - /// When this reaches 0, the entity will be converted. A value of less than 0 - /// will stop the current conversion process without converting the current - /// entity. - pub fn set_conversion_time(&self, time: i32) -> Result<(), Box> { + /// Sets the number of ticks that remain for the current item's usage. + /// Applies to items that take time to use, like eating food, drawing a bow, + /// or throwing a trident. + pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(time); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setConversionTime", + "setItemInUseTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets whether the zombie is a baby - pub fn is_baby(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isBaby", sig.as_str(), vec![]); + /// Gets the time in ticks until the next arrow leaves the entity's body. + pub fn arrow_cooldown(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getArrowCooldown", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - #[deprecated] - /// Sets whether the zombie is a baby - pub fn set_baby(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Sets the time in ticks until the next arrow leaves the entity's body. + pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setBaby", + "setArrowCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets whether the zombie is a villager - pub fn is_villager(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the amount of arrows in an entity's body. + pub fn arrows_in_body(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isVillager", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - #[deprecated] - - pub fn set_villager(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Set the amount of arrows in the entity's body. + pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(count); let res = self.jni_ref().call_method( &self.jni_object(), - "setVillager", + "setArrowsInBody", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - - pub fn set_villager_profession( - &self, - profession: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Villager/Profession;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(profession.into().jni_object().clone()) - }); + /// Returns the living entity's current maximum no damage ticks. + /// + /// This is the maximum duration in which the living entity will not take + /// damage. + pub fn maximum_no_damage_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "setVillagerProfession", + "getMaximumNoDamageTicks", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - #[deprecated] - - pub fn villager_profession( + /// Sets the living entity's current maximum no damage ticks. + pub fn set_maximum_no_damage_ticks( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Villager/Profession;"); + ticks: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "getVillagerProfession", + "setMaximumNoDamageTicks", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::VillagerProfession::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets whether this zombie can break doors - pub fn can_break_doors(&self) -> Result> { - let sig = String::from("()Z"); + /// Returns the living entity's last damage taken in the current no damage + /// ticks time. + /// + /// Only damage higher than this amount will further damage the living + /// entity. + pub fn last_damage(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "canBreakDoors", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Sets whether this zombie can break doors - /// This will be ignored if the entity is a Drowned. Will also stop the action if - /// the entity is currently breaking a door. - pub fn set_can_break_doors(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Sets the damage dealt within the current no damage ticks time period. + pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(damage); let res = self.jni_ref().call_method( &self.jni_object(), - "setCanBreakDoors", + "setLastDamage", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Husk<'mc> { - fn into(self) -> crate::entity::Zombie<'mc> { - crate::entity::Zombie::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Husk into crate::entity::Zombie") - } -} -#[repr(C)] -pub struct Witch<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Witch<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Returns the living entity's current no damage ticks. + pub fn no_damage_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNoDamageTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} -impl<'mc> JNIInstantiatable<'mc> for Witch<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Witch from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Witch")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Witch object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Sets the living entity's current no damage ticks. + pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setNoDamageTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> Witch<'mc> { - /// Gets whether the witch is drinking a potion - pub fn is_drinking_potion(&self) -> Result> { - let sig = String::from("()Z"); + /// Get the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn no_action_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "isDrinkingPotion", + "getNoActionTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Set the {@link Raid} that this raider is participating in. - pub fn set_raid( - &self, - raid: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Raid;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(raid.into().jni_object().clone()) - }); + /// Set the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setRaid", + "setNoActionTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the {@link Raid} that this raider is participating in, if any. - pub fn raid(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Raid;"); + /// Gets the player identified as the killer of the living entity. + /// + /// May be null. + pub fn killer(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getRaid", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Raid::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(Some(crate::entity::Player::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Get the raid wave that this raider spawned as part of. - pub fn wave(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWave", sig.as_str(), vec![]); + #[deprecated] + /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. + pub fn add_potion_effect( + &self, + effect: impl Into>, + force: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/potion/PotionEffect;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = force { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the raid wave that this raider was spawned as part of. - pub fn set_wave(&self, wave: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(wave); + /// Returns whether the living entity already has an existing effect of + /// the given {@link PotionEffectType} applied to it. + pub fn has_potion_effect( + &self, + val_type: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setWave", + "hasPotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the block the raider is targeting to patrol. - pub fn patrol_target( + /// Returns the active {@link PotionEffect} of the specified type. + /// + /// If the effect is not present on the entity then null will be returned. + pub fn get_potion_effect( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPatrolTarget", sig.as_str(), vec![]); + val_type: impl Into>, + ) -> Result>, Box> { + let sig = + String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPotionEffect", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::block::Block::from_raw( + Ok(Some(crate::potion::PotionEffect::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets the block the raider is targeting to patrol. - pub fn set_patrol_target( + /// Removes any effects present of the given {@link PotionEffectType}. + pub fn remove_potion_effect( &self, - block: impl Into>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/Block;)V"); + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPatrolTarget", + "removePotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether this entity is a patrol leader. - pub fn is_patrol_leader(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isPatrolLeader", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether this entity is a patrol leader. - pub fn set_patrol_leader(&self, leader: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(leader.into()); + /// Returns all currently active {@link PotionEffect}s on the living + /// entity. + pub fn active_potion_effects( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setPatrolLeader", + "getActivePotionEffects", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether this mob can join an active raid. - pub fn is_can_join_raid(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCanJoinRaid", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Sets whether this mob can join an active raid. - pub fn set_can_join_raid(&self, join: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(join.into()); + /// Checks whether the living entity has block line of sight to another. + /// + /// This uses the same algorithm that hostile mobs use to find the closest + /// player. + pub fn has_line_of_sight( + &self, + other: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(other.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCanJoinRaid", + "hasLineOfSight", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Get the amount of ticks that this mob has exited the bounds of a village - /// as a raid participant. + /// Returns if the living entity despawns when away from players or not. /// - /// This value is increased only when the mob has had no action for 2,400 ticks - /// (according to {@link #getNoActionTicks()}). Once both the no action ticks have - /// reached that value and the ticks outside a raid exceeds 30, the mob will be - /// expelled from the raid. - pub fn ticks_outside_raid(&self) -> Result> { - let sig = String::from("()I"); + /// By default, animals are not removed while other mobs are. + pub fn remove_when_far_away(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getTicksOutsideRaid", + "getRemoveWhenFarAway", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the amount of ticks that this mob has exited the bounds of a village - /// as a raid participant. - /// - /// This value is considered only when the mob has had no action for 2,400 ticks - /// (according to {@link #getNoActionTicks()}). Once both the no action ticks have - /// reached that value and the ticks outside a raid exceeds 30, the mob will be - /// expelled from the raid. - pub fn set_ticks_outside_raid(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets whether or not the living entity despawns when away from players + /// or not. + pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(remove.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setTicksOutsideRaid", + "setRemoveWhenFarAway", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check whether or not this raider is celebrating a raid victory. - pub fn is_celebrating(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the inventory with the equipment worn by the living entity. + pub fn equipment( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCelebrating", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::EntityEquipment::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Set whether or not this mob is celebrating a raid victory. - pub fn set_celebrating(&self, celebrating: bool) -> Result<(), Box> { + /// Sets whether or not the living entity can pick up items. + pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(celebrating.into()); + let val_1 = jni::objects::JValueGen::Bool(pickup.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCelebrating", + "setCanPickupItems", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the {@link Sound} this entity will play when celebrating. - pub fn celebration_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Gets if the living entity can pick up items. + pub fn can_pickup_items(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCelebrationSound", + "getCanPickupItems", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Witch<'mc> { - fn into(self) -> crate::entity::Raider<'mc> { - crate::entity::Raider::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Witch into crate::entity::Raider") - } -} -#[repr(C)] -pub struct FallingBlock<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for FallingBlock<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for FallingBlock<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate FallingBlock from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/FallingBlock")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a FallingBlock object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> FallingBlock<'mc> { - #[deprecated] - /// Get the Material of the falling block - pub fn material(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaterial", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Get the data for the falling block - pub fn block_data( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); + /// Returns whether the entity is currently leashed. + pub fn is_leashed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the entity that is currently leading this entity. + pub fn leash_holder(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBlockData", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get if the falling block will break into an item if it cannot be placed. + /// Sets the leash on this entity to be held by the supplied entity. /// - /// Note that if {@link #getCancelDrop()} is {@code true}, the falling block - /// will not drop an item regardless of whether or not the returned value is - /// {@code true}. - pub fn drop_item(&self) -> Result> { + /// This method has no effect on EnderDragons, Withers, Players, or Bats. + /// Non-living entities excluding leashes will not persist as leash + /// holders. + pub fn set_leash_holder( + &self, + holder: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(holder.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLeashHolder", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks to see if an entity is gliding, such as using an Elytra. + pub fn is_gliding(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Makes entity start or stop gliding. This will work even if an Elytra + /// is not equipped, but will be reverted by the server immediately after + /// unless an event-cancelling mechanism is put in place. + pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gliding.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setGliding", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks to see if an entity is swimming. + pub fn is_swimming(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDropItem", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set if the falling block will break into an item if it cannot be placed. - /// - /// Note that if {@link #getCancelDrop()} is {@code true}, the falling block - /// will not drop an item regardless of whether or not the value is set to - /// {@code true}. - pub fn set_drop_item(&self, drop: bool) -> Result<(), Box> { + /// Makes entity start or stop swimming. + /// This may have unexpected results if the entity is not in water. + pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(drop.into()); + let val_1 = jni::objects::JValueGen::Bool(swimming.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setDropItem", + "setSwimming", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get if the falling block will not become a block upon landing and not drop - /// an item. - /// - /// Unlike {@link #getDropItem()}, this property will prevent the block from - /// forming into a block when it lands, causing it to disappear. If this property - /// is true and {@link #getDropItem()} is true, an item will NOT - /// be dropped. - pub fn cancel_drop(&self) -> Result> { + /// Checks to see if an entity is currently riptiding. + pub fn is_riptiding(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getCancelDrop", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get if the falling block will not become a block upon landing and not drop - /// an item. + /// Makes entity start or stop riptiding. /// - /// Unlike {@link #setDropItem(boolean)}, this property will prevent the block - /// from forming into a block when it lands, causing it to disappear. If this - /// property is true and {@link #getDropItem()} is true, an item will - /// NOT be dropped. - pub fn set_cancel_drop(&self, cancel_drop: bool) -> Result<(), Box> { + /// Note: This does not damage attackable entities. + pub fn set_riptiding(&self, riptiding: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel_drop.into()); + let val_1 = jni::objects::JValueGen::Bool(riptiding.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCancelDrop", + "setRiptiding", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the HurtEntities state of this block. - pub fn can_hurt_entities(&self) -> Result> { + /// Returns whether this entity is slumbering. + pub fn is_sleeping(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "canHurtEntities", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set the HurtEntities state of this block. - pub fn set_hurt_entities(&self, hurt_entities: bool) -> Result<(), Box> { + /// Gets if the entity is climbing. + pub fn is_climbing(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether an entity will have AI. + /// The entity will be completely unable to move if it has no AI. + pub fn set_ai(&self, ai: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(hurt_entities.into()); + let val_1 = jni::objects::JValueGen::Bool(ai.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setHurtEntities", + "setAI", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the amount of damage inflicted upon entities multiplied by the distance - /// that the block had fallen when this falling block lands on them. - pub fn damage_per_block(&self) -> Result> { - let sig = String::from("()F"); + /// Checks whether an entity has AI. + /// The entity will be completely unable to move if it has no AI. + pub fn has_ai(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Makes this entity attack the given entity with a melee attack. + /// Attack damage is calculated by the server from the attributes and + /// equipment of this mob, and knockback is applied to {@code target} as + /// appropriate. + pub fn attack( + &self, + target: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(target.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getDamagePerBlock", + "attack", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Set the amount of damage inflicted upon entities multiplied by the distance - /// that the block had fallen when this falling block lands on them. - /// - /// If {@code damage} is non-zero, this method will automatically call - /// {@link #setHurtEntities(boolean) setHurtEntities(true)}. - pub fn set_damage_per_block(&self, damage: f32) -> Result<(), Box> { + /// Makes this entity swing their main hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their main hand. + pub fn swing_main_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Makes this entity swing their off hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their off hand. + pub fn swing_off_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Makes this entity flash red as if they were damaged. + pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(damage); + let val_1 = jni::objects::JValueGen::Float(yaw); let res = self.jni_ref().call_method( &self.jni_object(), - "setDamagePerBlock", + "playHurtAnimation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the maximum amount of damage that can be inflicted upon entities when - /// this falling block lands on them. - pub fn max_damage(&self) -> Result> { - let sig = String::from("()I"); + /// Set if this entity will be subject to collisions with other entities. + /// + /// Exemptions to this rule can be managed with + /// {@link #getCollidableExemptions()} + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not working for player collisions. This + /// method should therefore only be used to set the collision status of + /// non-player entities. + /// + /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in + /// combination with a {@link Scoreboard} and a {@link Team}. + pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(collidable.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCollidable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if this entity is subject to collisions with other entities. + /// + /// Some entities might be exempted from the collidable rule of this entity. + /// Use {@link #getCollidableExemptions()} to get these. + /// + /// Please note that this method returns only the custom collidable state, + /// not whether the entity is non-collidable for other reasons such as being + /// dead. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not being accurate for player collisions. + /// This method should therefore only be used to check the collision status + /// of non-player entities. + /// + /// To check the collision behavior for a player, use + /// {@link Team.Option#COLLISION_RULE} in combination with a + /// {@link Scoreboard} and a {@link Team}. + pub fn is_collidable(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxDamage", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the maximum amount of damage that can be inflicted upon entities when - /// this falling block lands on them. + /// Gets a mutable set of UUIDs of the entities which are exempt from the + /// entity's collidable rule and which's collision with this entity will + /// behave the opposite of it. /// - /// If {@code damage} is non-zero, this method will automatically call - /// {@link #setHurtEntities(boolean) setHurtEntities(true)}. - pub fn set_max_damage(&self, damage: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(damage); + /// This set can be modified to add or remove exemptions. + /// + /// For example if collidable is true and an entity is in the exemptions set + /// then it will not collide with it. Similarly if collidable is false and an + /// entity is in this set then it will still collide with it. + /// + /// Note these exemptions are not (currently) persistent. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in those exemptions not being accurate for player + /// collisions. This method should therefore only be used to exempt + /// non-player entities. + /// + /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} + /// in combination with a {@link Scoreboard} and a {@link Team}. + pub fn collidable_exemptions( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxDamage", + "getCollidableExemptions", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Stores the entity's current position in the provided Location object. + /// Returns the value of the memory specified. /// - /// If the provided Location is null this method does nothing and returns - /// null. - pub fn get_location( + /// Note that the value is null when the specific entity does not have that + /// value by default. + pub fn get_memory( &self, - loc: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + memory_key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocation", + "getMemory", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -34008,497 +41064,548 @@ impl<'mc> FallingBlock<'mc> { if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(Some(res.l()?)) } - /// Sets this entity's velocity in meters per tick - pub fn set_velocity( + /// Sets the value of the memory specified. + /// + /// Note that the value will not be persisted when the specific entity does + /// not have that value by default. + pub fn set_memory( &self, - velocity: impl Into>, + memory_key: impl Into>, + memory_value: jni::objects::JObject<'mc>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Object(memory_value); let res = self.jni_ref().call_method( &self.jni_object(), - "setVelocity", + "setMemory", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets this entity's current velocity - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); + /// Get the {@link Sound} this entity will make when damaged. + pub fn hurt_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the entity's height - pub fn height(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the entity's width - pub fn width(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + })?)) } - /// Gets the entity's current bounding box. - /// - /// The returned bounding box reflects the entity's current location and - /// size. - pub fn bounding_box( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); + /// Get the {@link Sound} this entity will make on death. + pub fn death_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns true if the entity is supported by a block. This value is a - /// state updated by the server and is not recalculated unless the entity - /// moves. - pub fn is_on_ground(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + })?)) } - /// Returns true if the entity is in water. - pub fn is_in_water(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); + /// Get the {@link Sound} this entity will make when falling from the given + /// height (in blocks). The sound will often differ between either a small + /// or a big fall damage sound if the height exceeds 4 blocks. + pub fn get_fall_damage_sound( + &self, + fall_height: i32, + ) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Int(fall_height); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getFallDamageSound", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the current world this entity resides in - pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + /// Get the {@link Sound} this entity will make when falling from a small + /// height. + pub fn fall_damage_sound_small(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getFallDamageSoundSmall", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { + crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the entity's rotation. - /// - /// Note that if the entity is affected by AI, it may override this rotation. - pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { - let sig = String::from("(FF)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); - let val_2 = jni::objects::JValueGen::Float(pitch); + /// Get the {@link Sound} this entity will make when falling from a large + /// height. + pub fn fall_damage_sound_big(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setRotation", + "getFallDamageSoundBig", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Teleports this entity to the given location. If this entity is riding a - /// vehicle, it will be dismounted prior to teleportation. - pub fn teleport( + /// Get the {@link Sound} this entity will make when drinking the given + /// {@link ItemStack}. + pub fn get_drinking_sound( &self, - location: impl Into>, - cause: std::option::Option< - impl Into>, - >, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) }); - args.push(val_1); - if let Some(a) = cause { - sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "teleport", sig.as_str(), args); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDrinkingSound", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns a list of entities within a bounding box centered around this - /// entity - pub fn get_nearby_entities( + /// Get the {@link Sound} this entity will make when eating the given + /// {@link ItemStack}. + pub fn get_eating_sound( &self, - x: f64, - y: f64, - z: f64, - ) -> Result>, Box> { - let sig = String::from("(DDD)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Double(x); - let val_2 = jni::objects::JValueGen::Double(y); - let val_3 = jni::objects::JValueGen::Double(z); + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getNearbyEntities", + "getEatingSound", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns a unique id for this entity - pub fn entity_id(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); + /// Returns true if this entity can breathe underwater and will not take + /// suffocation damage when its air supply reaches zero. + pub fn can_breathe_underwater(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "canBreatheUnderwater", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Returns the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn fire_ticks(&self) -> Result> { - let sig = String::from("()I"); + #[deprecated] + /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. + pub fn category( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the entity's maximum fire ticks. - pub fn max_fire_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Sets whether the entity is invisible or not. + pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(invisible.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setInvisible", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether the entity is invisible or not. + pub fn is_invisible(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Gets the specified attribute instance from the object. This instance will + /// be backed directly to the object and any changes will be visible at once. + pub fn get_attribute( + &self, + attribute: impl Into>, + ) -> Result>, Box> { + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setFireTicks", + "getAttribute", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::attribute::AttributeInstance::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Deals the given amount of damage to this entity from a specified + /// {@link DamageSource}. + pub fn damage( + &self, + amount: f64, + damage_source: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(amount); + args.push(val_1); + if let Some(a) = damage_source { + sig += "Lorg/bukkit/damage/DamageSource;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "damage", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets if the entity has visual fire (it will always appear to be on fire). - pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire.into()); + /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. + pub fn health(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is + /// dead. + pub fn set_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisualFire", + "setHealth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity has visual fire (it will always appear to be on fire). - pub fn is_visual_fire(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the entity's maximum freeze ticks (amount of ticks before it will - /// be fully frozen) - pub fn max_freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the entity's absorption amount. + pub fn absorption_amount(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref().call_method( &self.jni_object(), - "getMaxFreezeTicks", + "getAbsorptionAmount", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.d()?) } - /// Sets the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets the entity's absorption amount. + /// + /// Note: The amount is capped to the value of + /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on + /// that attribute is currently unspecified and subject to change. + pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "setFreezeTicks", + "setAbsorptionAmount", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity is fully frozen (it has been in powdered snow for max - /// freeze ticks). - pub fn is_frozen(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); + #[deprecated] + /// Gets the maximum health this entity has. + pub fn max_health(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Mark the entity's removal. - pub fn remove(&self) -> Result<(), Box> { + #[deprecated] + /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. + pub fn set_max_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaxHealth", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Resets the max health to the original amount. + pub fn reset_max_health(&self) -> Result<(), Box> { let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns true if this entity has been marked for removal. - pub fn is_dead(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); + /// Launches a {@link Projectile} from the ProjectileSource with an + /// initial velocity. + pub fn launch_projectile( + &self, + projectile: jni::objects::JClass<'mc>, + velocity: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(projectile.into()); + args.push(val_1); + if let Some(a) = velocity { + sig += "Lorg/bukkit/util/Vector;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")LT;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.l()?) } - /// Returns false if the entity has died, been despawned for some other - /// reason, or has not been added to the world. - pub fn is_valid(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Gets the {@link Server} that contains this Entity - pub fn server(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Server;"); +} +impl<'mc> Into> for Shulker<'mc> { + fn into(self) -> crate::entity::Golem<'mc> { + crate::entity::Golem::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Shulker into crate::entity::Golem") + } +} +impl<'mc> Into> for Shulker<'mc> { + fn into(self) -> crate::material::Colorable<'mc> { + crate::material::Colorable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Shulker into crate::material::Colorable") + } +} +impl<'mc> Into> for Shulker<'mc> { + fn into(self) -> crate::entity::Enemy<'mc> { + crate::entity::Enemy::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Shulker into crate::entity::Enemy") + } +} +#[repr(C)] +pub struct PigZombie<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PigZombie<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PigZombie<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate PigZombie from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/PigZombie")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PigZombie object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> PigZombie<'mc> { + /// Get the pig zombie's current anger level. + pub fn anger(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Server::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns true if the entity gets persisted. - /// - /// By default all entities are persistent. An entity will also not get - /// persisted, if it is riding an entity that is not persistent. - /// - /// The persistent flag on players controls whether or not to save their - /// playerdata file when they quit. If a player is directly or indirectly - /// riding a non-persistent entity, the vehicle at the root and all its - /// passengers won't get persisted. - /// - /// This should not be confused with - /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls - /// despawning of living entities. - pub fn is_persistent(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAnger", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets whether or not the entity gets persisted. - pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(persistent.into()); + /// Set the pig zombie's current anger level. + pub fn set_anger(&self, level: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(level); let res = self.jni_ref().call_method( &self.jni_object(), - "setPersistent", + "setAnger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. - pub fn passenger( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - #[deprecated] - /// Set the passenger of a vehicle. - pub fn set_passenger( - &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); + /// Shorthand; sets to either 0 or the default level. + pub fn set_angry(&self, angry: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(angry.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setPassenger", + "setAngry", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Shorthand; gets whether the zombie is angry. + pub fn is_angry(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isAngry", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets a list of passengers of this vehicle. - /// - /// The returned list will not be directly linked to the entity's current - /// passengers, and no guarantees are made as to its mutability. - pub fn passengers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + /// Not applicable to this entity + pub fn is_converting(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isConverting", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(res.z()?) } - /// Add a passenger to the vehicle. - pub fn add_passenger( - &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); + /// Not applicable to this entity + pub fn conversion_time(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "addPassenger", + "getConversionTime", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Remove a passenger from the vehicle. - pub fn remove_passenger( - &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); + /// Not applicable to this entity + pub fn set_conversion_time(&self, time: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(time); let res = self.jni_ref().call_method( &self.jni_object(), - "removePassenger", + "setConversionTime", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Check if a vehicle has passengers. - pub fn is_empty(&self) -> Result> { + #[deprecated] + /// Gets whether the zombie is a baby + pub fn is_baby(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isBaby", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Eject any passenger. - pub fn eject(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + #[deprecated] + /// Sets whether the zombie is a baby + pub fn set_baby(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBaby", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns the distance this entity has fallen - pub fn fall_distance(&self) -> Result> { - let sig = String::from("()F"); + #[deprecated] + /// Gets whether the zombie is a villager + pub fn is_villager(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isVillager", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + Ok(res.z()?) } - /// Sets the fall distance for this entity - pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(distance); + #[deprecated] + + pub fn set_villager(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setFallDistance", + "setVillager", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -34506,34 +41613,33 @@ impl<'mc> FallingBlock<'mc> { Ok(()) } #[deprecated] - /// Record the last {@link EntityDamageEvent} inflicted on this entity - pub fn set_last_damage_cause( + + pub fn set_villager_profession( &self, - event: impl Into>, + profession: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); + let sig = String::from("(Lorg/bukkit/entity/Villager/Profession;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(event.into().jni_object().clone()) + jni::objects::JObject::from_raw(profession.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDamageCause", + "setVillagerProfession", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. - /// This event may have been cancelled. - pub fn last_damage_cause( + #[deprecated] + + pub fn villager_profession( &self, - ) -> Result>, Box> - { - let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Villager/Profession;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLastDamageCause", + "getVillagerProfession", sig.as_str(), vec![], ); @@ -34541,763 +41647,711 @@ impl<'mc> FallingBlock<'mc> { if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( + Ok(Some(crate::entity::VillagerProfession::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Returns a unique and persistent id for this entity - pub fn unique_id( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. - pub fn ticks_lived(&self) -> Result> { - let sig = String::from("()I"); + /// Gets whether this zombie can break doors + pub fn can_break_doors(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "canBreakDoors", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. May not be less than one - /// tick. - pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(value); + /// Sets whether this zombie can break doors + /// This will be ignored if the entity is a Drowned. Will also stop the action if + /// the entity is currently breaking a door. + pub fn set_can_break_doors(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setTicksLived", + "setCanBreakDoors", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Performs the specified {@link EntityEffect} for this entity. - /// - /// This will be viewable to all players near the entity. - /// - /// If the effect is not applicable to this class of entity, it will not play. - pub fn play_effect( + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for PigZombie<'mc> { + fn into(self) -> crate::entity::Zombie<'mc> { + crate::entity::Zombie::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PigZombie into crate::entity::Zombie") + } +} +#[repr(C)] +pub struct Arrow<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Arrow<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Arrow<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Arrow from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Arrow")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Arrow object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Arrow<'mc> { + #[deprecated] + /// Sets the underlying potion data + pub fn set_base_potion_data( &self, - val_type: impl Into>, + data: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); + let sig = String::from("(Lorg/bukkit/potion/PotionData;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(data.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "playEffect", + "setBasePotionData", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the type of the entity. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity makes while swimming. - pub fn swim_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity makes when splashing in water. For most - /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_splash_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSwimSplashSound", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity makes when splashing in water at high - /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_high_speed_splash_sound( + #[deprecated] + /// Returns the potion data about the base potion + pub fn base_potion_data( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/potion/PotionData;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimHighSpeedSplashSound", + "getBasePotionData", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns whether this entity is inside a vehicle. - pub fn is_inside_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Leave the current vehicle. If the entity is currently in a vehicle (and - /// is removed from it), true will be returned, otherwise false will be - /// returned. - pub fn leave_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the vehicle that this entity is inside. If there is no vehicle, - /// null will be returned. - pub fn vehicle( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Entity::from_raw( + Ok(Some(crate::potion::PotionData::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets whether or not to display the mob's custom name client side. The - /// name will be displayed above the mob similarly to a player. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Sets the underlying potion type + pub fn set_base_potion_type( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/potion/PotionType;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomNameVisible", + "setBasePotionType", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not the mob's custom name is displayed client side. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn is_custom_name_visible(&self) -> Result> { - let sig = String::from("()Z"); + /// Returns the potion type about the base potion + pub fn base_potion_type( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/potion/PotionType;"); let res = self.jni_ref().call_method( &self.jni_object(), - "isCustomNameVisible", + "getBasePotionType", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::potion::PotionType::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(visible.into()); + /// Gets the color of this arrow. + pub fn color(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Color;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Color::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Sets the color of this arrow. Will be applied as a tint to its particles. + pub fn set_color( + &self, + color: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Color;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(color.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisibleByDefault", + "setColor", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn is_visible_by_default(&self) -> Result> { + /// Checks for the presence of custom potion effects. + pub fn has_custom_effects(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "isVisibleByDefault", + "hasCustomEffects", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get all players that are currently tracking this entity. + /// Gets an immutable list containing all custom potion effects applied to + /// this arrow. /// - /// 'Tracking' means that this entity has been sent to the player and that - /// they are receiving updates on its state. Note that the client's {@code - /// 'Entity Distance'} setting does not affect the range at which entities - /// are tracked. - pub fn tracked_by( + /// Plugins should check that hasCustomEffects() returns true before calling + /// this method. + pub fn custom_effects( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets whether the entity has a team colored (default: white) glow. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setGlowing", + "getCustomEffects", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether the entity is glowing or not. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn is_glowing(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Sets whether the entity is invulnerable or not. - /// - /// When an entity is invulnerable it can only be damaged by players in - /// creative mode. - pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Adds a custom potion effect to this arrow. + pub fn add_custom_effect( + &self, + effect: impl Into>, + overwrite: bool, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffect;Z)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Bool(overwrite.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvulnerable", + "addCustomEffect", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether the entity is invulnerable or not. - pub fn is_invulnerable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets whether the entity is silent or not. - pub fn is_silent(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the entity is silent or not. - /// - /// When an entity is silent it will not produce any sound. - pub fn set_silent(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Removes a custom potion effect from this arrow. + pub fn remove_custom_effect( + &self, + val_type: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setSilent", + "removeCustomEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns whether gravity applies to this entity. - pub fn has_gravity(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether gravity applies to this entity. - pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gravity.into()); + /// Checks for a specific custom potion effect type on this arrow. + pub fn has_custom_effect( + &self, + val_type: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setGravity", + "hasCustomEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the period of time (in ticks) before this entity can use a portal. - pub fn portal_cooldown(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPortalCooldown", - sig.as_str(), - vec![], - ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the period of time (in ticks) before this entity can use a portal. - pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(cooldown); + /// Removes all custom potion effects from this arrow. + pub fn clear_custom_effects(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref().call_method( &self.jni_object(), - "setPortalCooldown", + "clearCustomEffects", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a set of tags for this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn scoreboard_tags( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + #[deprecated] + /// Gets the knockback strength for an arrow, which is the {@link org.bukkit.enchantments.Enchantment#KNOCKBACK KnockBack} level of the bow that shot it. + pub fn knockback_strength(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getScoreboardTags", + "getKnockbackStrength", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Add a tag to this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn add_scoreboard_tag( + #[deprecated] + /// Sets the knockback strength for an arrow. + pub fn set_knockback_strength( &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); + knockback_strength: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(knockback_strength); let res = self.jni_ref().call_method( &self.jni_object(), - "addScoreboardTag", + "setKnockbackStrength", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the base amount of damage this arrow will do. + /// Defaults to 2.0 for a normal arrow with + /// 0.5 * (1 + power level) added for arrows fired from + /// enchanted bows. + pub fn damage(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getDamage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Removes a given tag from this entity. - pub fn remove_scoreboard_tag( - &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); + /// Sets the base amount of damage this arrow will do. + pub fn set_damage(&self, damage: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(damage); let res = self.jni_ref().call_method( &self.jni_object(), - "removeScoreboardTag", + "setDamage", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the number of times this arrow can pierce through an entity. + pub fn pierce_level(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPierceLevel", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Returns the reaction of the entity when moved by a piston. - pub fn piston_move_reaction( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + /// Sets the number of times this arrow can pierce through an entity. + /// Must be between 0 and 127 times. + pub fn set_pierce_level(&self, pierce_level: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(pierce_level); let res = self.jni_ref().call_method( &self.jni_object(), - "getPistonMoveReaction", + "setPierceLevel", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the closest cardinal {@link BlockFace} direction an entity is - /// currently facing. + /// Gets whether this arrow is critical. /// - /// This will not return any non-cardinal directions such as - /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// Critical arrows have increased damage and cause particle effects. /// - /// {@link Hanging} entities will override this call and thus their behavior - /// may be different. - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the entity's current pose. - /// Note that the pose is only updated at the end of a tick, so may be - /// inconsistent with other methods. eg {@link Player#isSneaking()} being - /// true does not imply the current pose will be {@link Pose#SNEAKING} - pub fn pose(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Pose;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + /// Critical arrows generally occur when a player fully draws a bow before + /// firing. + pub fn is_critical(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCritical", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Get the category of spawn to which this entity belongs. - pub fn spawn_category( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); + /// Sets whether or not this arrow should be critical. + pub fn set_critical(&self, critical: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(critical.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getSpawnCategory", + "setCritical", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Checks if this entity has been spawned in a world. + /// Gets whether this arrow is in a block or not. /// - /// Entities not spawned in a world will not tick, be sent to players, or be - /// saved to the server files. - pub fn is_in_world(&self) -> Result> { + /// Arrows in a block are motionless and may be picked up by players. + pub fn is_in_block(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInBlock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get this entity as an NBT string. - /// - /// This string should not be relied upon as a serializable value. - pub fn as_string(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// Crates an {@link EntitySnapshot} representing the current state of this entity. - pub fn create_snapshot( + /// Gets the block to which this arrow is attached. + pub fn attached_block( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAttachedBlock", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::EntitySnapshot::from_raw( + Ok(Some(crate::block::Block::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Creates a copy of this entity and all its data. Spawns the copy at the given location. - /// - /// Note: Players cannot be copied. - pub fn copy( + /// Gets the current pickup status of this arrow. + pub fn pickup_status( &self, - to: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = to { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")Lorg/bukkit/entity/Entity;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/AbstractArrow/PickupStatus;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPickupStatus", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + crate::entity::AbstractArrowPickupStatus::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets a metadata value in the implementing object's metadata store. - pub fn set_metadata( + /// Sets the current pickup status of this arrow. + pub fn set_pickup_status( &self, - metadata_key: impl Into, - new_metadata_value: impl Into>, + status: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) + let sig = String::from("(Lorg/bukkit/entity/AbstractArrow/PickupStatus;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(status.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setMetadata", + "setPickupStatus", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a list of previously set metadata values from the implementing - /// object's metadata store. - pub fn get_metadata( - &self, - metadata_key: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMetadata", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::metadata::MetadataValue::from_raw( - &self.jni_ref(), - obj, - )?); - } - Ok(new_vec) - } - /// Tests to see whether the implementing object contains the given - /// metadata value in its metadata store. - pub fn has_metadata( - &self, - metadata_key: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); + /// Gets if this arrow was shot from a crossbow. + pub fn is_shot_from_crossbow(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasMetadata", + "isShotFromCrossbow", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes the given metadata value from the implementing object's - /// metadata store. - pub fn remove_metadata( + #[deprecated] + /// Sets if this arrow was shot from a crossbow. + pub fn set_shot_from_crossbow( &self, - metadata_key: impl Into, - owning_plugin: impl Into>, + shot_from_crossbow: bool, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) - }); + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(shot_from_crossbow.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "removeMetadata", + "setShotFromCrossbow", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sends this sender multiple messages - pub fn send_message( + /// Gets the ItemStack which will be picked up from this arrow. + pub fn item(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/inventory/ItemStack;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getItem", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the ItemStack which will be picked up from this arrow. + pub fn set_item( &self, - sender: impl Into>, - messages: std::option::Option>, + item: impl Into>, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; + sig += "Lorg/bukkit/inventory/ItemStack;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); args.push(val_1); - if let Some(a) = messages { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_2); - } sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); + .call_method(&self.jni_object(), "setItem", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the name of this command sender - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Gets the ItemStack which fired this arrow. + pub fn weapon(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getWeapon", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the custom name on a mob or block. If there is no name this method - /// will return null. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn custom_name(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); + /// Sets the ItemStack which fired this arrow. + pub fn set_weapon( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setWeapon", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Arrow<'mc> { + fn into(self) -> crate::entity::AbstractArrow<'mc> { + crate::entity::AbstractArrow::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Arrow into crate::entity::AbstractArrow") + } +} +#[repr(C)] +pub struct Cod<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Cod<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Cod<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Cod from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Cod")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Cod object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Cod<'mc> { + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Cod<'mc> { + fn into(self) -> crate::entity::Fish<'mc> { + crate::entity::Fish::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Cod into crate::entity::Fish") + } +} +#[repr(C)] +pub struct LlamaSpit<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for LlamaSpit<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for LlamaSpit<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate LlamaSpit from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/LlamaSpit")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a LlamaSpit object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> LlamaSpit<'mc> { + /// Retrieve the shooter of this projectile. + pub fn shooter( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/projectiles/ProjectileSource;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getCustomName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getShooter", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(Some(crate::projectiles::ProjectileSource::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets a custom name on a mob or block. This name will be used in death - /// messages and can be sent to the client as a nameplate over the mob. - /// - /// Setting the name to null or an empty string will clear it. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn set_custom_name( + /// Set the shooter of this projectile. + pub fn set_shooter( &self, - name: impl Into, + source: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + let sig = String::from("(Lorg/bukkit/projectiles/ProjectileSource;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(source.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomName", + "setShooter", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + #[deprecated] + /// Determine if this projectile should bounce or not when it hits. + pub fn does_bounce(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "doesBounce", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Set whether or not this projectile should bounce or not when it hits something. + pub fn set_bounce(&self, does_bounce: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(does_bounce.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "setBounce", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -35305,19 +42359,19 @@ impl<'mc> FallingBlock<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for FallingBlock<'mc> { - fn into(self) -> crate::entity::Entity<'mc> { - crate::entity::Entity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting FallingBlock into crate::entity::Entity") +impl<'mc> Into> for LlamaSpit<'mc> { + fn into(self) -> crate::entity::Projectile<'mc> { + crate::entity::Projectile::from_raw(&self.jni_ref(), self.1) + .expect("Error converting LlamaSpit into crate::entity::Projectile") } } #[repr(C)] -pub struct Creeper<'mc>( +pub struct WanderingTrader<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Creeper<'mc> { +impl<'mc> JNIRaw<'mc> for WanderingTrader<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -35325,18 +42379,20 @@ impl<'mc> JNIRaw<'mc> for Creeper<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Creeper<'mc> { +impl<'mc> JNIInstantiatable<'mc> for WanderingTrader<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Creeper from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate WanderingTrader from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Creeper")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/WanderingTrader")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Creeper object, got {}", + "Invalid argument passed. Expected a WanderingTrader object, got {}", name ) .into()) @@ -35346,129 +42402,226 @@ impl<'mc> JNIInstantiatable<'mc> for Creeper<'mc> { } } -impl<'mc> Creeper<'mc> { - /// Checks if this Creeper is powered (Electrocuted) - pub fn is_powered(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); +impl<'mc> WanderingTrader<'mc> { + /// Gets the despawn delay before this {@link WanderingTrader} is forcibly + /// despawned. + /// If this is less than or equal to 0, then the trader will not be + /// despawned. + pub fn despawn_delay(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDespawnDelay", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets the Powered status of this Creeper - pub fn set_powered(&self, value: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(value.into()); + /// Sets the despawn delay before this {@link WanderingTrader} is forcibly + /// despawned. + /// If this is less than or equal to 0, then the trader will not be + /// despawned. + pub fn set_despawn_delay(&self, despawn_delay: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(despawn_delay); let res = self.jni_ref().call_method( &self.jni_object(), - "setPowered", + "setDespawnDelay", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Set the maximum fuse ticks for this Creeper, where the maximum ticks - /// is the amount of time in which a creeper is allowed to be in the - /// primed state before exploding. - pub fn set_max_fuse_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Gets this villager's inventory. + /// + /// Note that this inventory is not the Merchant inventory, rather, it is the + /// items that a villager might have collected (from harvesting crops, etc.) + /// {@inheritDoc} + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Lock the age of the animal, setting this will prevent the animal from + /// maturing or getting ready for mating. + pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(lock.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxFuseTicks", + "setAgeLock", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the maximum fuse ticks for this Creeper, where the maximum ticks - /// is the amount of time in which a creeper is allowed to be in the - /// primed state before exploding. - pub fn max_fuse_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the current agelock. + pub fn age_lock(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxFuseTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the fuse ticks for this Creeper, where the ticks is the amount of - /// time in which a creeper has been in the primed state. - pub fn set_fuse_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Return the ability to breed of the animal. + pub fn can_breed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set breedability of the animal, if the animal is a baby and set to + /// breed it will instantly grow up. + pub fn set_breed(&self, breed: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(breed.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setFuseTicks", + "setBreed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the maximum fuse ticks for this Creeper, where the ticks is the - /// amount of time in which a creeper has been in the primed state. - pub fn fuse_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Get a list of trades currently available from this merchant. + pub fn recipes( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFuseTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getRecipes", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::inventory::MerchantRecipe::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(new_vec) } - /// Set the explosion radius in which this Creeper's explosion will affect. - pub fn set_explosion_radius(&self, radius: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(radius); + /// Set the list of trades currently available from this merchant. + /// + /// This will not change the selected trades of players currently trading + /// with this merchant. + pub fn set_recipes( + &self, + recipes: Vec>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/List;)V"); + let raw_val_1 = self + .jni_ref() + .new_object("java/util/ArrayList", "()V", vec![])?; + for v in recipes { + let map_val_0 = jni::objects::JValueGen::Object(v); + self.jni_ref().call_method( + &raw_val_1, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_1 = jni::objects::JValueGen::Object(raw_val_1); let res = self.jni_ref().call_method( &self.jni_object(), - "setExplosionRadius", + "setRecipes", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the explosion radius in which this Creeper's explosion will affect. - pub fn explosion_radius(&self) -> Result> { - let sig = String::from("()I"); + /// Get the recipe at a certain index of this merchant's trade list. + pub fn get_recipe( + &self, + i: i32, + ) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/MerchantRecipe;"); + let val_1 = jni::objects::JValueGen::Int(i); let res = self.jni_ref().call_method( &self.jni_object(), - "getExplosionRadius", + "getRecipe", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; + crate::inventory::MerchantRecipe::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Set the recipe at a certain index of this merchant's trade list. + pub fn set_recipe( + &self, + i: i32, + recipe: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(ILorg/bukkit/inventory/MerchantRecipe;)V"); + let val_1 = jni::objects::JValueGen::Int(i); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRecipe", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the number of trades this merchant currently has available. + pub fn recipe_count(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRecipeCount", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Makes this Creeper explode instantly. - /// The resulting explosion can be cancelled by an - /// {@link org.bukkit.event.entity.ExplosionPrimeEvent} and obeys the mob - /// griefing gamerule. - pub fn explode(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Gets whether this merchant is currently trading. + pub fn is_trading(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "explode", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "isTrading", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Ignites this Creeper, beginning its fuse. - /// The amount of time the Creeper takes to explode will depend on what - /// {@link #setMaxFuseTicks} is set as. - /// The resulting explosion can be cancelled by an - /// {@link org.bukkit.event.entity.ExplosionPrimeEvent} and obeys the mob - /// griefing gamerule. - pub fn ignite(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Gets the player this merchant is trading with, or null if it is not + /// currently trading. + pub fn trader( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "ignite", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getTrader", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::HumanEntity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -35476,19 +42629,19 @@ impl<'mc> Creeper<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Creeper<'mc> { - fn into(self) -> crate::entity::Monster<'mc> { - crate::entity::Monster::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Creeper into crate::entity::Monster") +impl<'mc> Into> for WanderingTrader<'mc> { + fn into(self) -> crate::entity::AbstractVillager<'mc> { + crate::entity::AbstractVillager::from_raw(&self.jni_ref(), self.1) + .expect("Error converting WanderingTrader into crate::entity::AbstractVillager") } } #[repr(C)] -pub struct Raider<'mc>( +pub struct SmallFireball<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Raider<'mc> { +impl<'mc> JNIRaw<'mc> for SmallFireball<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -35496,18 +42649,18 @@ impl<'mc> JNIRaw<'mc> for Raider<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Raider<'mc> { +impl<'mc> JNIInstantiatable<'mc> for SmallFireball<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Raider from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate SmallFireball from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Raider")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/SmallFireball")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Raider object, got {}", + "Invalid argument passed. Expected a SmallFireball object, got {}", name ) .into()) @@ -35517,210 +42670,111 @@ impl<'mc> JNIInstantiatable<'mc> for Raider<'mc> { } } -impl<'mc> Raider<'mc> { - /// Set the {@link Raid} that this raider is participating in. - pub fn set_raid( - &self, - raid: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Raid;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(raid.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRaid", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the {@link Raid} that this raider is participating in, if any. - pub fn raid(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Raid;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getRaid", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Raid::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Get the raid wave that this raider spawned as part of. - pub fn wave(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWave", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the raid wave that this raider was spawned as part of. - pub fn set_wave(&self, wave: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(wave); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setWave", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the block the raider is targeting to patrol. - pub fn patrol_target( +impl<'mc> SmallFireball<'mc> { + /// Gets the display {@link ItemStack}. + pub fn display_item( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPatrolTarget", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDisplayItem", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::block::Block::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the block the raider is targeting to patrol. - pub fn set_patrol_target( + /// Sets the display {@link ItemStack} for the fireball. + pub fn set_display_item( &self, - block: impl Into>, + item: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/Block;)V"); + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) + jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPatrolTarget", + "setDisplayItem", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether this entity is a patrol leader. - pub fn is_patrol_leader(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isPatrolLeader", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether this entity is a patrol leader. - pub fn set_patrol_leader(&self, leader: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(leader.into()); + /// Sets the direction the fireball should be flying towards. + /// + /// This is a convenience method, it will change the velocity direction and + /// acceleration direction, while keeping the power the same. + /// + /// Note: This method only uses the direction of the vector and will + /// normalize (a copy of) it. + /// + /// Special Case: When the given direction is + /// {@link Vector#isZero() zero}, the velocity and acceleration will also be + /// set to zero without keeping the power. + pub fn set_direction( + &self, + direction: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(direction.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPatrolLeader", + "setDirection", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether this mob can join an active raid. - pub fn is_can_join_raid(&self) -> Result> { - let sig = String::from("()Z"); + #[deprecated] + /// Retrieve the direction this fireball is heading toward. The returned vector is not normalized. + pub fn direction(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCanJoinRaid", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether this mob can join an active raid. - pub fn set_can_join_raid(&self, join: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(join.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCanJoinRaid", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the amount of ticks that this mob has exited the bounds of a village - /// as a raid participant. - /// - /// This value is increased only when the mob has had no action for 2,400 ticks - /// (according to {@link #getNoActionTicks()}). Once both the no action ticks have - /// reached that value and the ticks outside a raid exceeds 30, the mob will be - /// expelled from the raid. - pub fn ticks_outside_raid(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTicksOutsideRaid", - sig.as_str(), - vec![], - ); + .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the amount of ticks that this mob has exited the bounds of a village - /// as a raid participant. + /// Sets the acceleration of the fireball. + /// The acceleration gets applied to the velocity every tick, depending on + /// the specific type of the fireball a damping / drag factor is applied so + /// that the velocity does not grow into infinity. /// - /// This value is considered only when the mob has had no action for 2,400 ticks - /// (according to {@link #getNoActionTicks()}). Once both the no action ticks have - /// reached that value and the ticks outside a raid exceeds 30, the mob will be - /// expelled from the raid. - pub fn set_ticks_outside_raid(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Note: that the client may not respect non-default acceleration + /// power and will therefore mispredict the location of the fireball, causing + /// visual stutter. + pub fn set_acceleration( + &self, + acceleration: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(acceleration.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setTicksOutsideRaid", + "setAcceleration", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check whether or not this raider is celebrating a raid victory. - pub fn is_celebrating(&self) -> Result> { - let sig = String::from("()Z"); + /// Retrieve the acceleration of this fireball. + pub fn acceleration(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCelebrating", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Set whether or not this mob is celebrating a raid victory. - pub fn set_celebrating(&self, celebrating: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(celebrating.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCelebrating", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the {@link Sound} this entity will play when celebrating. - pub fn celebration_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCelebrationSound", - sig.as_str(), - vec![], - ); + .call_method(&self.jni_object(), "getAcceleration", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -35730,19 +42784,19 @@ impl<'mc> Raider<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Raider<'mc> { - fn into(self) -> crate::entity::Monster<'mc> { - crate::entity::Monster::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Raider into crate::entity::Monster") +impl<'mc> Into> for SmallFireball<'mc> { + fn into(self) -> crate::entity::SizedFireball<'mc> { + crate::entity::SizedFireball::from_raw(&self.jni_ref(), self.1) + .expect("Error converting SmallFireball into crate::entity::SizedFireball") } } #[repr(C)] -pub struct Hoglin<'mc>( +pub struct Illager<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Hoglin<'mc> { +impl<'mc> JNIRaw<'mc> for Illager<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -35750,18 +42804,18 @@ impl<'mc> JNIRaw<'mc> for Hoglin<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Hoglin<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Illager<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Hoglin from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Illager from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Hoglin")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Illager")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Hoglin object, got {}", + "Invalid argument passed. Expected a Illager object, got {}", name ) .into()) @@ -35771,1596 +42825,1541 @@ impl<'mc> JNIInstantiatable<'mc> for Hoglin<'mc> { } } -impl<'mc> Hoglin<'mc> { - /// Gets whether the hoglin is immune to zombification. - pub fn is_immune_to_zombification(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isImmuneToZombification", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether the hoglin is immune to zombification. - pub fn set_immune_to_zombification( +impl<'mc> Illager<'mc> { + /// Set the {@link Raid} that this raider is participating in. + pub fn set_raid( &self, - flag: bool, + raid: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let sig = String::from("(Lorg/bukkit/Raid;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(raid.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setImmuneToZombification", + "setRaid", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get whether the hoglin is able to be hunted by piglins. - pub fn is_able_to_be_hunted(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isAbleToBeHunted", - sig.as_str(), - vec![], - ); + /// Get the {@link Raid} that this raider is participating in, if any. + pub fn raid(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Raid;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRaid", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether the hoglin is able to be hunted by piglins. - pub fn set_is_able_to_be_hunted(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setIsAbleToBeHunted", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Raid::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Gets the amount of ticks until this entity will be converted to a Zoglin. - /// When this reaches 300, the entity will be converted. - pub fn conversion_time(&self) -> Result> { + /// Get the raid wave that this raider spawned as part of. + pub fn wave(&self) -> Result> { let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getConversionTime", - sig.as_str(), - vec![], - ); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWave", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the amount of ticks until this entity will be converted to a Zoglin. - /// When this reaches 0, the entity will be converted. A value of less than 0 - /// will stop the current conversion process without converting the current - /// entity. - pub fn set_conversion_time(&self, time: i32) -> Result<(), Box> { + /// Set the raid wave that this raider was spawned as part of. + pub fn set_wave(&self, wave: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(time); + let val_1 = jni::objects::JValueGen::Int(wave); let res = self.jni_ref().call_method( &self.jni_object(), - "setConversionTime", + "setWave", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get if this entity is in the process of converting to a Zoglin. - pub fn is_converting(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isConverting", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn breed_cause( + /// Gets the block the raider is targeting to patrol. + pub fn patrol_target( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/UUID;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPatrolTarget", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( + Ok(Some(crate::block::Block::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Set the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn set_breed_cause( + /// Sets the block the raider is targeting to patrol. + pub fn set_patrol_target( &self, - uuid: impl Into>, + block: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/UUID;)V"); + let sig = String::from("(Lorg/bukkit/block/Block;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) + jni::objects::JObject::from_raw(block.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreedCause", + "setPatrolTarget", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get whether or not this entity is in love mode and will produce - /// offspring with another entity in love mode. Will return true if - /// and only if {@link #getLoveModeTicks()} is greater than 0. - pub fn is_love_mode(&self) -> Result> { + /// Gets whether this entity is a patrol leader. + pub fn is_patrol_leader(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the amount of ticks remaining for this entity in love mode. - /// If the entity is not in love mode, 0 will be returned. - pub fn love_mode_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLoveModeTicks", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the amount of ticks for which this entity should be in love mode. - /// Setting the love mode ticks to 600 is the equivalent of a player - /// feeding the entity their breeding item of choice. - pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLoveModeTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Check if the provided ItemStack is the correct item used for breeding - /// this entity.. - pub fn is_breed_item( - &self, - material: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); + .call_method(&self.jni_object(), "isPatrolLeader", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Lock the age of the animal, setting this will prevent the animal from - /// maturing or getting ready for mating. - pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { + /// Sets whether this entity is a patrol leader. + pub fn set_patrol_leader(&self, leader: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(lock.into()); + let val_1 = jni::objects::JValueGen::Bool(leader.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setAgeLock", + "setPatrolLeader", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the current agelock. - pub fn age_lock(&self) -> Result> { + /// Gets whether this mob can join an active raid. + pub fn is_can_join_raid(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Return the ability to breed of the animal. - pub fn can_breed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCanJoinRaid", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set breedability of the animal, if the animal is a baby and set to - /// breed it will instantly grow up. - pub fn set_breed(&self, breed: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(breed.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setBreed", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the height of the living entity's eyes above its Location. - pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { - let sig = String::from("(Z)D"); - let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getEyeHeight", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Get a Location detailing the current eye position of the living entity. - pub fn eye_location(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets all blocks along the living entity's line of sight. - /// - /// This list contains all blocks from the living entity's eye position to - /// target inclusive. This method considers all blocks as 1x1x1 in size. - pub fn get_line_of_sight( - &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { - let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(max_distance); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLineOfSight", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Gets the block that the living entity has targeted. - /// - /// This method considers all blocks as 1x1x1 in size. To take exact block - /// collision shapes into account, see {@link #getTargetBlockExact(int, - /// FluidCollisionMode)}. - pub fn get_target_block( - &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result, Box> { - let sig = String::from("(Ljava/util/Set;I)Lorg/bukkit/block/Block;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(max_distance); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTargetBlock", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the last two blocks along the living entity's line of sight. - /// - /// The target block will be the last block in the list. This method - /// considers all blocks as 1x1x1 in size. - pub fn get_last_two_target_blocks( - &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { - let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(max_distance); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLastTwoTargetBlocks", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Gets the block that the living entity has targeted. - /// - /// This takes the blocks' precise collision shapes into account. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn get_target_block_exact( - &self, - max_distance: i32, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(max_distance); - args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/block/Block;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTargetBlockExact", - sig.as_str(), - args, - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::block::Block::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Performs a ray trace that provides information on the targeted block. - /// - /// This takes the blocks' precise collision shapes into account. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn ray_trace_blocks( - &self, - max_distance: f64, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(max_distance); - args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/util/RayTraceResult;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::util::RayTraceResult::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Returns the amount of air that the living entity has remaining, in - /// ticks. - pub fn remaining_air(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the amount of air that the living entity has remaining, in ticks. - pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRemainingAir", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns the maximum amount of air the living entity can have, in ticks. - pub fn maximum_air(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the maximum amount of air the living entity can have, in ticks. - pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaximumAir", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the item that the player is using (eating food, drawing back a bow, - /// blocking, etc.) - pub fn item_in_use( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Gets the number of ticks remaining for the current item's usage. - pub fn item_in_use_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getItemInUseTicks", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the number of ticks that remain for the current item's usage. - /// Applies to items that take time to use, like eating food, drawing a bow, - /// or throwing a trident. - pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets whether this mob can join an active raid. + pub fn set_can_join_raid(&self, join: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(join.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemInUseTicks", + "setCanJoinRaid", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the time in ticks until the next arrow leaves the entity's body. - pub fn arrow_cooldown(&self) -> Result> { + /// Get the amount of ticks that this mob has exited the bounds of a village + /// as a raid participant. + /// + /// This value is increased only when the mob has had no action for 2,400 ticks + /// (according to {@link #getNoActionTicks()}). Once both the no action ticks have + /// reached that value and the ticks outside a raid exceeds 30, the mob will be + /// expelled from the raid. + pub fn ticks_outside_raid(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getArrowCooldown", + "getTicksOutsideRaid", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the time in ticks until the next arrow leaves the entity's body. - pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { + /// Set the amount of ticks that this mob has exited the bounds of a village + /// as a raid participant. + /// + /// This value is considered only when the mob has had no action for 2,400 ticks + /// (according to {@link #getNoActionTicks()}). Once both the no action ticks have + /// reached that value and the ticks outside a raid exceeds 30, the mob will be + /// expelled from the raid. + pub fn set_ticks_outside_raid(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setArrowCooldown", + "setTicksOutsideRaid", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the amount of arrows in an entity's body. - pub fn arrows_in_body(&self) -> Result> { - let sig = String::from("()I"); + /// Check whether or not this raider is celebrating a raid victory. + pub fn is_celebrating(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCelebrating", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the amount of arrows in the entity's body. - pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(count); + /// Set whether or not this mob is celebrating a raid victory. + pub fn set_celebrating(&self, celebrating: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(celebrating.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setArrowsInBody", + "setCelebrating", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's current maximum no damage ticks. - /// - /// This is the maximum duration in which the living entity will not take - /// damage. - pub fn maximum_no_damage_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Get the {@link Sound} this entity will play when celebrating. + pub fn celebration_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getMaximumNoDamageTicks", + "getCelebrationSound", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the living entity's current maximum no damage ticks. - pub fn set_maximum_no_damage_ticks( - &self, - ticks: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Illager<'mc> { + fn into(self) -> crate::entity::Raider<'mc> { + crate::entity::Raider::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Illager into crate::entity::Raider") + } +} +#[repr(C)] +pub struct Pig<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Pig<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Pig<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Pig from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Pig")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Pig object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Pig<'mc> { + /// Check if the pig has a saddle. + pub fn has_saddle(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasSaddle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets if the pig has a saddle or not + pub fn set_saddle(&self, saddled: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(saddled.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaximumNoDamageTicks", + "setSaddle", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's last damage taken in the current no damage - /// ticks time. - /// - /// Only damage higher than this amount will further damage the living - /// entity. - pub fn last_damage(&self) -> Result> { - let sig = String::from("()D"); + /// Get the time in ticks this entity's movement is being increased. + /// Movement speed is often increased as a result of using the + /// {@link #getSteerMaterial()}. + pub fn boost_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBoostTicks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.i()?) } - /// Sets the damage dealt within the current no damage ticks time period. - pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(damage); + /// Set the time in ticks this entity's movement will be increased. + /// This will reset the current boost ticks to 0 + /// ({@link #getCurrentBoostTicks()}). + pub fn set_boost_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDamage", + "setBoostTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's current no damage ticks. - pub fn no_damage_ticks(&self) -> Result> { + /// Get the time in ticks this entity's movement has been increased as of the + /// most recent boost. + /// Current boost ticks will never be {@literal >} {@link #getBoostTicks()}. + pub fn current_boost_ticks(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getNoDamageTicks", + "getCurrentBoostTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the living entity's current no damage ticks. - pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Set the time in ticks this entity's movement has been increased relative + /// to the most recent boost. + pub fn set_current_boost_ticks(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setNoDamageTicks", + "setCurrentBoostTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the ticks that this entity has performed no action. - /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn no_action_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Get the material used to steer this entity when ridden by a player. + pub fn steer_material(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getNoActionTicks", + "getSteerMaterial", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the ticks that this entity has performed no action. - /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setNoActionTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the player identified as the killer of the living entity. - /// - /// May be null. - pub fn killer(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Player;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); + /// Get the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn breed_cause( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Player::from_raw( + Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - #[deprecated] - /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. - pub fn add_potion_effect( - &self, - effect: impl Into>, - force: std::option::Option, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/potion/PotionEffect;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(effect.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = force { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns whether the living entity already has an existing effect of - /// the given {@link PotionEffectType} applied to it. - pub fn has_potion_effect( + /// Set the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn set_breed_cause( &self, - val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); + uuid: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/UUID;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasPotionEffect", + "setBreedCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get whether or not this entity is in love mode and will produce + /// offspring with another entity in love mode. Will return true if + /// and only if {@link #getLoveModeTicks()} is greater than 0. + pub fn is_love_mode(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns the active {@link PotionEffect} of the specified type. - /// - /// If the effect is not present on the entity then null will be returned. - pub fn get_potion_effect( - &self, - val_type: impl Into>, - ) -> Result>, Box> { - let sig = - String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Get the amount of ticks remaining for this entity in love mode. + /// If the entity is not in love mode, 0 will be returned. + pub fn love_mode_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPotionEffect", + "getLoveModeTicks", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::potion::PotionEffect::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - /// Removes any effects present of the given {@link PotionEffectType}. - pub fn remove_potion_effect( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Set the amount of ticks for which this entity should be in love mode. + /// Setting the love mode ticks to 600 is the equivalent of a player + /// feeding the entity their breeding item of choice. + pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "removePotionEffect", + "setLoveModeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns all currently active {@link PotionEffect}s on the living - /// entity. - pub fn active_potion_effects( + /// Check if the provided ItemStack is the correct item used for breeding + /// this entity.. + pub fn is_breed_item( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getActivePotionEffects", - sig.as_str(), - vec![], - ); + material: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(res.z()?) } - /// Checks whether the living entity has block line of sight to another. - /// - /// This uses the same algorithm that hostile mobs use to find the closest - /// player. - pub fn has_line_of_sight( + /// Gets the vehicle's velocity. + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the vehicle's velocity in meters per tick. + pub fn set_velocity( &self, - other: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + vel: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) + jni::objects::JObject::from_raw(vel.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasLineOfSight", + "setVelocity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns if the living entity despawns when away from players or not. - /// - /// By default, animals are not removed while other mobs are. - pub fn remove_when_far_away(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getRemoveWhenFarAway", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Sets whether or not the living entity despawns when away from players - /// or not. - pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(remove.into()); +} +impl<'mc> Into> for Pig<'mc> { + fn into(self) -> crate::entity::Steerable<'mc> { + crate::entity::Steerable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Pig into crate::entity::Steerable") + } +} +impl<'mc> Into> for Pig<'mc> { + fn into(self) -> crate::entity::Vehicle<'mc> { + crate::entity::Vehicle::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Pig into crate::entity::Vehicle") + } +} +#[repr(C)] +pub struct WaterMob<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for WaterMob<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for WaterMob<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate WaterMob from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/WaterMob")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a WaterMob object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> WaterMob<'mc> { + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for WaterMob<'mc> { + fn into(self) -> crate::entity::Creature<'mc> { + crate::entity::Creature::from_raw(&self.jni_ref(), self.1) + .expect("Error converting WaterMob into crate::entity::Creature") + } +} +#[repr(C)] +pub struct Flying<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Flying<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Flying<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Flying from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Flying")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Flying object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Flying<'mc> { + /// Instructs this Mob to set the specified LivingEntity as its target. + /// + /// Hostile creatures may attack their target, and friendly creatures may + /// follow their target. + pub fn set_target( + &self, + target: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(target.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setRemoveWhenFarAway", + "setTarget", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the inventory with the equipment worn by the living entity. - pub fn equipment( + /// Gets the current target of this Mob + pub fn target( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTarget", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::EntityEquipment::from_raw( + Ok(Some(crate::entity::LivingEntity::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets whether or not the living entity can pick up items. - pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { + /// Sets whether this mob is aware of its surroundings. + /// Unaware mobs will still move if pushed, attacked, etc. but will not move + /// or perform any actions on their own. Unaware mobs may also have other + /// unspecified behaviours disabled, such as drowning. + pub fn set_aware(&self, aware: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(pickup.into()); + let val_1 = jni::objects::JValueGen::Bool(aware.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCanPickupItems", + "setAware", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the living entity can pick up items. - pub fn can_pickup_items(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCanPickupItems", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns whether the entity is currently leashed. - pub fn is_leashed(&self) -> Result> { + /// Gets whether this mob is aware of its surroundings. + /// Unaware mobs will still move if pushed, attacked, etc. but will not move + /// or perform any actions on their own. Unaware mobs may also have other + /// unspecified behaviours disabled, such as drowning. + pub fn is_aware(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isAware", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the entity that is currently leading this entity. - pub fn leash_holder(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + /// Get the {@link Sound} this mob makes while ambiently existing. This sound + /// may change depending on the current state of the entity, and may also + /// return null under specific conditions. This sound is not constant. + /// For instance, villagers will make different passive noises depending + /// on whether or not they are actively trading with a player, or make no + /// ambient noise while sleeping. + pub fn ambient_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAmbientSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) + })?)) } - /// Sets the leash on this entity to be held by the supplied entity. - /// - /// This method has no effect on EnderDragons, Withers, Players, or Bats. - /// Non-living entities excluding leashes will not persist as leash - /// holders. - pub fn set_leash_holder( - &self, - holder: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(holder.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLeashHolder", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Checks to see if an entity is gliding, such as using an Elytra. - pub fn is_gliding(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} +impl<'mc> Into> for Flying<'mc> { + fn into(self) -> crate::entity::Mob<'mc> { + crate::entity::Mob::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Flying into crate::entity::Mob") } - /// Makes entity start or stop gliding. This will work even if an Elytra - /// is not equipped, but will be reverted by the server immediately after - /// unless an event-cancelling mechanism is put in place. - pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gliding.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setGliding", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +} +#[repr(C)] +pub struct IronGolem<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for IronGolem<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Checks to see if an entity is swimming. - pub fn is_swimming(&self) -> Result> { + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for IronGolem<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate IronGolem from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/IronGolem")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a IronGolem object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> IronGolem<'mc> { + /// Gets whether this iron golem was built by a player. + pub fn is_player_created(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isPlayerCreated", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Makes entity start or stop swimming. - /// This may have unexpected results if the entity is not in water. - pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { + /// Sets whether this iron golem was built by a player or not. + pub fn set_player_created( + &self, + player_created: bool, + ) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(swimming.into()); + let val_1 = jni::objects::JValueGen::Bool(player_created.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setSwimming", + "setPlayerCreated", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks to see if an entity is currently using the Riptide enchantment. - pub fn is_riptiding(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Returns whether this entity is slumbering. - pub fn is_sleeping(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} +impl<'mc> Into> for IronGolem<'mc> { + fn into(self) -> crate::entity::Golem<'mc> { + crate::entity::Golem::from_raw(&self.jni_ref(), self.1) + .expect("Error converting IronGolem into crate::entity::Golem") } - /// Gets if the entity is climbing. - pub fn is_climbing(&self) -> Result> { - let sig = String::from("()Z"); +} +#[repr(C)] +pub struct TropicalFish<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for TropicalFish<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for TropicalFish<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate TropicalFish from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/TropicalFish")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a TropicalFish object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> TropicalFish<'mc> { + /// Gets the color of the fish's pattern. + pub fn pattern_color(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/DyeColor;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPatternColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::DyeColor::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets whether an entity will have AI. - /// The entity will be completely unable to move if it has no AI. - pub fn set_ai(&self, ai: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(ai.into()); + /// Sets the color of the fish's pattern + pub fn set_pattern_color( + &self, + color: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/DyeColor;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(color.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setAI", + "setPatternColor", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks whether an entity has AI. - /// The entity will be completely unable to move if it has no AI. - pub fn has_ai(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); + /// Gets the color of the fish's body. + pub fn body_color(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/DyeColor;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBodyColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::DyeColor::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Makes this entity attack the given entity with a melee attack. - /// Attack damage is calculated by the server from the attributes and - /// equipment of this mob, and knockback is applied to {@code target} as - /// appropriate. - pub fn attack( + /// Sets the color of the fish's body + pub fn set_body_color( &self, - target: impl Into>, + color: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + let sig = String::from("(Lorg/bukkit/DyeColor;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) + jni::objects::JObject::from_raw(color.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "attack", + "setBodyColor", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Makes this entity swing their main hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their main hand. - pub fn swing_main_hand(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Makes this entity swing their off hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their off hand. - pub fn swing_off_hand(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Gets the fish's pattern. + pub fn pattern( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/TropicalFish/Pattern;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getPattern", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::TropicalFishPattern::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Makes this entity flash red as if they were damaged. - pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); + /// Sets the fish's pattern + pub fn set_pattern( + &self, + pattern: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/TropicalFish/Pattern;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(pattern.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "playHurtAnimation", + "setPattern", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Set if this entity will be subject to collisions with other entities. - /// - /// Exemptions to this rule can be managed with - /// {@link #getCollidableExemptions()} - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not working for player collisions. This - /// method should therefore only be used to set the collision status of - /// non-player entities. - /// - /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in - /// combination with a {@link Scoreboard} and a {@link Team}. - pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(collidable.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCollidable", - sig.as_str(), + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for TropicalFish<'mc> { + fn into(self) -> crate::entity::Fish<'mc> { + crate::entity::Fish::from_raw(&self.jni_ref(), self.1) + .expect("Error converting TropicalFish into crate::entity::Fish") + } +} +pub enum TropicalFishPattern<'mc> { + Kob { + inner: TropicalFishPatternStruct<'mc>, + }, + Sunstreak { + inner: TropicalFishPatternStruct<'mc>, + }, + Snooper { + inner: TropicalFishPatternStruct<'mc>, + }, + Dasher { + inner: TropicalFishPatternStruct<'mc>, + }, + Brinely { + inner: TropicalFishPatternStruct<'mc>, + }, + Spotty { + inner: TropicalFishPatternStruct<'mc>, + }, + Flopper { + inner: TropicalFishPatternStruct<'mc>, + }, + Stripey { + inner: TropicalFishPatternStruct<'mc>, + }, + Glitter { + inner: TropicalFishPatternStruct<'mc>, + }, + Blockfish { + inner: TropicalFishPatternStruct<'mc>, + }, + Betty { + inner: TropicalFishPatternStruct<'mc>, + }, + Clayfish { + inner: TropicalFishPatternStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for TropicalFishPattern<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + TropicalFishPattern::Kob { .. } => f.write_str("KOB"), + TropicalFishPattern::Sunstreak { .. } => f.write_str("SUNSTREAK"), + TropicalFishPattern::Snooper { .. } => f.write_str("SNOOPER"), + TropicalFishPattern::Dasher { .. } => f.write_str("DASHER"), + TropicalFishPattern::Brinely { .. } => f.write_str("BRINELY"), + TropicalFishPattern::Spotty { .. } => f.write_str("SPOTTY"), + TropicalFishPattern::Flopper { .. } => f.write_str("FLOPPER"), + TropicalFishPattern::Stripey { .. } => f.write_str("STRIPEY"), + TropicalFishPattern::Glitter { .. } => f.write_str("GLITTER"), + TropicalFishPattern::Blockfish { .. } => f.write_str("BLOCKFISH"), + TropicalFishPattern::Betty { .. } => f.write_str("BETTY"), + TropicalFishPattern::Clayfish { .. } => f.write_str("CLAYFISH"), + } + } +} +impl<'mc> std::ops::Deref for TropicalFishPattern<'mc> { + type Target = TropicalFishPatternStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + TropicalFishPattern::Kob { inner } => inner, + TropicalFishPattern::Sunstreak { inner } => inner, + TropicalFishPattern::Snooper { inner } => inner, + TropicalFishPattern::Dasher { inner } => inner, + TropicalFishPattern::Brinely { inner } => inner, + TropicalFishPattern::Spotty { inner } => inner, + TropicalFishPattern::Flopper { inner } => inner, + TropicalFishPattern::Stripey { inner } => inner, + TropicalFishPattern::Glitter { inner } => inner, + TropicalFishPattern::Blockfish { inner } => inner, + TropicalFishPattern::Betty { inner } => inner, + TropicalFishPattern::Clayfish { inner } => inner, + } + } +} + +impl<'mc> TropicalFishPattern<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/TropicalFish/Pattern"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/TropicalFish/Pattern;", vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "KOB" => Ok(TropicalFishPattern::Kob { + inner: TropicalFishPatternStruct::from_raw(env, obj)?, + }), + "SUNSTREAK" => Ok(TropicalFishPattern::Sunstreak { + inner: TropicalFishPatternStruct::from_raw(env, obj)?, + }), + "SNOOPER" => Ok(TropicalFishPattern::Snooper { + inner: TropicalFishPatternStruct::from_raw(env, obj)?, + }), + "DASHER" => Ok(TropicalFishPattern::Dasher { + inner: TropicalFishPatternStruct::from_raw(env, obj)?, + }), + "BRINELY" => Ok(TropicalFishPattern::Brinely { + inner: TropicalFishPatternStruct::from_raw(env, obj)?, + }), + "SPOTTY" => Ok(TropicalFishPattern::Spotty { + inner: TropicalFishPatternStruct::from_raw(env, obj)?, + }), + "FLOPPER" => Ok(TropicalFishPattern::Flopper { + inner: TropicalFishPatternStruct::from_raw(env, obj)?, + }), + "STRIPEY" => Ok(TropicalFishPattern::Stripey { + inner: TropicalFishPatternStruct::from_raw(env, obj)?, + }), + "GLITTER" => Ok(TropicalFishPattern::Glitter { + inner: TropicalFishPatternStruct::from_raw(env, obj)?, + }), + "BLOCKFISH" => Ok(TropicalFishPattern::Blockfish { + inner: TropicalFishPatternStruct::from_raw(env, obj)?, + }), + "BETTY" => Ok(TropicalFishPattern::Betty { + inner: TropicalFishPatternStruct::from_raw(env, obj)?, + }), + "CLAYFISH" => Ok(TropicalFishPattern::Clayfish { + inner: TropicalFishPatternStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct TropicalFishPatternStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for TropicalFishPattern<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Kob { inner } => inner.0.clone(), + Self::Sunstreak { inner } => inner.0.clone(), + Self::Snooper { inner } => inner.0.clone(), + Self::Dasher { inner } => inner.0.clone(), + Self::Brinely { inner } => inner.0.clone(), + Self::Spotty { inner } => inner.0.clone(), + Self::Flopper { inner } => inner.0.clone(), + Self::Stripey { inner } => inner.0.clone(), + Self::Glitter { inner } => inner.0.clone(), + Self::Blockfish { inner } => inner.0.clone(), + Self::Betty { inner } => inner.0.clone(), + Self::Clayfish { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Kob { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Sunstreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Snooper { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Dasher { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Brinely { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Spotty { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Flopper { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Stripey { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Glitter { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Blockfish { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Betty { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Clayfish { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for TropicalFishPattern<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate TropicalFishPattern from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/TropicalFish/Pattern")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a TropicalFishPattern object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "KOB" => Ok(TropicalFishPattern::Kob { + inner: TropicalFishPatternStruct::from_raw(env, obj)?, + }), + "SUNSTREAK" => Ok(TropicalFishPattern::Sunstreak { + inner: TropicalFishPatternStruct::from_raw(env, obj)?, + }), + "SNOOPER" => Ok(TropicalFishPattern::Snooper { + inner: TropicalFishPatternStruct::from_raw(env, obj)?, + }), + "DASHER" => Ok(TropicalFishPattern::Dasher { + inner: TropicalFishPatternStruct::from_raw(env, obj)?, + }), + "BRINELY" => Ok(TropicalFishPattern::Brinely { + inner: TropicalFishPatternStruct::from_raw(env, obj)?, + }), + "SPOTTY" => Ok(TropicalFishPattern::Spotty { + inner: TropicalFishPatternStruct::from_raw(env, obj)?, + }), + "FLOPPER" => Ok(TropicalFishPattern::Flopper { + inner: TropicalFishPatternStruct::from_raw(env, obj)?, + }), + "STRIPEY" => Ok(TropicalFishPattern::Stripey { + inner: TropicalFishPatternStruct::from_raw(env, obj)?, + }), + "GLITTER" => Ok(TropicalFishPattern::Glitter { + inner: TropicalFishPatternStruct::from_raw(env, obj)?, + }), + "BLOCKFISH" => Ok(TropicalFishPattern::Blockfish { + inner: TropicalFishPatternStruct::from_raw(env, obj)?, + }), + "BETTY" => Ok(TropicalFishPattern::Betty { + inner: TropicalFishPatternStruct::from_raw(env, obj)?, + }), + "CLAYFISH" => Ok(TropicalFishPattern::Clayfish { + inner: TropicalFishPatternStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for TropicalFishPatternStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for TropicalFishPatternStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate TropicalFishPatternStruct from null object." + ) + .into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/TropicalFish/Pattern")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a TropicalFishPatternStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> TropicalFishPatternStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/TropicalFish/Pattern;"); + let cls = jni.find_class("org/bukkit/entity/TropicalFish/Pattern"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::TropicalFishPattern::from_raw(&jni, obj) } - /// Gets if this entity is subject to collisions with other entities. - /// - /// Some entities might be exempted from the collidable rule of this entity. - /// Use {@link #getCollidableExemptions()} to get these. - /// - /// Please note that this method returns only the custom collidable state, - /// not whether the entity is non-collidable for other reasons such as being - /// dead. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not being accurate for player collisions. - /// This method should therefore only be used to check the collision status - /// of non-player entities. - /// - /// To check the collision behavior for a player, use - /// {@link Team.Option#COLLISION_RULE} in combination with a - /// {@link Scoreboard} and a {@link Team}. - pub fn is_collidable(&self) -> Result> { + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct Vindicator<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Vindicator<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Vindicator<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Vindicator from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Vindicator")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Vindicator object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Vindicator<'mc> { + /// Returns whether a vindicator is in "Johnny" mode. + /// When this mode is active, vindicators will be hostile to all mobs. + pub fn is_johnny(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isJohnny", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets a mutable set of UUIDs of the entities which are exempt from the - /// entity's collidable rule and which's collision with this entity will - /// behave the opposite of it. - /// - /// This set can be modified to add or remove exemptions. - /// - /// For example if collidable is true and an entity is in the exemptions set - /// then it will not collide with it. Similarly if collidable is false and an - /// entity is in this set then it will still collide with it. - /// - /// Note these exemptions are not (currently) persistent. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in those exemptions not being accurate for player - /// collisions. This method should therefore only be used to exempt - /// non-player entities. - /// - /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} - /// in combination with a {@link Scoreboard} and a {@link Team}. - pub fn collidable_exemptions( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCollidableExemptions", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns the value of the memory specified. - /// - /// Note that the value is null when the specific entity does not have that - /// value by default. - pub fn get_memory( - &self, - memory_key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) - }); + /// Sets the Johnny state of a vindicator. + pub fn set_johnny(&self, johnny: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(johnny.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getMemory", + "setJohnny", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(res.l()?)) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the value of the memory specified. - /// - /// Note that the value will not be persisted when the specific entity does - /// not have that value by default. - pub fn set_memory( + /// Set the {@link Raid} that this raider is participating in. + pub fn set_raid( &self, - memory_key: impl Into>, - memory_value: jni::objects::JObject<'mc>, + raid: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); + let sig = String::from("(Lorg/bukkit/Raid;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + jni::objects::JObject::from_raw(raid.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Object(memory_value); let res = self.jni_ref().call_method( &self.jni_object(), - "setMemory", + "setRaid", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the {@link Sound} this entity will make when damaged. - pub fn hurt_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); + /// Get the {@link Raid} that this raider is participating in, if any. + pub fn raid(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Raid;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRaid", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + Ok(Some(crate::Raid::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) })?)) } - /// Get the {@link Sound} this entity will make on death. - pub fn death_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); + /// Get the raid wave that this raider spawned as part of. + pub fn wave(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWave", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.i()?) } - /// Get the {@link Sound} this entity will make when falling from the given - /// height (in blocks). The sound will often differ between either a small - /// or a big fall damage sound if the height exceeds 4 blocks. - pub fn get_fall_damage_sound( - &self, - fall_height: i32, - ) -> Result, Box> { - let sig = String::from("(I)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Int(fall_height); + /// Set the raid wave that this raider was spawned as part of. + pub fn set_wave(&self, wave: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(wave); let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSound", + "setWave", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity will make when falling from a small - /// height. - pub fn fall_damage_sound_small(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFallDamageSoundSmall", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity will make when falling from a large - /// height. - pub fn fall_damage_sound_big(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFallDamageSoundBig", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the {@link Sound} this entity will make when drinking the given - /// {@link ItemStack}. - pub fn get_drinking_sound( + /// Gets the block the raider is targeting to patrol. + pub fn patrol_target( &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getDrinkingSound", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPatrolTarget", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::block::Block::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Get the {@link Sound} this entity will make when eating the given - /// {@link ItemStack}. - pub fn get_eating_sound( + /// Sets the block the raider is targeting to patrol. + pub fn set_patrol_target( &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + block: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/Block;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + jni::objects::JObject::from_raw(block.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getEatingSound", + "setPatrolTarget", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns true if this entity can breathe underwater and will not take - /// suffocation damage when its air supply reaches zero. - pub fn can_breathe_underwater(&self) -> Result> { + /// Gets whether this entity is a patrol leader. + pub fn is_patrol_leader(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "canBreatheUnderwater", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. - pub fn category( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isPatrolLeader", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets whether the entity is invisible or not. - pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { + /// Sets whether this entity is a patrol leader. + pub fn set_patrol_leader(&self, leader: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(invisible.into()); + let val_1 = jni::objects::JValueGen::Bool(leader.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvisible", + "setPatrolLeader", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invisible or not. - pub fn is_invisible(&self) -> Result> { + /// Gets whether this mob can join an active raid. + pub fn is_can_join_raid(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCanJoinRaid", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the specified attribute instance from the object. This instance will - /// be backed directly to the object and any changes will be visible at once. - pub fn get_attribute( - &self, - attribute: impl Into>, - ) -> Result>, Box> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); + /// Sets whether this mob can join an active raid. + pub fn set_can_join_raid(&self, join: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(join.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getAttribute", + "setCanJoinRaid", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::attribute::AttributeInstance::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Deals the given amount of damage to this entity from a specified - /// {@link DamageSource}. - pub fn damage( - &self, - amount: f64, - damage_source: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(amount); - args.push(val_1); - if let Some(a) = damage_source { - sig += "Lorg/bukkit/damage/DamageSource;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "damage", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. - pub fn health(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); + /// Get the amount of ticks that this mob has exited the bounds of a village + /// as a raid participant. + /// + /// This value is increased only when the mob has had no action for 2,400 ticks + /// (according to {@link #getNoActionTicks()}). Once both the no action ticks have + /// reached that value and the ticks outside a raid exceeds 30, the mob will be + /// expelled from the raid. + pub fn ticks_outside_raid(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTicksOutsideRaid", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.i()?) } - /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is - /// dead. - pub fn set_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); + /// Set the amount of ticks that this mob has exited the bounds of a village + /// as a raid participant. + /// + /// This value is considered only when the mob has had no action for 2,400 ticks + /// (according to {@link #getNoActionTicks()}). Once both the no action ticks have + /// reached that value and the ticks outside a raid exceeds 30, the mob will be + /// expelled from the raid. + pub fn set_ticks_outside_raid(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setHealth", + "setTicksOutsideRaid", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the entity's absorption amount. - pub fn absorption_amount(&self) -> Result> { - let sig = String::from("()D"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAbsorptionAmount", - sig.as_str(), - vec![], - ); + /// Check whether or not this raider is celebrating a raid victory. + pub fn is_celebrating(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCelebrating", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Sets the entity's absorption amount. - /// - /// Note: The amount is capped to the value of - /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on - /// that attribute is currently unspecified and subject to change. - pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(amount); + /// Set whether or not this mob is celebrating a raid victory. + pub fn set_celebrating(&self, celebrating: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(celebrating.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setAbsorptionAmount", + "setCelebrating", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the maximum health this entity has. - pub fn max_health(&self) -> Result> { - let sig = String::from("()D"); + /// Get the {@link Sound} this entity will play when celebrating. + pub fn celebration_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCelebrationSound", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Vindicator<'mc> { + fn into(self) -> crate::entity::Illager<'mc> { + crate::entity::Illager::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Vindicator into crate::entity::Illager") + } +} +#[repr(C)] +pub struct Mule<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Mule<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Mule<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Mule from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Mule")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Mule object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Mule<'mc> { + /// Gets whether the horse has a chest equipped. + pub fn is_carrying_chest(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCarryingChest", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - #[deprecated] - /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. - pub fn set_max_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); + /// Sets whether the horse has a chest equipped. Removing a chest will also + /// clear the chest's inventory. + pub fn set_carrying_chest(&self, chest: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(chest.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxHealth", + "setCarryingChest", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Resets the max health to the original amount. - pub fn reset_max_health(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Launches a {@link Projectile} from the ProjectileSource with an - /// initial velocity. - pub fn launch_projectile( - &self, - projectile: jni::objects::JClass<'mc>, - velocity: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/Class;"; - let val_1 = jni::objects::JValueGen::Object(projectile.into()); - args.push(val_1); - if let Some(a) = velocity { - sig += "Lorg/bukkit/util/Vector;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")LT;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) - } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Hoglin<'mc> { - fn into(self) -> crate::entity::Animals<'mc> { - crate::entity::Animals::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Hoglin into crate::entity::Animals") - } -} -impl<'mc> Into> for Hoglin<'mc> { - fn into(self) -> crate::entity::Enemy<'mc> { - crate::entity::Enemy::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Hoglin into crate::entity::Enemy") +impl<'mc> Into> for Mule<'mc> { + fn into(self) -> crate::entity::ChestedHorse<'mc> { + crate::entity::ChestedHorse::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Mule into crate::entity::ChestedHorse") } } #[repr(C)] -pub struct HumanEntity<'mc>( +pub struct SpectralArrow<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for HumanEntity<'mc> { +impl<'mc> JNIRaw<'mc> for SpectralArrow<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -37368,18 +44367,18 @@ impl<'mc> JNIRaw<'mc> for HumanEntity<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for HumanEntity<'mc> { +impl<'mc> JNIInstantiatable<'mc> for SpectralArrow<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate HumanEntity from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate SpectralArrow from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/HumanEntity")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/SpectralArrow")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a HumanEntity object, got {}", + "Invalid argument passed. Expected a SpectralArrow object, got {}", name ) .into()) @@ -37389,870 +44388,1052 @@ impl<'mc> JNIInstantiatable<'mc> for HumanEntity<'mc> { } } -impl<'mc> HumanEntity<'mc> { - /// Returns the name of this player - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Get the player's inventory. - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/PlayerInventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::PlayerInventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the player's EnderChest inventory - pub fn ender_chest( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEnderChest", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the player's selected main hand - pub fn main_hand(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/MainHand;"); +impl<'mc> SpectralArrow<'mc> { + /// Returns the amount of time that this arrow will apply + /// the glowing effect for. + pub fn glowing_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMainHand", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getGlowingTicks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::MainHand::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// If the player currently has an inventory window open, this method will - /// set a property of that window, such as the state of a progress bar. - pub fn set_window_property( - &self, - prop: impl Into>, - value: i32, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/InventoryView/Property;I)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(prop.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(value); + /// Sets the amount of time to apply the glowing effect for. + pub fn set_glowing_ticks(&self, duration: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(duration); let res = self.jni_ref().call_method( &self.jni_object(), - "setWindowProperty", + "setGlowingTicks", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the player's current enchantment seed. - /// The Seed is used to generate enchantment options in the enchanting table - /// for the player. - pub fn enchantment_seed(&self) -> Result> { + #[deprecated] + /// Gets the knockback strength for an arrow, which is the {@link org.bukkit.enchantments.Enchantment#KNOCKBACK KnockBack} level of the bow that shot it. + pub fn knockback_strength(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getEnchantmentSeed", + "getKnockbackStrength", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the player's enchantment seed. - /// The Seed is used to generate enchantment options in the enchanting table - /// for the player. - pub fn set_enchantment_seed(&self, seed: i32) -> Result<(), Box> { + #[deprecated] + /// Sets the knockback strength for an arrow. + pub fn set_knockback_strength( + &self, + knockback_strength: i32, + ) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(seed); + let val_1 = jni::objects::JValueGen::Int(knockback_strength); let res = self.jni_ref().call_method( &self.jni_object(), - "setEnchantmentSeed", + "setKnockbackStrength", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Opens an inventory window to the specified inventory view. - pub fn open_inventory( - &self, - inventory: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = inventory { - sig += "Lorg/bukkit/inventory/InventoryView;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getOpenInventory", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Opens an inventory window to the specified inventory view. - pub fn open_inventory_with_inventory( - &self, - inventory: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = inventory { - sig += "Lorg/bukkit/inventory/InventoryView;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "openInventory", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Opens an empty workbench inventory window with the player's inventory - /// on the bottom. - pub fn open_workbench( - &self, - location: impl Into>, - force: bool, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;Z)Lorg/bukkit/inventory/InventoryView;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Bool(force.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "openWorkbench", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + /// Gets the base amount of damage this arrow will do. + /// Defaults to 2.0 for a normal arrow with + /// 0.5 * (1 + power level) added for arrows fired from + /// enchanted bows. + pub fn damage(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getDamage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::InventoryView::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.d()?) } - /// Opens an empty enchanting inventory window with the player's inventory - /// on the bottom. - pub fn open_enchanting( - &self, - location: impl Into>, - force: bool, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;Z)Lorg/bukkit/inventory/InventoryView;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Bool(force.into()); + /// Sets the base amount of damage this arrow will do. + pub fn set_damage(&self, damage: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(damage); let res = self.jni_ref().call_method( &self.jni_object(), - "openEnchanting", + "setDamage", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::InventoryView::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Starts a trade between the player and the merchant. - /// Note that only one player may trade with a merchant at once. You must use - /// the force parameter for this. - pub fn open_merchant( - &self, - merchant: impl Into>, - force: bool, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/Merchant;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(merchant.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(force.into()); - args.push(val_2); - sig += ")Lorg/bukkit/inventory/InventoryView;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "openMerchant", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::InventoryView::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Force-closes the currently open inventory view for this player, if any. - pub fn close_inventory(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "closeInventory", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Returns the ItemStack currently in your hand, can be empty. - pub fn item_in_hand( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + /// Gets the number of times this arrow can pierce through an entity. + pub fn pierce_level(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemInHand", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPierceLevel", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - #[deprecated] - /// Sets the item to the given ItemStack, this will replace whatever the user was holding. - pub fn set_item_in_hand( - &self, - item: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); + /// Sets the number of times this arrow can pierce through an entity. + /// Must be between 0 and 127 times. + pub fn set_pierce_level(&self, pierce_level: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(pierce_level); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemInHand", + "setPierceLevel", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the ItemStack currently on your cursor, can be empty. Will - /// always be empty if the player currently has no open window. - pub fn item_on_cursor( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + /// Gets whether this arrow is critical. + /// + /// Critical arrows have increased damage and cause particle effects. + /// + /// Critical arrows generally occur when a player fully draws a bow before + /// firing. + pub fn is_critical(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemOnCursor", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCritical", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets the item to the given ItemStack, this will replace whatever the - /// user was moving. Will always be empty if the player currently has no - /// open window. - pub fn set_item_on_cursor( - &self, - item: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); + /// Sets whether or not this arrow should be critical. + pub fn set_critical(&self, critical: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(critical.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemOnCursor", + "setCritical", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check whether a cooldown is active on the specified material. - pub fn has_cooldown( - &self, - material: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/Material;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasCooldown", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Gets whether this arrow is in a block or not. + /// + /// Arrows in a block are motionless and may be picked up by players. + pub fn is_in_block(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInBlock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get the cooldown time in ticks remaining for the specified material. - pub fn get_cooldown( + /// Gets the block to which this arrow is attached. + pub fn attached_block( &self, - material: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/Material;)I"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCooldown", + "getAttachedBlock", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::block::Block::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Set a cooldown on the specified material for a certain amount of ticks. - /// ticks. 0 ticks will result in the removal of the cooldown. - /// - /// Cooldowns are used by the server for items such as ender pearls and - /// shields to prevent them from being used repeatedly. - /// - /// Note that cooldowns will not by themselves stop an item from being used - /// for attacking. - pub fn set_cooldown( + /// Gets the current pickup status of this arrow. + pub fn pickup_status( &self, - material: impl Into>, - ticks: i32, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/AbstractArrow/PickupStatus;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPickupStatus", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::AbstractArrowPickupStatus::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the current pickup status of this arrow. + pub fn set_pickup_status( + &self, + status: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Material;I)V"); + let sig = String::from("(Lorg/bukkit/entity/AbstractArrow/PickupStatus;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) + jni::objects::JObject::from_raw(status.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setCooldown", + "setPickupStatus", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the sleep ticks of the player. This value may be capped. - pub fn sleep_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSleepTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Attempts to make the entity sleep at the given location. - /// - /// The location must be in the current world and have a bed placed at the - /// location. The game may also enforce other requirements such as proximity - /// to bed, monsters, and dimension type if force is not set. - pub fn sleep( - &self, - location: impl Into>, - force: bool, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/Location;Z)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Bool(force.into()); + /// Gets if this arrow was shot from a crossbow. + pub fn is_shot_from_crossbow(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "sleep", + "isShotFromCrossbow", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Causes the player to wakeup if they are currently sleeping. - pub fn wakeup(&self, set_spawn_location: bool) -> Result<(), Box> { + #[deprecated] + /// Sets if this arrow was shot from a crossbow. + pub fn set_shot_from_crossbow( + &self, + shot_from_crossbow: bool, + ) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(set_spawn_location.into()); + let val_1 = jni::objects::JValueGen::Bool(shot_from_crossbow.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "wakeup", + "setShotFromCrossbow", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the location of the bed the player is currently sleeping in - pub fn bed_location(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBedLocation", sig.as_str(), vec![]); + /// Gets the ItemStack which will be picked up from this arrow. + pub fn item(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/inventory/ItemStack;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets this human's current {@link GameMode} - pub fn game_mode(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/GameMode;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getGameMode", sig.as_str(), vec![]); + /// Sets the ItemStack which will be picked up from this arrow. + pub fn set_item( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setItem", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the ItemStack which fired this arrow. + pub fn weapon(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWeapon", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::GameMode::from_raw(&self.jni_ref(), unsafe { + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets this human's current {@link GameMode} - pub fn set_game_mode( + /// Sets the ItemStack which fired this arrow. + pub fn set_weapon( &self, - mode: impl Into>, + item: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/GameMode;)V"); + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(mode.into().jni_object().clone()) + jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setGameMode", + "setWeapon", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check if the player is currently blocking (ie with a shield). - pub fn is_blocking(&self) -> Result> { + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for SpectralArrow<'mc> { + fn into(self) -> crate::entity::AbstractArrow<'mc> { + crate::entity::AbstractArrow::from_raw(&self.jni_ref(), self.1) + .expect("Error converting SpectralArrow into crate::entity::AbstractArrow") + } +} +#[repr(C)] +pub struct Zombie<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Zombie<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Zombie<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Zombie from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Zombie")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Zombie object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Zombie<'mc> { + #[deprecated] + /// Gets whether the zombie is a baby + pub fn is_baby(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isBlocking", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isBaby", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Check if the player currently has their hand raised (ie about to begin - /// blocking). - pub fn is_hand_raised(&self) -> Result> { + #[deprecated] + /// Sets whether the zombie is a baby + pub fn set_baby( + &self, + flag: std::option::Option, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = flag { + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_1); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setBaby", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets whether the zombie is a villager + pub fn is_villager(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isHandRaised", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isVillager", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get the total amount of experience required for the player to level - pub fn exp_to_level(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getExpToLevel", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the current cooldown for a player's attack. - /// This is used to calculate damage, with 1.0 representing a fully charged - /// attack and 0.0 representing a non-charged attack - pub fn attack_cooldown(&self) -> Result> { - let sig = String::from("()F"); + #[deprecated] + + pub fn set_villager(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getAttackCooldown", + "setVillager", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Discover a recipe for this player such that it has not already been - /// discovered. This method will add the key's associated recipe to the - /// player's recipe book. - pub fn discover_recipe( + #[deprecated] + + pub fn set_villager_profession( &self, - recipe: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)Z"); + profession: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Villager/Profession;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) + jni::objects::JObject::from_raw(profession.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "discoverRecipe", + "setVillagerProfession", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Undiscover a recipe for this player such that it has already been - /// discovered. This method will remove the key's associated recipe from the - /// player's recipe book. - pub fn undiscover_recipe( + #[deprecated] + + pub fn villager_profession( &self, - recipe: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) - }); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Villager/Profession;"); let res = self.jni_ref().call_method( &self.jni_object(), - "undiscoverRecipe", + "getVillagerProfession", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::VillagerProfession::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Check whether or not this entity has discovered the specified recipe. - pub fn has_discovered_recipe( - &self, - recipe: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasDiscoveredRecipe", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Get if this entity is in the process of converting to a Drowned as a + /// result of being underwater. + pub fn is_converting(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isConverting", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get an immutable set of recipes this entity has discovered. - pub fn discovered_recipes( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Gets the amount of ticks until this entity will be converted to a Drowned + /// as a result of being underwater. + /// When this reaches 0, the entity will be converted. + pub fn conversion_time(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getDiscoveredRecipes", + "getConversionTime", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - #[deprecated] - /// Gets the entity currently perched on the left shoulder or null if no entity. - /// - /// The returned entity will not be spawned within the world, so most operations are invalid unless the entity is first spawned in. - pub fn shoulder_entity_left( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + /// Sets the amount of ticks until this entity will be converted to a Drowned + /// as a result of being underwater. + /// When this reaches 0, the entity will be converted. A value of less than 0 + /// will stop the current conversion process without converting the current + /// entity. + pub fn set_conversion_time(&self, time: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(time); let res = self.jni_ref().call_method( &self.jni_object(), - "getShoulderEntityLeft", + "setConversionTime", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether this zombie can break doors + pub fn can_break_doors(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "canBreakDoors", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - #[deprecated] - /// Sets the entity currently perched on the left shoulder, or null to remove. This method will remove the entity from the world. - /// - /// Note that only a copy of the entity will be set to display on the shoulder. - /// - /// Also note that the client will currently only render {@link Parrot} entities. - pub fn set_shoulder_entity_left( - &self, - entity: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) - }); + /// Sets whether this zombie can break doors + /// This will be ignored if the entity is a Drowned. Will also stop the action if + /// the entity is currently breaking a door. + pub fn set_can_break_doors(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setShoulderEntityLeft", + "setCanBreakDoors", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the entity currently perched on the right shoulder or null if no entity. - /// - /// The returned entity will not be spawned within the world, so most operations are invalid unless the entity is first spawned in. - pub fn shoulder_entity_right( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + /// Gets the age of this mob. + pub fn age(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getAge", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the age of this mob. + pub fn set_age(&self, age: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(age); let res = self.jni_ref().call_method( &self.jni_object(), - "getShoulderEntityRight", + "setAge", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + self.jni_ref().translate_error(res)?; + Ok(()) } #[deprecated] - /// Sets the entity currently perched on the right shoulder, or null to remove. This method will remove the entity from the world. - /// - /// Note that only a copy of the entity will be set to display on the shoulder. - /// - /// Also note that the client will currently only render {@link Parrot} entities. - pub fn set_shoulder_entity_right( - &self, - entity: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) - }); + /// Lock the age of the animal, setting this will prevent the animal from maturing or getting ready for mating. + pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(lock.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setShoulderEntityRight", + "setAgeLock", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Make the entity drop the item in their hand. - /// - /// This will force the entity to drop the item they are holding with - /// an option to drop the entire {@link ItemStack} or just 1 of the items. - pub fn drop_item(&self, drop_all: bool) -> Result> { - let sig = String::from("(Z)Z"); - let val_1 = jni::objects::JValueGen::Bool(drop_all.into()); + #[deprecated] + /// Gets the current agelock. + pub fn age_lock(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the age of the mob to an adult + pub fn set_adult(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setAdult", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns true if the mob is an adult. + pub fn is_adult(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isAdult", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Return the ability to breed of the animal. + pub fn can_breed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Set breedability of the animal, if the animal is a baby and set to breed it will instantly grow up. + pub fn set_breed(&self, breed: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(breed.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "dropItem", + "setBreed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the players current exhaustion level. - /// - /// Exhaustion controls how fast the food level drops. While you have a - /// certain amount of exhaustion, your saturation will drop to zero, and - /// then your food will drop to zero. - pub fn exhaustion(&self) -> Result> { - let sig = String::from("()F"); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Zombie<'mc> { + fn into(self) -> crate::entity::Monster<'mc> { + crate::entity::Monster::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Zombie into crate::entity::Monster") + } +} +impl<'mc> Into> for Zombie<'mc> { + fn into(self) -> crate::entity::Ageable<'mc> { + crate::entity::Ageable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Zombie into crate::entity::Ageable") + } +} +#[repr(C)] +pub struct Parrot<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Parrot<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Parrot<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Parrot from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Parrot")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Parrot object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Parrot<'mc> { + /// Get the variant of this parrot. + pub fn variant(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Parrot/Variant;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getExhaustion", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + crate::entity::ParrotVariant::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the players current exhaustion level - pub fn set_exhaustion(&self, value: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(value); + /// Set the variant of this parrot. + pub fn set_variant( + &self, + variant: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Parrot/Variant;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(variant.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setExhaustion", + "setVariant", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the players current saturation level. + /// Gets whether a parrot is dancing + pub fn is_dancing(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isDancing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Check if this is tamed /// - /// Saturation is a buffer for food level. Your food level will not drop if - /// you are saturated {@literal >} 0. - pub fn saturation(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSaturation", sig.as_str(), vec![]); + /// If something is tamed then a player can not tame it through normal + /// methods, even if it does not belong to anyone in particular. + pub fn is_tamed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isTamed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + Ok(res.z()?) } - /// Sets the players current saturation level - pub fn set_saturation(&self, value: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(value); + /// Sets if this has been tamed. Not necessary if the method setOwner has + /// been used, as it tames automatically. + /// + /// If something is tamed then a player can not tame it through normal + /// methods, even if it does not belong to anyone in particular. + pub fn set_tamed(&self, tame: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(tame.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setSaturation", + "setTamed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the players current food level - pub fn food_level(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFoodLevel", sig.as_str(), vec![]); + /// Gets the current owning AnimalTamer + pub fn owner( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/AnimalTamer;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::AnimalTamer::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the players current food level - pub fn set_food_level(&self, value: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(value); + /// Set this to be owned by given AnimalTamer. + /// + /// If the owner is not null, this will be tamed and will have any current + /// path it is following removed. If the owner is set to null, this will be + /// untamed, and the current owner removed. + pub fn set_owner( + &self, + tamer: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/AnimalTamer;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(tamer.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setFoodLevel", + "setOwner", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the regeneration rate (1 health per x ticks) of - /// the HumanEntity when they have saturation and - /// their food level is {@literal >=} 20. Default is 10. - pub fn saturated_regen_rate(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSaturatedRegenRate", - sig.as_str(), - vec![], - ); + /// Checks if this animal is sitting + pub fn is_sitting(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSitting", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the regeneration rate (1 health per x ticks) of - /// the HumanEntity when they have saturation and - /// their food level is {@literal >=} 20. Default is 10. - /// Not affected if the world's difficulty is peaceful. - pub fn set_saturated_regen_rate(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets if this animal is sitting. Will remove any path that the animal + /// was following beforehand. + pub fn set_sitting(&self, sitting: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(sitting.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setSaturatedRegenRate", + "setSitting", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the regeneration rate (1 health per x ticks) of - /// the HumanEntity when they have no saturation and - /// their food level is {@literal >=} 18. Default is 80. - pub fn unsaturated_regen_rate(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getUnsaturatedRegenRate", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Get the regeneration rate (1 health per x ticks) of - /// the HumanEntity when they have no saturation and - /// their food level is {@literal >=} 18. Default is 80. - /// Not affected if the world's difficulty is peaceful. - pub fn set_unsaturated_regen_rate(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setUnsaturatedRegenRate", - sig.as_str(), +} +impl<'mc> Into> for Parrot<'mc> { + fn into(self) -> crate::entity::Tameable<'mc> { + crate::entity::Tameable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Parrot into crate::entity::Tameable") + } +} +impl<'mc> Into> for Parrot<'mc> { + fn into(self) -> crate::entity::Sittable<'mc> { + crate::entity::Sittable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Parrot into crate::entity::Sittable") + } +} +pub enum ParrotVariant<'mc> { + Red { inner: ParrotVariantStruct<'mc> }, + Blue { inner: ParrotVariantStruct<'mc> }, + Green { inner: ParrotVariantStruct<'mc> }, + Cyan { inner: ParrotVariantStruct<'mc> }, + Gray { inner: ParrotVariantStruct<'mc> }, +} +impl<'mc> std::fmt::Display for ParrotVariant<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ParrotVariant::Red { .. } => f.write_str("RED"), + ParrotVariant::Blue { .. } => f.write_str("BLUE"), + ParrotVariant::Green { .. } => f.write_str("GREEN"), + ParrotVariant::Cyan { .. } => f.write_str("CYAN"), + ParrotVariant::Gray { .. } => f.write_str("GRAY"), + } + } +} +impl<'mc> std::ops::Deref for ParrotVariant<'mc> { + type Target = ParrotVariantStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + ParrotVariant::Red { inner } => inner, + ParrotVariant::Blue { inner } => inner, + ParrotVariant::Green { inner } => inner, + ParrotVariant::Cyan { inner } => inner, + ParrotVariant::Gray { inner } => inner, + } + } +} + +impl<'mc> ParrotVariant<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/Parrot/Variant"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/Parrot/Variant;", vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "RED" => Ok(ParrotVariant::Red { + inner: ParrotVariantStruct::from_raw(env, obj)?, + }), + "BLUE" => Ok(ParrotVariant::Blue { + inner: ParrotVariantStruct::from_raw(env, obj)?, + }), + "GREEN" => Ok(ParrotVariant::Green { + inner: ParrotVariantStruct::from_raw(env, obj)?, + }), + "CYAN" => Ok(ParrotVariant::Cyan { + inner: ParrotVariantStruct::from_raw(env, obj)?, + }), + "GRAY" => Ok(ParrotVariant::Gray { + inner: ParrotVariantStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } - /// Get the starvation rate (1 health per x ticks) of - /// the HumanEntity. Default is 80. - pub fn starvation_rate(&self) -> Result> { +} + +#[repr(C)] +pub struct ParrotVariantStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ParrotVariant<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Red { inner } => inner.0.clone(), + Self::Blue { inner } => inner.0.clone(), + Self::Green { inner } => inner.0.clone(), + Self::Cyan { inner } => inner.0.clone(), + Self::Gray { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Red { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Blue { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Green { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Cyan { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Gray { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for ParrotVariant<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate ParrotVariant from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Parrot/Variant")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ParrotVariant object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "RED" => Ok(ParrotVariant::Red { + inner: ParrotVariantStruct::from_raw(env, obj)?, + }), + "BLUE" => Ok(ParrotVariant::Blue { + inner: ParrotVariantStruct::from_raw(env, obj)?, + }), + "GREEN" => Ok(ParrotVariant::Green { + inner: ParrotVariantStruct::from_raw(env, obj)?, + }), + "CYAN" => Ok(ParrotVariant::Cyan { + inner: ParrotVariantStruct::from_raw(env, obj)?, + }), + "GRAY" => Ok(ParrotVariant::Gray { + inner: ParrotVariantStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for ParrotVariantStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for ParrotVariantStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate ParrotVariantStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Parrot/Variant")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ParrotVariantStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> ParrotVariantStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Parrot/Variant;"); + let cls = jni.find_class("org/bukkit/entity/Parrot/Variant"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::ParrotVariant::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct ExperienceOrb<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ExperienceOrb<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for ExperienceOrb<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate ExperienceOrb from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ExperienceOrb")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ExperienceOrb object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> ExperienceOrb<'mc> { + /// Gets how much experience is contained within this orb + pub fn experience(&self) -> Result> { let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getStarvationRate", - sig.as_str(), - vec![], - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getExperience", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Get the starvation rate (1 health per x ticks) of - /// the HumanEntity. Default is 80. - pub fn set_starvation_rate(&self, ticks: i32) -> Result<(), Box> { + /// Sets how much experience is contained within this orb + pub fn set_experience(&self, value: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + let val_1 = jni::objects::JValueGen::Int(value); let res = self.jni_ref().call_method( &self.jni_object(), - "setStarvationRate", + "setExperience", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the player's last death location. - pub fn last_death_location( + /// Stores the entity's current position in the provided Location object. + /// + /// If the provided Location is null this method does nothing and returns + /// null. + pub fn get_location( &self, + loc: impl Into>, ) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/Location;"; + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getLastDeathLocation", + "getLocation", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { @@ -38262,163 +45443,169 @@ impl<'mc> HumanEntity<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) })?)) } - /// Sets the player's last death location. - /// - /// Note: This data is updated in the player's client only when the - /// player respawns. - pub fn set_last_death_location( + /// Sets this entity's velocity in meters per tick + pub fn set_velocity( &self, - location: impl Into>, + velocity: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Location;)V"); + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) + jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDeathLocation", + "setVelocity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Perform a firework boost. - /// - /// This method will only work such that {@link #isGliding()} is true and - /// the entity is actively gliding with an elytra. Additionally, the supplied - /// {@code fireworkItemStack} must be a firework rocket. The power of the boost - /// will directly correlate to {@link FireworkMeta#getPower()}. - pub fn firework_boost( - &self, - firework_item_stack: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/entity/Firework;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(firework_item_stack.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "fireworkBoost", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Gets this entity's current velocity + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Firework::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the height of the living entity's eyes above its Location. - pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { - let sig = String::from("(Z)D"); - let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getEyeHeight", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Gets the entity's height + pub fn height(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.d()?) } - /// Get a Location detailing the current eye position of the living entity. - pub fn eye_location(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); + /// Gets the entity's width + pub fn width(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the entity's current bounding box. + /// + /// The returned bounding box reflects the entity's current location and + /// size. + pub fn bounding_box( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets all blocks along the living entity's line of sight. - /// - /// This list contains all blocks from the living entity's eye position to - /// target inclusive. This method considers all blocks as 1x1x1 in size. - pub fn get_line_of_sight( - &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { - let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(max_distance); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLineOfSight", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + /// Returns true if the entity is supported by a block. This value is a + /// state updated by the server and is not recalculated unless the entity + /// moves. + pub fn is_on_ground(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns true if the entity is in water. + pub fn is_in_water(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(res.z()?) } - /// Gets the block that the living entity has targeted. + /// Gets the current world this entity resides in + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the entity's rotation. /// - /// This method considers all blocks as 1x1x1 in size. To take exact block - /// collision shapes into account, see {@link #getTargetBlockExact(int, - /// FluidCollisionMode)}. - pub fn get_target_block( - &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result, Box> { - let sig = String::from("(Ljava/util/Set;I)Lorg/bukkit/block/Block;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(max_distance); + /// Note that if the entity is affected by AI, it may override this rotation. + pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { + let sig = String::from("(FF)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); + let val_2 = jni::objects::JValueGen::Float(pitch); let res = self.jni_ref().call_method( &self.jni_object(), - "getTargetBlock", + "setRotation", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), ], ); - let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the last two blocks along the living entity's line of sight. - /// - /// The target block will be the last block in the list. This method - /// considers all blocks as 1x1x1 in size. - pub fn get_last_two_target_blocks( + /// Teleports this entity to the given location. If this entity is riding a + /// vehicle, it will be dismounted prior to teleportation. + pub fn teleport( &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { - let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + location: impl Into>, + cause: std::option::Option< + impl Into>, + >, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + jni::objects::JObject::from_raw(location.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(max_distance); + args.push(val_1); + if let Some(a) = cause { + sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "teleport", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns a list of entities within a bounding box centered around this + /// entity + pub fn get_nearby_entities( + &self, + x: f64, + y: f64, + z: f64, + ) -> Result>, Box> { + let sig = String::from("(DDD)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Double(x); + let val_2 = jni::objects::JValueGen::Double(y); + let val_3 = jni::objects::JValueGen::Double(z); let res = self.jni_ref().call_method( &self.jni_object(), - "getLastTwoTargetBlocks", + "getNearbyEntities", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), ], ); let res = self.jni_ref().translate_error(res)?; @@ -38427,879 +45614,1009 @@ impl<'mc> HumanEntity<'mc> { let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); } Ok(new_vec) } - /// Gets the block that the living entity has targeted. - /// - /// This takes the blocks' precise collision shapes into account. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn get_target_block_exact( - &self, - max_distance: i32, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(max_distance); - args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/block/Block;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTargetBlockExact", - sig.as_str(), - args, - ); + /// Returns a unique id for this entity + pub fn entity_id(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::block::Block::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - /// Performs a ray trace that provides information on the targeted block. - /// - /// This takes the blocks' precise collision shapes into account. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn ray_trace_blocks( - &self, - max_distance: f64, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(max_distance); - args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/util/RayTraceResult;"; + /// Returns the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn fire_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); + .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::util::RayTraceResult::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - /// Returns the amount of air that the living entity has remaining, in - /// ticks. - pub fn remaining_air(&self) -> Result> { + /// Returns the entity's maximum fire ticks. + pub fn max_fire_ticks(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the amount of air that the living entity has remaining, in ticks. - pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { + /// Sets the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setRemainingAir", + "setFireTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the maximum amount of air the living entity can have, in ticks. - pub fn maximum_air(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the maximum amount of air the living entity can have, in ticks. - pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets if the entity has visual fire (it will always appear to be on fire). + pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaximumAir", + "setVisualFire", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the item that the player is using (eating food, drawing back a bow, - /// blocking, etc.) - pub fn item_in_use( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + /// Gets if the entity has visual fire (it will always appear to be on fire). + pub fn is_visual_fire(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Gets the number of ticks remaining for the current item's usage. - pub fn item_in_use_ticks(&self) -> Result> { + /// Returns the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's maximum freeze ticks (amount of ticks before it will + /// be fully frozen) + pub fn max_freeze_ticks(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getItemInUseTicks", + "getMaxFreezeTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the number of ticks that remain for the current item's usage. - /// Applies to items that take time to use, like eating food, drawing a bow, - /// or throwing a trident. - pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Sets the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemInUseTicks", + "setFreezeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the time in ticks until the next arrow leaves the entity's body. - pub fn arrow_cooldown(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getArrowCooldown", - sig.as_str(), - vec![], - ); + /// Gets if the entity is fully frozen (it has been in powdered snow for max + /// freeze ticks). + pub fn is_frozen(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the time in ticks until the next arrow leaves the entity's body. - pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Mark the entity's removal. + pub fn remove(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns true if this entity has been marked for removal. + pub fn is_dead(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns false if the entity has died, been despawned for some other + /// reason, or has not been added to the world. + pub fn is_valid(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the {@link Server} that contains this Entity + pub fn server(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Server;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Server::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns true if the entity gets persisted. + /// + /// By default all entities are persistent. An entity will also not get + /// persisted, if it is riding an entity that is not persistent. + /// + /// The persistent flag on players controls whether or not to save their + /// playerdata file when they quit. If a player is directly or indirectly + /// riding a non-persistent entity, the vehicle at the root and all its + /// passengers won't get persisted. + /// + /// This should not be confused with + /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls + /// despawning of living entities. + pub fn is_persistent(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether or not the entity gets persisted. + pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(persistent.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setArrowCooldown", + "setPersistent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the amount of arrows in an entity's body. - pub fn arrows_in_body(&self) -> Result> { - let sig = String::from("()I"); + #[deprecated] + /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. + pub fn passenger( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Set the amount of arrows in the entity's body. - pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(count); + #[deprecated] + /// Set the passenger of a vehicle. + pub fn set_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setArrowsInBody", + "setPassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Returns the living entity's current maximum no damage ticks. + /// Gets a list of passengers of this vehicle. /// - /// This is the maximum duration in which the living entity will not take - /// damage. - pub fn maximum_no_damage_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// The returned list will not be directly linked to the entity's current + /// passengers, and no guarantees are made as to its mutability. + pub fn passengers( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Add a passenger to the vehicle. + pub fn add_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getMaximumNoDamageTicks", + "addPassenger", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the living entity's current maximum no damage ticks. - pub fn set_maximum_no_damage_ticks( + /// Remove a passenger from the vehicle. + pub fn remove_passenger( &self, - ticks: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaximumNoDamageTicks", + "removePassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Returns the living entity's last damage taken in the current no damage - /// ticks time. - /// - /// Only damage higher than this amount will further damage the living - /// entity. - pub fn last_damage(&self) -> Result> { - let sig = String::from("()D"); + /// Check if a vehicle has passengers. + pub fn is_empty(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Eject any passenger. + pub fn eject(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the distance this entity has fallen + pub fn fall_distance(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.f()?) } - /// Sets the damage dealt within the current no damage ticks time period. - pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(damage); + /// Sets the fall distance for this entity + pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDamage", + "setFallDistance", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Record the last {@link EntityDamageEvent} inflicted on this entity + pub fn set_last_damage_cause( + &self, + event: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(event.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLastDamageCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's current no damage ticks. - pub fn no_damage_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. + /// This event may have been cancelled. + pub fn last_damage_cause( + &self, + ) -> Result>, Box> + { + let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getNoDamageTicks", + "getLastDamageCause", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Returns a unique and persistent id for this entity + pub fn unique_id( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. + pub fn ticks_lived(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the living entity's current no damage ticks. - pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Sets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. May not be less than one + /// tick. + pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + let val_1 = jni::objects::JValueGen::Int(value); let res = self.jni_ref().call_method( &self.jni_object(), - "setNoDamageTicks", + "setTicksLived", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the ticks that this entity has performed no action. + /// Performs the specified {@link EntityEffect} for this entity. /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn no_action_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getNoActionTicks", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the ticks that this entity has performed no action. + /// This will be viewable to all players near the entity. /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// If the effect is not applicable to this class of entity, it will not play. + pub fn play_effect( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setNoActionTicks", + "playEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the player identified as the killer of the living entity. - /// - /// May be null. - pub fn killer(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Player;"); + /// Get the type of the entity. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Player::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. - pub fn add_potion_effect( - &self, - effect: impl Into>, - force: std::option::Option, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/potion/PotionEffect;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(effect.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = force { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")Z"; + /// Get the {@link Sound} this entity makes while swimming. + pub fn swim_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); + .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns whether the living entity already has an existing effect of - /// the given {@link PotionEffectType} applied to it. - pub fn has_potion_effect( - &self, - val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Get the {@link Sound} this entity makes when splashing in water. For most + /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_splash_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasPotionEffect", + "getSwimSplashSound", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the active {@link PotionEffect} of the specified type. - /// - /// If the effect is not present on the entity then null will be returned. - pub fn get_potion_effect( + /// Get the {@link Sound} this entity makes when splashing in water at high + /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_high_speed_splash_sound( &self, - val_type: impl Into>, - ) -> Result>, Box> { - let sig = - String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPotionEffect", + "getSwimHighSpeedSplashSound", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns whether this entity is inside a vehicle. + pub fn is_inside_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Leave the current vehicle. If the entity is currently in a vehicle (and + /// is removed from it), true will be returned, otherwise false will be + /// returned. + pub fn leave_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the vehicle that this entity is inside. If there is no vehicle, + /// null will be returned. + pub fn vehicle( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::potion::PotionEffect::from_raw( + Ok(Some(crate::entity::Entity::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Removes any effects present of the given {@link PotionEffectType}. - pub fn remove_potion_effect( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Sets whether or not to display the mob's custom name client side. The + /// name will be displayed above the mob similarly to a player. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "removePotionEffect", + "setCustomNameVisible", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns all currently active {@link PotionEffect}s on the living - /// entity. - pub fn active_potion_effects( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); + /// Gets whether or not the mob's custom name is displayed client side. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn is_custom_name_visible(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getActivePotionEffects", + "isCustomNameVisible", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(res.z()?) } - /// Checks whether the living entity has block line of sight to another. + /// Sets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(visible.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVisibleByDefault", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn is_visible_by_default(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isVisibleByDefault", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get all players that are currently tracking this entity. /// - /// This uses the same algorithm that hostile mobs use to find the closest - /// player. - pub fn has_line_of_sight( + /// 'Tracking' means that this entity has been sent to the player and that + /// they are receiving updates on its state. Note that the client's {@code + /// 'Entity Distance'} setting does not affect the range at which entities + /// are tracked. + pub fn tracked_by( &self, - other: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) - }); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets whether the entity has a team colored (default: white) glow. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "hasLineOfSight", + "setGlowing", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether the entity is glowing or not. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn is_glowing(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns if the living entity despawns when away from players or not. + /// Sets whether the entity is invulnerable or not. /// - /// By default, animals are not removed while other mobs are. - pub fn remove_when_far_away(&self) -> Result> { - let sig = String::from("()Z"); + /// When an entity is invulnerable it can only be damaged by players in + /// creative mode. + pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getRemoveWhenFarAway", + "setInvulnerable", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether the entity is invulnerable or not. + pub fn is_invulnerable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not the living entity despawns when away from players - /// or not. - pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { + /// Gets whether the entity is silent or not. + pub fn is_silent(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the entity is silent or not. + /// + /// When an entity is silent it will not produce any sound. + pub fn set_silent(&self, flag: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(remove.into()); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setRemoveWhenFarAway", + "setSilent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the inventory with the equipment worn by the living entity. - pub fn equipment( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); + /// Returns whether gravity applies to this entity. + pub fn has_gravity(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::EntityEquipment::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Sets whether or not the living entity can pick up items. - pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { + /// Sets whether gravity applies to this entity. + pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(pickup.into()); + let val_1 = jni::objects::JValueGen::Bool(gravity.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCanPickupItems", + "setGravity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the living entity can pick up items. - pub fn can_pickup_items(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the period of time (in ticks) before this entity can use a portal. + pub fn portal_cooldown(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCanPickupItems", + "getPortalCooldown", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Returns whether the entity is currently leashed. - pub fn is_leashed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Sets the period of time (in ticks) before this entity can use a portal. + pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(cooldown); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPortalCooldown", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the entity that is currently leading this entity. - pub fn leash_holder(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); + /// Returns a set of tags for this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn scoreboard_tags( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getScoreboardTags", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the leash on this entity to be held by the supplied entity. + /// Add a tag to this entity. /// - /// This method has no effect on EnderDragons, Withers, Players, or Bats. - /// Non-living entities excluding leashes will not persist as leash - /// holders. - pub fn set_leash_holder( + /// Entities can have no more than 1024 tags. + pub fn add_scoreboard_tag( &self, - holder: impl Into>, + tag: impl Into, ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(holder.into().jni_object().clone()) - }); + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setLeashHolder", + "addScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Checks to see if an entity is gliding, such as using an Elytra. - pub fn is_gliding(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Makes entity start or stop gliding. This will work even if an Elytra - /// is not equipped, but will be reverted by the server immediately after - /// unless an event-cancelling mechanism is put in place. - pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gliding.into()); + /// Removes a given tag from this entity. + pub fn remove_scoreboard_tag( + &self, + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setGliding", + "removeScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks to see if an entity is swimming. - pub fn is_swimming(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Makes entity start or stop swimming. - /// This may have unexpected results if the entity is not in water. - pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(swimming.into()); + /// Returns the reaction of the entity when moved by a piston. + pub fn piston_move_reaction( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setSwimming", + "getPistonMoveReaction", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks to see if an entity is currently using the Riptide enchantment. - pub fn is_riptiding(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns whether this entity is slumbering. - pub fn is_sleeping(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); + /// Get the closest cardinal {@link BlockFace} direction an entity is + /// currently facing. + /// + /// This will not return any non-cardinal directions such as + /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// + /// {@link Hanging} entities will override this call and thus their behavior + /// may be different. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets if the entity is climbing. - pub fn is_climbing(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); + /// Gets the entity's current pose. + /// Note that the pose is only updated at the end of a tick, so may be + /// inconsistent with other methods. eg {@link Player#isSneaking()} being + /// true does not imply the current pose will be {@link Pose#SNEAKING} + pub fn pose(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Pose;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets whether an entity will have AI. - /// The entity will be completely unable to move if it has no AI. - pub fn set_ai(&self, ai: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(ai.into()); + /// Get the category of spawn to which this entity belongs. + pub fn spawn_category( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setAI", + "getSpawnCategory", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Checks whether an entity has AI. - /// The entity will be completely unable to move if it has no AI. - pub fn has_ai(&self) -> Result> { + /// Checks if this entity has been spawned in a world. + /// + /// Entities not spawned in a world will not tick, be sent to players, or be + /// saved to the server files. + pub fn is_in_world(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Makes this entity attack the given entity with a melee attack. - /// Attack damage is calculated by the server from the attributes and - /// equipment of this mob, and knockback is applied to {@code target} as - /// appropriate. - pub fn attack( - &self, - target: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "attack", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Makes this entity swing their main hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their main hand. - pub fn swing_main_hand(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Get this entity as an NBT string. + /// + /// This string should not be relied upon as a serializable value. + pub fn as_string(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Makes this entity swing their off hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their off hand. - pub fn swing_off_hand(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Crates an {@link EntitySnapshot} representing the current state of this entity. + pub fn create_snapshot( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Makes this entity flash red as if they were damaged. - pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); - let res = self.jni_ref().call_method( - &self.jni_object(), - "playHurtAnimation", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntitySnapshot::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Set if this entity will be subject to collisions with other entities. - /// - /// Exemptions to this rule can be managed with - /// {@link #getCollidableExemptions()} - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not working for player collisions. This - /// method should therefore only be used to set the collision status of - /// non-player entities. + /// Creates a copy of this entity and all its data. Spawns the copy at the given location. /// - /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in - /// combination with a {@link Scoreboard} and a {@link Team}. - pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(collidable.into()); + /// Note: Players cannot be copied. + pub fn copy( + &self, + to: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = to { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Lorg/bukkit/entity/Entity;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets a metadata value in the implementing object's metadata store. + pub fn set_metadata( + &self, + metadata_key: impl Into, + new_metadata_value: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCollidable", + "setMetadata", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if this entity is subject to collisions with other entities. - /// - /// Some entities might be exempted from the collidable rule of this entity. - /// Use {@link #getCollidableExemptions()} to get these. - /// - /// Please note that this method returns only the custom collidable state, - /// not whether the entity is non-collidable for other reasons such as being - /// dead. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not being accurate for player collisions. - /// This method should therefore only be used to check the collision status - /// of non-player entities. - /// - /// To check the collision behavior for a player, use - /// {@link Team.Option#COLLISION_RULE} in combination with a - /// {@link Scoreboard} and a {@link Team}. - pub fn is_collidable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets a mutable set of UUIDs of the entities which are exempt from the - /// entity's collidable rule and which's collision with this entity will - /// behave the opposite of it. - /// - /// This set can be modified to add or remove exemptions. - /// - /// For example if collidable is true and an entity is in the exemptions set - /// then it will not collide with it. Similarly if collidable is false and an - /// entity is in this set then it will still collide with it. - /// - /// Note these exemptions are not (currently) persistent. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in those exemptions not being accurate for player - /// collisions. This method should therefore only be used to exempt - /// non-player entities. - /// - /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} - /// in combination with a {@link Scoreboard} and a {@link Team}. - pub fn collidable_exemptions( + /// Returns a list of previously set metadata values from the implementing + /// object's metadata store. + pub fn get_metadata( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + metadata_key: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "getCollidableExemptions", + "getMetadata", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::metadata::MetadataValue::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(new_vec) } - /// Returns the value of the memory specified. - /// - /// Note that the value is null when the specific entity does not have that - /// value by default. - pub fn get_memory( + /// Tests to see whether the implementing object contains the given + /// metadata value in its metadata store. + pub fn has_metadata( &self, - memory_key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) - }); + metadata_key: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "getMemory", + "hasMetadata", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(res.l()?)) + Ok(res.z()?) } - /// Sets the value of the memory specified. - /// - /// Note that the value will not be persisted when the specific entity does - /// not have that value by default. - pub fn set_memory( + /// Removes the given metadata value from the implementing object's + /// metadata store. + pub fn remove_metadata( &self, - memory_key: impl Into>, - memory_value: jni::objects::JObject<'mc>, + metadata_key: impl Into, + owning_plugin: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + let sig = String::from("(Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Object(memory_value); let res = self.jni_ref().call_method( &self.jni_object(), - "setMemory", + "removeMetadata", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), @@ -39309,274 +46626,288 @@ impl<'mc> HumanEntity<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the {@link Sound} this entity will make when damaged. - pub fn hurt_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + /// Sends this sender multiple messages + pub fn send_message( + &self, + sender: impl Into>, + messages: std::option::Option>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/util/UUID;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = messages { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_2); } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the {@link Sound} this entity will make on death. - pub fn death_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Gets the name of this command sender + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gets the custom name on a mob or block. If there is no name this method + /// will return null. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn custom_name(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCustomName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Get the {@link Sound} this entity will make when falling from the given - /// height (in blocks). The sound will often differ between either a small - /// or a big fall damage sound if the height exceeds 4 blocks. - pub fn get_fall_damage_sound( + /// Sets a custom name on a mob or block. This name will be used in death + /// messages and can be sent to the client as a nameplate over the mob. + /// + /// Setting the name to null or an empty string will clear it. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn set_custom_name( &self, - fall_height: i32, - ) -> Result, Box> { - let sig = String::from("(I)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Int(fall_height); + name: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSound", + "setCustomName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the {@link Sound} this entity will make when falling from a small - /// height. - pub fn fall_damage_sound_small(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + pub fn persistent_data_container( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSoundSmall", + "getPersistentDataContainer", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the {@link Sound} this entity will make when falling from a large - /// height. - pub fn fall_damage_sound_big(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for ExperienceOrb<'mc> { + fn into(self) -> crate::entity::Entity<'mc> { + crate::entity::Entity::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ExperienceOrb into crate::entity::Entity") + } +} +#[repr(C)] +pub struct PiglinAbstract<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PiglinAbstract<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PiglinAbstract<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate PiglinAbstract from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/PiglinAbstract")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PiglinAbstract object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> PiglinAbstract<'mc> { + /// Gets whether the piglin is immune to zombification. + pub fn is_immune_to_zombification(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSoundBig", + "isImmuneToZombification", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity will make when drinking the given - /// {@link ItemStack}. - pub fn get_drinking_sound( - &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getDrinkingSound", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Get the {@link Sound} this entity will make when eating the given - /// {@link ItemStack}. - pub fn get_eating_sound( + /// Sets whether the piglin is immune to zombification. + pub fn set_immune_to_zombification( &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) - }); + flag: bool, + ) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getEatingSound", + "setImmuneToZombification", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns true if this entity can breathe underwater and will not take - /// suffocation damage when its air supply reaches zero. - pub fn can_breathe_underwater(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the amount of ticks until this entity will be converted to a + /// Zombified Piglin. + /// When this reaches 300, the entity will be converted. + pub fn conversion_time(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "canBreatheUnderwater", + "getConversionTime", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. - pub fn category( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Sets whether the entity is invisible or not. - pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(invisible.into()); + /// Sets the amount of ticks until this entity will be converted to a + /// Zombified Piglin. + /// When this reaches 0, the entity will be converted. A value of less than 0 + /// will stop the current conversion process without converting the current + /// entity. + pub fn set_conversion_time(&self, time: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(time); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvisible", + "setConversionTime", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invisible or not. - pub fn is_invisible(&self) -> Result> { + /// Get if this entity is in the process of converting to a Zombified Piglin. + pub fn is_converting(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isConverting", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the specified attribute instance from the object. This instance will - /// be backed directly to the object and any changes will be visible at once. - pub fn get_attribute( - &self, - attribute: impl Into>, - ) -> Result>, Box> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAttribute", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + #[deprecated] + /// Gets whether the piglin is a baby + pub fn is_baby(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isBaby", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::attribute::AttributeInstance::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Deals the given amount of damage to this entity from a specified - /// {@link DamageSource}. - pub fn damage( + #[deprecated] + /// Sets whether the piglin is a baby + pub fn set_baby( &self, - amount: f64, - damage_source: std::option::Option>>, + flag: std::option::Option, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(amount); - args.push(val_1); - if let Some(a) = damage_source { - sig += "Lorg/bukkit/damage/DamageSource;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); + if let Some(a) = flag { + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_1); } sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "damage", sig.as_str(), args); + .call_method(&self.jni_object(), "setBaby", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. - pub fn health(&self) -> Result> { - let sig = String::from("()D"); + /// Gets the age of this mob. + pub fn age(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAge", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.i()?) } - /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is - /// dead. - pub fn set_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); + /// Sets the age of this mob. + pub fn set_age(&self, age: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(age); let res = self.jni_ref().call_method( &self.jni_object(), - "setHealth", + "setAge", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the entity's absorption amount. - pub fn absorption_amount(&self) -> Result> { - let sig = String::from("()D"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAbsorptionAmount", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Sets the entity's absorption amount. - /// - /// Note: The amount is capped to the value of - /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on - /// that attribute is currently unspecified and subject to change. - pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(amount); + #[deprecated] + /// Lock the age of the animal, setting this will prevent the animal from maturing or getting ready for mating. + pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(lock.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setAbsorptionAmount", + "setAgeLock", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -39584,159 +46915,56 @@ impl<'mc> HumanEntity<'mc> { Ok(()) } #[deprecated] - /// Gets the maximum health this entity has. - pub fn max_health(&self) -> Result> { - let sig = String::from("()D"); + /// Gets the current agelock. + pub fn age_lock(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - #[deprecated] - /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. - pub fn set_max_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaxHealth", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.z()?) } - #[deprecated] - /// Resets the max health to the original amount. - pub fn reset_max_health(&self) -> Result<(), Box> { + /// Sets the age of the mob to an adult + pub fn set_adult(&self) -> Result<(), Box> { let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setAdult", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Launches a {@link Projectile} from the ProjectileSource with an - /// initial velocity. - pub fn launch_projectile( - &self, - projectile: jni::objects::JClass<'mc>, - velocity: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/Class;"; - let val_1 = jni::objects::JValueGen::Object(projectile.into()); - args.push(val_1); - if let Some(a) = velocity { - sig += "Lorg/bukkit/util/Vector;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")LT;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); + /// Returns true if the mob is an adult. + pub fn is_adult(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isAdult", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) + Ok(res.z()?) } - /// This is the UUID of the specified AnimalTamer. - pub fn unique_id( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); + #[deprecated] + /// Return the ability to breed of the animal. + pub fn can_breed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for HumanEntity<'mc> { - fn into(self) -> crate::entity::LivingEntity<'mc> { - crate::entity::LivingEntity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting HumanEntity into crate::entity::LivingEntity") - } -} -impl<'mc> Into> for HumanEntity<'mc> { - fn into(self) -> crate::entity::AnimalTamer<'mc> { - crate::entity::AnimalTamer::from_raw(&self.jni_ref(), self.1) - .expect("Error converting HumanEntity into crate::entity::AnimalTamer") - } -} -impl<'mc> Into> for HumanEntity<'mc> { - fn into(self) -> crate::inventory::InventoryHolder<'mc> { - crate::inventory::InventoryHolder::from_raw(&self.jni_ref(), self.1) - .expect("Error converting HumanEntity into crate::inventory::InventoryHolder") - } -} -#[repr(C)] -pub struct EntityFactory<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for EntityFactory<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for EntityFactory<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate EntityFactory from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EntityFactory")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityFactory object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + Ok(res.z()?) } -} - -impl<'mc> EntityFactory<'mc> { - /// Create a new EntitySnapshot with the supplied input. - /// - /// Accepts strings in the format output by {@link EntitySnapshot#getAsString()}. - pub fn create_entity_snapshot( - &self, - input: impl Into, - ) -> Result, Box> { - let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/entity/EntitySnapshot;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(input.into())?, - )); + #[deprecated] + /// Set breedability of the animal, if the animal is a baby and set to breed it will instantly grow up. + pub fn set_breed(&self, breed: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(breed.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "createEntitySnapshot", + "setBreed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::entity::EntitySnapshot::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -39744,13 +46972,25 @@ impl<'mc> EntityFactory<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for PiglinAbstract<'mc> { + fn into(self) -> crate::entity::Monster<'mc> { + crate::entity::Monster::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PiglinAbstract into crate::entity::Monster") + } +} +impl<'mc> Into> for PiglinAbstract<'mc> { + fn into(self) -> crate::entity::Ageable<'mc> { + crate::entity::Ageable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PiglinAbstract into crate::entity::Ageable") + } +} #[repr(C)] -pub struct Shulker<'mc>( +pub struct Monster<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Shulker<'mc> { +impl<'mc> JNIRaw<'mc> for Monster<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -39758,18 +46998,18 @@ impl<'mc> JNIRaw<'mc> for Shulker<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Shulker<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Monster<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Shulker from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Monster from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Shulker")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Monster")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Shulker object, got {}", + "Invalid argument passed. Expected a Monster object, got {}", name ) .into()) @@ -39779,98 +47019,7 @@ impl<'mc> JNIInstantiatable<'mc> for Shulker<'mc> { } } -impl<'mc> Shulker<'mc> { - /// Gets the peek state of the shulker between 0.0 and 1.0. - pub fn peek(&self) -> Result> { - let sig = String::from("()F"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPeek", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Sets the peek state of the shulker, should be in between 0.0 and 1.0. - pub fn set_peek(&self, value: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(value); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPeek", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the face to which the shulker is attached. - pub fn attached_face( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAttachedFace", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the face to which the shulker is attached. - pub fn set_attached_face( - &self, - face: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAttachedFace", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the color of this object. - /// - /// This may be null to represent the default color of an object, if the - /// object has a special default color (e.g Shulkers). - pub fn color(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/DyeColor;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::DyeColor::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Sets the color of this object to the specified DyeColor. - /// - /// This may be null to represent the default color of an object, if the - /// object has a special default color (e.g Shulkers). - pub fn set_color( - &self, - color: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/DyeColor;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setColor", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } +impl<'mc> Monster<'mc> { /// Gets the height of the living entity's eyes above its Location. pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { let sig = String::from("(Z)D"); @@ -40628,7 +47777,7 @@ impl<'mc> Shulker<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks to see if an entity is currently using the Riptide enchantment. + /// Checks to see if an entity is currently riptiding. pub fn is_riptiding(&self) -> Result> { let sig = String::from("()Z"); let res = @@ -40637,6 +47786,21 @@ impl<'mc> Shulker<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } + /// Makes entity start or stop riptiding. + /// + /// Note: This does not damage attackable entities. + pub fn set_riptiding(&self, riptiding: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(riptiding.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRiptiding", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } /// Returns whether this entity is slumbering. pub fn is_sleeping(&self) -> Result> { let sig = String::from("()Z"); @@ -40969,508 +48133,264 @@ impl<'mc> Shulker<'mc> { } /// Get the {@link Sound} this entity will make when eating the given /// {@link ItemStack}. - pub fn get_eating_sound( - &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getEatingSound", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns true if this entity can breathe underwater and will not take - /// suffocation damage when its air supply reaches zero. - pub fn can_breathe_underwater(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "canBreatheUnderwater", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. - pub fn category( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets whether the entity is invisible or not. - pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(invisible.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setInvisible", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether the entity is invisible or not. - pub fn is_invisible(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the specified attribute instance from the object. This instance will - /// be backed directly to the object and any changes will be visible at once. - pub fn get_attribute( - &self, - attribute: impl Into>, - ) -> Result>, Box> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAttribute", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::attribute::AttributeInstance::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Deals the given amount of damage to this entity from a specified - /// {@link DamageSource}. - pub fn damage( - &self, - amount: f64, - damage_source: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(amount); - args.push(val_1); - if let Some(a) = damage_source { - sig += "Lorg/bukkit/damage/DamageSource;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "damage", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. - pub fn health(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is - /// dead. - pub fn set_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setHealth", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the entity's absorption amount. - pub fn absorption_amount(&self) -> Result> { - let sig = String::from("()D"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAbsorptionAmount", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Sets the entity's absorption amount. - /// - /// Note: The amount is capped to the value of - /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on - /// that attribute is currently unspecified and subject to change. - pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(amount); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAbsorptionAmount", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Gets the maximum health this entity has. - pub fn max_health(&self) -> Result> { - let sig = String::from("()D"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - #[deprecated] - /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. - pub fn set_max_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaxHealth", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Resets the max health to the original amount. - pub fn reset_max_health(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Launches a {@link Projectile} from the ProjectileSource with an - /// initial velocity. - pub fn launch_projectile( - &self, - projectile: jni::objects::JClass<'mc>, - velocity: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/Class;"; - let val_1 = jni::objects::JValueGen::Object(projectile.into()); - args.push(val_1); - if let Some(a) = velocity { - sig += "Lorg/bukkit/util/Vector;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")LT;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Shulker<'mc> { - fn into(self) -> crate::entity::Golem<'mc> { - crate::entity::Golem::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Shulker into crate::entity::Golem") - } -} -impl<'mc> Into> for Shulker<'mc> { - fn into(self) -> crate::material::Colorable<'mc> { - crate::material::Colorable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Shulker into crate::material::Colorable") - } -} -impl<'mc> Into> for Shulker<'mc> { - fn into(self) -> crate::entity::Enemy<'mc> { - crate::entity::Enemy::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Shulker into crate::entity::Enemy") - } -} -#[repr(C)] -pub struct PigZombie<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PigZombie<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PigZombie<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate PigZombie from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/PigZombie")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PigZombie object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> PigZombie<'mc> { - /// Get the pig zombie's current anger level. - pub fn anger(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getAnger", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the pig zombie's current anger level. - pub fn set_anger(&self, level: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(level); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAnger", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Shorthand; sets to either 0 or the default level. - pub fn set_angry(&self, angry: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(angry.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAngry", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Shorthand; gets whether the zombie is angry. - pub fn is_angry(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isAngry", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Not applicable to this entity - pub fn is_converting(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isConverting", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Not applicable to this entity - pub fn conversion_time(&self) -> Result> { - let sig = String::from("()I"); + pub fn get_eating_sound( + &self, + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getConversionTime", + "getEatingSound", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Not applicable to this entity - pub fn set_conversion_time(&self, time: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(time); + /// Returns true if this entity can breathe underwater and will not take + /// suffocation damage when its air supply reaches zero. + pub fn can_breathe_underwater(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "setConversionTime", + "canBreatheUnderwater", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Gets whether the zombie is a baby - pub fn is_baby(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isBaby", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } #[deprecated] - /// Sets whether the zombie is a baby - pub fn set_baby(&self, flag: bool) -> Result<(), Box> { + /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. + pub fn category( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets whether the entity is invisible or not. + pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(invisible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setBaby", + "setInvisible", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets whether the zombie is a villager - pub fn is_villager(&self) -> Result> { + /// Gets whether the entity is invisible or not. + pub fn is_invisible(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isVillager", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - - pub fn set_villager(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Gets the specified attribute instance from the object. This instance will + /// be backed directly to the object and any changes will be visible at once. + pub fn get_attribute( + &self, + attribute: impl Into>, + ) -> Result>, Box> { + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVillager", + "getAttribute", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::attribute::AttributeInstance::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - #[deprecated] - - pub fn set_villager_profession( + /// Deals the given amount of damage to this entity from a specified + /// {@link DamageSource}. + pub fn damage( &self, - profession: impl Into>, + amount: f64, + damage_source: std::option::Option>>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Villager/Profession;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(profession.into().jni_object().clone()) - }); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(amount); + args.push(val_1); + if let Some(a) = damage_source { + sig += "Lorg/bukkit/damage/DamageSource;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "damage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. + pub fn health(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is + /// dead. + pub fn set_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "setVillagerProfession", + "setHealth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - - pub fn villager_profession( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Villager/Profession;"); + /// Gets the entity's absorption amount. + pub fn absorption_amount(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref().call_method( &self.jni_object(), - "getVillagerProfession", + "getAbsorptionAmount", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::VillagerProfession::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.d()?) } - /// Gets whether this zombie can break doors - pub fn can_break_doors(&self) -> Result> { - let sig = String::from("()Z"); + /// Sets the entity's absorption amount. + /// + /// Note: The amount is capped to the value of + /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on + /// that attribute is currently unspecified and subject to change. + pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(amount); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAbsorptionAmount", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the maximum health this entity has. + pub fn max_health(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "canBreakDoors", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Sets whether this zombie can break doors - /// This will be ignored if the entity is a Drowned. Will also stop the action if - /// the entity is currently breaking a door. - pub fn set_can_break_doors(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + #[deprecated] + /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. + pub fn set_max_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "setCanBreakDoors", + "setMaxHealth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } + #[deprecated] + /// Resets the max health to the original amount. + pub fn reset_max_health(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Launches a {@link Projectile} from the ProjectileSource with an + /// initial velocity. + pub fn launch_projectile( + &self, + projectile: jni::objects::JClass<'mc>, + velocity: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(projectile.into()); + args.push(val_1); + if let Some(a) = velocity { + sig += "Lorg/bukkit/util/Vector;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")LT;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) + } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PigZombie<'mc> { - fn into(self) -> crate::entity::Zombie<'mc> { - crate::entity::Zombie::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PigZombie into crate::entity::Zombie") +impl<'mc> Into> for Monster<'mc> { + fn into(self) -> crate::entity::Creature<'mc> { + crate::entity::Creature::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Monster into crate::entity::Creature") + } +} +impl<'mc> Into> for Monster<'mc> { + fn into(self) -> crate::entity::Enemy<'mc> { + crate::entity::Enemy::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Monster into crate::entity::Enemy") } } #[repr(C)] -pub struct Arrow<'mc>( +pub struct MushroomCow<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Arrow<'mc> { +impl<'mc> JNIRaw<'mc> for MushroomCow<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -41478,18 +48398,18 @@ impl<'mc> JNIRaw<'mc> for Arrow<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Arrow<'mc> { +impl<'mc> JNIInstantiatable<'mc> for MushroomCow<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Arrow from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate MushroomCow from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Arrow")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/MushroomCow")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Arrow object, got {}", + "Invalid argument passed. Expected a MushroomCow object, got {}", name ) .into()) @@ -41499,123 +48419,14 @@ impl<'mc> JNIInstantiatable<'mc> for Arrow<'mc> { } } -impl<'mc> Arrow<'mc> { - #[deprecated] - /// Sets the underlying potion data - pub fn set_base_potion_data( - &self, - data: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/potion/PotionData;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setBasePotionData", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Returns the potion data about the base potion - pub fn base_potion_data( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/potion/PotionData;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getBasePotionData", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::potion::PotionData::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Sets the underlying potion type - pub fn set_base_potion_type( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/potion/PotionType;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setBasePotionType", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns the potion type about the base potion - pub fn base_potion_type( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/potion/PotionType;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getBasePotionType", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::potion::PotionType::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Gets the color of this arrow. - pub fn color(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Color;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Color::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Sets the color of this arrow. Will be applied as a tint to its particles. - pub fn set_color( - &self, - color: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Color;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setColor", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks for the presence of custom potion effects. - pub fn has_custom_effects(&self) -> Result> { +impl<'mc> MushroomCow<'mc> { + /// Checks for the presence of custom potion effects to be applied to the + /// next suspicious stew received from milking this {@link MushroomCow}. + pub fn has_effects_for_next_stew(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasCustomEffects", + "hasEffectsForNextStew", sig.as_str(), vec![], ); @@ -41623,17 +48434,17 @@ impl<'mc> Arrow<'mc> { Ok(res.z()?) } /// Gets an immutable list containing all custom potion effects applied to - /// this arrow. + /// the next suspicious stew received from milking this {@link MushroomCow}. /// /// Plugins should check that hasCustomEffects() returns true before calling /// this method. - pub fn custom_effects( + pub fn effects_for_next_stew( &self, ) -> Result>, Box> { let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCustomEffects", + "getEffectsForNextStew", sig.as_str(), vec![], ); @@ -41647,8 +48458,9 @@ impl<'mc> Arrow<'mc> { } Ok(new_vec) } - /// Adds a custom potion effect to this arrow. - pub fn add_custom_effect( + /// Adds a custom potion effect to be applied to the next suspicious stew + /// received from milking this {@link MushroomCow}. + pub fn add_effect_to_next_stew( &self, effect: impl Into>, overwrite: bool, @@ -41660,7 +48472,7 @@ impl<'mc> Arrow<'mc> { let val_2 = jni::objects::JValueGen::Bool(overwrite.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "addCustomEffect", + "addEffectToNextStew", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), @@ -41669,346 +48481,262 @@ impl<'mc> Arrow<'mc> { ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) - } - /// Removes a custom potion effect from this arrow. - pub fn remove_custom_effect( - &self, - val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removeCustomEffect", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Checks for a specific custom potion effect type on this arrow. - pub fn has_custom_effect( - &self, - val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasCustomEffect", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Removes all custom potion effects from this arrow. - pub fn clear_custom_effects(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "clearCustomEffects", - sig.as_str(), - vec![], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the knockback strength for an arrow, which is the - /// {@link org.bukkit.enchantments.Enchantment#KNOCKBACK KnockBack} level - /// of the bow that shot it. - pub fn knockback_strength(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getKnockbackStrength", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the knockback strength for an arrow. - pub fn set_knockback_strength( - &self, - knockback_strength: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(knockback_strength); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setKnockbackStrength", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the base amount of damage this arrow will do. - /// Defaults to 2.0 for a normal arrow with - /// 0.5 * (1 + power level) added for arrows fired from - /// enchanted bows. - pub fn damage(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getDamage", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Sets the base amount of damage this arrow will do. - pub fn set_damage(&self, damage: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(damage); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setDamage", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the number of times this arrow can pierce through an entity. - pub fn pierce_level(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPierceLevel", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the number of times this arrow can pierce through an entity. - /// Must be between 0 and 127 times. - pub fn set_pierce_level(&self, pierce_level: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(pierce_level); + } + /// Removes a custom potion effect from being applied to the next suspicious + /// stew received from milking this {@link MushroomCow}. + pub fn remove_effect_from_next_stew( + &self, + val_type: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPierceLevel", + "removeEffectFromNextStew", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether this arrow is critical. - /// - /// Critical arrows have increased damage and cause particle effects. - /// - /// Critical arrows generally occur when a player fully draws a bow before - /// firing. - pub fn is_critical(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCritical", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not this arrow should be critical. - pub fn set_critical(&self, critical: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(critical.into()); + /// Checks for a specific custom potion effect type to be applied to the next + /// suspicious stew received from milking this {@link MushroomCow}. + pub fn has_effect_for_next_stew( + &self, + val_type: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCritical", + "hasEffectForNextStew", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether this arrow is in a block or not. - /// - /// Arrows in a block are motionless and may be picked up by players. - pub fn is_in_block(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInBlock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the block to which this arrow is attached. - pub fn attached_block( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); + /// Removes all custom potion effects to be applied to the next suspicious + /// stew received from milking this {@link MushroomCow}. + pub fn clear_effects_for_next_stew(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref().call_method( &self.jni_object(), - "getAttachedBlock", + "clearEffectsForNextStew", sig.as_str(), vec![], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::block::Block::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the current pickup status of this arrow. - pub fn pickup_status( + /// Get the variant of this cow. + pub fn variant( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/AbstractArrow/PickupStatus;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/MushroomCow/Variant;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPickupStatus", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::AbstractArrowPickupStatus::from_raw(&self.jni_ref(), unsafe { + crate::entity::MushroomCowVariant::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the current pickup status of this arrow. - pub fn set_pickup_status( + /// Set the variant of this cow. + pub fn set_variant( &self, - status: impl Into>, + variant: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/AbstractArrow/PickupStatus;)V"); + let sig = String::from("(Lorg/bukkit/entity/MushroomCow/Variant;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(status.into().jni_object().clone()) + jni::objects::JObject::from_raw(variant.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPickupStatus", + "setVariant", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if this arrow was shot from a crossbow. - pub fn is_shot_from_crossbow(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isShotFromCrossbow", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Sets if this arrow was shot from a crossbow. - pub fn set_shot_from_crossbow( - &self, - shot_from_crossbow: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(shot_from_crossbow.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setShotFromCrossbow", - sig.as_str(), +} +impl<'mc> Into> for MushroomCow<'mc> { + fn into(self) -> crate::entity::Cow<'mc> { + crate::entity::Cow::from_raw(&self.jni_ref(), self.1) + .expect("Error converting MushroomCow into crate::entity::Cow") + } +} +pub enum MushroomCowVariant<'mc> { + Red { + inner: MushroomCowVariantStruct<'mc>, + }, + Brown { + inner: MushroomCowVariantStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for MushroomCowVariant<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + MushroomCowVariant::Red { .. } => f.write_str("RED"), + MushroomCowVariant::Brown { .. } => f.write_str("BROWN"), + } + } +} +impl<'mc> std::ops::Deref for MushroomCowVariant<'mc> { + type Target = MushroomCowVariantStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + MushroomCowVariant::Red { inner } => inner, + MushroomCowVariant::Brown { inner } => inner, + } + } +} + +impl<'mc> MushroomCowVariant<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/MushroomCow/Variant"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/MushroomCow/Variant;", vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "RED" => Ok(MushroomCowVariant::Red { + inner: MushroomCowVariantStruct::from_raw(env, obj)?, + }), + "BROWN" => Ok(MushroomCowVariant::Brown { + inner: MushroomCowVariantStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } - /// Gets the ItemStack which will be picked up from this arrow. - pub fn item(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/inventory/ItemStack;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} + +#[repr(C)] +pub struct MushroomCowVariantStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for MushroomCowVariant<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Red { inner } => inner.0.clone(), + Self::Brown { inner } => inner.0.clone(), + } } - /// Sets the ItemStack which will be picked up from this arrow. - pub fn set_item( - &self, - item: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setItem", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Red { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Brown { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } - /// Retrieve the shooter of this projectile. - pub fn shooter( - &self, - ) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/projectiles/ProjectileSource;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getShooter", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); +} +impl<'mc> JNIInstantiatable<'mc> for MushroomCowVariant<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate MushroomCowVariant from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/MushroomCow/Variant")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a MushroomCowVariant object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "RED" => Ok(MushroomCowVariant::Red { + inner: MushroomCowVariantStruct::from_raw(env, obj)?, + }), + "BROWN" => Ok(MushroomCowVariant::Brown { + inner: MushroomCowVariantStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } - Ok(Some(crate::projectiles::ProjectileSource::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) } - /// Set the shooter of this projectile. - pub fn set_shooter( - &self, - source: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/projectiles/ProjectileSource;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(source.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setShooter", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) +} + +impl<'mc> JNIRaw<'mc> for MushroomCowVariantStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - #[deprecated] - /// Determine if this projectile should bounce or not when it hits. - pub fn does_bounce(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "doesBounce", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - #[deprecated] - /// Set whether or not this projectile should bounce or not when it hits something. - pub fn set_bounce(&self, does_bounce: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(does_bounce.into()); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setBounce", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) +} +impl<'mc> JNIInstantiatable<'mc> for MushroomCowVariantStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate MushroomCowVariantStruct from null object." + ) + .into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/MushroomCow/Variant")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a MushroomCowVariantStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> MushroomCowVariantStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/MushroomCow/Variant;"); + let cls = jni.find_class("org/bukkit/entity/MushroomCow/Variant"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::MushroomCowVariant::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -42016,19 +48744,13 @@ impl<'mc> Arrow<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Arrow<'mc> { - fn into(self) -> crate::entity::AbstractArrow<'mc> { - crate::entity::AbstractArrow::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Arrow into crate::entity::AbstractArrow") - } -} #[repr(C)] -pub struct Cod<'mc>( +pub struct CaveSpider<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Cod<'mc> { +impl<'mc> JNIRaw<'mc> for CaveSpider<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -42036,18 +48758,18 @@ impl<'mc> JNIRaw<'mc> for Cod<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Cod<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CaveSpider<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Cod from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate CaveSpider from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Cod")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/CaveSpider")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Cod object, got {}", + "Invalid argument passed. Expected a CaveSpider object, got {}", name ) .into()) @@ -42057,25 +48779,25 @@ impl<'mc> JNIInstantiatable<'mc> for Cod<'mc> { } } -impl<'mc> Cod<'mc> { +impl<'mc> CaveSpider<'mc> { pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Cod<'mc> { - fn into(self) -> crate::entity::Fish<'mc> { - crate::entity::Fish::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Cod into crate::entity::Fish") +impl<'mc> Into> for CaveSpider<'mc> { + fn into(self) -> crate::entity::Spider<'mc> { + crate::entity::Spider::from_raw(&self.jni_ref(), self.1) + .expect("Error converting CaveSpider into crate::entity::Spider") } } #[repr(C)] -pub struct LlamaSpit<'mc>( +pub struct Hanging<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for LlamaSpit<'mc> { +impl<'mc> JNIRaw<'mc> for Hanging<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -42083,18 +48805,18 @@ impl<'mc> JNIRaw<'mc> for LlamaSpit<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for LlamaSpit<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Hanging<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate LlamaSpit from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Hanging from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/LlamaSpit")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Hanging")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a LlamaSpit object, got {}", + "Invalid argument passed. Expected a Hanging object, got {}", name ) .into()) @@ -42102,1294 +48824,1385 @@ impl<'mc> JNIInstantiatable<'mc> for LlamaSpit<'mc> { Ok(Self(env.clone(), obj)) } } -} - -impl<'mc> LlamaSpit<'mc> { - /// Retrieve the shooter of this projectile. - pub fn shooter( - &self, - ) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/projectiles/ProjectileSource;"; +} + +impl<'mc> Hanging<'mc> { + /// Sets the direction of the hanging entity, potentially overriding rules + /// of placement. Note that if the result is not valid the object would + /// normally drop as an item. + pub fn set_facing_direction( + &self, + face: impl Into>, + force: bool, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;Z)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Bool(force.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFacingDirection", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Stores the entity's current position in the provided Location object. + /// + /// If the provided Location is null this method does nothing and returns + /// null. + pub fn get_location( + &self, + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLocation", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Sets this entity's velocity in meters per tick + pub fn set_velocity( + &self, + velocity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVelocity", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets this entity's current velocity + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the entity's height + pub fn height(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the entity's width + pub fn width(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the entity's current bounding box. + /// + /// The returned bounding box reflects the entity's current location and + /// size. + pub fn bounding_box( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns true if the entity is supported by a block. This value is a + /// state updated by the server and is not recalculated unless the entity + /// moves. + pub fn is_on_ground(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns true if the entity is in water. + pub fn is_in_water(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the current world this entity resides in + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getShooter", sig.as_str(), args); + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::projectiles::ProjectileSource::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the shooter of this projectile. - pub fn set_shooter( + /// Sets the entity's rotation. + /// + /// Note that if the entity is affected by AI, it may override this rotation. + pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { + let sig = String::from("(FF)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); + let val_2 = jni::objects::JValueGen::Float(pitch); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRotation", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Teleports this entity to the given location. If this entity is riding a + /// vehicle, it will be dismounted prior to teleportation. + pub fn teleport( &self, - source: impl Into>, - ) -> Result<(), Box> { + location: impl Into>, + cause: std::option::Option< + impl Into>, + >, + ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/projectiles/ProjectileSource;"; + sig += "Lorg/bukkit/Location;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(source.into().jni_object().clone()) + jni::objects::JObject::from_raw(location.into().jni_object().clone()) }); args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setShooter", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Determine if this projectile should bounce or not when it hits. - pub fn does_bounce(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); + if let Some(a) = cause { + sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "doesBounce", sig.as_str(), args); + .call_method(&self.jni_object(), "teleport", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Set whether or not this projectile should bounce or not when it hits something. - pub fn set_bounce(&self, does_bounce: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(does_bounce.into()); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setBounce", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for LlamaSpit<'mc> { - fn into(self) -> crate::entity::Projectile<'mc> { - crate::entity::Projectile::from_raw(&self.jni_ref(), self.1) - .expect("Error converting LlamaSpit into crate::entity::Projectile") - } -} -#[repr(C)] -pub struct WanderingTrader<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for WanderingTrader<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Returns a list of entities within a bounding box centered around this + /// entity + pub fn get_nearby_entities( + &self, + x: f64, + y: f64, + z: f64, + ) -> Result>, Box> { + let sig = String::from("(DDD)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Double(x); + let val_2 = jni::objects::JValueGen::Double(y); + let val_3 = jni::objects::JValueGen::Double(z); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNearbyEntities", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Returns a unique id for this entity + pub fn entity_id(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} -impl<'mc> JNIInstantiatable<'mc> for WanderingTrader<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate WanderingTrader from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/WanderingTrader")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a WanderingTrader object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Returns the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} - -impl<'mc> WanderingTrader<'mc> { - /// Gets the despawn delay before this {@link WanderingTrader} is forcibly - /// despawned. - /// If this is less than or equal to 0, then the trader will not be - /// despawned. - pub fn despawn_delay(&self) -> Result> { + /// Returns the entity's maximum fire ticks. + pub fn max_fire_ticks(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDespawnDelay", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the despawn delay before this {@link WanderingTrader} is forcibly - /// despawned. - /// If this is less than or equal to 0, then the trader will not be - /// despawned. - pub fn set_despawn_delay(&self, despawn_delay: i32) -> Result<(), Box> { + /// Sets the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(despawn_delay); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setDespawnDelay", + "setFireTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets this villager's inventory. - /// - /// Note that this inventory is not the Merchant inventory, rather, it is the - /// items that a villager might have collected (from harvesting crops, etc.) - /// {@inheritDoc} - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Lock the age of the animal, setting this will prevent the animal from - /// maturing or getting ready for mating. - pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { + /// Sets if the entity has visual fire (it will always appear to be on fire). + pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(lock.into()); + let val_1 = jni::objects::JValueGen::Bool(fire.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setAgeLock", + "setVisualFire", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the current agelock. - pub fn age_lock(&self) -> Result> { + /// Gets if the entity has visual fire (it will always appear to be on fire). + pub fn is_visual_fire(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Return the ability to breed of the animal. - pub fn can_breed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); + /// Returns the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Set breedability of the animal, if the animal is a baby and set to - /// breed it will instantly grow up. - pub fn set_breed(&self, breed: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(breed.into()); + /// Returns the entity's maximum freeze ticks (amount of ticks before it will + /// be fully frozen) + pub fn max_freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreed", + "getMaxFreezeTicks", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get a list of trades currently available from this merchant. - pub fn recipes( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRecipes", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::inventory::MerchantRecipe::from_raw( - &self.jni_ref(), - obj, - )?); - } - Ok(new_vec) + Ok(res.i()?) } - /// Set the list of trades currently available from this merchant. - /// - /// This will not change the selected trades of players currently trading - /// with this merchant. - pub fn set_recipes( - &self, - recipes: Vec>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/List;)V"); - let raw_val_1 = self - .jni_ref() - .new_object("java/util/ArrayList", "()V", vec![])?; - for v in recipes { - let map_val_0 = jni::objects::JValueGen::Object(v); - self.jni_ref().call_method( - &raw_val_1, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_1 = jni::objects::JValueGen::Object(raw_val_1); + /// Sets the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setRecipes", + "setFreezeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the recipe at a certain index of this merchant's trade list. - pub fn get_recipe( - &self, - i: i32, - ) -> Result, Box> { - let sig = String::from("(I)Lorg/bukkit/inventory/MerchantRecipe;"); - let val_1 = jni::objects::JValueGen::Int(i); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getRecipe", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Gets if the entity is fully frozen (it has been in powdered snow for max + /// freeze ticks). + pub fn is_frozen(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::MerchantRecipe::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Set the recipe at a certain index of this merchant's trade list. - pub fn set_recipe( - &self, - i: i32, - recipe: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(ILorg/bukkit/inventory/MerchantRecipe;)V"); - let val_1 = jni::objects::JValueGen::Int(i); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRecipe", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + /// Mark the entity's removal. + pub fn remove(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the number of trades this merchant currently has available. - pub fn recipe_count(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRecipeCount", sig.as_str(), vec![]); + /// Returns true if this entity has been marked for removal. + pub fn is_dead(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Gets whether this merchant is currently trading. - pub fn is_trading(&self) -> Result> { + /// Returns false if the entity has died, been despawned for some other + /// reason, or has not been added to the world. + pub fn is_valid(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isTrading", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the player this merchant is trading with, or null if it is not - /// currently trading. - pub fn trader( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); + /// Gets the {@link Server} that contains this Entity + pub fn server(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Server;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getTrader", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Server::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns true if the entity gets persisted. + /// + /// By default all entities are persistent. An entity will also not get + /// persisted, if it is riding an entity that is not persistent. + /// + /// The persistent flag on players controls whether or not to save their + /// playerdata file when they quit. If a player is directly or indirectly + /// riding a non-persistent entity, the vehicle at the root and all its + /// passengers won't get persisted. + /// + /// This should not be confused with + /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls + /// despawning of living entities. + pub fn is_persistent(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether or not the entity gets persisted. + pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(persistent.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPersistent", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. + pub fn passenger( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::HumanEntity::from_raw( + Ok(Some(crate::entity::Entity::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for WanderingTrader<'mc> { - fn into(self) -> crate::entity::AbstractVillager<'mc> { - crate::entity::AbstractVillager::from_raw(&self.jni_ref(), self.1) - .expect("Error converting WanderingTrader into crate::entity::AbstractVillager") - } -} -#[repr(C)] -pub struct SmallFireball<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for SmallFireball<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for SmallFireball<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate SmallFireball from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/SmallFireball")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a SmallFireball object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + #[deprecated] + /// Set the passenger of a vehicle. + pub fn set_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPassenger", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} - -impl<'mc> SmallFireball<'mc> { - /// Gets the display {@link ItemStack}. - pub fn display_item( + /// Gets a list of passengers of this vehicle. + /// + /// The returned list will not be directly linked to the entity's current + /// passengers, and no guarantees are made as to its mutability. + pub fn passengers( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDisplayItem", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Sets the display {@link ItemStack} for the fireball. - pub fn set_display_item( + /// Add a passenger to the vehicle. + pub fn add_passenger( &self, - item: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setDisplayItem", + "addPassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Sets the direction the fireball should be flying towards. - /// - /// This is a convenience method, it will change the velocity direction and - /// acceleration direction, while keeping the power the same. - /// - /// Note: This method only uses the direction of the vector and will - /// normalize (a copy of) it. - /// - /// Special Case: When the given direction is - /// {@link Vector#isZero() zero}, the velocity and acceleration will also be - /// set to zero without keeping the power. - pub fn set_direction( + /// Remove a passenger from the vehicle. + pub fn remove_passenger( &self, - direction: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(direction.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setDirection", + "removePassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - #[deprecated] - /// Retrieve the direction this fireball is heading toward. The returned vector is not normalized. - pub fn direction(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); + /// Check if a vehicle has passengers. + pub fn is_empty(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Eject any passenger. + pub fn eject(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the distance this entity has fallen + pub fn fall_distance(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.f()?) } - /// Sets the acceleration of the fireball. - /// The acceleration gets applied to the velocity every tick, depending on - /// the specific type of the fireball a damping / drag factor is applied so - /// that the velocity does not grow into infinity. - /// - /// Note: that the client may not respect non-default acceleration - /// power and will therefore mispredict the location of the fireball, causing - /// visual stutter. - pub fn set_acceleration( - &self, - acceleration: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(acceleration.into().jni_object().clone()) - }); + /// Sets the fall distance for this entity + pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setAcceleration", + "setFallDistance", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the acceleration of this fireball. - pub fn acceleration(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAcceleration", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for SmallFireball<'mc> { - fn into(self) -> crate::entity::SizedFireball<'mc> { - crate::entity::SizedFireball::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SmallFireball into crate::entity::SizedFireball") - } -} -#[repr(C)] -pub struct Illager<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Illager<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Illager<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Illager from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Illager")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Illager object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Illager<'mc> { - /// Set the {@link Raid} that this raider is participating in. - pub fn set_raid( + #[deprecated] + /// Record the last {@link EntityDamageEvent} inflicted on this entity + pub fn set_last_damage_cause( &self, - raid: impl Into>, + event: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Raid;)V"); + let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(raid.into().jni_object().clone()) + jni::objects::JObject::from_raw(event.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setRaid", + "setLastDamageCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the {@link Raid} that this raider is participating in, if any. - pub fn raid(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Raid;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getRaid", sig.as_str(), vec![]); + /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. + /// This event may have been cancelled. + pub fn last_damage_cause( + &self, + ) -> Result>, Box> + { + let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLastDamageCause", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Raid::from_raw(&self.jni_ref(), unsafe { + Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Returns a unique and persistent id for this entity + pub fn unique_id( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + }) } - /// Get the raid wave that this raider spawned as part of. - pub fn wave(&self) -> Result> { + /// Gets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. + pub fn ticks_lived(&self) -> Result> { let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWave", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Set the raid wave that this raider was spawned as part of. - pub fn set_wave(&self, wave: i32) -> Result<(), Box> { + /// Sets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. May not be less than one + /// tick. + pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(wave); + let val_1 = jni::objects::JValueGen::Int(value); let res = self.jni_ref().call_method( &self.jni_object(), - "setWave", + "setTicksLived", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the block the raider is targeting to patrol. - pub fn patrol_target( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPatrolTarget", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::block::Block::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Sets the block the raider is targeting to patrol. - pub fn set_patrol_target( + /// Performs the specified {@link EntityEffect} for this entity. + /// + /// This will be viewable to all players near the entity. + /// + /// If the effect is not applicable to this class of entity, it will not play. + pub fn play_effect( &self, - block: impl Into>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/Block;)V"); + let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPatrolTarget", + "playEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether this entity is a patrol leader. - pub fn is_patrol_leader(&self) -> Result> { - let sig = String::from("()Z"); + /// Get the type of the entity. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes while swimming. + pub fn swim_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isPatrolLeader", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets whether this entity is a patrol leader. - pub fn set_patrol_leader(&self, leader: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(leader.into()); + /// Get the {@link Sound} this entity makes when splashing in water. For most + /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_splash_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setPatrolLeader", + "getSwimSplashSound", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets whether this mob can join an active raid. - pub fn is_can_join_raid(&self) -> Result> { + /// Get the {@link Sound} this entity makes when splashing in water at high + /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_high_speed_splash_sound( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSwimHighSpeedSplashSound", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns whether this entity is inside a vehicle. + pub fn is_inside_vehicle(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCanJoinRaid", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether this mob can join an active raid. - pub fn set_can_join_raid(&self, join: bool) -> Result<(), Box> { + /// Leave the current vehicle. If the entity is currently in a vehicle (and + /// is removed from it), true will be returned, otherwise false will be + /// returned. + pub fn leave_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the vehicle that this entity is inside. If there is no vehicle, + /// null will be returned. + pub fn vehicle( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets whether or not to display the mob's custom name client side. The + /// name will be displayed above the mob similarly to a player. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(join.into()); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCanJoinRaid", + "setCustomNameVisible", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the amount of ticks that this mob has exited the bounds of a village - /// as a raid participant. + /// Gets whether or not the mob's custom name is displayed client side. /// - /// This value is increased only when the mob has had no action for 2,400 ticks - /// (according to {@link #getNoActionTicks()}). Once both the no action ticks have - /// reached that value and the ticks outside a raid exceeds 30, the mob will be - /// expelled from the raid. - pub fn ticks_outside_raid(&self) -> Result> { - let sig = String::from("()I"); + /// This value has no effect on players, they will always display their + /// name. + pub fn is_custom_name_visible(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getTicksOutsideRaid", + "isCustomNameVisible", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the amount of ticks that this mob has exited the bounds of a village - /// as a raid participant. - /// - /// This value is considered only when the mob has had no action for 2,400 ticks - /// (according to {@link #getNoActionTicks()}). Once both the no action ticks have - /// reached that value and the ticks outside a raid exceeds 30, the mob will be - /// expelled from the raid. - pub fn set_ticks_outside_raid(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(visible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setTicksOutsideRaid", + "setVisibleByDefault", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check whether or not this raider is celebrating a raid victory. - pub fn is_celebrating(&self) -> Result> { + /// Gets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn is_visible_by_default(&self) -> Result> { let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isVisibleByDefault", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get all players that are currently tracking this entity. + /// + /// 'Tracking' means that this entity has been sent to the player and that + /// they are receiving updates on its state. Note that the client's {@code + /// 'Entity Distance'} setting does not affect the range at which entities + /// are tracked. + pub fn tracked_by( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCelebrating", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set whether or not this mob is celebrating a raid victory. - pub fn set_celebrating(&self, celebrating: bool) -> Result<(), Box> { + /// Sets whether the entity has a team colored (default: white) glow. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(celebrating.into()); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCelebrating", + "setGlowing", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the {@link Sound} this entity will play when celebrating. - pub fn celebration_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCelebrationSound", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Illager<'mc> { - fn into(self) -> crate::entity::Raider<'mc> { - crate::entity::Raider::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Illager into crate::entity::Raider") - } -} -#[repr(C)] -pub struct Pig<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Pig<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + Ok(()) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets whether the entity is glowing or not. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn is_glowing(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for Pig<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Pig from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Pig")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Pig object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Sets whether the entity is invulnerable or not. + /// + /// When an entity is invulnerable it can only be damaged by players in + /// creative mode. + pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setInvulnerable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> Pig<'mc> { - /// Check if the pig has a saddle. - pub fn has_saddle(&self) -> Result> { + /// Gets whether the entity is invulnerable or not. + pub fn is_invulnerable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets whether the entity is silent or not. + pub fn is_silent(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "hasSaddle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets if the pig has a saddle or not - pub fn set_saddle(&self, saddled: bool) -> Result<(), Box> { + /// Sets whether the entity is silent or not. + /// + /// When an entity is silent it will not produce any sound. + pub fn set_silent(&self, flag: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(saddled.into()); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setSaddle", + "setSilent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the time in ticks this entity's movement is being increased. - /// Movement speed is often increased as a result of using the - /// {@link #getSteerMaterial()}. - pub fn boost_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Returns whether gravity applies to this entity. + pub fn has_gravity(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBoostTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the time in ticks this entity's movement will be increased. - /// This will reset the current boost ticks to 0 - /// ({@link #getCurrentBoostTicks()}). - pub fn set_boost_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets whether gravity applies to this entity. + pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gravity.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setBoostTicks", + "setGravity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the time in ticks this entity's movement has been increased as of the - /// most recent boost. - /// Current boost ticks will never be {@literal >} {@link #getBoostTicks()}. - pub fn current_boost_ticks(&self) -> Result> { + /// Gets the period of time (in ticks) before this entity can use a portal. + pub fn portal_cooldown(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCurrentBoostTicks", + "getPortalCooldown", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Set the time in ticks this entity's movement has been increased relative - /// to the most recent boost. - pub fn set_current_boost_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Sets the period of time (in ticks) before this entity can use a portal. + pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + let val_1 = jni::objects::JValueGen::Int(cooldown); let res = self.jni_ref().call_method( &self.jni_object(), - "setCurrentBoostTicks", + "setPortalCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the material used to steer this entity when ridden by a player. - pub fn steer_material(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); + /// Returns a set of tags for this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn scoreboard_tags( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getSteerMaterial", + "getScoreboardTags", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn breed_cause( + /// Add a tag to this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn add_scoreboard_tag( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addScoreboardTag", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Set the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn set_breed_cause( + /// Removes a given tag from this entity. + pub fn remove_scoreboard_tag( &self, - uuid: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/UUID;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) - }); + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreedCause", + "removeScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get whether or not this entity is in love mode and will produce - /// offspring with another entity in love mode. Will return true if - /// and only if {@link #getLoveModeTicks()} is greater than 0. - pub fn is_love_mode(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get the amount of ticks remaining for this entity in love mode. - /// If the entity is not in love mode, 0 will be returned. - pub fn love_mode_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Returns the reaction of the entity when moved by a piston. + pub fn piston_move_reaction( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLoveModeTicks", + "getPistonMoveReaction", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the amount of ticks for which this entity should be in love mode. - /// Setting the love mode ticks to 600 is the equivalent of a player - /// feeding the entity their breeding item of choice. - pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Get the closest cardinal {@link BlockFace} direction an entity is + /// currently facing. + /// + /// This will not return any non-cardinal directions such as + /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// + /// {@link Hanging} entities will override this call and thus their behavior + /// may be different. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the entity's current pose. + /// Note that the pose is only updated at the end of a tick, so may be + /// inconsistent with other methods. eg {@link Player#isSneaking()} being + /// true does not imply the current pose will be {@link Pose#SNEAKING} + pub fn pose(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Pose;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the category of spawn to which this entity belongs. + pub fn spawn_category( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setLoveModeTicks", + "getSpawnCategory", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Check if the provided ItemStack is the correct item used for breeding - /// this entity.. - pub fn is_breed_item( - &self, - material: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Z"; + /// Checks if this entity has been spawned in a world. + /// + /// Entities not spawned in a world will not tick, be sent to players, or be + /// saved to the server files. + pub fn is_in_world(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); + .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the vehicle's velocity. - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); + /// Get this entity as an NBT string. + /// + /// This string should not be relied upon as a serializable value. + pub fn as_string(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Crates an {@link EntitySnapshot} representing the current state of this entity. + pub fn create_snapshot( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntitySnapshot::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// + /// Note: Players cannot be copied. + pub fn copy( + &self, + to: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = to { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Lorg/bukkit/entity/Entity;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the vehicle's velocity in meters per tick. - pub fn set_velocity( + /// Sets a metadata value in the implementing object's metadata store. + pub fn set_metadata( &self, - vel: impl Into>, + metadata_key: impl Into, + new_metadata_value: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(vel.into().jni_object().clone()) + let sig = String::from("(Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVelocity", + "setMetadata", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Pig<'mc> { - fn into(self) -> crate::entity::Steerable<'mc> { - crate::entity::Steerable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Pig into crate::entity::Steerable") - } -} -impl<'mc> Into> for Pig<'mc> { - fn into(self) -> crate::entity::Vehicle<'mc> { - crate::entity::Vehicle::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Pig into crate::entity::Vehicle") - } -} -#[repr(C)] -pub struct WaterMob<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for WaterMob<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for WaterMob<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate WaterMob from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/WaterMob")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a WaterMob object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> WaterMob<'mc> { - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for WaterMob<'mc> { - fn into(self) -> crate::entity::Creature<'mc> { - crate::entity::Creature::from_raw(&self.jni_ref(), self.1) - .expect("Error converting WaterMob into crate::entity::Creature") - } -} -#[repr(C)] -pub struct Flying<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Flying<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Flying<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Flying from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Flying")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Flying object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + /// Returns a list of previously set metadata values from the implementing + /// object's metadata store. + pub fn get_metadata( + &self, + metadata_key: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMetadata", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::metadata::MetadataValue::from_raw( + &self.jni_ref(), + obj, + )?); } + Ok(new_vec) } -} - -impl<'mc> Flying<'mc> { - /// Instructs this Mob to set the specified LivingEntity as its target. - /// - /// Hostile creatures may attack their target, and friendly creatures may - /// follow their target. - pub fn set_target( + /// Tests to see whether the implementing object contains the given + /// metadata value in its metadata store. + pub fn has_metadata( + &self, + metadata_key: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasMetadata", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Removes the given metadata value from the implementing object's + /// metadata store. + pub fn remove_metadata( &self, - target: impl Into>, + metadata_key: impl Into, + owning_plugin: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) + let sig = String::from("(Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setTarget", + "removeMetadata", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the current target of this Mob - pub fn target( + /// Sends this sender multiple messages + pub fn send_message( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); + sender: impl Into>, + messages: std::option::Option>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/util/UUID;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = messages { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_2); + } + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getTarget", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::LivingEntity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Sets whether this mob is aware of its surroundings. - /// Unaware mobs will still move if pushed, attacked, etc. but will not move - /// or perform any actions on their own. Unaware mobs may also have other - /// unspecified behaviours disabled, such as drowning. - pub fn set_aware(&self, aware: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(aware.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAware", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether this mob is aware of its surroundings. - /// Unaware mobs will still move if pushed, attacked, etc. but will not move - /// or perform any actions on their own. Unaware mobs may also have other - /// unspecified behaviours disabled, such as drowning. - pub fn is_aware(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the name of this command sender + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isAware", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Get the {@link Sound} this mob makes while ambiently existing. This sound - /// may change depending on the current state of the entity, and may also - /// return null under specific conditions. This sound is not constant. - /// For instance, villagers will make different passive noises depending - /// on whether or not they are actively trading with a player, or make no - /// ambient noise while sleeping. - pub fn ambient_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Gets the custom name on a mob or block. If there is no name this method + /// will return null. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn custom_name(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAmbientSound", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCustomName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Flying<'mc> { - fn into(self) -> crate::entity::Mob<'mc> { - crate::entity::Mob::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Flying into crate::entity::Mob") - } -} -#[repr(C)] -pub struct IronGolem<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for IronGolem<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for IronGolem<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate IronGolem from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/IronGolem")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a IronGolem object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> IronGolem<'mc> { - /// Gets whether this iron golem was built by a player. - pub fn is_player_created(&self) -> Result> { - let sig = String::from("()Z"); - let res = + Ok(Some( self.jni_ref() - .call_method(&self.jni_object(), "isPlayerCreated", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Sets whether this iron golem was built by a player or not. - pub fn set_player_created( + /// Sets a custom name on a mob or block. This name will be used in death + /// messages and can be sent to the client as a nameplate over the mob. + /// + /// Setting the name to null or an empty string will clear it. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn set_custom_name( &self, - player_created: bool, + name: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(player_created.into()); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setPlayerCreated", + "setCustomName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + pub fn persistent_data_container( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPersistentDataContainer", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the face that this block is attached on + pub fn attached_face( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAttachedFace", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for IronGolem<'mc> { - fn into(self) -> crate::entity::Golem<'mc> { - crate::entity::Golem::from_raw(&self.jni_ref(), self.1) - .expect("Error converting IronGolem into crate::entity::Golem") +impl<'mc> Into> for Hanging<'mc> { + fn into(self) -> crate::entity::Entity<'mc> { + crate::entity::Entity::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Hanging into crate::entity::Entity") + } +} +impl<'mc> Into> for Hanging<'mc> { + fn into(self) -> crate::material::Attachable<'mc> { + crate::material::Attachable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Hanging into crate::material::Attachable") } } #[repr(C)] -pub struct TropicalFish<'mc>( +pub struct Ageable<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for TropicalFish<'mc> { +impl<'mc> JNIRaw<'mc> for Ageable<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -43397,18 +50210,18 @@ impl<'mc> JNIRaw<'mc> for TropicalFish<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for TropicalFish<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Ageable<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate TropicalFish from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Ageable from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/TropicalFish")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Ageable")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a TropicalFish object, got {}", + "Invalid argument passed. Expected a Ageable object, got {}", name ) .into()) @@ -43418,90 +50231,100 @@ impl<'mc> JNIInstantiatable<'mc> for TropicalFish<'mc> { } } -impl<'mc> TropicalFish<'mc> { - /// Gets the color of the fish's pattern. - pub fn pattern_color(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/DyeColor;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPatternColor", sig.as_str(), vec![]); +impl<'mc> Ageable<'mc> { + /// Gets the age of this mob. + pub fn age(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getAge", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::DyeColor::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Sets the color of the fish's pattern - pub fn set_pattern_color( - &self, - color: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/DyeColor;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) - }); + /// Sets the age of this mob. + pub fn set_age(&self, age: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(age); let res = self.jni_ref().call_method( &self.jni_object(), - "setPatternColor", + "setAge", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the color of the fish's body. - pub fn body_color(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/DyeColor;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBodyColor", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::DyeColor::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the color of the fish's body - pub fn set_body_color( - &self, - color: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/DyeColor;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) - }); + #[deprecated] + /// Lock the age of the animal, setting this will prevent the animal from maturing or getting ready for mating. + pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(lock.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setBodyColor", + "setAgeLock", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the fish's pattern. - pub fn pattern( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/TropicalFish/Pattern;"); + #[deprecated] + /// Gets the current agelock. + pub fn age_lock(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPattern", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::TropicalFishPattern::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets the fish's pattern - pub fn set_pattern( - &self, - pattern: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/TropicalFish/Pattern;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(pattern.into().jni_object().clone()) - }); + /// Sets the age of the mob to a baby + pub fn set_baby(&self) -> Result<(), Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setBaby", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets the age of the mob to an adult + pub fn set_adult(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setAdult", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns true if the mob is an adult. + pub fn is_adult(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isAdult", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Return the ability to breed of the animal. + pub fn can_breed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Set breedability of the animal, if the animal is a baby and set to breed it will instantly grow up. + pub fn set_breed(&self, breed: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(breed.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setPattern", + "setBreed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -43514,149 +50337,19 @@ impl<'mc> TropicalFish<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for TropicalFish<'mc> { - fn into(self) -> crate::entity::Fish<'mc> { - crate::entity::Fish::from_raw(&self.jni_ref(), self.1) - .expect("Error converting TropicalFish into crate::entity::Fish") - } -} -pub enum TropicalFishPattern<'mc> {} -impl<'mc> std::fmt::Display for TropicalFishPattern<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> TropicalFishPattern<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/TropicalFish/Pattern"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/TropicalFish/Pattern;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct TropicalFishPatternStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for TropicalFishPattern<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for TropicalFishPattern<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate TropicalFishPattern from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/TropicalFish/Pattern")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a TropicalFishPattern object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for TropicalFishPatternStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for TropicalFishPatternStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate TropicalFishPatternStruct from null object." - ) - .into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/TropicalFish/Pattern")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a TropicalFishPatternStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> TropicalFishPatternStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/TropicalFish/Pattern;"); - let cls = jni.find_class("org/bukkit/entity/TropicalFish/Pattern"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::TropicalFishPattern::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) +impl<'mc> Into> for Ageable<'mc> { + fn into(self) -> crate::entity::Creature<'mc> { + crate::entity::Creature::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Ageable into crate::entity::Creature") } } #[repr(C)] -pub struct Vindicator<'mc>( +pub struct Tameable<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Vindicator<'mc> { +impl<'mc> JNIRaw<'mc> for Tameable<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -43664,18 +50357,18 @@ impl<'mc> JNIRaw<'mc> for Vindicator<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Vindicator<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Tameable<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Vindicator from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Tameable from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Vindicator")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Tameable")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Vindicator object, got {}", + "Invalid argument passed. Expected a Tameable object, got {}", name ) .into()) @@ -43685,255 +50378,236 @@ impl<'mc> JNIInstantiatable<'mc> for Vindicator<'mc> { } } -impl<'mc> Vindicator<'mc> { - /// Returns whether a vindicator is in "Johnny" mode. - /// When this mode is active, vindicators will be hostile to all mobs. - pub fn is_johnny(&self) -> Result> { +impl<'mc> Tameable<'mc> { + /// Check if this is tamed + /// + /// If something is tamed then a player can not tame it through normal + /// methods, even if it does not belong to anyone in particular. + pub fn is_tamed(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isJohnny", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isTamed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the Johnny state of a vindicator. - pub fn set_johnny(&self, johnny: bool) -> Result<(), Box> { + /// Sets if this has been tamed. Not necessary if the method setOwner has + /// been used, as it tames automatically. + /// + /// If something is tamed then a player can not tame it through normal + /// methods, even if it does not belong to anyone in particular. + pub fn set_tamed(&self, tame: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(johnny.into()); + let val_1 = jni::objects::JValueGen::Bool(tame.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setJohnny", + "setTamed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Set the {@link Raid} that this raider is participating in. - pub fn set_raid( + /// Gets the current owning AnimalTamer + pub fn owner( &self, - raid: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Raid;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(raid.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRaid", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the {@link Raid} that this raider is participating in, if any. - pub fn raid(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Raid;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/AnimalTamer;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getRaid", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Raid::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Get the raid wave that this raider spawned as part of. - pub fn wave(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWave", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(Some(crate::entity::AnimalTamer::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Set the raid wave that this raider was spawned as part of. - pub fn set_wave(&self, wave: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(wave); + /// Set this to be owned by given AnimalTamer. + /// + /// If the owner is not null, this will be tamed and will have any current + /// path it is following removed. If the owner is set to null, this will be + /// untamed, and the current owner removed. + pub fn set_owner( + &self, + tamer: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/AnimalTamer;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(tamer.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setWave", + "setOwner", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the block the raider is targeting to patrol. - pub fn patrol_target( + /// Get the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn breed_cause( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/UUID;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPatrolTarget", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::block::Block::from_raw( + Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets the block the raider is targeting to patrol. - pub fn set_patrol_target( + /// Set the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn set_breed_cause( &self, - block: impl Into>, + uuid: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/Block;)V"); + let sig = String::from("(Ljava/util/UUID;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) + jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPatrolTarget", + "setBreedCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether this entity is a patrol leader. - pub fn is_patrol_leader(&self) -> Result> { + /// Get whether or not this entity is in love mode and will produce + /// offspring with another entity in love mode. Will return true if + /// and only if {@link #getLoveModeTicks()} is greater than 0. + pub fn is_love_mode(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isPatrolLeader", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether this entity is a patrol leader. - pub fn set_patrol_leader(&self, leader: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(leader.into()); + /// Get the amount of ticks remaining for this entity in love mode. + /// If the entity is not in love mode, 0 will be returned. + pub fn love_mode_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "setPatrolLeader", + "getLoveModeTicks", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether this mob can join an active raid. - pub fn is_can_join_raid(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCanJoinRaid", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets whether this mob can join an active raid. - pub fn set_can_join_raid(&self, join: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(join.into()); + /// Set the amount of ticks for which this entity should be in love mode. + /// Setting the love mode ticks to 600 is the equivalent of a player + /// feeding the entity their breeding item of choice. + pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setCanJoinRaid", + "setLoveModeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the amount of ticks that this mob has exited the bounds of a village - /// as a raid participant. - /// - /// This value is increased only when the mob has had no action for 2,400 ticks - /// (according to {@link #getNoActionTicks()}). Once both the no action ticks have - /// reached that value and the ticks outside a raid exceeds 30, the mob will be - /// expelled from the raid. - pub fn ticks_outside_raid(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTicksOutsideRaid", - sig.as_str(), - vec![], - ); + /// Check if the provided ItemStack is the correct item used for breeding + /// this entity.. + pub fn is_breed_item( + &self, + material: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the amount of ticks that this mob has exited the bounds of a village - /// as a raid participant. - /// - /// This value is considered only when the mob has had no action for 2,400 ticks - /// (according to {@link #getNoActionTicks()}). Once both the no action ticks have - /// reached that value and the ticks outside a raid exceeds 30, the mob will be - /// expelled from the raid. - pub fn set_ticks_outside_raid(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Lock the age of the animal, setting this will prevent the animal from + /// maturing or getting ready for mating. + pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(lock.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setTicksOutsideRaid", + "setAgeLock", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check whether or not this raider is celebrating a raid victory. - pub fn is_celebrating(&self) -> Result> { + /// Gets the current agelock. + pub fn age_lock(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCelebrating", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set whether or not this mob is celebrating a raid victory. - pub fn set_celebrating(&self, celebrating: bool) -> Result<(), Box> { + /// Return the ability to breed of the animal. + pub fn can_breed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set breedability of the animal, if the animal is a baby and set to + /// breed it will instantly grow up. + pub fn set_breed(&self, breed: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(celebrating.into()); + let val_1 = jni::objects::JValueGen::Bool(breed.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCelebrating", + "setBreed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the {@link Sound} this entity will play when celebrating. - pub fn celebration_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCelebrationSound", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Vindicator<'mc> { - fn into(self) -> crate::entity::Illager<'mc> { - crate::entity::Illager::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Vindicator into crate::entity::Illager") +impl<'mc> Into> for Tameable<'mc> { + fn into(self) -> crate::entity::Animals<'mc> { + crate::entity::Animals::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Tameable into crate::entity::Animals") } } #[repr(C)] -pub struct Mule<'mc>( +pub struct Illusioner<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Mule<'mc> { +impl<'mc> JNIRaw<'mc> for Illusioner<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -43941,18 +50615,18 @@ impl<'mc> JNIRaw<'mc> for Mule<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Mule<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Illusioner<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Mule from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Illusioner from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Mule")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Illusioner")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Mule object, got {}", + "Invalid argument passed. Expected a Illusioner object, got {}", name ) .into()) @@ -43962,24 +50636,32 @@ impl<'mc> JNIInstantiatable<'mc> for Mule<'mc> { } } -impl<'mc> Mule<'mc> { - /// Gets whether the horse has a chest equipped. - pub fn is_carrying_chest(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCarryingChest", sig.as_str(), vec![]); +impl<'mc> Illusioner<'mc> { + /// Gets the {@link Spell} the entity is currently using. + pub fn spell( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Spellcaster/Spell;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSpell", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::SpellcasterSpell::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets whether the horse has a chest equipped. Removing a chest will also - /// clear the chest's inventory. - pub fn set_carrying_chest(&self, chest: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(chest.into()); + /// Sets the {@link Spell} the entity is currently using. + pub fn set_spell( + &self, + spell: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Spellcaster/Spell;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(spell.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCarryingChest", + "setSpell", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -43992,360 +50674,548 @@ impl<'mc> Mule<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Mule<'mc> { - fn into(self) -> crate::entity::ChestedHorse<'mc> { - crate::entity::ChestedHorse::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Mule into crate::entity::ChestedHorse") +impl<'mc> Into> for Illusioner<'mc> { + fn into(self) -> crate::entity::Spellcaster<'mc> { + crate::entity::Spellcaster::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Illusioner into crate::entity::Spellcaster") } } +pub enum Pose<'mc> { + Standing { inner: PoseStruct<'mc> }, + FallFlying { inner: PoseStruct<'mc> }, + Sleeping { inner: PoseStruct<'mc> }, + Swimming { inner: PoseStruct<'mc> }, + SpinAttack { inner: PoseStruct<'mc> }, + Sneaking { inner: PoseStruct<'mc> }, + LongJumping { inner: PoseStruct<'mc> }, + Dying { inner: PoseStruct<'mc> }, + Croaking { inner: PoseStruct<'mc> }, + UsingTongue { inner: PoseStruct<'mc> }, + Sitting { inner: PoseStruct<'mc> }, + Roaring { inner: PoseStruct<'mc> }, + Sniffing { inner: PoseStruct<'mc> }, + Emerging { inner: PoseStruct<'mc> }, + Digging { inner: PoseStruct<'mc> }, + Sliding { inner: PoseStruct<'mc> }, + Shooting { inner: PoseStruct<'mc> }, + Inhaling { inner: PoseStruct<'mc> }, +} +impl<'mc> std::fmt::Display for Pose<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Pose::Standing { .. } => f.write_str("STANDING"), + Pose::FallFlying { .. } => f.write_str("FALL_FLYING"), + Pose::Sleeping { .. } => f.write_str("SLEEPING"), + Pose::Swimming { .. } => f.write_str("SWIMMING"), + Pose::SpinAttack { .. } => f.write_str("SPIN_ATTACK"), + Pose::Sneaking { .. } => f.write_str("SNEAKING"), + Pose::LongJumping { .. } => f.write_str("LONG_JUMPING"), + Pose::Dying { .. } => f.write_str("DYING"), + Pose::Croaking { .. } => f.write_str("CROAKING"), + Pose::UsingTongue { .. } => f.write_str("USING_TONGUE"), + Pose::Sitting { .. } => f.write_str("SITTING"), + Pose::Roaring { .. } => f.write_str("ROARING"), + Pose::Sniffing { .. } => f.write_str("SNIFFING"), + Pose::Emerging { .. } => f.write_str("EMERGING"), + Pose::Digging { .. } => f.write_str("DIGGING"), + Pose::Sliding { .. } => f.write_str("SLIDING"), + Pose::Shooting { .. } => f.write_str("SHOOTING"), + Pose::Inhaling { .. } => f.write_str("INHALING"), + } + } +} +impl<'mc> std::ops::Deref for Pose<'mc> { + type Target = PoseStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + Pose::Standing { inner } => inner, + Pose::FallFlying { inner } => inner, + Pose::Sleeping { inner } => inner, + Pose::Swimming { inner } => inner, + Pose::SpinAttack { inner } => inner, + Pose::Sneaking { inner } => inner, + Pose::LongJumping { inner } => inner, + Pose::Dying { inner } => inner, + Pose::Croaking { inner } => inner, + Pose::UsingTongue { inner } => inner, + Pose::Sitting { inner } => inner, + Pose::Roaring { inner } => inner, + Pose::Sniffing { inner } => inner, + Pose::Emerging { inner } => inner, + Pose::Digging { inner } => inner, + Pose::Sliding { inner } => inner, + Pose::Shooting { inner } => inner, + Pose::Inhaling { inner } => inner, + } + } +} + +impl<'mc> Pose<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/Pose"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/Pose;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "STANDING" => Ok(Pose::Standing { + inner: PoseStruct::from_raw(env, obj)?, + }), + "FALL_FLYING" => Ok(Pose::FallFlying { + inner: PoseStruct::from_raw(env, obj)?, + }), + "SLEEPING" => Ok(Pose::Sleeping { + inner: PoseStruct::from_raw(env, obj)?, + }), + "SWIMMING" => Ok(Pose::Swimming { + inner: PoseStruct::from_raw(env, obj)?, + }), + "SPIN_ATTACK" => Ok(Pose::SpinAttack { + inner: PoseStruct::from_raw(env, obj)?, + }), + "SNEAKING" => Ok(Pose::Sneaking { + inner: PoseStruct::from_raw(env, obj)?, + }), + "LONG_JUMPING" => Ok(Pose::LongJumping { + inner: PoseStruct::from_raw(env, obj)?, + }), + "DYING" => Ok(Pose::Dying { + inner: PoseStruct::from_raw(env, obj)?, + }), + "CROAKING" => Ok(Pose::Croaking { + inner: PoseStruct::from_raw(env, obj)?, + }), + "USING_TONGUE" => Ok(Pose::UsingTongue { + inner: PoseStruct::from_raw(env, obj)?, + }), + "SITTING" => Ok(Pose::Sitting { + inner: PoseStruct::from_raw(env, obj)?, + }), + "ROARING" => Ok(Pose::Roaring { + inner: PoseStruct::from_raw(env, obj)?, + }), + "SNIFFING" => Ok(Pose::Sniffing { + inner: PoseStruct::from_raw(env, obj)?, + }), + "EMERGING" => Ok(Pose::Emerging { + inner: PoseStruct::from_raw(env, obj)?, + }), + "DIGGING" => Ok(Pose::Digging { + inner: PoseStruct::from_raw(env, obj)?, + }), + "SLIDING" => Ok(Pose::Sliding { + inner: PoseStruct::from_raw(env, obj)?, + }), + "SHOOTING" => Ok(Pose::Shooting { + inner: PoseStruct::from_raw(env, obj)?, + }), + "INHALING" => Ok(Pose::Inhaling { + inner: PoseStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + #[repr(C)] -pub struct SpectralArrow<'mc>( +pub struct PoseStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for SpectralArrow<'mc> { +impl<'mc> JNIRaw<'mc> for Pose<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + match self { + Self::Standing { inner } => inner.0.clone(), + Self::FallFlying { inner } => inner.0.clone(), + Self::Sleeping { inner } => inner.0.clone(), + Self::Swimming { inner } => inner.0.clone(), + Self::SpinAttack { inner } => inner.0.clone(), + Self::Sneaking { inner } => inner.0.clone(), + Self::LongJumping { inner } => inner.0.clone(), + Self::Dying { inner } => inner.0.clone(), + Self::Croaking { inner } => inner.0.clone(), + Self::UsingTongue { inner } => inner.0.clone(), + Self::Sitting { inner } => inner.0.clone(), + Self::Roaring { inner } => inner.0.clone(), + Self::Sniffing { inner } => inner.0.clone(), + Self::Emerging { inner } => inner.0.clone(), + Self::Digging { inner } => inner.0.clone(), + Self::Sliding { inner } => inner.0.clone(), + Self::Shooting { inner } => inner.0.clone(), + Self::Inhaling { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + match self { + Self::Standing { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::FallFlying { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Sleeping { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Swimming { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SpinAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Sneaking { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::LongJumping { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Dying { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Croaking { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::UsingTongue { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Sitting { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Roaring { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Sniffing { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Emerging { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Digging { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Sliding { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Shooting { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Inhaling { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for SpectralArrow<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Pose<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate SpectralArrow from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Pose from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/SpectralArrow")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Pose")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SpectralArrow object, got {}", + "Invalid argument passed. Expected a Pose object, got {}", name ) .into()) } else { - Ok(Self(env.clone(), obj)) + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "STANDING" => Ok(Pose::Standing { + inner: PoseStruct::from_raw(env, obj)?, + }), + "FALL_FLYING" => Ok(Pose::FallFlying { + inner: PoseStruct::from_raw(env, obj)?, + }), + "SLEEPING" => Ok(Pose::Sleeping { + inner: PoseStruct::from_raw(env, obj)?, + }), + "SWIMMING" => Ok(Pose::Swimming { + inner: PoseStruct::from_raw(env, obj)?, + }), + "SPIN_ATTACK" => Ok(Pose::SpinAttack { + inner: PoseStruct::from_raw(env, obj)?, + }), + "SNEAKING" => Ok(Pose::Sneaking { + inner: PoseStruct::from_raw(env, obj)?, + }), + "LONG_JUMPING" => Ok(Pose::LongJumping { + inner: PoseStruct::from_raw(env, obj)?, + }), + "DYING" => Ok(Pose::Dying { + inner: PoseStruct::from_raw(env, obj)?, + }), + "CROAKING" => Ok(Pose::Croaking { + inner: PoseStruct::from_raw(env, obj)?, + }), + "USING_TONGUE" => Ok(Pose::UsingTongue { + inner: PoseStruct::from_raw(env, obj)?, + }), + "SITTING" => Ok(Pose::Sitting { + inner: PoseStruct::from_raw(env, obj)?, + }), + "ROARING" => Ok(Pose::Roaring { + inner: PoseStruct::from_raw(env, obj)?, + }), + "SNIFFING" => Ok(Pose::Sniffing { + inner: PoseStruct::from_raw(env, obj)?, + }), + "EMERGING" => Ok(Pose::Emerging { + inner: PoseStruct::from_raw(env, obj)?, + }), + "DIGGING" => Ok(Pose::Digging { + inner: PoseStruct::from_raw(env, obj)?, + }), + "SLIDING" => Ok(Pose::Sliding { + inner: PoseStruct::from_raw(env, obj)?, + }), + "SHOOTING" => Ok(Pose::Shooting { + inner: PoseStruct::from_raw(env, obj)?, + }), + "INHALING" => Ok(Pose::Inhaling { + inner: PoseStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } } -impl<'mc> SpectralArrow<'mc> { - /// Returns the amount of time that this arrow will apply - /// the glowing effect for. - pub fn glowing_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getGlowingTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) +impl<'mc> JNIRaw<'mc> for PoseStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Sets the amount of time to apply the glowing effect for. - pub fn set_glowing_ticks(&self, duration: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(duration); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setGlowingTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Gets the knockback strength for an arrow, which is the - /// {@link org.bukkit.enchantments.Enchantment#KNOCKBACK KnockBack} level - /// of the bow that shot it. - pub fn knockback_strength(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getKnockbackStrength", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) +} +impl<'mc> JNIInstantiatable<'mc> for PoseStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate PoseStruct from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Pose")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PoseStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } - /// Sets the knockback strength for an arrow. - pub fn set_knockback_strength( - &self, - knockback_strength: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(knockback_strength); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setKnockbackStrength", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +} + +impl<'mc> PoseStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Pose;"); + let cls = jni.find_class("org/bukkit/entity/Pose"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::Pose::from_raw(&jni, obj) } - /// Gets the base amount of damage this arrow will do. - /// Defaults to 2.0 for a normal arrow with - /// 0.5 * (1 + power level) added for arrows fired from - /// enchanted bows. - pub fn damage(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getDamage", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Sets the base amount of damage this arrow will do. - pub fn set_damage(&self, damage: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(damage); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setDamage", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +} +#[repr(C)] +pub struct Turtle<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Turtle<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Gets the number of times this arrow can pierce through an entity. - pub fn pierce_level(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPierceLevel", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Sets the number of times this arrow can pierce through an entity. - /// Must be between 0 and 127 times. - pub fn set_pierce_level(&self, pierce_level: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(pierce_level); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPierceLevel", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +} +impl<'mc> JNIInstantiatable<'mc> for Turtle<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Turtle from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Turtle")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Turtle object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } - /// Gets whether this arrow is critical. - /// - /// Critical arrows have increased damage and cause particle effects. - /// - /// Critical arrows generally occur when a player fully draws a bow before - /// firing. - pub fn is_critical(&self) -> Result> { +} + +impl<'mc> Turtle<'mc> { + /// Gets whether the turtle has an egg + pub fn has_egg(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCritical", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasEgg", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not this arrow should be critical. - pub fn set_critical(&self, critical: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(critical.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCritical", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether this arrow is in a block or not. - /// - /// Arrows in a block are motionless and may be picked up by players. - pub fn is_in_block(&self) -> Result> { + /// Gets whether the turtle is laying an egg + pub fn is_laying_egg(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInBlock", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isLayingEgg", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the block to which this arrow is attached. - pub fn attached_block( + /// Get the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn breed_cause( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAttachedBlock", - sig.as_str(), - vec![], - ); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::block::Block::from_raw( + Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Gets the current pickup status of this arrow. - pub fn pickup_status( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/AbstractArrow/PickupStatus;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPickupStatus", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::AbstractArrowPickupStatus::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the current pickup status of this arrow. - pub fn set_pickup_status( + /// Set the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn set_breed_cause( &self, - status: impl Into>, + uuid: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/AbstractArrow/PickupStatus;)V"); + let sig = String::from("(Ljava/util/UUID;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(status.into().jni_object().clone()) + jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPickupStatus", + "setBreedCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if this arrow was shot from a crossbow. - pub fn is_shot_from_crossbow(&self) -> Result> { + /// Get whether or not this entity is in love mode and will produce + /// offspring with another entity in love mode. Will return true if + /// and only if {@link #getLoveModeTicks()} is greater than 0. + pub fn is_love_mode(&self) -> Result> { let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the amount of ticks remaining for this entity in love mode. + /// If the entity is not in love mode, 0 will be returned. + pub fn love_mode_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "isShotFromCrossbow", + "getLoveModeTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets if this arrow was shot from a crossbow. - pub fn set_shot_from_crossbow( - &self, - shot_from_crossbow: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(shot_from_crossbow.into()); + /// Set the amount of ticks for which this entity should be in love mode. + /// Setting the love mode ticks to 600 is the equivalent of a player + /// feeding the entity their breeding item of choice. + pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setShotFromCrossbow", + "setLoveModeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the ItemStack which will be picked up from this arrow. - pub fn item(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/inventory/ItemStack;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the ItemStack which will be picked up from this arrow. - pub fn set_item( + /// Check if the provided ItemStack is the correct item used for breeding + /// this entity.. + pub fn is_breed_item( &self, - item: impl Into>, - ) -> Result<(), Box> { + material: impl Into>, + ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; + sig += "Lorg/bukkit/Material;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(material.into().jni_object().clone()) }); args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setItem", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Retrieve the shooter of this projectile. - pub fn shooter( - &self, - ) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/projectiles/ProjectileSource;"; + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getShooter", sig.as_str(), args); + .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::projectiles::ProjectileSource::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Set the shooter of this projectile. - pub fn set_shooter( - &self, - source: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/projectiles/ProjectileSource;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(source.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setShooter", sig.as_str(), args); + /// Lock the age of the animal, setting this will prevent the animal from + /// maturing or getting ready for mating. + pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(lock.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAgeLock", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Determine if this projectile should bounce or not when it hits. - pub fn does_bounce(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "doesBounce", sig.as_str(), args); + /// Gets the current agelock. + pub fn age_lock(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Set whether or not this projectile should bounce or not when it hits something. - pub fn set_bounce(&self, does_bounce: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(does_bounce.into()); - args.push(val_1); - sig += ")V"; + /// Return the ability to breed of the animal. + pub fn can_breed(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "setBounce", sig.as_str(), args); + .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set breedability of the animal, if the animal is a baby and set to + /// breed it will instantly grow up. + pub fn set_breed(&self, breed: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(breed.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBreed", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } @@ -44355,19 +51225,19 @@ impl<'mc> SpectralArrow<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for SpectralArrow<'mc> { - fn into(self) -> crate::entity::AbstractArrow<'mc> { - crate::entity::AbstractArrow::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SpectralArrow into crate::entity::AbstractArrow") +impl<'mc> Into> for Turtle<'mc> { + fn into(self) -> crate::entity::Animals<'mc> { + crate::entity::Animals::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Turtle into crate::entity::Animals") } } #[repr(C)] -pub struct Zombie<'mc>( +pub struct BlockDisplay<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Zombie<'mc> { +impl<'mc> JNIRaw<'mc> for BlockDisplay<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -44375,18 +51245,18 @@ impl<'mc> JNIRaw<'mc> for Zombie<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Zombie<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockDisplay<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Zombie from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate BlockDisplay from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Zombie")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/BlockDisplay")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Zombie object, got {}", + "Invalid argument passed. Expected a BlockDisplay object, got {}", name ) .into()) @@ -44396,634 +51266,386 @@ impl<'mc> JNIInstantiatable<'mc> for Zombie<'mc> { } } -impl<'mc> Zombie<'mc> { - #[deprecated] - /// Gets whether the zombie is a baby - pub fn is_baby(&self) -> Result> { - let sig = String::from("()Z"); +impl<'mc> BlockDisplay<'mc> { + /// Gets the displayed block. + pub fn block(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isBaby", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - /// Sets whether the zombie is a baby - pub fn set_baby( + /// Sets the displayed block. + pub fn set_block( &self, - flag: std::option::Option, + block: impl Into>, ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = flag { - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_1); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setBaby", sig.as_str(), args); + let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(block.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBlock", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets whether the zombie is a villager - pub fn is_villager(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isVillager", sig.as_str(), vec![]); + /// Gets the transformation applied to this display. + pub fn transformation( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Transformation;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTransformation", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::util::Transformation::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - - pub fn set_villager(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Sets the transformation applied to this display + pub fn set_transformation( + &self, + transformation: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Transformation;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transformation.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVillager", + "setTransformation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - - pub fn set_villager_profession( + /// Sets the raw transformation matrix applied to this display + pub fn set_transformation_matrix( &self, - profession: impl Into>, + transformation_matrix: jni::objects::JObject<'mc>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Villager/Profession;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(profession.into().jni_object().clone()) - }); + let sig = String::from("(Lorg/joml/Matrix4f;)V"); + let val_1 = jni::objects::JValueGen::Object(transformation_matrix); let res = self.jni_ref().call_method( &self.jni_object(), - "setVillagerProfession", + "setTransformationMatrix", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - - pub fn villager_profession( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Villager/Profession;"); + /// Gets the interpolation duration of this display. + pub fn interpolation_duration(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getVillagerProfession", + "getInterpolationDuration", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::VillagerProfession::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - /// Get if this entity is in the process of converting to a Drowned as a - /// result of being underwater. - pub fn is_converting(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isConverting", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Sets the interpolation duration of this display. + pub fn set_interpolation_duration( + &self, + duration: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(duration); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setInterpolationDuration", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the amount of ticks until this entity will be converted to a Drowned - /// as a result of being underwater. - /// When this reaches 0, the entity will be converted. - pub fn conversion_time(&self) -> Result> { + /// Gets the teleport duration of this display. + ///
    + ///
  • 0 means that updates are applied immediately.
  • + ///
  • 1 means that the display entity will move from current position to the updated one over one tick.
  • + ///
  • Higher values spread the movement over multiple ticks.
  • + ///
+ pub fn teleport_duration(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getConversionTime", + "getTeleportDuration", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the amount of ticks until this entity will be converted to a Drowned - /// as a result of being underwater. - /// When this reaches 0, the entity will be converted. A value of less than 0 - /// will stop the current conversion process without converting the current - /// entity. - pub fn set_conversion_time(&self, time: i32) -> Result<(), Box> { + /// Sets the teleport duration of this display. + pub fn set_teleport_duration(&self, duration: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(time); + let val_1 = jni::objects::JValueGen::Int(duration); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTeleportDuration", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the view distance/range of this display. + pub fn view_range(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getViewRange", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the view distance/range of this display. + pub fn set_view_range(&self, range: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(range); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setViewRange", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the shadow radius of this display. + pub fn shadow_radius(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getShadowRadius", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the shadow radius of this display. + pub fn set_shadow_radius(&self, radius: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(radius); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setShadowRadius", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the shadow strength of this display. + pub fn shadow_strength(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getShadowStrength", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the shadow strength of this display. + pub fn set_shadow_strength(&self, strength: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(strength); let res = self.jni_ref().call_method( &self.jni_object(), - "setConversionTime", + "setShadowStrength", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether this zombie can break doors - pub fn can_break_doors(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the width of this display. + pub fn display_width(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "canBreakDoors", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDisplayWidth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.f()?) } - /// Sets whether this zombie can break doors - /// This will be ignored if the entity is a Drowned. Will also stop the action if - /// the entity is currently breaking a door. - pub fn set_can_break_doors(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Sets the width of this display. + pub fn set_display_width(&self, width: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(width); let res = self.jni_ref().call_method( &self.jni_object(), - "setCanBreakDoors", + "setDisplayWidth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the age of this mob. - pub fn age(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getAge", sig.as_str(), vec![]); + /// Gets the height of this display. + pub fn display_height(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDisplayHeight", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.f()?) } - /// Sets the age of this mob. - pub fn set_age(&self, age: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(age); + /// Sets the height if this display. + pub fn set_display_height(&self, height: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(height); let res = self.jni_ref().call_method( &self.jni_object(), - "setAge", + "setDisplayHeight", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Lock the age of the animal, setting this will prevent the animal from maturing or getting ready for mating. - pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(lock.into()); + /// Gets the amount of ticks before client-side interpolation will commence. + pub fn interpolation_delay(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "setAgeLock", + "getInterpolationDelay", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Gets the current agelock. - pub fn age_lock(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets the age of the mob to an adult - pub fn set_adult(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setAdult", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns true if the mob is an adult. - pub fn is_adult(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isAdult", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Return the ability to breed of the animal. - pub fn can_breed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - #[deprecated] - /// Set breedability of the animal, if the animal is a baby and set to breed it will instantly grow up. - pub fn set_breed(&self, breed: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(breed.into()); + /// Sets the amount of ticks before client-side interpolation will commence. + pub fn set_interpolation_delay(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreed", + "setInterpolationDelay", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Zombie<'mc> { - fn into(self) -> crate::entity::Monster<'mc> { - crate::entity::Monster::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Zombie into crate::entity::Monster") - } -} -impl<'mc> Into> for Zombie<'mc> { - fn into(self) -> crate::entity::Ageable<'mc> { - crate::entity::Ageable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Zombie into crate::entity::Ageable") - } -} -#[repr(C)] -pub struct Parrot<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Parrot<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Parrot<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Parrot from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Parrot")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Parrot object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Parrot<'mc> { - /// Get the variant of this parrot. - pub fn variant(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Parrot/Variant;"); + /// Gets the billboard setting of this entity. + /// The billboard setting controls the automatic rotation of the entity to + /// face the player. + pub fn billboard( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Display/Billboard;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBillboard", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::ParrotVariant::from_raw(&self.jni_ref(), unsafe { + crate::entity::DisplayBillboard::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Set the variant of this parrot. - pub fn set_variant( + /// Sets the billboard setting of this entity. + /// The billboard setting controls the automatic rotation of the entity to + /// face the player. + pub fn set_billboard( &self, - variant: impl Into>, + billboard: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Parrot/Variant;)V"); + let sig = String::from("(Lorg/bukkit/entity/Display/Billboard;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(variant.into().jni_object().clone()) + jni::objects::JObject::from_raw(billboard.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVariant", + "setBillboard", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether a parrot is dancing - pub fn is_dancing(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isDancing", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Check if this is tamed - /// - /// If something is tamed then a player can not tame it through normal - /// methods, even if it does not belong to anyone in particular. - pub fn is_tamed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isTamed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets if this has been tamed. Not necessary if the method setOwner has - /// been used, as it tames automatically. - /// - /// If something is tamed then a player can not tame it through normal - /// methods, even if it does not belong to anyone in particular. - pub fn set_tamed(&self, tame: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(tame.into()); + /// Gets the scoreboard team overridden glow color of this display. + pub fn glow_color_override( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Color;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setTamed", + "getGlowColorOverride", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the current owning AnimalTamer - pub fn owner( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/AnimalTamer;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::AnimalTamer::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(Some(crate::Color::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Set this to be owned by given AnimalTamer. - /// - /// If the owner is not null, this will be tamed and will have any current - /// path it is following removed. If the owner is set to null, this will be - /// untamed, and the current owner removed. - pub fn set_owner( + /// Sets the scoreboard team overridden glow color of this display. + pub fn set_glow_color_override( &self, - tamer: impl Into>, + color: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/AnimalTamer;)V"); + let sig = String::from("(Lorg/bukkit/Color;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tamer.into().jni_object().clone()) + jni::objects::JObject::from_raw(color.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setOwner", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks if this animal is sitting - pub fn is_sitting(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSitting", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets if this animal is sitting. Will remove any path that the animal - /// was following beforehand. - pub fn set_sitting(&self, sitting: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(sitting.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSitting", + "setGlowColorOverride", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Parrot<'mc> { - fn into(self) -> crate::entity::Tameable<'mc> { - crate::entity::Tameable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Parrot into crate::entity::Tameable") - } -} -impl<'mc> Into> for Parrot<'mc> { - fn into(self) -> crate::entity::Sittable<'mc> { - crate::entity::Sittable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Parrot into crate::entity::Sittable") - } -} -pub enum ParrotVariant<'mc> {} -impl<'mc> std::fmt::Display for ParrotVariant<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> ParrotVariant<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/Parrot/Variant"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/Parrot/Variant;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct ParrotVariantStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for ParrotVariant<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for ParrotVariant<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ParrotVariant from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Parrot/Variant")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ParrotVariant object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for ParrotVariantStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for ParrotVariantStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate ParrotVariantStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Parrot/Variant")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ParrotVariantStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> ParrotVariantStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Parrot/Variant;"); - let cls = jni.find_class("org/bukkit/entity/Parrot/Variant"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::ParrotVariant::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct ExperienceOrb<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for ExperienceOrb<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for ExperienceOrb<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ExperienceOrb from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ExperienceOrb")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ExperienceOrb object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> ExperienceOrb<'mc> { - /// Gets how much experience is contained within this orb - pub fn experience(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the brightness override of the entity. + pub fn brightness( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Display/Brightness;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getExperience", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBrightness", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::DisplayBrightness::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets how much experience is contained within this orb - pub fn set_experience(&self, value: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(value); + /// Sets the brightness override of the entity. + pub fn set_brightness( + &self, + brightness: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Display/Brightness;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(brightness.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setExperience", + "setBrightness", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -45975,609 +52597,170 @@ impl<'mc> ExperienceOrb<'mc> { let sig = String::from("(Ljava/lang/String;)Z"); let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( self.jni_ref().new_string(tag.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addScoreboardTag", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Removes a given tag from this entity. - pub fn remove_scoreboard_tag( - &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removeScoreboardTag", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the reaction of the entity when moved by a piston. - pub fn piston_move_reaction( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPistonMoveReaction", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the closest cardinal {@link BlockFace} direction an entity is - /// currently facing. - /// - /// This will not return any non-cardinal directions such as - /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. - /// - /// {@link Hanging} entities will override this call and thus their behavior - /// may be different. - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the entity's current pose. - /// Note that the pose is only updated at the end of a tick, so may be - /// inconsistent with other methods. eg {@link Player#isSneaking()} being - /// true does not imply the current pose will be {@link Pose#SNEAKING} - pub fn pose(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Pose;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the category of spawn to which this entity belongs. - pub fn spawn_category( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSpawnCategory", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Checks if this entity has been spawned in a world. - /// - /// Entities not spawned in a world will not tick, be sent to players, or be - /// saved to the server files. - pub fn is_in_world(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get this entity as an NBT string. - /// - /// This string should not be relied upon as a serializable value. - pub fn as_string(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// Crates an {@link EntitySnapshot} representing the current state of this entity. - pub fn create_snapshot( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::EntitySnapshot::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Creates a copy of this entity and all its data. Spawns the copy at the given location. - /// - /// Note: Players cannot be copied. - pub fn copy( - &self, - to: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = to { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")Lorg/bukkit/entity/Entity;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets a metadata value in the implementing object's metadata store. - pub fn set_metadata( - &self, - metadata_key: impl Into, - new_metadata_value: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMetadata", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns a list of previously set metadata values from the implementing - /// object's metadata store. - pub fn get_metadata( - &self, - metadata_key: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMetadata", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::metadata::MetadataValue::from_raw( - &self.jni_ref(), - obj, - )?); - } - Ok(new_vec) - } - /// Tests to see whether the implementing object contains the given - /// metadata value in its metadata store. - pub fn has_metadata( - &self, - metadata_key: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasMetadata", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Removes the given metadata value from the implementing object's - /// metadata store. - pub fn remove_metadata( - &self, - metadata_key: impl Into, - owning_plugin: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removeMetadata", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Sends this sender multiple messages - pub fn send_message( - &self, - sender: impl Into>, - messages: std::option::Option>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = messages { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the name of this command sender - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Gets the custom name on a mob or block. If there is no name this method - /// will return null. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn custom_name(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCustomName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// Sets a custom name on a mob or block. This name will be used in death - /// messages and can be sent to the client as a nameplate over the mob. - /// - /// Setting the name to null or an empty string will clear it. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn set_custom_name( - &self, - name: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCustomName", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPersistentDataContainer", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for ExperienceOrb<'mc> { - fn into(self) -> crate::entity::Entity<'mc> { - crate::entity::Entity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ExperienceOrb into crate::entity::Entity") - } -} -#[repr(C)] -pub struct PiglinAbstract<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PiglinAbstract<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PiglinAbstract<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate PiglinAbstract from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/PiglinAbstract")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PiglinAbstract object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> PiglinAbstract<'mc> { - /// Gets whether the piglin is immune to zombification. - pub fn is_immune_to_zombification(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isImmuneToZombification", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether the piglin is immune to zombification. - pub fn set_immune_to_zombification( - &self, - flag: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setImmuneToZombification", + "addScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the amount of ticks until this entity will be converted to a - /// Zombified Piglin. - /// When this reaches 300, the entity will be converted. - pub fn conversion_time(&self) -> Result> { - let sig = String::from("()I"); + /// Removes a given tag from this entity. + pub fn remove_scoreboard_tag( + &self, + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "getConversionTime", + "removeScoreboardTag", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the amount of ticks until this entity will be converted to a - /// Zombified Piglin. - /// When this reaches 0, the entity will be converted. A value of less than 0 - /// will stop the current conversion process without converting the current - /// entity. - pub fn set_conversion_time(&self, time: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(time); + /// Returns the reaction of the entity when moved by a piston. + pub fn piston_move_reaction( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setConversionTime", + "getPistonMoveReaction", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get if this entity is in the process of converting to a Zombified Piglin. - pub fn is_converting(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isConverting", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - /// Gets whether the piglin is a baby - pub fn is_baby(&self) -> Result> { - let sig = String::from("()Z"); + /// Get the closest cardinal {@link BlockFace} direction an entity is + /// currently facing. + /// + /// This will not return any non-cardinal directions such as + /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// + /// {@link Hanging} entities will override this call and thus their behavior + /// may be different. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isBaby", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Sets whether the piglin is a baby - pub fn set_baby( - &self, - flag: std::option::Option, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = flag { - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_1); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setBaby", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the age of this mob. - pub fn age(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the entity's current pose. + /// Note that the pose is only updated at the end of a tick, so may be + /// inconsistent with other methods. eg {@link Player#isSneaking()} being + /// true does not imply the current pose will be {@link Pose#SNEAKING} + pub fn pose(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Pose;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getAge", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the age of this mob. - pub fn set_age(&self, age: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(age); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAge", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - /// Lock the age of the animal, setting this will prevent the animal from maturing or getting ready for mating. - pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(lock.into()); + /// Get the category of spawn to which this entity belongs. + pub fn spawn_category( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setAgeLock", + "getSpawnCategory", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Gets the current agelock. - pub fn age_lock(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets the age of the mob to an adult - pub fn set_adult(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setAdult", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns true if the mob is an adult. - pub fn is_adult(&self) -> Result> { + /// Checks if this entity has been spawned in a world. + /// + /// Entities not spawned in a world will not tick, be sent to players, or be + /// saved to the server files. + pub fn is_in_world(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isAdult", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Return the ability to breed of the animal. - pub fn can_breed(&self) -> Result> { - let sig = String::from("()Z"); + /// Get this entity as an NBT string. + /// + /// This string should not be relied upon as a serializable value. + pub fn as_string(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Crates an {@link EntitySnapshot} representing the current state of this entity. + pub fn create_snapshot( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntitySnapshot::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// + /// Note: Players cannot be copied. + pub fn copy( + &self, + to: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = to { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Lorg/bukkit/entity/Entity;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "copy", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Set breedability of the animal, if the animal is a baby and set to breed it will instantly grow up. - pub fn set_breed(&self, breed: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(breed.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setBreed", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -46585,25 +52768,19 @@ impl<'mc> PiglinAbstract<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PiglinAbstract<'mc> { - fn into(self) -> crate::entity::Monster<'mc> { - crate::entity::Monster::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PiglinAbstract into crate::entity::Monster") - } -} -impl<'mc> Into> for PiglinAbstract<'mc> { - fn into(self) -> crate::entity::Ageable<'mc> { - crate::entity::Ageable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PiglinAbstract into crate::entity::Ageable") +impl<'mc> Into> for BlockDisplay<'mc> { + fn into(self) -> crate::entity::Display<'mc> { + crate::entity::Display::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockDisplay into crate::entity::Display") } } #[repr(C)] -pub struct Monster<'mc>( +pub struct WitherSkull<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Monster<'mc> { +impl<'mc> JNIRaw<'mc> for WitherSkull<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -46611,18 +52788,18 @@ impl<'mc> JNIRaw<'mc> for Monster<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Monster<'mc> { +impl<'mc> JNIInstantiatable<'mc> for WitherSkull<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Monster from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate WitherSkull from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Monster")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/WitherSkull")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Monster object, got {}", + "Invalid argument passed. Expected a WitherSkull object, got {}", name ) .into()) @@ -46632,995 +52809,882 @@ impl<'mc> JNIInstantiatable<'mc> for Monster<'mc> { } } -impl<'mc> Monster<'mc> { - /// Gets the height of the living entity's eyes above its Location. - pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { - let sig = String::from("(Z)D"); - let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); +impl<'mc> WitherSkull<'mc> { + /// Sets the charged status of the wither skull. + pub fn set_charged(&self, charged: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(charged.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getEyeHeight", + "setCharged", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get a Location detailing the current eye position of the living entity. - pub fn eye_location(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), vec![]); + /// Gets whether or not the wither skull is charged. + pub fn is_charged(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isCharged", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Gets all blocks along the living entity's line of sight. + /// Sets the direction the fireball should be flying towards. /// - /// This list contains all blocks from the living entity's eye position to - /// target inclusive. This method considers all blocks as 1x1x1 in size. - pub fn get_line_of_sight( - &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { - let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(max_distance); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLineOfSight", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Gets the block that the living entity has targeted. + /// This is a convenience method, it will change the velocity direction and + /// acceleration direction, while keeping the power the same. /// - /// This method considers all blocks as 1x1x1 in size. To take exact block - /// collision shapes into account, see {@link #getTargetBlockExact(int, - /// FluidCollisionMode)}. - pub fn get_target_block( + /// Note: This method only uses the direction of the vector and will + /// normalize (a copy of) it. + /// + /// Special Case: When the given direction is + /// {@link Vector#isZero() zero}, the velocity and acceleration will also be + /// set to zero without keeping the power. + pub fn set_direction( &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result, Box> { - let sig = String::from("(Ljava/util/Set;I)Lorg/bukkit/block/Block;"); + direction: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + jni::objects::JObject::from_raw(direction.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "getTargetBlock", + "setDirection", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Retrieve the direction this fireball is heading toward. The returned vector is not normalized. + pub fn direction(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the last two blocks along the living entity's line of sight. + /// Sets the acceleration of the fireball. + /// The acceleration gets applied to the velocity every tick, depending on + /// the specific type of the fireball a damping / drag factor is applied so + /// that the velocity does not grow into infinity. /// - /// The target block will be the last block in the list. This method - /// considers all blocks as 1x1x1 in size. - pub fn get_last_two_target_blocks( + /// Note: that the client may not respect non-default acceleration + /// power and will therefore mispredict the location of the fireball, causing + /// visual stutter. + pub fn set_acceleration( &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { - let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + acceleration: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + jni::objects::JObject::from_raw(acceleration.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(max_distance); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLastTwoTargetBlocks", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Gets the block that the living entity has targeted. - /// - /// This takes the blocks' precise collision shapes into account. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn get_target_block_exact( - &self, - max_distance: i32, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(max_distance); - args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/block/Block;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTargetBlockExact", - sig.as_str(), - args, - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::block::Block::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Performs a ray trace that provides information on the targeted block. - /// - /// This takes the blocks' precise collision shapes into account. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn ray_trace_blocks( - &self, - max_distance: f64, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(max_distance); - args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/util/RayTraceResult;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::util::RayTraceResult::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Returns the amount of air that the living entity has remaining, in - /// ticks. - pub fn remaining_air(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the amount of air that the living entity has remaining, in ticks. - pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setRemainingAir", + "setAcceleration", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the maximum amount of air the living entity can have, in ticks. - pub fn maximum_air(&self) -> Result> { - let sig = String::from("()I"); + /// Retrieve the acceleration of this fireball. + pub fn acceleration(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAcceleration", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the maximum amount of air the living entity can have, in ticks. - pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaximumAir", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Gets the item that the player is using (eating food, drawing back a bow, - /// blocking, etc.) - pub fn item_in_use( +} +impl<'mc> Into> for WitherSkull<'mc> { + fn into(self) -> crate::entity::Fireball<'mc> { + crate::entity::Fireball::from_raw(&self.jni_ref(), self.1) + .expect("Error converting WitherSkull into crate::entity::Fireball") + } +} +#[repr(C)] +pub struct WitherSkeleton<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for WitherSkeleton<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for WitherSkeleton<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate WitherSkeleton from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/WitherSkeleton")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a WitherSkeleton object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> WitherSkeleton<'mc> { + #[deprecated] + /// Gets the current type of this skeleton. + pub fn skeleton_type( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Skeleton/SkeletonType;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Gets the number of ticks remaining for the current item's usage. - pub fn item_in_use_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getItemInUseTicks", - sig.as_str(), - vec![], - ); + .call_method(&self.jni_object(), "getSkeletonType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::entity::SkeletonSkeletonType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the number of ticks that remain for the current item's usage. - /// Applies to items that take time to use, like eating food, drawing a bow, - /// or throwing a trident. - pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + #[deprecated] + + pub fn set_skeleton_type( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Skeleton/SkeletonType;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemInUseTicks", + "setSkeletonType", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the time in ticks until the next arrow leaves the entity's body. - pub fn arrow_cooldown(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getArrowCooldown", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Sets the time in ticks until the next arrow leaves the entity's body. - pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setArrowCooldown", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); +} +impl<'mc> Into> for WitherSkeleton<'mc> { + fn into(self) -> crate::entity::AbstractSkeleton<'mc> { + crate::entity::AbstractSkeleton::from_raw(&self.jni_ref(), self.1) + .expect("Error converting WitherSkeleton into crate::entity::AbstractSkeleton") + } +} +#[repr(C)] +pub struct AbstractWindCharge<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for AbstractWindCharge<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for AbstractWindCharge<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate AbstractWindCharge from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/AbstractWindCharge")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a AbstractWindCharge object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> AbstractWindCharge<'mc> { + /// Immediately explode this WindCharge. + pub fn explode(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "explode", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the amount of arrows in an entity's body. - pub fn arrows_in_body(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the amount of arrows in the entity's body. - pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(count); + /// Sets the direction the fireball should be flying towards. + /// + /// This is a convenience method, it will change the velocity direction and + /// acceleration direction, while keeping the power the same. + /// + /// Note: This method only uses the direction of the vector and will + /// normalize (a copy of) it. + /// + /// Special Case: When the given direction is + /// {@link Vector#isZero() zero}, the velocity and acceleration will also be + /// set to zero without keeping the power. + pub fn set_direction( + &self, + direction: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(direction.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setArrowsInBody", + "setDirection", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's current maximum no damage ticks. - /// - /// This is the maximum duration in which the living entity will not take - /// damage. - pub fn maximum_no_damage_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMaximumNoDamageTicks", - sig.as_str(), - vec![], - ); + #[deprecated] + /// Retrieve the direction this fireball is heading toward. The returned vector is not normalized. + pub fn direction(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the living entity's current maximum no damage ticks. - pub fn set_maximum_no_damage_ticks( + /// Sets the acceleration of the fireball. + /// The acceleration gets applied to the velocity every tick, depending on + /// the specific type of the fireball a damping / drag factor is applied so + /// that the velocity does not grow into infinity. + /// + /// Note: that the client may not respect non-default acceleration + /// power and will therefore mispredict the location of the fireball, causing + /// visual stutter. + pub fn set_acceleration( &self, - ticks: i32, + acceleration: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(acceleration.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaximumNoDamageTicks", + "setAcceleration", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's last damage taken in the current no damage - /// ticks time. - /// - /// Only damage higher than this amount will further damage the living - /// entity. - pub fn last_damage(&self) -> Result> { - let sig = String::from("()D"); + /// Retrieve the acceleration of this fireball. + pub fn acceleration(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAcceleration", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the damage dealt within the current no damage ticks time period. - pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(damage); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for AbstractWindCharge<'mc> { + fn into(self) -> crate::entity::Fireball<'mc> { + crate::entity::Fireball::from_raw(&self.jni_ref(), self.1) + .expect("Error converting AbstractWindCharge into crate::entity::Fireball") + } +} +#[repr(C)] +pub struct ArmorStand<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ArmorStand<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for ArmorStand<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate ArmorStand from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ArmorStand")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ArmorStand object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> ArmorStand<'mc> { + #[deprecated] + /// Returns the item the armor stand is currently holding. + pub fn item_in_hand( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemInHand", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + #[deprecated] + /// Sets the item the armor stand is currently holding. + pub fn set_item_in_hand( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDamage", + "setItemInHand", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's current no damage ticks. - pub fn no_damage_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getNoDamageTicks", - sig.as_str(), - vec![], - ); + #[deprecated] + /// Returns the item currently being worn by the armor stand on its feet. + pub fn boots(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBoots", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the living entity's current no damage ticks. - pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + #[deprecated] + /// Sets the item currently being worn by the armor stand on its feet. + pub fn set_boots( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setNoDamageTicks", + "setBoots", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the ticks that this entity has performed no action. - /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn no_action_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getNoActionTicks", - sig.as_str(), - vec![], - ); + #[deprecated] + /// Returns the item currently being worn by the armor stand on its legs. + pub fn leggings(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLeggings", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the ticks that this entity has performed no action. - /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + #[deprecated] + /// Sets the item currently being worn by the armor stand on its legs. + pub fn set_leggings( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setNoActionTicks", + "setLeggings", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the player identified as the killer of the living entity. - /// - /// May be null. - pub fn killer(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Player;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Player::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } #[deprecated] - /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. - pub fn add_potion_effect( + /// Returns the item currently being worn by the armor stand on its chest. + pub fn chestplate( &self, - effect: impl Into>, - force: std::option::Option, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/potion/PotionEffect;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(effect.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = force { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")Z"; + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); + .call_method(&self.jni_object(), "getChestplate", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns whether the living entity already has an existing effect of - /// the given {@link PotionEffectType} applied to it. - pub fn has_potion_effect( + #[deprecated] + /// Sets the item currently being worn by the armor stand on its chest. + pub fn set_chestplate( &self, - val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasPotionEffect", + "setChestplate", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Returns the item currently being worn by the armor stand on its head. + pub fn helmet(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHelmet", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the active {@link PotionEffect} of the specified type. - /// - /// If the effect is not present on the entity then null will be returned. - pub fn get_potion_effect( + #[deprecated] + /// Sets the item currently being worn by the armor stand on its head. + pub fn set_helmet( &self, - val_type: impl Into>, - ) -> Result>, Box> { - let sig = - String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getPotionEffect", + "setHelmet", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the armor stand's body's current pose as a + /// {@link org.bukkit.util.EulerAngle}. + pub fn body_pose(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/EulerAngle;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBodyPose", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::potion::PotionEffect::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::util::EulerAngle::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Removes any effects present of the given {@link PotionEffectType}. - pub fn remove_potion_effect( + /// Sets the armor stand's body's current pose as a + /// {@link org.bukkit.util.EulerAngle}. + pub fn set_body_pose( &self, - val_type: impl Into>, + pose: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); + let sig = String::from("(Lorg/bukkit/util/EulerAngle;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(pose.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removePotionEffect", + "setBodyPose", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns all currently active {@link PotionEffect}s on the living - /// entity. - pub fn active_potion_effects( + /// Returns the armor stand's left arm's current pose as a + /// {@link org.bukkit.util.EulerAngle}. + pub fn left_arm_pose( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getActivePotionEffects", - sig.as_str(), - vec![], - ); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/EulerAngle;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLeftArmPose", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + crate::util::EulerAngle::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Checks whether the living entity has block line of sight to another. - /// - /// This uses the same algorithm that hostile mobs use to find the closest - /// player. - pub fn has_line_of_sight( + /// Sets the armor stand's left arm's current pose as a + /// {@link org.bukkit.util.EulerAngle}. + pub fn set_left_arm_pose( &self, - other: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + pose: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/EulerAngle;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) + jni::objects::JObject::from_raw(pose.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasLineOfSight", + "setLeftArmPose", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns if the living entity despawns when away from players or not. - /// - /// By default, animals are not removed while other mobs are. - pub fn remove_when_far_away(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getRemoveWhenFarAway", - sig.as_str(), - vec![], - ); + /// Returns the armor stand's right arm's current pose as a + /// {@link org.bukkit.util.EulerAngle}. + pub fn right_arm_pose( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/EulerAngle;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRightArmPose", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::util::EulerAngle::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets whether or not the living entity despawns when away from players - /// or not. - pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(remove.into()); + /// Sets the armor stand's right arm's current pose as a + /// {@link org.bukkit.util.EulerAngle}. + pub fn set_right_arm_pose( + &self, + pose: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/EulerAngle;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(pose.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setRemoveWhenFarAway", + "setRightArmPose", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the inventory with the equipment worn by the living entity. - pub fn equipment( + /// Returns the armor stand's left leg's current pose as a + /// {@link org.bukkit.util.EulerAngle}. + pub fn left_leg_pose( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/EulerAngle;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLeftLegPose", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::EntityEquipment::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::util::EulerAngle::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets whether or not the living entity can pick up items. - pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(pickup.into()); + /// Sets the armor stand's left leg's current pose as a + /// {@link org.bukkit.util.EulerAngle}. + pub fn set_left_leg_pose( + &self, + pose: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/EulerAngle;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(pose.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCanPickupItems", + "setLeftLegPose", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the living entity can pick up items. - pub fn can_pickup_items(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCanPickupItems", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns whether the entity is currently leashed. - pub fn is_leashed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the entity that is currently leading this entity. - pub fn leash_holder(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + /// Returns the armor stand's right leg's current pose as a + /// {@link org.bukkit.util.EulerAngle}. + pub fn right_leg_pose( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/EulerAngle;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getRightLegPose", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + crate::util::EulerAngle::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the leash on this entity to be held by the supplied entity. - /// - /// This method has no effect on EnderDragons, Withers, Players, or Bats. - /// Non-living entities excluding leashes will not persist as leash - /// holders. - pub fn set_leash_holder( + /// Sets the armor stand's right leg's current pose as a + /// {@link org.bukkit.util.EulerAngle}. + pub fn set_right_leg_pose( &self, - holder: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + pose: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/EulerAngle;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(holder.into().jni_object().clone()) + jni::objects::JObject::from_raw(pose.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLeashHolder", + "setRightLegPose", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Checks to see if an entity is gliding, such as using an Elytra. - pub fn is_gliding(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); + /// Returns the armor stand's head's current pose as a + /// {@link org.bukkit.util.EulerAngle}. + pub fn head_pose(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/EulerAngle;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHeadPose", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::util::EulerAngle::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Makes entity start or stop gliding. This will work even if an Elytra - /// is not equipped, but will be reverted by the server immediately after - /// unless an event-cancelling mechanism is put in place. - pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gliding.into()); + /// Sets the armor stand's head's current pose as a + /// {@link org.bukkit.util.EulerAngle}. + pub fn set_head_pose( + &self, + pose: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/EulerAngle;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(pose.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setGliding", + "setHeadPose", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks to see if an entity is swimming. - pub fn is_swimming(&self) -> Result> { + /// Returns whether the armor stand has a base plate. + pub fn has_base_plate(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasBasePlate", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Makes entity start or stop swimming. - /// This may have unexpected results if the entity is not in water. - pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { + /// Sets whether the armor stand has a base plate. + pub fn set_base_plate(&self, base_plate: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(swimming.into()); + let val_1 = jni::objects::JValueGen::Bool(base_plate.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setSwimming", + "setBasePlate", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks to see if an entity is currently using the Riptide enchantment. - pub fn is_riptiding(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns whether this entity is slumbering. - pub fn is_sleeping(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets if the entity is climbing. - pub fn is_climbing(&self) -> Result> { + /// Returns whether the armor stand should be visible or not. + pub fn is_visible(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isVisible", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether an entity will have AI. - /// The entity will be completely unable to move if it has no AI. - pub fn set_ai(&self, ai: bool) -> Result<(), Box> { + /// Sets whether the armor stand should be visible or not. + pub fn set_visible(&self, visible: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(ai.into()); + let val_1 = jni::objects::JValueGen::Bool(visible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setAI", + "setVisible", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks whether an entity has AI. - /// The entity will be completely unable to move if it has no AI. - pub fn has_ai(&self) -> Result> { + /// Returns whether this armor stand has arms. + pub fn has_arms(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasArms", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Makes this entity attack the given entity with a melee attack. - /// Attack damage is calculated by the server from the attributes and - /// equipment of this mob, and knockback is applied to {@code target} as - /// appropriate. - pub fn attack( - &self, - target: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) - }); + /// Sets whether this armor stand has arms. + pub fn set_arms(&self, arms: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(arms.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "attack", + "setArms", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Makes this entity swing their main hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their main hand. - pub fn swing_main_hand(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Makes this entity swing their off hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their off hand. - pub fn swing_off_hand(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Makes this entity flash red as if they were damaged. - pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); - let res = self.jni_ref().call_method( - &self.jni_object(), - "playHurtAnimation", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Returns whether this armor stand is scaled down. + pub fn is_small(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSmall", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Set if this entity will be subject to collisions with other entities. - /// - /// Exemptions to this rule can be managed with - /// {@link #getCollidableExemptions()} - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not working for player collisions. This - /// method should therefore only be used to set the collision status of - /// non-player entities. - /// - /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in - /// combination with a {@link Scoreboard} and a {@link Team}. - pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { + /// Sets whether this armor stand is scaled down. + pub fn set_small(&self, small: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(collidable.into()); + let val_1 = jni::objects::JValueGen::Bool(small.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCollidable", + "setSmall", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if this entity is subject to collisions with other entities. - /// - /// Some entities might be exempted from the collidable rule of this entity. - /// Use {@link #getCollidableExemptions()} to get these. - /// - /// Please note that this method returns only the custom collidable state, - /// not whether the entity is non-collidable for other reasons such as being - /// dead. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not being accurate for player collisions. - /// This method should therefore only be used to check the collision status - /// of non-player entities. - /// - /// To check the collision behavior for a player, use - /// {@link Team.Option#COLLISION_RULE} in combination with a - /// {@link Scoreboard} and a {@link Team}. - pub fn is_collidable(&self) -> Result> { + /// Returns whether this armor stand is a marker, meaning it has a very small + /// collision box. + pub fn is_marker(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isMarker", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets a mutable set of UUIDs of the entities which are exempt from the - /// entity's collidable rule and which's collision with this entity will - /// behave the opposite of it. - /// - /// This set can be modified to add or remove exemptions. - /// - /// For example if collidable is true and an entity is in the exemptions set - /// then it will not collide with it. Similarly if collidable is false and an - /// entity is in this set then it will still collide with it. - /// - /// Note these exemptions are not (currently) persistent. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in those exemptions not being accurate for player - /// collisions. This method should therefore only be used to exempt - /// non-player entities. - /// - /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} - /// in combination with a {@link Scoreboard} and a {@link Team}. - pub fn collidable_exemptions( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Sets whether this armor stand is a marker, meaning it has a very small + /// collision box. + pub fn set_marker(&self, marker: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(marker.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getCollidableExemptions", + "setMarker", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns the value of the memory specified. - /// - /// Note that the value is null when the specific entity does not have that - /// value by default. - pub fn get_memory( + /// Locks the equipment slot with the specified + /// {@link LockType locking mechanism}. + pub fn add_equipment_lock( &self, - memory_key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); + slot: impl Into>, + lock_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from( + "(Lorg/bukkit/inventory/EquipmentSlot;Lorg/bukkit/entity/ArmorStand/LockType;)V", + ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + jni::objects::JObject::from_raw(slot.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(lock_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getMemory", + "addEquipmentLock", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(res.l()?)) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the value of the memory specified. - /// - /// Note that the value will not be persisted when the specific entity does - /// not have that value by default. - pub fn set_memory( + /// Remove a {@link LockType locking mechanism}. + pub fn remove_equipment_lock( &self, - memory_key: impl Into>, - memory_value: jni::objects::JObject<'mc>, + slot: impl Into>, + lock_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); + let sig = String::from( + "(Lorg/bukkit/inventory/EquipmentSlot;Lorg/bukkit/entity/ArmorStand/LockType;)V", + ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + jni::objects::JObject::from_raw(slot.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(lock_type.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Object(memory_value); let res = self.jni_ref().call_method( &self.jni_object(), - "setMemory", + "removeEquipmentLock", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), @@ -47630,803 +53694,559 @@ impl<'mc> Monster<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the {@link Sound} this entity will make when damaged. - pub fn hurt_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Get the {@link Sound} this entity will make on death. - pub fn death_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Get the {@link Sound} this entity will make when falling from the given - /// height (in blocks). The sound will often differ between either a small - /// or a big fall damage sound if the height exceeds 4 blocks. - pub fn get_fall_damage_sound( + /// Returns if the ArmorStand has the specified + /// {@link LockType locking mechanism}. + pub fn has_equipment_lock( &self, - fall_height: i32, - ) -> Result, Box> { - let sig = String::from("(I)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Int(fall_height); + slot: impl Into>, + lock_type: impl Into>, + ) -> Result> { + let sig = String::from( + "(Lorg/bukkit/inventory/EquipmentSlot;Lorg/bukkit/entity/ArmorStand/LockType;)Z", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(slot.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(lock_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSound", + "hasEquipmentLock", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Get the {@link Sound} this entity will make when falling from a small - /// height. - pub fn fall_damage_sound_small(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Gets the height of the living entity's eyes above its Location. + pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { + let sig = String::from("(Z)D"); + let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSoundSmall", + "getEyeHeight", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.d()?) } - /// Get the {@link Sound} this entity will make when falling from a large - /// height. - pub fn fall_damage_sound_big(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFallDamageSoundBig", - sig.as_str(), - vec![], - ); + /// Get a Location detailing the current eye position of the living entity. + pub fn eye_location(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { + crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the {@link Sound} this entity will make when drinking the given - /// {@link ItemStack}. - pub fn get_drinking_sound( + /// Gets all blocks along the living entity's line of sight. + /// + /// This list contains all blocks from the living entity's eye position to + /// target inclusive. This method considers all blocks as 1x1x1 in size. + pub fn get_line_of_sight( &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "getDrinkingSound", + "getLineOfSight", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Get the {@link Sound} this entity will make when eating the given - /// {@link ItemStack}. - pub fn get_eating_sound( + /// Gets the block that the living entity has targeted. + /// + /// This method considers all blocks as 1x1x1 in size. To take exact block + /// collision shapes into account, see {@link #getTargetBlockExact(int, + /// FluidCollisionMode)}. + pub fn get_target_block( &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + transparent: impl Into>, + max_distance: i32, + ) -> Result, Box> { + let sig = String::from("(Ljava/util/Set;I)Lorg/bukkit/block/Block;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "getEatingSound", + "getTargetBlock", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { + crate::block::Block::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns true if this entity can breathe underwater and will not take - /// suffocation damage when its air supply reaches zero. - pub fn can_breathe_underwater(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "canBreatheUnderwater", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. - pub fn category( + /// Gets the last two blocks along the living entity's line of sight. + /// + /// The target block will be the last block in the list. This method + /// considers all blocks as 1x1x1 in size. + pub fn get_last_two_target_blocks( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets whether the entity is invisible or not. - pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(invisible.into()); + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvisible", + "getLastTwoTargetBlocks", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether the entity is invisible or not. - pub fn is_invisible(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Gets the specified attribute instance from the object. This instance will - /// be backed directly to the object and any changes will be visible at once. - pub fn get_attribute( + /// Gets the block that the living entity has targeted. + /// + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn get_target_block_exact( &self, - attribute: impl Into>, - ) -> Result>, Box> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); + max_distance: i32, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/block/Block;"; let res = self.jni_ref().call_method( &self.jni_object(), - "getAttribute", + "getTargetBlockExact", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::attribute::AttributeInstance::from_raw( + Ok(Some(crate::block::Block::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Deals the given amount of damage to this entity from a specified - /// {@link DamageSource}. - pub fn damage( + /// Performs a ray trace that provides information on the targeted block. + /// + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn ray_trace_blocks( &self, - amount: f64, - damage_source: std::option::Option>>, - ) -> Result<(), Box> { + max_distance: f64, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "D"; - let val_1 = jni::objects::JValueGen::Double(amount); + let val_1 = jni::objects::JValueGen::Double(max_distance); args.push(val_1); - if let Some(a) = damage_source { - sig += "Lorg/bukkit/damage/DamageSource;"; + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; let val_2 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); args.push(val_2); } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "damage", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. - pub fn health(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); + sig += ")Lorg/bukkit/util/RayTraceResult;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is - /// dead. - pub fn set_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setHealth", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::util::RayTraceResult::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets the entity's absorption amount. - pub fn absorption_amount(&self) -> Result> { - let sig = String::from("()D"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAbsorptionAmount", - sig.as_str(), - vec![], - ); + /// Returns the amount of air that the living entity has remaining, in + /// ticks. + pub fn remaining_air(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.i()?) } - /// Sets the entity's absorption amount. - /// - /// Note: The amount is capped to the value of - /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on - /// that attribute is currently unspecified and subject to change. - pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(amount); + /// Sets the amount of air that the living entity has remaining, in ticks. + pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setAbsorptionAmount", + "setRemainingAir", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the maximum health this entity has. - pub fn max_health(&self) -> Result> { - let sig = String::from("()D"); + /// Returns the maximum amount of air the living entity can have, in ticks. + pub fn maximum_air(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.i()?) } - #[deprecated] - /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. - pub fn set_max_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); + /// Sets the maximum amount of air the living entity can have, in ticks. + pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxHealth", + "setMaximumAir", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Resets the max health to the original amount. - pub fn reset_max_health(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Launches a {@link Projectile} from the ProjectileSource with an - /// initial velocity. - pub fn launch_projectile( - &self, - projectile: jni::objects::JClass<'mc>, - velocity: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/Class;"; - let val_1 = jni::objects::JValueGen::Object(projectile.into()); - args.push(val_1); - if let Some(a) = velocity { - sig += "Lorg/bukkit/util/Vector;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")LT;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Monster<'mc> { - fn into(self) -> crate::entity::Creature<'mc> { - crate::entity::Creature::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Monster into crate::entity::Creature") - } -} -impl<'mc> Into> for Monster<'mc> { - fn into(self) -> crate::entity::Enemy<'mc> { - crate::entity::Enemy::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Monster into crate::entity::Enemy") - } -} -#[repr(C)] -pub struct MushroomCow<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for MushroomCow<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for MushroomCow<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate MushroomCow from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/MushroomCow")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a MushroomCow object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + Ok(()) + } + /// Gets the item that the player is using (eating food, drawing back a bow, + /// blocking, etc.) + pub fn item_in_use( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } -} - -impl<'mc> MushroomCow<'mc> { - /// Checks for the presence of custom potion effects to be applied to the - /// next suspicious stew received from milking this {@link MushroomCow}. - pub fn has_effects_for_next_stew(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the number of ticks remaining for the current item's usage. + pub fn item_in_use_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasEffectsForNextStew", + "getItemInUseTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Gets an immutable list containing all custom potion effects applied to - /// the next suspicious stew received from milking this {@link MushroomCow}. - /// - /// Plugins should check that hasCustomEffects() returns true before calling - /// this method. - pub fn effects_for_next_stew( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + /// Sets the number of ticks that remain for the current item's usage. + /// Applies to items that take time to use, like eating food, drawing a bow, + /// or throwing a trident. + pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "getEffectsForNextStew", + "setItemInUseTicks", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Adds a custom potion effect to be applied to the next suspicious stew - /// received from milking this {@link MushroomCow}. - pub fn add_effect_to_next_stew( - &self, - effect: impl Into>, - overwrite: bool, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffect;Z)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(effect.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Bool(overwrite.into()); + /// Gets the time in ticks until the next arrow leaves the entity's body. + pub fn arrow_cooldown(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "addEffectToNextStew", + "getArrowCooldown", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Removes a custom potion effect from being applied to the next suspicious - /// stew received from milking this {@link MushroomCow}. - pub fn remove_effect_from_next_stew( - &self, - val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Sets the time in ticks until the next arrow leaves the entity's body. + pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "removeEffectFromNextStew", + "setArrowCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the amount of arrows in an entity's body. + pub fn arrows_in_body(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Checks for a specific custom potion effect type to be applied to the next - /// suspicious stew received from milking this {@link MushroomCow}. - pub fn has_effect_for_next_stew( - &self, - val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Set the amount of arrows in the entity's body. + pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(count); let res = self.jni_ref().call_method( &self.jni_object(), - "hasEffectForNextStew", + "setArrowsInBody", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Removes all custom potion effects to be applied to the next suspicious - /// stew received from milking this {@link MushroomCow}. - pub fn clear_effects_for_next_stew(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Returns the living entity's current maximum no damage ticks. + /// + /// This is the maximum duration in which the living entity will not take + /// damage. + pub fn maximum_no_damage_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "clearEffectsForNextStew", + "getMaximumNoDamageTicks", sig.as_str(), vec![], ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the living entity's current maximum no damage ticks. + pub fn set_maximum_no_damage_ticks( + &self, + ticks: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaximumNoDamageTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the variant of this cow. - pub fn variant( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/MushroomCow/Variant;"); + /// Returns the living entity's last damage taken in the current no damage + /// ticks time. + /// + /// Only damage higher than this amount will further damage the living + /// entity. + pub fn last_damage(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::MushroomCowVariant::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.d()?) } - /// Set the variant of this cow. - pub fn set_variant( - &self, - variant: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/MushroomCow/Variant;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(variant.into().jni_object().clone()) - }); + /// Sets the damage dealt within the current no damage ticks time period. + pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(damage); let res = self.jni_ref().call_method( &self.jni_object(), - "setVariant", + "setLastDamage", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for MushroomCow<'mc> { - fn into(self) -> crate::entity::Cow<'mc> { - crate::entity::Cow::from_raw(&self.jni_ref(), self.1) - .expect("Error converting MushroomCow into crate::entity::Cow") - } -} -pub enum MushroomCowVariant<'mc> {} -impl<'mc> std::fmt::Display for MushroomCowVariant<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + /// Returns the living entity's current no damage ticks. + pub fn no_damage_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNoDamageTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} - -impl<'mc> MushroomCowVariant<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/MushroomCow/Variant"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/MushroomCow/Variant;", + /// Sets the living entity's current no damage ticks. + pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setNoDamageTicks", + sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct MushroomCowVariantStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for MushroomCowVariant<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for MushroomCowVariant<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate MushroomCowVariant from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/MushroomCow/Variant")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a MushroomCowVariant object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for MushroomCowVariantStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for MushroomCowVariantStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate MushroomCowVariantStruct from null object." - ) - .into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/MushroomCow/Variant")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a MushroomCowVariantStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> MushroomCowVariantStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/MushroomCow/Variant;"); - let cls = jni.find_class("org/bukkit/entity/MushroomCow/Variant"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::MushroomCowVariant::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + self.jni_ref().translate_error(res)?; + Ok(()) } -} -#[repr(C)] -pub struct CaveSpider<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for CaveSpider<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Get the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn no_action_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNoActionTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Set the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setNoActionTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -impl<'mc> JNIInstantiatable<'mc> for CaveSpider<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate CaveSpider from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/CaveSpider")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a CaveSpider object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + /// Gets the player identified as the killer of the living entity. + /// + /// May be null. + pub fn killer(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some(crate::entity::Player::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } -} - -impl<'mc> CaveSpider<'mc> { - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for CaveSpider<'mc> { - fn into(self) -> crate::entity::Spider<'mc> { - crate::entity::Spider::from_raw(&self.jni_ref(), self.1) - .expect("Error converting CaveSpider into crate::entity::Spider") - } -} -#[repr(C)] -pub struct Hanging<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Hanging<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Hanging<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Hanging from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Hanging")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Hanging object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + #[deprecated] + /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. + pub fn add_potion_effect( + &self, + effect: impl Into>, + force: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/potion/PotionEffect;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = force { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); } + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} - -impl<'mc> Hanging<'mc> { - /// Sets the direction of the hanging entity, potentially overriding rules - /// of placement. Note that if the result is not valid the object would - /// normally drop as an item. - pub fn set_facing_direction( + /// Returns whether the living entity already has an existing effect of + /// the given {@link PotionEffectType} applied to it. + pub fn has_potion_effect( &self, - face: impl Into>, - force: bool, + val_type: impl Into>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;Z)Z"); + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Bool(force.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setFacingDirection", + "hasPotionEffect", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Stores the entity's current position in the provided Location object. + /// Returns the active {@link PotionEffect} of the specified type. /// - /// If the provided Location is null this method does nothing and returns - /// null. - pub fn get_location( + /// If the effect is not present on the entity then null will be returned. + pub fn get_potion_effect( &self, - loc: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + val_type: impl Into>, + ) -> Result>, Box> { + let sig = + String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocation", + "getPotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -48434,635 +54254,541 @@ impl<'mc> Hanging<'mc> { if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(Some(crate::potion::PotionEffect::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets this entity's velocity in meters per tick - pub fn set_velocity( + /// Removes any effects present of the given {@link PotionEffectType}. + pub fn remove_potion_effect( &self, - velocity: impl Into>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVelocity", + "removePotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets this entity's current velocity - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the entity's height - pub fn height(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the entity's width - pub fn width(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the entity's current bounding box. - /// - /// The returned bounding box reflects the entity's current location and - /// size. - pub fn bounding_box( + /// Returns all currently active {@link PotionEffect}s on the living + /// entity. + pub fn active_potion_effects( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns true if the entity is supported by a block. This value is a - /// state updated by the server and is not recalculated unless the entity - /// moves. - pub fn is_on_ground(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns true if the entity is in water. - pub fn is_in_water(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the current world this entity resides in - pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the entity's rotation. - /// - /// Note that if the entity is affected by AI, it may override this rotation. - pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { - let sig = String::from("(FF)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); - let val_2 = jni::objects::JValueGen::Float(pitch); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setRotation", + "getActivePotionEffects", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Teleports this entity to the given location. If this entity is riding a - /// vehicle, it will be dismounted prior to teleportation. - pub fn teleport( + /// Checks whether the living entity has block line of sight to another. + /// + /// This uses the same algorithm that hostile mobs use to find the closest + /// player. + pub fn has_line_of_sight( &self, - location: impl Into>, - cause: std::option::Option< - impl Into>, - >, + other: impl Into>, ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) + jni::objects::JObject::from_raw(other.into().jni_object().clone()) }); - args.push(val_1); - if let Some(a) = cause { - sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "teleport", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns a list of entities within a bounding box centered around this - /// entity - pub fn get_nearby_entities( - &self, - x: f64, - y: f64, - z: f64, - ) -> Result>, Box> { - let sig = String::from("(DDD)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Double(x); - let val_2 = jni::objects::JValueGen::Double(y); - let val_3 = jni::objects::JValueGen::Double(z); let res = self.jni_ref().call_method( &self.jni_object(), - "getNearbyEntities", + "hasLineOfSight", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Returns a unique id for this entity - pub fn entity_id(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn fire_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the entity's maximum fire ticks. - pub fn max_fire_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Returns if the living entity despawns when away from players or not. + /// + /// By default, animals are not removed while other mobs are. + pub fn remove_when_far_away(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "setFireTicks", + "getRemoveWhenFarAway", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Sets if the entity has visual fire (it will always appear to be on fire). - pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { + /// Sets whether or not the living entity despawns when away from players + /// or not. + pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire.into()); + let val_1 = jni::objects::JValueGen::Bool(remove.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisualFire", + "setRemoveWhenFarAway", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity has visual fire (it will always appear to be on fire). - pub fn is_visual_fire(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the inventory with the equipment worn by the living entity. + pub fn equipment( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::EntityEquipment::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Returns the entity's maximum freeze ticks (amount of ticks before it will - /// be fully frozen) - pub fn max_freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Sets whether or not the living entity can pick up items. + pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(pickup.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getMaxFreezeTicks", + "setCanPickupItems", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Gets if the living entity can pick up items. + pub fn can_pickup_items(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "setFreezeTicks", + "getCanPickupItems", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets if the entity is fully frozen (it has been in powdered snow for max - /// freeze ticks). - pub fn is_frozen(&self) -> Result> { + /// Returns whether the entity is currently leashed. + pub fn is_leashed(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Mark the entity's removal. - pub fn remove(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Gets the entity that is currently leading this entity. + pub fn leash_holder(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns true if this entity has been marked for removal. - pub fn is_dead(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); + /// Sets the leash on this entity to be held by the supplied entity. + /// + /// This method has no effect on EnderDragons, Withers, Players, or Bats. + /// Non-living entities excluding leashes will not persist as leash + /// holders. + pub fn set_leash_holder( + &self, + holder: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(holder.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLeashHolder", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns false if the entity has died, been despawned for some other - /// reason, or has not been added to the world. - pub fn is_valid(&self) -> Result> { + /// Checks to see if an entity is gliding, such as using an Elytra. + pub fn is_gliding(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the {@link Server} that contains this Entity - pub fn server(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Server;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Server::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Makes entity start or stop gliding. This will work even if an Elytra + /// is not equipped, but will be reverted by the server immediately after + /// unless an event-cancelling mechanism is put in place. + pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gliding.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setGliding", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns true if the entity gets persisted. - /// - /// By default all entities are persistent. An entity will also not get - /// persisted, if it is riding an entity that is not persistent. - /// - /// The persistent flag on players controls whether or not to save their - /// playerdata file when they quit. If a player is directly or indirectly - /// riding a non-persistent entity, the vehicle at the root and all its - /// passengers won't get persisted. - /// - /// This should not be confused with - /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls - /// despawning of living entities. - pub fn is_persistent(&self) -> Result> { + /// Checks to see if an entity is swimming. + pub fn is_swimming(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not the entity gets persisted. - pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { + /// Makes entity start or stop swimming. + /// This may have unexpected results if the entity is not in water. + pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(persistent.into()); + let val_1 = jni::objects::JValueGen::Bool(swimming.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setPersistent", + "setSwimming", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. - pub fn passenger( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + /// Checks to see if an entity is currently riptiding. + pub fn is_riptiding(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - #[deprecated] - /// Set the passenger of a vehicle. - pub fn set_passenger( - &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); + /// Makes entity start or stop riptiding. + /// + /// Note: This does not damage attackable entities. + pub fn set_riptiding(&self, riptiding: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(riptiding.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setPassenger", + "setRiptiding", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns whether this entity is slumbering. + pub fn is_sleeping(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets a list of passengers of this vehicle. - /// - /// The returned list will not be directly linked to the entity's current - /// passengers, and no guarantees are made as to its mutability. - pub fn passengers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + /// Gets if the entity is climbing. + pub fn is_climbing(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(res.z()?) } - /// Add a passenger to the vehicle. - pub fn add_passenger( - &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); + /// Sets whether an entity will have AI. + /// The entity will be completely unable to move if it has no AI. + pub fn set_ai(&self, ai: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(ai.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "addPassenger", + "setAI", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks whether an entity has AI. + /// The entity will be completely unable to move if it has no AI. + pub fn has_ai(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Remove a passenger from the vehicle. - pub fn remove_passenger( + /// Makes this entity attack the given entity with a melee attack. + /// Attack damage is calculated by the server from the attributes and + /// equipment of this mob, and knockback is applied to {@code target} as + /// appropriate. + pub fn attack( &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + target: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(target.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removePassenger", + "attack", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Check if a vehicle has passengers. - pub fn is_empty(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Eject any passenger. - pub fn eject(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Makes this entity swing their main hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their main hand. + pub fn swing_main_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns the distance this entity has fallen - pub fn fall_distance(&self) -> Result> { - let sig = String::from("()F"); + /// Makes this entity swing their off hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their off hand. + pub fn swing_off_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the fall distance for this entity - pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { + /// Makes this entity flash red as if they were damaged. + pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(distance); + let val_1 = jni::objects::JValueGen::Float(yaw); let res = self.jni_ref().call_method( &self.jni_object(), - "setFallDistance", + "playHurtAnimation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Record the last {@link EntityDamageEvent} inflicted on this entity - pub fn set_last_damage_cause( - &self, - event: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(event.into().jni_object().clone()) - }); + /// Set if this entity will be subject to collisions with other entities. + /// + /// Exemptions to this rule can be managed with + /// {@link #getCollidableExemptions()} + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not working for player collisions. This + /// method should therefore only be used to set the collision status of + /// non-player entities. + /// + /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in + /// combination with a {@link Scoreboard} and a {@link Team}. + pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(collidable.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDamageCause", + "setCollidable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. - /// This event may have been cancelled. - pub fn last_damage_cause( + /// Gets if this entity is subject to collisions with other entities. + /// + /// Some entities might be exempted from the collidable rule of this entity. + /// Use {@link #getCollidableExemptions()} to get these. + /// + /// Please note that this method returns only the custom collidable state, + /// not whether the entity is non-collidable for other reasons such as being + /// dead. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not being accurate for player collisions. + /// This method should therefore only be used to check the collision status + /// of non-player entities. + /// + /// To check the collision behavior for a player, use + /// {@link Team.Option#COLLISION_RULE} in combination with a + /// {@link Scoreboard} and a {@link Team}. + pub fn is_collidable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets a mutable set of UUIDs of the entities which are exempt from the + /// entity's collidable rule and which's collision with this entity will + /// behave the opposite of it. + /// + /// This set can be modified to add or remove exemptions. + /// + /// For example if collidable is true and an entity is in the exemptions set + /// then it will not collide with it. Similarly if collidable is false and an + /// entity is in this set then it will still collide with it. + /// + /// Note these exemptions are not (currently) persistent. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in those exemptions not being accurate for player + /// collisions. This method should therefore only be used to exempt + /// non-player entities. + /// + /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} + /// in combination with a {@link Scoreboard} and a {@link Team}. + pub fn collidable_exemptions( &self, - ) -> Result>, Box> - { - let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLastDamageCause", + "getCollidableExemptions", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Returns a unique and persistent id for this entity - pub fn unique_id( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. - pub fn ticks_lived(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the amount of ticks this entity has lived for. + /// Returns the value of the memory specified. /// - /// This is the equivalent to "age" in entities. May not be less than one - /// tick. - pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(value); + /// Note that the value is null when the specific entity does not have that + /// value by default. + pub fn get_memory( + &self, + memory_key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setTicksLived", + "getMemory", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) } - /// Performs the specified {@link EntityEffect} for this entity. - /// - /// This will be viewable to all players near the entity. + /// Sets the value of the memory specified. /// - /// If the effect is not applicable to this class of entity, it will not play. - pub fn play_effect( + /// Note that the value will not be persisted when the specific entity does + /// not have that value by default. + pub fn set_memory( &self, - val_type: impl Into>, + memory_key: impl Into>, + memory_value: jni::objects::JObject<'mc>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Object(memory_value); let res = self.jni_ref().call_method( &self.jni_object(), - "playEffect", + "setMemory", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the type of the entity. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + /// Get the {@link Sound} this entity will make when damaged. + pub fn hurt_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) + })?)) } - /// Get the {@link Sound} this entity makes while swimming. - pub fn swim_sound(&self) -> Result, Box> { + /// Get the {@link Sound} this entity will make on death. + pub fn death_sound(&self) -> Result>, Box> { let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Get the {@link Sound} this entity will make when falling from the given + /// height (in blocks). The sound will often differ between either a small + /// or a big fall damage sound if the height exceeds 4 blocks. + pub fn get_fall_damage_sound( + &self, + fall_height: i32, + ) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Int(fall_height); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getFallDamageSound", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the {@link Sound} this entity makes when splashing in water. For most - /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_splash_sound(&self) -> Result, Box> { + /// Get the {@link Sound} this entity will make when falling from a small + /// height. + pub fn fall_damage_sound_small(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimSplashSound", + "getFallDamageSoundSmall", sig.as_str(), vec![], ); @@ -49071,15 +54797,13 @@ impl<'mc> Hanging<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the {@link Sound} this entity makes when splashing in water at high - /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_high_speed_splash_sound( - &self, - ) -> Result, Box> { + /// Get the {@link Sound} this entity will make when falling from a large + /// height. + pub fn fall_damage_sound_big(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimHighSpeedSplashSound", + "getFallDamageSoundBig", sig.as_str(), vec![], ); @@ -49088,1739 +54812,2223 @@ impl<'mc> Hanging<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns whether this entity is inside a vehicle. - pub fn is_inside_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Leave the current vehicle. If the entity is currently in a vehicle (and - /// is removed from it), true will be returned, otherwise false will be - /// returned. - pub fn leave_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the vehicle that this entity is inside. If there is no vehicle, - /// null will be returned. - pub fn vehicle( + /// Get the {@link Sound} this entity will make when drinking the given + /// {@link ItemStack}. + pub fn get_drinking_sound( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Sets whether or not to display the mob's custom name client side. The - /// name will be displayed above the mob similarly to a player. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomNameVisible", + "getDrinkingSound", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether or not the mob's custom name is displayed client side. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn is_custom_name_visible(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isCustomNameVisible", - sig.as_str(), - vec![], - ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(visible.into()); + /// Get the {@link Sound} this entity will make when eating the given + /// {@link ItemStack}. + pub fn get_eating_sound( + &self, + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisibleByDefault", + "getEatingSound", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn is_visible_by_default(&self) -> Result> { + /// Returns true if this entity can breathe underwater and will not take + /// suffocation damage when its air supply reaches zero. + pub fn can_breathe_underwater(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "isVisibleByDefault", + "canBreatheUnderwater", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get all players that are currently tracking this entity. - /// - /// 'Tracking' means that this entity has been sent to the player and that - /// they are receiving updates on its state. Note that the client's {@code - /// 'Entity Distance'} setting does not affect the range at which entities - /// are tracked. - pub fn tracked_by( + #[deprecated] + /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. + pub fn category( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets whether the entity has a team colored (default: white) glow. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { + /// Sets whether the entity is invisible or not. + pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(invisible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setGlowing", + "setInvisible", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is glowing or not. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn is_glowing(&self) -> Result> { + /// Gets whether the entity is invisible or not. + pub fn is_invisible(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the entity is invulnerable or not. - /// - /// When an entity is invulnerable it can only be damaged by players in - /// creative mode. - pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Gets the specified attribute instance from the object. This instance will + /// be backed directly to the object and any changes will be visible at once. + pub fn get_attribute( + &self, + attribute: impl Into>, + ) -> Result>, Box> { + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvulnerable", + "getAttribute", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether the entity is invulnerable or not. - pub fn is_invulnerable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::attribute::AttributeInstance::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets whether the entity is silent or not. - pub fn is_silent(&self) -> Result> { - let sig = String::from("()Z"); + /// Deals the given amount of damage to this entity from a specified + /// {@link DamageSource}. + pub fn damage( + &self, + amount: f64, + damage_source: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(amount); + args.push(val_1); + if let Some(a) = damage_source { + sig += "Lorg/bukkit/damage/DamageSource;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether the entity is silent or not. - /// - /// When an entity is silent it will not produce any sound. - pub fn set_silent(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSilent", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "damage", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether gravity applies to this entity. - pub fn has_gravity(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); + /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. + pub fn health(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Sets whether gravity applies to this entity. - pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gravity.into()); + /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is + /// dead. + pub fn set_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "setGravity", + "setHealth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the period of time (in ticks) before this entity can use a portal. - pub fn portal_cooldown(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the entity's absorption amount. + pub fn absorption_amount(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPortalCooldown", + "getAbsorptionAmount", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.d()?) } - /// Sets the period of time (in ticks) before this entity can use a portal. - pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(cooldown); + /// Sets the entity's absorption amount. + /// + /// Note: The amount is capped to the value of + /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on + /// that attribute is currently unspecified and subject to change. + pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "setPortalCooldown", + "setAbsorptionAmount", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a set of tags for this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn scoreboard_tags( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getScoreboardTags", - sig.as_str(), - vec![], - ); + #[deprecated] + /// Gets the maximum health this entity has. + pub fn max_health(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.d()?) } - /// Add a tag to this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn add_scoreboard_tag( - &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); + #[deprecated] + /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. + pub fn set_max_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "addScoreboardTag", + "setMaxHealth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Removes a given tag from this entity. - pub fn remove_scoreboard_tag( + #[deprecated] + /// Resets the max health to the original amount. + pub fn reset_max_health(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Launches a {@link Projectile} from the ProjectileSource with an + /// initial velocity. + pub fn launch_projectile( &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removeScoreboardTag", - sig.as_str(), + projectile: jni::objects::JClass<'mc>, + velocity: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(projectile.into()); + args.push(val_1); + if let Some(a) = velocity { + sig += "Lorg/bukkit/util/Vector;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")LT;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for ArmorStand<'mc> { + fn into(self) -> crate::entity::LivingEntity<'mc> { + crate::entity::LivingEntity::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ArmorStand into crate::entity::LivingEntity") + } +} +pub enum ArmorStandLockType<'mc> { + AddingOrChanging { + inner: ArmorStandLockTypeStruct<'mc>, + }, + RemovingOrChanging { + inner: ArmorStandLockTypeStruct<'mc>, + }, + Adding { + inner: ArmorStandLockTypeStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for ArmorStandLockType<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ArmorStandLockType::AddingOrChanging { .. } => f.write_str("ADDING_OR_CHANGING"), + ArmorStandLockType::RemovingOrChanging { .. } => f.write_str("REMOVING_OR_CHANGING"), + ArmorStandLockType::Adding { .. } => f.write_str("ADDING"), + } + } +} +impl<'mc> std::ops::Deref for ArmorStandLockType<'mc> { + type Target = ArmorStandLockTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + ArmorStandLockType::AddingOrChanging { inner } => inner, + ArmorStandLockType::RemovingOrChanging { inner } => inner, + ArmorStandLockType::Adding { inner } => inner, + } + } +} + +impl<'mc> ArmorStandLockType<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/ArmorStand/LockType"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/ArmorStand/LockType;", vec![jni::objects::JValueGen::from(val_1)], ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "ADDING_OR_CHANGING" => Ok(ArmorStandLockType::AddingOrChanging { + inner: ArmorStandLockTypeStruct::from_raw(env, obj)?, + }), + "REMOVING_OR_CHANGING" => Ok(ArmorStandLockType::RemovingOrChanging { + inner: ArmorStandLockTypeStruct::from_raw(env, obj)?, + }), + "ADDING" => Ok(ArmorStandLockType::Adding { + inner: ArmorStandLockTypeStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct ArmorStandLockTypeStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ArmorStandLockType<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::AddingOrChanging { inner } => inner.0.clone(), + Self::RemovingOrChanging { inner } => inner.0.clone(), + Self::Adding { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::AddingOrChanging { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RemovingOrChanging { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Adding { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for ArmorStandLockType<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate ArmorStandLockType from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ArmorStand/LockType")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ArmorStandLockType object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "ADDING_OR_CHANGING" => Ok(ArmorStandLockType::AddingOrChanging { + inner: ArmorStandLockTypeStruct::from_raw(env, obj)?, + }), + "REMOVING_OR_CHANGING" => Ok(ArmorStandLockType::RemovingOrChanging { + inner: ArmorStandLockTypeStruct::from_raw(env, obj)?, + }), + "ADDING" => Ok(ArmorStandLockType::Adding { + inner: ArmorStandLockTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for ArmorStandLockTypeStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for ArmorStandLockTypeStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate ArmorStandLockTypeStruct from null object." + ) + .into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ArmorStand/LockType")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ArmorStandLockTypeStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> ArmorStandLockTypeStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/ArmorStand/LockType;"); + let cls = jni.find_class("org/bukkit/entity/ArmorStand/LockType"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::ArmorStandLockType::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct Shearable<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Shearable<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Shearable<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Shearable from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Shearable")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Shearable object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Shearable<'mc> { + /// Gets whether the entity is in its sheared state. + pub fn is_sheared(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSheared", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns the reaction of the entity when moved by a piston. - pub fn piston_move_reaction( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + /// Sets whether the entity is in its sheared state. + pub fn set_sheared(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getPistonMoveReaction", + "setSheared", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the closest cardinal {@link BlockFace} direction an entity is - /// currently facing. - /// - /// This will not return any non-cardinal directions such as - /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. - /// - /// {@link Hanging} entities will override this call and thus their behavior - /// may be different. - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Gets the entity's current pose. - /// Note that the pose is only updated at the end of a tick, so may be - /// inconsistent with other methods. eg {@link Player#isSneaking()} being - /// true does not imply the current pose will be {@link Pose#SNEAKING} - pub fn pose(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Pose;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} +#[repr(C)] +pub struct Creature<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Creature<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Get the category of spawn to which this entity belongs. - pub fn spawn_category( + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Creature<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Creature from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Creature")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Creature object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Creature<'mc> { + /// Instructs this Mob to set the specified LivingEntity as its target. + /// + /// Hostile creatures may attack their target, and friendly creatures may + /// follow their target. + pub fn set_target( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); + target: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(target.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getSpawnCategory", + "setTarget", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Checks if this entity has been spawned in a world. - /// - /// Entities not spawned in a world will not tick, be sent to players, or be - /// saved to the server files. - pub fn is_in_world(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the current target of this Mob + pub fn target( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get this entity as an NBT string. - /// - /// This string should not be relied upon as a serializable value. - pub fn as_string(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTarget", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(Some(crate::entity::LivingEntity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets whether this mob is aware of its surroundings. + /// Unaware mobs will still move if pushed, attacked, etc. but will not move + /// or perform any actions on their own. Unaware mobs may also have other + /// unspecified behaviours disabled, such as drowning. + pub fn set_aware(&self, aware: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(aware.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAware", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether this mob is aware of its surroundings. + /// Unaware mobs will still move if pushed, attacked, etc. but will not move + /// or perform any actions on their own. Unaware mobs may also have other + /// unspecified behaviours disabled, such as drowning. + pub fn is_aware(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isAware", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Crates an {@link EntitySnapshot} representing the current state of this entity. - pub fn create_snapshot( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + /// Get the {@link Sound} this mob makes while ambiently existing. This sound + /// may change depending on the current state of the entity, and may also + /// return null under specific conditions. This sound is not constant. + /// For instance, villagers will make different passive noises depending + /// on whether or not they are actively trading with a player, or make no + /// ambient noise while sleeping. + pub fn ambient_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAmbientSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::EntitySnapshot::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Creates a copy of this entity and all its data. Spawns the copy at the given location. - /// - /// Note: Players cannot be copied. - pub fn copy( - &self, - to: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = to { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Creature<'mc> { + fn into(self) -> crate::entity::Mob<'mc> { + crate::entity::Mob::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Creature into crate::entity::Mob") + } +} +#[repr(C)] +pub struct Breeze<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Breeze<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Breeze<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Breeze from null object.").into()); } - sig += ")Lorg/bukkit/entity/Entity;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Breeze")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Breeze object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Breeze<'mc> { + /// Gets the height of the living entity's eyes above its Location. + pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { + let sig = String::from("(Z)D"); + let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getEyeHeight", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + Ok(res.d()?) + } + /// Get a Location detailing the current eye position of the living entity. + pub fn eye_location(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets a metadata value in the implementing object's metadata store. - pub fn set_metadata( + /// Gets all blocks along the living entity's line of sight. + /// + /// This list contains all blocks from the living entity's eye position to + /// target inclusive. This method considers all blocks as 1x1x1 in size. + pub fn get_line_of_sight( &self, - metadata_key: impl Into, - new_metadata_value: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setMetadata", + "getLineOfSight", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), ], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns a list of previously set metadata values from the implementing - /// object's metadata store. - pub fn get_metadata( - &self, - metadata_key: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMetadata", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::metadata::MetadataValue::from_raw( - &self.jni_ref(), - obj, - )?); + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); } Ok(new_vec) } - /// Tests to see whether the implementing object contains the given - /// metadata value in its metadata store. - pub fn has_metadata( + /// Gets the block that the living entity has targeted. + /// + /// This method considers all blocks as 1x1x1 in size. To take exact block + /// collision shapes into account, see {@link #getTargetBlockExact(int, + /// FluidCollisionMode)}. + pub fn get_target_block( &self, - metadata_key: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); + transparent: impl Into>, + max_distance: i32, + ) -> Result, Box> { + let sig = String::from("(Ljava/util/Set;I)Lorg/bukkit/block/Block;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "hasMetadata", + "getTargetBlock", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Removes the given metadata value from the implementing object's - /// metadata store. - pub fn remove_metadata( + /// Gets the last two blocks along the living entity's line of sight. + /// + /// The target block will be the last block in the list. This method + /// considers all blocks as 1x1x1 in size. + pub fn get_last_two_target_blocks( &self, - metadata_key: impl Into, - owning_plugin: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "removeMetadata", + "getLastTwoTargetBlocks", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Sends this sender multiple messages - pub fn send_message( + /// Gets the block that the living entity has targeted. + /// + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn get_target_block_exact( &self, - sender: impl Into>, - messages: std::option::Option>, - ) -> Result<(), Box> { + max_distance: i32, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) - }); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(max_distance); args.push(val_1); - if let Some(a) = messages { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); args.push(val_2); } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the name of this command sender - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + sig += ")Lorg/bukkit/block/Block;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTargetBlockExact", + sig.as_str(), + args, + ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::block::Block::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets the custom name on a mob or block. If there is no name this method - /// will return null. + /// Performs a ray trace that provides information on the targeted block. /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn custom_name(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn ray_trace_blocks( + &self, + max_distance: f64, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/util/RayTraceResult;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getCustomName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some( + Ok(Some(crate::util::RayTraceResult::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Returns the amount of air that the living entity has remaining, in + /// ticks. + pub fn remaining_air(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Sets a custom name on a mob or block. This name will be used in death - /// messages and can be sent to the client as a nameplate over the mob. - /// - /// Setting the name to null or an empty string will clear it. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn set_custom_name( - &self, - name: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + /// Sets the amount of air that the living entity has remaining, in ticks. + pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomName", + "setRemainingAir", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + /// Returns the maximum amount of air the living entity can have, in ticks. + pub fn maximum_air(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the maximum amount of air the living entity can have, in ticks. + pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "setMaximumAir", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the face that this block is attached on - pub fn attached_face( + /// Gets the item that the player is using (eating food, drawing back a bow, + /// blocking, etc.) + pub fn item_in_use( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAttachedFace", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Hanging<'mc> { - fn into(self) -> crate::entity::Entity<'mc> { - crate::entity::Entity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Hanging into crate::entity::Entity") + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } -} -impl<'mc> Into> for Hanging<'mc> { - fn into(self) -> crate::material::Attachable<'mc> { - crate::material::Attachable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Hanging into crate::material::Attachable") + /// Gets the number of ticks remaining for the current item's usage. + pub fn item_in_use_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItemInUseTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} -#[repr(C)] -pub struct Ageable<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Ageable<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Sets the number of ticks that remain for the current item's usage. + /// Applies to items that take time to use, like eating food, drawing a bow, + /// or throwing a trident. + pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItemInUseTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets the time in ticks until the next arrow leaves the entity's body. + pub fn arrow_cooldown(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getArrowCooldown", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} -impl<'mc> JNIInstantiatable<'mc> for Ageable<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Ageable from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Ageable")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Ageable object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Sets the time in ticks until the next arrow leaves the entity's body. + pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setArrowCooldown", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> Ageable<'mc> { - /// Gets the age of this mob. - pub fn age(&self) -> Result> { + /// Gets the amount of arrows in an entity's body. + pub fn arrows_in_body(&self) -> Result> { let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getAge", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the age of this mob. - pub fn set_age(&self, age: i32) -> Result<(), Box> { + /// Set the amount of arrows in the entity's body. + pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(age); + let val_1 = jni::objects::JValueGen::Int(count); let res = self.jni_ref().call_method( &self.jni_object(), - "setAge", + "setArrowsInBody", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Lock the age of the animal, setting this will prevent the animal from maturing or getting ready for mating. - pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(lock.into()); + /// Returns the living entity's current maximum no damage ticks. + /// + /// This is the maximum duration in which the living entity will not take + /// damage. + pub fn maximum_no_damage_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "setAgeLock", + "getMaximumNoDamageTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the living entity's current maximum no damage ticks. + pub fn set_maximum_no_damage_ticks( + &self, + ticks: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaximumNoDamageTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the current agelock. - pub fn age_lock(&self) -> Result> { - let sig = String::from("()Z"); + /// Returns the living entity's last damage taken in the current no damage + /// ticks time. + /// + /// Only damage higher than this amount will further damage the living + /// entity. + pub fn last_damage(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Sets the age of the mob to a baby - pub fn set_baby(&self) -> Result<(), Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setBaby", sig.as_str(), args); + /// Sets the damage dealt within the current no damage ticks time period. + pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(damage); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLastDamage", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets the age of the mob to an adult - pub fn set_adult(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setAdult", sig.as_str(), vec![]); + /// Returns the living entity's current no damage ticks. + pub fn no_damage_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNoDamageTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the living entity's current no damage ticks. + pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setNoDamageTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns true if the mob is an adult. - pub fn is_adult(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isAdult", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Return the ability to breed of the animal. - pub fn can_breed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); + /// Get the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn no_action_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNoActionTicks", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - #[deprecated] - /// Set breedability of the animal, if the animal is a baby and set to breed it will instantly grow up. - pub fn set_breed(&self, breed: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(breed.into()); + /// Set the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreed", + "setNoActionTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Ageable<'mc> { - fn into(self) -> crate::entity::Creature<'mc> { - crate::entity::Creature::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Ageable into crate::entity::Creature") - } -} -#[repr(C)] -pub struct Tameable<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Tameable<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Tameable<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Tameable from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Tameable")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Tameable object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Tameable<'mc> { - /// Check if this is tamed + /// Gets the player identified as the killer of the living entity. /// - /// If something is tamed then a player can not tame it through normal - /// methods, even if it does not belong to anyone in particular. - pub fn is_tamed(&self) -> Result> { - let sig = String::from("()Z"); + /// May be null. + pub fn killer(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isTamed", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Player::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + #[deprecated] + /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. + pub fn add_potion_effect( + &self, + effect: impl Into>, + force: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/potion/PotionEffect;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = force { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets if this has been tamed. Not necessary if the method setOwner has - /// been used, as it tames automatically. - /// - /// If something is tamed then a player can not tame it through normal - /// methods, even if it does not belong to anyone in particular. - pub fn set_tamed(&self, tame: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(tame.into()); + /// Returns whether the living entity already has an existing effect of + /// the given {@link PotionEffectType} applied to it. + pub fn has_potion_effect( + &self, + val_type: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setTamed", + "hasPotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the current owning AnimalTamer - pub fn owner( + /// Returns the active {@link PotionEffect} of the specified type. + /// + /// If the effect is not present on the entity then null will be returned. + pub fn get_potion_effect( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/AnimalTamer;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); + val_type: impl Into>, + ) -> Result>, Box> { + let sig = + String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPotionEffect", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::AnimalTamer::from_raw( + Ok(Some(crate::potion::PotionEffect::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Set this to be owned by given AnimalTamer. - /// - /// If the owner is not null, this will be tamed and will have any current - /// path it is following removed. If the owner is set to null, this will be - /// untamed, and the current owner removed. - pub fn set_owner( + /// Removes any effects present of the given {@link PotionEffectType}. + pub fn remove_potion_effect( &self, - tamer: impl Into>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/AnimalTamer;)V"); + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tamer.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setOwner", + "removePotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn breed_cause( + /// Returns all currently active {@link PotionEffect}s on the living + /// entity. + pub fn active_potion_effects( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/UUID;"); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getActivePotionEffects", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Checks whether the living entity has block line of sight to another. + /// + /// This uses the same algorithm that hostile mobs use to find the closest + /// player. + pub fn has_line_of_sight( + &self, + other: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(other.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasLineOfSight", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns if the living entity despawns when away from players or not. + /// + /// By default, animals are not removed while other mobs are. + pub fn remove_when_far_away(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getRemoveWhenFarAway", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether or not the living entity despawns when away from players + /// or not. + pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(remove.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRemoveWhenFarAway", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the inventory with the equipment worn by the living entity. + pub fn equipment( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( + Ok(Some(crate::inventory::EntityEquipment::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Set the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn set_breed_cause( - &self, - uuid: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/UUID;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) - }); + /// Sets whether or not the living entity can pick up items. + pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(pickup.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreedCause", + "setCanPickupItems", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get whether or not this entity is in love mode and will produce - /// offspring with another entity in love mode. Will return true if - /// and only if {@link #getLoveModeTicks()} is greater than 0. - pub fn is_love_mode(&self) -> Result> { + /// Gets if the living entity can pick up items. + pub fn can_pickup_items(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCanPickupItems", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns whether the entity is currently leashed. + pub fn is_leashed(&self) -> Result> { let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the entity that is currently leading this entity. + pub fn leash_holder(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get the amount of ticks remaining for this entity in love mode. - /// If the entity is not in love mode, 0 will be returned. - pub fn love_mode_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Sets the leash on this entity to be held by the supplied entity. + /// + /// This method has no effect on EnderDragons, Withers, Players, or Bats. + /// Non-living entities excluding leashes will not persist as leash + /// holders. + pub fn set_leash_holder( + &self, + holder: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(holder.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getLoveModeTicks", + "setLeashHolder", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the amount of ticks for which this entity should be in love mode. - /// Setting the love mode ticks to 600 is the equivalent of a player - /// feeding the entity their breeding item of choice. - pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Checks to see if an entity is gliding, such as using an Elytra. + pub fn is_gliding(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Makes entity start or stop gliding. This will work even if an Elytra + /// is not equipped, but will be reverted by the server immediately after + /// unless an event-cancelling mechanism is put in place. + pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gliding.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setGliding", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks to see if an entity is swimming. + pub fn is_swimming(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Makes entity start or stop swimming. + /// This may have unexpected results if the entity is not in water. + pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(swimming.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLoveModeTicks", + "setSwimming", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check if the provided ItemStack is the correct item used for breeding - /// this entity.. - pub fn is_breed_item( - &self, - material: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); + /// Checks to see if an entity is currently riptiding. + pub fn is_riptiding(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Lock the age of the animal, setting this will prevent the animal from - /// maturing or getting ready for mating. - pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { + /// Makes entity start or stop riptiding. + /// + /// Note: This does not damage attackable entities. + pub fn set_riptiding(&self, riptiding: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(lock.into()); + let val_1 = jni::objects::JValueGen::Bool(riptiding.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setAgeLock", + "setRiptiding", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the current agelock. - pub fn age_lock(&self) -> Result> { + /// Returns whether this entity is slumbering. + pub fn is_sleeping(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Return the ability to breed of the animal. - pub fn can_breed(&self) -> Result> { + /// Gets if the entity is climbing. + pub fn is_climbing(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set breedability of the animal, if the animal is a baby and set to - /// breed it will instantly grow up. - pub fn set_breed(&self, breed: bool) -> Result<(), Box> { + /// Sets whether an entity will have AI. + /// The entity will be completely unable to move if it has no AI. + pub fn set_ai(&self, ai: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(breed.into()); + let val_1 = jni::objects::JValueGen::Bool(ai.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreed", + "setAI", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Tameable<'mc> { - fn into(self) -> crate::entity::Animals<'mc> { - crate::entity::Animals::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Tameable into crate::entity::Animals") - } -} -#[repr(C)] -pub struct Illusioner<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Illusioner<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Illusioner<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Illusioner from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Illusioner")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Illusioner object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Illusioner<'mc> { - /// Gets the {@link Spell} the entity is currently using. - pub fn spell( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Spellcaster/Spell;"); + /// Checks whether an entity has AI. + /// The entity will be completely unable to move if it has no AI. + pub fn has_ai(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getSpell", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::SpellcasterSpell::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets the {@link Spell} the entity is currently using. - pub fn set_spell( + /// Makes this entity attack the given entity with a melee attack. + /// Attack damage is calculated by the server from the attributes and + /// equipment of this mob, and knockback is applied to {@code target} as + /// appropriate. + pub fn attack( &self, - spell: impl Into>, + target: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Spellcaster/Spell;)V"); + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(spell.into().jni_object().clone()) + jni::objects::JObject::from_raw(target.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setSpell", + "attack", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Illusioner<'mc> { - fn into(self) -> crate::entity::Spellcaster<'mc> { - crate::entity::Spellcaster::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Illusioner into crate::entity::Spellcaster") - } -} -#[repr(C)] -pub struct Display<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Display<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Display<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Display from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Display")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Display object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Makes this entity swing their main hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their main hand. + pub fn swing_main_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> Display<'mc> { - /// Gets the transformation applied to this display. - pub fn transformation( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Transformation;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTransformation", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::util::Transformation::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Makes this entity swing their off hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their off hand. + pub fn swing_off_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the transformation applied to this display - pub fn set_transformation( - &self, - transformation: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Transformation;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transformation.into().jni_object().clone()) - }); + /// Makes this entity flash red as if they were damaged. + pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); let res = self.jni_ref().call_method( &self.jni_object(), - "setTransformation", + "playHurtAnimation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets the raw transformation matrix applied to this display - pub fn set_transformation_matrix( - &self, - transformation_matrix: jni::objects::JObject<'mc>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/joml/Matrix4f;)V"); - let val_1 = jni::objects::JValueGen::Object(transformation_matrix); + /// Set if this entity will be subject to collisions with other entities. + /// + /// Exemptions to this rule can be managed with + /// {@link #getCollidableExemptions()} + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not working for player collisions. This + /// method should therefore only be used to set the collision status of + /// non-player entities. + /// + /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in + /// combination with a {@link Scoreboard} and a {@link Team}. + pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(collidable.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setTransformationMatrix", + "setCollidable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the interpolation duration of this display. - pub fn interpolation_duration(&self) -> Result> { - let sig = String::from("()I"); + /// Gets if this entity is subject to collisions with other entities. + /// + /// Some entities might be exempted from the collidable rule of this entity. + /// Use {@link #getCollidableExemptions()} to get these. + /// + /// Please note that this method returns only the custom collidable state, + /// not whether the entity is non-collidable for other reasons such as being + /// dead. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not being accurate for player collisions. + /// This method should therefore only be used to check the collision status + /// of non-player entities. + /// + /// To check the collision behavior for a player, use + /// {@link Team.Option#COLLISION_RULE} in combination with a + /// {@link Scoreboard} and a {@link Team}. + pub fn is_collidable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets a mutable set of UUIDs of the entities which are exempt from the + /// entity's collidable rule and which's collision with this entity will + /// behave the opposite of it. + /// + /// This set can be modified to add or remove exemptions. + /// + /// For example if collidable is true and an entity is in the exemptions set + /// then it will not collide with it. Similarly if collidable is false and an + /// entity is in this set then it will still collide with it. + /// + /// Note these exemptions are not (currently) persistent. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in those exemptions not being accurate for player + /// collisions. This method should therefore only be used to exempt + /// non-player entities. + /// + /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} + /// in combination with a {@link Scoreboard} and a {@link Team}. + pub fn collidable_exemptions( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getInterpolationDuration", + "getCollidableExemptions", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the interpolation duration of this display. - pub fn set_interpolation_duration( + /// Returns the value of the memory specified. + /// + /// Note that the value is null when the specific entity does not have that + /// value by default. + pub fn get_memory( &self, - duration: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(duration); + memory_key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setInterpolationDuration", + "getMemory", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the teleport duration of this display. - ///
    - ///
  • 0 means that updates are applied immediately.
  • - ///
  • 1 means that the display entity will move from current position to the updated one over one tick.
  • - ///
  • Higher values spread the movement over multiple ticks.
  • - ///
- pub fn teleport_duration(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTeleportDuration", - sig.as_str(), - vec![], - ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) } - /// Sets the teleport duration of this display. - pub fn set_teleport_duration(&self, duration: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(duration); + /// Sets the value of the memory specified. + /// + /// Note that the value will not be persisted when the specific entity does + /// not have that value by default. + pub fn set_memory( + &self, + memory_key: impl Into>, + memory_value: jni::objects::JObject<'mc>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(memory_value); let res = self.jni_ref().call_method( &self.jni_object(), - "setTeleportDuration", + "setMemory", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the view distance/range of this display. - pub fn view_range(&self) -> Result> { - let sig = String::from("()F"); + /// Get the {@link Sound} this entity will make when damaged. + pub fn hurt_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getViewRange", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Sets the view distance/range of this display. - pub fn set_view_range(&self, range: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(range); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setViewRange", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Gets the shadow radius of this display. - pub fn shadow_radius(&self) -> Result> { - let sig = String::from("()F"); + /// Get the {@link Sound} this entity will make on death. + pub fn death_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getShadowRadius", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Sets the shadow radius of this display. - pub fn set_shadow_radius(&self, radius: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(radius); + /// Get the {@link Sound} this entity will make when falling from the given + /// height (in blocks). The sound will often differ between either a small + /// or a big fall damage sound if the height exceeds 4 blocks. + pub fn get_fall_damage_sound( + &self, + fall_height: i32, + ) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Int(fall_height); let res = self.jni_ref().call_method( &self.jni_object(), - "setShadowRadius", + "getFallDamageSound", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the shadow strength of this display. - pub fn shadow_strength(&self) -> Result> { - let sig = String::from("()F"); + /// Get the {@link Sound} this entity will make when falling from a small + /// height. + pub fn fall_damage_sound_small(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getShadowStrength", + "getFallDamageSoundSmall", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the shadow strength of this display. - pub fn set_shadow_strength(&self, strength: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(strength); + /// Get the {@link Sound} this entity will make when falling from a large + /// height. + pub fn fall_damage_sound_big(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setShadowStrength", + "getFallDamageSoundBig", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the width of this display. - pub fn display_width(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDisplayWidth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Sets the width of this display. - pub fn set_display_width(&self, width: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(width); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setDisplayWidth", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the height of this display. - pub fn display_height(&self) -> Result> { - let sig = String::from("()F"); + /// Get the {@link Sound} this entity will make when drinking the given + /// {@link ItemStack}. + pub fn get_drinking_sound( + &self, + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getDisplayHeight", + "getDrinkingSound", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the height if this display. - pub fn set_display_height(&self, height: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(height); + /// Get the {@link Sound} this entity will make when eating the given + /// {@link ItemStack}. + pub fn get_eating_sound( + &self, + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setDisplayHeight", + "getEatingSound", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the amount of ticks before client-side interpolation will commence. - pub fn interpolation_delay(&self) -> Result> { - let sig = String::from("()I"); + /// Returns true if this entity can breathe underwater and will not take + /// suffocation damage when its air supply reaches zero. + pub fn can_breathe_underwater(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getInterpolationDelay", + "canBreatheUnderwater", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the amount of ticks before client-side interpolation will commence. - pub fn set_interpolation_delay(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setInterpolationDelay", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.z()?) } - /// Gets the billboard setting of this entity. - /// The billboard setting controls the automatic rotation of the entity to - /// face the player. - pub fn billboard( + #[deprecated] + /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. + pub fn category( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Display/Billboard;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBillboard", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::DisplayBillboard::from_raw(&self.jni_ref(), unsafe { + crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the billboard setting of this entity. - /// The billboard setting controls the automatic rotation of the entity to - /// face the player. - pub fn set_billboard( - &self, - billboard: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Display/Billboard;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(billboard.into().jni_object().clone()) - }); + /// Sets whether the entity is invisible or not. + pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(invisible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setBillboard", + "setInvisible", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the scoreboard team overridden glow color of this display. - pub fn glow_color_override( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Color;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getGlowColorOverride", - sig.as_str(), - vec![], - ); + /// Gets whether the entity is invisible or not. + pub fn is_invisible(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Color::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.z()?) } - /// Sets the scoreboard team overridden glow color of this display. - pub fn set_glow_color_override( + /// Gets the specified attribute instance from the object. This instance will + /// be backed directly to the object and any changes will be visible at once. + pub fn get_attribute( &self, - color: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Color;)V"); + attribute: impl Into>, + ) -> Result>, Box> { + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", + ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setGlowColorOverride", + "getAttribute", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the brightness override of the entity. - pub fn brightness( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Display/Brightness;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBrightness", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::DisplayBrightness::from_raw( + Ok(Some(crate::attribute::AttributeInstance::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets the brightness override of the entity. - pub fn set_brightness( + /// Deals the given amount of damage to this entity from a specified + /// {@link DamageSource}. + pub fn damage( &self, - brightness: impl Into>, + amount: f64, + damage_source: std::option::Option>>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Display/Brightness;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(brightness.into().jni_object().clone()) - }); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(amount); + args.push(val_1); + if let Some(a) = damage_source { + sig += "Lorg/bukkit/damage/DamageSource;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "damage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. + pub fn health(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is + /// dead. + pub fn set_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "setBrightness", + "setHealth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Stores the entity's current position in the provided Location object. - /// - /// If the provided Location is null this method does nothing and returns - /// null. - pub fn get_location( - &self, - loc: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) - }); + /// Gets the entity's absorption amount. + pub fn absorption_amount(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocation", + "getAbsorptionAmount", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.d()?) } - /// Sets this entity's velocity in meters per tick - pub fn set_velocity( - &self, - velocity: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) - }); + /// Sets the entity's absorption amount. + /// + /// Note: The amount is capped to the value of + /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on + /// that attribute is currently unspecified and subject to change. + pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "setVelocity", + "setAbsorptionAmount", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets this entity's current velocity - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); + #[deprecated] + /// Gets the maximum health this entity has. + pub fn max_health(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the entity's height - pub fn height(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.d()?) } - /// Gets the entity's width - pub fn width(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + #[deprecated] + /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. + pub fn set_max_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaxHealth", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the entity's current bounding box. - /// - /// The returned bounding box reflects the entity's current location and - /// size. - pub fn bounding_box( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); + #[deprecated] + /// Resets the max health to the original amount. + pub fn reset_max_health(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns true if the entity is supported by a block. This value is a - /// state updated by the server and is not recalculated unless the entity - /// moves. - pub fn is_on_ground(&self) -> Result> { - let sig = String::from("()Z"); + /// Launches a {@link Projectile} from the ProjectileSource with an + /// initial velocity. + pub fn launch_projectile( + &self, + projectile: jni::objects::JClass<'mc>, + velocity: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(projectile.into()); + args.push(val_1); + if let Some(a) = velocity { + sig += "Lorg/bukkit/util/Vector;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")LT;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.l()?) } - /// Returns true if the entity is in water. - pub fn is_in_water(&self) -> Result> { + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Breeze<'mc> { + fn into(self) -> crate::entity::Monster<'mc> { + crate::entity::Monster::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Breeze into crate::entity::Monster") + } +} +#[repr(C)] +pub struct Zoglin<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Zoglin<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Zoglin<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Zoglin from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Zoglin")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Zoglin object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Zoglin<'mc> { + #[deprecated] + /// Gets whether the zoglin is a baby + pub fn is_baby(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isBaby", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the current world this entity resides in - pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); + #[deprecated] + /// Sets whether the zoglin is a baby + pub fn set_baby( + &self, + flag: std::option::Option, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = flag { + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_1); + } + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "setBaby", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the height of the living entity's eyes above its Location. + pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { + let sig = String::from("(Z)D"); + let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getEyeHeight", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { + Ok(res.d()?) + } + /// Get a Location detailing the current eye position of the living entity. + pub fn eye_location(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the entity's rotation. + /// Gets all blocks along the living entity's line of sight. /// - /// Note that if the entity is affected by AI, it may override this rotation. - pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { - let sig = String::from("(FF)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); - let val_2 = jni::objects::JValueGen::Float(pitch); + /// This list contains all blocks from the living entity's eye position to + /// target inclusive. This method considers all blocks as 1x1x1 in size. + pub fn get_line_of_sight( + &self, + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setRotation", + "getLineOfSight", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Teleports this entity to the given location. If this entity is riding a - /// vehicle, it will be dismounted prior to teleportation. - pub fn teleport( + /// Gets the block that the living entity has targeted. + /// + /// This method considers all blocks as 1x1x1 in size. To take exact block + /// collision shapes into account, see {@link #getTargetBlockExact(int, + /// FluidCollisionMode)}. + pub fn get_target_block( &self, - location: impl Into>, - cause: std::option::Option< - impl Into>, - >, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; + transparent: impl Into>, + max_distance: i32, + ) -> Result, Box> { + let sig = String::from("(Ljava/util/Set;I)Lorg/bukkit/block/Block;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) }); - args.push(val_1); - if let Some(a) = cause { - sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "teleport", sig.as_str(), args); + let val_2 = jni::objects::JValueGen::Int(max_distance); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTargetBlock", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns a list of entities within a bounding box centered around this - /// entity - pub fn get_nearby_entities( + /// Gets the last two blocks along the living entity's line of sight. + /// + /// The target block will be the last block in the list. This method + /// considers all blocks as 1x1x1 in size. + pub fn get_last_two_target_blocks( &self, - x: f64, - y: f64, - z: f64, - ) -> Result>, Box> { - let sig = String::from("(DDD)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Double(x); - let val_2 = jni::objects::JValueGen::Double(y); - let val_3 = jni::objects::JValueGen::Double(z); + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "getNearbyEntities", + "getLastTwoTargetBlocks", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), ], ); let res = self.jni_ref().translate_error(res)?; @@ -50829,1215 +57037,1505 @@ impl<'mc> Display<'mc> { let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); } Ok(new_vec) } - /// Returns a unique id for this entity - pub fn entity_id(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the block that the living entity has targeted. + /// + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn get_target_block_exact( + &self, + max_distance: i32, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/block/Block;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTargetBlockExact", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::block::Block::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Performs a ray trace that provides information on the targeted block. + /// + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn ray_trace_blocks( + &self, + max_distance: f64, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/util/RayTraceResult;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::util::RayTraceResult::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Returns the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn fire_ticks(&self) -> Result> { + /// Returns the amount of air that the living entity has remaining, in + /// ticks. + pub fn remaining_air(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Returns the entity's maximum fire ticks. - pub fn max_fire_ticks(&self) -> Result> { + /// Sets the amount of air that the living entity has remaining, in ticks. + pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRemainingAir", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the maximum amount of air the living entity can have, in ticks. + pub fn maximum_air(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Sets the maximum amount of air the living entity can have, in ticks. + pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setFireTicks", + "setMaximumAir", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets if the entity has visual fire (it will always appear to be on fire). - pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire.into()); + /// Gets the item that the player is using (eating food, drawing back a bow, + /// blocking, etc.) + pub fn item_in_use( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the number of ticks remaining for the current item's usage. + pub fn item_in_use_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisualFire", + "getItemInUseTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the number of ticks that remain for the current item's usage. + /// Applies to items that take time to use, like eating food, drawing a bow, + /// or throwing a trident. + pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItemInUseTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity has visual fire (it will always appear to be on fire). - pub fn is_visual_fire(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); + /// Gets the time in ticks until the next arrow leaves the entity's body. + pub fn arrow_cooldown(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getArrowCooldown", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Returns the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn freeze_ticks(&self) -> Result> { + /// Sets the time in ticks until the next arrow leaves the entity's body. + pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setArrowCooldown", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the amount of arrows in an entity's body. + pub fn arrows_in_body(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Returns the entity's maximum freeze ticks (amount of ticks before it will - /// be fully frozen) - pub fn max_freeze_ticks(&self) -> Result> { + /// Set the amount of arrows in the entity's body. + pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(count); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setArrowsInBody", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the living entity's current maximum no damage ticks. + /// + /// This is the maximum duration in which the living entity will not take + /// damage. + pub fn maximum_no_damage_ticks(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getMaxFreezeTicks", + "getMaximumNoDamageTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Sets the living entity's current maximum no damage ticks. + pub fn set_maximum_no_damage_ticks( + &self, + ticks: i32, + ) -> Result<(), Box> { let sig = String::from("(I)V"); let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setFreezeTicks", + "setMaximumNoDamageTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity is fully frozen (it has been in powdered snow for max - /// freeze ticks). - pub fn is_frozen(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); + /// Returns the living entity's last damage taken in the current no damage + /// ticks time. + /// + /// Only damage higher than this amount will further damage the living + /// entity. + pub fn last_damage(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Mark the entity's removal. - pub fn remove(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); + /// Sets the damage dealt within the current no damage ticks time period. + pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(damage); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLastDamage", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns true if this entity has been marked for removal. - pub fn is_dead(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns false if the entity has died, been despawned for some other - /// reason, or has not been added to the world. - pub fn is_valid(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); + /// Returns the living entity's current no damage ticks. + pub fn no_damage_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNoDamageTicks", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Gets the {@link Server} that contains this Entity - pub fn server(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Server;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Server::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Sets the living entity's current no damage ticks. + pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setNoDamageTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns true if the entity gets persisted. - /// - /// By default all entities are persistent. An entity will also not get - /// persisted, if it is riding an entity that is not persistent. - /// - /// The persistent flag on players controls whether or not to save their - /// playerdata file when they quit. If a player is directly or indirectly - /// riding a non-persistent entity, the vehicle at the root and all its - /// passengers won't get persisted. + /// Get the ticks that this entity has performed no action. /// - /// This should not be confused with - /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls - /// despawning of living entities. - pub fn is_persistent(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn no_action_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNoActionTicks", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets whether or not the entity gets persisted. - pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(persistent.into()); + /// Set the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setPersistent", + "setNoActionTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. - pub fn passenger( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); + /// Gets the player identified as the killer of the living entity. + /// + /// May be null. + pub fn killer(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Entity::from_raw( + Ok(Some(crate::entity::Player::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } #[deprecated] - /// Set the passenger of a vehicle. - pub fn set_passenger( + /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. + pub fn add_potion_effect( &self, - passenger: impl Into>, + effect: impl Into>, + force: std::option::Option, ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/potion/PotionEffect;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = force { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns whether the living entity already has an existing effect of + /// the given {@link PotionEffectType} applied to it. + pub fn has_potion_effect( + &self, + val_type: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPassenger", + "hasPotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets a list of passengers of this vehicle. + /// Returns the active {@link PotionEffect} of the specified type. /// - /// The returned list will not be directly linked to the entity's current - /// passengers, and no guarantees are made as to its mutability. - pub fn passengers( + /// If the effect is not present on the entity then null will be returned. + pub fn get_potion_effect( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); + val_type: impl Into>, + ) -> Result>, Box> { + let sig = + String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPotionEffect", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - Ok(new_vec) + Ok(Some(crate::potion::PotionEffect::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Add a passenger to the vehicle. - pub fn add_passenger( + /// Removes any effects present of the given {@link PotionEffectType}. + pub fn remove_potion_effect( &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "addPassenger", + "removePotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns all currently active {@link PotionEffect}s on the living + /// entity. + pub fn active_potion_effects( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getActivePotionEffects", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Remove a passenger from the vehicle. - pub fn remove_passenger( + /// Checks whether the living entity has block line of sight to another. + /// + /// This uses the same algorithm that hostile mobs use to find the closest + /// player. + pub fn has_line_of_sight( &self, - passenger: impl Into>, + other: impl Into>, ) -> Result> { let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(other.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removePassenger", + "hasLineOfSight", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Check if a vehicle has passengers. - pub fn is_empty(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Eject any passenger. - pub fn eject(&self) -> Result> { + /// Returns if the living entity despawns when away from players or not. + /// + /// By default, animals are not removed while other mobs are. + pub fn remove_when_far_away(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the distance this entity has fallen - pub fn fall_distance(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Sets the fall distance for this entity - pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setFallDistance", + "getRemoveWhenFarAway", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - #[deprecated] - /// Record the last {@link EntityDamageEvent} inflicted on this entity - pub fn set_last_damage_cause( - &self, - event: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(event.into().jni_object().clone()) - }); + /// Sets whether or not the living entity despawns when away from players + /// or not. + pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(remove.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDamageCause", + "setRemoveWhenFarAway", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. - /// This event may have been cancelled. - pub fn last_damage_cause( + /// Gets the inventory with the equipment worn by the living entity. + pub fn equipment( &self, - ) -> Result>, Box> - { - let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLastDamageCause", - sig.as_str(), - vec![], - ); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( + Ok(Some(crate::inventory::EntityEquipment::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Returns a unique and persistent id for this entity - pub fn unique_id( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. - pub fn ticks_lived(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. May not be less than one - /// tick. - pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(value); + /// Sets whether or not the living entity can pick up items. + pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(pickup.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setTicksLived", + "setCanPickupItems", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Performs the specified {@link EntityEffect} for this entity. - /// - /// This will be viewable to all players near the entity. - /// - /// If the effect is not applicable to this class of entity, it will not play. - pub fn play_effect( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Gets if the living entity can pick up items. + pub fn can_pickup_items(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "playEffect", + "getCanPickupItems", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Get the type of the entity. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + /// Returns whether the entity is currently leashed. + pub fn is_leashed(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Get the {@link Sound} this entity makes while swimming. - pub fn swim_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Gets the entity that is currently leading this entity. + pub fn leash_holder(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the {@link Sound} this entity makes when splashing in water. For most - /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_splash_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Sets the leash on this entity to be held by the supplied entity. + /// + /// This method has no effect on EnderDragons, Withers, Players, or Bats. + /// Non-living entities excluding leashes will not persist as leash + /// holders. + pub fn set_leash_holder( + &self, + holder: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(holder.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimSplashSound", + "setLeashHolder", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Get the {@link Sound} this entity makes when splashing in water at high - /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_high_speed_splash_sound( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Checks to see if an entity is gliding, such as using an Elytra. + pub fn is_gliding(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Makes entity start or stop gliding. This will work even if an Elytra + /// is not equipped, but will be reverted by the server immediately after + /// unless an event-cancelling mechanism is put in place. + pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gliding.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimHighSpeedSplashSound", + "setGliding", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns whether this entity is inside a vehicle. - pub fn is_inside_vehicle(&self) -> Result> { + /// Checks to see if an entity is swimming. + pub fn is_swimming(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Leave the current vehicle. If the entity is currently in a vehicle (and - /// is removed from it), true will be returned, otherwise false will be - /// returned. - pub fn leave_vehicle(&self) -> Result> { + /// Makes entity start or stop swimming. + /// This may have unexpected results if the entity is not in water. + pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(swimming.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSwimming", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks to see if an entity is currently riptiding. + pub fn is_riptiding(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get the vehicle that this entity is inside. If there is no vehicle, - /// null will be returned. - pub fn vehicle( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Sets whether or not to display the mob's custom name client side. The - /// name will be displayed above the mob similarly to a player. + /// Makes entity start or stop riptiding. /// - /// This value has no effect on players, they will always display their - /// name. - pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { + /// Note: This does not damage attackable entities. + pub fn set_riptiding(&self, riptiding: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(riptiding.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomNameVisible", + "setRiptiding", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not the mob's custom name is displayed client side. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn is_custom_name_visible(&self) -> Result> { + /// Returns whether this entity is slumbering. + pub fn is_sleeping(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isCustomNameVisible", - sig.as_str(), - vec![], - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { + /// Gets if the entity is climbing. + pub fn is_climbing(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether an entity will have AI. + /// The entity will be completely unable to move if it has no AI. + pub fn set_ai(&self, ai: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(visible.into()); + let val_1 = jni::objects::JValueGen::Bool(ai.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisibleByDefault", + "setAI", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn is_visible_by_default(&self) -> Result> { + /// Checks whether an entity has AI. + /// The entity will be completely unable to move if it has no AI. + pub fn has_ai(&self) -> Result> { let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Makes this entity attack the given entity with a melee attack. + /// Attack damage is calculated by the server from the attributes and + /// equipment of this mob, and knockback is applied to {@code target} as + /// appropriate. + pub fn attack( + &self, + target: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(target.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "isVisibleByDefault", + "attack", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get all players that are currently tracking this entity. - /// - /// 'Tracking' means that this entity has been sent to the player and that - /// they are receiving updates on its state. Note that the client's {@code - /// 'Entity Distance'} setting does not affect the range at which entities - /// are tracked. - pub fn tracked_by( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Makes this entity swing their main hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their main hand. + pub fn swing_main_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets whether the entity has a team colored (default: white) glow. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Makes this entity swing their off hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their off hand. + pub fn swing_off_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Makes this entity flash red as if they were damaged. + pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); let res = self.jni_ref().call_method( &self.jni_object(), - "setGlowing", + "playHurtAnimation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is glowing or not. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn is_glowing(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether the entity is invulnerable or not. + /// Set if this entity will be subject to collisions with other entities. /// - /// When an entity is invulnerable it can only be damaged by players in - /// creative mode. - pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { + /// Exemptions to this rule can be managed with + /// {@link #getCollidableExemptions()} + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not working for player collisions. This + /// method should therefore only be used to set the collision status of + /// non-player entities. + /// + /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in + /// combination with a {@link Scoreboard} and a {@link Team}. + pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(collidable.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvulnerable", + "setCollidable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invulnerable or not. - pub fn is_invulnerable(&self) -> Result> { + /// Gets if this entity is subject to collisions with other entities. + /// + /// Some entities might be exempted from the collidable rule of this entity. + /// Use {@link #getCollidableExemptions()} to get these. + /// + /// Please note that this method returns only the custom collidable state, + /// not whether the entity is non-collidable for other reasons such as being + /// dead. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not being accurate for player collisions. + /// This method should therefore only be used to check the collision status + /// of non-player entities. + /// + /// To check the collision behavior for a player, use + /// {@link Team.Option#COLLISION_RULE} in combination with a + /// {@link Scoreboard} and a {@link Team}. + pub fn is_collidable(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets whether the entity is silent or not. - pub fn is_silent(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + /// Gets a mutable set of UUIDs of the entities which are exempt from the + /// entity's collidable rule and which's collision with this entity will + /// behave the opposite of it. + /// + /// This set can be modified to add or remove exemptions. + /// + /// For example if collidable is true and an entity is in the exemptions set + /// then it will not collide with it. Similarly if collidable is false and an + /// entity is in this set then it will still collide with it. + /// + /// Note these exemptions are not (currently) persistent. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in those exemptions not being accurate for player + /// collisions. This method should therefore only be used to exempt + /// non-player entities. + /// + /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} + /// in combination with a {@link Scoreboard} and a {@link Team}. + pub fn collidable_exemptions( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCollidableExemptions", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns the value of the memory specified. + /// + /// Note that the value is null when the specific entity does not have that + /// value by default. + pub fn get_memory( + &self, + memory_key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMemory", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) } - /// Sets whether the entity is silent or not. + /// Sets the value of the memory specified. /// - /// When an entity is silent it will not produce any sound. - pub fn set_silent(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Note that the value will not be persisted when the specific entity does + /// not have that value by default. + pub fn set_memory( + &self, + memory_key: impl Into>, + memory_value: jni::objects::JObject<'mc>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(memory_value); let res = self.jni_ref().call_method( &self.jni_object(), - "setSilent", + "setMemory", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether gravity applies to this entity. - pub fn has_gravity(&self) -> Result> { - let sig = String::from("()Z"); + /// Get the {@link Sound} this entity will make when damaged. + pub fn hurt_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Sets whether gravity applies to this entity. - pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gravity.into()); + /// Get the {@link Sound} this entity will make on death. + pub fn death_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Get the {@link Sound} this entity will make when falling from the given + /// height (in blocks). The sound will often differ between either a small + /// or a big fall damage sound if the height exceeds 4 blocks. + pub fn get_fall_damage_sound( + &self, + fall_height: i32, + ) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Int(fall_height); let res = self.jni_ref().call_method( &self.jni_object(), - "setGravity", + "getFallDamageSound", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the period of time (in ticks) before this entity can use a portal. - pub fn portal_cooldown(&self) -> Result> { - let sig = String::from("()I"); + /// Get the {@link Sound} this entity will make when falling from a small + /// height. + pub fn fall_damage_sound_small(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPortalCooldown", + "getFallDamageSoundSmall", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the period of time (in ticks) before this entity can use a portal. - pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(cooldown); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPortalCooldown", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns a set of tags for this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn scoreboard_tags( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Get the {@link Sound} this entity will make when falling from a large + /// height. + pub fn fall_damage_sound_big(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getScoreboardTags", + "getFallDamageSoundBig", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Add a tag to this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn add_scoreboard_tag( + /// Get the {@link Sound} this entity will make when drinking the given + /// {@link ItemStack}. + pub fn get_drinking_sound( &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "addScoreboardTag", + "getDrinkingSound", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Removes a given tag from this entity. - pub fn remove_scoreboard_tag( + /// Get the {@link Sound} this entity will make when eating the given + /// {@link ItemStack}. + pub fn get_eating_sound( &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeScoreboardTag", + "getEatingSound", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the reaction of the entity when moved by a piston. - pub fn piston_move_reaction( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + /// Returns true if this entity can breathe underwater and will not take + /// suffocation damage when its air supply reaches zero. + pub fn can_breathe_underwater(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPistonMoveReaction", + "canBreatheUnderwater", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the closest cardinal {@link BlockFace} direction an entity is - /// currently facing. - /// - /// This will not return any non-cardinal directions such as - /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. - /// - /// {@link Hanging} entities will override this call and thus their behavior - /// may be different. - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Gets the entity's current pose. - /// Note that the pose is only updated at the end of a tick, so may be - /// inconsistent with other methods. eg {@link Player#isSneaking()} being - /// true does not imply the current pose will be {@link Pose#SNEAKING} - pub fn pose(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Pose;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + #[deprecated] + /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. + pub fn category( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the category of spawn to which this entity belongs. - pub fn spawn_category( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); + /// Sets whether the entity is invisible or not. + pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(invisible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getSpawnCategory", + "setInvisible", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Checks if this entity has been spawned in a world. - /// - /// Entities not spawned in a world will not tick, be sent to players, or be - /// saved to the server files. - pub fn is_in_world(&self) -> Result> { + /// Gets whether the entity is invisible or not. + pub fn is_invisible(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get this entity as an NBT string. - /// - /// This string should not be relied upon as a serializable value. - pub fn as_string(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(res.z()?) } - /// Crates an {@link EntitySnapshot} representing the current state of this entity. - pub fn create_snapshot( + /// Gets the specified attribute instance from the object. This instance will + /// be backed directly to the object and any changes will be visible at once. + pub fn get_attribute( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + attribute: impl Into>, + ) -> Result>, Box> { + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAttribute", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::EntitySnapshot::from_raw( + Ok(Some(crate::attribute::AttributeInstance::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Creates a copy of this entity and all its data. Spawns the copy at the given location. - /// - /// Note: Players cannot be copied. - pub fn copy( + /// Deals the given amount of damage to this entity from a specified + /// {@link DamageSource}. + pub fn damage( &self, - to: std::option::Option>>, - ) -> Result, Box> { + amount: f64, + damage_source: std::option::Option>>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = to { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(amount); + args.push(val_1); + if let Some(a) = damage_source { + sig += "Lorg/bukkit/damage/DamageSource;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); - args.push(val_1); + args.push(val_2); } - sig += ")Lorg/bukkit/entity/Entity;"; + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); + .call_method(&self.jni_object(), "damage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. + pub fn health(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.d()?) } - /// Sets a metadata value in the implementing object's metadata store. - pub fn set_metadata( - &self, - metadata_key: impl Into, - new_metadata_value: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) - }); + /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is + /// dead. + pub fn set_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "setMetadata", + "setHealth", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a list of previously set metadata values from the implementing - /// object's metadata store. - pub fn get_metadata( - &self, - metadata_key: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); + /// Gets the entity's absorption amount. + pub fn absorption_amount(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref().call_method( &self.jni_object(), - "getMetadata", + "getAbsorptionAmount", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::metadata::MetadataValue::from_raw( - &self.jni_ref(), - obj, - )?); - } - Ok(new_vec) + Ok(res.d()?) } - /// Tests to see whether the implementing object contains the given - /// metadata value in its metadata store. - pub fn has_metadata( - &self, - metadata_key: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); + /// Sets the entity's absorption amount. + /// + /// Note: The amount is capped to the value of + /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on + /// that attribute is currently unspecified and subject to change. + pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "hasMetadata", + "setAbsorptionAmount", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the maximum health this entity has. + pub fn max_health(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Removes the given metadata value from the implementing object's - /// metadata store. - pub fn remove_metadata( + #[deprecated] + /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. + pub fn set_max_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaxHealth", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Resets the max health to the original amount. + pub fn reset_max_health(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Launches a {@link Projectile} from the ProjectileSource with an + /// initial velocity. + pub fn launch_projectile( &self, - metadata_key: impl Into, - owning_plugin: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) - }); + projectile: jni::objects::JClass<'mc>, + velocity: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(projectile.into()); + args.push(val_1); + if let Some(a) = velocity { + sig += "Lorg/bukkit/util/Vector;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")LT;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) + } + /// Gets the age of this mob. + pub fn age(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getAge", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the age of this mob. + pub fn set_age(&self, age: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(age); let res = self.jni_ref().call_method( &self.jni_object(), - "removeMetadata", + "setAge", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Lock the age of the animal, setting this will prevent the animal from maturing or getting ready for mating. + pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(lock.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAgeLock", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sends this sender multiple messages - pub fn send_message( - &self, - sender: impl Into>, - messages: std::option::Option>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = messages { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_2); - } - sig += ")V"; + #[deprecated] + /// Gets the current agelock. + pub fn age_lock(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the age of the mob to an adult + pub fn set_adult(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self .jni_ref() - .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); + .call_method(&self.jni_object(), "setAdult", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the name of this command sender - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Returns true if the mob is an adult. + pub fn is_adult(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isAdult", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - /// Gets the custom name on a mob or block. If there is no name this method - /// will return null. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn custom_name(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCustomName", sig.as_str(), vec![]); + #[deprecated] + /// Return the ability to breed of the animal. + pub fn can_breed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(res.z()?) } - /// Sets a custom name on a mob or block. This name will be used in death - /// messages and can be sent to the client as a nameplate over the mob. - /// - /// Setting the name to null or an empty string will clear it. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn set_custom_name( - &self, - name: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + #[deprecated] + /// Set breedability of the animal, if the animal is a baby and set to breed it will instantly grow up. + pub fn set_breed(&self, breed: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(breed.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomName", + "setBreed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPersistentDataContainer", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Display<'mc> { - fn into(self) -> crate::entity::Entity<'mc> { - crate::entity::Entity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Display into crate::entity::Entity") - } -} -pub enum DisplayBillboard<'mc> {} -impl<'mc> std::fmt::Display for DisplayBillboard<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} +impl<'mc> Into> for Zoglin<'mc> { + fn into(self) -> crate::entity::Monster<'mc> { + crate::entity::Monster::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Zoglin into crate::entity::Monster") } } - -impl<'mc> DisplayBillboard<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/Display/Billboard"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/Display/Billboard;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } +impl<'mc> Into> for Zoglin<'mc> { + fn into(self) -> crate::entity::Ageable<'mc> { + crate::entity::Ageable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Zoglin into crate::entity::Ageable") } } - #[repr(C)] -pub struct DisplayBillboardStruct<'mc>( +pub struct LargeFireball<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for DisplayBillboard<'mc> { +impl<'mc> JNIRaw<'mc> for LargeFireball<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + self.0.clone() } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for DisplayBillboard<'mc> { +impl<'mc> JNIInstantiatable<'mc> for LargeFireball<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate DisplayBillboard from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate LargeFireball from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Display/Billboard")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/LargeFireball")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a DisplayBillboard object, got {}", + "Invalid argument passed. Expected a LargeFireball object, got {}", name ) .into()) } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + Ok(Self(env.clone(), obj)) } } } -impl<'mc> JNIRaw<'mc> for DisplayBillboardStruct<'mc> { +impl<'mc> LargeFireball<'mc> { + /// Gets the display {@link ItemStack}. + pub fn display_item( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDisplayItem", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the display {@link ItemStack} for the fireball. + pub fn set_display_item( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDisplayItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets the direction the fireball should be flying towards. + /// + /// This is a convenience method, it will change the velocity direction and + /// acceleration direction, while keeping the power the same. + /// + /// Note: This method only uses the direction of the vector and will + /// normalize (a copy of) it. + /// + /// Special Case: When the given direction is + /// {@link Vector#isZero() zero}, the velocity and acceleration will also be + /// set to zero without keeping the power. + pub fn set_direction( + &self, + direction: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(direction.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDirection", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Retrieve the direction this fireball is heading toward. The returned vector is not normalized. + pub fn direction(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the acceleration of the fireball. + /// The acceleration gets applied to the velocity every tick, depending on + /// the specific type of the fireball a damping / drag factor is applied so + /// that the velocity does not grow into infinity. + /// + /// Note: that the client may not respect non-default acceleration + /// power and will therefore mispredict the location of the fireball, causing + /// visual stutter. + pub fn set_acceleration( + &self, + acceleration: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(acceleration.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAcceleration", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Retrieve the acceleration of this fireball. + pub fn acceleration(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAcceleration", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for LargeFireball<'mc> { + fn into(self) -> crate::entity::SizedFireball<'mc> { + crate::entity::SizedFireball::from_raw(&self.jni_ref(), self.1) + .expect("Error converting LargeFireball into crate::entity::SizedFireball") + } +} +#[repr(C)] +pub struct Projectile<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Projectile<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -52045,21 +58543,18 @@ impl<'mc> JNIRaw<'mc> for DisplayBillboardStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for DisplayBillboardStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Projectile<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate DisplayBillboardStruct from null object." - ) - .into()); + return Err(eyre::eyre!("Tried to instantiate Projectile from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Display/Billboard")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Projectile")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a DisplayBillboardStruct object, got {}", + "Invalid argument passed. Expected a Projectile object, got {}", name ) .into()) @@ -52069,910 +58564,1427 @@ impl<'mc> JNIInstantiatable<'mc> for DisplayBillboardStruct<'mc> { } } -impl<'mc> DisplayBillboardStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Display/Billboard;"); - let cls = jni.find_class("org/bukkit/entity/Display/Billboard"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::DisplayBillboard::from_raw(&jni, obj) +impl<'mc> Projectile<'mc> { + /// Retrieve the shooter of this projectile. + pub fn shooter( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/projectiles/ProjectileSource;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getShooter", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::projectiles::ProjectileSource::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + /// Set the shooter of this projectile. + pub fn set_shooter( + &self, + source: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/projectiles/ProjectileSource;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(source.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setShooter", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -#[repr(C)] -pub struct DisplayBrightness<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for DisplayBrightness<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + #[deprecated] + /// Determine if this projectile should bounce or not when it hits. + pub fn does_bounce(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "doesBounce", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Set whether or not this projectile should bounce or not when it hits something. + pub fn set_bounce(&self, does_bounce: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(does_bounce.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBounce", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Stores the entity's current position in the provided Location object. + /// + /// If the provided Location is null this method does nothing and returns + /// null. + pub fn get_location( + &self, + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLocation", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Sets this entity's velocity in meters per tick + pub fn set_velocity( + &self, + velocity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVelocity", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets this entity's current velocity + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the entity's height + pub fn height(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the entity's width + pub fn width(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the entity's current bounding box. + /// + /// The returned bounding box reflects the entity's current location and + /// size. + pub fn bounding_box( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns true if the entity is supported by a block. This value is a + /// state updated by the server and is not recalculated unless the entity + /// moves. + pub fn is_on_ground(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns true if the entity is in water. + pub fn is_in_water(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets the current world this entity resides in + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> JNIInstantiatable<'mc> for DisplayBrightness<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate DisplayBrightness from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Display/Brightness")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a DisplayBrightness object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + /// Sets the entity's rotation. + /// + /// Note that if the entity is affected by AI, it may override this rotation. + pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { + let sig = String::from("(FF)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); + let val_2 = jni::objects::JValueGen::Float(pitch); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRotation", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Teleports this entity to the given location. If this entity is riding a + /// vehicle, it will be dismounted prior to teleportation. + pub fn teleport( + &self, + location: impl Into>, + cause: std::option::Option< + impl Into>, + >, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = cause { + sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "teleport", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} - -impl<'mc> DisplayBrightness<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - block_light: i32, - sky_light: i32, - ) -> Result, Box> { - let sig = String::from("(II)V"); - let val_1 = jni::objects::JValueGen::Int(block_light); - let val_2 = jni::objects::JValueGen::Int(sky_light); - let cls = jni.find_class("org/bukkit/entity/Display/Brightness"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, + /// Returns a list of entities within a bounding box centered around this + /// entity + pub fn get_nearby_entities( + &self, + x: f64, + y: f64, + z: f64, + ) -> Result>, Box> { + let sig = String::from("(DDD)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Double(x); + let val_2 = jni::objects::JValueGen::Double(y); + let val_3 = jni::objects::JValueGen::Double(z); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNearbyEntities", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), ], ); - let res = jni.translate_error_no_gen(res)?; - crate::entity::DisplayBrightness::from_raw(&jni, res) + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Gets the block lighting component of this brightness. - pub fn block_light(&self) -> Result> { + /// Returns a unique id for this entity + pub fn entity_id(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBlockLight", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Gets the sky lighting component of this brightness. - pub fn sky_light(&self) -> Result> { + /// Returns the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn fire_ticks(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getSkyLight", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - - pub fn hash_code(&self) -> Result> { + /// Returns the entity's maximum fire ticks. + pub fn max_fire_ticks(&self) -> Result> { let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - - pub fn equals( - &self, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - let sig = String::from("(Ljava/lang/Object;)Z"); - let val_1 = jni::objects::JValueGen::Object(obj); + /// Sets the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "equals", + "setFireTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets if the entity has visual fire (it will always appear to be on fire). + pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVisualFire", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the entity has visual fire (it will always appear to be on fire). + pub fn is_visual_fire(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + /// Returns the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} - -impl<'mc> std::string::ToString for DisplayBrightness<'mc> { - fn to_string(&self) -> String { - match &self.internal_to_string() { - Ok(a) => a.clone(), - Err(err) => format!("Error calling DisplayBrightness.toString: {}", err), - } + Ok(res.i()?) } -} - -pub enum Pose<'mc> {} -impl<'mc> std::fmt::Display for Pose<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + /// Returns the entity's maximum freeze ticks (amount of ticks before it will + /// be fully frozen) + pub fn max_freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaxFreezeTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} - -impl<'mc> Pose<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/Pose"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/Pose;", + /// Sets the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFreezeTicks", + sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct PoseStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Pose<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for Pose<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Pose from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Pose")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Pose object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for PoseStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PoseStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate PoseStruct from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Pose")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PoseStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> PoseStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Pose;"); - let cls = jni.find_class("org/bukkit/entity/Pose"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::Pose::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + self.jni_ref().translate_error(res)?; + Ok(()) } -} -#[repr(C)] -pub struct Turtle<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Turtle<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Gets if the entity is fully frozen (it has been in powdered snow for max + /// freeze ticks). + pub fn is_frozen(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Mark the entity's removal. + pub fn remove(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -impl<'mc> JNIInstantiatable<'mc> for Turtle<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Turtle from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Turtle")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Turtle object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Returns true if this entity has been marked for removal. + pub fn is_dead(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} - -impl<'mc> Turtle<'mc> { - /// Gets whether the turtle has an egg - pub fn has_egg(&self) -> Result> { + /// Returns false if the entity has died, been despawned for some other + /// reason, or has not been added to the world. + pub fn is_valid(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "hasEgg", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets whether the turtle is laying an egg - pub fn is_laying_egg(&self) -> Result> { + /// Gets the {@link Server} that contains this Entity + pub fn server(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Server;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Server::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns true if the entity gets persisted. + /// + /// By default all entities are persistent. An entity will also not get + /// persisted, if it is riding an entity that is not persistent. + /// + /// The persistent flag on players controls whether or not to save their + /// playerdata file when they quit. If a player is directly or indirectly + /// riding a non-persistent entity, the vehicle at the root and all its + /// passengers won't get persisted. + /// + /// This should not be confused with + /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls + /// despawning of living entities. + pub fn is_persistent(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isLayingEgg", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn breed_cause( + /// Sets whether or not the entity gets persisted. + pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(persistent.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPersistent", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. + pub fn passenger( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + #[deprecated] + /// Set the passenger of a vehicle. + pub fn set_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPassenger", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets a list of passengers of this vehicle. + /// + /// The returned list will not be directly linked to the entity's current + /// passengers, and no guarantees are made as to its mutability. + pub fn passengers( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/UUID;"); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); } - Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(new_vec) } - /// Set the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn set_breed_cause( + /// Add a passenger to the vehicle. + pub fn add_passenger( &self, - uuid: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/UUID;)V"); + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreedCause", + "addPassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get whether or not this entity is in love mode and will produce - /// offspring with another entity in love mode. Will return true if - /// and only if {@link #getLoveModeTicks()} is greater than 0. - pub fn is_love_mode(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get the amount of ticks remaining for this entity in love mode. - /// If the entity is not in love mode, 0 will be returned. - pub fn love_mode_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Remove a passenger from the vehicle. + pub fn remove_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getLoveModeTicks", + "removePassenger", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the amount of ticks for which this entity should be in love mode. - /// Setting the love mode ticks to 600 is the equivalent of a player - /// feeding the entity their breeding item of choice. - pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Check if a vehicle has passengers. + pub fn is_empty(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Eject any passenger. + pub fn eject(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the distance this entity has fallen + pub fn fall_distance(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the fall distance for this entity + pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setLoveModeTicks", + "setFallDistance", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check if the provided ItemStack is the correct item used for breeding - /// this entity.. - pub fn is_breed_item( + #[deprecated] + /// Record the last {@link EntityDamageEvent} inflicted on this entity + pub fn set_last_damage_cause( &self, - material: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; + event: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) + jni::objects::JObject::from_raw(event.into().jni_object().clone()) }); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Lock the age of the animal, setting this will prevent the animal from - /// maturing or getting ready for mating. - pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(lock.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setAgeLock", + "setLastDamageCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the current agelock. - pub fn age_lock(&self) -> Result> { - let sig = String::from("()Z"); + /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. + /// This event may have been cancelled. + pub fn last_damage_cause( + &self, + ) -> Result>, Box> + { + let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLastDamageCause", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Returns a unique and persistent id for this entity + pub fn unique_id( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Return the ability to breed of the animal. - pub fn can_breed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); + /// Gets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. + pub fn ticks_lived(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Set breedability of the animal, if the animal is a baby and set to - /// breed it will instantly grow up. - pub fn set_breed(&self, breed: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(breed.into()); + /// Sets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. May not be less than one + /// tick. + pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(value); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreed", + "setTicksLived", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Turtle<'mc> { - fn into(self) -> crate::entity::Animals<'mc> { - crate::entity::Animals::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Turtle into crate::entity::Animals") - } -} -#[repr(C)] -pub struct BlockDisplay<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for BlockDisplay<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for BlockDisplay<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate BlockDisplay from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/BlockDisplay")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockDisplay object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> BlockDisplay<'mc> { - /// Gets the displayed block. - pub fn block(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the displayed block. - pub fn set_block( + /// Performs the specified {@link EntityEffect} for this entity. + /// + /// This will be viewable to all players near the entity. + /// + /// If the effect is not applicable to this class of entity, it will not play. + pub fn play_effect( &self, - block: impl Into>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); + let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBlock", + "playEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the transformation applied to this display. - pub fn transformation( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Transformation;"); + /// Get the type of the entity. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes while swimming. + pub fn swim_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes when splashing in water. For most + /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_splash_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getTransformation", + "getSwimSplashSound", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::util::Transformation::from_raw(&self.jni_ref(), unsafe { + crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the transformation applied to this display - pub fn set_transformation( + /// Get the {@link Sound} this entity makes when splashing in water at high + /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_high_speed_splash_sound( &self, - transformation: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Transformation;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transformation.into().jni_object().clone()) - }); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setTransformation", + "getSwimHighSpeedSplashSound", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the raw transformation matrix applied to this display - pub fn set_transformation_matrix( + /// Returns whether this entity is inside a vehicle. + pub fn is_inside_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Leave the current vehicle. If the entity is currently in a vehicle (and + /// is removed from it), true will be returned, otherwise false will be + /// returned. + pub fn leave_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the vehicle that this entity is inside. If there is no vehicle, + /// null will be returned. + pub fn vehicle( &self, - transformation_matrix: jni::objects::JObject<'mc>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/joml/Matrix4f;)V"); - let val_1 = jni::objects::JValueGen::Object(transformation_matrix); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets whether or not to display the mob's custom name client side. The + /// name will be displayed above the mob similarly to a player. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setTransformationMatrix", + "setCustomNameVisible", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the interpolation duration of this display. - pub fn interpolation_duration(&self) -> Result> { - let sig = String::from("()I"); + /// Gets whether or not the mob's custom name is displayed client side. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn is_custom_name_visible(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getInterpolationDuration", + "isCustomNameVisible", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the interpolation duration of this display. - pub fn set_interpolation_duration( - &self, - duration: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(duration); + /// Sets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(visible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setInterpolationDuration", + "setVisibleByDefault", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the teleport duration of this display. - ///
    - ///
  • 0 means that updates are applied immediately.
  • - ///
  • 1 means that the display entity will move from current position to the updated one over one tick.
  • - ///
  • Higher values spread the movement over multiple ticks.
  • - ///
- pub fn teleport_duration(&self) -> Result> { - let sig = String::from("()I"); + /// Gets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn is_visible_by_default(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getTeleportDuration", + "isVisibleByDefault", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the teleport duration of this display. - pub fn set_teleport_duration(&self, duration: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(duration); + /// Get all players that are currently tracking this entity. + /// + /// 'Tracking' means that this entity has been sent to the player and that + /// they are receiving updates on its state. Note that the client's {@code + /// 'Entity Distance'} setting does not affect the range at which entities + /// are tracked. + pub fn tracked_by( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets whether the entity has a team colored (default: white) glow. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setTeleportDuration", + "setGlowing", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the view distance/range of this display. - pub fn view_range(&self) -> Result> { - let sig = String::from("()F"); + /// Gets whether the entity is glowing or not. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn is_glowing(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the entity is invulnerable or not. + /// + /// When an entity is invulnerable it can only be damaged by players in + /// creative mode. + pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setInvulnerable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether the entity is invulnerable or not. + pub fn is_invulnerable(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getViewRange", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + Ok(res.z()?) + } + /// Gets whether the entity is silent or not. + pub fn is_silent(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Sets the view distance/range of this display. - pub fn set_view_range(&self, range: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(range); + /// Sets whether the entity is silent or not. + /// + /// When an entity is silent it will not produce any sound. + pub fn set_silent(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setViewRange", + "setSilent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the shadow radius of this display. - pub fn shadow_radius(&self) -> Result> { - let sig = String::from("()F"); + /// Returns whether gravity applies to this entity. + pub fn has_gravity(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getShadowRadius", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + Ok(res.z()?) } - /// Sets the shadow radius of this display. - pub fn set_shadow_radius(&self, radius: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(radius); + /// Sets whether gravity applies to this entity. + pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gravity.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setShadowRadius", + "setGravity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the shadow strength of this display. - pub fn shadow_strength(&self) -> Result> { - let sig = String::from("()F"); + /// Gets the period of time (in ticks) before this entity can use a portal. + pub fn portal_cooldown(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getShadowStrength", + "getPortalCooldown", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + Ok(res.i()?) } - /// Sets the shadow strength of this display. - pub fn set_shadow_strength(&self, strength: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(strength); + /// Sets the period of time (in ticks) before this entity can use a portal. + pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(cooldown); let res = self.jni_ref().call_method( &self.jni_object(), - "setShadowStrength", + "setPortalCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the width of this display. - pub fn display_width(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDisplayWidth", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Sets the width of this display. - pub fn set_display_width(&self, width: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(width); + /// Returns a set of tags for this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn scoreboard_tags( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setDisplayWidth", + "getScoreboardTags", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the height of this display. - pub fn display_height(&self) -> Result> { - let sig = String::from("()F"); + /// Add a tag to this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn add_scoreboard_tag( + &self, + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "getDisplayHeight", + "addScoreboardTag", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + Ok(res.z()?) } - /// Sets the height if this display. - pub fn set_display_height(&self, height: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(height); + /// Removes a given tag from this entity. + pub fn remove_scoreboard_tag( + &self, + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setDisplayHeight", + "removeScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the amount of ticks before client-side interpolation will commence. - pub fn interpolation_delay(&self) -> Result> { - let sig = String::from("()I"); + /// Returns the reaction of the entity when moved by a piston. + pub fn piston_move_reaction( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getInterpolationDelay", + "getPistonMoveReaction", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the amount of ticks before client-side interpolation will commence. - pub fn set_interpolation_delay(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Get the closest cardinal {@link BlockFace} direction an entity is + /// currently facing. + /// + /// This will not return any non-cardinal directions such as + /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// + /// {@link Hanging} entities will override this call and thus their behavior + /// may be different. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the entity's current pose. + /// Note that the pose is only updated at the end of a tick, so may be + /// inconsistent with other methods. eg {@link Player#isSneaking()} being + /// true does not imply the current pose will be {@link Pose#SNEAKING} + pub fn pose(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Pose;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the category of spawn to which this entity belongs. + pub fn spawn_category( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setInterpolationDelay", + "getSpawnCategory", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the billboard setting of this entity. - /// The billboard setting controls the automatic rotation of the entity to - /// face the player. - pub fn billboard( + /// Checks if this entity has been spawned in a world. + /// + /// Entities not spawned in a world will not tick, be sent to players, or be + /// saved to the server files. + pub fn is_in_world(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get this entity as an NBT string. + /// + /// This string should not be relied upon as a serializable value. + pub fn as_string(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Crates an {@link EntitySnapshot} representing the current state of this entity. + pub fn create_snapshot( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Display/Billboard;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBillboard", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::DisplayBillboard::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntitySnapshot::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// + /// Note: Players cannot be copied. + pub fn copy( + &self, + to: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = to { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Lorg/bukkit/entity/Entity;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the billboard setting of this entity. - /// The billboard setting controls the automatic rotation of the entity to - /// face the player. - pub fn set_billboard( + /// Sets a metadata value in the implementing object's metadata store. + pub fn set_metadata( &self, - billboard: impl Into>, + metadata_key: impl Into, + new_metadata_value: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Display/Billboard;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(billboard.into().jni_object().clone()) + let sig = String::from("(Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBillboard", + "setMetadata", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the scoreboard team overridden glow color of this display. - pub fn glow_color_override( + /// Returns a list of previously set metadata values from the implementing + /// object's metadata store. + pub fn get_metadata( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Color;"); + metadata_key: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "getGlowColorOverride", + "getMetadata", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::metadata::MetadataValue::from_raw( + &self.jni_ref(), + obj, + )?); } - Ok(Some(crate::Color::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(new_vec) } - /// Sets the scoreboard team overridden glow color of this display. - pub fn set_glow_color_override( + /// Tests to see whether the implementing object contains the given + /// metadata value in its metadata store. + pub fn has_metadata( &self, - color: impl Into>, + metadata_key: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasMetadata", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Removes the given metadata value from the implementing object's + /// metadata store. + pub fn remove_metadata( + &self, + metadata_key: impl Into, + owning_plugin: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Color;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) + let sig = String::from("(Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setGlowColorOverride", + "removeMetadata", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the brightness override of the entity. - pub fn brightness( + /// Sends this sender multiple messages + pub fn send_message( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Display/Brightness;"); + sender: impl Into>, + messages: std::option::Option>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/util/UUID;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = messages { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_2); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the name of this command sender + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gets the custom name on a mob or block. If there is no name this method + /// will return null. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn custom_name(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBrightness", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCustomName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::DisplayBrightness::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Sets the brightness override of the entity. - pub fn set_brightness( + /// Sets a custom name on a mob or block. This name will be used in death + /// messages and can be sent to the client as a nameplate over the mob. + /// + /// Setting the name to null or an empty string will clear it. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn set_custom_name( &self, - brightness: impl Into>, + name: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Display/Brightness;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(brightness.into().jni_object().clone()) - }); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setBrightness", + "setCustomName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + pub fn persistent_data_container( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPersistentDataContainer", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Projectile<'mc> { + fn into(self) -> crate::entity::Entity<'mc> { + crate::entity::Entity::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Projectile into crate::entity::Entity") + } +} +#[repr(C)] +pub struct Marker<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Marker<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Marker<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Marker from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Marker")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Marker object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Marker<'mc> { /// Stores the entity's current position in the provided Location object. /// /// If the provided Location is null this method does nothing and returns @@ -54031,1049 +61043,1493 @@ impl<'mc> BlockDisplay<'mc> { self.jni_ref() .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Crates an {@link EntitySnapshot} representing the current state of this entity. + pub fn create_snapshot( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntitySnapshot::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// + /// Note: Players cannot be copied. + pub fn copy( + &self, + to: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = to { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Lorg/bukkit/entity/Entity;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets a metadata value in the implementing object's metadata store. + pub fn set_metadata( + &self, + metadata_key: impl Into, + new_metadata_value: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMetadata", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns a list of previously set metadata values from the implementing + /// object's metadata store. + pub fn get_metadata( + &self, + metadata_key: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMetadata", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::metadata::MetadataValue::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(new_vec) + } + /// Tests to see whether the implementing object contains the given + /// metadata value in its metadata store. + pub fn has_metadata( + &self, + metadata_key: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasMetadata", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Removes the given metadata value from the implementing object's + /// metadata store. + pub fn remove_metadata( + &self, + metadata_key: impl Into, + owning_plugin: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeMetadata", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sends this sender multiple messages + pub fn send_message( + &self, + sender: impl Into>, + messages: std::option::Option>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/util/UUID;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = messages { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_2); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the name of this command sender + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gets the custom name on a mob or block. If there is no name this method + /// will return null. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn custom_name(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCustomName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Sets a custom name on a mob or block. This name will be used in death + /// messages and can be sent to the client as a nameplate over the mob. + /// + /// Setting the name to null or an empty string will clear it. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn set_custom_name( + &self, + name: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCustomName", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + pub fn persistent_data_container( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPersistentDataContainer", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Marker<'mc> { + fn into(self) -> crate::entity::Entity<'mc> { + crate::entity::Entity::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Marker into crate::entity::Entity") + } +} +#[repr(C)] +pub struct Bogged<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Bogged<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Bogged<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Bogged from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Bogged")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Bogged object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Bogged<'mc> { + #[deprecated] + /// Gets the current type of this skeleton. + pub fn skeleton_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Skeleton/SkeletonType;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSkeletonType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::SkeletonSkeletonType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + #[deprecated] + + pub fn set_skeleton_type( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Skeleton/SkeletonType;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSkeletonType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether the entity is in its sheared state. + pub fn is_sheared(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSheared", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the entity is in its sheared state. + pub fn set_sheared(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSheared", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Bogged<'mc> { + fn into(self) -> crate::entity::AbstractSkeleton<'mc> { + crate::entity::AbstractSkeleton::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Bogged into crate::entity::AbstractSkeleton") + } +} +impl<'mc> Into> for Bogged<'mc> { + fn into(self) -> crate::entity::Shearable<'mc> { + crate::entity::Shearable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Bogged into crate::entity::Shearable") + } +} +#[repr(C)] +pub struct Wither<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Wither<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Wither<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Wither from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Wither")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Wither object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Wither<'mc> { + /// {@inheritDoc} + /// + /// This method will set the target of the {@link Head#CENTER center head} of + /// the wither. + pub fn set_target( + &self, + target: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(target.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTarget", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// This method will get the target of individual heads {@link Head} of the + /// wither. + pub fn get_target( + &self, + head: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/entity/Wither/Head;)Lorg/bukkit/entity/LivingEntity;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(head.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTarget", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::LivingEntity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Returns the wither's current invulnerability ticks. + pub fn invulnerability_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getInvulnerabilityTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the wither's current invulnerability ticks. + /// When invulnerability ticks reach 0, the wither will trigger an explosion. + pub fn set_invulnerability_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setInvulnerabilityTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the height of the living entity's eyes above its Location. + pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { + let sig = String::from("(Z)D"); + let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getEyeHeight", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } - /// Crates an {@link EntitySnapshot} representing the current state of this entity. - pub fn create_snapshot( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + /// Get a Location detailing the current eye position of the living entity. + pub fn eye_location(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::EntitySnapshot::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Creates a copy of this entity and all its data. Spawns the copy at the given location. - /// - /// Note: Players cannot be copied. - pub fn copy( - &self, - to: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = to { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")Lorg/bukkit/entity/Entity;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); + .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets a metadata value in the implementing object's metadata store. - pub fn set_metadata( + /// Gets all blocks along the living entity's line of sight. + /// + /// This list contains all blocks from the living entity's eye position to + /// target inclusive. This method considers all blocks as 1x1x1 in size. + pub fn get_line_of_sight( &self, - metadata_key: impl Into, - new_metadata_value: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setMetadata", + "getLineOfSight", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), ], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns a list of previously set metadata values from the implementing - /// object's metadata store. - pub fn get_metadata( - &self, - metadata_key: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMetadata", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::metadata::MetadataValue::from_raw( - &self.jni_ref(), - obj, - )?); + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); } Ok(new_vec) } - /// Tests to see whether the implementing object contains the given - /// metadata value in its metadata store. - pub fn has_metadata( + /// Gets the block that the living entity has targeted. + /// + /// This method considers all blocks as 1x1x1 in size. To take exact block + /// collision shapes into account, see {@link #getTargetBlockExact(int, + /// FluidCollisionMode)}. + pub fn get_target_block( &self, - metadata_key: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); + transparent: impl Into>, + max_distance: i32, + ) -> Result, Box> { + let sig = String::from("(Ljava/util/Set;I)Lorg/bukkit/block/Block;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "hasMetadata", + "getTargetBlock", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Removes the given metadata value from the implementing object's - /// metadata store. - pub fn remove_metadata( + /// Gets the last two blocks along the living entity's line of sight. + /// + /// The target block will be the last block in the list. This method + /// considers all blocks as 1x1x1 in size. + pub fn get_last_two_target_blocks( &self, - metadata_key: impl Into, - owning_plugin: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "removeMetadata", + "getLastTwoTargetBlocks", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Sends this sender multiple messages - pub fn send_message( + /// Gets the block that the living entity has targeted. + /// + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn get_target_block_exact( &self, - sender: impl Into>, - messages: std::option::Option>, - ) -> Result<(), Box> { + max_distance: i32, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) - }); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(max_distance); args.push(val_1); - if let Some(a) = messages { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); args.push(val_2); } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the name of this command sender - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + sig += ")Lorg/bukkit/block/Block;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTargetBlockExact", + sig.as_str(), + args, + ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::block::Block::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets the custom name on a mob or block. If there is no name this method - /// will return null. + /// Performs a ray trace that provides information on the targeted block. /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn custom_name(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn ray_trace_blocks( + &self, + max_distance: f64, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/util/RayTraceResult;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getCustomName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some( + Ok(Some(crate::util::RayTraceResult::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Returns the amount of air that the living entity has remaining, in + /// ticks. + pub fn remaining_air(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Sets a custom name on a mob or block. This name will be used in death - /// messages and can be sent to the client as a nameplate over the mob. - /// - /// Setting the name to null or an empty string will clear it. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn set_custom_name( - &self, - name: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + /// Sets the amount of air that the living entity has remaining, in ticks. + pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomName", + "setRemainingAir", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( + /// Returns the maximum amount of air the living entity can have, in ticks. + pub fn maximum_air(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the maximum amount of air the living entity can have, in ticks. + pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaximumAir", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the item that the player is using (eating food, drawing back a bow, + /// blocking, etc.) + pub fn item_in_use( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the number of ticks remaining for the current item's usage. + pub fn item_in_use_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "getItemInUseTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + Ok(res.i()?) } -} -impl<'mc> Into> for BlockDisplay<'mc> { - fn into(self) -> crate::entity::Display<'mc> { - crate::entity::Display::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockDisplay into crate::entity::Display") + /// Sets the number of ticks that remain for the current item's usage. + /// Applies to items that take time to use, like eating food, drawing a bow, + /// or throwing a trident. + pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItemInUseTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -#[repr(C)] -pub struct WitherSkull<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for WitherSkull<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Gets the time in ticks until the next arrow leaves the entity's body. + pub fn arrow_cooldown(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getArrowCooldown", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Sets the time in ticks until the next arrow leaves the entity's body. + pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setArrowCooldown", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -impl<'mc> JNIInstantiatable<'mc> for WitherSkull<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate WitherSkull from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/WitherSkull")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a WitherSkull object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Gets the amount of arrows in an entity's body. + pub fn arrows_in_body(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} - -impl<'mc> WitherSkull<'mc> { - /// Sets the charged status of the wither skull. - pub fn set_charged(&self, charged: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(charged.into()); + /// Set the amount of arrows in the entity's body. + pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(count); let res = self.jni_ref().call_method( &self.jni_object(), - "setCharged", + "setArrowsInBody", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not the wither skull is charged. - pub fn is_charged(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isCharged", sig.as_str(), vec![]); + /// Returns the living entity's current maximum no damage ticks. + /// + /// This is the maximum duration in which the living entity will not take + /// damage. + pub fn maximum_no_damage_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaximumNoDamageTicks", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets the direction the fireball should be flying towards. - /// - /// This is a convenience method, it will change the velocity direction and - /// acceleration direction, while keeping the power the same. - /// - /// Note: This method only uses the direction of the vector and will - /// normalize (a copy of) it. - /// - /// Special Case: When the given direction is - /// {@link Vector#isZero() zero}, the velocity and acceleration will also be - /// set to zero without keeping the power. - pub fn set_direction( - &self, - direction: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(direction.into().jni_object().clone()) - }); + /// Sets the living entity's current maximum no damage ticks. + pub fn set_maximum_no_damage_ticks( + &self, + ticks: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setDirection", + "setMaximumNoDamageTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Retrieve the direction this fireball is heading toward. The returned vector is not normalized. - pub fn direction(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); + /// Returns the living entity's last damage taken in the current no damage + /// ticks time. + /// + /// Only damage higher than this amount will further damage the living + /// entity. + pub fn last_damage(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.d()?) } - /// Sets the acceleration of the fireball. - /// The acceleration gets applied to the velocity every tick, depending on - /// the specific type of the fireball a damping / drag factor is applied so - /// that the velocity does not grow into infinity. - /// - /// Note: that the client may not respect non-default acceleration - /// power and will therefore mispredict the location of the fireball, causing - /// visual stutter. - pub fn set_acceleration( - &self, - acceleration: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(acceleration.into().jni_object().clone()) - }); + /// Sets the damage dealt within the current no damage ticks time period. + pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(damage); let res = self.jni_ref().call_method( &self.jni_object(), - "setAcceleration", + "setLastDamage", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the acceleration of this fireball. - pub fn acceleration(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAcceleration", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for WitherSkull<'mc> { - fn into(self) -> crate::entity::Fireball<'mc> { - crate::entity::Fireball::from_raw(&self.jni_ref(), self.1) - .expect("Error converting WitherSkull into crate::entity::Fireball") - } -} -#[repr(C)] -pub struct WitherSkeleton<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for WitherSkeleton<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for WitherSkeleton<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate WitherSkeleton from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/WitherSkeleton")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a WitherSkeleton object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> WitherSkeleton<'mc> { - #[deprecated] - /// Gets the current type of this skeleton. - pub fn skeleton_type( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Skeleton/SkeletonType;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSkeletonType", sig.as_str(), vec![]); + /// Returns the living entity's current no damage ticks. + pub fn no_damage_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNoDamageTicks", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::entity::SkeletonSkeletonType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - #[deprecated] - - pub fn set_skeleton_type( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Skeleton/SkeletonType;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Sets the living entity's current no damage ticks. + pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setSkeletonType", + "setNoDamageTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for WitherSkeleton<'mc> { - fn into(self) -> crate::entity::AbstractSkeleton<'mc> { - crate::entity::AbstractSkeleton::from_raw(&self.jni_ref(), self.1) - .expect("Error converting WitherSkeleton into crate::entity::AbstractSkeleton") - } -} -#[repr(C)] -pub struct ArmorStand<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for ArmorStand<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for ArmorStand<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ArmorStand from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ArmorStand")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ArmorStand object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> ArmorStand<'mc> { - #[deprecated] - /// Returns the item the armor stand is currently holding. - pub fn item_in_hand( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemInHand", sig.as_str(), vec![]); + /// Get the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn no_action_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNoActionTicks", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - #[deprecated] - /// Sets the item the armor stand is currently holding. - pub fn set_item_in_hand( - &self, - item: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); + /// Set the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemInHand", + "setNoActionTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Returns the item currently being worn by the armor stand on its feet. - pub fn boots(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + /// Gets the player identified as the killer of the living entity. + /// + /// May be null. + pub fn killer(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getBoots", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Player::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } #[deprecated] - /// Sets the item currently being worn by the armor stand on its feet. - pub fn set_boots( + /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. + pub fn add_potion_effect( &self, - item: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + effect: impl Into>, + force: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/potion/PotionEffect;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setBoots", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Returns the item currently being worn by the armor stand on its legs. - pub fn leggings(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + args.push(val_1); + if let Some(a) = force { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getLeggings", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - #[deprecated] - /// Sets the item currently being worn by the armor stand on its legs. - pub fn set_leggings( + /// Returns whether the living entity already has an existing effect of + /// the given {@link PotionEffectType} applied to it. + pub fn has_potion_effect( &self, - item: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + val_type: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLeggings", + "hasPotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Returns the item currently being worn by the armor stand on its chest. - pub fn chestplate( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getChestplate", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - #[deprecated] - /// Sets the item currently being worn by the armor stand on its chest. - pub fn set_chestplate( + /// Returns the active {@link PotionEffect} of the specified type. + /// + /// If the effect is not present on the entity then null will be returned. + pub fn get_potion_effect( &self, - item: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + val_type: impl Into>, + ) -> Result>, Box> { + let sig = + String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setChestplate", + "getPotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Returns the item currently being worn by the armor stand on its head. - pub fn helmet(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHelmet", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::potion::PotionEffect::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - #[deprecated] - /// Sets the item currently being worn by the armor stand on its head. - pub fn set_helmet( + /// Removes any effects present of the given {@link PotionEffectType}. + pub fn remove_potion_effect( &self, - item: impl Into>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setHelmet", + "removePotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the armor stand's body's current pose as a - /// {@link org.bukkit.util.EulerAngle}. - pub fn body_pose(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/EulerAngle;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBodyPose", sig.as_str(), vec![]); + /// Returns all currently active {@link PotionEffect}s on the living + /// entity. + pub fn active_potion_effects( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getActivePotionEffects", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::util::EulerAngle::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Sets the armor stand's body's current pose as a - /// {@link org.bukkit.util.EulerAngle}. - pub fn set_body_pose( + /// Checks whether the living entity has block line of sight to another. + /// + /// This uses the same algorithm that hostile mobs use to find the closest + /// player. + pub fn has_line_of_sight( &self, - pose: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/EulerAngle;)V"); + other: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(pose.into().jni_object().clone()) + jni::objects::JObject::from_raw(other.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBodyPose", + "hasLineOfSight", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Returns the armor stand's left arm's current pose as a - /// {@link org.bukkit.util.EulerAngle}. - pub fn left_arm_pose( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/EulerAngle;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLeftArmPose", sig.as_str(), vec![]); + /// Returns if the living entity despawns when away from players or not. + /// + /// By default, animals are not removed while other mobs are. + pub fn remove_when_far_away(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getRemoveWhenFarAway", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::util::EulerAngle::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets the armor stand's left arm's current pose as a - /// {@link org.bukkit.util.EulerAngle}. - pub fn set_left_arm_pose( - &self, - pose: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/EulerAngle;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(pose.into().jni_object().clone()) - }); + /// Sets whether or not the living entity despawns when away from players + /// or not. + pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(remove.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLeftArmPose", + "setRemoveWhenFarAway", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the armor stand's right arm's current pose as a - /// {@link org.bukkit.util.EulerAngle}. - pub fn right_arm_pose( + /// Gets the inventory with the equipment worn by the living entity. + pub fn equipment( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/EulerAngle;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getRightArmPose", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::EulerAngle::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::EntityEquipment::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the armor stand's right arm's current pose as a - /// {@link org.bukkit.util.EulerAngle}. - pub fn set_right_arm_pose( - &self, - pose: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/EulerAngle;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(pose.into().jni_object().clone()) - }); + /// Sets whether or not the living entity can pick up items. + pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(pickup.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setRightArmPose", + "setCanPickupItems", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the armor stand's left leg's current pose as a - /// {@link org.bukkit.util.EulerAngle}. - pub fn left_leg_pose( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/EulerAngle;"); + /// Gets if the living entity can pick up items. + pub fn can_pickup_items(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCanPickupItems", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns whether the entity is currently leashed. + pub fn is_leashed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the entity that is currently leading this entity. + pub fn leash_holder(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLeftLegPose", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::EulerAngle::from_raw(&self.jni_ref(), unsafe { + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the armor stand's left leg's current pose as a - /// {@link org.bukkit.util.EulerAngle}. - pub fn set_left_leg_pose( + /// Sets the leash on this entity to be held by the supplied entity. + /// + /// This method has no effect on EnderDragons, Withers, Players, or Bats. + /// Non-living entities excluding leashes will not persist as leash + /// holders. + pub fn set_leash_holder( &self, - pose: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/EulerAngle;)V"); + holder: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(pose.into().jni_object().clone()) + jni::objects::JObject::from_raw(holder.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLeftLegPose", + "setLeashHolder", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Returns the armor stand's right leg's current pose as a - /// {@link org.bukkit.util.EulerAngle}. - pub fn right_leg_pose( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/EulerAngle;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRightLegPose", sig.as_str(), vec![]); + /// Checks to see if an entity is gliding, such as using an Elytra. + pub fn is_gliding(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::EulerAngle::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets the armor stand's right leg's current pose as a - /// {@link org.bukkit.util.EulerAngle}. - pub fn set_right_leg_pose( - &self, - pose: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/EulerAngle;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(pose.into().jni_object().clone()) - }); + /// Makes entity start or stop gliding. This will work even if an Elytra + /// is not equipped, but will be reverted by the server immediately after + /// unless an event-cancelling mechanism is put in place. + pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gliding.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setRightLegPose", + "setGliding", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the armor stand's head's current pose as a - /// {@link org.bukkit.util.EulerAngle}. - pub fn head_pose(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/EulerAngle;"); + /// Checks to see if an entity is swimming. + pub fn is_swimming(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getHeadPose", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::EulerAngle::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets the armor stand's head's current pose as a - /// {@link org.bukkit.util.EulerAngle}. - pub fn set_head_pose( - &self, - pose: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/EulerAngle;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(pose.into().jni_object().clone()) - }); + /// Makes entity start or stop swimming. + /// This may have unexpected results if the entity is not in water. + pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(swimming.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setHeadPose", + "setSwimming", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether the armor stand has a base plate. - pub fn has_base_plate(&self) -> Result> { + /// Checks to see if an entity is currently riptiding. + pub fn is_riptiding(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasBasePlate", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the armor stand has a base plate. - pub fn set_base_plate(&self, base_plate: bool) -> Result<(), Box> { + /// Makes entity start or stop riptiding. + /// + /// Note: This does not damage attackable entities. + pub fn set_riptiding(&self, riptiding: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(base_plate.into()); + let val_1 = jni::objects::JValueGen::Bool(riptiding.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setBasePlate", + "setRiptiding", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether the armor stand should be visible or not. - pub fn is_visible(&self) -> Result> { + /// Returns whether this entity is slumbering. + pub fn is_sleeping(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isVisible", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the armor stand should be visible or not. - pub fn set_visible(&self, visible: bool) -> Result<(), Box> { + /// Gets if the entity is climbing. + pub fn is_climbing(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether an entity will have AI. + /// The entity will be completely unable to move if it has no AI. + pub fn set_ai(&self, ai: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(visible.into()); + let val_1 = jni::objects::JValueGen::Bool(ai.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisible", + "setAI", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether this armor stand has arms. - pub fn has_arms(&self) -> Result> { + /// Checks whether an entity has AI. + /// The entity will be completely unable to move if it has no AI. + pub fn has_ai(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "hasArms", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether this armor stand has arms. - pub fn set_arms(&self, arms: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(arms.into()); + /// Makes this entity attack the given entity with a melee attack. + /// Attack damage is calculated by the server from the attributes and + /// equipment of this mob, and knockback is applied to {@code target} as + /// appropriate. + pub fn attack( + &self, + target: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(target.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setArms", + "attack", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether this armor stand is scaled down. - pub fn is_small(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSmall", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Makes this entity swing their main hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their main hand. + pub fn swing_main_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets whether this armor stand is scaled down. - pub fn set_small(&self, small: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(small.into()); + /// Makes this entity swing their off hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their off hand. + pub fn swing_off_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Makes this entity flash red as if they were damaged. + pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); let res = self.jni_ref().call_method( &self.jni_object(), - "setSmall", + "playHurtAnimation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether this armor stand is a marker, meaning it has a very small - /// collision box. - pub fn is_marker(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isMarker", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether this armor stand is a marker, meaning it has a very small - /// collision box. - pub fn set_marker(&self, marker: bool) -> Result<(), Box> { + /// Set if this entity will be subject to collisions with other entities. + /// + /// Exemptions to this rule can be managed with + /// {@link #getCollidableExemptions()} + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not working for player collisions. This + /// method should therefore only be used to set the collision status of + /// non-player entities. + /// + /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in + /// combination with a {@link Scoreboard} and a {@link Team}. + pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(marker.into()); + let val_1 = jni::objects::JValueGen::Bool(collidable.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setMarker", + "setCollidable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Locks the equipment slot with the specified - /// {@link LockType locking mechanism}. - pub fn add_equipment_lock( + /// Gets if this entity is subject to collisions with other entities. + /// + /// Some entities might be exempted from the collidable rule of this entity. + /// Use {@link #getCollidableExemptions()} to get these. + /// + /// Please note that this method returns only the custom collidable state, + /// not whether the entity is non-collidable for other reasons such as being + /// dead. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not being accurate for player collisions. + /// This method should therefore only be used to check the collision status + /// of non-player entities. + /// + /// To check the collision behavior for a player, use + /// {@link Team.Option#COLLISION_RULE} in combination with a + /// {@link Scoreboard} and a {@link Team}. + pub fn is_collidable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets a mutable set of UUIDs of the entities which are exempt from the + /// entity's collidable rule and which's collision with this entity will + /// behave the opposite of it. + /// + /// This set can be modified to add or remove exemptions. + /// + /// For example if collidable is true and an entity is in the exemptions set + /// then it will not collide with it. Similarly if collidable is false and an + /// entity is in this set then it will still collide with it. + /// + /// Note these exemptions are not (currently) persistent. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in those exemptions not being accurate for player + /// collisions. This method should therefore only be used to exempt + /// non-player entities. + /// + /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} + /// in combination with a {@link Scoreboard} and a {@link Team}. + pub fn collidable_exemptions( &self, - slot: impl Into>, - lock_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from( - "(Lorg/bukkit/inventory/EquipmentSlot;Lorg/bukkit/entity/ArmorStand/LockType;)V", + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCollidableExemptions", + sig.as_str(), + vec![], ); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns the value of the memory specified. + /// + /// Note that the value is null when the specific entity does not have that + /// value by default. + pub fn get_memory( + &self, + memory_key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(slot.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(lock_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "addEquipmentLock", + "getMemory", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) } - /// Remove a {@link LockType locking mechanism}. - pub fn remove_equipment_lock( + /// Sets the value of the memory specified. + /// + /// Note that the value will not be persisted when the specific entity does + /// not have that value by default. + pub fn set_memory( &self, - slot: impl Into>, - lock_type: impl Into>, + memory_key: impl Into>, + memory_value: jni::objects::JObject<'mc>, ) -> Result<(), Box> { - let sig = String::from( - "(Lorg/bukkit/inventory/EquipmentSlot;Lorg/bukkit/entity/ArmorStand/LockType;)V", - ); + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(slot.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(lock_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Object(memory_value); let res = self.jni_ref().call_method( &self.jni_object(), - "removeEquipmentLock", + "setMemory", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), @@ -55083,1364 +62539,1466 @@ impl<'mc> ArmorStand<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns if the ArmorStand has the specified - /// {@link LockType locking mechanism}. - pub fn has_equipment_lock( + /// Get the {@link Sound} this entity will make when damaged. + pub fn hurt_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Get the {@link Sound} this entity will make on death. + pub fn death_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Get the {@link Sound} this entity will make when falling from the given + /// height (in blocks). The sound will often differ between either a small + /// or a big fall damage sound if the height exceeds 4 blocks. + pub fn get_fall_damage_sound( &self, - slot: impl Into>, - lock_type: impl Into>, - ) -> Result> { - let sig = String::from( - "(Lorg/bukkit/inventory/EquipmentSlot;Lorg/bukkit/entity/ArmorStand/LockType;)Z", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(slot.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(lock_type.into().jni_object().clone()) - }); + fall_height: i32, + ) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Int(fall_height); let res = self.jni_ref().call_method( &self.jni_object(), - "hasEquipmentLock", + "getFallDamageSound", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the height of the living entity's eyes above its Location. - pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { - let sig = String::from("(Z)D"); - let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); + /// Get the {@link Sound} this entity will make when falling from a small + /// height. + pub fn fall_damage_sound_small(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getEyeHeight", + "getFallDamageSoundSmall", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Get a Location detailing the current eye position of the living entity. - pub fn eye_location(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { + crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets all blocks along the living entity's line of sight. - /// - /// This list contains all blocks from the living entity's eye position to - /// target inclusive. This method considers all blocks as 1x1x1 in size. - pub fn get_line_of_sight( - &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { - let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(max_distance); + /// Get the {@link Sound} this entity will make when falling from a large + /// height. + pub fn fall_damage_sound_big(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLineOfSight", + "getFallDamageSoundBig", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![], ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the block that the living entity has targeted. - /// - /// This method considers all blocks as 1x1x1 in size. To take exact block - /// collision shapes into account, see {@link #getTargetBlockExact(int, - /// FluidCollisionMode)}. - pub fn get_target_block( + /// Get the {@link Sound} this entity will make when drinking the given + /// {@link ItemStack}. + pub fn get_drinking_sound( &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result, Box> { - let sig = String::from("(Ljava/util/Set;I)Lorg/bukkit/block/Block;"); + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "getTargetBlock", + "getDrinkingSound", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { + crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the last two blocks along the living entity's line of sight. - /// - /// The target block will be the last block in the list. This method - /// considers all blocks as 1x1x1 in size. - pub fn get_last_two_target_blocks( + /// Get the {@link Sound} this entity will make when eating the given + /// {@link ItemStack}. + pub fn get_eating_sound( &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { - let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "getLastTwoTargetBlocks", + "getEatingSound", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the block that the living entity has targeted. - /// - /// This takes the blocks' precise collision shapes into account. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn get_target_block_exact( + /// Returns true if this entity can breathe underwater and will not take + /// suffocation damage when its air supply reaches zero. + pub fn can_breathe_underwater(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "canBreatheUnderwater", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. + pub fn category( &self, - max_distance: i32, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(max_distance); - args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/block/Block;"; + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets whether the entity is invisible or not. + pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(invisible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getTargetBlockExact", + "setInvisible", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether the entity is invisible or not. + pub fn is_invisible(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the specified attribute instance from the object. This instance will + /// be backed directly to the object and any changes will be visible at once. + pub fn get_attribute( + &self, + attribute: impl Into>, + ) -> Result>, Box> { + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAttribute", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::block::Block::from_raw( + Ok(Some(crate::attribute::AttributeInstance::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Performs a ray trace that provides information on the targeted block. - /// - /// This takes the blocks' precise collision shapes into account. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn ray_trace_blocks( + /// Deals the given amount of damage to this entity from a specified + /// {@link DamageSource}. + pub fn damage( &self, - max_distance: f64, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { + amount: f64, + damage_source: std::option::Option>>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "D"; - let val_1 = jni::objects::JValueGen::Double(max_distance); + let val_1 = jni::objects::JValueGen::Double(amount); args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; + if let Some(a) = damage_source { + sig += "Lorg/bukkit/damage/DamageSource;"; let val_2 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); args.push(val_2); } - sig += ")Lorg/bukkit/util/RayTraceResult;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "damage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. + pub fn health(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::util::RayTraceResult::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.d()?) } - /// Returns the amount of air that the living entity has remaining, in - /// ticks. - pub fn remaining_air(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); + /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is + /// dead. + pub fn set_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setHealth", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the entity's absorption amount. + pub fn absorption_amount(&self) -> Result> { + let sig = String::from("()D"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAbsorptionAmount", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.d()?) } - /// Sets the amount of air that the living entity has remaining, in ticks. - pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets the entity's absorption amount. + /// + /// Note: The amount is capped to the value of + /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on + /// that attribute is currently unspecified and subject to change. + pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "setRemainingAir", + "setAbsorptionAmount", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the maximum amount of air the living entity can have, in ticks. - pub fn maximum_air(&self) -> Result> { - let sig = String::from("()I"); + #[deprecated] + /// Gets the maximum health this entity has. + pub fn max_health(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.d()?) } - /// Sets the maximum amount of air the living entity can have, in ticks. - pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + #[deprecated] + /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. + pub fn set_max_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaximumAir", + "setMaxHealth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the item that the player is using (eating food, drawing back a bow, - /// blocking, etc.) - pub fn item_in_use( + #[deprecated] + /// Resets the max health to the original amount. + pub fn reset_max_health(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Launches a {@link Projectile} from the ProjectileSource with an + /// initial velocity. + pub fn launch_projectile( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + projectile: jni::objects::JClass<'mc>, + velocity: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(projectile.into()); + args.push(val_1); + if let Some(a) = velocity { + sig += "Lorg/bukkit/util/Vector;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")LT;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) + } + /// Returns the {@link BossBar} of the {@link Boss} + pub fn boss_bar( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/boss/BossBar;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBossBar", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::ItemStack::from_raw( + Ok(Some(crate::boss::BossBar::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Gets the number of ticks remaining for the current item's usage. - pub fn item_in_use_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Stores the entity's current position in the provided Location object. + /// + /// If the provided Location is null this method does nothing and returns + /// null. + pub fn get_location( + &self, + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getItemInUseTicks", + "getLocation", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Sets the number of ticks that remain for the current item's usage. - /// Applies to items that take time to use, like eating food, drawing a bow, - /// or throwing a trident. - pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets this entity's velocity in meters per tick + pub fn set_velocity( + &self, + velocity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemInUseTicks", + "setVelocity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the time in ticks until the next arrow leaves the entity's body. - pub fn arrow_cooldown(&self) -> Result> { - let sig = String::from("()I"); + /// Gets this entity's current velocity + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the entity's height + pub fn height(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the entity's width + pub fn width(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the entity's current bounding box. + /// + /// The returned bounding box reflects the entity's current location and + /// size. + pub fn bounding_box( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns true if the entity is supported by a block. This value is a + /// state updated by the server and is not recalculated unless the entity + /// moves. + pub fn is_on_ground(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns true if the entity is in water. + pub fn is_in_water(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the current world this entity resides in + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the entity's rotation. + /// + /// Note that if the entity is affected by AI, it may override this rotation. + pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { + let sig = String::from("(FF)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); + let val_2 = jni::objects::JValueGen::Float(pitch); let res = self.jni_ref().call_method( &self.jni_object(), - "getArrowCooldown", + "setRotation", sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Teleports this entity to the given location. If this entity is riding a + /// vehicle, it will be dismounted prior to teleportation. + pub fn teleport( + &self, + location: impl Into>, + cause: std::option::Option< + impl Into>, + >, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = cause { + sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "teleport", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns a list of entities within a bounding box centered around this + /// entity + pub fn get_nearby_entities( + &self, + x: f64, + y: f64, + z: f64, + ) -> Result>, Box> { + let sig = String::from("(DDD)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Double(x); + let val_2 = jni::objects::JValueGen::Double(y); + let val_3 = jni::objects::JValueGen::Double(z); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNearbyEntities", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Returns a unique id for this entity + pub fn entity_id(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the time in ticks until the next arrow leaves the entity's body. - pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setArrowCooldown", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the amount of arrows in an entity's body. - pub fn arrows_in_body(&self) -> Result> { + /// Returns the entity's maximum fire ticks. + pub fn max_fire_ticks(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Set the amount of arrows in the entity's body. - pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { + /// Sets the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(count); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setArrowsInBody", + "setFireTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's current maximum no damage ticks. - /// - /// This is the maximum duration in which the living entity will not take - /// damage. - pub fn maximum_no_damage_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMaximumNoDamageTicks", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the living entity's current maximum no damage ticks. - pub fn set_maximum_no_damage_ticks( - &self, - ticks: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets if the entity has visual fire (it will always appear to be on fire). + pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaximumNoDamageTicks", + "setVisualFire", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's last damage taken in the current no damage - /// ticks time. - /// - /// Only damage higher than this amount will further damage the living - /// entity. - pub fn last_damage(&self) -> Result> { - let sig = String::from("()D"); + /// Gets if the entity has visual fire (it will always appear to be on fire). + pub fn is_visual_fire(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Sets the damage dealt within the current no damage ticks time period. - pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(damage); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLastDamage", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Returns the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Returns the living entity's current no damage ticks. - pub fn no_damage_ticks(&self) -> Result> { + /// Returns the entity's maximum freeze ticks (amount of ticks before it will + /// be fully frozen) + pub fn max_freeze_ticks(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getNoDamageTicks", + "getMaxFreezeTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the living entity's current no damage ticks. - pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Sets the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setNoDamageTicks", + "setFreezeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the ticks that this entity has performed no action. - /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn no_action_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getNoActionTicks", - sig.as_str(), - vec![], - ); + /// Gets if the entity is fully frozen (it has been in powdered snow for max + /// freeze ticks). + pub fn is_frozen(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the ticks that this entity has performed no action. - /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setNoActionTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Mark the entity's removal. + pub fn remove(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the player identified as the killer of the living entity. - /// - /// May be null. - pub fn killer(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Player;"); + /// Returns true if this entity has been marked for removal. + pub fn is_dead(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Player::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - #[deprecated] - /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. - pub fn add_potion_effect( - &self, - effect: impl Into>, - force: std::option::Option, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/potion/PotionEffect;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(effect.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = force { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")Z"; + /// Returns false if the entity has died, been despawned for some other + /// reason, or has not been added to the world. + pub fn is_valid(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the {@link Server} that contains this Entity + pub fn server(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Server;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Server::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns true if the entity gets persisted. + /// + /// By default all entities are persistent. An entity will also not get + /// persisted, if it is riding an entity that is not persistent. + /// + /// The persistent flag on players controls whether or not to save their + /// playerdata file when they quit. If a player is directly or indirectly + /// riding a non-persistent entity, the vehicle at the root and all its + /// passengers won't get persisted. + /// + /// This should not be confused with + /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls + /// despawning of living entities. + pub fn is_persistent(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); + .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns whether the living entity already has an existing effect of - /// the given {@link PotionEffectType} applied to it. - pub fn has_potion_effect( - &self, - val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Sets whether or not the entity gets persisted. + pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(persistent.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "hasPotionEffect", + "setPersistent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns the active {@link PotionEffect} of the specified type. - /// - /// If the effect is not present on the entity then null will be returned. - pub fn get_potion_effect( + #[deprecated] + /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. + pub fn passenger( &self, - val_type: impl Into>, - ) -> Result>, Box> { - let sig = - String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPotionEffect", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::potion::PotionEffect::from_raw( + Ok(Some(crate::entity::Entity::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Removes any effects present of the given {@link PotionEffectType}. - pub fn remove_potion_effect( + #[deprecated] + /// Set the passenger of a vehicle. + pub fn set_passenger( &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removePotionEffect", + "setPassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Returns all currently active {@link PotionEffect}s on the living - /// entity. - pub fn active_potion_effects( + /// Gets a list of passengers of this vehicle. + /// + /// The returned list will not be directly linked to the entity's current + /// passengers, and no guarantees are made as to its mutability. + pub fn passengers( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getActivePotionEffects", - sig.as_str(), - vec![], - ); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); } Ok(new_vec) } - /// Checks whether the living entity has block line of sight to another. - /// - /// This uses the same algorithm that hostile mobs use to find the closest - /// player. - pub fn has_line_of_sight( + /// Add a passenger to the vehicle. + pub fn add_passenger( &self, - other: impl Into>, + passenger: impl Into>, ) -> Result> { let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasLineOfSight", + "addPassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns if the living entity despawns when away from players or not. - /// - /// By default, animals are not removed while other mobs are. - pub fn remove_when_far_away(&self) -> Result> { - let sig = String::from("()Z"); + /// Remove a passenger from the vehicle. + pub fn remove_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getRemoveWhenFarAway", + "removePassenger", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not the living entity despawns when away from players - /// or not. - pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(remove.into()); + /// Check if a vehicle has passengers. + pub fn is_empty(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Eject any passenger. + pub fn eject(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the distance this entity has fallen + pub fn fall_distance(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the fall distance for this entity + pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setRemoveWhenFarAway", + "setFallDistance", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the inventory with the equipment worn by the living entity. - pub fn equipment( + #[deprecated] + /// Record the last {@link EntityDamageEvent} inflicted on this entity + pub fn set_last_damage_cause( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::EntityEquipment::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Sets whether or not the living entity can pick up items. - pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(pickup.into()); + event: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(event.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCanPickupItems", + "setLastDamageCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the living entity can pick up items. - pub fn can_pickup_items(&self) -> Result> { - let sig = String::from("()Z"); + /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. + /// This event may have been cancelled. + pub fn last_damage_cause( + &self, + ) -> Result>, Box> + { + let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCanPickupItems", + "getLastDamageCause", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns whether the entity is currently leashed. - pub fn is_leashed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets the entity that is currently leading this entity. - pub fn leash_holder(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + /// Returns a unique and persistent id for this entity + pub fn unique_id( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the leash on this entity to be held by the supplied entity. + /// Gets the amount of ticks this entity has lived for. /// - /// This method has no effect on EnderDragons, Withers, Players, or Bats. - /// Non-living entities excluding leashes will not persist as leash - /// holders. - pub fn set_leash_holder( + /// This is the equivalent to "age" in entities. + pub fn ticks_lived(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. May not be less than one + /// tick. + pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTicksLived", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Performs the specified {@link EntityEffect} for this entity. + /// + /// This will be viewable to all players near the entity. + /// + /// If the effect is not applicable to this class of entity, it will not play. + pub fn play_effect( &self, - holder: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(holder.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLeashHolder", + "playEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Checks to see if an entity is gliding, such as using an Elytra. - pub fn is_gliding(&self) -> Result> { - let sig = String::from("()Z"); + /// Get the type of the entity. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Makes entity start or stop gliding. This will work even if an Elytra - /// is not equipped, but will be reverted by the server immediately after - /// unless an event-cancelling mechanism is put in place. - pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gliding.into()); + /// Get the {@link Sound} this entity makes while swimming. + pub fn swim_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes when splashing in water. For most + /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_splash_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setGliding", + "getSwimSplashSound", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks to see if an entity is swimming. - pub fn is_swimming(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Makes entity start or stop swimming. - /// This may have unexpected results if the entity is not in water. - pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(swimming.into()); + /// Get the {@link Sound} this entity makes when splashing in water at high + /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_high_speed_splash_sound( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setSwimming", + "getSwimHighSpeedSplashSound", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Checks to see if an entity is currently using the Riptide enchantment. - pub fn is_riptiding(&self) -> Result> { + /// Returns whether this entity is inside a vehicle. + pub fn is_inside_vehicle(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns whether this entity is slumbering. - pub fn is_sleeping(&self) -> Result> { + /// Leave the current vehicle. If the entity is currently in a vehicle (and + /// is removed from it), true will be returned, otherwise false will be + /// returned. + pub fn leave_vehicle(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets if the entity is climbing. - pub fn is_climbing(&self) -> Result> { - let sig = String::from("()Z"); + /// Get the vehicle that this entity is inside. If there is no vehicle, + /// null will be returned. + pub fn vehicle( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets whether an entity will have AI. - /// The entity will be completely unable to move if it has no AI. - pub fn set_ai(&self, ai: bool) -> Result<(), Box> { + /// Sets whether or not to display the mob's custom name client side. The + /// name will be displayed above the mob similarly to a player. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(ai.into()); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setAI", + "setCustomNameVisible", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks whether an entity has AI. - /// The entity will be completely unable to move if it has no AI. - pub fn has_ai(&self) -> Result> { + /// Gets whether or not the mob's custom name is displayed client side. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn is_custom_name_visible(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Makes this entity attack the given entity with a melee attack. - /// Attack damage is calculated by the server from the attributes and - /// equipment of this mob, and knockback is applied to {@code target} as - /// appropriate. - pub fn attack( - &self, - target: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) - }); let res = self.jni_ref().call_method( &self.jni_object(), - "attack", + "isCustomNameVisible", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Makes this entity swing their main hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their main hand. - pub fn swing_main_hand(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Makes this entity swing their off hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their off hand. - pub fn swing_off_hand(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Makes this entity flash red as if they were damaged. - pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); + /// Sets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(visible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "playHurtAnimation", + "setVisibleByDefault", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Set if this entity will be subject to collisions with other entities. - /// - /// Exemptions to this rule can be managed with - /// {@link #getCollidableExemptions()} - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not working for player collisions. This - /// method should therefore only be used to set the collision status of - /// non-player entities. - /// - /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in - /// combination with a {@link Scoreboard} and a {@link Team}. - pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(collidable.into()); + /// Gets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn is_visible_by_default(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "setCollidable", + "isVisibleByDefault", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets if this entity is subject to collisions with other entities. - /// - /// Some entities might be exempted from the collidable rule of this entity. - /// Use {@link #getCollidableExemptions()} to get these. - /// - /// Please note that this method returns only the custom collidable state, - /// not whether the entity is non-collidable for other reasons such as being - /// dead. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not being accurate for player collisions. - /// This method should therefore only be used to check the collision status - /// of non-player entities. - /// - /// To check the collision behavior for a player, use - /// {@link Team.Option#COLLISION_RULE} in combination with a - /// {@link Scoreboard} and a {@link Team}. - pub fn is_collidable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets a mutable set of UUIDs of the entities which are exempt from the - /// entity's collidable rule and which's collision with this entity will - /// behave the opposite of it. - /// - /// This set can be modified to add or remove exemptions. - /// - /// For example if collidable is true and an entity is in the exemptions set - /// then it will not collide with it. Similarly if collidable is false and an - /// entity is in this set then it will still collide with it. - /// - /// Note these exemptions are not (currently) persistent. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in those exemptions not being accurate for player - /// collisions. This method should therefore only be used to exempt - /// non-player entities. + /// Get all players that are currently tracking this entity. /// - /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} - /// in combination with a {@link Scoreboard} and a {@link Team}. - pub fn collidable_exemptions( + /// 'Tracking' means that this entity has been sent to the player and that + /// they are receiving updates on its state. Note that the client's {@code + /// 'Entity Distance'} setting does not affect the range at which entities + /// are tracked. + pub fn tracked_by( &self, ) -> Result, Box> { let sig = String::from("()Ljava/util/Set;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCollidableExemptions", - sig.as_str(), - vec![], - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns the value of the memory specified. - /// - /// Note that the value is null when the specific entity does not have that - /// value by default. - pub fn get_memory( - &self, - memory_key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) - }); + /// Sets whether the entity has a team colored (default: white) glow. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getMemory", + "setGlowing", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether the entity is glowing or not. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn is_glowing(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(res.l()?)) + Ok(res.z()?) } - /// Sets the value of the memory specified. + /// Sets whether the entity is invulnerable or not. /// - /// Note that the value will not be persisted when the specific entity does - /// not have that value by default. - pub fn set_memory( - &self, - memory_key: impl Into>, - memory_value: jni::objects::JObject<'mc>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(memory_value); + /// When an entity is invulnerable it can only be damaged by players in + /// creative mode. + pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setMemory", + "setInvulnerable", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the {@link Sound} this entity will make when damaged. - pub fn hurt_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Gets whether the entity is invulnerable or not. + pub fn is_invulnerable(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.z()?) } - /// Get the {@link Sound} this entity will make on death. - pub fn death_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); + /// Gets whether the entity is silent or not. + pub fn is_silent(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.z()?) } - /// Get the {@link Sound} this entity will make when falling from the given - /// height (in blocks). The sound will often differ between either a small - /// or a big fall damage sound if the height exceeds 4 blocks. - pub fn get_fall_damage_sound( - &self, - fall_height: i32, - ) -> Result, Box> { - let sig = String::from("(I)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Int(fall_height); + /// Sets whether the entity is silent or not. + /// + /// When an entity is silent it will not produce any sound. + pub fn set_silent(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSound", + "setSilent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns whether gravity applies to this entity. + pub fn has_gravity(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Get the {@link Sound} this entity will make when falling from a small - /// height. - pub fn fall_damage_sound_small(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Sets whether gravity applies to this entity. + pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gravity.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSoundSmall", + "setGravity", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the {@link Sound} this entity will make when falling from a large - /// height. - pub fn fall_damage_sound_big(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Gets the period of time (in ticks) before this entity can use a portal. + pub fn portal_cooldown(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSoundBig", + "getPortalCooldown", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Get the {@link Sound} this entity will make when drinking the given - /// {@link ItemStack}. - pub fn get_drinking_sound( - &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) - }); + /// Sets the period of time (in ticks) before this entity can use a portal. + pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(cooldown); let res = self.jni_ref().call_method( &self.jni_object(), - "getDrinkingSound", + "setPortalCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the {@link Sound} this entity will make when eating the given - /// {@link ItemStack}. - pub fn get_eating_sound( + /// Returns a set of tags for this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn scoreboard_tags( &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) - }); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getEatingSound", + "getScoreboardTags", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns true if this entity can breathe underwater and will not take - /// suffocation damage when its air supply reaches zero. - pub fn can_breathe_underwater(&self) -> Result> { - let sig = String::from("()Z"); + /// Add a tag to this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn add_scoreboard_tag( + &self, + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "canBreatheUnderwater", + "addScoreboardTag", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. - pub fn category( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets whether the entity is invisible or not. - pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(invisible.into()); + /// Removes a given tag from this entity. + pub fn remove_scoreboard_tag( + &self, + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvisible", + "removeScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether the entity is invisible or not. - pub fn is_invisible(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the specified attribute instance from the object. This instance will - /// be backed directly to the object and any changes will be visible at once. - pub fn get_attribute( + /// Returns the reaction of the entity when moved by a piston. + pub fn piston_move_reaction( &self, - attribute: impl Into>, - ) -> Result>, Box> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getAttribute", + "getPistonMoveReaction", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::attribute::AttributeInstance::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Deals the given amount of damage to this entity from a specified - /// {@link DamageSource}. - pub fn damage( - &self, - amount: f64, - damage_source: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(amount); - args.push(val_1); - if let Some(a) = damage_source { - sig += "Lorg/bukkit/damage/DamageSource;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; + /// Get the closest cardinal {@link BlockFace} direction an entity is + /// currently facing. + /// + /// This will not return any non-cardinal directions such as + /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// + /// {@link Hanging} entities will override this call and thus their behavior + /// may be different. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "damage", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. - pub fn health(&self) -> Result> { - let sig = String::from("()D"); + /// Gets the entity's current pose. + /// Note that the pose is only updated at the end of a tick, so may be + /// inconsistent with other methods. eg {@link Player#isSneaking()} being + /// true does not imply the current pose will be {@link Pose#SNEAKING} + pub fn pose(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Pose;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is - /// dead. - pub fn set_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setHealth", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the entity's absorption amount. - pub fn absorption_amount(&self) -> Result> { - let sig = String::from("()D"); + /// Get the category of spawn to which this entity belongs. + pub fn spawn_category( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getAbsorptionAmount", + "getSpawnCategory", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the entity's absorption amount. + /// Checks if this entity has been spawned in a world. /// - /// Note: The amount is capped to the value of - /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on - /// that attribute is currently unspecified and subject to change. - pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(amount); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAbsorptionAmount", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Entities not spawned in a world will not tick, be sent to players, or be + /// saved to the server files. + pub fn is_in_world(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - #[deprecated] - /// Gets the maximum health this entity has. - pub fn max_health(&self) -> Result> { - let sig = String::from("()D"); + /// Get this entity as an NBT string. + /// + /// This string should not be relied upon as a serializable value. + pub fn as_string(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - #[deprecated] - /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. - pub fn set_max_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaxHealth", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - #[deprecated] - /// Resets the max health to the original amount. - pub fn reset_max_health(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Crates an {@link EntitySnapshot} representing the current state of this entity. + pub fn create_snapshot( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntitySnapshot::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Launches a {@link Projectile} from the ProjectileSource with an - /// initial velocity. - pub fn launch_projectile( + /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// + /// Note: Players cannot be copied. + pub fn copy( &self, - projectile: jni::objects::JClass<'mc>, - velocity: std::option::Option>>, - ) -> Result, Box> { + to: std::option::Option>>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/lang/Class;"; - let val_1 = jni::objects::JValueGen::Object(projectile.into()); - args.push(val_1); - if let Some(a) = velocity { - sig += "Lorg/bukkit/util/Vector;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { + if let Some(a) = to { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); - args.push(val_2); + args.push(val_1); } - sig += ")LT;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); + sig += ")Lorg/bukkit/entity/Entity;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -56448,31 +64006,55 @@ impl<'mc> ArmorStand<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for ArmorStand<'mc> { - fn into(self) -> crate::entity::LivingEntity<'mc> { - crate::entity::LivingEntity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ArmorStand into crate::entity::LivingEntity") +impl<'mc> Into> for Wither<'mc> { + fn into(self) -> crate::entity::Monster<'mc> { + crate::entity::Monster::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Wither into crate::entity::Monster") } } -pub enum ArmorStandLockType<'mc> {} -impl<'mc> std::fmt::Display for ArmorStandLockType<'mc> { +impl<'mc> Into> for Wither<'mc> { + fn into(self) -> crate::entity::Boss<'mc> { + crate::entity::Boss::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Wither into crate::entity::Boss") + } +} +pub enum WitherHead<'mc> { + Center { inner: WitherHeadStruct<'mc> }, + Left { inner: WitherHeadStruct<'mc> }, + Right { inner: WitherHeadStruct<'mc> }, +} +impl<'mc> std::fmt::Display for WitherHead<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + WitherHead::Center { .. } => f.write_str("CENTER"), + WitherHead::Left { .. } => f.write_str("LEFT"), + WitherHead::Right { .. } => f.write_str("RIGHT"), + } + } +} +impl<'mc> std::ops::Deref for WitherHead<'mc> { + type Target = WitherHeadStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + WitherHead::Center { inner } => inner, + WitherHead::Left { inner } => inner, + WitherHead::Right { inner } => inner, + } } } -impl<'mc> ArmorStandLockType<'mc> { +impl<'mc> WitherHead<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/ArmorStand/LockType"); + let cls = env.find_class("org/bukkit/entity/Wither/Head"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/ArmorStand/LockType;", + "(Ljava/lang/String;)Lorg/bukkit/entity/Wither/Head;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -56484,39 +64066,55 @@ impl<'mc> ArmorStandLockType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "CENTER" => Ok(WitherHead::Center { + inner: WitherHeadStruct::from_raw(env, obj)?, + }), + "LEFT" => Ok(WitherHead::Left { + inner: WitherHeadStruct::from_raw(env, obj)?, + }), + "RIGHT" => Ok(WitherHead::Right { + inner: WitherHeadStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct ArmorStandLockTypeStruct<'mc>( +pub struct WitherHeadStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ArmorStandLockType<'mc> { +impl<'mc> JNIRaw<'mc> for WitherHead<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Center { inner } => inner.0.clone(), + Self::Left { inner } => inner.0.clone(), + Self::Right { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Center { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Left { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Right { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for ArmorStandLockType<'mc> { +impl<'mc> JNIInstantiatable<'mc> for WitherHead<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate ArmorStandLockType from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate WitherHead from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ArmorStand/LockType")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Wither/Head")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ArmorStandLockType object, got {}", + "Invalid argument passed. Expected a WitherHead object, got {}", name ) .into()) @@ -56528,13 +64126,22 @@ impl<'mc> JNIInstantiatable<'mc> for ArmorStandLockType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "CENTER" => Ok(WitherHead::Center { + inner: WitherHeadStruct::from_raw(env, obj)?, + }), + "LEFT" => Ok(WitherHead::Left { + inner: WitherHeadStruct::from_raw(env, obj)?, + }), + "RIGHT" => Ok(WitherHead::Right { + inner: WitherHeadStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for ArmorStandLockTypeStruct<'mc> { +impl<'mc> JNIRaw<'mc> for WitherHeadStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -56542,21 +64149,20 @@ impl<'mc> JNIRaw<'mc> for ArmorStandLockTypeStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ArmorStandLockTypeStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for WitherHeadStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate ArmorStandLockTypeStruct from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate WitherHeadStruct from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ArmorStand/LockType")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Wither/Head")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ArmorStandLockTypeStruct object, got {}", + "Invalid argument passed. Expected a WitherHeadStruct object, got {}", name ) .into()) @@ -56566,17 +64172,17 @@ impl<'mc> JNIInstantiatable<'mc> for ArmorStandLockTypeStruct<'mc> { } } -impl<'mc> ArmorStandLockTypeStruct<'mc> { +impl<'mc> WitherHeadStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/ArmorStand/LockType;"); - let cls = jni.find_class("org/bukkit/entity/ArmorStand/LockType"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Wither/Head;"); + let cls = jni.find_class("org/bukkit/entity/Wither/Head"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::entity::ArmorStandLockType::from_raw(&jni, obj) + crate::entity::WitherHead::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -56585,12 +64191,12 @@ impl<'mc> ArmorStandLockTypeStruct<'mc> { } } #[repr(C)] -pub struct Creature<'mc>( +pub struct Sittable<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Creature<'mc> { +impl<'mc> JNIRaw<'mc> for Sittable<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -56598,18 +64204,18 @@ impl<'mc> JNIRaw<'mc> for Creature<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Creature<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Sittable<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Creature from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Sittable from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Creature")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Sittable")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Creature object, got {}", + "Invalid argument passed. Expected a Sittable object, got {}", name ) .into()) @@ -56619,111 +64225,43 @@ impl<'mc> JNIInstantiatable<'mc> for Creature<'mc> { } } -impl<'mc> Creature<'mc> { - /// Instructs this Mob to set the specified LivingEntity as its target. - /// - /// Hostile creatures may attack their target, and friendly creatures may - /// follow their target. - pub fn set_target( - &self, - target: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTarget", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the current target of this Mob - pub fn target( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); +impl<'mc> Sittable<'mc> { + /// Checks if this animal is sitting + pub fn is_sitting(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getTarget", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSitting", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::LivingEntity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Sets whether this mob is aware of its surroundings. - /// Unaware mobs will still move if pushed, attacked, etc. but will not move - /// or perform any actions on their own. Unaware mobs may also have other - /// unspecified behaviours disabled, such as drowning. - pub fn set_aware(&self, aware: bool) -> Result<(), Box> { + /// Sets if this animal is sitting. Will remove any path that the animal + /// was following beforehand. + pub fn set_sitting(&self, sitting: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(aware.into()); + let val_1 = jni::objects::JValueGen::Bool(sitting.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setAware", + "setSitting", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether this mob is aware of its surroundings. - /// Unaware mobs will still move if pushed, attacked, etc. but will not move - /// or perform any actions on their own. Unaware mobs may also have other - /// unspecified behaviours disabled, such as drowning. - pub fn is_aware(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isAware", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the {@link Sound} this mob makes while ambiently existing. This sound - /// may change depending on the current state of the entity, and may also - /// return null under specific conditions. This sound is not constant. - /// For instance, villagers will make different passive noises depending - /// on whether or not they are actively trading with a player, or make no - /// ambient noise while sleeping. - pub fn ambient_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAmbientSound", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Creature<'mc> { - fn into(self) -> crate::entity::Mob<'mc> { - crate::entity::Mob::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Creature into crate::entity::Mob") - } -} #[repr(C)] -pub struct Zoglin<'mc>( +pub struct Enderman<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Zoglin<'mc> { +impl<'mc> JNIRaw<'mc> for Enderman<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -56731,18 +64269,18 @@ impl<'mc> JNIRaw<'mc> for Zoglin<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Zoglin<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Enderman<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Zoglin from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Enderman from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Zoglin")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Enderman")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Zoglin object, got {}", + "Invalid argument passed. Expected a Enderman object, got {}", name ) .into()) @@ -56752,36 +64290,119 @@ impl<'mc> JNIInstantiatable<'mc> for Zoglin<'mc> { } } -impl<'mc> Zoglin<'mc> { - #[deprecated] - /// Gets whether the zoglin is a baby - pub fn is_baby(&self) -> Result> { +impl<'mc> Enderman<'mc> { + /// Gets the id and data of the block that the Enderman is carrying. + pub fn carried_material( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/MaterialData;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCarriedMaterial", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the id and data of the block that the Enderman is carrying. + pub fn set_carried_material( + &self, + material: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/material/MaterialData;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCarriedMaterial", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the data of the block that the Enderman is carrying. + pub fn carried_block( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCarriedBlock", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::block::data::BlockData::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets the data of the block that the Enderman is carrying. + pub fn set_carried_block( + &self, + block_data: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(block_data.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCarriedBlock", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Randomly teleports the Enderman in a 64x64x64 block cuboid region. + /// + /// If the randomly selected point is in the ground, the point is moved 1 block + /// down until air is found or until it goes under + /// {@link org.bukkit.World#getMinHeight()}. + /// + /// This method will return false if this Enderman is not alive, or if the + /// teleport location was obstructed, or if the teleport location is in water. + pub fn teleport(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isBaby", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "teleport", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Sets whether the zoglin is a baby - pub fn set_baby( + /// Randomly teleports the Enderman towards the given entity. + /// + /// The point is selected by drawing a vector between this enderman and the + /// given entity. That vector's length is set to 16 blocks. + /// That point is then moved within a 8x8x8 cuboid region. If the randomly + /// selected point is in the ground, the point is moved 1 block down until + /// air is found or until it goes under + /// {@link org.bukkit.World#getMinHeight()}. + /// + /// This method will return false if this Enderman is not alive, or if the + /// teleport location was obstructed, or if the teleport location is in water. + pub fn teleport_towards( &self, - flag: std::option::Option, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = flag { - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_1); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setBaby", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + entity: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "teleportTowards", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } /// Gets the height of the living entity's eyes above its Location. pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { @@ -56875,1269 +64496,1872 @@ impl<'mc> Zoglin<'mc> { /// considers all blocks as 1x1x1 in size. pub fn get_last_two_target_blocks( &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { - let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(max_distance); + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(max_distance); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLastTwoTargetBlocks", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Gets the block that the living entity has targeted. + /// + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn get_target_block_exact( + &self, + max_distance: i32, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/block/Block;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTargetBlockExact", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::block::Block::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Performs a ray trace that provides information on the targeted block. + /// + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn ray_trace_blocks( + &self, + max_distance: f64, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/util/RayTraceResult;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::util::RayTraceResult::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Returns the amount of air that the living entity has remaining, in + /// ticks. + pub fn remaining_air(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the amount of air that the living entity has remaining, in ticks. + pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRemainingAir", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the maximum amount of air the living entity can have, in ticks. + pub fn maximum_air(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the maximum amount of air the living entity can have, in ticks. + pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaximumAir", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the item that the player is using (eating food, drawing back a bow, + /// blocking, etc.) + pub fn item_in_use( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the number of ticks remaining for the current item's usage. + pub fn item_in_use_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItemInUseTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the number of ticks that remain for the current item's usage. + /// Applies to items that take time to use, like eating food, drawing a bow, + /// or throwing a trident. + pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItemInUseTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the time in ticks until the next arrow leaves the entity's body. + pub fn arrow_cooldown(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getArrowCooldown", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the time in ticks until the next arrow leaves the entity's body. + pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setArrowCooldown", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the amount of arrows in an entity's body. + pub fn arrows_in_body(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the amount of arrows in the entity's body. + pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(count); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setArrowsInBody", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the living entity's current maximum no damage ticks. + /// + /// This is the maximum duration in which the living entity will not take + /// damage. + pub fn maximum_no_damage_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaximumNoDamageTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the living entity's current maximum no damage ticks. + pub fn set_maximum_no_damage_ticks( + &self, + ticks: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaximumNoDamageTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the living entity's last damage taken in the current no damage + /// ticks time. + /// + /// Only damage higher than this amount will further damage the living + /// entity. + pub fn last_damage(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Sets the damage dealt within the current no damage ticks time period. + pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(damage); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLastDamage", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the living entity's current no damage ticks. + pub fn no_damage_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNoDamageTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the living entity's current no damage ticks. + pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setNoDamageTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn no_action_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNoActionTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setNoActionTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the player identified as the killer of the living entity. + /// + /// May be null. + pub fn killer(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Player::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + #[deprecated] + /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. + pub fn add_potion_effect( + &self, + effect: impl Into>, + force: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/potion/PotionEffect;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = force { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns whether the living entity already has an existing effect of + /// the given {@link PotionEffectType} applied to it. + pub fn has_potion_effect( + &self, + val_type: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasPotionEffect", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the active {@link PotionEffect} of the specified type. + /// + /// If the effect is not present on the entity then null will be returned. + pub fn get_potion_effect( + &self, + val_type: impl Into>, + ) -> Result>, Box> { + let sig = + String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPotionEffect", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::potion::PotionEffect::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Removes any effects present of the given {@link PotionEffectType}. + pub fn remove_potion_effect( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removePotionEffect", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns all currently active {@link PotionEffect}s on the living + /// entity. + pub fn active_potion_effects( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLastTwoTargetBlocks", + "getActivePotionEffects", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![], ); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); } Ok(new_vec) } - /// Gets the block that the living entity has targeted. - /// - /// This takes the blocks' precise collision shapes into account. + /// Checks whether the living entity has block line of sight to another. /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn get_target_block_exact( + /// This uses the same algorithm that hostile mobs use to find the closest + /// player. + pub fn has_line_of_sight( &self, - max_distance: i32, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(max_distance); - args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/block/Block;"; + other: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(other.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getTargetBlockExact", + "hasLineOfSight", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::block::Block::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Performs a ray trace that provides information on the targeted block. - /// - /// This takes the blocks' precise collision shapes into account. + /// Returns if the living entity despawns when away from players or not. /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn ray_trace_blocks( - &self, - max_distance: f64, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(max_distance); - args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/util/RayTraceResult;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::util::RayTraceResult::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Returns the amount of air that the living entity has remaining, in - /// ticks. - pub fn remaining_air(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the amount of air that the living entity has remaining, in ticks. - pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// By default, animals are not removed while other mobs are. + pub fn remove_when_far_away(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "setRemainingAir", + "getRemoveWhenFarAway", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns the maximum amount of air the living entity can have, in ticks. - pub fn maximum_air(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the maximum amount of air the living entity can have, in ticks. - pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets whether or not the living entity despawns when away from players + /// or not. + pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(remove.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaximumAir", + "setRemoveWhenFarAway", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the item that the player is using (eating food, drawing back a bow, - /// blocking, etc.) - pub fn item_in_use( + /// Gets the inventory with the equipment worn by the living entity. + pub fn equipment( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::ItemStack::from_raw( + Ok(Some(crate::inventory::EntityEquipment::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Gets the number of ticks remaining for the current item's usage. - pub fn item_in_use_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Sets whether or not the living entity can pick up items. + pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(pickup.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getItemInUseTicks", + "setCanPickupItems", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the number of ticks that remain for the current item's usage. - /// Applies to items that take time to use, like eating food, drawing a bow, - /// or throwing a trident. - pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Gets if the living entity can pick up items. + pub fn can_pickup_items(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemInUseTicks", + "getCanPickupItems", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the time in ticks until the next arrow leaves the entity's body. - pub fn arrow_cooldown(&self) -> Result> { - let sig = String::from("()I"); + /// Returns whether the entity is currently leashed. + pub fn is_leashed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the entity that is currently leading this entity. + pub fn leash_holder(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the leash on this entity to be held by the supplied entity. + /// + /// This method has no effect on EnderDragons, Withers, Players, or Bats. + /// Non-living entities excluding leashes will not persist as leash + /// holders. + pub fn set_leash_holder( + &self, + holder: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(holder.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getArrowCooldown", + "setLeashHolder", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the time in ticks until the next arrow leaves the entity's body. - pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Checks to see if an entity is gliding, such as using an Elytra. + pub fn is_gliding(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Makes entity start or stop gliding. This will work even if an Elytra + /// is not equipped, but will be reverted by the server immediately after + /// unless an event-cancelling mechanism is put in place. + pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gliding.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setArrowCooldown", + "setGliding", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the amount of arrows in an entity's body. - pub fn arrows_in_body(&self) -> Result> { - let sig = String::from("()I"); + /// Checks to see if an entity is swimming. + pub fn is_swimming(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the amount of arrows in the entity's body. - pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(count); + /// Makes entity start or stop swimming. + /// This may have unexpected results if the entity is not in water. + pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(swimming.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setArrowsInBody", + "setSwimming", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's current maximum no damage ticks. + /// Checks to see if an entity is currently riptiding. + pub fn is_riptiding(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Makes entity start or stop riptiding. /// - /// This is the maximum duration in which the living entity will not take - /// damage. - pub fn maximum_no_damage_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Note: This does not damage attackable entities. + pub fn set_riptiding(&self, riptiding: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(riptiding.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getMaximumNoDamageTicks", + "setRiptiding", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns whether this entity is slumbering. + pub fn is_sleeping(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the living entity's current maximum no damage ticks. - pub fn set_maximum_no_damage_ticks( - &self, - ticks: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Gets if the entity is climbing. + pub fn is_climbing(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether an entity will have AI. + /// The entity will be completely unable to move if it has no AI. + pub fn set_ai(&self, ai: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(ai.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaximumNoDamageTicks", + "setAI", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's last damage taken in the current no damage - /// ticks time. - /// - /// Only damage higher than this amount will further damage the living - /// entity. - pub fn last_damage(&self) -> Result> { - let sig = String::from("()D"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); + /// Checks whether an entity has AI. + /// The entity will be completely unable to move if it has no AI. + pub fn has_ai(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Sets the damage dealt within the current no damage ticks time period. - pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(damage); + /// Makes this entity attack the given entity with a melee attack. + /// Attack damage is calculated by the server from the attributes and + /// equipment of this mob, and knockback is applied to {@code target} as + /// appropriate. + pub fn attack( + &self, + target: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(target.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDamage", + "attack", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's current no damage ticks. - pub fn no_damage_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Makes this entity swing their main hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their main hand. + pub fn swing_main_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Makes this entity swing their off hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their off hand. + pub fn swing_off_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Makes this entity flash red as if they were damaged. + pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); let res = self.jni_ref().call_method( &self.jni_object(), - "getNoDamageTicks", + "playHurtAnimation", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the living entity's current no damage ticks. - pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Set if this entity will be subject to collisions with other entities. + /// + /// Exemptions to this rule can be managed with + /// {@link #getCollidableExemptions()} + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not working for player collisions. This + /// method should therefore only be used to set the collision status of + /// non-player entities. + /// + /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in + /// combination with a {@link Scoreboard} and a {@link Team}. + pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(collidable.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setNoDamageTicks", + "setCollidable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the ticks that this entity has performed no action. + /// Gets if this entity is subject to collisions with other entities. /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn no_action_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Some entities might be exempted from the collidable rule of this entity. + /// Use {@link #getCollidableExemptions()} to get these. + /// + /// Please note that this method returns only the custom collidable state, + /// not whether the entity is non-collidable for other reasons such as being + /// dead. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not being accurate for player collisions. + /// This method should therefore only be used to check the collision status + /// of non-player entities. + /// + /// To check the collision behavior for a player, use + /// {@link Team.Option#COLLISION_RULE} in combination with a + /// {@link Scoreboard} and a {@link Team}. + pub fn is_collidable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets a mutable set of UUIDs of the entities which are exempt from the + /// entity's collidable rule and which's collision with this entity will + /// behave the opposite of it. + /// + /// This set can be modified to add or remove exemptions. + /// + /// For example if collidable is true and an entity is in the exemptions set + /// then it will not collide with it. Similarly if collidable is false and an + /// entity is in this set then it will still collide with it. + /// + /// Note these exemptions are not (currently) persistent. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in those exemptions not being accurate for player + /// collisions. This method should therefore only be used to exempt + /// non-player entities. + /// + /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} + /// in combination with a {@link Scoreboard} and a {@link Team}. + pub fn collidable_exemptions( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getNoActionTicks", + "getCollidableExemptions", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the ticks that this entity has performed no action. + /// Returns the value of the memory specified. /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Note that the value is null when the specific entity does not have that + /// value by default. + pub fn get_memory( + &self, + memory_key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMemory", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) + } + /// Sets the value of the memory specified. + /// + /// Note that the value will not be persisted when the specific entity does + /// not have that value by default. + pub fn set_memory( + &self, + memory_key: impl Into>, + memory_value: jni::objects::JObject<'mc>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(memory_value); let res = self.jni_ref().call_method( &self.jni_object(), - "setNoActionTicks", + "setMemory", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the player identified as the killer of the living entity. - /// - /// May be null. - pub fn killer(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Player;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); + /// Get the {@link Sound} this entity will make when damaged. + pub fn hurt_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Player::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - #[deprecated] - /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. - pub fn add_potion_effect( - &self, - effect: impl Into>, - force: std::option::Option, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/potion/PotionEffect;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(effect.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = force { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")Z"; + /// Get the {@link Sound} this entity will make on death. + pub fn death_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); + .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Returns whether the living entity already has an existing effect of - /// the given {@link PotionEffectType} applied to it. - pub fn has_potion_effect( + /// Get the {@link Sound} this entity will make when falling from the given + /// height (in blocks). The sound will often differ between either a small + /// or a big fall damage sound if the height exceeds 4 blocks. + pub fn get_fall_damage_sound( &self, - val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + fall_height: i32, + ) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Int(fall_height); let res = self.jni_ref().call_method( &self.jni_object(), - "hasPotionEffect", + "getFallDamageSound", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the active {@link PotionEffect} of the specified type. - /// - /// If the effect is not present on the entity then null will be returned. - pub fn get_potion_effect( - &self, - val_type: impl Into>, - ) -> Result>, Box> { - let sig = - String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Get the {@link Sound} this entity will make when falling from a small + /// height. + pub fn fall_damage_sound_small(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPotionEffect", + "getFallDamageSoundSmall", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::potion::PotionEffect::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Removes any effects present of the given {@link PotionEffectType}. - pub fn remove_potion_effect( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Get the {@link Sound} this entity will make when falling from a large + /// height. + pub fn fall_damage_sound_big(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "removePotionEffect", + "getFallDamageSoundBig", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns all currently active {@link PotionEffect}s on the living - /// entity. - pub fn active_potion_effects( + /// Get the {@link Sound} this entity will make when drinking the given + /// {@link ItemStack}. + pub fn get_drinking_sound( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getActivePotionEffects", + "getDrinkingSound", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Checks whether the living entity has block line of sight to another. - /// - /// This uses the same algorithm that hostile mobs use to find the closest - /// player. - pub fn has_line_of_sight( + /// Get the {@link Sound} this entity will make when eating the given + /// {@link ItemStack}. + pub fn get_eating_sound( &self, - other: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasLineOfSight", + "getEatingSound", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns if the living entity despawns when away from players or not. - /// - /// By default, animals are not removed while other mobs are. - pub fn remove_when_far_away(&self) -> Result> { + /// Returns true if this entity can breathe underwater and will not take + /// suffocation damage when its air supply reaches zero. + pub fn can_breathe_underwater(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getRemoveWhenFarAway", + "canBreatheUnderwater", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not the living entity despawns when away from players - /// or not. - pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { + #[deprecated] + /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. + pub fn category( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets whether the entity is invisible or not. + pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(remove.into()); + let val_1 = jni::objects::JValueGen::Bool(invisible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setRemoveWhenFarAway", + "setInvisible", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the inventory with the equipment worn by the living entity. - pub fn equipment( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); + /// Gets whether the entity is invisible or not. + pub fn is_invisible(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the specified attribute instance from the object. This instance will + /// be backed directly to the object and any changes will be visible at once. + pub fn get_attribute( + &self, + attribute: impl Into>, + ) -> Result>, Box> { + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAttribute", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::EntityEquipment::from_raw( + Ok(Some(crate::attribute::AttributeInstance::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets whether or not the living entity can pick up items. - pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(pickup.into()); + /// Deals the given amount of damage to this entity from a specified + /// {@link DamageSource}. + pub fn damage( + &self, + amount: f64, + damage_source: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(amount); + args.push(val_1); + if let Some(a) = damage_source { + sig += "Lorg/bukkit/damage/DamageSource;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "damage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. + pub fn health(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is + /// dead. + pub fn set_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "setCanPickupItems", + "setHealth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the living entity can pick up items. - pub fn can_pickup_items(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the entity's absorption amount. + pub fn absorption_amount(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCanPickupItems", + "getAbsorptionAmount", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns whether the entity is currently leashed. - pub fn is_leashed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the entity that is currently leading this entity. - pub fn leash_holder(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.d()?) } - /// Sets the leash on this entity to be held by the supplied entity. + /// Sets the entity's absorption amount. /// - /// This method has no effect on EnderDragons, Withers, Players, or Bats. - /// Non-living entities excluding leashes will not persist as leash - /// holders. - pub fn set_leash_holder( - &self, - holder: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(holder.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLeashHolder", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Checks to see if an entity is gliding, such as using an Elytra. - pub fn is_gliding(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Makes entity start or stop gliding. This will work even if an Elytra - /// is not equipped, but will be reverted by the server immediately after - /// unless an event-cancelling mechanism is put in place. - pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gliding.into()); + /// Note: The amount is capped to the value of + /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on + /// that attribute is currently unspecified and subject to change. + pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "setGliding", + "setAbsorptionAmount", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks to see if an entity is swimming. - pub fn is_swimming(&self) -> Result> { - let sig = String::from("()Z"); + #[deprecated] + /// Gets the maximum health this entity has. + pub fn max_health(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Makes entity start or stop swimming. - /// This may have unexpected results if the entity is not in water. - pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(swimming.into()); + #[deprecated] + /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. + pub fn set_max_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "setSwimming", + "setMaxHealth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks to see if an entity is currently using the Riptide enchantment. - pub fn is_riptiding(&self) -> Result> { - let sig = String::from("()Z"); + #[deprecated] + /// Resets the max health to the original amount. + pub fn reset_max_health(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns whether this entity is slumbering. - pub fn is_sleeping(&self) -> Result> { - let sig = String::from("()Z"); + /// Launches a {@link Projectile} from the ProjectileSource with an + /// initial velocity. + pub fn launch_projectile( + &self, + projectile: jni::objects::JClass<'mc>, + velocity: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(projectile.into()); + args.push(val_1); + if let Some(a) = velocity { + sig += "Lorg/bukkit/util/Vector;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")LT;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.l()?) } - /// Gets if the entity is climbing. - pub fn is_climbing(&self) -> Result> { - let sig = String::from("()Z"); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Enderman<'mc> { + fn into(self) -> crate::entity::Monster<'mc> { + crate::entity::Monster::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Enderman into crate::entity::Monster") + } +} +#[repr(C)] +pub struct ChestBoat<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ChestBoat<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for ChestBoat<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate ChestBoat from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ChestBoat")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ChestBoat object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> ChestBoat<'mc> { + #[deprecated] + /// Gets the wood type of the boat. + pub fn wood_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/TreeSpecies;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getWoodType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::TreeSpecies::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets whether an entity will have AI. - /// The entity will be completely unable to move if it has no AI. - pub fn set_ai(&self, ai: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(ai.into()); + #[deprecated] + /// Sets the wood type of the boat. + pub fn set_wood_type( + &self, + species: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/TreeSpecies;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(species.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setAI", + "setWoodType", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks whether an entity has AI. - /// The entity will be completely unable to move if it has no AI. - pub fn has_ai(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); + /// Gets the type of the boat. + pub fn boat_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Boat/Type;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBoatType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::BoatType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Makes this entity attack the given entity with a melee attack. - /// Attack damage is calculated by the server from the attributes and - /// equipment of this mob, and knockback is applied to {@code target} as - /// appropriate. - pub fn attack( + /// Sets the type of the boat. + pub fn set_boat_type( &self, - target: impl Into>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + let sig = String::from("(Lorg/bukkit/entity/Boat/Type;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "attack", + "setBoatType", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Makes this entity swing their main hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their main hand. - pub fn swing_main_hand(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Makes this entity swing their off hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their off hand. - pub fn swing_off_hand(&self) -> Result<(), Box> { - let sig = String::from("()V"); + #[deprecated] + /// Gets the maximum speed of a boat. The speed is unrelated to the velocity. + pub fn max_speed(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getMaxSpeed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } - /// Makes this entity flash red as if they were damaged. - pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); + #[deprecated] + /// Sets the maximum speed of a boat. Must be nonnegative. Default is 0.4D. + pub fn set_max_speed(&self, speed: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(speed); let res = self.jni_ref().call_method( &self.jni_object(), - "playHurtAnimation", + "setMaxSpeed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Set if this entity will be subject to collisions with other entities. - /// - /// Exemptions to this rule can be managed with - /// {@link #getCollidableExemptions()} - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not working for player collisions. This - /// method should therefore only be used to set the collision status of - /// non-player entities. - /// - /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in - /// combination with a {@link Scoreboard} and a {@link Team}. - pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(collidable.into()); + #[deprecated] + /// Gets the deceleration rate (newSpeed = curSpeed * rate) of occupied boats. The default is 0.2. + pub fn occupied_deceleration(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref().call_method( &self.jni_object(), - "setCollidable", + "getOccupiedDeceleration", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets if this entity is subject to collisions with other entities. - /// - /// Some entities might be exempted from the collidable rule of this entity. - /// Use {@link #getCollidableExemptions()} to get these. - /// - /// Please note that this method returns only the custom collidable state, - /// not whether the entity is non-collidable for other reasons such as being - /// dead. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not being accurate for player collisions. - /// This method should therefore only be used to check the collision status - /// of non-player entities. - /// - /// To check the collision behavior for a player, use - /// {@link Team.Option#COLLISION_RULE} in combination with a - /// {@link Scoreboard} and a {@link Team}. - pub fn is_collidable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Gets a mutable set of UUIDs of the entities which are exempt from the - /// entity's collidable rule and which's collision with this entity will - /// behave the opposite of it. - /// - /// This set can be modified to add or remove exemptions. - /// - /// For example if collidable is true and an entity is in the exemptions set - /// then it will not collide with it. Similarly if collidable is false and an - /// entity is in this set then it will still collide with it. - /// - /// Note these exemptions are not (currently) persistent. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in those exemptions not being accurate for player - /// collisions. This method should therefore only be used to exempt - /// non-player entities. - /// - /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} - /// in combination with a {@link Scoreboard} and a {@link Team}. - pub fn collidable_exemptions( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + #[deprecated] + /// Sets the deceleration rate (newSpeed = curSpeed * rate) of occupied boats. Setting this to a higher value allows for quicker acceleration. The default is 0.2. + pub fn set_occupied_deceleration(&self, rate: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(rate); let res = self.jni_ref().call_method( &self.jni_object(), - "getCollidableExemptions", + "setOccupiedDeceleration", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns the value of the memory specified. - /// - /// Note that the value is null when the specific entity does not have that - /// value by default. - pub fn get_memory( - &self, - memory_key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) - }); + #[deprecated] + /// Gets the deceleration rate (newSpeed = curSpeed * rate) of unoccupied boats. The default is -1. Values below 0 indicate that no additional deceleration is imposed. + pub fn unoccupied_deceleration(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref().call_method( &self.jni_object(), - "getMemory", + "getUnoccupiedDeceleration", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(res.l()?)) + Ok(res.d()?) } - /// Sets the value of the memory specified. - /// - /// Note that the value will not be persisted when the specific entity does - /// not have that value by default. - pub fn set_memory( - &self, - memory_key: impl Into>, - memory_value: jni::objects::JObject<'mc>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(memory_value); + #[deprecated] + /// Sets the deceleration rate (newSpeed = curSpeed * rate) of unoccupied boats. Setting this to a higher value allows for quicker deceleration of boats when a player disembarks. The default is -1. Values below 0 indicate that no additional deceleration is imposed. + pub fn set_unoccupied_deceleration(&self, rate: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(rate); let res = self.jni_ref().call_method( &self.jni_object(), - "setMemory", + "setUnoccupiedDeceleration", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the {@link Sound} this entity will make when damaged. - pub fn hurt_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Get the {@link Sound} this entity will make on death. - pub fn death_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + #[deprecated] + /// Get whether boats can work on land. + pub fn work_on_land(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getWorkOnLand", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.z()?) } - /// Get the {@link Sound} this entity will make when falling from the given - /// height (in blocks). The sound will often differ between either a small - /// or a big fall damage sound if the height exceeds 4 blocks. - pub fn get_fall_damage_sound( - &self, - fall_height: i32, - ) -> Result, Box> { - let sig = String::from("(I)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Int(fall_height); + #[deprecated] + /// Set whether boats can work on land. + pub fn set_work_on_land(&self, work_on_land: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(work_on_land.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSound", + "setWorkOnLand", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the {@link Sound} this entity will make when falling from a small - /// height. - pub fn fall_damage_sound_small(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFallDamageSoundSmall", - sig.as_str(), - vec![], - ); + /// Gets the status of the boat. + pub fn status(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Boat/Status;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getStatus", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { + crate::entity::BoatStatus::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the {@link Sound} this entity will make when falling from a large - /// height. - pub fn fall_damage_sound_big(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFallDamageSoundBig", - sig.as_str(), - vec![], - ); + /// Gets the vehicle's velocity. + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the {@link Sound} this entity will make when drinking the given - /// {@link ItemStack}. - pub fn get_drinking_sound( + /// Sets the vehicle's velocity in meters per tick. + pub fn set_velocity( &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + vel: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + jni::objects::JObject::from_raw(vel.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getDrinkingSound", + "setVelocity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the object's inventory. + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the {@link Sound} this entity will make when eating the given - /// {@link ItemStack}. - pub fn get_eating_sound( + /// Set the loot table for a container or entity. + /// + /// To remove a loot table use null. Do not use {@link LootTables#EMPTY} to + /// clear a LootTable. + pub fn set_loot_table( &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + table: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/loot/LootTable;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + jni::objects::JObject::from_raw(table.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getEatingSound", + "setLootTable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the Loot Table attached to this block or entity. + /// + /// If an block/entity does not have a loot table, this will return null, NOT + /// an empty loot table. + pub fn loot_table( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/loot/LootTable;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLootTable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::loot::LootTable::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Returns true if this entity can breathe underwater and will not take - /// suffocation damage when its air supply reaches zero. - pub fn can_breathe_underwater(&self) -> Result> { - let sig = String::from("()Z"); + /// Set the seed used when this Loot Table generates loot. + pub fn set_seed(&self, seed: i64) -> Result<(), Box> { + let sig = String::from("(J)V"); + let val_1 = jni::objects::JValueGen::Long(seed); let res = self.jni_ref().call_method( &self.jni_object(), - "canBreatheUnderwater", + "setSeed", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the Loot Table's seed. + /// + /// The seed is used when generating loot. + pub fn seed(&self) -> Result> { + let sig = String::from("()J"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSeed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.j()?) } - #[deprecated] - /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. - pub fn category( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for ChestBoat<'mc> { + fn into(self) -> crate::entity::Boat<'mc> { + crate::entity::Boat::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ChestBoat into crate::entity::Boat") + } +} +impl<'mc> Into> for ChestBoat<'mc> { + fn into(self) -> crate::inventory::InventoryHolder<'mc> { + crate::inventory::InventoryHolder::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ChestBoat into crate::inventory::InventoryHolder") + } +} +impl<'mc> Into> for ChestBoat<'mc> { + fn into(self) -> crate::loot::Lootable<'mc> { + crate::loot::Lootable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ChestBoat into crate::loot::Lootable") + } +} +#[repr(C)] +pub struct Cat<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Cat<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Cat<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Cat from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Cat")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Cat object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Cat<'mc> { + /// Gets the current type of this cat. + pub fn cat_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Cat/Type;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCatType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { + crate::entity::CatType::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets whether the entity is invisible or not. - pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(invisible.into()); + /// Sets the current type of this cat. + pub fn set_cat_type( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Cat/Type;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvisible", + "setCatType", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invisible or not. - pub fn is_invisible(&self) -> Result> { - let sig = String::from("()Z"); + /// Get the collar color of this cat + pub fn collar_color(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/DyeColor;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCollarColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the specified attribute instance from the object. This instance will - /// be backed directly to the object and any changes will be visible at once. - pub fn get_attribute( + crate::DyeColor::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Set the collar color of this cat + pub fn set_collar_color( &self, - attribute: impl Into>, - ) -> Result>, Box> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", - ); + color: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/DyeColor;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + jni::objects::JObject::from_raw(color.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getAttribute", + "setCollarColor", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::attribute::AttributeInstance::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Deals the given amount of damage to this entity from a specified - /// {@link DamageSource}. - pub fn damage( - &self, - amount: f64, - damage_source: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(amount); - args.push(val_1); - if let Some(a) = damage_source { - sig += "Lorg/bukkit/damage/DamageSource;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "damage", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. - pub fn health(&self) -> Result> { - let sig = String::from("()D"); + /// Check if this is tamed + /// + /// If something is tamed then a player can not tame it through normal + /// methods, even if it does not belong to anyone in particular. + pub fn is_tamed(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isTamed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is - /// dead. - pub fn set_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); + /// Sets if this has been tamed. Not necessary if the method setOwner has + /// been used, as it tames automatically. + /// + /// If something is tamed then a player can not tame it through normal + /// methods, even if it does not belong to anyone in particular. + pub fn set_tamed(&self, tame: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(tame.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setHealth", + "setTamed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the entity's absorption amount. - pub fn absorption_amount(&self) -> Result> { - let sig = String::from("()D"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAbsorptionAmount", - sig.as_str(), - vec![], - ); + /// Gets the current owning AnimalTamer + pub fn owner( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/AnimalTamer;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::AnimalTamer::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the entity's absorption amount. + /// Set this to be owned by given AnimalTamer. /// - /// Note: The amount is capped to the value of - /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on - /// that attribute is currently unspecified and subject to change. - pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(amount); + /// If the owner is not null, this will be tamed and will have any current + /// path it is following removed. If the owner is set to null, this will be + /// untamed, and the current owner removed. + pub fn set_owner( + &self, + tamer: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/AnimalTamer;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(tamer.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setAbsorptionAmount", + "setOwner", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the maximum health this entity has. - pub fn max_health(&self) -> Result> { - let sig = String::from("()D"); + /// Get the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn breed_cause( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/UUID;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - #[deprecated] - /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. - pub fn set_max_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); + /// Set the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn set_breed_cause( + &self, + uuid: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/UUID;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxHealth", + "setBreedCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Resets the max health to the original amount. - pub fn reset_max_health(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Launches a {@link Projectile} from the ProjectileSource with an - /// initial velocity. - pub fn launch_projectile( - &self, - projectile: jni::objects::JClass<'mc>, - velocity: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/Class;"; - let val_1 = jni::objects::JValueGen::Object(projectile.into()); - args.push(val_1); - if let Some(a) = velocity { - sig += "Lorg/bukkit/util/Vector;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")LT;"; + /// Get whether or not this entity is in love mode and will produce + /// offspring with another entity in love mode. Will return true if + /// and only if {@link #getLoveModeTicks()} is greater than 0. + pub fn is_love_mode(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); + .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) + Ok(res.z()?) } - /// Gets the age of this mob. - pub fn age(&self) -> Result> { + /// Get the amount of ticks remaining for this entity in love mode. + /// If the entity is not in love mode, 0 will be returned. + pub fn love_mode_ticks(&self) -> Result> { let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getAge", sig.as_str(), vec![]); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLoveModeTicks", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the age of this mob. - pub fn set_age(&self, age: i32) -> Result<(), Box> { + /// Set the amount of ticks for which this entity should be in love mode. + /// Setting the love mode ticks to 600 is the equivalent of a player + /// feeding the entity their breeding item of choice. + pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(age); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setAge", + "setLoveModeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Lock the age of the animal, setting this will prevent the animal from maturing or getting ready for mating. + /// Check if the provided ItemStack is the correct item used for breeding + /// this entity.. + pub fn is_breed_item( + &self, + material: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Lock the age of the animal, setting this will prevent the animal from + /// maturing or getting ready for mating. pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); let val_1 = jni::objects::JValueGen::Bool(lock.into()); @@ -58150,7 +66374,6 @@ impl<'mc> Zoglin<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] /// Gets the current agelock. pub fn age_lock(&self) -> Result> { let sig = String::from("()Z"); @@ -58160,25 +66383,6 @@ impl<'mc> Zoglin<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the age of the mob to an adult - pub fn set_adult(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setAdult", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns true if the mob is an adult. - pub fn is_adult(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isAdult", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] /// Return the ability to breed of the animal. pub fn can_breed(&self) -> Result> { let sig = String::from("()Z"); @@ -58188,8 +66392,8 @@ impl<'mc> Zoglin<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Set breedability of the animal, if the animal is a baby and set to breed it will instantly grow up. + /// Set breedability of the animal, if the animal is a baby and set to + /// breed it will instantly grow up. pub fn set_breed(&self, breed: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); let val_1 = jni::objects::JValueGen::Bool(breed.into()); @@ -58202,31 +66406,54 @@ impl<'mc> Zoglin<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } + /// Checks if this animal is sitting + pub fn is_sitting(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSitting", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets if this animal is sitting. Will remove any path that the animal + /// was following beforehand. + pub fn set_sitting(&self, sitting: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(sitting.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSitting", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Zoglin<'mc> { - fn into(self) -> crate::entity::Monster<'mc> { - crate::entity::Monster::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Zoglin into crate::entity::Monster") +impl<'mc> Into> for Cat<'mc> { + fn into(self) -> crate::entity::Tameable<'mc> { + crate::entity::Tameable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Cat into crate::entity::Tameable") } } -impl<'mc> Into> for Zoglin<'mc> { - fn into(self) -> crate::entity::Ageable<'mc> { - crate::entity::Ageable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Zoglin into crate::entity::Ageable") +impl<'mc> Into> for Cat<'mc> { + fn into(self) -> crate::entity::Sittable<'mc> { + crate::entity::Sittable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Cat into crate::entity::Sittable") } } #[repr(C)] -pub struct LargeFireball<'mc>( +pub struct CatType<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for LargeFireball<'mc> { +impl<'mc> JNIRaw<'mc> for CatType<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -58234,18 +66461,18 @@ impl<'mc> JNIRaw<'mc> for LargeFireball<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for LargeFireball<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CatType<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate LargeFireball from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate CatType from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/LargeFireball")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Cat/Type")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a LargeFireball object, got {}", + "Invalid argument passed. Expected a CatType object, got {}", name ) .into()) @@ -58255,113 +66482,210 @@ impl<'mc> JNIInstantiatable<'mc> for LargeFireball<'mc> { } } -impl<'mc> LargeFireball<'mc> { - /// Gets the display {@link ItemStack}. - pub fn display_item( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDisplayItem", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +impl<'mc> CatType<'mc> { + #[deprecated] + + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Cat/Type;"); + let cls = jni.find_class("org/bukkit/entity/Cat/Type"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::CatType::from_raw(&jni, obj) } - /// Sets the display {@link ItemStack} for the fireball. - pub fn set_display_item( + #[deprecated] + + pub fn compare_to( &self, - item: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); + other: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(LT;)I"); + let val_1 = jni::objects::JValueGen::Object(other); let res = self.jni_ref().call_method( &self.jni_object(), - "setDisplayItem", + "compareTo", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Sets the direction the fireball should be flying towards. - /// - /// This is a convenience method, it will change the velocity direction and - /// acceleration direction, while keeping the power the same. - /// - /// Note: This method only uses the direction of the vector and will - /// normalize (a copy of) it. + #[deprecated] + + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "name", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + #[deprecated] + + pub fn ordinal(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "ordinal", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Return the namespaced identifier for this object. + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for CatType<'mc> { + fn into(self) -> crate::util::OldEnum<'mc> { + crate::util::OldEnum::from_raw(&self.jni_ref(), self.1) + .expect("Error converting CatType into crate::util::OldEnum") + } +} +impl<'mc> Into> for CatType<'mc> { + fn into(self) -> crate::Keyed<'mc> { + crate::Keyed::from_raw(&self.jni_ref(), self.1) + .expect("Error converting CatType into crate::Keyed") + } +} +#[repr(C)] +pub struct NPC<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for NPC<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for NPC<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate NPC from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/NPC")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a NPC object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> NPC<'mc> { + /// Instructs this Mob to set the specified LivingEntity as its target. /// - /// Special Case: When the given direction is - /// {@link Vector#isZero() zero}, the velocity and acceleration will also be - /// set to zero without keeping the power. - pub fn set_direction( + /// Hostile creatures may attack their target, and friendly creatures may + /// follow their target. + pub fn set_target( &self, - direction: impl Into>, + target: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(direction.into().jni_object().clone()) + jni::objects::JObject::from_raw(target.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setDirection", + "setTarget", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Retrieve the direction this fireball is heading toward. The returned vector is not normalized. - pub fn direction(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); + /// Gets the current target of this Mob + pub fn target( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTarget", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::LivingEntity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the acceleration of the fireball. - /// The acceleration gets applied to the velocity every tick, depending on - /// the specific type of the fireball a damping / drag factor is applied so - /// that the velocity does not grow into infinity. - /// - /// Note: that the client may not respect non-default acceleration - /// power and will therefore mispredict the location of the fireball, causing - /// visual stutter. - pub fn set_acceleration( - &self, - acceleration: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(acceleration.into().jni_object().clone()) - }); + /// Sets whether this mob is aware of its surroundings. + /// Unaware mobs will still move if pushed, attacked, etc. but will not move + /// or perform any actions on their own. Unaware mobs may also have other + /// unspecified behaviours disabled, such as drowning. + pub fn set_aware(&self, aware: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(aware.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setAcceleration", + "setAware", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the acceleration of this fireball. - pub fn acceleration(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); + /// Gets whether this mob is aware of its surroundings. + /// Unaware mobs will still move if pushed, attacked, etc. but will not move + /// or perform any actions on their own. Unaware mobs may also have other + /// unspecified behaviours disabled, such as drowning. + pub fn is_aware(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isAware", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the {@link Sound} this mob makes while ambiently existing. This sound + /// may change depending on the current state of the entity, and may also + /// return null under specific conditions. This sound is not constant. + /// For instance, villagers will make different passive noises depending + /// on whether or not they are actively trading with a player, or make no + /// ambient noise while sleeping. + pub fn ambient_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAcceleration", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAmbientSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) + })?)) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -58369,19 +66693,19 @@ impl<'mc> LargeFireball<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for LargeFireball<'mc> { - fn into(self) -> crate::entity::SizedFireball<'mc> { - crate::entity::SizedFireball::from_raw(&self.jni_ref(), self.1) - .expect("Error converting LargeFireball into crate::entity::SizedFireball") +impl<'mc> Into> for NPC<'mc> { + fn into(self) -> crate::entity::Creature<'mc> { + crate::entity::Creature::from_raw(&self.jni_ref(), self.1) + .expect("Error converting NPC into crate::entity::Creature") } } #[repr(C)] -pub struct Projectile<'mc>( +pub struct LingeringPotion<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Projectile<'mc> { +impl<'mc> JNIRaw<'mc> for LingeringPotion<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -58389,18 +66713,20 @@ impl<'mc> JNIRaw<'mc> for Projectile<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Projectile<'mc> { +impl<'mc> JNIInstantiatable<'mc> for LingeringPotion<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Projectile from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate LingeringPotion from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Projectile")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/LingeringPotion")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Projectile object, got {}", + "Invalid argument passed. Expected a LingeringPotion object, got {}", name ) .into()) @@ -58410,999 +66736,1059 @@ impl<'mc> JNIInstantiatable<'mc> for Projectile<'mc> { } } -impl<'mc> Projectile<'mc> { - /// Retrieve the shooter of this projectile. - pub fn shooter( +impl<'mc> LingeringPotion<'mc> { + /// Returns the effects that are applied by this potion. + pub fn effects( &self, - ) -> Result>, Box> { + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEffects", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Gets the ItemStack the thrown projectile will display. + pub fn item(&self) -> Result, Box> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")Lorg/bukkit/projectiles/ProjectileSource;"; + sig += ")Lorg/bukkit/inventory/ItemStack;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getShooter", sig.as_str(), args); + .call_method(&self.jni_object(), "getItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::projectiles::ProjectileSource::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the shooter of this projectile. - pub fn set_shooter( + /// Sets the display ItemStack for the thrown projectile. + pub fn set_item( &self, - source: impl Into>, + item: impl Into>, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/projectiles/ProjectileSource;"; + sig += "Lorg/bukkit/inventory/ItemStack;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(source.into().jni_object().clone()) + jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); args.push(val_1); sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "setShooter", sig.as_str(), args); + .call_method(&self.jni_object(), "setItem", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Determine if this projectile should bounce or not when it hits. - pub fn does_bounce(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "doesBounce", sig.as_str(), args); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for LingeringPotion<'mc> { + fn into(self) -> crate::entity::ThrownPotion<'mc> { + crate::entity::ThrownPotion::from_raw(&self.jni_ref(), self.1) + .expect("Error converting LingeringPotion into crate::entity::ThrownPotion") + } +} +#[repr(C)] +pub struct Spider<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Spider<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Spider<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Spider from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Spider")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Spider object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Spider<'mc> { + /// Gets the height of the living entity's eyes above its Location. + pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { + let sig = String::from("(Z)D"); + let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getEyeHeight", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - #[deprecated] - /// Set whether or not this projectile should bounce or not when it hits something. - pub fn set_bounce(&self, does_bounce: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(does_bounce.into()); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setBounce", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Get a Location detailing the current eye position of the living entity. + pub fn eye_location(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Stores the entity's current position in the provided Location object. + /// Gets all blocks along the living entity's line of sight. /// - /// If the provided Location is null this method does nothing and returns - /// null. - pub fn get_location( + /// This list contains all blocks from the living entity's eye position to + /// target inclusive. This method considers all blocks as 1x1x1 in size. + pub fn get_line_of_sight( &self, - loc: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocation", + "getLineOfSight", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(new_vec) } - /// Sets this entity's velocity in meters per tick - pub fn set_velocity( + /// Gets the block that the living entity has targeted. + /// + /// This method considers all blocks as 1x1x1 in size. To take exact block + /// collision shapes into account, see {@link #getTargetBlockExact(int, + /// FluidCollisionMode)}. + pub fn get_target_block( &self, - velocity: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + transparent: impl Into>, + max_distance: i32, + ) -> Result, Box> { + let sig = String::from("(Ljava/util/Set;I)Lorg/bukkit/block/Block;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setVelocity", + "getTargetBlock", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets this entity's current velocity - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + crate::block::Block::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the entity's height - pub fn height(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the entity's width - pub fn width(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the entity's current bounding box. + /// Gets the last two blocks along the living entity's line of sight. /// - /// The returned bounding box reflects the entity's current location and - /// size. - pub fn bounding_box( + /// The target block will be the last block in the list. This method + /// considers all blocks as 1x1x1 in size. + pub fn get_last_two_target_blocks( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns true if the entity is supported by a block. This value is a - /// state updated by the server and is not recalculated unless the entity - /// moves. - pub fn is_on_ground(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns true if the entity is in water. - pub fn is_in_water(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the current world this entity resides in - pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the entity's rotation. - /// - /// Note that if the entity is affected by AI, it may override this rotation. - pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { - let sig = String::from("(FF)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); - let val_2 = jni::objects::JValueGen::Float(pitch); + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setRotation", + "getLastTwoTargetBlocks", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Teleports this entity to the given location. If this entity is riding a - /// vehicle, it will be dismounted prior to teleportation. - pub fn teleport( + /// Gets the block that the living entity has targeted. + /// + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn get_target_block_exact( &self, - location: impl Into>, - cause: std::option::Option< - impl Into>, - >, - ) -> Result> { + max_distance: i32, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(max_distance); args.push(val_1); - if let Some(a) = cause { - sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; let val_2 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); args.push(val_2); } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "teleport", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns a list of entities within a bounding box centered around this - /// entity - pub fn get_nearby_entities( - &self, - x: f64, - y: f64, - z: f64, - ) -> Result>, Box> { - let sig = String::from("(DDD)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Double(x); - let val_2 = jni::objects::JValueGen::Double(y); - let val_3 = jni::objects::JValueGen::Double(z); + sig += ")Lorg/bukkit/block/Block;"; let res = self.jni_ref().call_method( &self.jni_object(), - "getNearbyEntities", + "getTargetBlockExact", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + args, ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - Ok(new_vec) + Ok(Some(crate::block::Block::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Returns a unique id for this entity - pub fn entity_id(&self) -> Result> { + /// Performs a ray trace that provides information on the targeted block. + /// + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn ray_trace_blocks( + &self, + max_distance: f64, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/util/RayTraceResult;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::util::RayTraceResult::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Returns the amount of air that the living entity has remaining, in + /// ticks. + pub fn remaining_air(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Returns the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn fire_ticks(&self) -> Result> { + /// Sets the amount of air that the living entity has remaining, in ticks. + pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRemainingAir", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the maximum amount of air the living entity can have, in ticks. + pub fn maximum_air(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the maximum amount of air the living entity can have, in ticks. + pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaximumAir", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the item that the player is using (eating food, drawing back a bow, + /// blocking, etc.) + pub fn item_in_use( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Returns the entity's maximum fire ticks. - pub fn max_fire_ticks(&self) -> Result> { + /// Gets the number of ticks remaining for the current item's usage. + pub fn item_in_use_ticks(&self) -> Result> { let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItemInUseTicks", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Sets the number of ticks that remain for the current item's usage. + /// Applies to items that take time to use, like eating food, drawing a bow, + /// or throwing a trident. + pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setFireTicks", + "setItemInUseTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets if the entity has visual fire (it will always appear to be on fire). - pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire.into()); + /// Gets the time in ticks until the next arrow leaves the entity's body. + pub fn arrow_cooldown(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisualFire", + "getArrowCooldown", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the time in ticks until the next arrow leaves the entity's body. + pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setArrowCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity has visual fire (it will always appear to be on fire). - pub fn is_visual_fire(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn freeze_ticks(&self) -> Result> { + /// Gets the amount of arrows in an entity's body. + pub fn arrows_in_body(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Returns the entity's maximum freeze ticks (amount of ticks before it will - /// be fully frozen) - pub fn max_freeze_ticks(&self) -> Result> { + /// Set the amount of arrows in the entity's body. + pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(count); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setArrowsInBody", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the living entity's current maximum no damage ticks. + /// + /// This is the maximum duration in which the living entity will not take + /// damage. + pub fn maximum_no_damage_ticks(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getMaxFreezeTicks", + "getMaximumNoDamageTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Sets the living entity's current maximum no damage ticks. + pub fn set_maximum_no_damage_ticks( + &self, + ticks: i32, + ) -> Result<(), Box> { let sig = String::from("(I)V"); let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setFreezeTicks", + "setMaximumNoDamageTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity is fully frozen (it has been in powdered snow for max - /// freeze ticks). - pub fn is_frozen(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); + /// Returns the living entity's last damage taken in the current no damage + /// ticks time. + /// + /// Only damage higher than this amount will further damage the living + /// entity. + pub fn last_damage(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Mark the entity's removal. - pub fn remove(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); + /// Sets the damage dealt within the current no damage ticks time period. + pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(damage); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLastDamage", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns true if this entity has been marked for removal. - pub fn is_dead(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns false if the entity has died, been despawned for some other - /// reason, or has not been added to the world. - pub fn is_valid(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); + /// Returns the living entity's current no damage ticks. + pub fn no_damage_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNoDamageTicks", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Gets the {@link Server} that contains this Entity - pub fn server(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Server;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Server::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Sets the living entity's current no damage ticks. + pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setNoDamageTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns true if the entity gets persisted. - /// - /// By default all entities are persistent. An entity will also not get - /// persisted, if it is riding an entity that is not persistent. - /// - /// The persistent flag on players controls whether or not to save their - /// playerdata file when they quit. If a player is directly or indirectly - /// riding a non-persistent entity, the vehicle at the root and all its - /// passengers won't get persisted. + /// Get the ticks that this entity has performed no action. /// - /// This should not be confused with - /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls - /// despawning of living entities. - pub fn is_persistent(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn no_action_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNoActionTicks", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets whether or not the entity gets persisted. - pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(persistent.into()); + /// Set the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setPersistent", + "setNoActionTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. - pub fn passenger( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); + /// Gets the player identified as the killer of the living entity. + /// + /// May be null. + pub fn killer(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Entity::from_raw( + Ok(Some(crate::entity::Player::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } #[deprecated] - /// Set the passenger of a vehicle. - pub fn set_passenger( + /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. + pub fn add_potion_effect( &self, - passenger: impl Into>, + effect: impl Into>, + force: std::option::Option, ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/potion/PotionEffect;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPassenger", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets a list of passengers of this vehicle. - /// - /// The returned list will not be directly linked to the entity's current - /// passengers, and no guarantees are made as to its mutability. - pub fn passengers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + args.push(val_1); + if let Some(a) = force { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(res.z()?) } - /// Add a passenger to the vehicle. - pub fn add_passenger( + /// Returns whether the living entity already has an existing effect of + /// the given {@link PotionEffectType} applied to it. + pub fn has_potion_effect( &self, - passenger: impl Into>, + val_type: impl Into>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "addPassenger", + "hasPotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Remove a passenger from the vehicle. - pub fn remove_passenger( + /// Returns the active {@link PotionEffect} of the specified type. + /// + /// If the effect is not present on the entity then null will be returned. + pub fn get_potion_effect( &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + val_type: impl Into>, + ) -> Result>, Box> { + let sig = + String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removePassenger", + "getPotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Check if a vehicle has passengers. - pub fn is_empty(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Eject any passenger. - pub fn eject(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the distance this entity has fallen - pub fn fall_distance(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Sets the fall distance for this entity - pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(distance); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFallDistance", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::potion::PotionEffect::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - #[deprecated] - /// Record the last {@link EntityDamageEvent} inflicted on this entity - pub fn set_last_damage_cause( + /// Removes any effects present of the given {@link PotionEffectType}. + pub fn remove_potion_effect( &self, - event: impl Into>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(event.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDamageCause", + "removePotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. - /// This event may have been cancelled. - pub fn last_damage_cause( + /// Returns all currently active {@link PotionEffect}s on the living + /// entity. + pub fn active_potion_effects( &self, - ) -> Result>, Box> - { - let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLastDamageCause", + "getActivePotionEffects", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); } - Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Returns a unique and persistent id for this entity - pub fn unique_id( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. - pub fn ticks_lived(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. May not be less than one - /// tick. - pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(value); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTicksLived", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(new_vec) } - /// Performs the specified {@link EntityEffect} for this entity. - /// - /// This will be viewable to all players near the entity. + /// Checks whether the living entity has block line of sight to another. /// - /// If the effect is not applicable to this class of entity, it will not play. - pub fn play_effect( + /// This uses the same algorithm that hostile mobs use to find the closest + /// player. + pub fn has_line_of_sight( &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); + other: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(other.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "playEffect", + "hasLineOfSight", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the type of the entity. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity makes while swimming. - pub fn swim_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Get the {@link Sound} this entity makes when splashing in water. For most - /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_splash_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Returns if the living entity despawns when away from players or not. + /// + /// By default, animals are not removed while other mobs are. + pub fn remove_when_far_away(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimSplashSound", + "getRemoveWhenFarAway", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Get the {@link Sound} this entity makes when splashing in water at high - /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_high_speed_splash_sound( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Sets whether or not the living entity despawns when away from players + /// or not. + pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(remove.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimHighSpeedSplashSound", + "setRemoveWhenFarAway", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns whether this entity is inside a vehicle. - pub fn is_inside_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Leave the current vehicle. If the entity is currently in a vehicle (and - /// is removed from it), true will be returned, otherwise false will be - /// returned. - pub fn leave_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the vehicle that this entity is inside. If there is no vehicle, - /// null will be returned. - pub fn vehicle( + /// Gets the inventory with the equipment worn by the living entity. + pub fn equipment( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Entity::from_raw( + Ok(Some(crate::inventory::EntityEquipment::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets whether or not to display the mob's custom name client side. The - /// name will be displayed above the mob similarly to a player. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { + /// Sets whether or not the living entity can pick up items. + pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(pickup.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomNameVisible", + "setCanPickupItems", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not the mob's custom name is displayed client side. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn is_custom_name_visible(&self) -> Result> { + /// Gets if the living entity can pick up items. + pub fn can_pickup_items(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "isCustomNameVisible", + "getCanPickupItems", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(visible.into()); + /// Returns whether the entity is currently leashed. + pub fn is_leashed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the entity that is currently leading this entity. + pub fn leash_holder(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the leash on this entity to be held by the supplied entity. + /// + /// This method has no effect on EnderDragons, Withers, Players, or Bats. + /// Non-living entities excluding leashes will not persist as leash + /// holders. + pub fn set_leash_holder( + &self, + holder: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(holder.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisibleByDefault", + "setLeashHolder", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn is_visible_by_default(&self) -> Result> { + /// Checks to see if an entity is gliding, such as using an Elytra. + pub fn is_gliding(&self) -> Result> { let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Makes entity start or stop gliding. This will work even if an Elytra + /// is not equipped, but will be reverted by the server immediately after + /// unless an event-cancelling mechanism is put in place. + pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gliding.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "isVisibleByDefault", + "setGliding", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get all players that are currently tracking this entity. - /// - /// 'Tracking' means that this entity has been sent to the player and that - /// they are receiving updates on its state. Note that the client's {@code - /// 'Entity Distance'} setting does not affect the range at which entities - /// are tracked. - pub fn tracked_by( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Checks to see if an entity is swimming. + pub fn is_swimming(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets whether the entity has a team colored (default: white) glow. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { + /// Makes entity start or stop swimming. + /// This may have unexpected results if the entity is not in water. + pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(swimming.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setGlowing", + "setSwimming", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is glowing or not. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn is_glowing(&self) -> Result> { + /// Checks to see if an entity is currently riptiding. + pub fn is_riptiding(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the entity is invulnerable or not. + /// Makes entity start or stop riptiding. /// - /// When an entity is invulnerable it can only be damaged by players in - /// creative mode. - pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { + /// Note: This does not damage attackable entities. + pub fn set_riptiding(&self, riptiding: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(riptiding.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvulnerable", + "setRiptiding", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invulnerable or not. - pub fn is_invulnerable(&self) -> Result> { + /// Returns whether this entity is slumbering. + pub fn is_sleeping(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets whether the entity is silent or not. - pub fn is_silent(&self) -> Result> { + /// Gets if the entity is climbing. + pub fn is_climbing(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the entity is silent or not. - /// - /// When an entity is silent it will not produce any sound. - pub fn set_silent(&self, flag: bool) -> Result<(), Box> { + /// Sets whether an entity will have AI. + /// The entity will be completely unable to move if it has no AI. + pub fn set_ai(&self, ai: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(ai.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setSilent", + "setAI", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether gravity applies to this entity. - pub fn has_gravity(&self) -> Result> { + /// Checks whether an entity has AI. + /// The entity will be completely unable to move if it has no AI. + pub fn has_ai(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether gravity applies to this entity. - pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gravity.into()); + /// Makes this entity attack the given entity with a melee attack. + /// Attack damage is calculated by the server from the attributes and + /// equipment of this mob, and knockback is applied to {@code target} as + /// appropriate. + pub fn attack( + &self, + target: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(target.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setGravity", + "attack", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the period of time (in ticks) before this entity can use a portal. - pub fn portal_cooldown(&self) -> Result> { - let sig = String::from("()I"); + /// Makes this entity swing their main hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their main hand. + pub fn swing_main_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Makes this entity swing their off hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their off hand. + pub fn swing_off_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Makes this entity flash red as if they were damaged. + pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); let res = self.jni_ref().call_method( &self.jni_object(), - "getPortalCooldown", + "playHurtAnimation", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the period of time (in ticks) before this entity can use a portal. - pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(cooldown); + /// Set if this entity will be subject to collisions with other entities. + /// + /// Exemptions to this rule can be managed with + /// {@link #getCollidableExemptions()} + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not working for player collisions. This + /// method should therefore only be used to set the collision status of + /// non-player entities. + /// + /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in + /// combination with a {@link Scoreboard} and a {@link Team}. + pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(collidable.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setPortalCooldown", + "setCollidable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a set of tags for this entity. + /// Gets if this entity is subject to collisions with other entities. /// - /// Entities can have no more than 1024 tags. - pub fn scoreboard_tags( + /// Some entities might be exempted from the collidable rule of this entity. + /// Use {@link #getCollidableExemptions()} to get these. + /// + /// Please note that this method returns only the custom collidable state, + /// not whether the entity is non-collidable for other reasons such as being + /// dead. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not being accurate for player collisions. + /// This method should therefore only be used to check the collision status + /// of non-player entities. + /// + /// To check the collision behavior for a player, use + /// {@link Team.Option#COLLISION_RULE} in combination with a + /// {@link Scoreboard} and a {@link Team}. + pub fn is_collidable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets a mutable set of UUIDs of the entities which are exempt from the + /// entity's collidable rule and which's collision with this entity will + /// behave the opposite of it. + /// + /// This set can be modified to add or remove exemptions. + /// + /// For example if collidable is true and an entity is in the exemptions set + /// then it will not collide with it. Similarly if collidable is false and an + /// entity is in this set then it will still collide with it. + /// + /// Note these exemptions are not (currently) persistent. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in those exemptions not being accurate for player + /// collisions. This method should therefore only be used to exempt + /// non-player entities. + /// + /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} + /// in combination with a {@link Scoreboard} and a {@link Team}. + pub fn collidable_exemptions( &self, ) -> Result, Box> { let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getScoreboardTags", + "getCollidableExemptions", sig.as_str(), vec![], ); @@ -59411,383 +67797,389 @@ impl<'mc> Projectile<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Add a tag to this entity. + /// Returns the value of the memory specified. /// - /// Entities can have no more than 1024 tags. - pub fn add_scoreboard_tag( + /// Note that the value is null when the specific entity does not have that + /// value by default. + pub fn get_memory( &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); + memory_key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "addScoreboardTag", + "getMemory", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) + } + /// Sets the value of the memory specified. + /// + /// Note that the value will not be persisted when the specific entity does + /// not have that value by default. + pub fn set_memory( + &self, + memory_key: impl Into>, + memory_value: jni::objects::JObject<'mc>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(memory_value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMemory", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the {@link Sound} this entity will make when damaged. + pub fn hurt_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Get the {@link Sound} this entity will make on death. + pub fn death_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Get the {@link Sound} this entity will make when falling from the given + /// height (in blocks). The sound will often differ between either a small + /// or a big fall damage sound if the height exceeds 4 blocks. + pub fn get_fall_damage_sound( + &self, + fall_height: i32, + ) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Int(fall_height); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getFallDamageSound", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity will make when falling from a small + /// height. + pub fn fall_damage_sound_small(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getFallDamageSoundSmall", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity will make when falling from a large + /// height. + pub fn fall_damage_sound_big(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getFallDamageSoundBig", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity will make when drinking the given + /// {@link ItemStack}. + pub fn get_drinking_sound( + &self, + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDrinkingSound", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Removes a given tag from this entity. - pub fn remove_scoreboard_tag( + /// Get the {@link Sound} this entity will make when eating the given + /// {@link ItemStack}. + pub fn get_eating_sound( &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeScoreboardTag", + "getEatingSound", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the reaction of the entity when moved by a piston. - pub fn piston_move_reaction( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + /// Returns true if this entity can breathe underwater and will not take + /// suffocation damage when its air supply reaches zero. + pub fn can_breathe_underwater(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPistonMoveReaction", + "canBreatheUnderwater", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the closest cardinal {@link BlockFace} direction an entity is - /// currently facing. - /// - /// This will not return any non-cardinal directions such as - /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. - /// - /// {@link Hanging} entities will override this call and thus their behavior - /// may be different. - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Gets the entity's current pose. - /// Note that the pose is only updated at the end of a tick, so may be - /// inconsistent with other methods. eg {@link Player#isSneaking()} being - /// true does not imply the current pose will be {@link Pose#SNEAKING} - pub fn pose(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Pose;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + #[deprecated] + /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. + pub fn category( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the category of spawn to which this entity belongs. - pub fn spawn_category( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); + /// Sets whether the entity is invisible or not. + pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(invisible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getSpawnCategory", + "setInvisible", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Checks if this entity has been spawned in a world. - /// - /// Entities not spawned in a world will not tick, be sent to players, or be - /// saved to the server files. - pub fn is_in_world(&self) -> Result> { + /// Gets whether the entity is invisible or not. + pub fn is_invisible(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get this entity as an NBT string. - /// - /// This string should not be relied upon as a serializable value. - pub fn as_string(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(res.z()?) } - /// Crates an {@link EntitySnapshot} representing the current state of this entity. - pub fn create_snapshot( + /// Gets the specified attribute instance from the object. This instance will + /// be backed directly to the object and any changes will be visible at once. + pub fn get_attribute( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + attribute: impl Into>, + ) -> Result>, Box> { + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAttribute", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::EntitySnapshot::from_raw( + Ok(Some(crate::attribute::AttributeInstance::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Creates a copy of this entity and all its data. Spawns the copy at the given location. - /// - /// Note: Players cannot be copied. - pub fn copy( + /// Deals the given amount of damage to this entity from a specified + /// {@link DamageSource}. + pub fn damage( &self, - to: std::option::Option>>, - ) -> Result, Box> { + amount: f64, + damage_source: std::option::Option>>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = to { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(amount); + args.push(val_1); + if let Some(a) = damage_source { + sig += "Lorg/bukkit/damage/DamageSource;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); - args.push(val_1); + args.push(val_2); } - sig += ")Lorg/bukkit/entity/Entity;"; + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); + .call_method(&self.jni_object(), "damage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. + pub fn health(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.d()?) } - /// Sets a metadata value in the implementing object's metadata store. - pub fn set_metadata( - &self, - metadata_key: impl Into, - new_metadata_value: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) - }); + /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is + /// dead. + pub fn set_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "setMetadata", + "setHealth", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a list of previously set metadata values from the implementing - /// object's metadata store. - pub fn get_metadata( - &self, - metadata_key: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); + /// Gets the entity's absorption amount. + pub fn absorption_amount(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref().call_method( &self.jni_object(), - "getMetadata", + "getAbsorptionAmount", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::metadata::MetadataValue::from_raw( - &self.jni_ref(), - obj, - )?); - } - Ok(new_vec) + Ok(res.d()?) } - /// Tests to see whether the implementing object contains the given - /// metadata value in its metadata store. - pub fn has_metadata( - &self, - metadata_key: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); + /// Sets the entity's absorption amount. + /// + /// Note: The amount is capped to the value of + /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on + /// that attribute is currently unspecified and subject to change. + pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "hasMetadata", + "setAbsorptionAmount", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the maximum health this entity has. + pub fn max_health(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Removes the given metadata value from the implementing object's - /// metadata store. - pub fn remove_metadata( - &self, - metadata_key: impl Into, - owning_plugin: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) - }); + #[deprecated] + /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. + pub fn set_max_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "removeMetadata", + "setMaxHealth", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sends this sender multiple messages - pub fn send_message( + #[deprecated] + /// Resets the max health to the original amount. + pub fn reset_max_health(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Launches a {@link Projectile} from the ProjectileSource with an + /// initial velocity. + pub fn launch_projectile( &self, - sender: impl Into>, - messages: std::option::Option>, - ) -> Result<(), Box> { + projectile: jni::objects::JClass<'mc>, + velocity: std::option::Option>>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) - }); + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(projectile.into()); args.push(val_1); - if let Some(a) = messages { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); + if let Some(a) = velocity { + sig += "Lorg/bukkit/util/Vector;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); args.push(val_2); } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the name of this command sender - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Gets the custom name on a mob or block. If there is no name this method - /// will return null. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn custom_name(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); + sig += ")LT;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getCustomName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// Sets a custom name on a mob or block. This name will be used in death - /// messages and can be sent to the client as a nameplate over the mob. - /// - /// Setting the name to null or an empty string will clear it. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn set_custom_name( - &self, - name: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCustomName", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPersistentDataContainer", - sig.as_str(), - vec![], - ); + .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.l()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -59795,19 +68187,19 @@ impl<'mc> Projectile<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Projectile<'mc> { - fn into(self) -> crate::entity::Entity<'mc> { - crate::entity::Entity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Projectile into crate::entity::Entity") +impl<'mc> Into> for Spider<'mc> { + fn into(self) -> crate::entity::Monster<'mc> { + crate::entity::Monster::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Spider into crate::entity::Monster") } } #[repr(C)] -pub struct Marker<'mc>( +pub struct OminousItemSpawner<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Marker<'mc> { +impl<'mc> JNIRaw<'mc> for OminousItemSpawner<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -59815,18 +68207,20 @@ impl<'mc> JNIRaw<'mc> for Marker<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Marker<'mc> { +impl<'mc> JNIInstantiatable<'mc> for OminousItemSpawner<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Marker from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate OminousItemSpawner from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Marker")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/OminousItemSpawner")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Marker object, got {}", + "Invalid argument passed. Expected a OminousItemSpawner object, got {}", name ) .into()) @@ -59836,7 +68230,67 @@ impl<'mc> JNIInstantiatable<'mc> for Marker<'mc> { } } -impl<'mc> Marker<'mc> { +impl<'mc> OminousItemSpawner<'mc> { + /// Gets the item which will be spawned by this spawner. + pub fn item( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets the item which will be spawned by this spawner. + pub fn set_item( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the ticks after which this item will be spawned. + pub fn spawn_item_after_ticks(&self) -> Result> { + let sig = String::from("()J"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSpawnItemAfterTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.j()?) + } + /// Sets the ticks after which this item will be spawned. + pub fn set_spawn_item_after_ticks(&self, ticks: i64) -> Result<(), Box> { + let sig = String::from("(J)V"); + let val_1 = jni::objects::JValueGen::Long(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSpawnItemAfterTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } /// Stores the entity's current position in the provided Location object. /// /// If the provided Location is null this method does nothing and returns @@ -61156,19 +69610,19 @@ impl<'mc> Marker<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Marker<'mc> { +impl<'mc> Into> for OminousItemSpawner<'mc> { fn into(self) -> crate::entity::Entity<'mc> { crate::entity::Entity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Marker into crate::entity::Entity") + .expect("Error converting OminousItemSpawner into crate::entity::Entity") } } #[repr(C)] -pub struct Wither<'mc>( +pub struct Item<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Wither<'mc> { +impl<'mc> JNIRaw<'mc> for Item<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -61176,18 +69630,18 @@ impl<'mc> JNIRaw<'mc> for Wither<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Wither<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Item<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Wither from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Item from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Wither")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Item")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Wither object, got {}", + "Invalid argument passed. Expected a Item object, got {}", name ) .into()) @@ -61197,604 +69651,177 @@ impl<'mc> JNIInstantiatable<'mc> for Wither<'mc> { } } -impl<'mc> Wither<'mc> { - /// {@inheritDoc} - /// - /// This method will set the target of the {@link Head#CENTER center head} of - /// the wither. - pub fn set_target( - &self, - target: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTarget", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// This method will get the target of individual heads {@link Head} of the - /// wither. - pub fn get_target( +impl<'mc> Item<'mc> { + /// Gets the item stack associated with this item drop. + pub fn item_stack( &self, - head: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/entity/Wither/Head;)Lorg/bukkit/entity/LivingEntity;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(head.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTarget", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::LivingEntity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Returns the wither's current invulnerability ticks. - pub fn invulnerability_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getInvulnerabilityTicks", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the wither's current invulnerability ticks. - /// When invulnerability ticks reach 0, the wither will trigger an explosion. - pub fn set_invulnerability_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setInvulnerabilityTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the height of the living entity's eyes above its Location. - pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { - let sig = String::from("(Z)D"); - let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getEyeHeight", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Get a Location detailing the current eye position of the living entity. - pub fn eye_location(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets all blocks along the living entity's line of sight. - /// - /// This list contains all blocks from the living entity's eye position to - /// target inclusive. This method considers all blocks as 1x1x1 in size. - pub fn get_line_of_sight( - &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { - let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(max_distance); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLineOfSight", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Gets the block that the living entity has targeted. - /// - /// This method considers all blocks as 1x1x1 in size. To take exact block - /// collision shapes into account, see {@link #getTargetBlockExact(int, - /// FluidCollisionMode)}. - pub fn get_target_block( - &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result, Box> { - let sig = String::from("(Ljava/util/Set;I)Lorg/bukkit/block/Block;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(max_distance); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTargetBlock", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + .call_method(&self.jni_object(), "getItemStack", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the last two blocks along the living entity's line of sight. - /// - /// The target block will be the last block in the list. This method - /// considers all blocks as 1x1x1 in size. - pub fn get_last_two_target_blocks( + /// Sets the item stack associated with this item drop. + pub fn set_item_stack( &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { - let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + stack: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + jni::objects::JObject::from_raw(stack.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(max_distance); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLastTwoTargetBlocks", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Gets the block that the living entity has targeted. - /// - /// This takes the blocks' precise collision shapes into account. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn get_target_block_exact( - &self, - max_distance: i32, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(max_distance); - args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/block/Block;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTargetBlockExact", - sig.as_str(), - args, - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::block::Block::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Performs a ray trace that provides information on the targeted block. - /// - /// This takes the blocks' precise collision shapes into account. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn ray_trace_blocks( - &self, - max_distance: f64, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(max_distance); - args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/util/RayTraceResult;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::util::RayTraceResult::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Returns the amount of air that the living entity has remaining, in - /// ticks. - pub fn remaining_air(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the amount of air that the living entity has remaining, in ticks. - pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRemainingAir", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns the maximum amount of air the living entity can have, in ticks. - pub fn maximum_air(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the maximum amount of air the living entity can have, in ticks. - pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaximumAir", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the item that the player is using (eating food, drawing back a bow, - /// blocking, etc.) - pub fn item_in_use( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Gets the number of ticks remaining for the current item's usage. - pub fn item_in_use_ticks(&self) -> Result> { - let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getItemInUseTicks", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the number of ticks that remain for the current item's usage. - /// Applies to items that take time to use, like eating food, drawing a bow, - /// or throwing a trident. - pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setItemInUseTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the time in ticks until the next arrow leaves the entity's body. - pub fn arrow_cooldown(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getArrowCooldown", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the time in ticks until the next arrow leaves the entity's body. - pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setArrowCooldown", + "setItemStack", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the amount of arrows in an entity's body. - pub fn arrows_in_body(&self) -> Result> { + /// Gets the delay before this Item is available to be picked up by players + pub fn pickup_delay(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPickupDelay", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Set the amount of arrows in the entity's body. - pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { + /// Sets the delay before this Item is available to be picked up by players + pub fn set_pickup_delay(&self, delay: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(count); + let val_1 = jni::objects::JValueGen::Int(delay); let res = self.jni_ref().call_method( &self.jni_object(), - "setArrowsInBody", + "setPickupDelay", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's current maximum no damage ticks. - /// - /// This is the maximum duration in which the living entity will not take - /// damage. - pub fn maximum_no_damage_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMaximumNoDamageTicks", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the living entity's current maximum no damage ticks. - pub fn set_maximum_no_damage_ticks( + /// Sets if this Item should live forever + pub fn set_unlimited_lifetime( &self, - ticks: i32, + unlimited: bool, ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaximumNoDamageTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns the living entity's last damage taken in the current no damage - /// ticks time. - /// - /// Only damage higher than this amount will further damage the living - /// entity. - pub fn last_damage(&self) -> Result> { - let sig = String::from("()D"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Sets the damage dealt within the current no damage ticks time period. - pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(damage); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLastDamage", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns the living entity's current no damage ticks. - pub fn no_damage_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getNoDamageTicks", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the living entity's current no damage ticks. - pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(unlimited.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setNoDamageTicks", + "setUnlimitedLifetime", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the ticks that this entity has performed no action. - /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn no_action_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Gets if this Item lives forever + pub fn is_unlimited_lifetime(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getNoActionTicks", + "isUnlimitedLifetime", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the ticks that this entity has performed no action. - /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets the owner of this item. + /// Other entities will not be able to pickup this item when an owner is set. + pub fn set_owner( + &self, + owner: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/UUID;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owner.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setNoActionTicks", + "setOwner", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the player identified as the killer of the living entity. - /// - /// May be null. - pub fn killer(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Player;"); + /// Get the owner of this item. + pub fn owner( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/UUID;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Player::from_raw( + Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - #[deprecated] - /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. - pub fn add_potion_effect( - &self, - effect: impl Into>, - force: std::option::Option, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/potion/PotionEffect;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(effect.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = force { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns whether the living entity already has an existing effect of - /// the given {@link PotionEffectType} applied to it. - pub fn has_potion_effect( + /// Set the thrower of this item. + /// The thrower is the entity which dropped the item. This affects the + /// trigger criteria for item pickups, for things such as advancements. + pub fn set_thrower( &self, - val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); + uuid: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/UUID;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasPotionEffect", + "setThrower", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the thrower of this item. + /// The thrower is the entity which dropped the item. + pub fn thrower( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getThrower", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Returns the active {@link PotionEffect} of the specified type. + /// Stores the entity's current position in the provided Location object. /// - /// If the effect is not present on the entity then null will be returned. - pub fn get_potion_effect( + /// If the provided Location is null this method does nothing and returns + /// null. + pub fn get_location( &self, - val_type: impl Into>, - ) -> Result>, Box> { - let sig = - String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getPotionEffect", + "getLocation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -61802,526 +69829,635 @@ impl<'mc> Wither<'mc> { if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::potion::PotionEffect::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Removes any effects present of the given {@link PotionEffectType}. - pub fn remove_potion_effect( + /// Sets this entity's velocity in meters per tick + pub fn set_velocity( &self, - val_type: impl Into>, + velocity: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removePotionEffect", + "setVelocity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns all currently active {@link PotionEffect}s on the living - /// entity. - pub fn active_potion_effects( + /// Gets this entity's current velocity + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the entity's height + pub fn height(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the entity's width + pub fn width(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the entity's current bounding box. + /// + /// The returned bounding box reflects the entity's current location and + /// size. + pub fn bounding_box( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns true if the entity is supported by a block. This value is a + /// state updated by the server and is not recalculated unless the entity + /// moves. + pub fn is_on_ground(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns true if the entity is in water. + pub fn is_in_water(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the current world this entity resides in + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the entity's rotation. + /// + /// Note that if the entity is affected by AI, it may override this rotation. + pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { + let sig = String::from("(FF)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); + let val_2 = jni::objects::JValueGen::Float(pitch); let res = self.jni_ref().call_method( &self.jni_object(), - "getActivePotionEffects", + "setRotation", sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Checks whether the living entity has block line of sight to another. - /// - /// This uses the same algorithm that hostile mobs use to find the closest - /// player. - pub fn has_line_of_sight( + /// Teleports this entity to the given location. If this entity is riding a + /// vehicle, it will be dismounted prior to teleportation. + pub fn teleport( &self, - other: impl Into>, + location: impl Into>, + cause: std::option::Option< + impl Into>, + >, ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) + jni::objects::JObject::from_raw(location.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasLineOfSight", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + if let Some(a) = cause { + sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "teleport", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns if the living entity despawns when away from players or not. - /// - /// By default, animals are not removed while other mobs are. - pub fn remove_when_far_away(&self) -> Result> { - let sig = String::from("()Z"); + /// Returns a list of entities within a bounding box centered around this + /// entity + pub fn get_nearby_entities( + &self, + x: f64, + y: f64, + z: f64, + ) -> Result>, Box> { + let sig = String::from("(DDD)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Double(x); + let val_2 = jni::objects::JValueGen::Double(y); + let val_3 = jni::objects::JValueGen::Double(z); let res = self.jni_ref().call_method( &self.jni_object(), - "getRemoveWhenFarAway", + "getNearbyEntities", sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Sets whether or not the living entity despawns when away from players - /// or not. - pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(remove.into()); + /// Returns a unique id for this entity + pub fn entity_id(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's maximum fire ticks. + pub fn max_fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setRemoveWhenFarAway", + "setFireTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the inventory with the equipment worn by the living entity. - pub fn equipment( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::EntityEquipment::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Sets whether or not the living entity can pick up items. - pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { + /// Sets if the entity has visual fire (it will always appear to be on fire). + pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(pickup.into()); + let val_1 = jni::objects::JValueGen::Bool(fire.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCanPickupItems", + "setVisualFire", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the living entity can pick up items. - pub fn can_pickup_items(&self) -> Result> { + /// Gets if the entity has visual fire (it will always appear to be on fire). + pub fn is_visual_fire(&self) -> Result> { let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's maximum freeze ticks (amount of ticks before it will + /// be fully frozen) + pub fn max_freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCanPickupItems", + "getMaxFreezeTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Returns whether the entity is currently leashed. - pub fn is_leashed(&self) -> Result> { + /// Sets the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFreezeTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the entity is fully frozen (it has been in powdered snow for max + /// freeze ticks). + pub fn is_frozen(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the entity that is currently leading this entity. - pub fn leash_holder(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Mark the entity's removal. + pub fn remove(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the leash on this entity to be held by the supplied entity. - /// - /// This method has no effect on EnderDragons, Withers, Players, or Bats. - /// Non-living entities excluding leashes will not persist as leash - /// holders. - pub fn set_leash_holder( - &self, - holder: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(holder.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLeashHolder", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Returns true if this entity has been marked for removal. + pub fn is_dead(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Checks to see if an entity is gliding, such as using an Elytra. - pub fn is_gliding(&self) -> Result> { + /// Returns false if the entity has died, been despawned for some other + /// reason, or has not been added to the world. + pub fn is_valid(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Makes entity start or stop gliding. This will work even if an Elytra - /// is not equipped, but will be reverted by the server immediately after - /// unless an event-cancelling mechanism is put in place. - pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gliding.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setGliding", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Gets the {@link Server} that contains this Entity + pub fn server(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Server;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Server::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Checks to see if an entity is swimming. - pub fn is_swimming(&self) -> Result> { + /// Returns true if the entity gets persisted. + /// + /// By default all entities are persistent. An entity will also not get + /// persisted, if it is riding an entity that is not persistent. + /// + /// The persistent flag on players controls whether or not to save their + /// playerdata file when they quit. If a player is directly or indirectly + /// riding a non-persistent entity, the vehicle at the root and all its + /// passengers won't get persisted. + /// + /// This should not be confused with + /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls + /// despawning of living entities. + pub fn is_persistent(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Makes entity start or stop swimming. - /// This may have unexpected results if the entity is not in water. - pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { + /// Sets whether or not the entity gets persisted. + pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(swimming.into()); + let val_1 = jni::objects::JValueGen::Bool(persistent.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setSwimming", + "setPersistent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks to see if an entity is currently using the Riptide enchantment. - pub fn is_riptiding(&self) -> Result> { - let sig = String::from("()Z"); + #[deprecated] + /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. + pub fn passenger( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Returns whether this entity is slumbering. - pub fn is_sleeping(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); + #[deprecated] + /// Set the passenger of a vehicle. + pub fn set_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPassenger", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets if the entity is climbing. - pub fn is_climbing(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets a list of passengers of this vehicle. + /// + /// The returned list will not be directly linked to the entity's current + /// passengers, and no guarantees are made as to its mutability. + pub fn passengers( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Sets whether an entity will have AI. - /// The entity will be completely unable to move if it has no AI. - pub fn set_ai(&self, ai: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(ai.into()); + /// Add a passenger to the vehicle. + pub fn add_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setAI", + "addPassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks whether an entity has AI. - /// The entity will be completely unable to move if it has no AI. - pub fn has_ai(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Makes this entity attack the given entity with a melee attack. - /// Attack damage is calculated by the server from the attributes and - /// equipment of this mob, and knockback is applied to {@code target} as - /// appropriate. - pub fn attack( + /// Remove a passenger from the vehicle. + pub fn remove_passenger( &self, - target: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "attack", + "removePassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Makes this entity swing their main hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their main hand. - pub fn swing_main_hand(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Check if a vehicle has passengers. + pub fn is_empty(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Makes this entity swing their off hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their off hand. - pub fn swing_off_hand(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Eject any passenger. + pub fn eject(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the distance this entity has fallen + pub fn fall_distance(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) } - /// Makes this entity flash red as if they were damaged. - pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { + /// Sets the fall distance for this entity + pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); + let val_1 = jni::objects::JValueGen::Float(distance); let res = self.jni_ref().call_method( &self.jni_object(), - "playHurtAnimation", + "setFallDistance", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Set if this entity will be subject to collisions with other entities. - /// - /// Exemptions to this rule can be managed with - /// {@link #getCollidableExemptions()} - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not working for player collisions. This - /// method should therefore only be used to set the collision status of - /// non-player entities. - /// - /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in - /// combination with a {@link Scoreboard} and a {@link Team}. - pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(collidable.into()); + #[deprecated] + /// Record the last {@link EntityDamageEvent} inflicted on this entity + pub fn set_last_damage_cause( + &self, + event: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(event.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCollidable", + "setLastDamageCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if this entity is subject to collisions with other entities. - /// - /// Some entities might be exempted from the collidable rule of this entity. - /// Use {@link #getCollidableExemptions()} to get these. - /// - /// Please note that this method returns only the custom collidable state, - /// not whether the entity is non-collidable for other reasons such as being - /// dead. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not being accurate for player collisions. - /// This method should therefore only be used to check the collision status - /// of non-player entities. - /// - /// To check the collision behavior for a player, use - /// {@link Team.Option#COLLISION_RULE} in combination with a - /// {@link Scoreboard} and a {@link Team}. - pub fn is_collidable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets a mutable set of UUIDs of the entities which are exempt from the - /// entity's collidable rule and which's collision with this entity will - /// behave the opposite of it. - /// - /// This set can be modified to add or remove exemptions. - /// - /// For example if collidable is true and an entity is in the exemptions set - /// then it will not collide with it. Similarly if collidable is false and an - /// entity is in this set then it will still collide with it. - /// - /// Note these exemptions are not (currently) persistent. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in those exemptions not being accurate for player - /// collisions. This method should therefore only be used to exempt - /// non-player entities. - /// - /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} - /// in combination with a {@link Scoreboard} and a {@link Team}. - pub fn collidable_exemptions( + /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. + /// This event may have been cancelled. + pub fn last_damage_cause( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + ) -> Result>, Box> + { + let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCollidableExemptions", + "getLastDamageCause", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Returns a unique and persistent id for this entity + pub fn unique_id( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns the value of the memory specified. + /// Gets the amount of ticks this entity has lived for. /// - /// Note that the value is null when the specific entity does not have that - /// value by default. - pub fn get_memory( - &self, - memory_key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) - }); + /// This is the equivalent to "age" in entities. + pub fn ticks_lived(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. May not be less than one + /// tick. + pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(value); let res = self.jni_ref().call_method( &self.jni_object(), - "getMemory", + "setTicksLived", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(res.l()?)) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the value of the memory specified. + /// Performs the specified {@link EntityEffect} for this entity. /// - /// Note that the value will not be persisted when the specific entity does - /// not have that value by default. - pub fn set_memory( + /// This will be viewable to all players near the entity. + /// + /// If the effect is not applicable to this class of entity, it will not play. + pub fn play_effect( &self, - memory_key: impl Into>, - memory_value: jni::objects::JObject<'mc>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); + let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Object(memory_value); let res = self.jni_ref().call_method( &self.jni_object(), - "setMemory", + "playEffect", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the {@link Sound} this entity will make when damaged. - pub fn hurt_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); + /// Get the type of the entity. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + }) } - /// Get the {@link Sound} this entity will make on death. - pub fn death_sound(&self) -> Result>, Box> { + /// Get the {@link Sound} this entity makes while swimming. + pub fn swim_sound(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Get the {@link Sound} this entity will make when falling from the given - /// height (in blocks). The sound will often differ between either a small - /// or a big fall damage sound if the height exceeds 4 blocks. - pub fn get_fall_damage_sound( - &self, - fall_height: i32, - ) -> Result, Box> { - let sig = String::from("(I)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Int(fall_height); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFallDamageSound", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the {@link Sound} this entity will make when falling from a small - /// height. - pub fn fall_damage_sound_small(&self) -> Result, Box> { + /// Get the {@link Sound} this entity makes when splashing in water. For most + /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_splash_sound(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSoundSmall", + "getSwimSplashSound", sig.as_str(), vec![], ); @@ -62330,13 +70466,15 @@ impl<'mc> Wither<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the {@link Sound} this entity will make when falling from a large - /// height. - pub fn fall_damage_sound_big(&self) -> Result, Box> { + /// Get the {@link Sound} this entity makes when splashing in water at high + /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_high_speed_splash_sound( + &self, + ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSoundBig", + "getSwimHighSpeedSplashSound", sig.as_str(), vec![], ); @@ -62345,409 +70483,530 @@ impl<'mc> Wither<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the {@link Sound} this entity will make when drinking the given - /// {@link ItemStack}. - pub fn get_drinking_sound( + /// Returns whether this entity is inside a vehicle. + pub fn is_inside_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Leave the current vehicle. If the entity is currently in a vehicle (and + /// is removed from it), true will be returned, otherwise false will be + /// returned. + pub fn leave_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the vehicle that this entity is inside. If there is no vehicle, + /// null will be returned. + pub fn vehicle( &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) - }); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets whether or not to display the mob's custom name client side. The + /// name will be displayed above the mob similarly to a player. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getDrinkingSound", + "setCustomNameVisible", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether or not the mob's custom name is displayed client side. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn is_custom_name_visible(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isCustomNameVisible", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Get the {@link Sound} this entity will make when eating the given - /// {@link ItemStack}. - pub fn get_eating_sound( - &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) - }); + /// Sets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(visible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getEatingSound", + "setVisibleByDefault", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns true if this entity can breathe underwater and will not take - /// suffocation damage when its air supply reaches zero. - pub fn can_breathe_underwater(&self) -> Result> { + /// Gets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn is_visible_by_default(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "canBreatheUnderwater", + "isVisibleByDefault", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. - pub fn category( + /// Get all players that are currently tracking this entity. + /// + /// 'Tracking' means that this entity has been sent to the player and that + /// they are receiving updates on its state. Note that the client's {@code + /// 'Entity Distance'} setting does not affect the range at which entities + /// are tracked. + pub fn tracked_by( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets whether the entity is invisible or not. - pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { + /// Sets whether the entity has a team colored (default: white) glow. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(invisible.into()); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvisible", + "setGlowing", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invisible or not. - pub fn is_invisible(&self) -> Result> { + /// Gets whether the entity is glowing or not. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn is_glowing(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the specified attribute instance from the object. This instance will - /// be backed directly to the object and any changes will be visible at once. - pub fn get_attribute( - &self, - attribute: impl Into>, - ) -> Result>, Box> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); + /// Sets whether the entity is invulnerable or not. + /// + /// When an entity is invulnerable it can only be damaged by players in + /// creative mode. + pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getAttribute", + "setInvulnerable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::attribute::AttributeInstance::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Deals the given amount of damage to this entity from a specified - /// {@link DamageSource}. - pub fn damage( - &self, - amount: f64, - damage_source: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(amount); - args.push(val_1); - if let Some(a) = damage_source { - sig += "Lorg/bukkit/damage/DamageSource;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "damage", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. - pub fn health(&self) -> Result> { - let sig = String::from("()D"); + /// Gets whether the entity is invulnerable or not. + pub fn is_invulnerable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets whether the entity is silent or not. + pub fn is_silent(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is - /// dead. - pub fn set_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); + /// Sets whether the entity is silent or not. + /// + /// When an entity is silent it will not produce any sound. + pub fn set_silent(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setHealth", + "setSilent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the entity's absorption amount. - pub fn absorption_amount(&self) -> Result> { - let sig = String::from("()D"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAbsorptionAmount", - sig.as_str(), - vec![], - ); + /// Returns whether gravity applies to this entity. + pub fn has_gravity(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Sets the entity's absorption amount. - /// - /// Note: The amount is capped to the value of - /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on - /// that attribute is currently unspecified and subject to change. - pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(amount); + /// Sets whether gravity applies to this entity. + pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gravity.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setAbsorptionAmount", + "setGravity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the maximum health this entity has. - pub fn max_health(&self) -> Result> { - let sig = String::from("()D"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); + /// Gets the period of time (in ticks) before this entity can use a portal. + pub fn portal_cooldown(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPortalCooldown", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.i()?) } - #[deprecated] - /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. - pub fn set_max_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); + /// Sets the period of time (in ticks) before this entity can use a portal. + pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(cooldown); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxHealth", + "setPortalCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Resets the max health to the original amount. - pub fn reset_max_health(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Launches a {@link Projectile} from the ProjectileSource with an - /// initial velocity. - pub fn launch_projectile( - &self, - projectile: jni::objects::JClass<'mc>, - velocity: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/Class;"; - let val_1 = jni::objects::JValueGen::Object(projectile.into()); - args.push(val_1); - if let Some(a) = velocity { - sig += "Lorg/bukkit/util/Vector;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")LT;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) - } - /// Returns the {@link BossBar} of the {@link Boss} - pub fn boss_bar( + /// Returns a set of tags for this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn scoreboard_tags( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/boss/BossBar;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBossBar", sig.as_str(), vec![]); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getScoreboardTags", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::boss::BossBar::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Stores the entity's current position in the provided Location object. + /// Add a tag to this entity. /// - /// If the provided Location is null this method does nothing and returns - /// null. - pub fn get_location( + /// Entities can have no more than 1024 tags. + pub fn add_scoreboard_tag( &self, - loc: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) - }); + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocation", + "addScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.z()?) } - /// Sets this entity's velocity in meters per tick - pub fn set_velocity( + /// Removes a given tag from this entity. + pub fn remove_scoreboard_tag( &self, - velocity: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) - }); + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setVelocity", + "removeScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets this entity's current velocity - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + /// Returns the reaction of the entity when moved by a piston. + pub fn piston_move_reaction( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPistonMoveReaction", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the entity's height - pub fn height(&self) -> Result> { - let sig = String::from("()D"); + /// Get the closest cardinal {@link BlockFace} direction an entity is + /// currently facing. + /// + /// This will not return any non-cardinal directions such as + /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// + /// {@link Hanging} entities will override this call and thus their behavior + /// may be different. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the entity's width - pub fn width(&self) -> Result> { - let sig = String::from("()D"); + /// Gets the entity's current pose. + /// Note that the pose is only updated at the end of a tick, so may be + /// inconsistent with other methods. eg {@link Player#isSneaking()} being + /// true does not imply the current pose will be {@link Pose#SNEAKING} + pub fn pose(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Pose;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the entity's current bounding box. - /// - /// The returned bounding box reflects the entity's current location and - /// size. - pub fn bounding_box( + /// Get the category of spawn to which this entity belongs. + pub fn spawn_category( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSpawnCategory", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns true if the entity is supported by a block. This value is a - /// state updated by the server and is not recalculated unless the entity - /// moves. - pub fn is_on_ground(&self) -> Result> { + /// Checks if this entity has been spawned in a world. + /// + /// Entities not spawned in a world will not tick, be sent to players, or be + /// saved to the server files. + pub fn is_in_world(&self) -> Result> { let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get this entity as an NBT string. + /// + /// This string should not be relied upon as a serializable value. + pub fn as_string(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Returns true if the entity is in water. - pub fn is_in_water(&self) -> Result> { - let sig = String::from("()Z"); + /// Crates an {@link EntitySnapshot} representing the current state of this entity. + pub fn create_snapshot( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntitySnapshot::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// + /// Note: Players cannot be copied. + pub fn copy( + &self, + to: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = to { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Lorg/bukkit/entity/Entity;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "copy", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets a metadata value in the implementing object's metadata store. + pub fn set_metadata( + &self, + metadata_key: impl Into, + new_metadata_value: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMetadata", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns a list of previously set metadata values from the implementing + /// object's metadata store. + pub fn get_metadata( + &self, + metadata_key: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMetadata", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::metadata::MetadataValue::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(new_vec) + } + /// Tests to see whether the implementing object contains the given + /// metadata value in its metadata store. + pub fn has_metadata( + &self, + metadata_key: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasMetadata", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the current world this entity resides in - pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the entity's rotation. - /// - /// Note that if the entity is affected by AI, it may override this rotation. - pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { - let sig = String::from("(FF)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); - let val_2 = jni::objects::JValueGen::Float(pitch); + /// Removes the given metadata value from the implementing object's + /// metadata store. + pub fn remove_metadata( + &self, + metadata_key: impl Into, + owning_plugin: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setRotation", + "removeMetadata", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), @@ -62757,3620 +71016,3614 @@ impl<'mc> Wither<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Teleports this entity to the given location. If this entity is riding a - /// vehicle, it will be dismounted prior to teleportation. - pub fn teleport( + /// Sends this sender multiple messages + pub fn send_message( &self, - location: impl Into>, - cause: std::option::Option< - impl Into>, - >, - ) -> Result> { + sender: impl Into>, + messages: std::option::Option>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; + sig += "Ljava/util/UUID;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) }); args.push(val_1); - if let Some(a) = cause { - sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); + if let Some(a) = messages { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); args.push(val_2); } - sig += ")Z"; + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "teleport", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns a list of entities within a bounding box centered around this - /// entity - pub fn get_nearby_entities( - &self, - x: f64, - y: f64, - z: f64, - ) -> Result>, Box> { - let sig = String::from("(DDD)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Double(x); - let val_2 = jni::objects::JValueGen::Double(y); - let val_3 = jni::objects::JValueGen::Double(z); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getNearbyEntities", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns a unique id for this entity - pub fn entity_id(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); + /// Gets the name of this command sender + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Returns the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn fire_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the custom name on a mob or block. If there is no name this method + /// will return null. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn custom_name(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCustomName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the entity's maximum fire ticks. - pub fn max_fire_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( self.jni_ref() - .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Sets the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets a custom name on a mob or block. This name will be used in death + /// messages and can be sent to the client as a nameplate over the mob. + /// + /// Setting the name to null or an empty string will clear it. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn set_custom_name( + &self, + name: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setFireTicks", + "setCustomName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets if the entity has visual fire (it will always appear to be on fire). - pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire.into()); + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + pub fn persistent_data_container( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisualFire", + "getPersistentDataContainer", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets if the entity has visual fire (it will always appear to be on fire). - pub fn is_visual_fire(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Returns the entity's maximum freeze ticks (amount of ticks before it will - /// be fully frozen) - pub fn max_freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMaxFreezeTicks", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) +} +impl<'mc> Into> for Item<'mc> { + fn into(self) -> crate::entity::Entity<'mc> { + crate::entity::Entity::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Item into crate::entity::Entity") } - /// Sets the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFreezeTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +} +#[repr(C)] +pub struct Squid<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Squid<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Gets if the entity is fully frozen (it has been in powdered snow for max - /// freeze ticks). - pub fn is_frozen(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Mark the entity's removal. - pub fn remove(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) +} +impl<'mc> JNIInstantiatable<'mc> for Squid<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Squid from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Squid")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Squid object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } - /// Returns true if this entity has been marked for removal. - pub fn is_dead(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} + +impl<'mc> Squid<'mc> { + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Returns false if the entity has died, been despawned for some other - /// reason, or has not been added to the world. - pub fn is_valid(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} +impl<'mc> Into> for Squid<'mc> { + fn into(self) -> crate::entity::WaterMob<'mc> { + crate::entity::WaterMob::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Squid into crate::entity::WaterMob") } - /// Gets the {@link Server} that contains this Entity - pub fn server(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Server;"); +} +#[repr(C)] +pub struct TextDisplay<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for TextDisplay<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for TextDisplay<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate TextDisplay from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/TextDisplay")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a TextDisplay object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> TextDisplay<'mc> { + /// Gets the displayed text. + pub fn text(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getText", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Server::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Returns true if the entity gets persisted. - /// - /// By default all entities are persistent. An entity will also not get - /// persisted, if it is riding an entity that is not persistent. - /// - /// The persistent flag on players controls whether or not to save their - /// playerdata file when they quit. If a player is directly or indirectly - /// riding a non-persistent entity, the vehicle at the root and all its - /// passengers won't get persisted. - /// - /// This should not be confused with - /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls - /// despawning of living entities. - pub fn is_persistent(&self) -> Result> { - let sig = String::from("()Z"); + /// Sets the displayed text. + pub fn set_text(&self, text: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(text.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setText", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the maximum line width before wrapping. + pub fn line_width(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLineWidth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets whether or not the entity gets persisted. - pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(persistent.into()); + /// Sets the maximum line width before wrapping. + pub fn set_line_width(&self, width: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(width); let res = self.jni_ref().call_method( &self.jni_object(), - "setPersistent", + "setLineWidth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. - pub fn passenger( + /// Gets the text background color. + pub fn background_color( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Color;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBackgroundColor", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(Some(crate::Color::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - #[deprecated] - /// Set the passenger of a vehicle. - pub fn set_passenger( + /// Sets the text background color. + pub fn set_background_color( &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + color: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Color;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(color.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPassenger", + "setBackgroundColor", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets a list of passengers of this vehicle. - /// - /// The returned list will not be directly linked to the entity's current - /// passengers, and no guarantees are made as to its mutability. - pub fn passengers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + /// Gets the text opacity. + pub fn text_opacity(&self) -> Result> { + let sig = String::from("()B"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTextOpacity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(res.b()?) } - /// Add a passenger to the vehicle. - pub fn add_passenger( - &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); + /// Sets the text opacity. + pub fn set_text_opacity(&self, opacity: i8) -> Result<(), Box> { + let sig = String::from("(B)V"); + let val_1 = jni::objects::JValueGen::Byte(opacity); let res = self.jni_ref().call_method( &self.jni_object(), - "addPassenger", + "setTextOpacity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the text is shadowed. + pub fn is_shadowed(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isShadowed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Remove a passenger from the vehicle. - pub fn remove_passenger( - &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); + /// Sets if the text is shadowed. + pub fn set_shadowed(&self, shadow: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(shadow.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "removePassenger", + "setShadowed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Check if a vehicle has passengers. - pub fn is_empty(&self) -> Result> { + /// Gets if the text is see through. + pub fn is_see_through(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isSeeThrough", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Eject any passenger. - pub fn eject(&self) -> Result> { + /// Sets if the text is see through. + pub fn set_see_through(&self, see_through: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(see_through.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSeeThrough", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the text has its default background. + pub fn is_default_background(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isDefaultBackground", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns the distance this entity has fallen - pub fn fall_distance(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Sets the fall distance for this entity - pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(distance); + /// Sets if the text has its default background. + pub fn set_default_background( + &self, + default_background: bool, + ) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(default_background.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setFallDistance", + "setDefaultBackground", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Record the last {@link EntityDamageEvent} inflicted on this entity - pub fn set_last_damage_cause( + /// Gets the text alignment for this display. + pub fn alignment( &self, - event: impl Into>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/TextDisplay/TextAlignment;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAlignment", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::TextDisplayTextAlignment::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the text alignment for this display. + pub fn set_alignment( + &self, + alignment: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); + let sig = String::from("(Lorg/bukkit/entity/TextDisplay/TextAlignment;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(event.into().jni_object().clone()) + jni::objects::JObject::from_raw(alignment.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDamageCause", + "setAlignment", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. - /// This event may have been cancelled. - pub fn last_damage_cause( + /// Gets the transformation applied to this display. + pub fn transformation( &self, - ) -> Result>, Box> - { - let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Transformation;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLastDamageCause", + "getTransformation", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Returns a unique and persistent id for this entity - pub fn unique_id( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + crate::util::Transformation::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. - pub fn ticks_lived(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. May not be less than one - /// tick. - pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(value); + /// Sets the transformation applied to this display + pub fn set_transformation( + &self, + transformation: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Transformation;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transformation.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setTicksLived", + "setTransformation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Performs the specified {@link EntityEffect} for this entity. - /// - /// This will be viewable to all players near the entity. - /// - /// If the effect is not applicable to this class of entity, it will not play. - pub fn play_effect( + /// Sets the raw transformation matrix applied to this display + pub fn set_transformation_matrix( &self, - val_type: impl Into>, + transformation_matrix: jni::objects::JObject<'mc>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + let sig = String::from("(Lorg/joml/Matrix4f;)V"); + let val_1 = jni::objects::JValueGen::Object(transformation_matrix); let res = self.jni_ref().call_method( &self.jni_object(), - "playEffect", + "setTransformationMatrix", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the type of the entity. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity makes while swimming. - pub fn swim_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity makes when splashing in water. For most - /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_splash_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Gets the interpolation duration of this display. + pub fn interpolation_duration(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimSplashSound", + "getInterpolationDuration", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Get the {@link Sound} this entity makes when splashing in water at high - /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_high_speed_splash_sound( + /// Sets the interpolation duration of this display. + pub fn set_interpolation_duration( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + duration: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(duration); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimHighSpeedSplashSound", + "setInterpolationDuration", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the teleport duration of this display. + ///
    + ///
  • 0 means that updates are applied immediately.
  • + ///
  • 1 means that the display entity will move from current position to the updated one over one tick.
  • + ///
  • Higher values spread the movement over multiple ticks.
  • + ///
+ pub fn teleport_duration(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTeleportDuration", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Returns whether this entity is inside a vehicle. - pub fn is_inside_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Sets the teleport duration of this display. + pub fn set_teleport_duration(&self, duration: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(duration); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTeleportDuration", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Leave the current vehicle. If the entity is currently in a vehicle (and - /// is removed from it), true will be returned, otherwise false will be - /// returned. - pub fn leave_vehicle(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the view distance/range of this display. + pub fn view_range(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getViewRange", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.f()?) } - /// Get the vehicle that this entity is inside. If there is no vehicle, - /// null will be returned. - pub fn vehicle( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + /// Sets the view distance/range of this display. + pub fn set_view_range(&self, range: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(range); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setViewRange", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the shadow radius of this display. + pub fn shadow_radius(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getShadowRadius", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.f()?) } - /// Sets whether or not to display the mob's custom name client side. The - /// name will be displayed above the mob similarly to a player. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Sets the shadow radius of this display. + pub fn set_shadow_radius(&self, radius: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(radius); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomNameVisible", + "setShadowRadius", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not the mob's custom name is displayed client side. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn is_custom_name_visible(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the shadow strength of this display. + pub fn shadow_strength(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref().call_method( &self.jni_object(), - "isCustomNameVisible", + "getShadowStrength", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.f()?) } - /// Sets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(visible.into()); + /// Sets the shadow strength of this display. + pub fn set_shadow_strength(&self, strength: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(strength); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisibleByDefault", + "setShadowStrength", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn is_visible_by_default(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isVisibleByDefault", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get all players that are currently tracking this entity. - /// - /// 'Tracking' means that this entity has been sent to the player and that - /// they are receiving updates on its state. Note that the client's {@code - /// 'Entity Distance'} setting does not affect the range at which entities - /// are tracked. - pub fn tracked_by( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Gets the width of this display. + pub fn display_width(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDisplayWidth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.f()?) } - /// Sets whether the entity has a team colored (default: white) glow. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Sets the width of this display. + pub fn set_display_width(&self, width: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(width); let res = self.jni_ref().call_method( &self.jni_object(), - "setGlowing", + "setDisplayWidth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is glowing or not. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn is_glowing(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); + /// Gets the height of this display. + pub fn display_height(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDisplayHeight", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.f()?) } - /// Sets whether the entity is invulnerable or not. - /// - /// When an entity is invulnerable it can only be damaged by players in - /// creative mode. - pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Sets the height if this display. + pub fn set_display_height(&self, height: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(height); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvulnerable", + "setDisplayHeight", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invulnerable or not. - pub fn is_invulnerable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets whether the entity is silent or not. - pub fn is_silent(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + /// Gets the amount of ticks before client-side interpolation will commence. + pub fn interpolation_delay(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getInterpolationDelay", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets whether the entity is silent or not. - /// - /// When an entity is silent it will not produce any sound. - pub fn set_silent(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Sets the amount of ticks before client-side interpolation will commence. + pub fn set_interpolation_delay(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setSilent", + "setInterpolationDelay", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether gravity applies to this entity. - pub fn has_gravity(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the billboard setting of this entity. + /// The billboard setting controls the automatic rotation of the entity to + /// face the player. + pub fn billboard( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Display/Billboard;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBillboard", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::DisplayBillboard::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets whether gravity applies to this entity. - pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gravity.into()); + /// Sets the billboard setting of this entity. + /// The billboard setting controls the automatic rotation of the entity to + /// face the player. + pub fn set_billboard( + &self, + billboard: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Display/Billboard;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(billboard.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setGravity", + "setBillboard", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the period of time (in ticks) before this entity can use a portal. - pub fn portal_cooldown(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the scoreboard team overridden glow color of this display. + pub fn glow_color_override( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Color;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPortalCooldown", + "getGlowColorOverride", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Color::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Sets the period of time (in ticks) before this entity can use a portal. - pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(cooldown); + /// Sets the scoreboard team overridden glow color of this display. + pub fn set_glow_color_override( + &self, + color: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Color;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(color.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPortalCooldown", + "setGlowColorOverride", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a set of tags for this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn scoreboard_tags( + /// Gets the brightness override of the entity. + pub fn brightness( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getScoreboardTags", - sig.as_str(), - vec![], - ); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Display/Brightness;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBrightness", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::DisplayBrightness::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Add a tag to this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn add_scoreboard_tag( + /// Sets the brightness override of the entity. + pub fn set_brightness( &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); + brightness: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Display/Brightness;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(brightness.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "addScoreboardTag", + "setBrightness", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Removes a given tag from this entity. - pub fn remove_scoreboard_tag( + /// Stores the entity's current position in the provided Location object. + /// + /// If the provided Location is null this method does nothing and returns + /// null. + pub fn get_location( &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeScoreboardTag", + "getLocation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Returns the reaction of the entity when moved by a piston. - pub fn piston_move_reaction( + /// Sets this entity's velocity in meters per tick + pub fn set_velocity( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + velocity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getPistonMoveReaction", + "setVelocity", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets this entity's current velocity + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the closest cardinal {@link BlockFace} direction an entity is - /// currently facing. - /// - /// This will not return any non-cardinal directions such as - /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. - /// - /// {@link Hanging} entities will override this call and thus their behavior - /// may be different. - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + /// Gets the entity's height + pub fn height(&self) -> Result> { + let sig = String::from("()D"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.d()?) } - /// Gets the entity's current pose. - /// Note that the pose is only updated at the end of a tick, so may be - /// inconsistent with other methods. eg {@link Player#isSneaking()} being - /// true does not imply the current pose will be {@link Pose#SNEAKING} - pub fn pose(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Pose;"); + /// Gets the entity's width + pub fn width(&self) -> Result> { + let sig = String::from("()D"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.d()?) } - /// Get the category of spawn to which this entity belongs. - pub fn spawn_category( + /// Gets the entity's current bounding box. + /// + /// The returned bounding box reflects the entity's current location and + /// size. + pub fn bounding_box( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSpawnCategory", - sig.as_str(), - vec![], - ); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Checks if this entity has been spawned in a world. - /// - /// Entities not spawned in a world will not tick, be sent to players, or be - /// saved to the server files. - pub fn is_in_world(&self) -> Result> { + /// Returns true if the entity is supported by a block. This value is a + /// state updated by the server and is not recalculated unless the entity + /// moves. + pub fn is_on_ground(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get this entity as an NBT string. - /// - /// This string should not be relied upon as a serializable value. - pub fn as_string(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + /// Returns true if the entity is in water. + pub fn is_in_water(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(res.z()?) } - /// Crates an {@link EntitySnapshot} representing the current state of this entity. - pub fn create_snapshot( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + /// Gets the current world this entity resides in + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::EntitySnapshot::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// Sets the entity's rotation. /// - /// Note: Players cannot be copied. - pub fn copy( + /// Note that if the entity is affected by AI, it may override this rotation. + pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { + let sig = String::from("(FF)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); + let val_2 = jni::objects::JValueGen::Float(pitch); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRotation", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Teleports this entity to the given location. If this entity is riding a + /// vehicle, it will be dismounted prior to teleportation. + pub fn teleport( &self, - to: std::option::Option>>, - ) -> Result, Box> { + location: impl Into>, + cause: std::option::Option< + impl Into>, + >, + ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = to { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = cause { + sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); - args.push(val_1); + args.push(val_2); } - sig += ")Lorg/bukkit/entity/Entity;"; + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); + .call_method(&self.jni_object(), "teleport", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Wither<'mc> { - fn into(self) -> crate::entity::Monster<'mc> { - crate::entity::Monster::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Wither into crate::entity::Monster") - } -} -impl<'mc> Into> for Wither<'mc> { - fn into(self) -> crate::entity::Boss<'mc> { - crate::entity::Boss::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Wither into crate::entity::Boss") - } -} -pub enum WitherHead<'mc> {} -impl<'mc> std::fmt::Display for WitherHead<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + Ok(res.z()?) } -} - -impl<'mc> WitherHead<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/Wither/Head"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/Wither/Head;", - vec![jni::objects::JValueGen::from(val_1)], + /// Returns a list of entities within a bounding box centered around this + /// entity + pub fn get_nearby_entities( + &self, + x: f64, + y: f64, + z: f64, + ) -> Result>, Box> { + let sig = String::from("(DDD)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Double(x); + let val_2 = jni::objects::JValueGen::Double(y); + let val_3 = jni::objects::JValueGen::Double(z); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNearbyEntities", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct WitherHeadStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for WitherHead<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for WitherHead<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate WitherHead from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Wither/Head")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a WitherHead object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for WitherHeadStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for WitherHeadStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate WitherHeadStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Wither/Head")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a WitherHeadStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> WitherHeadStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Wither/Head;"); - let cls = jni.find_class("org/bukkit/entity/Wither/Head"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::WitherHead::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct Sittable<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Sittable<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Sittable<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Sittable from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Sittable")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Sittable object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); } + Ok(new_vec) } -} - -impl<'mc> Sittable<'mc> { - /// Checks if this animal is sitting - pub fn is_sitting(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSitting", sig.as_str(), vec![]); + /// Returns a unique id for this entity + pub fn entity_id(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets if this animal is sitting. Will remove any path that the animal - /// was following beforehand. - pub fn set_sitting(&self, sitting: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(sitting.into()); + /// Returns the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's maximum fire ticks. + pub fn max_fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setSitting", + "setFireTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct Enderman<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Enderman<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Sets if the entity has visual fire (it will always appear to be on fire). + pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVisualFire", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets if the entity has visual fire (it will always appear to be on fire). + pub fn is_visual_fire(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for Enderman<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Enderman from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Enderman")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Enderman object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Returns the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} - -impl<'mc> Enderman<'mc> { - /// Gets the id and data of the block that the Enderman is carrying. - pub fn carried_material( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/MaterialData;"); + /// Returns the entity's maximum freeze ticks (amount of ticks before it will + /// be fully frozen) + pub fn max_freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCarriedMaterial", + "getMaxFreezeTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Sets the id and data of the block that the Enderman is carrying. - pub fn set_carried_material( - &self, - material: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/material/MaterialData;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); + /// Sets the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setCarriedMaterial", + "setFreezeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the data of the block that the Enderman is carrying. - pub fn carried_block( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCarriedBlock", sig.as_str(), vec![]); + /// Gets if the entity is fully frozen (it has been in powdered snow for max + /// freeze ticks). + pub fn is_frozen(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::block::data::BlockData::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Sets the data of the block that the Enderman is carrying. - pub fn set_carried_block( - &self, - block_data: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block_data.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCarriedBlock", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Mark the entity's removal. + pub fn remove(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Randomly teleports the Enderman in a 64x64x64 block cuboid region. - /// - /// If the randomly selected point is in the ground, the point is moved 1 block - /// down until air is found or until it goes under - /// {@link org.bukkit.World#getMinHeight()}. - /// - /// This method will return false if this Enderman is not alive, or if the - /// teleport location was obstructed, or if the teleport location is in water. - pub fn teleport(&self) -> Result> { + /// Returns true if this entity has been marked for removal. + pub fn is_dead(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "teleport", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Randomly teleports the Enderman towards the given entity. + /// Returns false if the entity has died, been despawned for some other + /// reason, or has not been added to the world. + pub fn is_valid(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the {@link Server} that contains this Entity + pub fn server(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Server;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Server::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns true if the entity gets persisted. /// - /// The point is selected by drawing a vector between this enderman and the - /// given entity. That vector's length is set to 16 blocks. - /// That point is then moved within a 8x8x8 cuboid region. If the randomly - /// selected point is in the ground, the point is moved 1 block down until - /// air is found or until it goes under - /// {@link org.bukkit.World#getMinHeight()}. + /// By default all entities are persistent. An entity will also not get + /// persisted, if it is riding an entity that is not persistent. /// - /// This method will return false if this Enderman is not alive, or if the - /// teleport location was obstructed, or if the teleport location is in water. - pub fn teleport_towards( - &self, - entity: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "teleportTowards", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// The persistent flag on players controls whether or not to save their + /// playerdata file when they quit. If a player is directly or indirectly + /// riding a non-persistent entity, the vehicle at the root and all its + /// passengers won't get persisted. + /// + /// This should not be confused with + /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls + /// despawning of living entities. + pub fn is_persistent(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the height of the living entity's eyes above its Location. - pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { - let sig = String::from("(Z)D"); - let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); + /// Sets whether or not the entity gets persisted. + pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(persistent.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getEyeHeight", + "setPersistent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get a Location detailing the current eye position of the living entity. - pub fn eye_location(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); + #[deprecated] + /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. + pub fn passenger( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets all blocks along the living entity's line of sight. - /// - /// This list contains all blocks from the living entity's eye position to - /// target inclusive. This method considers all blocks as 1x1x1 in size. - pub fn get_line_of_sight( + #[deprecated] + /// Set the passenger of a vehicle. + pub fn set_passenger( &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { - let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "getLineOfSight", + "setPassenger", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets a list of passengers of this vehicle. + /// + /// The returned list will not be directly linked to the entity's current + /// passengers, and no guarantees are made as to its mutability. + pub fn passengers( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); } Ok(new_vec) } - /// Gets the block that the living entity has targeted. - /// - /// This method considers all blocks as 1x1x1 in size. To take exact block - /// collision shapes into account, see {@link #getTargetBlockExact(int, - /// FluidCollisionMode)}. - pub fn get_target_block( + /// Add a passenger to the vehicle. + pub fn add_passenger( &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result, Box> { - let sig = String::from("(Ljava/util/Set;I)Lorg/bukkit/block/Block;"); + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "getTargetBlock", + "addPassenger", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Gets the last two blocks along the living entity's line of sight. - /// - /// The target block will be the last block in the list. This method - /// considers all blocks as 1x1x1 in size. - pub fn get_last_two_target_blocks( + /// Remove a passenger from the vehicle. + pub fn remove_passenger( &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { - let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "getLastTwoTargetBlocks", + "removePassenger", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(res.z()?) } - /// Gets the block that the living entity has targeted. - /// - /// This takes the blocks' precise collision shapes into account. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn get_target_block_exact( - &self, - max_distance: i32, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(max_distance); - args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/block/Block;"; + /// Check if a vehicle has passengers. + pub fn is_empty(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Eject any passenger. + pub fn eject(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the distance this entity has fallen + pub fn fall_distance(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the fall distance for this entity + pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(distance); let res = self.jni_ref().call_method( &self.jni_object(), - "getTargetBlockExact", + "setFallDistance", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::block::Block::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Performs a ray trace that provides information on the targeted block. - /// - /// This takes the blocks' precise collision shapes into account. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn ray_trace_blocks( + #[deprecated] + /// Record the last {@link EntityDamageEvent} inflicted on this entity + pub fn set_last_damage_cause( &self, - max_distance: f64, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(max_distance); - args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/util/RayTraceResult;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); + event: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(event.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLastDamageCause", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. + /// This event may have been cancelled. + pub fn last_damage_cause( + &self, + ) -> Result>, Box> + { + let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLastDamageCause", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::util::RayTraceResult::from_raw( + Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Returns the amount of air that the living entity has remaining, in - /// ticks. - pub fn remaining_air(&self) -> Result> { + /// Returns a unique and persistent id for this entity + pub fn unique_id( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. + pub fn ticks_lived(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the amount of air that the living entity has remaining, in ticks. - pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { + /// Sets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. May not be less than one + /// tick. + pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + let val_1 = jni::objects::JValueGen::Int(value); let res = self.jni_ref().call_method( &self.jni_object(), - "setRemainingAir", + "setTicksLived", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the maximum amount of air the living entity can have, in ticks. - pub fn maximum_air(&self) -> Result> { - let sig = String::from("()I"); + /// Performs the specified {@link EntityEffect} for this entity. + /// + /// This will be viewable to all players near the entity. + /// + /// If the effect is not applicable to this class of entity, it will not play. + pub fn play_effect( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "playEffect", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the type of the entity. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes while swimming. + pub fn swim_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the maximum amount of air the living entity can have, in ticks. - pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Get the {@link Sound} this entity makes when splashing in water. For most + /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_splash_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaximumAir", + "getSwimSplashSound", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the item that the player is using (eating food, drawing back a bow, - /// blocking, etc.) - pub fn item_in_use( + /// Get the {@link Sound} this entity makes when splashing in water at high + /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_high_speed_splash_sound( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSwimHighSpeedSplashSound", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns whether this entity is inside a vehicle. + pub fn is_inside_vehicle(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Leave the current vehicle. If the entity is currently in a vehicle (and + /// is removed from it), true will be returned, otherwise false will be + /// returned. + pub fn leave_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the vehicle that this entity is inside. If there is no vehicle, + /// null will be returned. + pub fn vehicle( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::ItemStack::from_raw( + Ok(Some(crate::entity::Entity::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Gets the number of ticks remaining for the current item's usage. - pub fn item_in_use_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getItemInUseTicks", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the number of ticks that remain for the current item's usage. - /// Applies to items that take time to use, like eating food, drawing a bow, - /// or throwing a trident. - pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets whether or not to display the mob's custom name client side. The + /// name will be displayed above the mob similarly to a player. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemInUseTicks", + "setCustomNameVisible", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the time in ticks until the next arrow leaves the entity's body. - pub fn arrow_cooldown(&self) -> Result> { - let sig = String::from("()I"); + /// Gets whether or not the mob's custom name is displayed client side. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn is_custom_name_visible(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getArrowCooldown", + "isCustomNameVisible", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the time in ticks until the next arrow leaves the entity's body. - pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(visible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setArrowCooldown", + "setVisibleByDefault", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the amount of arrows in an entity's body. - pub fn arrows_in_body(&self) -> Result> { - let sig = String::from("()I"); + /// Gets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn is_visible_by_default(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isVisibleByDefault", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get all players that are currently tracking this entity. + /// + /// 'Tracking' means that this entity has been sent to the player and that + /// they are receiving updates on its state. Note that the client's {@code + /// 'Entity Distance'} setting does not affect the range at which entities + /// are tracked. + pub fn tracked_by( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the amount of arrows in the entity's body. - pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(count); + /// Sets whether the entity has a team colored (default: white) glow. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setArrowsInBody", + "setGlowing", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's current maximum no damage ticks. + /// Gets whether the entity is glowing or not. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn is_glowing(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the entity is invulnerable or not. /// - /// This is the maximum duration in which the living entity will not take - /// damage. - pub fn maximum_no_damage_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// When an entity is invulnerable it can only be damaged by players in + /// creative mode. + pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getMaximumNoDamageTicks", + "setInvulnerable", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether the entity is invulnerable or not. + pub fn is_invulnerable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the living entity's current maximum no damage ticks. - pub fn set_maximum_no_damage_ticks( - &self, - ticks: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Gets whether the entity is silent or not. + pub fn is_silent(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the entity is silent or not. + /// + /// When an entity is silent it will not produce any sound. + pub fn set_silent(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaximumNoDamageTicks", + "setSilent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's last damage taken in the current no damage - /// ticks time. - /// - /// Only damage higher than this amount will further damage the living - /// entity. - pub fn last_damage(&self) -> Result> { - let sig = String::from("()D"); + /// Returns whether gravity applies to this entity. + pub fn has_gravity(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Sets the damage dealt within the current no damage ticks time period. - pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(damage); + /// Sets whether gravity applies to this entity. + pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gravity.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDamage", + "setGravity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's current no damage ticks. - pub fn no_damage_ticks(&self) -> Result> { + /// Gets the period of time (in ticks) before this entity can use a portal. + pub fn portal_cooldown(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getNoDamageTicks", + "getPortalCooldown", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the living entity's current no damage ticks. - pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Sets the period of time (in ticks) before this entity can use a portal. + pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + let val_1 = jni::objects::JValueGen::Int(cooldown); let res = self.jni_ref().call_method( &self.jni_object(), - "setNoDamageTicks", + "setPortalCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the ticks that this entity has performed no action. + /// Returns a set of tags for this entity. /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn no_action_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Entities can have no more than 1024 tags. + pub fn scoreboard_tags( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getNoActionTicks", + "getScoreboardTags", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the ticks that this entity has performed no action. + /// Add a tag to this entity. /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Entities can have no more than 1024 tags. + pub fn add_scoreboard_tag( + &self, + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setNoActionTicks", + "addScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Removes a given tag from this entity. + pub fn remove_scoreboard_tag( + &self, + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeScoreboardTag", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the reaction of the entity when moved by a piston. + pub fn piston_move_reaction( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPistonMoveReaction", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the closest cardinal {@link BlockFace} direction an entity is + /// currently facing. + /// + /// This will not return any non-cardinal directions such as + /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// + /// {@link Hanging} entities will override this call and thus their behavior + /// may be different. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the entity's current pose. + /// Note that the pose is only updated at the end of a tick, so may be + /// inconsistent with other methods. eg {@link Player#isSneaking()} being + /// true does not imply the current pose will be {@link Pose#SNEAKING} + pub fn pose(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Pose;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the category of spawn to which this entity belongs. + pub fn spawn_category( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSpawnCategory", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Checks if this entity has been spawned in a world. + /// + /// Entities not spawned in a world will not tick, be sent to players, or be + /// saved to the server files. + pub fn is_in_world(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get this entity as an NBT string. + /// + /// This string should not be relied upon as a serializable value. + pub fn as_string(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Gets the player identified as the killer of the living entity. - /// - /// May be null. - pub fn killer(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Player;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); + /// Crates an {@link EntitySnapshot} representing the current state of this entity. + pub fn create_snapshot( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Player::from_raw( + Ok(Some(crate::entity::EntitySnapshot::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - #[deprecated] - /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. - pub fn add_potion_effect( + /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// + /// Note: Players cannot be copied. + pub fn copy( &self, - effect: impl Into>, - force: std::option::Option, - ) -> Result> { + to: std::option::Option>>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/potion/PotionEffect;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(effect.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = force { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); + if let Some(a) = to { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); } - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); + sig += ")Lorg/bukkit/entity/Entity;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns whether the living entity already has an existing effect of - /// the given {@link PotionEffectType} applied to it. - pub fn has_potion_effect( - &self, - val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasPotionEffect", - sig.as_str(), + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for TextDisplay<'mc> { + fn into(self) -> crate::entity::Display<'mc> { + crate::entity::Display::from_raw(&self.jni_ref(), self.1) + .expect("Error converting TextDisplay into crate::entity::Display") + } +} +pub enum TextDisplayTextAlignment<'mc> { + Center { + inner: TextDisplayTextAlignmentStruct<'mc>, + }, + Left { + inner: TextDisplayTextAlignmentStruct<'mc>, + }, + Right { + inner: TextDisplayTextAlignmentStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for TextDisplayTextAlignment<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + TextDisplayTextAlignment::Center { .. } => f.write_str("CENTER"), + TextDisplayTextAlignment::Left { .. } => f.write_str("LEFT"), + TextDisplayTextAlignment::Right { .. } => f.write_str("RIGHT"), + } + } +} +impl<'mc> std::ops::Deref for TextDisplayTextAlignment<'mc> { + type Target = TextDisplayTextAlignmentStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + TextDisplayTextAlignment::Center { inner } => inner, + TextDisplayTextAlignment::Left { inner } => inner, + TextDisplayTextAlignment::Right { inner } => inner, + } + } +} + +impl<'mc> TextDisplayTextAlignment<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/TextDisplay/TextAlignment"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/TextDisplay/TextAlignment;", vec![jni::objects::JValueGen::from(val_1)], ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "CENTER" => Ok(TextDisplayTextAlignment::Center { + inner: TextDisplayTextAlignmentStruct::from_raw(env, obj)?, + }), + "LEFT" => Ok(TextDisplayTextAlignment::Left { + inner: TextDisplayTextAlignmentStruct::from_raw(env, obj)?, + }), + "RIGHT" => Ok(TextDisplayTextAlignment::Right { + inner: TextDisplayTextAlignmentStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct TextDisplayTextAlignmentStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for TextDisplayTextAlignment<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Center { inner } => inner.0.clone(), + Self::Left { inner } => inner.0.clone(), + Self::Right { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Center { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Left { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Right { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for TextDisplayTextAlignment<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate TextDisplayTextAlignment from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/entity/TextDisplay/TextAlignment")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a TextDisplayTextAlignment object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "CENTER" => Ok(TextDisplayTextAlignment::Center { + inner: TextDisplayTextAlignmentStruct::from_raw(env, obj)?, + }), + "LEFT" => Ok(TextDisplayTextAlignment::Left { + inner: TextDisplayTextAlignmentStruct::from_raw(env, obj)?, + }), + "RIGHT" => Ok(TextDisplayTextAlignment::Right { + inner: TextDisplayTextAlignmentStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for TextDisplayTextAlignmentStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for TextDisplayTextAlignmentStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate TextDisplayTextAlignmentStruct from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/entity/TextDisplay/TextAlignment")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a TextDisplayTextAlignmentStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> TextDisplayTextAlignmentStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/TextDisplay/TextAlignment;"); + let cls = jni.find_class("org/bukkit/entity/TextDisplay/TextAlignment"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::TextDisplayTextAlignment::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct Egg<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Egg<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Egg<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Egg from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Egg")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Egg object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Egg<'mc> { + /// Gets the ItemStack the thrown projectile will display. + pub fn item(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/inventory/ItemStack;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the active {@link PotionEffect} of the specified type. - /// - /// If the effect is not present on the entity then null will be returned. - pub fn get_potion_effect( + /// Sets the display ItemStack for the thrown projectile. + pub fn set_item( &self, - val_type: impl Into>, - ) -> Result>, Box> { - let sig = - String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); + item: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPotionEffect", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setItem", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Retrieve the shooter of this projectile. + pub fn shooter( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/projectiles/ProjectileSource;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getShooter", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::potion::PotionEffect::from_raw( + Ok(Some(crate::projectiles::ProjectileSource::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Removes any effects present of the given {@link PotionEffectType}. - pub fn remove_potion_effect( + /// Set the shooter of this projectile. + pub fn set_shooter( &self, - val_type: impl Into>, + source: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); + let sig = String::from("(Lorg/bukkit/projectiles/ProjectileSource;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(source.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removePotionEffect", + "setShooter", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns all currently active {@link PotionEffect}s on the living - /// entity. - pub fn active_potion_effects( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getActivePotionEffects", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Checks whether the living entity has block line of sight to another. - /// - /// This uses the same algorithm that hostile mobs use to find the closest - /// player. - pub fn has_line_of_sight( - &self, - other: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasLineOfSight", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns if the living entity despawns when away from players or not. - /// - /// By default, animals are not removed while other mobs are. - pub fn remove_when_far_away(&self) -> Result> { + #[deprecated] + /// Determine if this projectile should bounce or not when it hits. + pub fn does_bounce(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getRemoveWhenFarAway", - sig.as_str(), - vec![], - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "doesBounce", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not the living entity despawns when away from players - /// or not. - pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { + #[deprecated] + /// Set whether or not this projectile should bounce or not when it hits something. + pub fn set_bounce(&self, does_bounce: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(remove.into()); + let val_1 = jni::objects::JValueGen::Bool(does_bounce.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setRemoveWhenFarAway", + "setBounce", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the inventory with the equipment worn by the living entity. - pub fn equipment( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::EntityEquipment::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Sets whether or not the living entity can pick up items. - pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(pickup.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCanPickupItems", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +} +impl<'mc> Into> for Egg<'mc> { + fn into(self) -> crate::entity::ThrowableProjectile<'mc> { + crate::entity::ThrowableProjectile::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Egg into crate::entity::ThrowableProjectile") } - /// Gets if the living entity can pick up items. - pub fn can_pickup_items(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCanPickupItems", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} +#[repr(C)] +pub struct Explosive<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Explosive<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Returns whether the entity is currently leashed. - pub fn is_leashed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Gets the entity that is currently leading this entity. - pub fn leash_holder(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} +impl<'mc> JNIInstantiatable<'mc> for Explosive<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Explosive from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Explosive")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Explosive object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } - /// Sets the leash on this entity to be held by the supplied entity. - /// - /// This method has no effect on EnderDragons, Withers, Players, or Bats. - /// Non-living entities excluding leashes will not persist as leash - /// holders. - pub fn set_leash_holder( - &self, - holder: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(holder.into().jni_object().clone()) - }); +} + +impl<'mc> Explosive<'mc> { + /// Set the radius affected by this explosive's explosion + pub fn set_yield(&self, val_yield: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(val_yield); let res = self.jni_ref().call_method( &self.jni_object(), - "setLeashHolder", + "setYield", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Checks to see if an entity is gliding, such as using an Elytra. - pub fn is_gliding(&self) -> Result> { - let sig = String::from("()Z"); + /// Return the radius or yield of this explosive's explosion + pub fn get_yield(&self) -> Result> { + let sig = String::from("()F"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getYield", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.f()?) } - /// Makes entity start or stop gliding. This will work even if an Elytra - /// is not equipped, but will be reverted by the server immediately after - /// unless an event-cancelling mechanism is put in place. - pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { + /// Set whether or not this explosive's explosion causes fire + pub fn set_is_incendiary(&self, is_incendiary: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gliding.into()); + let val_1 = jni::objects::JValueGen::Bool(is_incendiary.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setGliding", + "setIsIncendiary", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks to see if an entity is swimming. - pub fn is_swimming(&self) -> Result> { + /// Return whether or not this explosive creates a fire when exploding + pub fn is_incendiary(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isIncendiary", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Makes entity start or stop swimming. - /// This may have unexpected results if the entity is not in water. - pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(swimming.into()); + /// Stores the entity's current position in the provided Location object. + /// + /// If the provided Location is null this method does nothing and returns + /// null. + pub fn get_location( + &self, + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setSwimming", + "getLocation", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Sets this entity's velocity in meters per tick + pub fn set_velocity( + &self, + velocity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVelocity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks to see if an entity is currently using the Riptide enchantment. - pub fn is_riptiding(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets this entity's current velocity + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns whether this entity is slumbering. - pub fn is_sleeping(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the entity's height + pub fn height(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the entity's width + pub fn width(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the entity's current bounding box. + /// + /// The returned bounding box reflects the entity's current location and + /// size. + pub fn bounding_box( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets if the entity is climbing. - pub fn is_climbing(&self) -> Result> { + /// Returns true if the entity is supported by a block. This value is a + /// state updated by the server and is not recalculated unless the entity + /// moves. + pub fn is_on_ground(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether an entity will have AI. - /// The entity will be completely unable to move if it has no AI. - pub fn set_ai(&self, ai: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(ai.into()); + /// Returns true if the entity is in water. + pub fn is_in_water(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the current world this entity resides in + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the entity's rotation. + /// + /// Note that if the entity is affected by AI, it may override this rotation. + pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { + let sig = String::from("(FF)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); + let val_2 = jni::objects::JValueGen::Float(pitch); let res = self.jni_ref().call_method( &self.jni_object(), - "setAI", + "setRotation", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks whether an entity has AI. - /// The entity will be completely unable to move if it has no AI. - pub fn has_ai(&self) -> Result> { - let sig = String::from("()Z"); + /// Teleports this entity to the given location. If this entity is riding a + /// vehicle, it will be dismounted prior to teleportation. + pub fn teleport( + &self, + location: impl Into>, + cause: std::option::Option< + impl Into>, + >, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = cause { + sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "teleport", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Makes this entity attack the given entity with a melee attack. - /// Attack damage is calculated by the server from the attributes and - /// equipment of this mob, and knockback is applied to {@code target} as - /// appropriate. - pub fn attack( + /// Returns a list of entities within a bounding box centered around this + /// entity + pub fn get_nearby_entities( &self, - target: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) - }); + x: f64, + y: f64, + z: f64, + ) -> Result>, Box> { + let sig = String::from("(DDD)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Double(x); + let val_2 = jni::objects::JValueGen::Double(y); + let val_3 = jni::objects::JValueGen::Double(z); let res = self.jni_ref().call_method( &self.jni_object(), - "attack", + "getNearbyEntities", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Makes this entity swing their main hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their main hand. - pub fn swing_main_hand(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Returns a unique id for this entity + pub fn entity_id(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Makes this entity swing their off hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their off hand. - pub fn swing_off_hand(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Returns the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn fire_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Makes this entity flash red as if they were damaged. - pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); + /// Returns the entity's maximum fire ticks. + pub fn max_fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "playHurtAnimation", + "setFireTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Set if this entity will be subject to collisions with other entities. - /// - /// Exemptions to this rule can be managed with - /// {@link #getCollidableExemptions()} - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not working for player collisions. This - /// method should therefore only be used to set the collision status of - /// non-player entities. - /// - /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in - /// combination with a {@link Scoreboard} and a {@link Team}. - pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { + /// Sets if the entity has visual fire (it will always appear to be on fire). + pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(collidable.into()); + let val_1 = jni::objects::JValueGen::Bool(fire.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCollidable", + "setVisualFire", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if this entity is subject to collisions with other entities. - /// - /// Some entities might be exempted from the collidable rule of this entity. - /// Use {@link #getCollidableExemptions()} to get these. - /// - /// Please note that this method returns only the custom collidable state, - /// not whether the entity is non-collidable for other reasons such as being - /// dead. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not being accurate for player collisions. - /// This method should therefore only be used to check the collision status - /// of non-player entities. - /// - /// To check the collision behavior for a player, use - /// {@link Team.Option#COLLISION_RULE} in combination with a - /// {@link Scoreboard} and a {@link Team}. - pub fn is_collidable(&self) -> Result> { + /// Gets if the entity has visual fire (it will always appear to be on fire). + pub fn is_visual_fire(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets a mutable set of UUIDs of the entities which are exempt from the - /// entity's collidable rule and which's collision with this entity will - /// behave the opposite of it. - /// - /// This set can be modified to add or remove exemptions. - /// - /// For example if collidable is true and an entity is in the exemptions set - /// then it will not collide with it. Similarly if collidable is false and an - /// entity is in this set then it will still collide with it. - /// - /// Note these exemptions are not (currently) persistent. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in those exemptions not being accurate for player - /// collisions. This method should therefore only be used to exempt - /// non-player entities. - /// - /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} - /// in combination with a {@link Scoreboard} and a {@link Team}. - pub fn collidable_exemptions( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Returns the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's maximum freeze ticks (amount of ticks before it will + /// be fully frozen) + pub fn max_freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCollidableExemptions", + "getMaxFreezeTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Returns the value of the memory specified. - /// - /// Note that the value is null when the specific entity does not have that - /// value by default. - pub fn get_memory( - &self, - memory_key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) - }); + /// Sets the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "getMemory", + "setFreezeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the entity is fully frozen (it has been in powdered snow for max + /// freeze ticks). + pub fn is_frozen(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(res.l()?)) + Ok(res.z()?) } - /// Sets the value of the memory specified. - /// - /// Note that the value will not be persisted when the specific entity does - /// not have that value by default. - pub fn set_memory( - &self, - memory_key: impl Into>, - memory_value: jni::objects::JObject<'mc>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(memory_value); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMemory", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + /// Mark the entity's removal. + pub fn remove(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the {@link Sound} this entity will make when damaged. - pub fn hurt_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Returns true if this entity has been marked for removal. + pub fn is_dead(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns false if the entity has died, been despawned for some other + /// reason, or has not been added to the world. + pub fn is_valid(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the {@link Server} that contains this Entity + pub fn server(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Server;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Server::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns true if the entity gets persisted. + /// + /// By default all entities are persistent. An entity will also not get + /// persisted, if it is riding an entity that is not persistent. + /// + /// The persistent flag on players controls whether or not to save their + /// playerdata file when they quit. If a player is directly or indirectly + /// riding a non-persistent entity, the vehicle at the root and all its + /// passengers won't get persisted. + /// + /// This should not be confused with + /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls + /// despawning of living entities. + pub fn is_persistent(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.z()?) } - /// Get the {@link Sound} this entity will make on death. - pub fn death_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Sets whether or not the entity gets persisted. + pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(persistent.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPersistent", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. + pub fn passenger( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Get the {@link Sound} this entity will make when falling from the given - /// height (in blocks). The sound will often differ between either a small - /// or a big fall damage sound if the height exceeds 4 blocks. - pub fn get_fall_damage_sound( + #[deprecated] + /// Set the passenger of a vehicle. + pub fn set_passenger( &self, - fall_height: i32, - ) -> Result, Box> { - let sig = String::from("(I)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Int(fall_height); + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSound", + "setPassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity will make when falling from a small - /// height. - pub fn fall_damage_sound_small(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFallDamageSoundSmall", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Get the {@link Sound} this entity will make when falling from a large - /// height. - pub fn fall_damage_sound_big(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFallDamageSoundBig", - sig.as_str(), - vec![], - ); + /// Gets a list of passengers of this vehicle. + /// + /// The returned list will not be directly linked to the entity's current + /// passengers, and no guarantees are made as to its mutability. + pub fn passengers( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Get the {@link Sound} this entity will make when drinking the given - /// {@link ItemStack}. - pub fn get_drinking_sound( + /// Add a passenger to the vehicle. + pub fn add_passenger( &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getDrinkingSound", + "addPassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Get the {@link Sound} this entity will make when eating the given - /// {@link ItemStack}. - pub fn get_eating_sound( + /// Remove a passenger from the vehicle. + pub fn remove_passenger( &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getEatingSound", + "removePassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Returns true if this entity can breathe underwater and will not take - /// suffocation damage when its air supply reaches zero. - pub fn can_breathe_underwater(&self) -> Result> { + /// Check if a vehicle has passengers. + pub fn is_empty(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "canBreatheUnderwater", - sig.as_str(), - vec![], - ); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. - pub fn category( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); + /// Eject any passenger. + pub fn eject(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the distance this entity has fallen + pub fn fall_distance(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.f()?) } - /// Sets whether the entity is invisible or not. - pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(invisible.into()); + /// Sets the fall distance for this entity + pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvisible", + "setFallDistance", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invisible or not. - pub fn is_invisible(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the specified attribute instance from the object. This instance will - /// be backed directly to the object and any changes will be visible at once. - pub fn get_attribute( + #[deprecated] + /// Record the last {@link EntityDamageEvent} inflicted on this entity + pub fn set_last_damage_cause( &self, - attribute: impl Into>, - ) -> Result>, Box> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", - ); + event: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + jni::objects::JObject::from_raw(event.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getAttribute", + "setLastDamageCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. + /// This event may have been cancelled. + pub fn last_damage_cause( + &self, + ) -> Result>, Box> + { + let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLastDamageCause", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::attribute::AttributeInstance::from_raw( + Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Deals the given amount of damage to this entity from a specified - /// {@link DamageSource}. - pub fn damage( + /// Returns a unique and persistent id for this entity + pub fn unique_id( &self, - amount: f64, - damage_source: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(amount); - args.push(val_1); - if let Some(a) = damage_source { - sig += "Lorg/bukkit/damage/DamageSource;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "damage", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. - pub fn health(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is - /// dead. - pub fn set_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setHealth", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the entity's absorption amount. - pub fn absorption_amount(&self) -> Result> { - let sig = String::from("()D"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAbsorptionAmount", - sig.as_str(), - vec![], - ); + /// Gets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. + pub fn ticks_lived(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.i()?) } - /// Sets the entity's absorption amount. + /// Sets the amount of ticks this entity has lived for. /// - /// Note: The amount is capped to the value of - /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on - /// that attribute is currently unspecified and subject to change. - pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(amount); + /// This is the equivalent to "age" in entities. May not be less than one + /// tick. + pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(value); let res = self.jni_ref().call_method( &self.jni_object(), - "setAbsorptionAmount", + "setTicksLived", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the maximum health this entity has. - pub fn max_health(&self) -> Result> { - let sig = String::from("()D"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - #[deprecated] - /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. - pub fn set_max_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); + /// Performs the specified {@link EntityEffect} for this entity. + /// + /// This will be viewable to all players near the entity. + /// + /// If the effect is not applicable to this class of entity, it will not play. + pub fn play_effect( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxHealth", + "playEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Resets the max health to the original amount. - pub fn reset_max_health(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Launches a {@link Projectile} from the ProjectileSource with an - /// initial velocity. - pub fn launch_projectile( - &self, - projectile: jni::objects::JClass<'mc>, - velocity: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/Class;"; - let val_1 = jni::objects::JValueGen::Object(projectile.into()); - args.push(val_1); - if let Some(a) = velocity { - sig += "Lorg/bukkit/util/Vector;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")LT;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); + /// Get the type of the entity. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Enderman<'mc> { - fn into(self) -> crate::entity::Monster<'mc> { - crate::entity::Monster::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Enderman into crate::entity::Monster") - } -} -#[repr(C)] -pub struct ChestBoat<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for ChestBoat<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for ChestBoat<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ChestBoat from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ChestBoat")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ChestBoat object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} - -impl<'mc> ChestBoat<'mc> { - #[deprecated] - /// Gets the wood type of the boat. - pub fn wood_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/TreeSpecies;"); + /// Get the {@link Sound} this entity makes while swimming. + pub fn swim_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getWoodType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::TreeSpecies::from_raw(&self.jni_ref(), unsafe { + crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - #[deprecated] - /// Sets the wood type of the boat. - pub fn set_wood_type( - &self, - species: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/TreeSpecies;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(species.into().jni_object().clone()) - }); + /// Get the {@link Sound} this entity makes when splashing in water. For most + /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_splash_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setWoodType", + "getSwimSplashSound", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the type of the boat. - pub fn boat_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Boat/Type;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBoatType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::BoatType::from_raw(&self.jni_ref(), unsafe { + crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the type of the boat. - pub fn set_boat_type( + /// Get the {@link Sound} this entity makes when splashing in water at high + /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_high_speed_splash_sound( &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Boat/Type;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setBoatType", + "getSwimHighSpeedSplashSound", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - /// Gets the maximum speed of a boat. The speed is unrelated to the velocity. - pub fn max_speed(&self) -> Result> { - let sig = String::from("()D"); + /// Returns whether this entity is inside a vehicle. + pub fn is_inside_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Leave the current vehicle. If the entity is currently in a vehicle (and + /// is removed from it), true will be returned, otherwise false will be + /// returned. + pub fn leave_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the vehicle that this entity is inside. If there is no vehicle, + /// null will be returned. + pub fn vehicle( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxSpeed", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - #[deprecated] - /// Sets the maximum speed of a boat. Must be nonnegative. Default is 0.4D. - pub fn set_max_speed(&self, speed: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(speed); + /// Sets whether or not to display the mob's custom name client side. The + /// name will be displayed above the mob similarly to a player. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxSpeed", + "setCustomNameVisible", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the deceleration rate (newSpeed = curSpeed * rate) of occupied boats. The default is 0.2. - pub fn occupied_deceleration(&self) -> Result> { - let sig = String::from("()D"); + /// Gets whether or not the mob's custom name is displayed client side. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn is_custom_name_visible(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getOccupiedDeceleration", + "isCustomNameVisible", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - #[deprecated] - /// Sets the deceleration rate (newSpeed = curSpeed * rate) of occupied boats. Setting this to a higher value allows for quicker acceleration. The default is 0.2. - pub fn set_occupied_deceleration(&self, rate: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(rate); + /// Sets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(visible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setOccupiedDeceleration", + "setVisibleByDefault", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the deceleration rate (newSpeed = curSpeed * rate) of unoccupied boats. The default is -1. Values below 0 indicate that no additional deceleration is imposed. - pub fn unoccupied_deceleration(&self) -> Result> { - let sig = String::from("()D"); + /// Gets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn is_visible_by_default(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getUnoccupiedDeceleration", + "isVisibleByDefault", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - #[deprecated] - /// Sets the deceleration rate (newSpeed = curSpeed * rate) of unoccupied boats. Setting this to a higher value allows for quicker deceleration of boats when a player disembarks. The default is -1. Values below 0 indicate that no additional deceleration is imposed. - pub fn set_unoccupied_deceleration(&self, rate: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(rate); + /// Get all players that are currently tracking this entity. + /// + /// 'Tracking' means that this entity has been sent to the player and that + /// they are receiving updates on its state. Note that the client's {@code + /// 'Entity Distance'} setting does not affect the range at which entities + /// are tracked. + pub fn tracked_by( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets whether the entity has a team colored (default: white) glow. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setUnoccupiedDeceleration", + "setGlowing", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Get whether boats can work on land. - pub fn work_on_land(&self) -> Result> { + /// Gets whether the entity is glowing or not. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn is_glowing(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getWorkOnLand", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Set whether boats can work on land. - pub fn set_work_on_land(&self, work_on_land: bool) -> Result<(), Box> { + /// Sets whether the entity is invulnerable or not. + /// + /// When an entity is invulnerable it can only be damaged by players in + /// creative mode. + pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(work_on_land.into()); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setWorkOnLand", + "setInvulnerable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the status of the boat. - pub fn status(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Boat/Status;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getStatus", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::BoatStatus::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the vehicle's velocity. - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); + /// Gets whether the entity is invulnerable or not. + pub fn is_invulnerable(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets the vehicle's velocity in meters per tick. - pub fn set_velocity( - &self, - vel: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(vel.into().jni_object().clone()) - }); + /// Gets whether the entity is silent or not. + pub fn is_silent(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the entity is silent or not. + /// + /// When an entity is silent it will not produce any sound. + pub fn set_silent(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setVelocity", + "setSilent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the object's inventory. - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + /// Returns whether gravity applies to this entity. + pub fn has_gravity(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Set the loot table for a container or entity. - /// - /// To remove a loot table use null. Do not use {@link LootTables#EMPTY} to - /// clear a LootTable. - pub fn set_loot_table( - &self, - table: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/loot/LootTable;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(table.into().jni_object().clone()) - }); + /// Sets whether gravity applies to this entity. + pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gravity.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLootTable", + "setGravity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the Loot Table attached to this block or entity. - /// - /// If an block/entity does not have a loot table, this will return null, NOT - /// an empty loot table. - pub fn loot_table( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/loot/LootTable;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLootTable", sig.as_str(), vec![]); + /// Gets the period of time (in ticks) before this entity can use a portal. + pub fn portal_cooldown(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPortalCooldown", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::loot::LootTable::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - /// Set the seed used when this Loot Table generates loot. - pub fn set_seed(&self, seed: i64) -> Result<(), Box> { - let sig = String::from("(J)V"); - let val_1 = jni::objects::JValueGen::Long(seed); + /// Sets the period of time (in ticks) before this entity can use a portal. + pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(cooldown); let res = self.jni_ref().call_method( &self.jni_object(), - "setSeed", + "setPortalCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the Loot Table's seed. + /// Returns a set of tags for this entity. /// - /// The seed is used when generating loot. - pub fn seed(&self) -> Result> { - let sig = String::from("()J"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSeed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for ChestBoat<'mc> { - fn into(self) -> crate::entity::Boat<'mc> { - crate::entity::Boat::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ChestBoat into crate::entity::Boat") - } -} -impl<'mc> Into> for ChestBoat<'mc> { - fn into(self) -> crate::inventory::InventoryHolder<'mc> { - crate::inventory::InventoryHolder::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ChestBoat into crate::inventory::InventoryHolder") - } -} -impl<'mc> Into> for ChestBoat<'mc> { - fn into(self) -> crate::loot::Lootable<'mc> { - crate::loot::Lootable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ChestBoat into crate::loot::Lootable") - } -} -#[repr(C)] -pub struct Cat<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Cat<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Cat<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Cat from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Cat")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Cat object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Cat<'mc> { - /// Gets the current type of this cat. - pub fn cat_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Cat/Type;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCatType", sig.as_str(), vec![]); + /// Entities can have no more than 1024 tags. + pub fn scoreboard_tags( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getScoreboardTags", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::entity::CatType::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the current type of this cat. - pub fn set_cat_type( + /// Add a tag to this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn add_scoreboard_tag( &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Cat/Type;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setCatType", + "addScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the collar color of this cat - pub fn collar_color(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/DyeColor;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCollarColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::DyeColor::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Set the collar color of this cat - pub fn set_collar_color( + /// Removes a given tag from this entity. + pub fn remove_scoreboard_tag( &self, - color: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/DyeColor;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) - }); + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setCollarColor", + "removeScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Check if this is tamed - /// - /// If something is tamed then a player can not tame it through normal - /// methods, even if it does not belong to anyone in particular. - pub fn is_tamed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isTamed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets if this has been tamed. Not necessary if the method setOwner has - /// been used, as it tames automatically. - /// - /// If something is tamed then a player can not tame it through normal - /// methods, even if it does not belong to anyone in particular. - pub fn set_tamed(&self, tame: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(tame.into()); + /// Returns the reaction of the entity when moved by a piston. + pub fn piston_move_reaction( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setTamed", + "getPistonMoveReaction", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the current owning AnimalTamer - pub fn owner( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/AnimalTamer;"); + /// Get the closest cardinal {@link BlockFace} direction an entity is + /// currently facing. + /// + /// This will not return any non-cardinal directions such as + /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// + /// {@link Hanging} entities will override this call and thus their behavior + /// may be different. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::AnimalTamer::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set this to be owned by given AnimalTamer. - /// - /// If the owner is not null, this will be tamed and will have any current - /// path it is following removed. If the owner is set to null, this will be - /// untamed, and the current owner removed. - pub fn set_owner( + /// Gets the entity's current pose. + /// Note that the pose is only updated at the end of a tick, so may be + /// inconsistent with other methods. eg {@link Player#isSneaking()} being + /// true does not imply the current pose will be {@link Pose#SNEAKING} + pub fn pose(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Pose;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the category of spawn to which this entity belongs. + pub fn spawn_category( &self, - tamer: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/AnimalTamer;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tamer.into().jni_object().clone()) - }); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setOwner", + "getSpawnCategory", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Checks if this entity has been spawned in a world. + /// + /// Entities not spawned in a world will not tick, be sent to players, or be + /// saved to the server files. + pub fn is_in_world(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get this entity as an NBT string. + /// + /// This string should not be relied upon as a serializable value. + pub fn as_string(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Get the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn breed_cause( + /// Crates an {@link EntitySnapshot} representing the current state of this entity. + pub fn create_snapshot( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/UUID;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( + Ok(Some(crate::entity::EntitySnapshot::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Set the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn set_breed_cause( + /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// + /// Note: Players cannot be copied. + pub fn copy( &self, - uuid: impl Into>, + to: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = to { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Lorg/bukkit/entity/Entity;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets a metadata value in the implementing object's metadata store. + pub fn set_metadata( + &self, + metadata_key: impl Into, + new_metadata_value: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/UUID;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) + let sig = String::from("(Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreedCause", + "setMetadata", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get whether or not this entity is in love mode and will produce - /// offspring with another entity in love mode. Will return true if - /// and only if {@link #getLoveModeTicks()} is greater than 0. - pub fn is_love_mode(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the amount of ticks remaining for this entity in love mode. - /// If the entity is not in love mode, 0 will be returned. - pub fn love_mode_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLoveModeTicks", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the amount of ticks for which this entity should be in love mode. - /// Setting the love mode ticks to 600 is the equivalent of a player - /// feeding the entity their breeding item of choice. - pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Returns a list of previously set metadata values from the implementing + /// object's metadata store. + pub fn get_metadata( + &self, + metadata_key: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setLoveModeTicks", + "getMetadata", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::metadata::MetadataValue::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(new_vec) } - /// Check if the provided ItemStack is the correct item used for breeding - /// this entity.. - pub fn is_breed_item( + /// Tests to see whether the implementing object contains the given + /// metadata value in its metadata store. + pub fn has_metadata( &self, - material: impl Into>, + metadata_key: impl Into, ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Lock the age of the animal, setting this will prevent the animal from - /// maturing or getting ready for mating. - pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(lock.into()); + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setAgeLock", + "hasMetadata", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the current agelock. - pub fn age_lock(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Return the ability to breed of the animal. - pub fn can_breed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set breedability of the animal, if the animal is a baby and set to - /// breed it will instantly grow up. - pub fn set_breed(&self, breed: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(breed.into()); + /// Removes the given metadata value from the implementing object's + /// metadata store. + pub fn remove_metadata( + &self, + metadata_key: impl Into, + owning_plugin: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreed", + "removeMetadata", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if this animal is sitting - pub fn is_sitting(&self) -> Result> { - let sig = String::from("()Z"); + /// Sends this sender multiple messages + pub fn send_message( + &self, + sender: impl Into>, + messages: std::option::Option>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/util/UUID;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = messages { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_2); + } + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isSitting", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets if this animal is sitting. Will remove any path that the animal - /// was following beforehand. - pub fn set_sitting(&self, sitting: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(sitting.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSitting", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Cat<'mc> { - fn into(self) -> crate::entity::Tameable<'mc> { - crate::entity::Tameable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Cat into crate::entity::Tameable") - } -} -impl<'mc> Into> for Cat<'mc> { - fn into(self) -> crate::entity::Sittable<'mc> { - crate::entity::Sittable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Cat into crate::entity::Sittable") - } -} -pub enum CatType<'mc> {} -impl<'mc> std::fmt::Display for CatType<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> CatType<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/Cat/Type"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/Cat/Type;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct CatTypeStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for CatType<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for CatType<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate CatType from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Cat/Type")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a CatType object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for CatTypeStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for CatTypeStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate CatTypeStruct from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Cat/Type")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a CatTypeStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> CatTypeStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Cat/Type;"); - let cls = jni.find_class("org/bukkit/entity/Cat/Type"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::CatType::from_raw(&jni, obj) - } - - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + /// Gets the name of this command sender + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct NPC<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for NPC<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for NPC<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate NPC from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/NPC")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a NPC object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } -} - -impl<'mc> NPC<'mc> { - /// Instructs this Mob to set the specified LivingEntity as its target. + /// Gets the custom name on a mob or block. If there is no name this method + /// will return null. /// - /// Hostile creatures may attack their target, and friendly creatures may - /// follow their target. - pub fn set_target( - &self, - target: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTarget", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the current target of this Mob - pub fn target( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTarget", sig.as_str(), vec![]); + /// This value has no effect on players, they will always use their real + /// name. + pub fn custom_name(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCustomName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::LivingEntity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Sets whether this mob is aware of its surroundings. - /// Unaware mobs will still move if pushed, attacked, etc. but will not move - /// or perform any actions on their own. Unaware mobs may also have other - /// unspecified behaviours disabled, such as drowning. - pub fn set_aware(&self, aware: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(aware.into()); + /// Sets a custom name on a mob or block. This name will be used in death + /// messages and can be sent to the client as a nameplate over the mob. + /// + /// Setting the name to null or an empty string will clear it. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn set_custom_name( + &self, + name: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setAware", + "setCustomName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether this mob is aware of its surroundings. - /// Unaware mobs will still move if pushed, attacked, etc. but will not move - /// or perform any actions on their own. Unaware mobs may also have other - /// unspecified behaviours disabled, such as drowning. - pub fn is_aware(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isAware", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the {@link Sound} this mob makes while ambiently existing. This sound - /// may change depending on the current state of the entity, and may also - /// return null under specific conditions. This sound is not constant. - /// For instance, villagers will make different passive noises depending - /// on whether or not they are actively trading with a player, or make no - /// ambient noise while sleeping. - pub fn ambient_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAmbientSound", sig.as_str(), vec![]); + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + pub fn persistent_data_container( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPersistentDataContainer", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -66378,19 +74631,19 @@ impl<'mc> NPC<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for NPC<'mc> { - fn into(self) -> crate::entity::Creature<'mc> { - crate::entity::Creature::from_raw(&self.jni_ref(), self.1) - .expect("Error converting NPC into crate::entity::Creature") +impl<'mc> Into> for Explosive<'mc> { + fn into(self) -> crate::entity::Entity<'mc> { + crate::entity::Entity::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Explosive into crate::entity::Entity") } } #[repr(C)] -pub struct LingeringPotion<'mc>( +pub struct Vehicle<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for LingeringPotion<'mc> { +impl<'mc> JNIRaw<'mc> for Vehicle<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -66398,20 +74651,18 @@ impl<'mc> JNIRaw<'mc> for LingeringPotion<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for LingeringPotion<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Vehicle<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate LingeringPotion from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate Vehicle from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/LingeringPotion")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Vehicle")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a LingeringPotion object, got {}", + "Invalid argument passed. Expected a Vehicle object, got {}", name ) .into()) @@ -66421,1370 +74672,2093 @@ impl<'mc> JNIInstantiatable<'mc> for LingeringPotion<'mc> { } } -impl<'mc> LingeringPotion<'mc> { - /// Returns the effects that are applied by this potion. - pub fn effects( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); +impl<'mc> Vehicle<'mc> { + /// Gets the vehicle's velocity. + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getEffects", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the vehicle's velocity in meters per tick. + pub fn set_velocity( + &self, + vel: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(vel.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVelocity", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Stores the entity's current position in the provided Location object. + /// + /// If the provided Location is null this method does nothing and returns + /// null. + pub fn get_location( + &self, + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLocation", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - Ok(new_vec) + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Gets the ItemStack the thrown projectile will display. - pub fn item(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/inventory/ItemStack;"; + /// Gets the entity's height + pub fn height(&self) -> Result> { + let sig = String::from("()D"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), args); + .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + Ok(res.d()?) + } + /// Gets the entity's width + pub fn width(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the entity's current bounding box. + /// + /// The returned bounding box reflects the entity's current location and + /// size. + pub fn bounding_box( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the display ItemStack for the thrown projectile. - pub fn set_item( + /// Returns true if the entity is supported by a block. This value is a + /// state updated by the server and is not recalculated unless the entity + /// moves. + pub fn is_on_ground(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns true if the entity is in water. + pub fn is_in_water(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the current world this entity resides in + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the entity's rotation. + /// + /// Note that if the entity is affected by AI, it may override this rotation. + pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { + let sig = String::from("(FF)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); + let val_2 = jni::objects::JValueGen::Float(pitch); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRotation", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Teleports this entity to the given location. If this entity is riding a + /// vehicle, it will be dismounted prior to teleportation. + pub fn teleport( &self, - item: impl Into>, - ) -> Result<(), Box> { + location: impl Into>, + cause: std::option::Option< + impl Into>, + >, + ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; + sig += "Lorg/bukkit/Location;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(location.into().jni_object().clone()) }); args.push(val_1); - sig += ")V"; + if let Some(a) = cause { + sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "setItem", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "teleport", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + /// Returns a list of entities within a bounding box centered around this + /// entity + pub fn get_nearby_entities( + &self, + x: f64, + y: f64, + z: f64, + ) -> Result>, Box> { + let sig = String::from("(DDD)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Double(x); + let val_2 = jni::objects::JValueGen::Double(y); + let val_3 = jni::objects::JValueGen::Double(z); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNearbyEntities", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } -} -impl<'mc> Into> for LingeringPotion<'mc> { - fn into(self) -> crate::entity::ThrownPotion<'mc> { - crate::entity::ThrownPotion::from_raw(&self.jni_ref(), self.1) - .expect("Error converting LingeringPotion into crate::entity::ThrownPotion") + /// Returns a unique id for this entity + pub fn entity_id(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} -#[repr(C)] -pub struct Spider<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Spider<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Returns the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Returns the entity's maximum fire ticks. + pub fn max_fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} -impl<'mc> JNIInstantiatable<'mc> for Spider<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Spider from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Spider")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Spider object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Sets the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFireTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> Spider<'mc> { - /// Gets the height of the living entity's eyes above its Location. - pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { - let sig = String::from("(Z)D"); - let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); + /// Sets if the entity has visual fire (it will always appear to be on fire). + pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getEyeHeight", + "setVisualFire", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the entity has visual fire (it will always appear to be on fire). + pub fn is_visual_fire(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Get a Location detailing the current eye position of the living entity. - pub fn eye_location(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); + /// Returns the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { + Ok(res.i()?) + } + /// Returns the entity's maximum freeze ticks (amount of ticks before it will + /// be fully frozen) + pub fn max_freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaxFreezeTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFreezeTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the entity is fully frozen (it has been in powdered snow for max + /// freeze ticks). + pub fn is_frozen(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Mark the entity's removal. + pub fn remove(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns true if this entity has been marked for removal. + pub fn is_dead(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns false if the entity has died, been despawned for some other + /// reason, or has not been added to the world. + pub fn is_valid(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the {@link Server} that contains this Entity + pub fn server(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Server;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Server::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets all blocks along the living entity's line of sight. + /// Returns true if the entity gets persisted. /// - /// This list contains all blocks from the living entity's eye position to - /// target inclusive. This method considers all blocks as 1x1x1 in size. - pub fn get_line_of_sight( + /// By default all entities are persistent. An entity will also not get + /// persisted, if it is riding an entity that is not persistent. + /// + /// The persistent flag on players controls whether or not to save their + /// playerdata file when they quit. If a player is directly or indirectly + /// riding a non-persistent entity, the vehicle at the root and all its + /// passengers won't get persisted. + /// + /// This should not be confused with + /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls + /// despawning of living entities. + pub fn is_persistent(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether or not the entity gets persisted. + pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(persistent.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPersistent", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. + pub fn passenger( &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { - let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + #[deprecated] + /// Set the passenger of a vehicle. + pub fn set_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "getLineOfSight", + "setPassenger", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets a list of passengers of this vehicle. + /// + /// The returned list will not be directly linked to the entity's current + /// passengers, and no guarantees are made as to its mutability. + pub fn passengers( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); } Ok(new_vec) } - /// Gets the block that the living entity has targeted. - /// - /// This method considers all blocks as 1x1x1 in size. To take exact block - /// collision shapes into account, see {@link #getTargetBlockExact(int, - /// FluidCollisionMode)}. - pub fn get_target_block( + /// Add a passenger to the vehicle. + pub fn add_passenger( &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result, Box> { - let sig = String::from("(Ljava/util/Set;I)Lorg/bukkit/block/Block;"); + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "getTargetBlock", + "addPassenger", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Gets the last two blocks along the living entity's line of sight. - /// - /// The target block will be the last block in the list. This method - /// considers all blocks as 1x1x1 in size. - pub fn get_last_two_target_blocks( + /// Remove a passenger from the vehicle. + pub fn remove_passenger( &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { - let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "getLastTwoTargetBlocks", + "removePassenger", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(res.z()?) } - /// Gets the block that the living entity has targeted. - /// - /// This takes the blocks' precise collision shapes into account. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn get_target_block_exact( + /// Check if a vehicle has passengers. + pub fn is_empty(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Eject any passenger. + pub fn eject(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the distance this entity has fallen + pub fn fall_distance(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the fall distance for this entity + pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(distance); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFallDistance", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Record the last {@link EntityDamageEvent} inflicted on this entity + pub fn set_last_damage_cause( &self, - max_distance: i32, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(max_distance); - args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/block/Block;"; + event: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(event.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getTargetBlockExact", + "setLastDamageCause", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. + /// This event may have been cancelled. + pub fn last_damage_cause( + &self, + ) -> Result>, Box> + { + let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLastDamageCause", + sig.as_str(), + vec![], ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::block::Block::from_raw( + Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Performs a ray trace that provides information on the targeted block. - /// - /// This takes the blocks' precise collision shapes into account. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn ray_trace_blocks( + /// Returns a unique and persistent id for this entity + pub fn unique_id( &self, - max_distance: f64, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(max_distance); - args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/util/RayTraceResult;"; + ) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::util::RayTraceResult::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the amount of air that the living entity has remaining, in - /// ticks. - pub fn remaining_air(&self) -> Result> { + /// Gets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. + pub fn ticks_lived(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the amount of air that the living entity has remaining, in ticks. - pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { + /// Sets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. May not be less than one + /// tick. + pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + let val_1 = jni::objects::JValueGen::Int(value); let res = self.jni_ref().call_method( &self.jni_object(), - "setRemainingAir", + "setTicksLived", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the maximum amount of air the living entity can have, in ticks. - pub fn maximum_air(&self) -> Result> { - let sig = String::from("()I"); + /// Performs the specified {@link EntityEffect} for this entity. + /// + /// This will be viewable to all players near the entity. + /// + /// If the effect is not applicable to this class of entity, it will not play. + pub fn play_effect( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "playEffect", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the type of the entity. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes while swimming. + pub fn swim_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the maximum amount of air the living entity can have, in ticks. - pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Get the {@link Sound} this entity makes when splashing in water. For most + /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_splash_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaximumAir", + "getSwimSplashSound", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the item that the player is using (eating food, drawing back a bow, - /// blocking, etc.) - pub fn item_in_use( + /// Get the {@link Sound} this entity makes when splashing in water at high + /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_high_speed_splash_sound( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSwimHighSpeedSplashSound", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns whether this entity is inside a vehicle. + pub fn is_inside_vehicle(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Leave the current vehicle. If the entity is currently in a vehicle (and + /// is removed from it), true will be returned, otherwise false will be + /// returned. + pub fn leave_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the vehicle that this entity is inside. If there is no vehicle, + /// null will be returned. + pub fn vehicle( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::ItemStack::from_raw( + Ok(Some(crate::entity::Entity::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Gets the number of ticks remaining for the current item's usage. - pub fn item_in_use_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Sets whether or not to display the mob's custom name client side. The + /// name will be displayed above the mob similarly to a player. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getItemInUseTicks", + "setCustomNameVisible", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether or not the mob's custom name is displayed client side. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn is_custom_name_visible(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isCustomNameVisible", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the number of ticks that remain for the current item's usage. - /// Applies to items that take time to use, like eating food, drawing a bow, - /// or throwing a trident. - pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(visible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemInUseTicks", + "setVisibleByDefault", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the time in ticks until the next arrow leaves the entity's body. - pub fn arrow_cooldown(&self) -> Result> { - let sig = String::from("()I"); + /// Gets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn is_visible_by_default(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getArrowCooldown", + "isVisibleByDefault", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the time in ticks until the next arrow leaves the entity's body. - pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Get all players that are currently tracking this entity. + /// + /// 'Tracking' means that this entity has been sent to the player and that + /// they are receiving updates on its state. Note that the client's {@code + /// 'Entity Distance'} setting does not affect the range at which entities + /// are tracked. + pub fn tracked_by( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets whether the entity has a team colored (default: white) glow. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setArrowCooldown", + "setGlowing", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the amount of arrows in an entity's body. - pub fn arrows_in_body(&self) -> Result> { - let sig = String::from("()I"); + /// Gets whether the entity is glowing or not. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn is_glowing(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the entity is invulnerable or not. + /// + /// When an entity is invulnerable it can only be damaged by players in + /// creative mode. + pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setInvulnerable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether the entity is invulnerable or not. + pub fn is_invulnerable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets whether the entity is silent or not. + pub fn is_silent(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the entity is silent or not. + /// + /// When an entity is silent it will not produce any sound. + pub fn set_silent(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSilent", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns whether gravity applies to this entity. + pub fn has_gravity(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the amount of arrows in the entity's body. - pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(count); + /// Sets whether gravity applies to this entity. + pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gravity.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setArrowsInBody", + "setGravity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's current maximum no damage ticks. - /// - /// This is the maximum duration in which the living entity will not take - /// damage. - pub fn maximum_no_damage_ticks(&self) -> Result> { + /// Gets the period of time (in ticks) before this entity can use a portal. + pub fn portal_cooldown(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getMaximumNoDamageTicks", + "getPortalCooldown", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the living entity's current maximum no damage ticks. - pub fn set_maximum_no_damage_ticks( - &self, - ticks: i32, - ) -> Result<(), Box> { + /// Sets the period of time (in ticks) before this entity can use a portal. + pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + let val_1 = jni::objects::JValueGen::Int(cooldown); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaximumNoDamageTicks", + "setPortalCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's last damage taken in the current no damage - /// ticks time. + /// Returns a set of tags for this entity. /// - /// Only damage higher than this amount will further damage the living - /// entity. - pub fn last_damage(&self) -> Result> { - let sig = String::from("()D"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Sets the damage dealt within the current no damage ticks time period. - pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(damage); + /// Entities can have no more than 1024 tags. + pub fn scoreboard_tags( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDamage", + "getScoreboardTags", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the living entity's current no damage ticks. - pub fn no_damage_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Add a tag to this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn add_scoreboard_tag( + &self, + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "getNoDamageTicks", + "addScoreboardTag", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the living entity's current no damage ticks. - pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Removes a given tag from this entity. + pub fn remove_scoreboard_tag( + &self, + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setNoDamageTicks", + "removeScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Get the ticks that this entity has performed no action. - /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn no_action_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Returns the reaction of the entity when moved by a piston. + pub fn piston_move_reaction( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getNoActionTicks", + "getPistonMoveReaction", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the ticks that this entity has performed no action. + /// Get the closest cardinal {@link BlockFace} direction an entity is + /// currently facing. /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// This will not return any non-cardinal directions such as + /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// + /// {@link Hanging} entities will override this call and thus their behavior + /// may be different. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the entity's current pose. + /// Note that the pose is only updated at the end of a tick, so may be + /// inconsistent with other methods. eg {@link Player#isSneaking()} being + /// true does not imply the current pose will be {@link Pose#SNEAKING} + pub fn pose(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Pose;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the category of spawn to which this entity belongs. + pub fn spawn_category( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setNoActionTicks", + "getSpawnCategory", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the player identified as the killer of the living entity. + /// Checks if this entity has been spawned in a world. /// - /// May be null. - pub fn killer(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Player;"); + /// Entities not spawned in a world will not tick, be sent to players, or be + /// saved to the server files. + pub fn is_in_world(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get this entity as an NBT string. + /// + /// This string should not be relied upon as a serializable value. + pub fn as_string(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Player::from_raw( + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Crates an {@link EntitySnapshot} representing the current state of this entity. + pub fn create_snapshot( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntitySnapshot::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - #[deprecated] - /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. - pub fn add_potion_effect( + /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// + /// Note: Players cannot be copied. + pub fn copy( &self, - effect: impl Into>, - force: std::option::Option, - ) -> Result> { + to: std::option::Option>>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/potion/PotionEffect;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(effect.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = force { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); + if let Some(a) = to { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); } - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); + sig += ")Lorg/bukkit/entity/Entity;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns whether the living entity already has an existing effect of - /// the given {@link PotionEffectType} applied to it. - pub fn has_potion_effect( + /// Sets a metadata value in the implementing object's metadata store. + pub fn set_metadata( &self, - val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + metadata_key: impl Into, + new_metadata_value: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasPotionEffect", + "setMetadata", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns a list of previously set metadata values from the implementing + /// object's metadata store. + pub fn get_metadata( + &self, + metadata_key: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMetadata", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::metadata::MetadataValue::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(new_vec) + } + /// Tests to see whether the implementing object contains the given + /// metadata value in its metadata store. + pub fn has_metadata( + &self, + metadata_key: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasMetadata", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns the active {@link PotionEffect} of the specified type. - /// - /// If the effect is not present on the entity then null will be returned. - pub fn get_potion_effect( + /// Removes the given metadata value from the implementing object's + /// metadata store. + pub fn remove_metadata( &self, - val_type: impl Into>, - ) -> Result>, Box> { - let sig = - String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + metadata_key: impl Into, + owning_plugin: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getPotionEffect", + "removeMetadata", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sends this sender multiple messages + pub fn send_message( + &self, + sender: impl Into>, + messages: std::option::Option>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/util/UUID;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = messages { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_2); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the name of this command sender + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gets the custom name on a mob or block. If there is no name this method + /// will return null. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn custom_name(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCustomName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::potion::PotionEffect::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Removes any effects present of the given {@link PotionEffectType}. - pub fn remove_potion_effect( + /// Sets a custom name on a mob or block. This name will be used in death + /// messages and can be sent to the client as a nameplate over the mob. + /// + /// Setting the name to null or an empty string will clear it. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn set_custom_name( &self, - val_type: impl Into>, + name: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "removePotionEffect", + "setCustomName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns all currently active {@link PotionEffect}s on the living - /// entity. - pub fn active_potion_effects( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + pub fn persistent_data_container( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPersistentDataContainer", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Vehicle<'mc> { + fn into(self) -> crate::entity::Entity<'mc> { + crate::entity::Entity::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Vehicle into crate::entity::Entity") + } +} +#[repr(C)] +pub struct GlowSquid<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for GlowSquid<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for GlowSquid<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate GlowSquid from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/GlowSquid")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a GlowSquid object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> GlowSquid<'mc> { + /// Get the number of dark ticks remaining for this squid. + /// Bravo Six will go dark for 100 ticks (5 seconds) if damaged. + pub fn dark_ticks_remaining(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getActivePotionEffects", + "getDarkTicksRemaining", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(res.i()?) } - /// Checks whether the living entity has block line of sight to another. - /// - /// This uses the same algorithm that hostile mobs use to find the closest - /// player. - pub fn has_line_of_sight( + /// Sets the number of dark ticks remaining for this squid. + /// Bravo Six will go dark for 100 ticks (5 seconds) if damaged. + pub fn set_dark_ticks_remaining( &self, - other: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) - }); + dark_ticks_remaining: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(dark_ticks_remaining); let res = self.jni_ref().call_method( &self.jni_object(), - "hasLineOfSight", + "setDarkTicksRemaining", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns if the living entity despawns when away from players or not. + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for GlowSquid<'mc> { + fn into(self) -> crate::entity::Squid<'mc> { + crate::entity::Squid::from_raw(&self.jni_ref(), self.1) + .expect("Error converting GlowSquid into crate::entity::Squid") + } +} +#[repr(C)] +pub struct SkeletonHorse<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for SkeletonHorse<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for SkeletonHorse<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate SkeletonHorse from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/SkeletonHorse")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a SkeletonHorse object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> SkeletonHorse<'mc> { + /// Returns whether this skeleton horse is trapped. /// - /// By default, animals are not removed while other mobs are. - pub fn remove_when_far_away(&self) -> Result> { + /// When a horse is trapped and a player comes within 10 blocks of a trapped + /// horse, lightning will strike the horse. When struck, the skeleton trap + /// will activate, turning the horse into a skeleton horseman as well as + /// spawning three additional horsemen nearby. + pub fn is_trapped(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getRemoveWhenFarAway", - sig.as_str(), - vec![], - ); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isTrapped", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not the living entity despawns when away from players - /// or not. - pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { + /// Sets if this skeleton horse is trapped. + pub fn set_trapped(&self, trapped: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(remove.into()); + let val_1 = jni::objects::JValueGen::Bool(trapped.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setRemoveWhenFarAway", + "setTrapped", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the inventory with the equipment worn by the living entity. - pub fn equipment( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); + /// Returns the horse's current trap time in ticks. + /// Trap time is incremented every tick when {@link #isTrapped()} is true. + /// The horse automatically despawns when it reaches 18000 ticks. + pub fn trap_time(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTrapTime", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::EntityEquipment::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - /// Sets whether or not the living entity can pick up items. - pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(pickup.into()); + /// Sets the trap time for the horse. + /// Values greater than 18000 will cause the horse to despawn on the next + /// tick. + pub fn set_trap_time(&self, trap_time: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(trap_time); let res = self.jni_ref().call_method( &self.jni_object(), - "setCanPickupItems", + "setTrapTime", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the living entity can pick up items. - pub fn can_pickup_items(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCanPickupItems", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns whether the entity is currently leashed. - pub fn is_leashed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the entity that is currently leading this entity. - pub fn leash_holder(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + #[deprecated] + /// Gets the horse's variant.A horse's variant defines its physical appearance and capabilities. Whether a horse is a regular horse, donkey, mule, or other kind of horse is determined using the variant. + pub fn variant(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Horse/Variant;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + crate::entity::HorseVariant::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the leash on this entity to be held by the supplied entity. - /// - /// This method has no effect on EnderDragons, Withers, Players, or Bats. - /// Non-living entities excluding leashes will not persist as leash - /// holders. - pub fn set_leash_holder( + #[deprecated] + + pub fn set_variant( &self, - holder: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + variant: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Horse/Variant;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(holder.into().jni_object().clone()) + jni::objects::JObject::from_raw(variant.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLeashHolder", + "setVariant", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Checks to see if an entity is gliding, such as using an Elytra. - pub fn is_gliding(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); + /// Gets the domestication level of this horse. + /// + /// A higher domestication level indicates that the horse is closer to + /// becoming tame. As the domestication level gets closer to the max + /// domestication level, the chance of the horse becoming tame increases. + pub fn domestication(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDomestication", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Makes entity start or stop gliding. This will work even if an Elytra - /// is not equipped, but will be reverted by the server immediately after - /// unless an event-cancelling mechanism is put in place. - pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gliding.into()); + /// Sets the domestication level of this horse. + /// + /// Setting the domestication level to a high value will increase the + /// horse's chances of becoming tame. + /// + /// Domestication level must be greater than zero and no greater than + /// the max domestication level of the horse, determined with + /// {@link #getMaxDomestication()} + pub fn set_domestication(&self, level: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(level); let res = self.jni_ref().call_method( &self.jni_object(), - "setGliding", + "setDomestication", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks to see if an entity is swimming. - pub fn is_swimming(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); + /// Gets the maximum domestication level of this horse. + /// + /// The higher this level is, the longer it will likely take + /// for the horse to be tamed. + pub fn max_domestication(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaxDomestication", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Makes entity start or stop swimming. - /// This may have unexpected results if the entity is not in water. - pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(swimming.into()); + /// Sets the maximum domestication level of this horse. + /// + /// Setting a higher max domestication will increase the amount of + /// domesticating (feeding, riding, etc.) necessary in order to tame it, + /// while setting a lower max value will have the opposite effect. + /// + /// Maximum domestication must be greater than zero. + pub fn set_max_domestication(&self, level: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(level); let res = self.jni_ref().call_method( &self.jni_object(), - "setSwimming", + "setMaxDomestication", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks to see if an entity is currently using the Riptide enchantment. - pub fn is_riptiding(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns whether this entity is slumbering. - pub fn is_sleeping(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets if the entity is climbing. - pub fn is_climbing(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the jump strength of this horse. + /// + /// Jump strength defines how high the horse can jump. A higher jump strength + /// increases how high a jump will go. + pub fn jump_strength(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getJumpStrength", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Sets whether an entity will have AI. - /// The entity will be completely unable to move if it has no AI. - pub fn set_ai(&self, ai: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(ai.into()); + /// Sets the jump strength of this horse. + /// + /// A higher jump strength increases how high a jump will go. + /// Setting a jump strength to 0 will result in no jump. + /// You cannot set a jump strength to a value below 0 or + /// above 2. + pub fn set_jump_strength(&self, strength: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(strength); let res = self.jni_ref().call_method( &self.jni_object(), - "setAI", + "setJumpStrength", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks whether an entity has AI. - /// The entity will be completely unable to move if it has no AI. - pub fn has_ai(&self) -> Result> { + /// Gets whether the horse is currently grazing hay. + pub fn is_eating_haystack(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isEatingHaystack", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Makes this entity attack the given entity with a melee attack. - /// Attack damage is calculated by the server from the attributes and - /// equipment of this mob, and knockback is applied to {@code target} as - /// appropriate. - pub fn attack( + /// Sets whether the horse is grazing hay. + pub fn set_eating_haystack( &self, - target: impl Into>, + eating_haystack: bool, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) - }); + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(eating_haystack.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "attack", + "setEatingHaystack", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Makes this entity swing their main hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their main hand. - pub fn swing_main_hand(&self) -> Result<(), Box> { - let sig = String::from("()V"); + + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/AbstractHorseInventory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::AbstractHorseInventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Makes this entity swing their off hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their off hand. - pub fn swing_off_hand(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Gets the vehicle's velocity. + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Makes this entity flash red as if they were damaged. - pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); - let res = self.jni_ref().call_method( - &self.jni_object(), - "playHurtAnimation", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set if this entity will be subject to collisions with other entities. - /// - /// Exemptions to this rule can be managed with - /// {@link #getCollidableExemptions()} - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not working for player collisions. This - /// method should therefore only be used to set the collision status of - /// non-player entities. - /// - /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in - /// combination with a {@link Scoreboard} and a {@link Team}. - pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(collidable.into()); + /// Sets the vehicle's velocity in meters per tick. + pub fn set_velocity( + &self, + vel: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(vel.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCollidable", + "setVelocity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if this entity is subject to collisions with other entities. - /// - /// Some entities might be exempted from the collidable rule of this entity. - /// Use {@link #getCollidableExemptions()} to get these. - /// - /// Please note that this method returns only the custom collidable state, - /// not whether the entity is non-collidable for other reasons such as being - /// dead. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not being accurate for player collisions. - /// This method should therefore only be used to check the collision status - /// of non-player entities. + /// Check if this is tamed /// - /// To check the collision behavior for a player, use - /// {@link Team.Option#COLLISION_RULE} in combination with a - /// {@link Scoreboard} and a {@link Team}. - pub fn is_collidable(&self) -> Result> { + /// If something is tamed then a player can not tame it through normal + /// methods, even if it does not belong to anyone in particular. + pub fn is_tamed(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isTamed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets a mutable set of UUIDs of the entities which are exempt from the - /// entity's collidable rule and which's collision with this entity will - /// behave the opposite of it. - /// - /// This set can be modified to add or remove exemptions. - /// - /// For example if collidable is true and an entity is in the exemptions set - /// then it will not collide with it. Similarly if collidable is false and an - /// entity is in this set then it will still collide with it. - /// - /// Note these exemptions are not (currently) persistent. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in those exemptions not being accurate for player - /// collisions. This method should therefore only be used to exempt - /// non-player entities. - /// - /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} - /// in combination with a {@link Scoreboard} and a {@link Team}. - pub fn collidable_exemptions( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCollidableExemptions", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns the value of the memory specified. + /// Sets if this has been tamed. Not necessary if the method setOwner has + /// been used, as it tames automatically. /// - /// Note that the value is null when the specific entity does not have that - /// value by default. - pub fn get_memory( - &self, - memory_key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) - }); + /// If something is tamed then a player can not tame it through normal + /// methods, even if it does not belong to anyone in particular. + pub fn set_tamed(&self, tame: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(tame.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getMemory", + "setTamed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the current owning AnimalTamer + pub fn owner( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/AnimalTamer;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(res.l()?)) + Ok(Some(crate::entity::AnimalTamer::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the value of the memory specified. + /// Set this to be owned by given AnimalTamer. /// - /// Note that the value will not be persisted when the specific entity does - /// not have that value by default. - pub fn set_memory( + /// If the owner is not null, this will be tamed and will have any current + /// path it is following removed. If the owner is set to null, this will be + /// untamed, and the current owner removed. + pub fn set_owner( &self, - memory_key: impl Into>, - memory_value: jni::objects::JObject<'mc>, + tamer: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); + let sig = String::from("(Lorg/bukkit/entity/AnimalTamer;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + jni::objects::JObject::from_raw(tamer.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Object(memory_value); let res = self.jni_ref().call_method( &self.jni_object(), - "setMemory", + "setOwner", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the {@link Sound} this entity will make when damaged. - pub fn hurt_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for SkeletonHorse<'mc> { + fn into(self) -> crate::entity::AbstractHorse<'mc> { + crate::entity::AbstractHorse::from_raw(&self.jni_ref(), self.1) + .expect("Error converting SkeletonHorse into crate::entity::AbstractHorse") + } +} +#[repr(C)] +pub struct FishHook<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for FishHook<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for FishHook<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate FishHook from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/FishHook")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a FishHook object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) } - /// Get the {@link Sound} this entity will make on death. - pub fn death_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); +} + +impl<'mc> FishHook<'mc> { + /// Get the minimum number of ticks one has to wait for a fish appearing. + /// + /// The default is 100 ticks (5 seconds). + /// + /// Note that this is before applying lure. + pub fn min_wait_time(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMinWaitTime", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.i()?) } - /// Get the {@link Sound} this entity will make when falling from the given - /// height (in blocks). The sound will often differ between either a small - /// or a big fall damage sound if the height exceeds 4 blocks. - pub fn get_fall_damage_sound( - &self, - fall_height: i32, - ) -> Result, Box> { - let sig = String::from("(I)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Int(fall_height); + /// Set the minimum number of ticks one has to wait for a fish appearing. + /// + /// The default is 100 ticks (5 seconds). + /// + /// Note that this is before applying lure. + pub fn set_min_wait_time(&self, min_wait_time: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(min_wait_time); let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSound", + "setMinWaitTime", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the maximum number of ticks one has to wait for a fish appearing. + /// + /// The default is 600 ticks (30 seconds). + /// + /// Note that this is before applying lure. + pub fn max_wait_time(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxWaitTime", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Get the {@link Sound} this entity will make when falling from a small - /// height. - pub fn fall_damage_sound_small(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Set the maximum number of ticks one has to wait for a fish appearing. + /// + /// The default is 600 ticks (30 seconds). + /// + /// Note that this is before applying lure. + pub fn set_max_wait_time(&self, max_wait_time: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(max_wait_time); let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSoundSmall", + "setMaxWaitTime", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the {@link Sound} this entity will make when falling from a large - /// height. - pub fn fall_damage_sound_big(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Set both the minimum (default 100) and maximum (default 600) amount + /// of ticks one has to wait for a fish appearing. + pub fn set_wait_time(&self, min: i32, max: i32) -> Result<(), Box> { + let sig = String::from("(II)V"); + let val_1 = jni::objects::JValueGen::Int(min); + let val_2 = jni::objects::JValueGen::Int(max); let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSoundBig", + "setWaitTime", sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the minimum number of ticks one has to wait for a fish to bite + /// after appearing. + /// + /// The default is 20 ticks (1 second). + /// + /// Lure does not affect this value. + /// This will also effect the radius (0.1 * lureTime) of where + /// the fish will appear. + pub fn min_lure_time(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMinLureTime", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Get the {@link Sound} this entity will make when drinking the given - /// {@link ItemStack}. - pub fn get_drinking_sound( - &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) - }); + /// Set the minimum number of ticks one has to wait for a fish to bite + /// after appearing. + /// + /// The default is 20 ticks (1 second). + /// + /// Lure does not affect this value. + /// This will also effect the radius (0.1 * lureTime) of where + /// the fish will appear. + pub fn set_min_lure_time(&self, min_lure_time: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(min_lure_time); let res = self.jni_ref().call_method( &self.jni_object(), - "getDrinkingSound", + "setMinLureTime", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the maximum number of ticks one has to wait for a fish to bite + /// after appearing. + /// + /// The default is 80 ticks (4 second). + /// + /// Lure does not affect this value. + /// This will also effect the radius (0.1 * lureTime) of where + /// the fish will appear. + pub fn max_lure_time(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxLureTime", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Get the {@link Sound} this entity will make when eating the given - /// {@link ItemStack}. - pub fn get_eating_sound( - &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) - }); + /// Set the maximum number of ticks one has to wait for a fish to bite + /// after appearing. + /// + /// The default is 80 ticks (4 second). + /// + /// Lure does not affect this value. + /// This will also effect the radius (0.1 * lureTime) of where + /// the fish will appear. + pub fn set_max_lure_time(&self, max_lure_time: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(max_lure_time); let res = self.jni_ref().call_method( &self.jni_object(), - "getEatingSound", + "setMaxLureTime", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns true if this entity can breathe underwater and will not take - /// suffocation damage when its air supply reaches zero. - pub fn can_breathe_underwater(&self) -> Result> { - let sig = String::from("()Z"); + /// Set both the minimum (default 20) and maximum (default 80) amount + /// of ticks one has to wait for a fish to bite after appearing. + pub fn set_lure_time(&self, min: i32, max: i32) -> Result<(), Box> { + let sig = String::from("(II)V"); + let val_1 = jni::objects::JValueGen::Int(min); + let val_2 = jni::objects::JValueGen::Int(max); let res = self.jni_ref().call_method( &self.jni_object(), - "canBreatheUnderwater", + "setLureTime", sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - #[deprecated] - /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. - pub fn category( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); + /// Get the minimum angle (in degrees, 0 being positive Z 90 being negative + /// X) of where a fish will appear after the wait time. + /// + /// The default is 0 degrees. + pub fn min_lure_angle(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMinLureAngle", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.f()?) } - /// Sets whether the entity is invisible or not. - pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(invisible.into()); + /// Set the minimum angle (in degrees, 0 being positive Z 90 being negative + /// X) of where a fish will appear after the wait time. + /// + /// The default is 0 degrees. + pub fn set_min_lure_angle( + &self, + min_lure_angle: f32, + ) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(min_lure_angle); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvisible", + "setMinLureAngle", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invisible or not. - pub fn is_invisible(&self) -> Result> { - let sig = String::from("()Z"); + /// Get the maximum angle (in degrees, 0 being positive Z 90 being negative + /// X) of where a fish will appear after the wait time. + /// + /// The default is 360 degrees. + pub fn max_lure_angle(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxLureAngle", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.f()?) } - /// Gets the specified attribute instance from the object. This instance will - /// be backed directly to the object and any changes will be visible at once. - pub fn get_attribute( + /// Set the maximum angle (in degrees, 0 being positive Z 90 being negative + /// X) of where a fish will appear after the wait time. + /// + /// The default is 360 degrees. + pub fn set_max_lure_angle( &self, - attribute: impl Into>, - ) -> Result>, Box> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); + max_lure_angle: f32, + ) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(max_lure_angle); let res = self.jni_ref().call_method( &self.jni_object(), - "getAttribute", + "setMaxLureAngle", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::attribute::AttributeInstance::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Deals the given amount of damage to this entity from a specified - /// {@link DamageSource}. - pub fn damage( - &self, - amount: f64, - damage_source: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(amount); - args.push(val_1); - if let Some(a) = damage_source { - sig += "Lorg/bukkit/damage/DamageSource;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "damage", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. - pub fn health(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is - /// dead. - pub fn set_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); + /// Set both the minimum (default 0) and maximum (default 360) angle of where + /// a fish will appear after the wait time. + /// 0 degrees is positive Z, 90 degrees is negative X. + pub fn set_lure_angle(&self, min: f32, max: f32) -> Result<(), Box> { + let sig = String::from("(FF)V"); + let val_1 = jni::objects::JValueGen::Float(min); + let val_2 = jni::objects::JValueGen::Float(max); let res = self.jni_ref().call_method( &self.jni_object(), - "setHealth", + "setLureAngle", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the entity's absorption amount. - pub fn absorption_amount(&self) -> Result> { - let sig = String::from("()D"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAbsorptionAmount", - sig.as_str(), - vec![], - ); + /// Get whether the lure enchantment should be applied to reduce the wait + /// time. + /// + /// The default is true. + /// + /// Lure reduces the wait time by 100 ticks (5 seconds) for each level of the + /// enchantment. + pub fn apply_lure(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getApplyLure", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Sets the entity's absorption amount. + /// Set whether the lure enchantment should be applied to reduce the wait + /// time. /// - /// Note: The amount is capped to the value of - /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on - /// that attribute is currently unspecified and subject to change. - pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(amount); + /// The default is true. + /// + /// Lure reduces the wait time by 100 ticks (5 seconds) for each level of the + /// enchantment. + pub fn set_apply_lure(&self, apply_lure: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(apply_lure.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setAbsorptionAmount", + "setApplyLure", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -67792,267 +76766,222 @@ impl<'mc> Spider<'mc> { Ok(()) } #[deprecated] - /// Gets the maximum health this entity has. - pub fn max_health(&self) -> Result> { + /// Gets the chance of a fish biting.0.0 = No Chance. + /// + /// 1.0 = Instant catch. + pub fn bite_chance(&self) -> Result> { let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBiteChance", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.d()?) } #[deprecated] - /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. - pub fn set_max_health(&self, health: f64) -> Result<(), Box> { + /// Sets the chance of a fish biting.0.0 = No Chance. + /// + /// 1.0 = Instant catch. + pub fn set_bite_chance(&self, chance: f64) -> Result<(), Box> { let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); + let val_1 = jni::objects::JValueGen::Double(chance); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxHealth", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Resets the max health to the original amount. - pub fn reset_max_health(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); + "setBiteChance", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Launches a {@link Projectile} from the ProjectileSource with an - /// initial velocity. - pub fn launch_projectile( - &self, - projectile: jni::objects::JClass<'mc>, - velocity: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/Class;"; - let val_1 = jni::objects::JValueGen::Object(projectile.into()); - args.push(val_1); - if let Some(a) = velocity { - sig += "Lorg/bukkit/util/Vector;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")LT;"; + /// Check whether or not this fish hook is in open water. + /// + /// Open water is defined by a 5x4x5 area of water, air and lily pads. If in + /// open water, treasure items may be caught. + pub fn is_in_open_water(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); + .call_method(&self.jni_object(), "isInOpenWater", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Spider<'mc> { - fn into(self) -> crate::entity::Monster<'mc> { - crate::entity::Monster::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Spider into crate::entity::Monster") - } -} -#[repr(C)] -pub struct Item<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Item<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Item<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Item from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Item")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Item object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + Ok(res.z()?) } -} - -impl<'mc> Item<'mc> { - /// Gets the item stack associated with this item drop. - pub fn item_stack( + /// Get the entity hooked by this fish hook. + pub fn hooked_entity( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemStack", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getHookedEntity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the item stack associated with this item drop. - pub fn set_item_stack( + /// Set the entity hooked by this fish hook. + pub fn set_hooked_entity( &self, - stack: impl Into>, + entity: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(stack.into().jni_object().clone()) + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemStack", + "setHookedEntity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the delay before this Item is available to be picked up by players - pub fn pickup_delay(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPickupDelay", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the delay before this Item is available to be picked up by players - pub fn set_pickup_delay(&self, delay: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(delay); + /// Pull the hooked entity to the caster of this fish hook. If no entity is + /// hooked, this method has no effect. + pub fn pull_hooked_entity(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "setPickupDelay", + "pullHookedEntity", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Sets if this Item should live forever - pub fn set_unlimited_lifetime( + /// Whether or not wait and lure time will be impacted by direct sky access. + /// True by default, causes a 50% time increase on average. + pub fn is_sky_influenced(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isSkyInfluenced", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set whether or not wait and lure time will be impacted by direct sky + /// access. + /// True by default, causes a 50% time increase on average. + pub fn set_sky_influenced( &self, - unlimited: bool, + sky_influenced: bool, ) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(unlimited.into()); + let val_1 = jni::objects::JValueGen::Bool(sky_influenced.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setUnlimitedLifetime", + "setSkyInfluenced", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if this Item lives forever - pub fn is_unlimited_lifetime(&self) -> Result> { + /// Whether or not wait and lure time will be impacted by rain. + /// True by default, causes a 25% time decrease on average. + pub fn is_rain_influenced(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "isUnlimitedLifetime", + "isRainInfluenced", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the owner of this item. - /// Other entities will not be able to pickup this item when an owner is set. - pub fn set_owner( + /// Set whether or not wait and lure time will be impacted by rain. + /// True by default, causes a 25% time decrease on average. + pub fn set_rain_influenced( &self, - owner: impl Into>, + rain_influenced: bool, ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/UUID;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owner.into().jni_object().clone()) - }); + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(rain_influenced.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setOwner", + "setRainInfluenced", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the owner of this item. - pub fn owner( + /// Get the current state of this fish hook. + pub fn state( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/UUID;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/FishHook/HookState;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getState", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::FishHookHookState::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Retrieve the shooter of this projectile. + pub fn shooter( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/projectiles/ProjectileSource;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getShooter", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( + Ok(Some(crate::projectiles::ProjectileSource::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Set the thrower of this item. - /// The thrower is the entity which dropped the item. This affects the - /// trigger criteria for item pickups, for things such as advancements. - pub fn set_thrower( + /// Set the shooter of this projectile. + pub fn set_shooter( &self, - uuid: impl Into>, + source: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/UUID;)V"); + let sig = String::from("(Lorg/bukkit/projectiles/ProjectileSource;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) + jni::objects::JObject::from_raw(source.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setThrower", + "setShooter", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the thrower of this item. - /// The thrower is the entity which dropped the item. - pub fn thrower( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/UUID;"); + #[deprecated] + /// Determine if this projectile should bounce or not when it hits. + pub fn does_bounce(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getThrower", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "doesBounce", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) + } + #[deprecated] + /// Set whether or not this projectile should bounce or not when it hits something. + pub fn set_bounce(&self, does_bounce: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(does_bounce.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBounce", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } /// Stores the entity's current position in the provided Location object. /// @@ -69373,19 +78302,140 @@ impl<'mc> Item<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Item<'mc> { - fn into(self) -> crate::entity::Entity<'mc> { - crate::entity::Entity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Item into crate::entity::Entity") +impl<'mc> Into> for FishHook<'mc> { + fn into(self) -> crate::entity::Projectile<'mc> { + crate::entity::Projectile::from_raw(&self.jni_ref(), self.1) + .expect("Error converting FishHook into crate::entity::Projectile") + } +} +pub enum FishHookHookState<'mc> { + Unhooked { inner: FishHookHookStateStruct<'mc> }, + HookedEntity { inner: FishHookHookStateStruct<'mc> }, + Bobbing { inner: FishHookHookStateStruct<'mc> }, +} +impl<'mc> std::fmt::Display for FishHookHookState<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + FishHookHookState::Unhooked { .. } => f.write_str("UNHOOKED"), + FishHookHookState::HookedEntity { .. } => f.write_str("HOOKED_ENTITY"), + FishHookHookState::Bobbing { .. } => f.write_str("BOBBING"), + } + } +} +impl<'mc> std::ops::Deref for FishHookHookState<'mc> { + type Target = FishHookHookStateStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + FishHookHookState::Unhooked { inner } => inner, + FishHookHookState::HookedEntity { inner } => inner, + FishHookHookState::Bobbing { inner } => inner, + } + } +} + +impl<'mc> FishHookHookState<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/FishHook/HookState"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/FishHook/HookState;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "UNHOOKED" => Ok(FishHookHookState::Unhooked { + inner: FishHookHookStateStruct::from_raw(env, obj)?, + }), + "HOOKED_ENTITY" => Ok(FishHookHookState::HookedEntity { + inner: FishHookHookStateStruct::from_raw(env, obj)?, + }), + "BOBBING" => Ok(FishHookHookState::Bobbing { + inner: FishHookHookStateStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } + #[repr(C)] -pub struct Squid<'mc>( +pub struct FishHookHookStateStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Squid<'mc> { +impl<'mc> JNIRaw<'mc> for FishHookHookState<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Unhooked { inner } => inner.0.clone(), + Self::HookedEntity { inner } => inner.0.clone(), + Self::Bobbing { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Unhooked { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::HookedEntity { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Bobbing { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for FishHookHookState<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate FishHookHookState from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/FishHook/HookState")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a FishHookHookState object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "UNHOOKED" => Ok(FishHookHookState::Unhooked { + inner: FishHookHookStateStruct::from_raw(env, obj)?, + }), + "HOOKED_ENTITY" => Ok(FishHookHookState::HookedEntity { + inner: FishHookHookStateStruct::from_raw(env, obj)?, + }), + "BOBBING" => Ok(FishHookHookState::Bobbing { + inner: FishHookHookStateStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for FishHookHookStateStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -69393,18 +78443,21 @@ impl<'mc> JNIRaw<'mc> for Squid<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Squid<'mc> { +impl<'mc> JNIInstantiatable<'mc> for FishHookHookStateStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Squid from null object.").into()); + return Err(eyre::eyre!( + "Tried to instantiate FishHookHookStateStruct from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Squid")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/FishHook/HookState")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Squid object, got {}", + "Invalid argument passed. Expected a FishHookHookStateStruct object, got {}", name ) .into()) @@ -69414,25 +78467,31 @@ impl<'mc> JNIInstantiatable<'mc> for Squid<'mc> { } } -impl<'mc> Squid<'mc> { +impl<'mc> FishHookHookStateStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/FishHook/HookState;"); + let cls = jni.find_class("org/bukkit/entity/FishHook/HookState"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::FishHookHookState::from_raw(&jni, obj) + } + pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Squid<'mc> { - fn into(self) -> crate::entity::WaterMob<'mc> { - crate::entity::WaterMob::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Squid into crate::entity::WaterMob") - } -} #[repr(C)] -pub struct TextDisplay<'mc>( +pub struct ChestedHorse<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for TextDisplay<'mc> { +impl<'mc> JNIRaw<'mc> for ChestedHorse<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -69440,18 +78499,18 @@ impl<'mc> JNIRaw<'mc> for TextDisplay<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for TextDisplay<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ChestedHorse<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate TextDisplay from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate ChestedHorse from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/TextDisplay")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ChestedHorse")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a TextDisplay object, got {}", + "Invalid argument passed. Expected a ChestedHorse object, got {}", name ) .into()) @@ -69461,958 +78520,1344 @@ impl<'mc> JNIInstantiatable<'mc> for TextDisplay<'mc> { } } -impl<'mc> TextDisplay<'mc> { - /// Gets the displayed text. - pub fn text(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getText", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// Sets the displayed text. - pub fn set_text(&self, text: impl Into) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(text.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setText", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the maximum line width before wrapping. - pub fn line_width(&self) -> Result> { - let sig = String::from("()I"); +impl<'mc> ChestedHorse<'mc> { + /// Gets whether the horse has a chest equipped. + pub fn is_carrying_chest(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLineWidth", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCarryingChest", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the maximum line width before wrapping. - pub fn set_line_width(&self, width: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(width); + /// Sets whether the horse has a chest equipped. Removing a chest will also + /// clear the chest's inventory. + pub fn set_carrying_chest(&self, chest: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(chest.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLineWidth", + "setCarryingChest", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the text background color. - pub fn background_color( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Color;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getBackgroundColor", - sig.as_str(), - vec![], - ); + #[deprecated] + /// Gets the horse's variant.A horse's variant defines its physical appearance and capabilities. Whether a horse is a regular horse, donkey, mule, or other kind of horse is determined using the variant. + pub fn variant(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Horse/Variant;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Color::from_raw(&self.jni_ref(), unsafe { + crate::entity::HorseVariant::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + }) } - /// Sets the text background color. - pub fn set_background_color( + #[deprecated] + + pub fn set_variant( &self, - color: impl Into>, + variant: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Color;)V"); + let sig = String::from("(Lorg/bukkit/entity/Horse/Variant;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) + jni::objects::JObject::from_raw(variant.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBackgroundColor", + "setVariant", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the text opacity. - pub fn text_opacity(&self) -> Result> { - let sig = String::from("()B"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTextOpacity", sig.as_str(), vec![]); + /// Gets the domestication level of this horse. + /// + /// A higher domestication level indicates that the horse is closer to + /// becoming tame. As the domestication level gets closer to the max + /// domestication level, the chance of the horse becoming tame increases. + pub fn domestication(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDomestication", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) + Ok(res.i()?) } - /// Sets the text opacity. - pub fn set_text_opacity(&self, opacity: i8) -> Result<(), Box> { - let sig = String::from("(B)V"); - let val_1 = jni::objects::JValueGen::Byte(opacity); + /// Sets the domestication level of this horse. + /// + /// Setting the domestication level to a high value will increase the + /// horse's chances of becoming tame. + /// + /// Domestication level must be greater than zero and no greater than + /// the max domestication level of the horse, determined with + /// {@link #getMaxDomestication()} + pub fn set_domestication(&self, level: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(level); let res = self.jni_ref().call_method( &self.jni_object(), - "setTextOpacity", + "setDomestication", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the text is shadowed. - pub fn is_shadowed(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isShadowed", sig.as_str(), vec![]); + /// Gets the maximum domestication level of this horse. + /// + /// The higher this level is, the longer it will likely take + /// for the horse to be tamed. + pub fn max_domestication(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaxDomestication", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets if the text is shadowed. - pub fn set_shadowed(&self, shadow: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(shadow.into()); + /// Sets the maximum domestication level of this horse. + /// + /// Setting a higher max domestication will increase the amount of + /// domesticating (feeding, riding, etc.) necessary in order to tame it, + /// while setting a lower max value will have the opposite effect. + /// + /// Maximum domestication must be greater than zero. + pub fn set_max_domestication(&self, level: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(level); let res = self.jni_ref().call_method( &self.jni_object(), - "setShadowed", + "setMaxDomestication", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the text is see through. - pub fn is_see_through(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the jump strength of this horse. + /// + /// Jump strength defines how high the horse can jump. A higher jump strength + /// increases how high a jump will go. + pub fn jump_strength(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isSeeThrough", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getJumpStrength", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Sets if the text is see through. - pub fn set_see_through(&self, see_through: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(see_through.into()); + /// Sets the jump strength of this horse. + /// + /// A higher jump strength increases how high a jump will go. + /// Setting a jump strength to 0 will result in no jump. + /// You cannot set a jump strength to a value below 0 or + /// above 2. + pub fn set_jump_strength(&self, strength: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(strength); let res = self.jni_ref().call_method( &self.jni_object(), - "setSeeThrough", + "setJumpStrength", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the text has its default background. - pub fn is_default_background(&self) -> Result> { + /// Gets whether the horse is currently grazing hay. + pub fn is_eating_haystack(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "isDefaultBackground", + "isEatingHaystack", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets if the text has its default background. - pub fn set_default_background( + /// Sets whether the horse is grazing hay. + pub fn set_eating_haystack( &self, - default_background: bool, + eating_haystack: bool, ) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(default_background.into()); + let val_1 = jni::objects::JValueGen::Bool(eating_haystack.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setDefaultBackground", + "setEatingHaystack", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the text alignment for this display. - pub fn alignment( + + pub fn inventory( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/TextDisplay/TextAlignment;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/AbstractHorseInventory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAlignment", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::TextDisplayTextAlignment::from_raw(&self.jni_ref(), unsafe { + crate::inventory::AbstractHorseInventory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the text alignment for this display. - pub fn set_alignment( - &self, - alignment: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/TextDisplay/TextAlignment;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(alignment.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAlignment", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the transformation applied to this display. - pub fn transformation( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Transformation;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTransformation", - sig.as_str(), - vec![], - ); + /// Gets the vehicle's velocity. + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Transformation::from_raw(&self.jni_ref(), unsafe { + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the transformation applied to this display - pub fn set_transformation( + /// Sets the vehicle's velocity in meters per tick. + pub fn set_velocity( &self, - transformation: impl Into>, + vel: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Transformation;)V"); + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transformation.into().jni_object().clone()) + jni::objects::JObject::from_raw(vel.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setTransformation", + "setVelocity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets the raw transformation matrix applied to this display - pub fn set_transformation_matrix( - &self, - transformation_matrix: jni::objects::JObject<'mc>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/joml/Matrix4f;)V"); - let val_1 = jni::objects::JValueGen::Object(transformation_matrix); + /// Check if this is tamed + /// + /// If something is tamed then a player can not tame it through normal + /// methods, even if it does not belong to anyone in particular. + pub fn is_tamed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isTamed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets if this has been tamed. Not necessary if the method setOwner has + /// been used, as it tames automatically. + /// + /// If something is tamed then a player can not tame it through normal + /// methods, even if it does not belong to anyone in particular. + pub fn set_tamed(&self, tame: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(tame.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setTransformationMatrix", + "setTamed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the interpolation duration of this display. - pub fn interpolation_duration(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getInterpolationDuration", - sig.as_str(), - vec![], - ); + /// Gets the current owning AnimalTamer + pub fn owner( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/AnimalTamer;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::AnimalTamer::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the interpolation duration of this display. - pub fn set_interpolation_duration( + /// Set this to be owned by given AnimalTamer. + /// + /// If the owner is not null, this will be tamed and will have any current + /// path it is following removed. If the owner is set to null, this will be + /// untamed, and the current owner removed. + pub fn set_owner( &self, - duration: i32, + tamer: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(duration); + let sig = String::from("(Lorg/bukkit/entity/AnimalTamer;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(tamer.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setInterpolationDuration", + "setOwner", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the teleport duration of this display. - ///
    - ///
  • 0 means that updates are applied immediately.
  • - ///
  • 1 means that the display entity will move from current position to the updated one over one tick.
  • - ///
  • Higher values spread the movement over multiple ticks.
  • - ///
- pub fn teleport_duration(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTeleportDuration", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Sets the teleport duration of this display. - pub fn set_teleport_duration(&self, duration: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(duration); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTeleportDuration", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +} +impl<'mc> Into> for ChestedHorse<'mc> { + fn into(self) -> crate::entity::AbstractHorse<'mc> { + crate::entity::AbstractHorse::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ChestedHorse into crate::entity::AbstractHorse") } - /// Gets the view distance/range of this display. - pub fn view_range(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getViewRange", sig.as_str(), vec![]); +} +#[repr(C)] +pub struct Llama<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Llama<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Llama<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Llama from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Llama")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Llama object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Llama<'mc> { + /// Gets the llama's color. + pub fn color(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Llama/Color;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + crate::entity::LlamaColor::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the view distance/range of this display. - pub fn set_view_range(&self, range: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(range); + /// Sets the llama's color. + pub fn set_color( + &self, + color: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Llama/Color;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(color.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setViewRange", + "setColor", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the shadow radius of this display. - pub fn shadow_radius(&self) -> Result> { - let sig = String::from("()F"); + /// Gets the llama's strength. A higher strength llama will have more + /// inventory slots and be more threatening to entities. + pub fn strength(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getShadowRadius", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getStrength", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + Ok(res.i()?) } - /// Sets the shadow radius of this display. - pub fn set_shadow_radius(&self, radius: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(radius); + /// Sets the llama's strength. A higher strength llama will have more + /// inventory slots and be more threatening to entities. Inventory slots are + /// equal to strength * 3. + pub fn set_strength(&self, strength: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(strength); let res = self.jni_ref().call_method( &self.jni_object(), - "setShadowRadius", + "setStrength", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the shadow strength of this display. - pub fn shadow_strength(&self) -> Result> { - let sig = String::from("()F"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getShadowStrength", - sig.as_str(), - vec![], - ); + /// Gets whether the horse has a chest equipped. + pub fn is_carrying_chest(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCarryingChest", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + Ok(res.z()?) } - /// Sets the shadow strength of this display. - pub fn set_shadow_strength(&self, strength: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(strength); + /// Sets whether the horse has a chest equipped. Removing a chest will also + /// clear the chest's inventory. + pub fn set_carrying_chest(&self, chest: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(chest.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setShadowStrength", + "setCarryingChest", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the width of this display. - pub fn display_width(&self) -> Result> { - let sig = String::from("()F"); + #[deprecated] + /// Gets the horse's variant.A horse's variant defines its physical appearance and capabilities. Whether a horse is a regular horse, donkey, mule, or other kind of horse is determined using the variant. + pub fn variant(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Horse/Variant;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDisplayWidth", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + crate::entity::HorseVariant::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the width of this display. - pub fn set_display_width(&self, width: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(width); + #[deprecated] + + pub fn set_variant( + &self, + variant: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Horse/Variant;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(variant.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setDisplayWidth", + "setVariant", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the height of this display. - pub fn display_height(&self) -> Result> { - let sig = String::from("()F"); + /// Gets the domestication level of this horse. + /// + /// A higher domestication level indicates that the horse is closer to + /// becoming tame. As the domestication level gets closer to the max + /// domestication level, the chance of the horse becoming tame increases. + pub fn domestication(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getDisplayHeight", + "getDomestication", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + Ok(res.i()?) } - /// Sets the height if this display. - pub fn set_display_height(&self, height: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(height); + /// Sets the domestication level of this horse. + /// + /// Setting the domestication level to a high value will increase the + /// horse's chances of becoming tame. + /// + /// Domestication level must be greater than zero and no greater than + /// the max domestication level of the horse, determined with + /// {@link #getMaxDomestication()} + pub fn set_domestication(&self, level: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(level); let res = self.jni_ref().call_method( &self.jni_object(), - "setDisplayHeight", + "setDomestication", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the amount of ticks before client-side interpolation will commence. - pub fn interpolation_delay(&self) -> Result> { + /// Gets the maximum domestication level of this horse. + /// + /// The higher this level is, the longer it will likely take + /// for the horse to be tamed. + pub fn max_domestication(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getInterpolationDelay", + "getMaxDomestication", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the amount of ticks before client-side interpolation will commence. - pub fn set_interpolation_delay(&self, ticks: i32) -> Result<(), Box> { + /// Sets the maximum domestication level of this horse. + /// + /// Setting a higher max domestication will increase the amount of + /// domesticating (feeding, riding, etc.) necessary in order to tame it, + /// while setting a lower max value will have the opposite effect. + /// + /// Maximum domestication must be greater than zero. + pub fn set_max_domestication(&self, level: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + let val_1 = jni::objects::JValueGen::Int(level); let res = self.jni_ref().call_method( &self.jni_object(), - "setInterpolationDelay", + "setMaxDomestication", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the billboard setting of this entity. - /// The billboard setting controls the automatic rotation of the entity to - /// face the player. - pub fn billboard( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Display/Billboard;"); + /// Gets the jump strength of this horse. + /// + /// Jump strength defines how high the horse can jump. A higher jump strength + /// increases how high a jump will go. + pub fn jump_strength(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBillboard", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getJumpStrength", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::DisplayBillboard::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.d()?) } - /// Sets the billboard setting of this entity. - /// The billboard setting controls the automatic rotation of the entity to - /// face the player. - pub fn set_billboard( - &self, - billboard: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Display/Billboard;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(billboard.into().jni_object().clone()) - }); + /// Sets the jump strength of this horse. + /// + /// A higher jump strength increases how high a jump will go. + /// Setting a jump strength to 0 will result in no jump. + /// You cannot set a jump strength to a value below 0 or + /// above 2. + pub fn set_jump_strength(&self, strength: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(strength); let res = self.jni_ref().call_method( &self.jni_object(), - "setBillboard", + "setJumpStrength", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the scoreboard team overridden glow color of this display. - pub fn glow_color_override( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Color;"); + /// Gets whether the horse is currently grazing hay. + pub fn is_eating_haystack(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getGlowColorOverride", + "isEatingHaystack", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Color::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.z()?) } - /// Sets the scoreboard team overridden glow color of this display. - pub fn set_glow_color_override( + /// Sets whether the horse is grazing hay. + pub fn set_eating_haystack( &self, - color: impl Into>, + eating_haystack: bool, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Color;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) - }); + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(eating_haystack.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setGlowColorOverride", + "setEatingHaystack", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the brightness override of the entity. - pub fn brightness( + + pub fn inventory( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Display/Brightness;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/AbstractHorseInventory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBrightness", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::DisplayBrightness::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::inventory::AbstractHorseInventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the brightness override of the entity. - pub fn set_brightness( + /// Gets the vehicle's velocity. + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the vehicle's velocity in meters per tick. + pub fn set_velocity( &self, - brightness: impl Into>, + vel: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Display/Brightness;)V"); + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(brightness.into().jni_object().clone()) + jni::objects::JObject::from_raw(vel.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBrightness", + "setVelocity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Stores the entity's current position in the provided Location object. + /// Check if this is tamed /// - /// If the provided Location is null this method does nothing and returns - /// null. - pub fn get_location( - &self, - loc: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) - }); + /// If something is tamed then a player can not tame it through normal + /// methods, even if it does not belong to anyone in particular. + pub fn is_tamed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isTamed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets if this has been tamed. Not necessary if the method setOwner has + /// been used, as it tames automatically. + /// + /// If something is tamed then a player can not tame it through normal + /// methods, even if it does not belong to anyone in particular. + pub fn set_tamed(&self, tame: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(tame.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocation", + "setTamed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the current owning AnimalTamer + pub fn owner( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/AnimalTamer;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(Some(crate::entity::AnimalTamer::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets this entity's velocity in meters per tick - pub fn set_velocity( + /// Set this to be owned by given AnimalTamer. + /// + /// If the owner is not null, this will be tamed and will have any current + /// path it is following removed. If the owner is set to null, this will be + /// untamed, and the current owner removed. + pub fn set_owner( &self, - velocity: impl Into>, + tamer: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let sig = String::from("(Lorg/bukkit/entity/AnimalTamer;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + jni::objects::JObject::from_raw(tamer.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVelocity", + "setOwner", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets this entity's current velocity - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Gets the entity's height - pub fn height(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) +} +impl<'mc> Into> for Llama<'mc> { + fn into(self) -> crate::entity::ChestedHorse<'mc> { + crate::entity::ChestedHorse::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Llama into crate::entity::ChestedHorse") } - /// Gets the entity's width - pub fn width(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) +} +pub enum LlamaColor<'mc> { + Creamy { inner: LlamaColorStruct<'mc> }, + White { inner: LlamaColorStruct<'mc> }, + Brown { inner: LlamaColorStruct<'mc> }, + Gray { inner: LlamaColorStruct<'mc> }, +} +impl<'mc> std::fmt::Display for LlamaColor<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + LlamaColor::Creamy { .. } => f.write_str("CREAMY"), + LlamaColor::White { .. } => f.write_str("WHITE"), + LlamaColor::Brown { .. } => f.write_str("BROWN"), + LlamaColor::Gray { .. } => f.write_str("GRAY"), + } } - /// Gets the entity's current bounding box. - /// - /// The returned bounding box reflects the entity's current location and - /// size. - pub fn bounding_box( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} +impl<'mc> std::ops::Deref for LlamaColor<'mc> { + type Target = LlamaColorStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + LlamaColor::Creamy { inner } => inner, + LlamaColor::White { inner } => inner, + LlamaColor::Brown { inner } => inner, + LlamaColor::Gray { inner } => inner, + } } - /// Returns true if the entity is supported by a block. This value is a - /// state updated by the server and is not recalculated unless the entity - /// moves. - pub fn is_on_ground(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} + +impl<'mc> LlamaColor<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/Llama/Color"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/Llama/Color;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "CREAMY" => Ok(LlamaColor::Creamy { + inner: LlamaColorStruct::from_raw(env, obj)?, + }), + "WHITE" => Ok(LlamaColor::White { + inner: LlamaColorStruct::from_raw(env, obj)?, + }), + "BROWN" => Ok(LlamaColor::Brown { + inner: LlamaColorStruct::from_raw(env, obj)?, + }), + "GRAY" => Ok(LlamaColor::Gray { + inner: LlamaColorStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } - /// Returns true if the entity is in water. - pub fn is_in_water(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} + +#[repr(C)] +pub struct LlamaColorStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for LlamaColor<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Creamy { inner } => inner.0.clone(), + Self::White { inner } => inner.0.clone(), + Self::Brown { inner } => inner.0.clone(), + Self::Gray { inner } => inner.0.clone(), + } } - /// Gets the current world this entity resides in - pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Creamy { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::White { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Brown { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Gray { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } - /// Sets the entity's rotation. - /// - /// Note that if the entity is affected by AI, it may override this rotation. - pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { - let sig = String::from("(FF)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); - let val_2 = jni::objects::JValueGen::Float(pitch); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRotation", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +} +impl<'mc> JNIInstantiatable<'mc> for LlamaColor<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate LlamaColor from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Llama/Color")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a LlamaColor object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "CREAMY" => Ok(LlamaColor::Creamy { + inner: LlamaColorStruct::from_raw(env, obj)?, + }), + "WHITE" => Ok(LlamaColor::White { + inner: LlamaColorStruct::from_raw(env, obj)?, + }), + "BROWN" => Ok(LlamaColor::Brown { + inner: LlamaColorStruct::from_raw(env, obj)?, + }), + "GRAY" => Ok(LlamaColor::Gray { + inner: LlamaColorStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } } - /// Teleports this entity to the given location. If this entity is riding a - /// vehicle, it will be dismounted prior to teleportation. - pub fn teleport( - &self, - location: impl Into>, - cause: std::option::Option< - impl Into>, - >, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = cause { - sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); +} + +impl<'mc> JNIRaw<'mc> for LlamaColorStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for LlamaColorStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate LlamaColorStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Llama/Color")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a LlamaColorStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "teleport", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) } - /// Returns a list of entities within a bounding box centered around this - /// entity - pub fn get_nearby_entities( - &self, - x: f64, - y: f64, - z: f64, - ) -> Result>, Box> { - let sig = String::from("(DDD)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Double(x); - let val_2 = jni::objects::JValueGen::Double(y); - let val_3 = jni::objects::JValueGen::Double(z); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getNearbyEntities", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], +} + +impl<'mc> LlamaColorStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Llama/Color;"); + let cls = jni.find_class("org/bukkit/entity/Llama/Color"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::LlamaColor::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +pub enum SpawnCategory<'mc> { + Monster { inner: SpawnCategoryStruct<'mc> }, + Animal { inner: SpawnCategoryStruct<'mc> }, + WaterAnimal { inner: SpawnCategoryStruct<'mc> }, + WaterAmbient { inner: SpawnCategoryStruct<'mc> }, + WaterUndergroundCreature { inner: SpawnCategoryStruct<'mc> }, + Ambient { inner: SpawnCategoryStruct<'mc> }, + Axolotl { inner: SpawnCategoryStruct<'mc> }, + Misc { inner: SpawnCategoryStruct<'mc> }, +} +impl<'mc> std::fmt::Display for SpawnCategory<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + SpawnCategory::Monster { .. } => f.write_str("MONSTER"), + SpawnCategory::Animal { .. } => f.write_str("ANIMAL"), + SpawnCategory::WaterAnimal { .. } => f.write_str("WATER_ANIMAL"), + SpawnCategory::WaterAmbient { .. } => f.write_str("WATER_AMBIENT"), + SpawnCategory::WaterUndergroundCreature { .. } => { + f.write_str("WATER_UNDERGROUND_CREATURE") + } + SpawnCategory::Ambient { .. } => f.write_str("AMBIENT"), + SpawnCategory::Axolotl { .. } => f.write_str("AXOLOTL"), + SpawnCategory::Misc { .. } => f.write_str("MISC"), + } + } +} +impl<'mc> std::ops::Deref for SpawnCategory<'mc> { + type Target = SpawnCategoryStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + SpawnCategory::Monster { inner } => inner, + SpawnCategory::Animal { inner } => inner, + SpawnCategory::WaterAnimal { inner } => inner, + SpawnCategory::WaterAmbient { inner } => inner, + SpawnCategory::WaterUndergroundCreature { inner } => inner, + SpawnCategory::Ambient { inner } => inner, + SpawnCategory::Axolotl { inner } => inner, + SpawnCategory::Misc { inner } => inner, + } + } +} + +impl<'mc> SpawnCategory<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/SpawnCategory"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/SpawnCategory;", + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "MONSTER" => Ok(SpawnCategory::Monster { + inner: SpawnCategoryStruct::from_raw(env, obj)?, + }), + "ANIMAL" => Ok(SpawnCategory::Animal { + inner: SpawnCategoryStruct::from_raw(env, obj)?, + }), + "WATER_ANIMAL" => Ok(SpawnCategory::WaterAnimal { + inner: SpawnCategoryStruct::from_raw(env, obj)?, + }), + "WATER_AMBIENT" => Ok(SpawnCategory::WaterAmbient { + inner: SpawnCategoryStruct::from_raw(env, obj)?, + }), + "WATER_UNDERGROUND_CREATURE" => Ok(SpawnCategory::WaterUndergroundCreature { + inner: SpawnCategoryStruct::from_raw(env, obj)?, + }), + "AMBIENT" => Ok(SpawnCategory::Ambient { + inner: SpawnCategoryStruct::from_raw(env, obj)?, + }), + "AXOLOTL" => Ok(SpawnCategory::Axolotl { + inner: SpawnCategoryStruct::from_raw(env, obj)?, + }), + "MISC" => Ok(SpawnCategory::Misc { + inner: SpawnCategoryStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct SpawnCategoryStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for SpawnCategory<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Monster { inner } => inner.0.clone(), + Self::Animal { inner } => inner.0.clone(), + Self::WaterAnimal { inner } => inner.0.clone(), + Self::WaterAmbient { inner } => inner.0.clone(), + Self::WaterUndergroundCreature { inner } => inner.0.clone(), + Self::Ambient { inner } => inner.0.clone(), + Self::Axolotl { inner } => inner.0.clone(), + Self::Misc { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Monster { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Animal { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::WaterAnimal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaterAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaterUndergroundCreature { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Ambient { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Axolotl { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Misc { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for SpawnCategory<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate SpawnCategory from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/SpawnCategory")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a SpawnCategory object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "MONSTER" => Ok(SpawnCategory::Monster { + inner: SpawnCategoryStruct::from_raw(env, obj)?, + }), + "ANIMAL" => Ok(SpawnCategory::Animal { + inner: SpawnCategoryStruct::from_raw(env, obj)?, + }), + "WATER_ANIMAL" => Ok(SpawnCategory::WaterAnimal { + inner: SpawnCategoryStruct::from_raw(env, obj)?, + }), + "WATER_AMBIENT" => Ok(SpawnCategory::WaterAmbient { + inner: SpawnCategoryStruct::from_raw(env, obj)?, + }), + "WATER_UNDERGROUND_CREATURE" => Ok(SpawnCategory::WaterUndergroundCreature { + inner: SpawnCategoryStruct::from_raw(env, obj)?, + }), + "AMBIENT" => Ok(SpawnCategory::Ambient { + inner: SpawnCategoryStruct::from_raw(env, obj)?, + }), + "AXOLOTL" => Ok(SpawnCategory::Axolotl { + inner: SpawnCategoryStruct::from_raw(env, obj)?, + }), + "MISC" => Ok(SpawnCategory::Misc { + inner: SpawnCategoryStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for SpawnCategoryStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for SpawnCategoryStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate SpawnCategoryStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/SpawnCategory")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a SpawnCategoryStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - Ok(new_vec) } - /// Returns a unique id for this entity - pub fn entity_id(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) +} + +impl<'mc> SpawnCategoryStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); + let cls = jni.find_class("org/bukkit/entity/SpawnCategory"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::SpawnCategory::from_raw(&jni, obj) } - /// Returns the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn fire_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Returns the entity's maximum fire ticks. - pub fn max_fire_ticks(&self) -> Result> { +} +#[repr(C)] +pub struct MagmaCube<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for MagmaCube<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for MagmaCube<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate MagmaCube from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/MagmaCube")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a MagmaCube object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> MagmaCube<'mc> { + pub fn size(&self) -> Result> { let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { + + pub fn set_size(&self, sz: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + let val_1 = jni::objects::JValueGen::Int(sz); let res = self.jni_ref().call_method( &self.jni_object(), - "setFireTicks", + "setSize", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets if the entity has visual fire (it will always appear to be on fire). - pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire.into()); + /// Instructs this Mob to set the specified LivingEntity as its target. + /// + /// Hostile creatures may attack their target, and friendly creatures may + /// follow their target. + pub fn set_target( + &self, + target: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(target.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisualFire", + "setTarget", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity has visual fire (it will always appear to be on fire). - pub fn is_visual_fire(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the entity's maximum freeze ticks (amount of ticks before it will - /// be fully frozen) - pub fn max_freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMaxFreezeTicks", - sig.as_str(), - vec![], - ); + /// Gets the current target of this Mob + pub fn target( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTarget", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::LivingEntity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets whether this mob is aware of its surroundings. + /// Unaware mobs will still move if pushed, attacked, etc. but will not move + /// or perform any actions on their own. Unaware mobs may also have other + /// unspecified behaviours disabled, such as drowning. + pub fn set_aware(&self, aware: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(aware.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setFreezeTicks", + "setAware", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity is fully frozen (it has been in powdered snow for max - /// freeze ticks). - pub fn is_frozen(&self) -> Result> { + /// Gets whether this mob is aware of its surroundings. + /// Unaware mobs will still move if pushed, attacked, etc. but will not move + /// or perform any actions on their own. Unaware mobs may also have other + /// unspecified behaviours disabled, such as drowning. + pub fn is_aware(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isAware", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Mark the entity's removal. - pub fn remove(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns true if this entity has been marked for removal. - pub fn is_dead(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); + /// Get the {@link Sound} this mob makes while ambiently existing. This sound + /// may change depending on the current state of the entity, and may also + /// return null under specific conditions. This sound is not constant. + /// For instance, villagers will make different passive noises depending + /// on whether or not they are actively trading with a player, or make no + /// ambient noise while sleeping. + pub fn ambient_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAmbientSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Returns false if the entity has died, been despawned for some other - /// reason, or has not been added to the world. - pub fn is_valid(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Gets the {@link Server} that contains this Entity - pub fn server(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Server;"); +} +impl<'mc> Into> for MagmaCube<'mc> { + fn into(self) -> crate::entity::Slime<'mc> { + crate::entity::Slime::from_raw(&self.jni_ref(), self.1) + .expect("Error converting MagmaCube into crate::entity::Slime") + } +} +#[repr(C)] +pub struct WindCharge<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for WindCharge<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for WindCharge<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate WindCharge from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/WindCharge")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a WindCharge object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> WindCharge<'mc> { + /// Immediately explode this WindCharge. + pub fn explode(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Server::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + .call_method(&self.jni_object(), "explode", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns true if the entity gets persisted. + /// Sets the direction the fireball should be flying towards. /// - /// By default all entities are persistent. An entity will also not get - /// persisted, if it is riding an entity that is not persistent. + /// This is a convenience method, it will change the velocity direction and + /// acceleration direction, while keeping the power the same. /// - /// The persistent flag on players controls whether or not to save their - /// playerdata file when they quit. If a player is directly or indirectly - /// riding a non-persistent entity, the vehicle at the root and all its - /// passengers won't get persisted. + /// Note: This method only uses the direction of the vector and will + /// normalize (a copy of) it. /// - /// This should not be confused with - /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls - /// despawning of living entities. - pub fn is_persistent(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether or not the entity gets persisted. - pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(persistent.into()); + /// Special Case: When the given direction is + /// {@link Vector#isZero() zero}, the velocity and acceleration will also be + /// set to zero without keeping the power. + pub fn set_direction( + &self, + direction: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(direction.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPersistent", + "setDirection", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -70420,820 +79865,1251 @@ impl<'mc> TextDisplay<'mc> { Ok(()) } #[deprecated] - /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. - pub fn passenger( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + /// Retrieve the direction this fireball is heading toward. The returned vector is not normalized. + pub fn direction(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - /// Set the passenger of a vehicle. - pub fn set_passenger( + /// Sets the acceleration of the fireball. + /// The acceleration gets applied to the velocity every tick, depending on + /// the specific type of the fireball a damping / drag factor is applied so + /// that the velocity does not grow into infinity. + /// + /// Note: that the client may not respect non-default acceleration + /// power and will therefore mispredict the location of the fireball, causing + /// visual stutter. + pub fn set_acceleration( &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + acceleration: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(acceleration.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPassenger", + "setAcceleration", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets a list of passengers of this vehicle. - /// - /// The returned list will not be directly linked to the entity's current - /// passengers, and no guarantees are made as to its mutability. - pub fn passengers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + /// Retrieve the acceleration of this fireball. + pub fn acceleration(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAcceleration", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for WindCharge<'mc> { + fn into(self) -> crate::entity::AbstractWindCharge<'mc> { + crate::entity::AbstractWindCharge::from_raw(&self.jni_ref(), self.1) + .expect("Error converting WindCharge into crate::entity::AbstractWindCharge") + } +} +#[repr(C)] +pub struct Bee<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Bee<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Bee<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Bee from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Bee")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Bee object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - Ok(new_vec) } - /// Add a passenger to the vehicle. - pub fn add_passenger( +} + +impl<'mc> Bee<'mc> { + /// Get the bee's hive location. + pub fn hive(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHive", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Set the bee's hive location. + pub fn set_hive( &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + location: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Location;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(location.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "addPassenger", + "setHive", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the bee's flower location. + pub fn flower(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFlower", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Remove a passenger from the vehicle. - pub fn remove_passenger( + /// Set the bee's flower location. + pub fn set_flower( &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + location: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Location;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(location.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removePassenger", + "setFlower", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Check if a vehicle has passengers. - pub fn is_empty(&self) -> Result> { + /// Get if the bee has nectar. + pub fn has_nectar(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasNectar", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Eject any passenger. - pub fn eject(&self) -> Result> { + /// Set if the bee has nectar. + pub fn set_has_nectar(&self, nectar: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(nectar.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setHasNectar", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get if the bee has stung. + pub fn has_stung(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasStung", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns the distance this entity has fallen - pub fn fall_distance(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Sets the fall distance for this entity - pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(distance); + /// Set if the bee has stung. + pub fn set_has_stung(&self, stung: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(stung.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setFallDistance", + "setHasStung", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Record the last {@link EntityDamageEvent} inflicted on this entity - pub fn set_last_damage_cause( - &self, - event: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(event.into().jni_object().clone()) - }); + /// Get the bee's anger level. + pub fn anger(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getAnger", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the bee's new anger level. + pub fn set_anger(&self, anger: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(anger); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDamageCause", + "setAnger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. - /// This event may have been cancelled. - pub fn last_damage_cause( - &self, - ) -> Result>, Box> - { - let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + /// Get the amount of ticks the bee cannot enter the hive for. + pub fn cannot_enter_hive_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLastDamageCause", + "getCannotEnterHiveTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Returns a unique and persistent id for this entity - pub fn unique_id( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. - pub fn ticks_lived(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. May not be less than one - /// tick. - pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { + /// Set the amount of ticks the bee cannot enter a hive for. + pub fn set_cannot_enter_hive_ticks( + &self, + ticks: i32, + ) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(value); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setTicksLived", + "setCannotEnterHiveTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Performs the specified {@link EntityEffect} for this entity. - /// - /// This will be viewable to all players near the entity. - /// - /// If the effect is not applicable to this class of entity, it will not play. - pub fn play_effect( + /// Get the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn breed_cause( &self, - val_type: impl Into>, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Set the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn set_breed_cause( + &self, + uuid: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); + let sig = String::from("(Ljava/util/UUID;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "playEffect", + "setBreedCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the type of the entity. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity makes while swimming. - pub fn swim_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Get whether or not this entity is in love mode and will produce + /// offspring with another entity in love mode. Will return true if + /// and only if {@link #getLoveModeTicks()} is greater than 0. + pub fn is_love_mode(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Get the {@link Sound} this entity makes when splashing in water. For most - /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_splash_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Get the amount of ticks remaining for this entity in love mode. + /// If the entity is not in love mode, 0 will be returned. + pub fn love_mode_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimSplashSound", + "getLoveModeTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Get the {@link Sound} this entity makes when splashing in water at high - /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_high_speed_splash_sound( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Set the amount of ticks for which this entity should be in love mode. + /// Setting the love mode ticks to 600 is the equivalent of a player + /// feeding the entity their breeding item of choice. + pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimHighSpeedSplashSound", + "setLoveModeTicks", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns whether this entity is inside a vehicle. - pub fn is_inside_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); + /// Check if the provided ItemStack is the correct item used for breeding + /// this entity.. + pub fn is_breed_item( + &self, + material: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Leave the current vehicle. If the entity is currently in a vehicle (and - /// is removed from it), true will be returned, otherwise false will be - /// returned. - pub fn leave_vehicle(&self) -> Result> { + /// Lock the age of the animal, setting this will prevent the animal from + /// maturing or getting ready for mating. + pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(lock.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAgeLock", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the current agelock. + pub fn age_lock(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get the vehicle that this entity is inside. If there is no vehicle, - /// null will be returned. - pub fn vehicle( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + /// Return the ability to breed of the animal. + pub fn can_breed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Sets whether or not to display the mob's custom name client side. The - /// name will be displayed above the mob similarly to a player. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { + /// Set breedability of the animal, if the animal is a baby and set to + /// breed it will instantly grow up. + pub fn set_breed(&self, breed: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(breed.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomNameVisible", + "setBreed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not the mob's custom name is displayed client side. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn is_custom_name_visible(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isCustomNameVisible", - sig.as_str(), - vec![], - ); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Bee<'mc> { + fn into(self) -> crate::entity::Animals<'mc> { + crate::entity::Animals::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Bee into crate::entity::Animals") + } +} +#[repr(C)] +pub struct Breedable<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Breedable<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Breedable<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Breedable from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Breedable")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Breedable object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Breedable<'mc> { + #[deprecated] + /// Lock the age of the animal, setting this will prevent the animal from maturing or getting ready for mating. + pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(lock.into()); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setAgeLock", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the current agelock. + pub fn age_lock(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(visible.into()); + #[deprecated] + /// Return the ability to breed of the animal. + pub fn can_breed(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "canBreed", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Set breedability of the animal, if the animal is a baby and set to breed it will instantly grow up. + pub fn set_breed(&self, breed: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(breed.into()); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setBreed", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the age of this mob. + pub fn age(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getAge", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the age of this mob. + pub fn set_age(&self, age: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(age); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisibleByDefault", + "setAge", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn is_visible_by_default(&self) -> Result> { + /// Sets the age of the mob to a baby + pub fn set_baby(&self) -> Result<(), Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setBaby", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets the age of the mob to an adult + pub fn set_adult(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setAdult", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns true if the mob is an adult. + pub fn is_adult(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isAdult", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Breedable<'mc> { + fn into(self) -> crate::entity::Ageable<'mc> { + crate::entity::Ageable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Breedable into crate::entity::Ageable") + } +} +#[repr(C)] +pub struct Skeleton<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Skeleton<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Skeleton<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Skeleton from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Skeleton")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Skeleton object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Skeleton<'mc> { + /// Computes whether or not this skeleton is currently in the process of + /// converting to a {@link Stray} due to it being frozen by powdered snow. + pub fn is_converting(&self) -> Result> { let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isConverting", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the amount of ticks until this entity will be converted to a stray + /// as a result of being frozen by a powdered snow block. + /// + /// When this reaches 0, the entity will be converted. + pub fn conversion_time(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "isVisibleByDefault", + "getConversionTime", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Get all players that are currently tracking this entity. + /// Sets the amount of ticks until this entity will be converted to a stray + /// as a result of being frozen by a powdered snow block. /// - /// 'Tracking' means that this entity has been sent to the player and that - /// they are receiving updates on its state. Note that the client's {@code - /// 'Entity Distance'} setting does not affect the range at which entities - /// are tracked. - pub fn tracked_by( + /// When this reaches 0, the entity will be converted. A value of less than 0 + /// will stop the current conversion process without converting the current + /// entity. + pub fn set_conversion_time(&self, time: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(time); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setConversionTime", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the current type of this skeleton. + pub fn skeleton_type( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Skeleton/SkeletonType;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSkeletonType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + crate::entity::SkeletonSkeletonType::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets whether the entity has a team colored (default: white) glow. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + #[deprecated] + + pub fn set_skeleton_type( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Skeleton/SkeletonType;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setGlowing", + "setSkeletonType", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is glowing or not. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn is_glowing(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Sets whether the entity is invulnerable or not. - /// - /// When an entity is invulnerable it can only be damaged by players in - /// creative mode. - pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setInvulnerable", - sig.as_str(), +} +impl<'mc> Into> for Skeleton<'mc> { + fn into(self) -> crate::entity::AbstractSkeleton<'mc> { + crate::entity::AbstractSkeleton::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Skeleton into crate::entity::AbstractSkeleton") + } +} +pub enum SkeletonSkeletonType<'mc> { + Normal { + inner: SkeletonSkeletonTypeStruct<'mc>, + }, + Wither { + inner: SkeletonSkeletonTypeStruct<'mc>, + }, + Stray { + inner: SkeletonSkeletonTypeStruct<'mc>, + }, + Bogged { + inner: SkeletonSkeletonTypeStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for SkeletonSkeletonType<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + SkeletonSkeletonType::Normal { .. } => f.write_str("NORMAL"), + SkeletonSkeletonType::Wither { .. } => f.write_str("WITHER"), + SkeletonSkeletonType::Stray { .. } => f.write_str("STRAY"), + SkeletonSkeletonType::Bogged { .. } => f.write_str("BOGGED"), + } + } +} +impl<'mc> std::ops::Deref for SkeletonSkeletonType<'mc> { + type Target = SkeletonSkeletonTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + SkeletonSkeletonType::Normal { inner } => inner, + SkeletonSkeletonType::Wither { inner } => inner, + SkeletonSkeletonType::Stray { inner } => inner, + SkeletonSkeletonType::Bogged { inner } => inner, + } + } +} + +impl<'mc> SkeletonSkeletonType<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/Skeleton/SkeletonType"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/Skeleton/SkeletonType;", vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "NORMAL" => Ok(SkeletonSkeletonType::Normal { + inner: SkeletonSkeletonTypeStruct::from_raw(env, obj)?, + }), + "WITHER" => Ok(SkeletonSkeletonType::Wither { + inner: SkeletonSkeletonTypeStruct::from_raw(env, obj)?, + }), + "STRAY" => Ok(SkeletonSkeletonType::Stray { + inner: SkeletonSkeletonTypeStruct::from_raw(env, obj)?, + }), + "BOGGED" => Ok(SkeletonSkeletonType::Bogged { + inner: SkeletonSkeletonTypeStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } - /// Gets whether the entity is invulnerable or not. - pub fn is_invulnerable(&self) -> Result> { - let sig = String::from("()Z"); +} + +#[repr(C)] +pub struct SkeletonSkeletonTypeStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for SkeletonSkeletonType<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Normal { inner } => inner.0.clone(), + Self::Wither { inner } => inner.0.clone(), + Self::Stray { inner } => inner.0.clone(), + Self::Bogged { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Normal { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Wither { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Stray { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Bogged { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for SkeletonSkeletonType<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate SkeletonSkeletonType from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Skeleton/SkeletonType")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a SkeletonSkeletonType object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "NORMAL" => Ok(SkeletonSkeletonType::Normal { + inner: SkeletonSkeletonTypeStruct::from_raw(env, obj)?, + }), + "WITHER" => Ok(SkeletonSkeletonType::Wither { + inner: SkeletonSkeletonTypeStruct::from_raw(env, obj)?, + }), + "STRAY" => Ok(SkeletonSkeletonType::Stray { + inner: SkeletonSkeletonTypeStruct::from_raw(env, obj)?, + }), + "BOGGED" => Ok(SkeletonSkeletonType::Bogged { + inner: SkeletonSkeletonTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for SkeletonSkeletonTypeStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for SkeletonSkeletonTypeStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate SkeletonSkeletonTypeStruct from null object." + ) + .into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Skeleton/SkeletonType")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a SkeletonSkeletonTypeStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> SkeletonSkeletonTypeStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Skeleton/SkeletonType;"); + let cls = jni.find_class("org/bukkit/entity/Skeleton/SkeletonType"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::SkeletonSkeletonType::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct Villager<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Villager<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Villager<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Villager from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Villager")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Villager object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Villager<'mc> { + /// Gets the current profession of this villager. + pub fn profession( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Villager/Profession;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets whether the entity is silent or not. - pub fn is_silent(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getProfession", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::VillagerProfession::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets whether the entity is silent or not. - /// - /// When an entity is silent it will not produce any sound. - pub fn set_silent(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Sets the new profession of this villager. + pub fn set_profession( + &self, + profession: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Villager/Profession;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(profession.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setSilent", + "setProfession", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether gravity applies to this entity. - pub fn has_gravity(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the current type of this villager. + pub fn villager_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Villager/Type;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getVillagerType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::VillagerType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets whether gravity applies to this entity. - pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gravity.into()); + /// Sets the new type of this villager. + pub fn set_villager_type( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Villager/Type;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setGravity", + "setVillagerType", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the period of time (in ticks) before this entity can use a portal. - pub fn portal_cooldown(&self) -> Result> { + /// Gets the level of this villager. + /// A villager with a level of 1 and no experience is liable to lose its + /// profession. + pub fn villager_level(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPortalCooldown", + "getVillagerLevel", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the period of time (in ticks) before this entity can use a portal. - pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { + /// Sets the level of this villager. + /// A villager with a level of 1 and no experience is liable to lose its + /// profession. + pub fn set_villager_level(&self, level: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(cooldown); + let val_1 = jni::objects::JValueGen::Int(level); let res = self.jni_ref().call_method( &self.jni_object(), - "setPortalCooldown", + "setVillagerLevel", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a set of tags for this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn scoreboard_tags( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Gets the trading experience of this villager. + pub fn villager_experience(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getScoreboardTags", + "getVillagerExperience", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Add a tag to this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn add_scoreboard_tag( + /// Sets the trading experience of this villager. + pub fn set_villager_experience( &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); + experience: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(experience); let res = self.jni_ref().call_method( &self.jni_object(), - "addScoreboardTag", + "setVillagerExperience", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Removes a given tag from this entity. - pub fn remove_scoreboard_tag( + /// Attempts to make this villager sleep at the given location. + /// + /// The location must be in the current world and have a bed placed at the + /// location. The villager will put its head on the specified block while + /// sleeping. + pub fn sleep( &self, - tag: impl Into, + location: impl Into>, ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); + let sig = String::from("(Lorg/bukkit/Location;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeScoreboardTag", + "sleep", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns the reaction of the entity when moved by a piston. - pub fn piston_move_reaction( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPistonMoveReaction", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the closest cardinal {@link BlockFace} direction an entity is - /// currently facing. - /// - /// This will not return any non-cardinal directions such as - /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. - /// - /// {@link Hanging} entities will override this call and thus their behavior - /// may be different. - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the entity's current pose. - /// Note that the pose is only updated at the end of a tick, so may be - /// inconsistent with other methods. eg {@link Player#isSneaking()} being - /// true does not imply the current pose will be {@link Pose#SNEAKING} - pub fn pose(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Pose;"); + /// Causes this villager to wake up if he's currently sleeping. + pub fn wakeup(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the category of spawn to which this entity belongs. - pub fn spawn_category( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSpawnCategory", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + .call_method(&self.jni_object(), "wakeup", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Checks if this entity has been spawned in a world. - /// - /// Entities not spawned in a world will not tick, be sent to players, or be - /// saved to the server files. - pub fn is_in_world(&self) -> Result> { - let sig = String::from("()Z"); + /// Causes this villager to shake his head. + pub fn shake_head(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get this entity as an NBT string. - /// - /// This string should not be relied upon as a serializable value. - pub fn as_string(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + .call_method(&self.jni_object(), "shakeHead", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Crates an {@link EntitySnapshot} representing the current state of this entity. - pub fn create_snapshot( + /// Convert this Villager into a ZombieVillager as if it was killed by a + /// Zombie. + /// Note: this will fire a EntityTransformEvent + pub fn zombify( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/ZombieVillager;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "zombify", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::EntitySnapshot::from_raw( + Ok(Some(crate::entity::ZombieVillager::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// Gets this villager's inventory. /// - /// Note: Players cannot be copied. - pub fn copy( + /// Note that this inventory is not the Merchant inventory, rather, it is the + /// items that a villager might have collected (from harvesting crops, etc.) + /// {@inheritDoc} + pub fn inventory( &self, - to: std::option::Option>>, - ) -> Result, Box> { + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Lock the age of the animal, setting this will prevent the animal from + /// maturing or getting ready for mating. + pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = to { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")Lorg/bukkit/entity/Entity;"; + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(lock.into()); + args.push(val_1); + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); + .call_method(&self.jni_object(), "setAgeLock", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the current agelock. + pub fn age_lock(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets a metadata value in the implementing object's metadata store. - pub fn set_metadata( - &self, - metadata_key: impl Into, - new_metadata_value: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMetadata", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + /// Return the ability to breed of the animal. + pub fn can_breed(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "canBreed", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set breedability of the animal, if the animal is a baby and set to + /// breed it will instantly grow up. + pub fn set_breed(&self, breed: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(breed.into()); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setBreed", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a list of previously set metadata values from the implementing - /// object's metadata store. - pub fn get_metadata( + /// Get a list of trades currently available from this merchant. + pub fn recipes( &self, - metadata_key: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMetadata", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRecipes", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::metadata::MetadataValue::from_raw( + new_vec.push(crate::inventory::MerchantRecipe::from_raw( &self.jni_ref(), obj, )?); } Ok(new_vec) } - /// Tests to see whether the implementing object contains the given - /// metadata value in its metadata store. - pub fn has_metadata( + /// Set the list of trades currently available from this merchant. + /// + /// This will not change the selected trades of players currently trading + /// with this merchant. + pub fn set_recipes( &self, - metadata_key: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); + recipes: Vec>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/List;)V"); + let raw_val_1 = self + .jni_ref() + .new_object("java/util/ArrayList", "()V", vec![])?; + for v in recipes { + let map_val_0 = jni::objects::JValueGen::Object(v); + self.jni_ref().call_method( + &raw_val_1, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_1 = jni::objects::JValueGen::Object(raw_val_1); let res = self.jni_ref().call_method( &self.jni_object(), - "hasMetadata", + "setRecipes", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the recipe at a certain index of this merchant's trade list. + pub fn get_recipe( + &self, + i: i32, + ) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/MerchantRecipe;"); + let val_1 = jni::objects::JValueGen::Int(i); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getRecipe", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::MerchantRecipe::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Removes the given metadata value from the implementing object's - /// metadata store. - pub fn remove_metadata( + /// Set the recipe at a certain index of this merchant's trade list. + pub fn set_recipe( &self, - metadata_key: impl Into, - owning_plugin: impl Into>, + i: i32, + recipe: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); + let sig = String::from("(ILorg/bukkit/inventory/MerchantRecipe;)V"); + let val_1 = jni::objects::JValueGen::Int(i); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeMetadata", + "setRecipe", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), @@ -71243,109 +81119,41 @@ impl<'mc> TextDisplay<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Sends this sender multiple messages - pub fn send_message( - &self, - sender: impl Into>, - messages: std::option::Option>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = messages { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Get the number of trades this merchant currently has available. + pub fn recipe_count(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRecipeCount", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Gets the name of this command sender - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Gets whether this merchant is currently trading. + pub fn is_trading(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isTrading", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - /// Gets the custom name on a mob or block. If there is no name this method - /// will return null. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn custom_name(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCustomName", sig.as_str(), vec![]); + /// Gets the player this merchant is trading with, or null if it is not + /// currently trading. + pub fn trader( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTrader", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// Sets a custom name on a mob or block. This name will be used in death - /// messages and can be sent to the client as a nameplate over the mob. - /// - /// Setting the name to null or an empty string will clear it. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn set_custom_name( - &self, - name: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCustomName", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPersistentDataContainer", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(Some(crate::entity::HumanEntity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -71353,95 +81161,19 @@ impl<'mc> TextDisplay<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for TextDisplay<'mc> { - fn into(self) -> crate::entity::Display<'mc> { - crate::entity::Display::from_raw(&self.jni_ref(), self.1) - .expect("Error converting TextDisplay into crate::entity::Display") - } -} -pub enum TextDisplayTextAlignment<'mc> {} -impl<'mc> std::fmt::Display for TextDisplayTextAlignment<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> TextDisplayTextAlignment<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/TextDisplay/TextAlignment"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/TextDisplay/TextAlignment;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } +impl<'mc> Into> for Villager<'mc> { + fn into(self) -> crate::entity::AbstractVillager<'mc> { + crate::entity::AbstractVillager::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Villager into crate::entity::AbstractVillager") } } - #[repr(C)] -pub struct TextDisplayTextAlignmentStruct<'mc>( +pub struct VillagerType<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for TextDisplayTextAlignment<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for TextDisplayTextAlignment<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate TextDisplayTextAlignment from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/entity/TextDisplay/TextAlignment")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a TextDisplayTextAlignment object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for TextDisplayTextAlignmentStruct<'mc> { +impl<'mc> JNIRaw<'mc> for VillagerType<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -71449,22 +81181,18 @@ impl<'mc> JNIRaw<'mc> for TextDisplayTextAlignmentStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for TextDisplayTextAlignmentStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for VillagerType<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate TextDisplayTextAlignmentStruct from null object." - ) - .into()); + return Err(eyre::eyre!("Tried to instantiate VillagerType from null object.").into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/entity/TextDisplay/TextAlignment")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Villager/Type")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a TextDisplayTextAlignmentStruct object, got {}", + "Invalid argument passed. Expected a VillagerType object, got {}", name ) .into()) @@ -71474,17 +81202,71 @@ impl<'mc> JNIInstantiatable<'mc> for TextDisplayTextAlignmentStruct<'mc> { } } -impl<'mc> TextDisplayTextAlignmentStruct<'mc> { +impl<'mc> VillagerType<'mc> { + #[deprecated] + pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/TextDisplay/TextAlignment;"); - let cls = jni.find_class("org/bukkit/entity/TextDisplay/TextAlignment"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Villager/Type;"); + let cls = jni.find_class("org/bukkit/entity/Villager/Type"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::entity::TextDisplayTextAlignment::from_raw(&jni, obj) + crate::entity::VillagerType::from_raw(&jni, obj) + } + #[deprecated] + + pub fn compare_to( + &self, + other: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(LT;)I"); + let val_1 = jni::objects::JValueGen::Object(other); + let res = self.jni_ref().call_method( + &self.jni_object(), + "compareTo", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + #[deprecated] + + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "name", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + #[deprecated] + + pub fn ordinal(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "ordinal", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Return the namespaced identifier for this object. + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -71492,13 +81274,25 @@ impl<'mc> TextDisplayTextAlignmentStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for VillagerType<'mc> { + fn into(self) -> crate::util::OldEnum<'mc> { + crate::util::OldEnum::from_raw(&self.jni_ref(), self.1) + .expect("Error converting VillagerType into crate::util::OldEnum") + } +} +impl<'mc> Into> for VillagerType<'mc> { + fn into(self) -> crate::Keyed<'mc> { + crate::Keyed::from_raw(&self.jni_ref(), self.1) + .expect("Error converting VillagerType into crate::Keyed") + } +} #[repr(C)] -pub struct Egg<'mc>( +pub struct VillagerProfession<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Egg<'mc> { +impl<'mc> JNIRaw<'mc> for VillagerProfession<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -71506,18 +81300,20 @@ impl<'mc> JNIRaw<'mc> for Egg<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Egg<'mc> { +impl<'mc> JNIInstantiatable<'mc> for VillagerProfession<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Egg from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate VillagerProfession from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Egg")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Villager/Profession")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Egg object, got {}", + "Invalid argument passed. Expected a VillagerProfession object, got {}", name ) .into()) @@ -71525,105 +81321,73 @@ impl<'mc> JNIInstantiatable<'mc> for Egg<'mc> { Ok(Self(env.clone(), obj)) } } -} +} + +impl<'mc> VillagerProfession<'mc> { + #[deprecated] + + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Villager/Profession;"); + let cls = jni.find_class("org/bukkit/entity/Villager/Profession"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::VillagerProfession::from_raw(&jni, obj) + } + #[deprecated] -impl<'mc> Egg<'mc> { - /// Gets the ItemStack the thrown projectile will display. - pub fn item(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/inventory/ItemStack;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the display ItemStack for the thrown projectile. - pub fn set_item( + pub fn compare_to( &self, - item: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setItem", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + other: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(LT;)I"); + let val_1 = jni::objects::JValueGen::Object(other); + let res = self.jni_ref().call_method( + &self.jni_object(), + "compareTo", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Retrieve the shooter of this projectile. - pub fn shooter( - &self, - ) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/projectiles/ProjectileSource;"; + #[deprecated] + + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getShooter", sig.as_str(), args); + .call_method(&self.jni_object(), "name", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::projectiles::ProjectileSource::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Set the shooter of this projectile. - pub fn set_shooter( - &self, - source: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/projectiles/ProjectileSource;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(source.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")V"; - let res = self + Ok(self .jni_ref() - .call_method(&self.jni_object(), "setShooter", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } #[deprecated] - /// Determine if this projectile should bounce or not when it hits. - pub fn does_bounce(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; + + pub fn ordinal(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "doesBounce", sig.as_str(), args); + .call_method(&self.jni_object(), "ordinal", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - #[deprecated] - /// Set whether or not this projectile should bounce or not when it hits something. - pub fn set_bounce(&self, does_bounce: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(does_bounce.into()); - args.push(val_1); - sig += ")V"; + /// Return the namespaced identifier for this object. + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "setBounce", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -71631,19 +81395,25 @@ impl<'mc> Egg<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Egg<'mc> { - fn into(self) -> crate::entity::ThrowableProjectile<'mc> { - crate::entity::ThrowableProjectile::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Egg into crate::entity::ThrowableProjectile") +impl<'mc> Into> for VillagerProfession<'mc> { + fn into(self) -> crate::util::OldEnum<'mc> { + crate::util::OldEnum::from_raw(&self.jni_ref(), self.1) + .expect("Error converting VillagerProfession into crate::util::OldEnum") + } +} +impl<'mc> Into> for VillagerProfession<'mc> { + fn into(self) -> crate::Keyed<'mc> { + crate::Keyed::from_raw(&self.jni_ref(), self.1) + .expect("Error converting VillagerProfession into crate::Keyed") } } #[repr(C)] -pub struct Explosive<'mc>( +pub struct Giant<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Explosive<'mc> { +impl<'mc> JNIRaw<'mc> for Giant<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -71651,18 +81421,18 @@ impl<'mc> JNIRaw<'mc> for Explosive<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Explosive<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Giant<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Explosive from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Giant from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Explosive")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Giant")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Explosive object, got {}", + "Invalid argument passed. Expected a Giant object, got {}", name ) .into()) @@ -71672,978 +81442,961 @@ impl<'mc> JNIInstantiatable<'mc> for Explosive<'mc> { } } -impl<'mc> Explosive<'mc> { - /// Set the radius affected by this explosive's explosion - pub fn set_yield(&self, val_yield: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(val_yield); +impl<'mc> Giant<'mc> { + /// Gets the height of the living entity's eyes above its Location. + pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { + let sig = String::from("(Z)D"); + let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setYield", + "getEyeHeight", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Return the radius or yield of this explosive's explosion - pub fn get_yield(&self) -> Result> { - let sig = String::from("()F"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getYield", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Set whether or not this explosive's explosion causes fire - pub fn set_is_incendiary(&self, is_incendiary: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(is_incendiary.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setIsIncendiary", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.d()?) } - /// Return whether or not this explosive creates a fire when exploding - pub fn is_incendiary(&self) -> Result> { - let sig = String::from("()Z"); + /// Get a Location detailing the current eye position of the living entity. + pub fn eye_location(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isIncendiary", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Stores the entity's current position in the provided Location object. + /// Gets all blocks along the living entity's line of sight. /// - /// If the provided Location is null this method does nothing and returns - /// null. - pub fn get_location( + /// This list contains all blocks from the living entity's eye position to + /// target inclusive. This method considers all blocks as 1x1x1 in size. + pub fn get_line_of_sight( &self, - loc: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocation", + "getLineOfSight", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(new_vec) } - /// Sets this entity's velocity in meters per tick - pub fn set_velocity( + /// Gets the block that the living entity has targeted. + /// + /// This method considers all blocks as 1x1x1 in size. To take exact block + /// collision shapes into account, see {@link #getTargetBlockExact(int, + /// FluidCollisionMode)}. + pub fn get_target_block( &self, - velocity: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + transparent: impl Into>, + max_distance: i32, + ) -> Result, Box> { + let sig = String::from("(Ljava/util/Set;I)Lorg/bukkit/block/Block;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setVelocity", + "getTargetBlock", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets this entity's current velocity - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + crate::block::Block::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the entity's height - pub fn height(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the entity's width - pub fn width(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the entity's current bounding box. + /// Gets the last two blocks along the living entity's line of sight. /// - /// The returned bounding box reflects the entity's current location and - /// size. - pub fn bounding_box( + /// The target block will be the last block in the list. This method + /// considers all blocks as 1x1x1 in size. + pub fn get_last_two_target_blocks( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns true if the entity is supported by a block. This value is a - /// state updated by the server and is not recalculated unless the entity - /// moves. - pub fn is_on_ground(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns true if the entity is in water. - pub fn is_in_water(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the current world this entity resides in - pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the entity's rotation. - /// - /// Note that if the entity is affected by AI, it may override this rotation. - pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { - let sig = String::from("(FF)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); - let val_2 = jni::objects::JValueGen::Float(pitch); + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(max_distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setRotation", + "getLastTwoTargetBlocks", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Teleports this entity to the given location. If this entity is riding a - /// vehicle, it will be dismounted prior to teleportation. - pub fn teleport( + /// Gets the block that the living entity has targeted. + /// + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn get_target_block_exact( &self, - location: impl Into>, - cause: std::option::Option< - impl Into>, - >, - ) -> Result> { + max_distance: i32, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(max_distance); args.push(val_1); - if let Some(a) = cause { - sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; let val_2 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); args.push(val_2); } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "teleport", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns a list of entities within a bounding box centered around this - /// entity - pub fn get_nearby_entities( - &self, - x: f64, - y: f64, - z: f64, - ) -> Result>, Box> { - let sig = String::from("(DDD)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Double(x); - let val_2 = jni::objects::JValueGen::Double(y); - let val_3 = jni::objects::JValueGen::Double(z); + sig += ")Lorg/bukkit/block/Block;"; let res = self.jni_ref().call_method( &self.jni_object(), - "getNearbyEntities", + "getTargetBlockExact", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + args, ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - Ok(new_vec) + Ok(Some(crate::block::Block::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Returns a unique id for this entity - pub fn entity_id(&self) -> Result> { + /// Performs a ray trace that provides information on the targeted block. + /// + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn ray_trace_blocks( + &self, + max_distance: f64, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/util/RayTraceResult;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::util::RayTraceResult::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Returns the amount of air that the living entity has remaining, in + /// ticks. + pub fn remaining_air(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Returns the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn fire_ticks(&self) -> Result> { + /// Sets the amount of air that the living entity has remaining, in ticks. + pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRemainingAir", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the maximum amount of air the living entity can have, in ticks. + pub fn maximum_air(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Returns the entity's maximum fire ticks. - pub fn max_fire_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Sets the maximum amount of air the living entity can have, in ticks. + pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaximumAir", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the item that the player is using (eating food, drawing back a bow, + /// blocking, etc.) + pub fn item_in_use( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the number of ticks remaining for the current item's usage. + pub fn item_in_use_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItemInUseTicks", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Sets the number of ticks that remain for the current item's usage. + /// Applies to items that take time to use, like eating food, drawing a bow, + /// or throwing a trident. + pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setFireTicks", + "setItemInUseTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets if the entity has visual fire (it will always appear to be on fire). - pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire.into()); + /// Gets the time in ticks until the next arrow leaves the entity's body. + pub fn arrow_cooldown(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisualFire", + "getArrowCooldown", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the time in ticks until the next arrow leaves the entity's body. + pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setArrowCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity has visual fire (it will always appear to be on fire). - pub fn is_visual_fire(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn freeze_ticks(&self) -> Result> { + /// Gets the amount of arrows in an entity's body. + pub fn arrows_in_body(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Returns the entity's maximum freeze ticks (amount of ticks before it will - /// be fully frozen) - pub fn max_freeze_ticks(&self) -> Result> { + /// Set the amount of arrows in the entity's body. + pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(count); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setArrowsInBody", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the living entity's current maximum no damage ticks. + /// + /// This is the maximum duration in which the living entity will not take + /// damage. + pub fn maximum_no_damage_ticks(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getMaxFreezeTicks", + "getMaximumNoDamageTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Sets the living entity's current maximum no damage ticks. + pub fn set_maximum_no_damage_ticks( + &self, + ticks: i32, + ) -> Result<(), Box> { let sig = String::from("(I)V"); let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setFreezeTicks", + "setMaximumNoDamageTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity is fully frozen (it has been in powdered snow for max - /// freeze ticks). - pub fn is_frozen(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); + /// Returns the living entity's last damage taken in the current no damage + /// ticks time. + /// + /// Only damage higher than this amount will further damage the living + /// entity. + pub fn last_damage(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Mark the entity's removal. - pub fn remove(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); + /// Sets the damage dealt within the current no damage ticks time period. + pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(damage); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLastDamage", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns true if this entity has been marked for removal. - pub fn is_dead(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns false if the entity has died, been despawned for some other - /// reason, or has not been added to the world. - pub fn is_valid(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); + /// Returns the living entity's current no damage ticks. + pub fn no_damage_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNoDamageTicks", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Gets the {@link Server} that contains this Entity - pub fn server(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Server;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Server::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Sets the living entity's current no damage ticks. + pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setNoDamageTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns true if the entity gets persisted. - /// - /// By default all entities are persistent. An entity will also not get - /// persisted, if it is riding an entity that is not persistent. - /// - /// The persistent flag on players controls whether or not to save their - /// playerdata file when they quit. If a player is directly or indirectly - /// riding a non-persistent entity, the vehicle at the root and all its - /// passengers won't get persisted. + /// Get the ticks that this entity has performed no action. /// - /// This should not be confused with - /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls - /// despawning of living entities. - pub fn is_persistent(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn no_action_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNoActionTicks", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets whether or not the entity gets persisted. - pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(persistent.into()); + /// Set the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setPersistent", + "setNoActionTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. - pub fn passenger( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); + /// Gets the player identified as the killer of the living entity. + /// + /// May be null. + pub fn killer(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Entity::from_raw( + Ok(Some(crate::entity::Player::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } #[deprecated] - /// Set the passenger of a vehicle. - pub fn set_passenger( + /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. + pub fn add_potion_effect( &self, - passenger: impl Into>, + effect: impl Into>, + force: std::option::Option, ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/potion/PotionEffect;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPassenger", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets a list of passengers of this vehicle. - /// - /// The returned list will not be directly linked to the entity's current - /// passengers, and no guarantees are made as to its mutability. - pub fn passengers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + args.push(val_1); + if let Some(a) = force { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(res.z()?) } - /// Add a passenger to the vehicle. - pub fn add_passenger( + /// Returns whether the living entity already has an existing effect of + /// the given {@link PotionEffectType} applied to it. + pub fn has_potion_effect( &self, - passenger: impl Into>, + val_type: impl Into>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "addPassenger", + "hasPotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Remove a passenger from the vehicle. - pub fn remove_passenger( + /// Returns the active {@link PotionEffect} of the specified type. + /// + /// If the effect is not present on the entity then null will be returned. + pub fn get_potion_effect( &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + val_type: impl Into>, + ) -> Result>, Box> { + let sig = + String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removePassenger", + "getPotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Check if a vehicle has passengers. - pub fn is_empty(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Eject any passenger. - pub fn eject(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the distance this entity has fallen - pub fn fall_distance(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Sets the fall distance for this entity - pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(distance); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFallDistance", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::potion::PotionEffect::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - #[deprecated] - /// Record the last {@link EntityDamageEvent} inflicted on this entity - pub fn set_last_damage_cause( + /// Removes any effects present of the given {@link PotionEffectType}. + pub fn remove_potion_effect( &self, - event: impl Into>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(event.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDamageCause", + "removePotionEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. - /// This event may have been cancelled. - pub fn last_damage_cause( + /// Returns all currently active {@link PotionEffect}s on the living + /// entity. + pub fn active_potion_effects( &self, - ) -> Result>, Box> - { - let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLastDamageCause", + "getActivePotionEffects", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); } - Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Returns a unique and persistent id for this entity - pub fn unique_id( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. - pub fn ticks_lived(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. May not be less than one - /// tick. - pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(value); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTicksLived", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(new_vec) } - /// Performs the specified {@link EntityEffect} for this entity. - /// - /// This will be viewable to all players near the entity. + /// Checks whether the living entity has block line of sight to another. /// - /// If the effect is not applicable to this class of entity, it will not play. - pub fn play_effect( + /// This uses the same algorithm that hostile mobs use to find the closest + /// player. + pub fn has_line_of_sight( &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); + other: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(other.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "playEffect", + "hasLineOfSight", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the type of the entity. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity makes while swimming. - pub fn swim_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Get the {@link Sound} this entity makes when splashing in water. For most - /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_splash_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Returns if the living entity despawns when away from players or not. + /// + /// By default, animals are not removed while other mobs are. + pub fn remove_when_far_away(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimSplashSound", + "getRemoveWhenFarAway", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Get the {@link Sound} this entity makes when splashing in water at high - /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_high_speed_splash_sound( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Sets whether or not the living entity despawns when away from players + /// or not. + pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(remove.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimHighSpeedSplashSound", + "setRemoveWhenFarAway", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns whether this entity is inside a vehicle. - pub fn is_inside_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Leave the current vehicle. If the entity is currently in a vehicle (and - /// is removed from it), true will be returned, otherwise false will be - /// returned. - pub fn leave_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the vehicle that this entity is inside. If there is no vehicle, - /// null will be returned. - pub fn vehicle( + /// Gets the inventory with the equipment worn by the living entity. + pub fn equipment( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Entity::from_raw( + Ok(Some(crate::inventory::EntityEquipment::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets whether or not to display the mob's custom name client side. The - /// name will be displayed above the mob similarly to a player. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { + /// Sets whether or not the living entity can pick up items. + pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(pickup.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomNameVisible", + "setCanPickupItems", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not the mob's custom name is displayed client side. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn is_custom_name_visible(&self) -> Result> { + /// Gets if the living entity can pick up items. + pub fn can_pickup_items(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "isCustomNameVisible", + "getCanPickupItems", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(visible.into()); + /// Returns whether the entity is currently leashed. + pub fn is_leashed(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the entity that is currently leading this entity. + pub fn leash_holder(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the leash on this entity to be held by the supplied entity. + /// + /// This method has no effect on EnderDragons, Withers, Players, or Bats. + /// Non-living entities excluding leashes will not persist as leash + /// holders. + pub fn set_leash_holder( + &self, + holder: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(holder.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisibleByDefault", + "setLeashHolder", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn is_visible_by_default(&self) -> Result> { + /// Checks to see if an entity is gliding, such as using an Elytra. + pub fn is_gliding(&self) -> Result> { let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Makes entity start or stop gliding. This will work even if an Elytra + /// is not equipped, but will be reverted by the server immediately after + /// unless an event-cancelling mechanism is put in place. + pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gliding.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "isVisibleByDefault", + "setGliding", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get all players that are currently tracking this entity. - /// - /// 'Tracking' means that this entity has been sent to the player and that - /// they are receiving updates on its state. Note that the client's {@code - /// 'Entity Distance'} setting does not affect the range at which entities - /// are tracked. - pub fn tracked_by( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Checks to see if an entity is swimming. + pub fn is_swimming(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets whether the entity has a team colored (default: white) glow. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { + /// Makes entity start or stop swimming. + /// This may have unexpected results if the entity is not in water. + pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(swimming.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setGlowing", + "setSwimming", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is glowing or not. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn is_glowing(&self) -> Result> { + /// Checks to see if an entity is currently riptiding. + pub fn is_riptiding(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the entity is invulnerable or not. + /// Makes entity start or stop riptiding. /// - /// When an entity is invulnerable it can only be damaged by players in - /// creative mode. - pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { + /// Note: This does not damage attackable entities. + pub fn set_riptiding(&self, riptiding: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(riptiding.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvulnerable", + "setRiptiding", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invulnerable or not. - pub fn is_invulnerable(&self) -> Result> { + /// Returns whether this entity is slumbering. + pub fn is_sleeping(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets whether the entity is silent or not. - pub fn is_silent(&self) -> Result> { + /// Gets if the entity is climbing. + pub fn is_climbing(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the entity is silent or not. - /// - /// When an entity is silent it will not produce any sound. - pub fn set_silent(&self, flag: bool) -> Result<(), Box> { + /// Sets whether an entity will have AI. + /// The entity will be completely unable to move if it has no AI. + pub fn set_ai(&self, ai: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let val_1 = jni::objects::JValueGen::Bool(ai.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setSilent", + "setAI", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether gravity applies to this entity. - pub fn has_gravity(&self) -> Result> { + /// Checks whether an entity has AI. + /// The entity will be completely unable to move if it has no AI. + pub fn has_ai(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether gravity applies to this entity. - pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gravity.into()); + /// Makes this entity attack the given entity with a melee attack. + /// Attack damage is calculated by the server from the attributes and + /// equipment of this mob, and knockback is applied to {@code target} as + /// appropriate. + pub fn attack( + &self, + target: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(target.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setGravity", + "attack", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the period of time (in ticks) before this entity can use a portal. - pub fn portal_cooldown(&self) -> Result> { - let sig = String::from("()I"); + /// Makes this entity swing their main hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their main hand. + pub fn swing_main_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Makes this entity swing their off hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their off hand. + pub fn swing_off_hand(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Makes this entity flash red as if they were damaged. + pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); let res = self.jni_ref().call_method( &self.jni_object(), - "getPortalCooldown", + "playHurtAnimation", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the period of time (in ticks) before this entity can use a portal. - pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(cooldown); + /// Set if this entity will be subject to collisions with other entities. + /// + /// Exemptions to this rule can be managed with + /// {@link #getCollidableExemptions()} + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not working for player collisions. This + /// method should therefore only be used to set the collision status of + /// non-player entities. + /// + /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in + /// combination with a {@link Scoreboard} and a {@link Team}. + pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(collidable.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setPortalCooldown", + "setCollidable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a set of tags for this entity. + /// Gets if this entity is subject to collisions with other entities. /// - /// Entities can have no more than 1024 tags. - pub fn scoreboard_tags( + /// Some entities might be exempted from the collidable rule of this entity. + /// Use {@link #getCollidableExemptions()} to get these. + /// + /// Please note that this method returns only the custom collidable state, + /// not whether the entity is non-collidable for other reasons such as being + /// dead. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not being accurate for player collisions. + /// This method should therefore only be used to check the collision status + /// of non-player entities. + /// + /// To check the collision behavior for a player, use + /// {@link Team.Option#COLLISION_RULE} in combination with a + /// {@link Scoreboard} and a {@link Team}. + pub fn is_collidable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets a mutable set of UUIDs of the entities which are exempt from the + /// entity's collidable rule and which's collision with this entity will + /// behave the opposite of it. + /// + /// This set can be modified to add or remove exemptions. + /// + /// For example if collidable is true and an entity is in the exemptions set + /// then it will not collide with it. Similarly if collidable is false and an + /// entity is in this set then it will still collide with it. + /// + /// Note these exemptions are not (currently) persistent. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in those exemptions not being accurate for player + /// collisions. This method should therefore only be used to exempt + /// non-player entities. + /// + /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} + /// in combination with a {@link Scoreboard} and a {@link Team}. + pub fn collidable_exemptions( &self, ) -> Result, Box> { let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getScoreboardTags", + "getCollidableExemptions", sig.as_str(), vec![], ); @@ -72652,383 +82405,389 @@ impl<'mc> Explosive<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Add a tag to this entity. + /// Returns the value of the memory specified. /// - /// Entities can have no more than 1024 tags. - pub fn add_scoreboard_tag( + /// Note that the value is null when the specific entity does not have that + /// value by default. + pub fn get_memory( &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); + memory_key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "addScoreboardTag", + "getMemory", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) } - /// Removes a given tag from this entity. - pub fn remove_scoreboard_tag( + /// Sets the value of the memory specified. + /// + /// Note that the value will not be persisted when the specific entity does + /// not have that value by default. + pub fn set_memory( &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); + memory_key: impl Into>, + memory_value: jni::objects::JObject<'mc>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(memory_value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMemory", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the {@link Sound} this entity will make when damaged. + pub fn hurt_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Get the {@link Sound} this entity will make on death. + pub fn death_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Get the {@link Sound} this entity will make when falling from the given + /// height (in blocks). The sound will often differ between either a small + /// or a big fall damage sound if the height exceeds 4 blocks. + pub fn get_fall_damage_sound( + &self, + fall_height: i32, + ) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Int(fall_height); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getFallDamageSound", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity will make when falling from a small + /// height. + pub fn fall_damage_sound_small(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getFallDamageSoundSmall", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity will make when falling from a large + /// height. + pub fn fall_damage_sound_big(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getFallDamageSoundBig", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity will make when drinking the given + /// {@link ItemStack}. + pub fn get_drinking_sound( + &self, + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDrinkingSound", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity will make when eating the given + /// {@link ItemStack}. + pub fn get_eating_sound( + &self, + item_stack: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeScoreboardTag", + "getEatingSound", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the reaction of the entity when moved by a piston. - pub fn piston_move_reaction( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + /// Returns true if this entity can breathe underwater and will not take + /// suffocation damage when its air supply reaches zero. + pub fn can_breathe_underwater(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPistonMoveReaction", + "canBreatheUnderwater", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the closest cardinal {@link BlockFace} direction an entity is - /// currently facing. - /// - /// This will not return any non-cardinal directions such as - /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. - /// - /// {@link Hanging} entities will override this call and thus their behavior - /// may be different. - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Gets the entity's current pose. - /// Note that the pose is only updated at the end of a tick, so may be - /// inconsistent with other methods. eg {@link Player#isSneaking()} being - /// true does not imply the current pose will be {@link Pose#SNEAKING} - pub fn pose(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Pose;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + #[deprecated] + /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. + pub fn category( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the category of spawn to which this entity belongs. - pub fn spawn_category( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); + /// Sets whether the entity is invisible or not. + pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(invisible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getSpawnCategory", + "setInvisible", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Checks if this entity has been spawned in a world. - /// - /// Entities not spawned in a world will not tick, be sent to players, or be - /// saved to the server files. - pub fn is_in_world(&self) -> Result> { + /// Gets whether the entity is invisible or not. + pub fn is_invisible(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get this entity as an NBT string. - /// - /// This string should not be relied upon as a serializable value. - pub fn as_string(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(res.z()?) } - /// Crates an {@link EntitySnapshot} representing the current state of this entity. - pub fn create_snapshot( + /// Gets the specified attribute instance from the object. This instance will + /// be backed directly to the object and any changes will be visible at once. + pub fn get_attribute( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + attribute: impl Into>, + ) -> Result>, Box> { + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAttribute", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::EntitySnapshot::from_raw( + Ok(Some(crate::attribute::AttributeInstance::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Creates a copy of this entity and all its data. Spawns the copy at the given location. - /// - /// Note: Players cannot be copied. - pub fn copy( + /// Deals the given amount of damage to this entity from a specified + /// {@link DamageSource}. + pub fn damage( &self, - to: std::option::Option>>, - ) -> Result, Box> { + amount: f64, + damage_source: std::option::Option>>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = to { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(amount); + args.push(val_1); + if let Some(a) = damage_source { + sig += "Lorg/bukkit/damage/DamageSource;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); - args.push(val_1); + args.push(val_2); } - sig += ")Lorg/bukkit/entity/Entity;"; + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); + .call_method(&self.jni_object(), "damage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. + pub fn health(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.d()?) } - /// Sets a metadata value in the implementing object's metadata store. - pub fn set_metadata( - &self, - metadata_key: impl Into, - new_metadata_value: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) - }); + /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is + /// dead. + pub fn set_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "setMetadata", + "setHealth", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a list of previously set metadata values from the implementing - /// object's metadata store. - pub fn get_metadata( - &self, - metadata_key: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); + /// Gets the entity's absorption amount. + pub fn absorption_amount(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref().call_method( &self.jni_object(), - "getMetadata", + "getAbsorptionAmount", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::metadata::MetadataValue::from_raw( - &self.jni_ref(), - obj, - )?); - } - Ok(new_vec) + Ok(res.d()?) } - /// Tests to see whether the implementing object contains the given - /// metadata value in its metadata store. - pub fn has_metadata( - &self, - metadata_key: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); + /// Sets the entity's absorption amount. + /// + /// Note: The amount is capped to the value of + /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on + /// that attribute is currently unspecified and subject to change. + pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "hasMetadata", + "setAbsorptionAmount", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the maximum health this entity has. + pub fn max_health(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Removes the given metadata value from the implementing object's - /// metadata store. - pub fn remove_metadata( - &self, - metadata_key: impl Into, - owning_plugin: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) - }); + #[deprecated] + /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. + pub fn set_max_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "removeMetadata", + "setMaxHealth", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sends this sender multiple messages - pub fn send_message( + #[deprecated] + /// Resets the max health to the original amount. + pub fn reset_max_health(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Launches a {@link Projectile} from the ProjectileSource with an + /// initial velocity. + pub fn launch_projectile( &self, - sender: impl Into>, - messages: std::option::Option>, - ) -> Result<(), Box> { + projectile: jni::objects::JClass<'mc>, + velocity: std::option::Option>>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) - }); + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(projectile.into()); args.push(val_1); - if let Some(a) = messages { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); + if let Some(a) = velocity { + sig += "Lorg/bukkit/util/Vector;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); args.push(val_2); } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the name of this command sender - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Gets the custom name on a mob or block. If there is no name this method - /// will return null. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn custom_name(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); + sig += ")LT;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getCustomName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// Sets a custom name on a mob or block. This name will be used in death - /// messages and can be sent to the client as a nameplate over the mob. - /// - /// Setting the name to null or an empty string will clear it. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn set_custom_name( - &self, - name: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCustomName", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPersistentDataContainer", - sig.as_str(), - vec![], - ); + .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.l()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -73036,19 +82795,19 @@ impl<'mc> Explosive<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Explosive<'mc> { - fn into(self) -> crate::entity::Entity<'mc> { - crate::entity::Entity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Explosive into crate::entity::Entity") +impl<'mc> Into> for Giant<'mc> { + fn into(self) -> crate::entity::Monster<'mc> { + crate::entity::Monster::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Giant into crate::entity::Monster") } } #[repr(C)] -pub struct Vehicle<'mc>( +pub struct EnderCrystal<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Vehicle<'mc> { +impl<'mc> JNIRaw<'mc> for EnderCrystal<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -73056,18 +82815,18 @@ impl<'mc> JNIRaw<'mc> for Vehicle<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Vehicle<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EnderCrystal<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Vehicle from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate EnderCrystal from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Vehicle")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EnderCrystal")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Vehicle object, got {}", + "Invalid argument passed. Expected a EnderCrystal object, got {}", name ) .into()) @@ -73077,30 +82836,58 @@ impl<'mc> JNIInstantiatable<'mc> for Vehicle<'mc> { } } -impl<'mc> Vehicle<'mc> { - /// Gets the vehicle's velocity. - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); +impl<'mc> EnderCrystal<'mc> { + /// Return whether or not this end crystal is showing the + /// bedrock slate underneath it. + pub fn is_showing_bottom(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isShowingBottom", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + Ok(res.z()?) + } + /// Sets whether or not this end crystal is showing the + /// bedrock slate underneath it. + pub fn set_showing_bottom(&self, showing: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(showing.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setShowingBottom", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the location that this end crystal is pointing its beam to. + pub fn beam_target(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBeamTarget", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) + })?)) } - /// Sets the vehicle's velocity in meters per tick. - pub fn set_velocity( + /// Sets the location that this end crystal is pointing to. Passing a null + /// value will remove the current beam. + pub fn set_beam_target( &self, - vel: impl Into>, + location: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let sig = String::from("(Lorg/bukkit/Location;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(vel.into().jni_object().clone()) + jni::objects::JObject::from_raw(location.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVelocity", + "setBeamTarget", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -73133,6 +82920,35 @@ impl<'mc> Vehicle<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) })?)) } + /// Sets this entity's velocity in meters per tick + pub fn set_velocity( + &self, + velocity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVelocity", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets this entity's current velocity + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } /// Gets the entity's height pub fn height(&self) -> Result> { let sig = String::from("()D"); @@ -74397,19 +84213,19 @@ impl<'mc> Vehicle<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Vehicle<'mc> { +impl<'mc> Into> for EnderCrystal<'mc> { fn into(self) -> crate::entity::Entity<'mc> { crate::entity::Entity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Vehicle into crate::entity::Entity") + .expect("Error converting EnderCrystal into crate::entity::Entity") } } #[repr(C)] -pub struct GlowSquid<'mc>( +pub struct EnderDragon<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for GlowSquid<'mc> { +impl<'mc> JNIRaw<'mc> for EnderDragon<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -74417,18 +84233,18 @@ impl<'mc> JNIRaw<'mc> for GlowSquid<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for GlowSquid<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EnderDragon<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate GlowSquid from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate EnderDragon from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/GlowSquid")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EnderDragon")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a GlowSquid object, got {}", + "Invalid argument passed. Expected a EnderDragon object, got {}", name ) .into()) @@ -74438,3138 +84254,2742 @@ impl<'mc> JNIInstantiatable<'mc> for GlowSquid<'mc> { } } -impl<'mc> GlowSquid<'mc> { - /// Get the number of dark ticks remaining for this squid. - /// Bravo Six will go dark for 100 ticks (5 seconds) if damaged. - pub fn dark_ticks_remaining(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getDarkTicksRemaining", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the number of dark ticks remaining for this squid. - /// Bravo Six will go dark for 100 ticks (5 seconds) if damaged. - pub fn set_dark_ticks_remaining( +impl<'mc> EnderDragon<'mc> { + /// Gets the current phase that the dragon is performing. + pub fn phase( &self, - dark_ticks_remaining: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(dark_ticks_remaining); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setDarkTicksRemaining", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for GlowSquid<'mc> { - fn into(self) -> crate::entity::Squid<'mc> { - crate::entity::Squid::from_raw(&self.jni_ref(), self.1) - .expect("Error converting GlowSquid into crate::entity::Squid") - } -} -#[repr(C)] -pub struct SkeletonHorse<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for SkeletonHorse<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for SkeletonHorse<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate SkeletonHorse from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/SkeletonHorse")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a SkeletonHorse object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> SkeletonHorse<'mc> { - /// Returns whether this skeleton horse is trapped. - /// - /// When a horse is trapped and a player comes within 10 blocks of a trapped - /// horse, lightning will strike the horse. When struck, the skeleton trap - /// will activate, turning the horse into a skeleton horseman as well as - /// spawning three additional horsemen nearby. - pub fn is_trapped(&self) -> Result> { - let sig = String::from("()Z"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EnderDragon/Phase;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isTrapped", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets if this skeleton horse is trapped. - pub fn set_trapped(&self, trapped: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(trapped.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTrapped", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns the horse's current trap time in ticks. - /// Trap time is incremented every tick when {@link #isTrapped()} is true. - /// The horse automatically despawns when it reaches 18000 ticks. - pub fn trap_time(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTrapTime", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the trap time for the horse. - /// Values greater than 18000 will cause the horse to despawn on the next - /// tick. - pub fn set_trap_time(&self, trap_time: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(trap_time); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTrapTime", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Gets the horse's variant.A horse's variant defines its physical appearance and capabilities. Whether a horse is a regular horse, donkey, mule, or other kind of horse is determined using the variant. - pub fn variant(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Horse/Variant;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPhase", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::HorseVariant::from_raw(&self.jni_ref(), unsafe { + crate::entity::EnderDragonPhase::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - #[deprecated] - - pub fn set_variant( + /// Sets the next phase for the dragon to perform. + pub fn set_phase( &self, - variant: impl Into>, + phase: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Horse/Variant;)V"); + let sig = String::from("(Lorg/bukkit/entity/EnderDragon/Phase;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(variant.into().jni_object().clone()) + jni::objects::JObject::from_raw(phase.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVariant", + "setPhase", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the domestication level of this horse. + /// Get the {@link DragonBattle} associated with this EnderDragon. /// - /// A higher domestication level indicates that the horse is closer to - /// becoming tame. As the domestication level gets closer to the max - /// domestication level, the chance of the horse becoming tame increases. - pub fn domestication(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getDomestication", - sig.as_str(), - vec![], - ); + /// This will return null for the following reasons: + ///
    + ///
  • The EnderDragon is not in the End dimension
  • + ///
  • The EnderDragon was summoned by command/API
  • + ///
+ pub fn dragon_battle( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/boss/DragonBattle;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDragonBattle", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the domestication level of this horse. - /// - /// Setting the domestication level to a high value will increase the - /// horse's chances of becoming tame. - /// - /// Domestication level must be greater than zero and no greater than - /// the max domestication level of the horse, determined with - /// {@link #getMaxDomestication()} - pub fn set_domestication(&self, level: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(level); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setDomestication", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::boss::DragonBattle::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets the maximum domestication level of this horse. - /// - /// The higher this level is, the longer it will likely take - /// for the horse to be tamed. - pub fn max_domestication(&self) -> Result> { + /// Get the current time in ticks relative to the start of this dragon's + /// death animation. + /// If this dragon is alive, 0 will be returned. This value will never exceed + /// 200 (the length of the animation). + pub fn death_animation_ticks(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getMaxDomestication", + "getDeathAnimationTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the maximum domestication level of this horse. - /// - /// Setting a higher max domestication will increase the amount of - /// domesticating (feeding, riding, etc.) necessary in order to tame it, - /// while setting a lower max value will have the opposite effect. - /// - /// Maximum domestication must be greater than zero. - pub fn set_max_domestication(&self, level: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(level); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaxDomestication", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Gets a list of parts that belong to this complex entity + pub fn parts(&self) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getParts", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the jump strength of this horse. - /// - /// Jump strength defines how high the horse can jump. A higher jump strength - /// increases how high a jump will go. - pub fn jump_strength(&self) -> Result> { - let sig = String::from("()D"); + /// Gets the height of the living entity's eyes above its Location. + pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); + args.push(val_1); + sig += ")D"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getJumpStrength", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEyeHeight", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.d()?) } - /// Sets the jump strength of this horse. - /// - /// A higher jump strength increases how high a jump will go. - /// Setting a jump strength to 0 will result in no jump. - /// You cannot set a jump strength to a value below 0 or - /// above 2. - pub fn set_jump_strength(&self, strength: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(strength); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setJumpStrength", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether the horse is currently grazing hay. - pub fn is_eating_haystack(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isEatingHaystack", - sig.as_str(), - vec![], - ); + /// Get a Location detailing the current eye position of the living entity. + pub fn eye_location(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Location;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether the horse is grazing hay. - pub fn set_eating_haystack( - &self, - eating_haystack: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(eating_haystack.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setEatingHaystack", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - - pub fn inventory( + /// Gets all blocks along the living entity's line of sight. + /// + /// This list contains all blocks from the living entity's eye position to + /// target inclusive. This method considers all blocks as 1x1x1 in size. + pub fn get_line_of_sight( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/AbstractHorseInventory;"); + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/util/Set;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); + args.push(val_1); + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(max_distance); + args.push(val_2); + sig += ")Ljava/util/List;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLineOfSight", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::inventory::AbstractHorseInventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Gets the vehicle's velocity. - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); + /// Gets the block that the living entity has targeted. + /// + /// This method considers all blocks as 1x1x1 in size. To take exact block + /// collision shapes into account, see {@link #getTargetBlockExact(int, + /// FluidCollisionMode)}. + pub fn get_target_block( + &self, + transparent: impl Into>, + max_distance: i32, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/util/Set;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); + args.push(val_1); + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(max_distance); + args.push(val_2); + sig += ")Lorg/bukkit/block/Block;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTargetBlock", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + crate::block::Block::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the vehicle's velocity in meters per tick. - pub fn set_velocity( + /// Gets the last two blocks along the living entity's line of sight. + /// + /// The target block will be the last block in the list. This method + /// considers all blocks as 1x1x1 in size. + pub fn get_last_two_target_blocks( &self, - vel: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/util/Set;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(vel.into().jni_object().clone()) + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) }); + args.push(val_1); + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(max_distance); + args.push(val_2); + sig += ")Ljava/util/List;"; let res = self.jni_ref().call_method( &self.jni_object(), - "setVelocity", + "getLastTwoTargetBlocks", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Check if this is tamed - /// - /// If something is tamed then a player can not tame it through normal - /// methods, even if it does not belong to anyone in particular. - pub fn is_tamed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isTamed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Sets if this has been tamed. Not necessary if the method setOwner has - /// been used, as it tames automatically. + /// Gets the block that the living entity has targeted. /// - /// If something is tamed then a player can not tame it through normal - /// methods, even if it does not belong to anyone in particular. - pub fn set_tamed(&self, tame: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(tame.into()); + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn get_target_block_exact( + &self, + max_distance: i32, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/block/Block;"; let res = self.jni_ref().call_method( &self.jni_object(), - "setTamed", + "getTargetBlockExact", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the current owning AnimalTamer - pub fn owner( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/AnimalTamer;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::AnimalTamer::from_raw( + Ok(Some(crate::block::Block::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Set this to be owned by given AnimalTamer. + /// Performs a ray trace that provides information on the targeted block. /// - /// If the owner is not null, this will be tamed and will have any current - /// path it is following removed. If the owner is set to null, this will be - /// untamed, and the current owner removed. - pub fn set_owner( + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn ray_trace_blocks( &self, - tamer: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/AnimalTamer;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tamer.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setOwner", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for SkeletonHorse<'mc> { - fn into(self) -> crate::entity::AbstractHorse<'mc> { - crate::entity::AbstractHorse::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SkeletonHorse into crate::entity::AbstractHorse") - } -} -#[repr(C)] -pub struct FishHook<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for FishHook<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for FishHook<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate FishHook from null object.").into()); + max_distance: f64, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/FishHook")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a FishHook object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + sig += ")Lorg/bukkit/util/RayTraceResult;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some(crate::util::RayTraceResult::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } -} - -impl<'mc> FishHook<'mc> { - /// Get the minimum number of ticks one has to wait for a fish appearing. - /// - /// The default is 100 ticks (5 seconds). - /// - /// Note that this is before applying lure. - pub fn min_wait_time(&self) -> Result> { - let sig = String::from("()I"); + /// Returns the amount of air that the living entity has remaining, in + /// ticks. + pub fn remaining_air(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getMinWaitTime", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Set the minimum number of ticks one has to wait for a fish appearing. - /// - /// The default is 100 ticks (5 seconds). - /// - /// Note that this is before applying lure. - pub fn set_min_wait_time(&self, min_wait_time: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(min_wait_time); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMinWaitTime", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Sets the amount of air that the living entity has remaining, in ticks. + pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setRemainingAir", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the maximum number of ticks one has to wait for a fish appearing. - /// - /// The default is 600 ticks (30 seconds). - /// - /// Note that this is before applying lure. - pub fn max_wait_time(&self) -> Result> { - let sig = String::from("()I"); + /// Returns the maximum amount of air the living entity can have, in ticks. + pub fn maximum_air(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxWaitTime", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Set the maximum number of ticks one has to wait for a fish appearing. - /// - /// The default is 600 ticks (30 seconds). - /// - /// Note that this is before applying lure. - pub fn set_max_wait_time(&self, max_wait_time: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(max_wait_time); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaxWaitTime", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Sets the maximum amount of air the living entity can have, in ticks. + pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setMaximumAir", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Set both the minimum (default 100) and maximum (default 600) amount - /// of ticks one has to wait for a fish appearing. - pub fn set_wait_time(&self, min: i32, max: i32) -> Result<(), Box> { - let sig = String::from("(II)V"); - let val_1 = jni::objects::JValueGen::Int(min); - let val_2 = jni::objects::JValueGen::Int(max); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setWaitTime", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Gets the item that the player is using (eating food, drawing back a bow, + /// blocking, etc.) + pub fn item_in_use( + &self, + ) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/inventory/ItemStack;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Get the minimum number of ticks one has to wait for a fish to bite - /// after appearing. - /// - /// The default is 20 ticks (1 second). - /// - /// Lure does not affect this value. - /// This will also effect the radius (0.1 * lureTime) of where - /// the fish will appear. - pub fn min_lure_time(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the number of ticks remaining for the current item's usage. + pub fn item_in_use_ticks(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getMinLureTime", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItemInUseTicks", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Set the minimum number of ticks one has to wait for a fish to bite - /// after appearing. - /// - /// The default is 20 ticks (1 second). - /// - /// Lure does not affect this value. - /// This will also effect the radius (0.1 * lureTime) of where - /// the fish will appear. - pub fn set_min_lure_time(&self, min_lure_time: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(min_lure_time); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMinLureTime", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Sets the number of ticks that remain for the current item's usage. + /// Applies to items that take time to use, like eating food, drawing a bow, + /// or throwing a trident. + pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setItemInUseTicks", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the maximum number of ticks one has to wait for a fish to bite - /// after appearing. - /// - /// The default is 80 ticks (4 second). - /// - /// Lure does not affect this value. - /// This will also effect the radius (0.1 * lureTime) of where - /// the fish will appear. - pub fn max_lure_time(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the time in ticks until the next arrow leaves the entity's body. + pub fn arrow_cooldown(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxLureTime", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getArrowCooldown", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Set the maximum number of ticks one has to wait for a fish to bite - /// after appearing. - /// - /// The default is 80 ticks (4 second). - /// - /// Lure does not affect this value. - /// This will also effect the radius (0.1 * lureTime) of where - /// the fish will appear. - pub fn set_max_lure_time(&self, max_lure_time: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(max_lure_time); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaxLureTime", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Set both the minimum (default 20) and maximum (default 80) amount - /// of ticks one has to wait for a fish to bite after appearing. - pub fn set_lure_time(&self, min: i32, max: i32) -> Result<(), Box> { - let sig = String::from("(II)V"); - let val_1 = jni::objects::JValueGen::Int(min); - let val_2 = jni::objects::JValueGen::Int(max); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLureTime", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + /// Sets the time in ticks until the next arrow leaves the entity's body. + pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setArrowCooldown", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the minimum angle (in degrees, 0 being positive Z 90 being negative - /// X) of where a fish will appear after the wait time. - /// - /// The default is 0 degrees. - pub fn min_lure_angle(&self) -> Result> { - let sig = String::from("()F"); + /// Gets the amount of arrows in an entity's body. + pub fn arrows_in_body(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getMinLureAngle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Set the minimum angle (in degrees, 0 being positive Z 90 being negative - /// X) of where a fish will appear after the wait time. - /// - /// The default is 0 degrees. - pub fn set_min_lure_angle( - &self, - min_lure_angle: f32, - ) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(min_lure_angle); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMinLureAngle", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.i()?) } - /// Get the maximum angle (in degrees, 0 being positive Z 90 being negative - /// X) of where a fish will appear after the wait time. - /// - /// The default is 360 degrees. - pub fn max_lure_angle(&self) -> Result> { - let sig = String::from("()F"); + /// Set the amount of arrows in the entity's body. + pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(count); + args.push(val_1); + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxLureAngle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + .call_method(&self.jni_object(), "setArrowsInBody", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Set the maximum angle (in degrees, 0 being positive Z 90 being negative - /// X) of where a fish will appear after the wait time. - /// - /// The default is 360 degrees. - pub fn set_max_lure_angle( - &self, - max_lure_angle: f32, - ) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(max_lure_angle); + /// Returns the living entity's current maximum no damage ticks. + /// + /// This is the maximum duration in which the living entity will not take + /// damage. + pub fn maximum_no_damage_ticks(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxLureAngle", + "getMaximumNoDamageTicks", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Set both the minimum (default 0) and maximum (default 360) angle of where - /// a fish will appear after the wait time. - /// 0 degrees is positive Z, 90 degrees is negative X. - pub fn set_lure_angle(&self, min: f32, max: f32) -> Result<(), Box> { - let sig = String::from("(FF)V"); - let val_1 = jni::objects::JValueGen::Float(min); - let val_2 = jni::objects::JValueGen::Float(max); + /// Sets the living entity's current maximum no damage ticks. + pub fn set_maximum_no_damage_ticks( + &self, + ticks: i32, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); + args.push(val_1); + sig += ")V"; let res = self.jni_ref().call_method( &self.jni_object(), - "setLureAngle", + "setMaximumNoDamageTicks", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + args, ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get whether the lure enchantment should be applied to reduce the wait - /// time. - /// - /// The default is true. + /// Returns the living entity's last damage taken in the current no damage + /// ticks time. /// - /// Lure reduces the wait time by 100 ticks (5 seconds) for each level of the - /// enchantment. - pub fn apply_lure(&self) -> Result> { - let sig = String::from("()Z"); + /// Only damage higher than this amount will further damage the living + /// entity. + pub fn last_damage(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")D"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getApplyLure", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Set whether the lure enchantment should be applied to reduce the wait - /// time. - /// - /// The default is true. - /// - /// Lure reduces the wait time by 100 ticks (5 seconds) for each level of the - /// enchantment. - pub fn set_apply_lure(&self, apply_lure: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(apply_lure.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setApplyLure", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Sets the damage dealt within the current no damage ticks time period. + pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(damage); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setLastDamage", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the chance of a fish biting.0.0 = No Chance. - /// - /// 1.0 = Instant catch. - pub fn bite_chance(&self) -> Result> { - let sig = String::from("()D"); + /// Returns the living entity's current no damage ticks. + pub fn no_damage_ticks(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getBiteChance", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getNoDamageTicks", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.i()?) } - #[deprecated] - /// Sets the chance of a fish biting.0.0 = No Chance. - /// - /// 1.0 = Instant catch. - pub fn set_bite_chance(&self, chance: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(chance); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setBiteChance", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Sets the living entity's current no damage ticks. + pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setNoDamageTicks", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check whether or not this fish hook is in open water. + /// Get the ticks that this entity has performed no action. /// - /// Open water is defined by a 5x4x5 area of water, air and lily pads. If in - /// open water, treasure items may be caught. - pub fn is_in_open_water(&self) -> Result> { - let sig = String::from("()Z"); + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn no_action_ticks(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; let res = self.jni_ref() - .call_method(&self.jni_object(), "isInOpenWater", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getNoActionTicks", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Get the entity hooked by this fish hook. - pub fn hooked_entity( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + /// Set the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); + args.push(val_1); + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getHookedEntity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "setNoActionTicks", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the player identified as the killer of the living entity. + /// + /// May be null. + pub fn killer(&self) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/entity/Player;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKiller", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Entity::from_raw( + Ok(Some(crate::entity::Player::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Set the entity hooked by this fish hook. - pub fn set_hooked_entity( + #[deprecated] + /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. + pub fn add_potion_effect( &self, - entity: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + effect: impl Into>, + force: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/potion/PotionEffect;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setHookedEntity", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Pull the hooked entity to the caster of this fish hook. If no entity is - /// hooked, this method has no effect. - pub fn pull_hooked_entity(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "pullHookedEntity", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Whether or not wait and lure time will be impacted by direct sky access. - /// True by default, causes a 50% time increase on average. - pub fn is_sky_influenced(&self) -> Result> { - let sig = String::from("()Z"); + args.push(val_1); + if let Some(a) = force { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "isSkyInfluenced", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set whether or not wait and lure time will be impacted by direct sky - /// access. - /// True by default, causes a 50% time increase on average. - pub fn set_sky_influenced( + /// Returns whether the living entity already has an existing effect of + /// the given {@link PotionEffectType} applied to it. + pub fn has_potion_effect( &self, - sky_influenced: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(sky_influenced.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSkyInfluenced", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Whether or not wait and lure time will be impacted by rain. - /// True by default, causes a 25% time decrease on average. - pub fn is_rain_influenced(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isRainInfluenced", - sig.as_str(), - vec![], - ); + val_type: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/potion/PotionEffectType;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasPotionEffect", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set whether or not wait and lure time will be impacted by rain. - /// True by default, causes a 25% time decrease on average. - pub fn set_rain_influenced( - &self, - rain_influenced: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(rain_influenced.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRainInfluenced", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the current state of this fish hook. - pub fn state( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/FishHook/HookState;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getState", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::FishHookHookState::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Retrieve the shooter of this projectile. - pub fn shooter( + /// Returns the active {@link PotionEffect} of the specified type. + /// + /// If the effect is not present on the entity then null will be returned. + pub fn get_potion_effect( &self, - ) -> Result>, Box> { - let args = Vec::new(); + val_type: impl Into>, + ) -> Result>, Box> { + let mut args = Vec::new(); let mut sig = String::from("("); - sig += ")Lorg/bukkit/projectiles/ProjectileSource;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getShooter", sig.as_str(), args); + sig += "Lorg/bukkit/potion/PotionEffectType;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Lorg/bukkit/potion/PotionEffect;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPotionEffect", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::projectiles::ProjectileSource::from_raw( + Ok(Some(crate::potion::PotionEffect::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Set the shooter of this projectile. - pub fn set_shooter( + /// Removes any effects present of the given {@link PotionEffectType}. + pub fn remove_potion_effect( &self, - source: impl Into>, + val_type: impl Into>, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/projectiles/ProjectileSource;"; + sig += "Lorg/bukkit/potion/PotionEffectType;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(source.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); args.push(val_1); sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setShooter", sig.as_str(), args); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removePotionEffect", + sig.as_str(), + args, + ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Determine if this projectile should bounce or not when it hits. - pub fn does_bounce(&self) -> Result> { + /// Returns all currently active {@link PotionEffect}s on the living + /// entity. + pub fn active_potion_effects( + &self, + ) -> Result>, Box> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "doesBounce", sig.as_str(), args); + sig += ")Ljava/util/Collection;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getActivePotionEffects", + sig.as_str(), + args, + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - #[deprecated] - /// Set whether or not this projectile should bounce or not when it hits something. - pub fn set_bounce(&self, does_bounce: bool) -> Result<(), Box> { + /// Checks whether the living entity has block line of sight to another. + /// + /// This uses the same algorithm that hostile mobs use to find the closest + /// player. + pub fn has_line_of_sight( + &self, + other: impl Into>, + ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(does_bounce.into()); + sig += "Lorg/bukkit/entity/Entity;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(other.into().jni_object().clone()) + }); args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setBounce", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasLineOfSight", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Stores the entity's current position in the provided Location object. + /// Returns if the living entity despawns when away from players or not. /// - /// If the provided Location is null this method does nothing and returns - /// null. - pub fn get_location( - &self, - loc: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) - }); + /// By default, animals are not removed while other mobs are. + pub fn remove_when_far_away(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self.jni_ref().call_method( &self.jni_object(), - "getLocation", + "getRemoveWhenFarAway", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.z()?) } - /// Sets this entity's velocity in meters per tick - pub fn set_velocity( - &self, - velocity: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) - }); + /// Sets whether or not the living entity despawns when away from players + /// or not. + pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(remove.into()); + args.push(val_1); + sig += ")V"; let res = self.jni_ref().call_method( &self.jni_object(), - "setVelocity", + "setRemoveWhenFarAway", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets this entity's current velocity - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); + /// Gets the inventory with the equipment worn by the living entity. + pub fn equipment( + &self, + ) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/inventory/EntityEquipment;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the entity's height - pub fn height(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the entity's width - pub fn width(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEquipment", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::EntityEquipment::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets the entity's current bounding box. - /// - /// The returned bounding box reflects the entity's current location and - /// size. - pub fn bounding_box( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); + /// Sets whether or not the living entity can pick up items. + pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(pickup.into()); + args.push(val_1); + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + .call_method(&self.jni_object(), "setCanPickupItems", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns true if the entity is supported by a block. This value is a - /// state updated by the server and is not recalculated unless the entity - /// moves. - pub fn is_on_ground(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets if the living entity can pick up items. + pub fn can_pickup_items(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCanPickupItems", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns true if the entity is in water. - pub fn is_in_water(&self) -> Result> { - let sig = String::from("()Z"); + /// Returns whether the entity is currently leashed. + pub fn is_leashed(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isLeashed", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the current world this entity resides in - pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + /// Gets the entity that is currently leading this entity. + pub fn leash_holder(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/entity/Entity;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the entity's rotation. + /// Sets the leash on this entity to be held by the supplied entity. /// - /// Note that if the entity is affected by AI, it may override this rotation. - pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { - let sig = String::from("(FF)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); - let val_2 = jni::objects::JValueGen::Float(pitch); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRotation", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Teleports this entity to the given location. If this entity is riding a - /// vehicle, it will be dismounted prior to teleportation. - pub fn teleport( + /// This method has no effect on EnderDragons, Withers, Players, or Bats. + /// Non-living entities excluding leashes will not persist as leash + /// holders. + pub fn set_leash_holder( &self, - location: impl Into>, - cause: std::option::Option< - impl Into>, - >, + holder: impl Into>, ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; + sig += "Lorg/bukkit/entity/Entity;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) + jni::objects::JObject::from_raw(holder.into().jni_object().clone()) }); args.push(val_1); - if let Some(a) = cause { - sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "teleport", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns a list of entities within a bounding box centered around this - /// entity - pub fn get_nearby_entities( - &self, - x: f64, - y: f64, - z: f64, - ) -> Result>, Box> { - let sig = String::from("(DDD)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Double(x); - let val_2 = jni::objects::JValueGen::Double(y); - let val_3 = jni::objects::JValueGen::Double(z); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getNearbyEntities", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Returns a unique id for this entity - pub fn entity_id(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn fire_ticks(&self) -> Result> { - let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "setLeashHolder", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Returns the entity's maximum fire ticks. - pub fn max_fire_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + /// Checks to see if an entity is gliding, such as using an Elytra. + pub fn is_gliding(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGliding", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFireTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Makes entity start or stop gliding. This will work even if an Elytra + /// is not equipped, but will be reverted by the server immediately after + /// unless an event-cancelling mechanism is put in place. + pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(gliding.into()); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setGliding", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets if the entity has visual fire (it will always appear to be on fire). - pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setVisualFire", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Checks to see if an entity is swimming. + pub fn is_swimming(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSwimming", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Makes entity start or stop swimming. + /// This may have unexpected results if the entity is not in water. + pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(swimming.into()); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setSwimming", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity has visual fire (it will always appear to be on fire). - pub fn is_visual_fire(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); + /// Checks to see if an entity is currently riptiding. + pub fn is_riptiding(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Makes entity start or stop riptiding. + /// + /// Note: This does not damage attackable entities. + pub fn set_riptiding(&self, riptiding: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(riptiding.into()); + args.push(val_1); + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the entity's maximum freeze ticks (amount of ticks before it will - /// be fully frozen) - pub fn max_freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMaxFreezeTicks", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFreezeTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "setRiptiding", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity is fully frozen (it has been in powdered snow for max - /// freeze ticks). - pub fn is_frozen(&self) -> Result> { - let sig = String::from("()Z"); + /// Returns whether this entity is slumbering. + pub fn is_sleeping(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSleeping", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Mark the entity's removal. - pub fn remove(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Gets if the entity is climbing. + pub fn is_climbing(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "isClimbing", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Returns true if this entity has been marked for removal. - pub fn is_dead(&self) -> Result> { - let sig = String::from("()Z"); + /// Sets whether an entity will have AI. + /// The entity will be completely unable to move if it has no AI. + pub fn set_ai(&self, ai: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(ai.into()); + args.push(val_1); + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + .call_method(&self.jni_object(), "setAI", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns false if the entity has died, been despawned for some other - /// reason, or has not been added to the world. - pub fn is_valid(&self) -> Result> { - let sig = String::from("()Z"); + /// Checks whether an entity has AI. + /// The entity will be completely unable to move if it has no AI. + pub fn has_ai(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasAI", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the {@link Server} that contains this Entity - pub fn server(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Server;"); + /// Makes this entity attack the given entity with a melee attack. + /// Attack damage is calculated by the server from the attributes and + /// equipment of this mob, and knockback is applied to {@code target} as + /// appropriate. + pub fn attack( + &self, + target: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Entity;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(target.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Server::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + .call_method(&self.jni_object(), "attack", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns true if the entity gets persisted. - /// - /// By default all entities are persistent. An entity will also not get - /// persisted, if it is riding an entity that is not persistent. - /// - /// The persistent flag on players controls whether or not to save their - /// playerdata file when they quit. If a player is directly or indirectly - /// riding a non-persistent entity, the vehicle at the root and all its - /// passengers won't get persisted. - /// - /// This should not be confused with - /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls - /// despawning of living entities. - pub fn is_persistent(&self) -> Result> { - let sig = String::from("()Z"); + /// Makes this entity swing their main hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their main hand. + pub fn swing_main_hand(&self) -> Result<(), Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets whether or not the entity gets persisted. - pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(persistent.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPersistent", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Makes this entity swing their off hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their off hand. + pub fn swing_off_hand(&self) -> Result<(), Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. - pub fn passenger( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + /// Makes this entity flash red as if they were damaged. + pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "F"; + let val_1 = jni::objects::JValueGen::Float(yaw); + args.push(val_1); + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + .call_method(&self.jni_object(), "playHurtAnimation", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - #[deprecated] - /// Set the passenger of a vehicle. - pub fn set_passenger( - &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPassenger", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Set if this entity will be subject to collisions with other entities. + /// + /// Exemptions to this rule can be managed with + /// {@link #getCollidableExemptions()} + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not working for player collisions. This + /// method should therefore only be used to set the collision status of + /// non-player entities. + /// + /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in + /// combination with a {@link Scoreboard} and a {@link Team}. + pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(collidable.into()); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setCollidable", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets a list of passengers of this vehicle. + /// Gets if this entity is subject to collisions with other entities. /// - /// The returned list will not be directly linked to the entity's current - /// passengers, and no guarantees are made as to its mutability. - pub fn passengers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + /// Some entities might be exempted from the collidable rule of this entity. + /// Use {@link #getCollidableExemptions()} to get these. + /// + /// Please note that this method returns only the custom collidable state, + /// not whether the entity is non-collidable for other reasons such as being + /// dead. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not being accurate for player collisions. + /// This method should therefore only be used to check the collision status + /// of non-player entities. + /// + /// To check the collision behavior for a player, use + /// {@link Team.Option#COLLISION_RULE} in combination with a + /// {@link Scoreboard} and a {@link Team}. + pub fn is_collidable(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCollidable", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(res.z()?) } - /// Add a passenger to the vehicle. - pub fn add_passenger( + /// Gets a mutable set of UUIDs of the entities which are exempt from the + /// entity's collidable rule and which's collision with this entity will + /// behave the opposite of it. + /// + /// This set can be modified to add or remove exemptions. + /// + /// For example if collidable is true and an entity is in the exemptions set + /// then it will not collide with it. Similarly if collidable is false and an + /// entity is in this set then it will still collide with it. + /// + /// Note these exemptions are not (currently) persistent. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in those exemptions not being accurate for player + /// collisions. This method should therefore only be used to exempt + /// non-player entities. + /// + /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} + /// in combination with a {@link Scoreboard} and a {@link Team}. + pub fn collidable_exemptions( &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); + ) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/util/Set;"; let res = self.jni_ref().call_method( &self.jni_object(), - "addPassenger", + "getCollidableExemptions", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Remove a passenger from the vehicle. - pub fn remove_passenger( + /// Returns the value of the memory specified. + /// + /// Note that the value is null when the specific entity does not have that + /// value by default. + pub fn get_memory( &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + memory_key: impl Into>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/memory/MemoryKey;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removePassenger", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Check if a vehicle has passengers. - pub fn is_empty(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Eject any passenger. - pub fn eject(&self) -> Result> { - let sig = String::from("()Z"); + args.push(val_1); + sig += ")LT;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the distance this entity has fallen - pub fn fall_distance(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMemory", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Sets the fall distance for this entity - pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(distance); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFallDistance", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) } - #[deprecated] - /// Record the last {@link EntityDamageEvent} inflicted on this entity - pub fn set_last_damage_cause( + /// Sets the value of the memory specified. + /// + /// Note that the value will not be persisted when the specific entity does + /// not have that value by default. + pub fn set_memory( &self, - event: impl Into>, + memory_key: impl Into>, + memory_value: jni::objects::JObject<'mc>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/memory/MemoryKey;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(event.into().jni_object().clone()) + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLastDamageCause", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + sig += "LT;"; + let val_2 = jni::objects::JValueGen::Object(memory_value); + args.push(val_2); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setMemory", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. - /// This event may have been cancelled. - pub fn last_damage_cause( - &self, - ) -> Result>, Box> - { - let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLastDamageCause", - sig.as_str(), - vec![], - ); + /// Get the {@link Sound} this entity will make when damaged. + pub fn hurt_sound(&self) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Sound;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Returns a unique and persistent id for this entity - pub fn unique_id( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); + /// Get the {@link Sound} this entity will make on death. + pub fn death_sound(&self) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) + })?)) } - /// Gets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. - pub fn ticks_lived(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); + /// Get the {@link Sound} this entity will make when falling from the given + /// height (in blocks). The sound will often differ between either a small + /// or a big fall damage sound if the height exceeds 4 blocks. + pub fn get_fall_damage_sound( + &self, + fall_height: i32, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(fall_height); + args.push(val_1); + sig += ")Lorg/bukkit/Sound;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getFallDamageSound", + sig.as_str(), + args, + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. May not be less than one - /// tick. - pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(value); + /// Get the {@link Sound} this entity will make when falling from a small + /// height. + pub fn fall_damage_sound_small(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref().call_method( &self.jni_object(), - "setTicksLived", + "getFallDamageSoundSmall", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Performs the specified {@link EntityEffect} for this entity. - /// - /// This will be viewable to all players near the entity. - /// - /// If the effect is not applicable to this class of entity, it will not play. - pub fn play_effect( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Get the {@link Sound} this entity will make when falling from a large + /// height. + pub fn fall_damage_sound_big(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref().call_method( &self.jni_object(), - "playEffect", + "getFallDamageSoundBig", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the type of the entity. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the {@link Sound} this entity makes while swimming. - pub fn swim_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Get the {@link Sound} this entity will make when drinking the given + /// {@link ItemStack}. + pub fn get_drinking_sound( + &self, + item_stack: impl Into>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDrinkingSound", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the {@link Sound} this entity makes when splashing in water. For most - /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_splash_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSwimSplashSound", - sig.as_str(), - vec![], - ); + /// Get the {@link Sound} this entity will make when eating the given + /// {@link ItemStack}. + pub fn get_eating_sound( + &self, + item_stack: impl Into>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Lorg/bukkit/Sound;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEatingSound", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the {@link Sound} this entity makes when splashing in water at high - /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_high_speed_splash_sound( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Returns true if this entity can breathe underwater and will not take + /// suffocation damage when its air supply reaches zero. + pub fn can_breathe_underwater(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimHighSpeedSplashSound", + "canBreatheUnderwater", sig.as_str(), - vec![], + args, ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { + Ok(res.z()?) + } + #[deprecated] + /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. + pub fn category( + &self, + ) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/entity/EntityCategory;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCategory", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns whether this entity is inside a vehicle. - pub fn is_inside_vehicle(&self) -> Result> { - let sig = String::from("()Z"); + /// Sets whether the entity is invisible or not. + pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(invisible.into()); + args.push(val_1); + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + .call_method(&self.jni_object(), "setInvisible", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Leave the current vehicle. If the entity is currently in a vehicle (and - /// is removed from it), true will be returned, otherwise false will be - /// returned. - pub fn leave_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); + /// Gets whether the entity is invisible or not. + pub fn is_invisible(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInvisible", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get the vehicle that this entity is inside. If there is no vehicle, - /// null will be returned. - pub fn vehicle( + /// Returns the {@link BossBar} of the {@link Boss} + pub fn boss_bar( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/boss/BossBar;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBossBar", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Entity::from_raw( + Ok(Some(crate::boss::BossBar::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets whether or not to display the mob's custom name client side. The - /// name will be displayed above the mob similarly to a player. + /// Stores the entity's current position in the provided Location object. /// - /// This value has no effect on players, they will always display their - /// name. - pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// If the provided Location is null this method does nothing and returns + /// null. + pub fn get_location( + &self, + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomNameVisible", + "getLocation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether or not the mob's custom name is displayed client side. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn is_custom_name_visible(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isCustomNameVisible", - sig.as_str(), - vec![], - ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Sets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(visible.into()); + /// Sets this entity's velocity in meters per tick + pub fn set_velocity( + &self, + velocity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisibleByDefault", + "setVelocity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn is_visible_by_default(&self) -> Result> { + /// Gets this entity's current velocity + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the entity's height + pub fn height(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the entity's width + pub fn width(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the entity's current bounding box. + /// + /// The returned bounding box reflects the entity's current location and + /// size. + pub fn bounding_box( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns true if the entity is supported by a block. This value is a + /// state updated by the server and is not recalculated unless the entity + /// moves. + pub fn is_on_ground(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isVisibleByDefault", - sig.as_str(), - vec![], - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns true if the entity is in water. + pub fn is_in_water(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get all players that are currently tracking this entity. - /// - /// 'Tracking' means that this entity has been sent to the player and that - /// they are receiving updates on its state. Note that the client's {@code - /// 'Entity Distance'} setting does not affect the range at which entities - /// are tracked. - pub fn tracked_by( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); + /// Gets the current world this entity resides in + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + crate::World::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets whether the entity has a team colored (default: white) glow. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Sets the entity's rotation. + /// + /// Note that if the entity is affected by AI, it may override this rotation. + pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { + let sig = String::from("(FF)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); + let val_2 = jni::objects::JValueGen::Float(pitch); let res = self.jni_ref().call_method( &self.jni_object(), - "setGlowing", + "setRotation", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is glowing or not. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn is_glowing(&self) -> Result> { - let sig = String::from("()Z"); + /// Teleports this entity to the given location. If this entity is riding a + /// vehicle, it will be dismounted prior to teleportation. + pub fn teleport( + &self, + location: impl Into>, + cause: std::option::Option< + impl Into>, + >, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = cause { + sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "teleport", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the entity is invulnerable or not. - /// - /// When an entity is invulnerable it can only be damaged by players in - /// creative mode. - pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Returns a list of entities within a bounding box centered around this + /// entity + pub fn get_nearby_entities( + &self, + x: f64, + y: f64, + z: f64, + ) -> Result>, Box> { + let sig = String::from("(DDD)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Double(x); + let val_2 = jni::objects::JValueGen::Double(y); + let val_3 = jni::objects::JValueGen::Double(z); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvulnerable", + "getNearbyEntities", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Gets whether the entity is invulnerable or not. - pub fn is_invulnerable(&self) -> Result> { - let sig = String::from("()Z"); + /// Returns a unique id for this entity + pub fn entity_id(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Gets whether the entity is silent or not. - pub fn is_silent(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + /// Returns the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets whether the entity is silent or not. - /// - /// When an entity is silent it will not produce any sound. - pub fn set_silent(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Returns the entity's maximum fire ticks. + pub fn max_fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setSilent", + "setFireTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether gravity applies to this entity. - pub fn has_gravity(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether gravity applies to this entity. - pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { + /// Sets if the entity has visual fire (it will always appear to be on fire). + pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gravity.into()); + let val_1 = jni::objects::JValueGen::Bool(fire.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setGravity", + "setVisualFire", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the period of time (in ticks) before this entity can use a portal. - pub fn portal_cooldown(&self) -> Result> { + /// Gets if the entity has visual fire (it will always appear to be on fire). + pub fn is_visual_fire(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's maximum freeze ticks (amount of ticks before it will + /// be fully frozen) + pub fn max_freeze_ticks(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPortalCooldown", + "getMaxFreezeTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the period of time (in ticks) before this entity can use a portal. - pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { + /// Sets the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(cooldown); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setPortalCooldown", + "setFreezeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a set of tags for this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn scoreboard_tags( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getScoreboardTags", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Add a tag to this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn add_scoreboard_tag( - &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addScoreboardTag", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Removes a given tag from this entity. - pub fn remove_scoreboard_tag( - &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removeScoreboardTag", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Gets if the entity is fully frozen (it has been in powdered snow for max + /// freeze ticks). + pub fn is_frozen(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns the reaction of the entity when moved by a piston. - pub fn piston_move_reaction( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPistonMoveReaction", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Mark the entity's removal. + pub fn remove(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the closest cardinal {@link BlockFace} direction an entity is - /// currently facing. - /// - /// This will not return any non-cardinal directions such as - /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. - /// - /// {@link Hanging} entities will override this call and thus their behavior - /// may be different. - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + /// Returns true if this entity has been marked for removal. + pub fn is_dead(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Gets the entity's current pose. - /// Note that the pose is only updated at the end of a tick, so may be - /// inconsistent with other methods. eg {@link Player#isSneaking()} being - /// true does not imply the current pose will be {@link Pose#SNEAKING} - pub fn pose(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Pose;"); + /// Returns false if the entity has died, been despawned for some other + /// reason, or has not been added to the world. + pub fn is_valid(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Get the category of spawn to which this entity belongs. - pub fn spawn_category( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSpawnCategory", - sig.as_str(), - vec![], - ); + /// Gets the {@link Server} that contains this Entity + pub fn server(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Server;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + crate::Server::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Checks if this entity has been spawned in a world. + /// Returns true if the entity gets persisted. /// - /// Entities not spawned in a world will not tick, be sent to players, or be - /// saved to the server files. - pub fn is_in_world(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get this entity as an NBT string. + /// By default all entities are persistent. An entity will also not get + /// persisted, if it is riding an entity that is not persistent. /// - /// This string should not be relied upon as a serializable value. - pub fn as_string(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); + /// The persistent flag on players controls whether or not to save their + /// playerdata file when they quit. If a player is directly or indirectly + /// riding a non-persistent entity, the vehicle at the root and all its + /// passengers won't get persisted. + /// + /// This should not be confused with + /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls + /// despawning of living entities. + pub fn is_persistent(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(res.z()?) } - /// Crates an {@link EntitySnapshot} representing the current state of this entity. - pub fn create_snapshot( + /// Sets whether or not the entity gets persisted. + pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(persistent.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPersistent", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. + pub fn passenger( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::EntitySnapshot::from_raw( + Ok(Some(crate::entity::Entity::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Creates a copy of this entity and all its data. Spawns the copy at the given location. - /// - /// Note: Players cannot be copied. - pub fn copy( - &self, - to: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = to { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")Lorg/bukkit/entity/Entity;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets a metadata value in the implementing object's metadata store. - pub fn set_metadata( + #[deprecated] + /// Set the passenger of a vehicle. + pub fn set_passenger( &self, - metadata_key: impl Into, - new_metadata_value: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setMetadata", + "setPassenger", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Returns a list of previously set metadata values from the implementing - /// object's metadata store. - pub fn get_metadata( + /// Gets a list of passengers of this vehicle. + /// + /// The returned list will not be directly linked to the entity's current + /// passengers, and no guarantees are made as to its mutability. + pub fn passengers( &self, - metadata_key: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMetadata", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::metadata::MetadataValue::from_raw( - &self.jni_ref(), - obj, - )?); + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); } Ok(new_vec) } - /// Tests to see whether the implementing object contains the given - /// metadata value in its metadata store. - pub fn has_metadata( + /// Add a passenger to the vehicle. + pub fn add_passenger( &self, - metadata_key: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasMetadata", + "addPassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes the given metadata value from the implementing object's - /// metadata store. - pub fn remove_metadata( + /// Remove a passenger from the vehicle. + pub fn remove_passenger( &self, - metadata_key: impl Into, - owning_plugin: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeMetadata", + "removePassenger", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Sends this sender multiple messages - pub fn send_message( - &self, - sender: impl Into>, - messages: std::option::Option>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = messages { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_2); - } - sig += ")V"; + /// Check if a vehicle has passengers. + pub fn is_empty(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the name of this command sender - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Eject any passenger. + pub fn eject(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - /// Gets the custom name on a mob or block. If there is no name this method - /// will return null. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn custom_name(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); + /// Returns the distance this entity has fallen + pub fn fall_distance(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getCustomName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(res.f()?) } - /// Sets a custom name on a mob or block. This name will be used in death - /// messages and can be sent to the client as a nameplate over the mob. - /// - /// Setting the name to null or an empty string will clear it. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn set_custom_name( + /// Sets the fall distance for this entity + pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(distance); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFallDistance", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Record the last {@link EntityDamageEvent} inflicted on this entity + pub fn set_last_damage_cause( &self, - name: impl Into, + event: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(event.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomName", + "setLastDamageCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( + /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. + /// This event may have been cancelled. + pub fn last_damage_cause( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); + ) -> Result>, Box> + { + let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "getLastDamageCause", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for FishHook<'mc> { - fn into(self) -> crate::entity::Projectile<'mc> { - crate::entity::Projectile::from_raw(&self.jni_ref(), self.1) - .expect("Error converting FishHook into crate::entity::Projectile") - } -} -pub enum FishHookHookState<'mc> {} -impl<'mc> std::fmt::Display for FishHookHookState<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> FishHookHookState<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/FishHook/HookState"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/FishHook/HookState;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct FishHookHookStateStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for FishHookHookState<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for FishHookHookState<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate FishHookHookState from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/FishHook/HookState")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a FishHookHookState object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for FishHookHookStateStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for FishHookHookStateStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate FishHookHookStateStruct from null object." - ) - .into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/FishHook/HookState")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a FishHookHookStateStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } -} - -impl<'mc> FishHookHookStateStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/FishHook/HookState;"); - let cls = jni.find_class("org/bukkit/entity/FishHook/HookState"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::FishHookHookState::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct ChestedHorse<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for ChestedHorse<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for ChestedHorse<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ChestedHorse from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/ChestedHorse")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ChestedHorse object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Returns a unique and persistent id for this entity + pub fn unique_id( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} - -impl<'mc> ChestedHorse<'mc> { - /// Gets whether the horse has a chest equipped. - pub fn is_carrying_chest(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. + pub fn ticks_lived(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCarryingChest", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets whether the horse has a chest equipped. Removing a chest will also - /// clear the chest's inventory. - pub fn set_carrying_chest(&self, chest: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(chest.into()); + /// Sets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. May not be less than one + /// tick. + pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(value); let res = self.jni_ref().call_method( &self.jni_object(), - "setCarryingChest", + "setTicksLived", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the horse's variant.A horse's variant defines its physical appearance and capabilities. Whether a horse is a regular horse, donkey, mule, or other kind of horse is determined using the variant. - pub fn variant(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Horse/Variant;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::HorseVariant::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - #[deprecated] - - pub fn set_variant( + /// Performs the specified {@link EntityEffect} for this entity. + /// + /// This will be viewable to all players near the entity. + /// + /// If the effect is not applicable to this class of entity, it will not play. + pub fn play_effect( &self, - variant: impl Into>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Horse/Variant;)V"); + let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(variant.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVariant", + "playEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the domestication level of this horse. - /// - /// A higher domestication level indicates that the horse is closer to - /// becoming tame. As the domestication level gets closer to the max - /// domestication level, the chance of the horse becoming tame increases. - pub fn domestication(&self) -> Result> { - let sig = String::from("()I"); + /// Get the type of the entity. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes while swimming. + pub fn swim_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes when splashing in water. For most + /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_splash_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getDomestication", + "getSwimSplashSound", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the domestication level of this horse. - /// - /// Setting the domestication level to a high value will increase the - /// horse's chances of becoming tame. + /// Get the {@link Sound} this entity makes when splashing in water at high + /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_high_speed_splash_sound( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSwimHighSpeedSplashSound", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns whether this entity is inside a vehicle. + pub fn is_inside_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Leave the current vehicle. If the entity is currently in a vehicle (and + /// is removed from it), true will be returned, otherwise false will be + /// returned. + pub fn leave_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the vehicle that this entity is inside. If there is no vehicle, + /// null will be returned. + pub fn vehicle( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets whether or not to display the mob's custom name client side. The + /// name will be displayed above the mob similarly to a player. /// - /// Domestication level must be greater than zero and no greater than - /// the max domestication level of the horse, determined with - /// {@link #getMaxDomestication()} - pub fn set_domestication(&self, level: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(level); + /// This value has no effect on players, they will always display their + /// name. + pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setDomestication", + "setCustomNameVisible", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the maximum domestication level of this horse. + /// Gets whether or not the mob's custom name is displayed client side. /// - /// The higher this level is, the longer it will likely take - /// for the horse to be tamed. - pub fn max_domestication(&self) -> Result> { - let sig = String::from("()I"); + /// This value has no effect on players, they will always display their + /// name. + pub fn is_custom_name_visible(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getMaxDomestication", + "isCustomNameVisible", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the maximum domestication level of this horse. - /// - /// Setting a higher max domestication will increase the amount of - /// domesticating (feeding, riding, etc.) necessary in order to tame it, - /// while setting a lower max value will have the opposite effect. - /// - /// Maximum domestication must be greater than zero. - pub fn set_max_domestication(&self, level: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(level); + /// Sets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(visible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxDomestication", + "setVisibleByDefault", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the jump strength of this horse. + /// Gets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn is_visible_by_default(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isVisibleByDefault", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get all players that are currently tracking this entity. /// - /// Jump strength defines how high the horse can jump. A higher jump strength - /// increases how high a jump will go. - pub fn jump_strength(&self) -> Result> { - let sig = String::from("()D"); + /// 'Tracking' means that this entity has been sent to the player and that + /// they are receiving updates on its state. Note that the client's {@code + /// 'Entity Distance'} setting does not affect the range at which entities + /// are tracked. + pub fn tracked_by( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getJumpStrength", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the jump strength of this horse. - /// - /// A higher jump strength increases how high a jump will go. - /// Setting a jump strength to 0 will result in no jump. - /// You cannot set a jump strength to a value below 0 or - /// above 2. - pub fn set_jump_strength(&self, strength: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(strength); + /// Sets whether the entity has a team colored (default: white) glow. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setJumpStrength", + "setGlowing", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the horse is currently grazing hay. - pub fn is_eating_haystack(&self) -> Result> { + /// Gets whether the entity is glowing or not. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn is_glowing(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isEatingHaystack", - sig.as_str(), - vec![], - ); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the horse is grazing hay. - pub fn set_eating_haystack( - &self, - eating_haystack: bool, - ) -> Result<(), Box> { + /// Sets whether the entity is invulnerable or not. + /// + /// When an entity is invulnerable it can only be damaged by players in + /// creative mode. + pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(eating_haystack.into()); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setEatingHaystack", + "setInvulnerable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/AbstractHorseInventory;"); + /// Gets whether the entity is invulnerable or not. + pub fn is_invulnerable(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::AbstractHorseInventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Gets the vehicle's velocity. - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + /// Gets whether the entity is silent or not. + pub fn is_silent(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets the vehicle's velocity in meters per tick. - pub fn set_velocity( - &self, - vel: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(vel.into().jni_object().clone()) - }); + /// Sets whether the entity is silent or not. + /// + /// When an entity is silent it will not produce any sound. + pub fn set_silent(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setVelocity", + "setSilent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check if this is tamed - /// - /// If something is tamed then a player can not tame it through normal - /// methods, even if it does not belong to anyone in particular. - pub fn is_tamed(&self) -> Result> { + /// Returns whether gravity applies to this entity. + pub fn has_gravity(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isTamed", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets if this has been tamed. Not necessary if the method setOwner has - /// been used, as it tames automatically. - /// - /// If something is tamed then a player can not tame it through normal - /// methods, even if it does not belong to anyone in particular. - pub fn set_tamed(&self, tame: bool) -> Result<(), Box> { + /// Sets whether gravity applies to this entity. + pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(tame.into()); + let val_1 = jni::objects::JValueGen::Bool(gravity.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setTamed", + "setGravity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the current owning AnimalTamer - pub fn owner( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/AnimalTamer;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); + /// Gets the period of time (in ticks) before this entity can use a portal. + pub fn portal_cooldown(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPortalCooldown", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::AnimalTamer::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - /// Set this to be owned by given AnimalTamer. - /// - /// If the owner is not null, this will be tamed and will have any current - /// path it is following removed. If the owner is set to null, this will be - /// untamed, and the current owner removed. - pub fn set_owner( - &self, - tamer: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/AnimalTamer;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tamer.into().jni_object().clone()) - }); + /// Sets the period of time (in ticks) before this entity can use a portal. + pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(cooldown); let res = self.jni_ref().call_method( &self.jni_object(), - "setOwner", + "setPortalCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for ChestedHorse<'mc> { - fn into(self) -> crate::entity::AbstractHorse<'mc> { - crate::entity::AbstractHorse::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ChestedHorse into crate::entity::AbstractHorse") - } -} -#[repr(C)] -pub struct Llama<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Llama<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Llama<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Llama from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Llama")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Llama object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Llama<'mc> { - /// Gets the llama's color. - pub fn color(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Llama/Color;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); + /// Returns a set of tags for this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn scoreboard_tags( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getScoreboardTags", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::entity::LlamaColor::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the llama's color. - pub fn set_color( + /// Add a tag to this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn add_scoreboard_tag( &self, - color: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Llama/Color;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) - }); + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setColor", + "addScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the llama's strength. A higher strength llama will have more - /// inventory slots and be more threatening to entities. - pub fn strength(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getStrength", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the llama's strength. A higher strength llama will have more - /// inventory slots and be more threatening to entities. Inventory slots are - /// equal to strength * 3. - pub fn set_strength(&self, strength: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(strength); + /// Removes a given tag from this entity. + pub fn remove_scoreboard_tag( + &self, + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setStrength", + "removeScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether the horse has a chest equipped. - pub fn is_carrying_chest(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCarryingChest", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the horse has a chest equipped. Removing a chest will also - /// clear the chest's inventory. - pub fn set_carrying_chest(&self, chest: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(chest.into()); + /// Returns the reaction of the entity when moved by a piston. + pub fn piston_move_reaction( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setCarryingChest", + "getPistonMoveReaction", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - /// Gets the horse's variant.A horse's variant defines its physical appearance and capabilities. Whether a horse is a regular horse, donkey, mule, or other kind of horse is determined using the variant. - pub fn variant(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Horse/Variant;"); + /// Get the closest cardinal {@link BlockFace} direction an entity is + /// currently facing. + /// + /// This will not return any non-cardinal directions such as + /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// + /// {@link Hanging} entities will override this call and thus their behavior + /// may be different. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the entity's current pose. + /// Note that the pose is only updated at the end of a tick, so may be + /// inconsistent with other methods. eg {@link Player#isSneaking()} being + /// true does not imply the current pose will be {@link Pose#SNEAKING} + pub fn pose(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Pose;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the category of spawn to which this entity belongs. + pub fn spawn_category( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSpawnCategory", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Checks if this entity has been spawned in a world. + /// + /// Entities not spawned in a world will not tick, be sent to players, or be + /// saved to the server files. + pub fn is_in_world(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get this entity as an NBT string. + /// + /// This string should not be relied upon as a serializable value. + pub fn as_string(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::HorseVariant::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Crates an {@link EntitySnapshot} representing the current state of this entity. + pub fn create_snapshot( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntitySnapshot::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// + /// Note: Players cannot be copied. + pub fn copy( + &self, + to: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = to { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Lorg/bukkit/entity/Entity;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - #[deprecated] - - pub fn set_variant( + /// Instructs this Mob to set the specified LivingEntity as its target. + /// + /// Hostile creatures may attack their target, and friendly creatures may + /// follow their target. + pub fn set_target( &self, - variant: impl Into>, + target: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Horse/Variant;)V"); + let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(variant.into().jni_object().clone()) + jni::objects::JObject::from_raw(target.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVariant", + "setTarget", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the domestication level of this horse. - /// - /// A higher domestication level indicates that the horse is closer to - /// becoming tame. As the domestication level gets closer to the max - /// domestication level, the chance of the horse becoming tame increases. - pub fn domestication(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getDomestication", - sig.as_str(), - vec![], - ); + /// Gets the current target of this Mob + pub fn target( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTarget", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::LivingEntity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the domestication level of this horse. - /// - /// Setting the domestication level to a high value will increase the - /// horse's chances of becoming tame. - /// - /// Domestication level must be greater than zero and no greater than - /// the max domestication level of the horse, determined with - /// {@link #getMaxDomestication()} - pub fn set_domestication(&self, level: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(level); + /// Sets whether this mob is aware of its surroundings. + /// Unaware mobs will still move if pushed, attacked, etc. but will not move + /// or perform any actions on their own. Unaware mobs may also have other + /// unspecified behaviours disabled, such as drowning. + pub fn set_aware(&self, aware: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(aware.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setDomestication", + "setAware", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the maximum domestication level of this horse. - /// - /// The higher this level is, the longer it will likely take - /// for the horse to be tamed. - pub fn max_domestication(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMaxDomestication", - sig.as_str(), - vec![], - ); + /// Gets whether this mob is aware of its surroundings. + /// Unaware mobs will still move if pushed, attacked, etc. but will not move + /// or perform any actions on their own. Unaware mobs may also have other + /// unspecified behaviours disabled, such as drowning. + pub fn is_aware(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isAware", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the maximum domestication level of this horse. - /// - /// Setting a higher max domestication will increase the amount of - /// domesticating (feeding, riding, etc.) necessary in order to tame it, - /// while setting a lower max value will have the opposite effect. - /// - /// Maximum domestication must be greater than zero. - pub fn set_max_domestication(&self, level: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(level); + /// Get the {@link Sound} this mob makes while ambiently existing. This sound + /// may change depending on the current state of the entity, and may also + /// return null under specific conditions. This sound is not constant. + /// For instance, villagers will make different passive noises depending + /// on whether or not they are actively trading with a player, or make no + /// ambient noise while sleeping. + pub fn ambient_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAmbientSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Gets the specified attribute instance from the object. This instance will + /// be backed directly to the object and any changes will be visible at once. + pub fn get_attribute( + &self, + attribute: impl Into>, + ) -> Result>, Box> { + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxDomestication", + "getAttribute", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::attribute::AttributeInstance::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Deals the given amount of damage to this entity from a specified + /// {@link DamageSource}. + pub fn damage( + &self, + amount: f64, + damage_source: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(amount); + args.push(val_1); + if let Some(a) = damage_source { + sig += "Lorg/bukkit/damage/DamageSource;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "damage", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the jump strength of this horse. - /// - /// Jump strength defines how high the horse can jump. A higher jump strength - /// increases how high a jump will go. - pub fn jump_strength(&self) -> Result> { + /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. + pub fn health(&self) -> Result> { let sig = String::from("()D"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getJumpStrength", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.d()?) } - /// Sets the jump strength of this horse. - /// - /// A higher jump strength increases how high a jump will go. - /// Setting a jump strength to 0 will result in no jump. - /// You cannot set a jump strength to a value below 0 or - /// above 2. - pub fn set_jump_strength(&self, strength: f64) -> Result<(), Box> { + /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is + /// dead. + pub fn set_health(&self, health: f64) -> Result<(), Box> { let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(strength); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "setJumpStrength", + "setHealth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the horse is currently grazing hay. - pub fn is_eating_haystack(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the entity's absorption amount. + pub fn absorption_amount(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref().call_method( &self.jni_object(), - "isEatingHaystack", + "getAbsorptionAmount", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Sets whether the horse is grazing hay. - pub fn set_eating_haystack( - &self, - eating_haystack: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(eating_haystack.into()); + /// Sets the entity's absorption amount. + /// + /// Note: The amount is capped to the value of + /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on + /// that attribute is currently unspecified and subject to change. + pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "setEatingHaystack", + "setAbsorptionAmount", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/AbstractHorseInventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::AbstractHorseInventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the vehicle's velocity. - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); + #[deprecated] + /// Gets the maximum health this entity has. + pub fn max_health(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.d()?) } - /// Sets the vehicle's velocity in meters per tick. - pub fn set_velocity( - &self, - vel: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(vel.into().jni_object().clone()) - }); + #[deprecated] + /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. + pub fn set_max_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "setVelocity", + "setMaxHealth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check if this is tamed - /// - /// If something is tamed then a player can not tame it through normal - /// methods, even if it does not belong to anyone in particular. - pub fn is_tamed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isTamed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets if this has been tamed. Not necessary if the method setOwner has - /// been used, as it tames automatically. - /// - /// If something is tamed then a player can not tame it through normal - /// methods, even if it does not belong to anyone in particular. - pub fn set_tamed(&self, tame: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(tame.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTamed", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + #[deprecated] + /// Resets the max health to the original amount. + pub fn reset_max_health(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the current owning AnimalTamer - pub fn owner( + /// Launches a {@link Projectile} from the ProjectileSource with an + /// initial velocity. + pub fn launch_projectile( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/AnimalTamer;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + projectile: jni::objects::JClass<'mc>, + velocity: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(projectile.into()); + args.push(val_1); + if let Some(a) = velocity { + sig += "Lorg/bukkit/util/Vector;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); } - Ok(Some(crate::entity::AnimalTamer::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Set this to be owned by given AnimalTamer. - /// - /// If the owner is not null, this will be tamed and will have any current - /// path it is following removed. If the owner is set to null, this will be - /// untamed, and the current owner removed. - pub fn set_owner( - &self, - tamer: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/AnimalTamer;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tamer.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setOwner", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + sig += ")LT;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -77577,158 +86997,93 @@ impl<'mc> Llama<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Llama<'mc> { - fn into(self) -> crate::entity::ChestedHorse<'mc> { - crate::entity::ChestedHorse::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Llama into crate::entity::ChestedHorse") +impl<'mc> Into> for EnderDragon<'mc> { + fn into(self) -> crate::entity::ComplexLivingEntity<'mc> { + crate::entity::ComplexLivingEntity::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EnderDragon into crate::entity::ComplexLivingEntity") } } -pub enum LlamaColor<'mc> {} -impl<'mc> std::fmt::Display for LlamaColor<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} +impl<'mc> Into> for EnderDragon<'mc> { + fn into(self) -> crate::entity::Boss<'mc> { + crate::entity::Boss::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EnderDragon into crate::entity::Boss") } } - -impl<'mc> LlamaColor<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/Llama/Color"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/Llama/Color;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } +impl<'mc> Into> for EnderDragon<'mc> { + fn into(self) -> crate::entity::Mob<'mc> { + crate::entity::Mob::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EnderDragon into crate::entity::Mob") } } - -#[repr(C)] -pub struct LlamaColorStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for LlamaColor<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} +impl<'mc> Into> for EnderDragon<'mc> { + fn into(self) -> crate::entity::Enemy<'mc> { + crate::entity::Enemy::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EnderDragon into crate::entity::Enemy") } } -impl<'mc> JNIInstantiatable<'mc> for LlamaColor<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate LlamaColor from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Llama/Color")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a LlamaColor object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), +pub enum EnderDragonPhase<'mc> { + Circling { inner: EnderDragonPhaseStruct<'mc> }, + Strafing { inner: EnderDragonPhaseStruct<'mc> }, + FlyToPortal { inner: EnderDragonPhaseStruct<'mc> }, + LandOnPortal { inner: EnderDragonPhaseStruct<'mc> }, + LeavePortal { inner: EnderDragonPhaseStruct<'mc> }, + BreathAttack { inner: EnderDragonPhaseStruct<'mc> }, + SearchForBreathAttackTarget { inner: EnderDragonPhaseStruct<'mc> }, + RoarBeforeAttack { inner: EnderDragonPhaseStruct<'mc> }, + ChargePlayer { inner: EnderDragonPhaseStruct<'mc> }, + Dying { inner: EnderDragonPhaseStruct<'mc> }, + Hover { inner: EnderDragonPhaseStruct<'mc> }, +} +impl<'mc> std::fmt::Display for EnderDragonPhase<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + EnderDragonPhase::Circling { .. } => f.write_str("CIRCLING"), + EnderDragonPhase::Strafing { .. } => f.write_str("STRAFING"), + EnderDragonPhase::FlyToPortal { .. } => f.write_str("FLY_TO_PORTAL"), + EnderDragonPhase::LandOnPortal { .. } => f.write_str("LAND_ON_PORTAL"), + EnderDragonPhase::LeavePortal { .. } => f.write_str("LEAVE_PORTAL"), + EnderDragonPhase::BreathAttack { .. } => f.write_str("BREATH_ATTACK"), + EnderDragonPhase::SearchForBreathAttackTarget { .. } => { + f.write_str("SEARCH_FOR_BREATH_ATTACK_TARGET") } + EnderDragonPhase::RoarBeforeAttack { .. } => f.write_str("ROAR_BEFORE_ATTACK"), + EnderDragonPhase::ChargePlayer { .. } => f.write_str("CHARGE_PLAYER"), + EnderDragonPhase::Dying { .. } => f.write_str("DYING"), + EnderDragonPhase::Hover { .. } => f.write_str("HOVER"), } } } - -impl<'mc> JNIRaw<'mc> for LlamaColorStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for LlamaColorStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate LlamaColorStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Llama/Color")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a LlamaColorStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) +impl<'mc> std::ops::Deref for EnderDragonPhase<'mc> { + type Target = EnderDragonPhaseStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + EnderDragonPhase::Circling { inner } => inner, + EnderDragonPhase::Strafing { inner } => inner, + EnderDragonPhase::FlyToPortal { inner } => inner, + EnderDragonPhase::LandOnPortal { inner } => inner, + EnderDragonPhase::LeavePortal { inner } => inner, + EnderDragonPhase::BreathAttack { inner } => inner, + EnderDragonPhase::SearchForBreathAttackTarget { inner } => inner, + EnderDragonPhase::RoarBeforeAttack { inner } => inner, + EnderDragonPhase::ChargePlayer { inner } => inner, + EnderDragonPhase::Dying { inner } => inner, + EnderDragonPhase::Hover { inner } => inner, } } } -impl<'mc> LlamaColorStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Llama/Color;"); - let cls = jni.find_class("org/bukkit/entity/Llama/Color"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::LlamaColor::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -pub enum SpawnCategory<'mc> {} -impl<'mc> std::fmt::Display for SpawnCategory<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> SpawnCategory<'mc> { +impl<'mc> EnderDragonPhase<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/SpawnCategory"); + let cls = env.find_class("org/bukkit/entity/EnderDragon/Phase"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/SpawnCategory;", + "(Ljava/lang/String;)Lorg/bukkit/entity/EnderDragon/Phase;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -77740,37 +87095,113 @@ impl<'mc> SpawnCategory<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "CIRCLING" => Ok(EnderDragonPhase::Circling { + inner: EnderDragonPhaseStruct::from_raw(env, obj)?, + }), + "STRAFING" => Ok(EnderDragonPhase::Strafing { + inner: EnderDragonPhaseStruct::from_raw(env, obj)?, + }), + "FLY_TO_PORTAL" => Ok(EnderDragonPhase::FlyToPortal { + inner: EnderDragonPhaseStruct::from_raw(env, obj)?, + }), + "LAND_ON_PORTAL" => Ok(EnderDragonPhase::LandOnPortal { + inner: EnderDragonPhaseStruct::from_raw(env, obj)?, + }), + "LEAVE_PORTAL" => Ok(EnderDragonPhase::LeavePortal { + inner: EnderDragonPhaseStruct::from_raw(env, obj)?, + }), + "BREATH_ATTACK" => Ok(EnderDragonPhase::BreathAttack { + inner: EnderDragonPhaseStruct::from_raw(env, obj)?, + }), + "SEARCH_FOR_BREATH_ATTACK_TARGET" => { + Ok(EnderDragonPhase::SearchForBreathAttackTarget { + inner: EnderDragonPhaseStruct::from_raw(env, obj)?, + }) + } + "ROAR_BEFORE_ATTACK" => Ok(EnderDragonPhase::RoarBeforeAttack { + inner: EnderDragonPhaseStruct::from_raw(env, obj)?, + }), + "CHARGE_PLAYER" => Ok(EnderDragonPhase::ChargePlayer { + inner: EnderDragonPhaseStruct::from_raw(env, obj)?, + }), + "DYING" => Ok(EnderDragonPhase::Dying { + inner: EnderDragonPhaseStruct::from_raw(env, obj)?, + }), + "HOVER" => Ok(EnderDragonPhase::Hover { + inner: EnderDragonPhaseStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct SpawnCategoryStruct<'mc>( +pub struct EnderDragonPhaseStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for SpawnCategory<'mc> { +impl<'mc> JNIRaw<'mc> for EnderDragonPhase<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Circling { inner } => inner.0.clone(), + Self::Strafing { inner } => inner.0.clone(), + Self::FlyToPortal { inner } => inner.0.clone(), + Self::LandOnPortal { inner } => inner.0.clone(), + Self::LeavePortal { inner } => inner.0.clone(), + Self::BreathAttack { inner } => inner.0.clone(), + Self::SearchForBreathAttackTarget { inner } => inner.0.clone(), + Self::RoarBeforeAttack { inner } => inner.0.clone(), + Self::ChargePlayer { inner } => inner.0.clone(), + Self::Dying { inner } => inner.0.clone(), + Self::Hover { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Circling { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Strafing { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::FlyToPortal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LandOnPortal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LeavePortal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BreathAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SearchForBreathAttackTarget { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RoarBeforeAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChargePlayer { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Dying { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Hover { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for SpawnCategory<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EnderDragonPhase<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate SpawnCategory from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate EnderDragonPhase from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/SpawnCategory")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EnderDragon/Phase")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SpawnCategory object, got {}", + "Invalid argument passed. Expected a EnderDragonPhase object, got {}", name ) .into()) @@ -77782,13 +87213,48 @@ impl<'mc> JNIInstantiatable<'mc> for SpawnCategory<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "CIRCLING" => Ok(EnderDragonPhase::Circling { + inner: EnderDragonPhaseStruct::from_raw(env, obj)?, + }), + "STRAFING" => Ok(EnderDragonPhase::Strafing { + inner: EnderDragonPhaseStruct::from_raw(env, obj)?, + }), + "FLY_TO_PORTAL" => Ok(EnderDragonPhase::FlyToPortal { + inner: EnderDragonPhaseStruct::from_raw(env, obj)?, + }), + "LAND_ON_PORTAL" => Ok(EnderDragonPhase::LandOnPortal { + inner: EnderDragonPhaseStruct::from_raw(env, obj)?, + }), + "LEAVE_PORTAL" => Ok(EnderDragonPhase::LeavePortal { + inner: EnderDragonPhaseStruct::from_raw(env, obj)?, + }), + "BREATH_ATTACK" => Ok(EnderDragonPhase::BreathAttack { + inner: EnderDragonPhaseStruct::from_raw(env, obj)?, + }), + "SEARCH_FOR_BREATH_ATTACK_TARGET" => { + Ok(EnderDragonPhase::SearchForBreathAttackTarget { + inner: EnderDragonPhaseStruct::from_raw(env, obj)?, + }) + } + "ROAR_BEFORE_ATTACK" => Ok(EnderDragonPhase::RoarBeforeAttack { + inner: EnderDragonPhaseStruct::from_raw(env, obj)?, + }), + "CHARGE_PLAYER" => Ok(EnderDragonPhase::ChargePlayer { + inner: EnderDragonPhaseStruct::from_raw(env, obj)?, + }), + "DYING" => Ok(EnderDragonPhase::Dying { + inner: EnderDragonPhaseStruct::from_raw(env, obj)?, + }), + "HOVER" => Ok(EnderDragonPhase::Hover { + inner: EnderDragonPhaseStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for SpawnCategoryStruct<'mc> { +impl<'mc> JNIRaw<'mc> for EnderDragonPhaseStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -77796,20 +87262,21 @@ impl<'mc> JNIRaw<'mc> for SpawnCategoryStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for SpawnCategoryStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EnderDragonPhaseStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate SpawnCategoryStruct from null object.").into(), - ); + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate EnderDragonPhaseStruct from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/SpawnCategory")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EnderDragon/Phase")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SpawnCategoryStruct object, got {}", + "Invalid argument passed. Expected a EnderDragonPhaseStruct object, got {}", name ) .into()) @@ -77819,17 +87286,17 @@ impl<'mc> JNIInstantiatable<'mc> for SpawnCategoryStruct<'mc> { } } -impl<'mc> SpawnCategoryStruct<'mc> { +impl<'mc> EnderDragonPhaseStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); - let cls = jni.find_class("org/bukkit/entity/SpawnCategory"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EnderDragon/Phase;"); + let cls = jni.find_class("org/bukkit/entity/EnderDragon/Phase"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::entity::SpawnCategory::from_raw(&jni, obj) + crate::entity::EnderDragonPhase::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -77838,12 +87305,12 @@ impl<'mc> SpawnCategoryStruct<'mc> { } } #[repr(C)] -pub struct MagmaCube<'mc>( +pub struct Minecart<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for MagmaCube<'mc> { +impl<'mc> JNIRaw<'mc> for Minecart<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -77851,18 +87318,18 @@ impl<'mc> JNIRaw<'mc> for MagmaCube<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for MagmaCube<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Minecart<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate MagmaCube from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Minecart from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/MagmaCube")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Minecart")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a MagmaCube object, got {}", + "Invalid argument passed. Expected a Minecart object, got {}", name ) .into()) @@ -77872,1383 +87339,1580 @@ impl<'mc> JNIInstantiatable<'mc> for MagmaCube<'mc> { } } -impl<'mc> MagmaCube<'mc> { - pub fn size(&self) -> Result> { - let sig = String::from("()I"); +impl<'mc> Minecart<'mc> { + /// Sets a minecart's damage. + pub fn set_damage(&self, damage: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(damage); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDamage", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets a minecart's damage. + pub fn damage(&self) -> Result> { + let sig = String::from("()D"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDamage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.d()?) } - - pub fn set_size(&self, sz: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(sz); + /// Gets the maximum speed of a minecart. The speed is unrelated to the + /// velocity. + pub fn max_speed(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxSpeed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Sets the maximum speed of a minecart. Must be nonnegative. Default is + /// 0.4D. + pub fn set_max_speed(&self, speed: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(speed); let res = self.jni_ref().call_method( &self.jni_object(), - "setSize", + "setMaxSpeed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Instructs this Mob to set the specified LivingEntity as its target. + /// Returns whether this minecart will slow down faster without a passenger + /// occupying it + pub fn is_slow_when_empty(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isSlowWhenEmpty", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether this minecart will slow down faster without a passenger + /// occupying it + pub fn set_slow_when_empty(&self, slow: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(slow.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSlowWhenEmpty", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the flying velocity modifier. Used for minecarts that are in + /// mid-air. A flying minecart's velocity is multiplied by this factor each + /// tick. + pub fn flying_velocity_mod( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getFlyingVelocityMod", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the flying velocity modifier. Used for minecarts that are in + /// mid-air. A flying minecart's velocity is multiplied by this factor each + /// tick. + pub fn set_flying_velocity_mod( + &self, + flying: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(flying.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFlyingVelocityMod", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the derailed velocity modifier. Used for minecarts that are on the + /// ground, but not on rails. /// - /// Hostile creatures may attack their target, and friendly creatures may - /// follow their target. - pub fn set_target( + /// A derailed minecart's velocity is multiplied by this factor each tick. + pub fn derailed_velocity_mod( &self, - target: impl Into>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDerailedVelocityMod", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the derailed velocity modifier. Used for minecarts that are on the + /// ground, but not on rails. A derailed minecart's velocity is multiplied + /// by this factor each tick. + pub fn set_derailed_velocity_mod( + &self, + derailed: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)V"); + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) + jni::objects::JObject::from_raw(derailed.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setTarget", + "setDerailedVelocityMod", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the current target of this Mob - pub fn target( + /// Sets the display block for this minecart. + /// Passing a null value will set the minecart to have no display block. + pub fn set_display_block( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTarget", sig.as_str(), vec![]); + material: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/material/MaterialData;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDisplayBlock", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the display block for this minecart. + /// This function will return the type AIR if none is set. + pub fn display_block( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/MaterialData;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDisplayBlock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::LivingEntity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets whether this mob is aware of its surroundings. - /// Unaware mobs will still move if pushed, attacked, etc. but will not move - /// or perform any actions on their own. Unaware mobs may also have other - /// unspecified behaviours disabled, such as drowning. - pub fn set_aware(&self, aware: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(aware.into()); + /// Sets the display block for this minecart. + /// Passing a null value will set the minecart to have no display block. + pub fn set_display_block_data( + &self, + block_data: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(block_data.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setAware", + "setDisplayBlockData", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether this mob is aware of its surroundings. - /// Unaware mobs will still move if pushed, attacked, etc. but will not move - /// or perform any actions on their own. Unaware mobs may also have other - /// unspecified behaviours disabled, such as drowning. - pub fn is_aware(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isAware", sig.as_str(), vec![]); + /// Gets the display block for this minecart. + /// This function will return the type AIR if none is set. + pub fn display_block_data( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDisplayBlockData", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get the {@link Sound} this mob makes while ambiently existing. This sound - /// may change depending on the current state of the entity, and may also - /// return null under specific conditions. This sound is not constant. - /// For instance, villagers will make different passive noises depending - /// on whether or not they are actively trading with a player, or make no - /// ambient noise while sleeping. - pub fn ambient_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Sets the offset of the display block. + pub fn set_display_block_offset(&self, offset: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(offset); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDisplayBlockOffset", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the offset of the display block. + pub fn display_block_offset(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDisplayBlockOffset", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the vehicle's velocity. + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAmbientSound", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the vehicle's velocity in meters per tick. + pub fn set_velocity( + &self, + vel: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(vel.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVelocity", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Stores the entity's current position in the provided Location object. + /// + /// If the provided Location is null this method does nothing and returns + /// null. + pub fn get_location( + &self, + loc: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLocation", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) })?)) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + /// Gets the entity's height + pub fn height(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } -} -impl<'mc> Into> for MagmaCube<'mc> { - fn into(self) -> crate::entity::Slime<'mc> { - crate::entity::Slime::from_raw(&self.jni_ref(), self.1) - .expect("Error converting MagmaCube into crate::entity::Slime") + /// Gets the entity's width + pub fn width(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } -} -#[repr(C)] -pub struct Bee<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Bee<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Gets the entity's current bounding box. + /// + /// The returned bounding box reflects the entity's current location and + /// size. + pub fn bounding_box( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Returns true if the entity is supported by a block. This value is a + /// state updated by the server and is not recalculated unless the entity + /// moves. + pub fn is_on_ground(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for Bee<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Bee from null object.").into()); + /// Returns true if the entity is in water. + pub fn is_in_water(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the current world this entity resides in + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the entity's rotation. + /// + /// Note that if the entity is affected by AI, it may override this rotation. + pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { + let sig = String::from("(FF)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); + let val_2 = jni::objects::JValueGen::Float(pitch); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRotation", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Teleports this entity to the given location. If this entity is riding a + /// vehicle, it will be dismounted prior to teleportation. + pub fn teleport( + &self, + location: impl Into>, + cause: std::option::Option< + impl Into>, + >, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = cause { + sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Bee")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Bee object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "teleport", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns a list of entities within a bounding box centered around this + /// entity + pub fn get_nearby_entities( + &self, + x: f64, + y: f64, + z: f64, + ) -> Result>, Box> { + let sig = String::from("(DDD)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Double(x); + let val_2 = jni::objects::JValueGen::Double(y); + let val_3 = jni::objects::JValueGen::Double(z); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNearbyEntities", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); } + Ok(new_vec) } -} - -impl<'mc> Bee<'mc> { - /// Get the bee's hive location. - pub fn hive(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHive", sig.as_str(), vec![]); + /// Returns a unique id for this entity + pub fn entity_id(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.i()?) } - /// Set the bee's hive location. - pub fn set_hive( - &self, - location: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Location;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); + /// Returns the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's maximum fire ticks. + pub fn max_fire_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setHive", + "setFireTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the bee's flower location. - pub fn flower(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFlower", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Set the bee's flower location. - pub fn set_flower( - &self, - location: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Location;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); + /// Sets if the entity has visual fire (it will always appear to be on fire). + pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setFlower", + "setVisualFire", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get if the bee has nectar. - pub fn has_nectar(&self) -> Result> { + /// Gets if the entity has visual fire (it will always appear to be on fire). + pub fn is_visual_fire(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasNectar", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set if the bee has nectar. - pub fn set_has_nectar(&self, nectar: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(nectar.into()); + /// Returns the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's maximum freeze ticks (amount of ticks before it will + /// be fully frozen) + pub fn max_freeze_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "setHasNectar", + "getMaxFreezeTicks", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFreezeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get if the bee has stung. - pub fn has_stung(&self) -> Result> { + /// Gets if the entity is fully frozen (it has been in powdered snow for max + /// freeze ticks). + pub fn is_frozen(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "hasStung", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set if the bee has stung. - pub fn set_has_stung(&self, stung: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(stung.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setHasStung", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Mark the entity's removal. + pub fn remove(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the bee's anger level. - pub fn anger(&self) -> Result> { - let sig = String::from("()I"); + /// Returns true if this entity has been marked for removal. + pub fn is_dead(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getAnger", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the bee's new anger level. - pub fn set_anger(&self, anger: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(anger); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAnger", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Returns false if the entity has died, been despawned for some other + /// reason, or has not been added to the world. + pub fn is_valid(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Get the amount of ticks the bee cannot enter the hive for. - pub fn cannot_enter_hive_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCannotEnterHiveTicks", - sig.as_str(), - vec![], - ); + /// Gets the {@link Server} that contains this Entity + pub fn server(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Server;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::Server::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the amount of ticks the bee cannot enter a hive for. - pub fn set_cannot_enter_hive_ticks( - &self, - ticks: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Returns true if the entity gets persisted. + /// + /// By default all entities are persistent. An entity will also not get + /// persisted, if it is riding an entity that is not persistent. + /// + /// The persistent flag on players controls whether or not to save their + /// playerdata file when they quit. If a player is directly or indirectly + /// riding a non-persistent entity, the vehicle at the root and all its + /// passengers won't get persisted. + /// + /// This should not be confused with + /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls + /// despawning of living entities. + pub fn is_persistent(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether or not the entity gets persisted. + pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(persistent.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCannotEnterHiveTicks", + "setPersistent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn breed_cause( + #[deprecated] + /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. + pub fn passenger( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/UUID;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( + Ok(Some(crate::entity::Entity::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Set the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn set_breed_cause( + #[deprecated] + /// Set the passenger of a vehicle. + pub fn set_passenger( &self, - uuid: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/UUID;)V"); + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreedCause", + "setPassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get whether or not this entity is in love mode and will produce - /// offspring with another entity in love mode. Will return true if - /// and only if {@link #getLoveModeTicks()} is greater than 0. - pub fn is_love_mode(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get the amount of ticks remaining for this entity in love mode. - /// If the entity is not in love mode, 0 will be returned. - pub fn love_mode_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLoveModeTicks", - sig.as_str(), - vec![], - ); + /// Gets a list of passengers of this vehicle. + /// + /// The returned list will not be directly linked to the entity's current + /// passengers, and no guarantees are made as to its mutability. + pub fn passengers( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Set the amount of ticks for which this entity should be in love mode. - /// Setting the love mode ticks to 600 is the equivalent of a player - /// feeding the entity their breeding item of choice. - pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Add a passenger to the vehicle. + pub fn add_passenger( + &self, + passenger: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLoveModeTicks", + "addPassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Check if the provided ItemStack is the correct item used for breeding - /// this entity.. - pub fn is_breed_item( + /// Remove a passenger from the vehicle. + pub fn remove_passenger( &self, - material: impl Into>, + passenger: impl Into>, ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; + let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Lock the age of the animal, setting this will prevent the animal from - /// maturing or getting ready for mating. - pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(lock.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setAgeLock", + "removePassenger", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the current agelock. - pub fn age_lock(&self) -> Result> { + /// Check if a vehicle has passengers. + pub fn is_empty(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Return the ability to breed of the animal. - pub fn can_breed(&self) -> Result> { + /// Eject any passenger. + pub fn eject(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "canBreed", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set breedability of the animal, if the animal is a baby and set to - /// breed it will instantly grow up. - pub fn set_breed(&self, breed: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(breed.into()); + /// Returns the distance this entity has fallen + pub fn fall_distance(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the fall distance for this entity + pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(distance); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreed", + "setFallDistance", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Bee<'mc> { - fn into(self) -> crate::entity::Animals<'mc> { - crate::entity::Animals::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Bee into crate::entity::Animals") - } -} -#[repr(C)] -pub struct Breedable<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Breedable<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Breedable<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Breedable from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Breedable")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Breedable object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Breedable<'mc> { #[deprecated] - /// Lock the age of the animal, setting this will prevent the animal from maturing or getting ready for mating. - pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(lock.into()); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setAgeLock", sig.as_str(), args); + /// Record the last {@link EntityDamageEvent} inflicted on this entity + pub fn set_last_damage_cause( + &self, + event: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(event.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLastDamageCause", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the current agelock. - pub fn age_lock(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Return the ability to breed of the animal. - pub fn can_breed(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "canBreed", sig.as_str(), args); + /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. + /// This event may have been cancelled. + pub fn last_damage_cause( + &self, + ) -> Result>, Box> + { + let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLastDamageCause", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - #[deprecated] - /// Set breedability of the animal, if the animal is a baby and set to breed it will instantly grow up. - pub fn set_breed(&self, breed: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(breed.into()); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setBreed", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Returns a unique and persistent id for this entity + pub fn unique_id( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the age of this mob. - pub fn age(&self) -> Result> { + /// Gets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. + pub fn ticks_lived(&self) -> Result> { let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getAge", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the age of this mob. - pub fn set_age(&self, age: i32) -> Result<(), Box> { + /// Sets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. May not be less than one + /// tick. + pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(age); + let val_1 = jni::objects::JValueGen::Int(value); let res = self.jni_ref().call_method( &self.jni_object(), - "setAge", + "setTicksLived", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets the age of the mob to a baby - pub fn set_baby(&self) -> Result<(), Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setBaby", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Sets the age of the mob to an adult - pub fn set_adult(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setAdult", sig.as_str(), vec![]); + /// Performs the specified {@link EntityEffect} for this entity. + /// + /// This will be viewable to all players near the entity. + /// + /// If the effect is not applicable to this class of entity, it will not play. + pub fn play_effect( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "playEffect", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns true if the mob is an adult. - pub fn is_adult(&self) -> Result> { - let sig = String::from("()Z"); + /// Get the type of the entity. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isAdult", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> Into> for Breedable<'mc> { - fn into(self) -> crate::entity::Ageable<'mc> { - crate::entity::Ageable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Breedable into crate::entity::Ageable") + /// Get the {@link Sound} this entity makes while swimming. + pub fn swim_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -#[repr(C)] -pub struct Skeleton<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Skeleton<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Get the {@link Sound} this entity makes when splashing in water. For most + /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_splash_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSwimSplashSound", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Get the {@link Sound} this entity makes when splashing in water at high + /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_high_speed_splash_sound( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSwimHighSpeedSplashSound", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> JNIInstantiatable<'mc> for Skeleton<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Skeleton from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Skeleton")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Skeleton object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Returns whether this entity is inside a vehicle. + pub fn is_inside_vehicle(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} - -impl<'mc> Skeleton<'mc> { - /// Computes whether or not this skeleton is currently in the process of - /// converting to a {@link Stray} due to it being frozen by powdered snow. - pub fn is_converting(&self) -> Result> { + /// Leave the current vehicle. If the entity is currently in a vehicle (and + /// is removed from it), true will be returned, otherwise false will be + /// returned. + pub fn leave_vehicle(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isConverting", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the amount of ticks until this entity will be converted to a stray - /// as a result of being frozen by a powdered snow block. + /// Get the vehicle that this entity is inside. If there is no vehicle, + /// null will be returned. + pub fn vehicle( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets whether or not to display the mob's custom name client side. The + /// name will be displayed above the mob similarly to a player. /// - /// When this reaches 0, the entity will be converted. - pub fn conversion_time(&self) -> Result> { - let sig = String::from("()I"); + /// This value has no effect on players, they will always display their + /// name. + pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getConversionTime", + "setCustomNameVisible", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether or not the mob's custom name is displayed client side. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn is_custom_name_visible(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isCustomNameVisible", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the amount of ticks until this entity will be converted to a stray - /// as a result of being frozen by a powdered snow block. - /// - /// When this reaches 0, the entity will be converted. A value of less than 0 - /// will stop the current conversion process without converting the current - /// entity. - pub fn set_conversion_time(&self, time: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(time); + /// Sets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(visible.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setConversionTime", + "setVisibleByDefault", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the current type of this skeleton. - pub fn skeleton_type( + /// Gets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn is_visible_by_default(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isVisibleByDefault", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get all players that are currently tracking this entity. + /// + /// 'Tracking' means that this entity has been sent to the player and that + /// they are receiving updates on its state. Note that the client's {@code + /// 'Entity Distance'} setting does not affect the range at which entities + /// are tracked. + pub fn tracked_by( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Skeleton/SkeletonType;"); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getSkeletonType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::SkeletonSkeletonType::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - #[deprecated] - - pub fn set_skeleton_type( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Skeleton/SkeletonType;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Sets whether the entity has a team colored (default: white) glow. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setSkeletonType", + "setGlowing", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Skeleton<'mc> { - fn into(self) -> crate::entity::AbstractSkeleton<'mc> { - crate::entity::AbstractSkeleton::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Skeleton into crate::entity::AbstractSkeleton") - } -} -pub enum SkeletonSkeletonType<'mc> {} -impl<'mc> std::fmt::Display for SkeletonSkeletonType<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> SkeletonSkeletonType<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/Skeleton/SkeletonType"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/Skeleton/SkeletonType;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct SkeletonSkeletonTypeStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for SkeletonSkeletonType<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for SkeletonSkeletonType<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate SkeletonSkeletonType from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Skeleton/SkeletonType")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a SkeletonSkeletonType object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for SkeletonSkeletonTypeStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for SkeletonSkeletonTypeStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate SkeletonSkeletonTypeStruct from null object." - ) - .into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Skeleton/SkeletonType")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a SkeletonSkeletonTypeStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> SkeletonSkeletonTypeStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Skeleton/SkeletonType;"); - let cls = jni.find_class("org/bukkit/entity/Skeleton/SkeletonType"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::SkeletonSkeletonType::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct Villager<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Villager<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets whether the entity is glowing or not. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn is_glowing(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for Villager<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Villager from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Villager")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Villager object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Sets whether the entity is invulnerable or not. + /// + /// When an entity is invulnerable it can only be damaged by players in + /// creative mode. + pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setInvulnerable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> Villager<'mc> { - /// Gets the current profession of this villager. - pub fn profession( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Villager/Profession;"); + /// Gets whether the entity is invulnerable or not. + pub fn is_invulnerable(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getProfession", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::VillagerProfession::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets the new profession of this villager. - pub fn set_profession( - &self, - profession: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Villager/Profession;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(profession.into().jni_object().clone()) - }); + /// Gets whether the entity is silent or not. + pub fn is_silent(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the entity is silent or not. + /// + /// When an entity is silent it will not produce any sound. + pub fn set_silent(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setProfession", + "setSilent", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the current type of this villager. - pub fn villager_type( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Villager/Type;"); + /// Returns whether gravity applies to this entity. + pub fn has_gravity(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVillagerType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::VillagerType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets the new type of this villager. - pub fn set_villager_type( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Villager/Type;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Sets whether gravity applies to this entity. + pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(gravity.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setVillagerType", + "setGravity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the level of this villager. - /// A villager with a level of 1 and no experience is liable to lose its - /// profession. - pub fn villager_level(&self) -> Result> { + /// Gets the period of time (in ticks) before this entity can use a portal. + pub fn portal_cooldown(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getVillagerLevel", + "getPortalCooldown", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the level of this villager. - /// A villager with a level of 1 and no experience is liable to lose its - /// profession. - pub fn set_villager_level(&self, level: i32) -> Result<(), Box> { + /// Sets the period of time (in ticks) before this entity can use a portal. + pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(level); + let val_1 = jni::objects::JValueGen::Int(cooldown); let res = self.jni_ref().call_method( &self.jni_object(), - "setVillagerLevel", + "setPortalCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the trading experience of this villager. - pub fn villager_experience(&self) -> Result> { - let sig = String::from("()I"); + /// Returns a set of tags for this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn scoreboard_tags( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getVillagerExperience", + "getScoreboardTags", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the trading experience of this villager. - pub fn set_villager_experience( + /// Add a tag to this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn add_scoreboard_tag( &self, - experience: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(experience); + tag: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setVillagerExperience", + "addScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Attempts to make this villager sleep at the given location. - /// - /// The location must be in the current world and have a bed placed at the - /// location. The villager will put its head on the specified block while - /// sleeping. - pub fn sleep( + /// Removes a given tag from this entity. + pub fn remove_scoreboard_tag( &self, - location: impl Into>, + tag: impl Into, ) -> Result> { - let sig = String::from("(Lorg/bukkit/Location;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "sleep", + "removeScoreboardTag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Causes this villager to wake up if he's currently sleeping. - pub fn wakeup(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Returns the reaction of the entity when moved by a piston. + pub fn piston_move_reaction( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPistonMoveReaction", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the closest cardinal {@link BlockFace} direction an entity is + /// currently facing. + /// + /// This will not return any non-cardinal directions such as + /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// + /// {@link Hanging} entities will override this call and thus their behavior + /// may be different. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "wakeup", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Causes this villager to shake his head. - pub fn shake_head(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Gets the entity's current pose. + /// Note that the pose is only updated at the end of a tick, so may be + /// inconsistent with other methods. eg {@link Player#isSneaking()} being + /// true does not imply the current pose will be {@link Pose#SNEAKING} + pub fn pose(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Pose;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "shakeHead", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Convert this Villager into a ZombieVillager as if it was killed by a - /// Zombie. - /// Note: this will fire a EntityTransformEvent - pub fn zombify( + /// Get the category of spawn to which this entity belongs. + pub fn spawn_category( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/ZombieVillager;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSpawnCategory", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Checks if this entity has been spawned in a world. + /// + /// Entities not spawned in a world will not tick, be sent to players, or be + /// saved to the server files. + pub fn is_in_world(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "zombify", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get this entity as an NBT string. + /// + /// This string should not be relied upon as a serializable value. + pub fn as_string(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::ZombieVillager::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Gets this villager's inventory. - /// - /// Note that this inventory is not the Merchant inventory, rather, it is the - /// items that a villager might have collected (from harvesting crops, etc.) - /// {@inheritDoc} - pub fn inventory( + /// Crates an {@link EntitySnapshot} representing the current state of this entity. + pub fn create_snapshot( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntitySnapshot::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Lock the age of the animal, setting this will prevent the animal from - /// maturing or getting ready for mating. - pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { + /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// + /// Note: Players cannot be copied. + pub fn copy( + &self, + to: std::option::Option>>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(lock.into()); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setAgeLock", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the current agelock. - pub fn age_lock(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Return the ability to breed of the animal. - pub fn can_breed(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; + if let Some(a) = to { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Lorg/bukkit/entity/Entity;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "canBreed", sig.as_str(), args); + .call_method(&self.jni_object(), "copy", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set breedability of the animal, if the animal is a baby and set to - /// breed it will instantly grow up. - pub fn set_breed(&self, breed: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(breed.into()); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setBreed", sig.as_str(), args); + /// Sets a metadata value in the implementing object's metadata store. + pub fn set_metadata( + &self, + metadata_key: impl Into, + new_metadata_value: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMetadata", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get a list of trades currently available from this merchant. - pub fn recipes( + /// Returns a list of previously set metadata values from the implementing + /// object's metadata store. + pub fn get_metadata( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRecipes", sig.as_str(), vec![]); + metadata_key: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMetadata", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::inventory::MerchantRecipe::from_raw( + new_vec.push(crate::metadata::MetadataValue::from_raw( &self.jni_ref(), obj, )?); } Ok(new_vec) } - /// Set the list of trades currently available from this merchant. - /// - /// This will not change the selected trades of players currently trading - /// with this merchant. - pub fn set_recipes( + /// Tests to see whether the implementing object contains the given + /// metadata value in its metadata store. + pub fn has_metadata( &self, - recipes: Vec>, + metadata_key: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasMetadata", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Removes the given metadata value from the implementing object's + /// metadata store. + pub fn remove_metadata( + &self, + metadata_key: impl Into, + owning_plugin: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/List;)V"); - let raw_val_1 = self + let sig = String::from("(Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeMetadata", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sends this sender multiple messages + pub fn send_message( + &self, + sender: impl Into>, + messages: std::option::Option>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/util/UUID;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = messages { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_2); + } + sig += ")V"; + let res = self .jni_ref() - .new_object("java/util/ArrayList", "()V", vec![])?; - for v in recipes { - let map_val_0 = jni::objects::JValueGen::Object(v); - self.jni_ref().call_method( - &raw_val_1, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; + .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the name of this command sender + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gets the custom name on a mob or block. If there is no name this method + /// will return null. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn custom_name(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCustomName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - let val_1 = jni::objects::JValueGen::Object(raw_val_1); + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Sets a custom name on a mob or block. This name will be used in death + /// messages and can be sent to the client as a nameplate over the mob. + /// + /// Setting the name to null or an empty string will clear it. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn set_custom_name( + &self, + name: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setRecipes", + "setCustomName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the recipe at a certain index of this merchant's trade list. - pub fn get_recipe( + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + pub fn persistent_data_container( &self, - i: i32, - ) -> Result, Box> { - let sig = String::from("(I)Lorg/bukkit/inventory/MerchantRecipe;"); - let val_1 = jni::objects::JValueGen::Int(i); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getRecipe", + "getPersistentDataContainer", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::MerchantRecipe::from_raw(&self.jni_ref(), unsafe { + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Set the recipe at a certain index of this merchant's trade list. - pub fn set_recipe( - &self, - i: i32, - recipe: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(ILorg/bukkit/inventory/MerchantRecipe;)V"); - let val_1 = jni::objects::JValueGen::Int(i); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRecipe", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the number of trades this merchant currently has available. - pub fn recipe_count(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRecipeCount", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets whether this merchant is currently trading. - pub fn is_trading(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isTrading", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the player this merchant is trading with, or null if it is not - /// currently trading. - pub fn trader( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTrader", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::HumanEntity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Villager<'mc> { - fn into(self) -> crate::entity::AbstractVillager<'mc> { - crate::entity::AbstractVillager::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Villager into crate::entity::AbstractVillager") - } -} -pub enum VillagerType<'mc> {} -impl<'mc> std::fmt::Display for VillagerType<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> VillagerType<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/Villager/Type"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/Villager/Type;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } +impl<'mc> Into> for Minecart<'mc> { + fn into(self) -> crate::entity::Vehicle<'mc> { + crate::entity::Vehicle::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Minecart into crate::entity::Vehicle") } } - #[repr(C)] -pub struct VillagerTypeStruct<'mc>( +pub struct Phantom<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for VillagerType<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for VillagerType<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate VillagerType from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Villager/Type")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a VillagerType object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for VillagerTypeStruct<'mc> { +impl<'mc> JNIRaw<'mc> for Phantom<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -79256,20 +88920,18 @@ impl<'mc> JNIRaw<'mc> for VillagerTypeStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for VillagerTypeStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Phantom<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate VillagerTypeStruct from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate Phantom from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Villager/Type")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Phantom")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a VillagerTypeStruct object, got {}", + "Invalid argument passed. Expected a Phantom object, got {}", name ) .into()) @@ -79279,258 +88941,227 @@ impl<'mc> JNIInstantiatable<'mc> for VillagerTypeStruct<'mc> { } } -impl<'mc> VillagerTypeStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Villager/Type;"); - let cls = jni.find_class("org/bukkit/entity/Villager/Type"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::VillagerType::from_raw(&jni, obj) - } - - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); +impl<'mc> Phantom<'mc> { + pub fn size(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -pub enum VillagerProfession<'mc> {} -impl<'mc> std::fmt::Display for VillagerProfession<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + Ok(res.i()?) } -} -impl<'mc> VillagerProfession<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/Villager/Profession"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/Villager/Profession;", + pub fn set_size(&self, sz: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(sz); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSize", + sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct VillagerProfessionStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for VillagerProfession<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for VillagerProfession<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate VillagerProfession from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Villager/Profession")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a VillagerProfession object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for VillagerProfessionStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + self.jni_ref().translate_error(res)?; + Ok(()) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Instructs this Mob to set the specified LivingEntity as its target. + /// + /// Hostile creatures may attack their target, and friendly creatures may + /// follow their target. + pub fn set_target( + &self, + target: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(target.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTarget", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -impl<'mc> JNIInstantiatable<'mc> for VillagerProfessionStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate VillagerProfessionStruct from null object." - ) - .into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Villager/Profession")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a VillagerProfessionStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + /// Gets the current target of this Mob + pub fn target( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTarget", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some(crate::entity::LivingEntity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } -} - -impl<'mc> VillagerProfessionStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Villager/Profession;"); - let cls = jni.find_class("org/bukkit/entity/Villager/Profession"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::VillagerProfession::from_raw(&jni, obj) + /// Sets whether this mob is aware of its surroundings. + /// Unaware mobs will still move if pushed, attacked, etc. but will not move + /// or perform any actions on their own. Unaware mobs may also have other + /// unspecified behaviours disabled, such as drowning. + pub fn set_aware(&self, aware: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(aware.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAware", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + /// Gets whether this mob is aware of its surroundings. + /// Unaware mobs will still move if pushed, attacked, etc. but will not move + /// or perform any actions on their own. Unaware mobs may also have other + /// unspecified behaviours disabled, such as drowning. + pub fn is_aware(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isAware", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct Giant<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Giant<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for Giant<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Giant from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Giant")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Giant object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + /// Get the {@link Sound} this mob makes while ambiently existing. This sound + /// may change depending on the current state of the entity, and may also + /// return null under specific conditions. This sound is not constant. + /// For instance, villagers will make different passive noises depending + /// on whether or not they are actively trading with a player, or make no + /// ambient noise while sleeping. + pub fn ambient_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAmbientSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } -} - -impl<'mc> Giant<'mc> { /// Gets the height of the living entity's eyes above its Location. pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { - let sig = String::from("(Z)D"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getEyeHeight", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + sig += ")D"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEyeHeight", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.d()?) } /// Get a Location detailing the current eye position of the living entity. pub fn eye_location(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Location;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets all blocks along the living entity's line of sight. + /// + /// This list contains all blocks from the living entity's eye position to + /// target inclusive. This method considers all blocks as 1x1x1 in size. + pub fn get_line_of_sight( + &self, + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/util/Set;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); + args.push(val_1); + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(max_distance); + args.push(val_2); + sig += ")Ljava/util/List;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLineOfSight", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Gets the block that the living entity has targeted. + /// + /// This method considers all blocks as 1x1x1 in size. To take exact block + /// collision shapes into account, see {@link #getTargetBlockExact(int, + /// FluidCollisionMode)}. + pub fn get_target_block( + &self, + transparent: impl Into>, + max_distance: i32, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/util/Set;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); + args.push(val_1); + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(max_distance); + args.push(val_2); + sig += ")Lorg/bukkit/block/Block;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTargetBlock", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { + crate::block::Block::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets all blocks along the living entity's line of sight. + /// Gets the last two blocks along the living entity's line of sight. /// - /// This list contains all blocks from the living entity's eye position to - /// target inclusive. This method considers all blocks as 1x1x1 in size. - pub fn get_line_of_sight( + /// The target block will be the last block in the list. This method + /// considers all blocks as 1x1x1 in size. + pub fn get_last_two_target_blocks( &self, transparent: impl Into>, max_distance: i32, ) -> Result>, Box> { - let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/util/Set;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) }); + args.push(val_1); + sig += "I"; let val_2 = jni::objects::JValueGen::Int(max_distance); + args.push(val_2); + sig += ")Ljava/util/List;"; let res = self.jni_ref().call_method( &self.jni_object(), - "getLineOfSight", + "getLastTwoTargetBlocks", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + args, ); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); @@ -79544,1277 +89175,2009 @@ impl<'mc> Giant<'mc> { } /// Gets the block that the living entity has targeted. /// - /// This method considers all blocks as 1x1x1 in size. To take exact block - /// collision shapes into account, see {@link #getTargetBlockExact(int, - /// FluidCollisionMode)}. - pub fn get_target_block( + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn get_target_block_exact( &self, - transparent: impl Into>, max_distance: i32, - ) -> Result, Box> { - let sig = String::from("(Ljava/util/Set;I)Lorg/bukkit/block/Block;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(max_distance); + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/block/Block;"; let res = self.jni_ref().call_method( &self.jni_object(), - "getTargetBlock", + "getTargetBlockExact", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + args, ); let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::block::Block::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets the last two blocks along the living entity's line of sight. + /// Performs a ray trace that provides information on the targeted block. /// - /// The target block will be the last block in the list. This method - /// considers all blocks as 1x1x1 in size. - pub fn get_last_two_target_blocks( + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn ray_trace_blocks( &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { - let sig = String::from("(Ljava/util/Set;I)Ljava/util/List;"); + max_distance: f64, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/util/RayTraceResult;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::util::RayTraceResult::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Returns the amount of air that the living entity has remaining, in + /// ticks. + pub fn remaining_air(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the amount of air that the living entity has remaining, in ticks. + pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setRemainingAir", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the maximum amount of air the living entity can have, in ticks. + pub fn maximum_air(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the maximum amount of air the living entity can have, in ticks. + pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setMaximumAir", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the item that the player is using (eating food, drawing back a bow, + /// blocking, etc.) + pub fn item_in_use( + &self, + ) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/inventory/ItemStack;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the number of ticks remaining for the current item's usage. + pub fn item_in_use_ticks(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemInUseTicks", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the number of ticks that remain for the current item's usage. + /// Applies to items that take time to use, like eating food, drawing a bow, + /// or throwing a trident. + pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setItemInUseTicks", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the time in ticks until the next arrow leaves the entity's body. + pub fn arrow_cooldown(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getArrowCooldown", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the time in ticks until the next arrow leaves the entity's body. + pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setArrowCooldown", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the amount of arrows in an entity's body. + pub fn arrows_in_body(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the amount of arrows in the entity's body. + pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(count); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setArrowsInBody", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the living entity's current maximum no damage ticks. + /// + /// This is the maximum duration in which the living entity will not take + /// damage. + pub fn maximum_no_damage_ticks(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaximumNoDamageTicks", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the living entity's current maximum no damage ticks. + pub fn set_maximum_no_damage_ticks( + &self, + ticks: i32, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); + args.push(val_1); + sig += ")V"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaximumNoDamageTicks", + sig.as_str(), + args, + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the living entity's last damage taken in the current no damage + /// ticks time. + /// + /// Only damage higher than this amount will further damage the living + /// entity. + pub fn last_damage(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")D"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Sets the damage dealt within the current no damage ticks time period. + pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(damage); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setLastDamage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the living entity's current no damage ticks. + pub fn no_damage_ticks(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getNoDamageTicks", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the living entity's current no damage ticks. + pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setNoDamageTicks", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn no_action_ticks(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getNoActionTicks", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setNoActionTicks", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the player identified as the killer of the living entity. + /// + /// May be null. + pub fn killer(&self) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/entity/Player;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKiller", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Player::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + #[deprecated] + /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. + pub fn add_potion_effect( + &self, + effect: impl Into>, + force: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/potion/PotionEffect;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(max_distance); + args.push(val_1); + if let Some(a) = force { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns whether the living entity already has an existing effect of + /// the given {@link PotionEffectType} applied to it. + pub fn has_potion_effect( + &self, + val_type: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/potion/PotionEffectType;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasPotionEffect", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the active {@link PotionEffect} of the specified type. + /// + /// If the effect is not present on the entity then null will be returned. + pub fn get_potion_effect( + &self, + val_type: impl Into>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/potion/PotionEffectType;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Lorg/bukkit/potion/PotionEffect;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPotionEffect", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::potion::PotionEffect::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Removes any effects present of the given {@link PotionEffectType}. + pub fn remove_potion_effect( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/potion/PotionEffectType;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "removePotionEffect", + sig.as_str(), + args, + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns all currently active {@link PotionEffect}s on the living + /// entity. + pub fn active_potion_effects( + &self, + ) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/util/Collection;"; let res = self.jni_ref().call_method( &self.jni_object(), - "getLastTwoTargetBlocks", + "getActivePotionEffects", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + args, ); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); } Ok(new_vec) } - /// Gets the block that the living entity has targeted. - /// - /// This takes the blocks' precise collision shapes into account. + /// Checks whether the living entity has block line of sight to another. /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn get_target_block_exact( + /// This uses the same algorithm that hostile mobs use to find the closest + /// player. + pub fn has_line_of_sight( &self, - max_distance: i32, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { + other: impl Into>, + ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(max_distance); + sig += "Lorg/bukkit/entity/Entity;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(other.into().jni_object().clone()) + }); args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/block/Block;"; + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasLineOfSight", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns if the living entity despawns when away from players or not. + /// + /// By default, animals are not removed while other mobs are. + pub fn remove_when_far_away(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self.jni_ref().call_method( &self.jni_object(), - "getTargetBlockExact", + "getRemoveWhenFarAway", sig.as_str(), args, ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::block::Block::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Performs a ray trace that provides information on the targeted block. - /// - /// This takes the blocks' precise collision shapes into account. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn ray_trace_blocks( - &self, - max_distance: f64, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { + /// Sets whether or not the living entity despawns when away from players + /// or not. + pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(max_distance); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(remove.into()); args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/util/RayTraceResult;"; + sig += ")V"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRemoveWhenFarAway", + sig.as_str(), + args, + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the inventory with the equipment worn by the living entity. + pub fn equipment( + &self, + ) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/inventory/EntityEquipment;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); + .call_method(&self.jni_object(), "getEquipment", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::util::RayTraceResult::from_raw( + Ok(Some(crate::inventory::EntityEquipment::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Returns the amount of air that the living entity has remaining, in - /// ticks. - pub fn remaining_air(&self) -> Result> { - let sig = String::from("()I"); + /// Sets whether or not the living entity can pick up items. + pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(pickup.into()); + args.push(val_1); + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the amount of air that the living entity has remaining, in ticks. - pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRemainingAir", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "setCanPickupItems", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the maximum amount of air the living entity can have, in ticks. - pub fn maximum_air(&self) -> Result> { - let sig = String::from("()I"); + /// Gets if the living entity can pick up items. + pub fn can_pickup_items(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCanPickupItems", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the maximum amount of air the living entity can have, in ticks. - pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaximumAir", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Returns whether the entity is currently leashed. + pub fn is_leashed(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isLeashed", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the item that the player is using (eating food, drawing back a bow, - /// blocking, etc.) - pub fn item_in_use( + /// Gets the entity that is currently leading this entity. + pub fn leash_holder(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/entity/Entity;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the leash on this entity to be held by the supplied entity. + /// + /// This method has no effect on EnderDragons, Withers, Players, or Bats. + /// Non-living entities excluding leashes will not persist as leash + /// holders. + pub fn set_leash_holder( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + holder: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Entity;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(holder.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "setLeashHolder", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Gets the number of ticks remaining for the current item's usage. - pub fn item_in_use_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getItemInUseTicks", - sig.as_str(), - vec![], - ); + /// Checks to see if an entity is gliding, such as using an Elytra. + pub fn is_gliding(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGliding", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the number of ticks that remain for the current item's usage. - /// Applies to items that take time to use, like eating food, drawing a bow, - /// or throwing a trident. - pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setItemInUseTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Makes entity start or stop gliding. This will work even if an Elytra + /// is not equipped, but will be reverted by the server immediately after + /// unless an event-cancelling mechanism is put in place. + pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(gliding.into()); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setGliding", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the time in ticks until the next arrow leaves the entity's body. - pub fn arrow_cooldown(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getArrowCooldown", - sig.as_str(), - vec![], - ); + /// Checks to see if an entity is swimming. + pub fn is_swimming(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSwimming", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the time in ticks until the next arrow leaves the entity's body. - pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setArrowCooldown", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Makes entity start or stop swimming. + /// This may have unexpected results if the entity is not in water. + pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(swimming.into()); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setSwimming", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the amount of arrows in an entity's body. - pub fn arrows_in_body(&self) -> Result> { - let sig = String::from("()I"); + /// Checks to see if an entity is currently riptiding. + pub fn is_riptiding(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Makes entity start or stop riptiding. + /// + /// Note: This does not damage attackable entities. + pub fn set_riptiding(&self, riptiding: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(riptiding.into()); + args.push(val_1); + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "setRiptiding", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns whether this entity is slumbering. + pub fn is_sleeping(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSleeping", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the amount of arrows in the entity's body. - pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(count); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setArrowsInBody", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Gets if the entity is climbing. + pub fn is_climbing(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isClimbing", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether an entity will have AI. + /// The entity will be completely unable to move if it has no AI. + pub fn set_ai(&self, ai: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(ai.into()); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setAI", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's current maximum no damage ticks. - /// - /// This is the maximum duration in which the living entity will not take - /// damage. - pub fn maximum_no_damage_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMaximumNoDamageTicks", - sig.as_str(), - vec![], - ); + /// Checks whether an entity has AI. + /// The entity will be completely unable to move if it has no AI. + pub fn has_ai(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasAI", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the living entity's current maximum no damage ticks. - pub fn set_maximum_no_damage_ticks( + /// Makes this entity attack the given entity with a melee attack. + /// Attack damage is calculated by the server from the attributes and + /// equipment of this mob, and knockback is applied to {@code target} as + /// appropriate. + pub fn attack( &self, - ticks: i32, + target: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaximumNoDamageTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Entity;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(target.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "attack", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's last damage taken in the current no damage - /// ticks time. - /// - /// Only damage higher than this amount will further damage the living - /// entity. - pub fn last_damage(&self) -> Result> { - let sig = String::from("()D"); + /// Makes this entity swing their main hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their main hand. + pub fn swing_main_hand(&self) -> Result<(), Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the damage dealt within the current no damage ticks time period. - pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(damage); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLastDamage", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Makes this entity swing their off hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their off hand. + pub fn swing_off_hand(&self) -> Result<(), Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's current no damage ticks. - pub fn no_damage_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getNoDamageTicks", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + /// Makes this entity flash red as if they were damaged. + pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "F"; + let val_1 = jni::objects::JValueGen::Float(yaw); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "playHurtAnimation", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the living entity's current no damage ticks. - pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setNoDamageTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Set if this entity will be subject to collisions with other entities. + /// + /// Exemptions to this rule can be managed with + /// {@link #getCollidableExemptions()} + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not working for player collisions. This + /// method should therefore only be used to set the collision status of + /// non-player entities. + /// + /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in + /// combination with a {@link Scoreboard} and a {@link Team}. + pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(collidable.into()); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setCollidable", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the ticks that this entity has performed no action. + /// Gets if this entity is subject to collisions with other entities. /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn no_action_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getNoActionTicks", - sig.as_str(), - vec![], - ); + /// Some entities might be exempted from the collidable rule of this entity. + /// Use {@link #getCollidableExemptions()} to get these. + /// + /// Please note that this method returns only the custom collidable state, + /// not whether the entity is non-collidable for other reasons such as being + /// dead. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not being accurate for player collisions. + /// This method should therefore only be used to check the collision status + /// of non-player entities. + /// + /// To check the collision behavior for a player, use + /// {@link Team.Option#COLLISION_RULE} in combination with a + /// {@link Scoreboard} and a {@link Team}. + pub fn is_collidable(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCollidable", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the ticks that this entity has performed no action. + /// Gets a mutable set of UUIDs of the entities which are exempt from the + /// entity's collidable rule and which's collision with this entity will + /// behave the opposite of it. /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// This set can be modified to add or remove exemptions. + /// + /// For example if collidable is true and an entity is in the exemptions set + /// then it will not collide with it. Similarly if collidable is false and an + /// entity is in this set then it will still collide with it. + /// + /// Note these exemptions are not (currently) persistent. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in those exemptions not being accurate for player + /// collisions. This method should therefore only be used to exempt + /// non-player entities. + /// + /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} + /// in combination with a {@link Scoreboard} and a {@link Team}. + pub fn collidable_exemptions( + &self, + ) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/util/Set;"; let res = self.jni_ref().call_method( &self.jni_object(), - "setNoActionTicks", + "getCollidableExemptions", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the player identified as the killer of the living entity. + /// Returns the value of the memory specified. /// - /// May be null. - pub fn killer(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Player;"); + /// Note that the value is null when the specific entity does not have that + /// value by default. + pub fn get_memory( + &self, + memory_key: impl Into>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/memory/MemoryKey;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")LT;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getKiller", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMemory", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Player::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(Some(res.l()?)) } - #[deprecated] - /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. - pub fn add_potion_effect( + /// Sets the value of the memory specified. + /// + /// Note that the value will not be persisted when the specific entity does + /// not have that value by default. + pub fn set_memory( &self, - effect: impl Into>, - force: std::option::Option, - ) -> Result> { + memory_key: impl Into>, + memory_value: jni::objects::JObject<'mc>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/potion/PotionEffect;"; + sig += "Lorg/bukkit/entity/memory/MemoryKey;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(effect.into().jni_object().clone()) + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) }); args.push(val_1); - if let Some(a) = force { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); + sig += "LT;"; + let val_2 = jni::objects::JValueGen::Object(memory_value); + args.push(val_2); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setMemory", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the {@link Sound} this entity will make when damaged. + pub fn hurt_sound(&self) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Sound;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - sig += ")Z"; + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Get the {@link Sound} this entity will make on death. + pub fn death_sound(&self) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); + .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Returns whether the living entity already has an existing effect of - /// the given {@link PotionEffectType} applied to it. - pub fn has_potion_effect( + /// Get the {@link Sound} this entity will make when falling from the given + /// height (in blocks). The sound will often differ between either a small + /// or a big fall damage sound if the height exceeds 4 blocks. + pub fn get_fall_damage_sound( &self, - val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + fall_height: i32, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(fall_height); + args.push(val_1); + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref().call_method( &self.jni_object(), - "hasPotionEffect", + "getFallDamageSound", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the active {@link PotionEffect} of the specified type. - /// - /// If the effect is not present on the entity then null will be returned. - pub fn get_potion_effect( - &self, - val_type: impl Into>, - ) -> Result>, Box> { - let sig = - String::from("(Lorg/bukkit/potion/PotionEffectType;)Lorg/bukkit/potion/PotionEffect;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Get the {@link Sound} this entity will make when falling from a small + /// height. + pub fn fall_damage_sound_small(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref().call_method( &self.jni_object(), - "getPotionEffect", + "getFallDamageSoundSmall", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::potion::PotionEffect::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Removes any effects present of the given {@link PotionEffectType}. - pub fn remove_potion_effect( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Get the {@link Sound} this entity will make when falling from a large + /// height. + pub fn fall_damage_sound_big(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref().call_method( &self.jni_object(), - "removePotionEffect", + "getFallDamageSoundBig", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns all currently active {@link PotionEffect}s on the living - /// entity. - pub fn active_potion_effects( + /// Get the {@link Sound} this entity will make when drinking the given + /// {@link ItemStack}. + pub fn get_drinking_sound( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getActivePotionEffects", - sig.as_str(), - vec![], - ); + item_stack: impl Into>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Lorg/bukkit/Sound;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDrinkingSound", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Checks whether the living entity has block line of sight to another. - /// - /// This uses the same algorithm that hostile mobs use to find the closest - /// player. - pub fn has_line_of_sight( + /// Get the {@link Sound} this entity will make when eating the given + /// {@link ItemStack}. + pub fn get_eating_sound( &self, - other: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + item_stack: impl Into>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) }); + args.push(val_1); + sig += ")Lorg/bukkit/Sound;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEatingSound", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns true if this entity can breathe underwater and will not take + /// suffocation damage when its air supply reaches zero. + pub fn can_breathe_underwater(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self.jni_ref().call_method( &self.jni_object(), - "hasLineOfSight", + "canBreatheUnderwater", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns if the living entity despawns when away from players or not. - /// - /// By default, animals are not removed while other mobs are. - pub fn remove_when_far_away(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getRemoveWhenFarAway", - sig.as_str(), - vec![], - ); + #[deprecated] + /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. + pub fn category( + &self, + ) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/entity/EntityCategory;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCategory", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets whether the entity is invisible or not. + pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(invisible.into()); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setInvisible", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether the entity is invisible or not. + pub fn is_invisible(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInvisible", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not the living entity despawns when away from players - /// or not. - pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(remove.into()); + /// Gets the specified attribute instance from the object. This instance will + /// be backed directly to the object and any changes will be visible at once. + pub fn get_attribute( + &self, + attribute: impl Into>, + ) -> Result>, Box> { + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setRemoveWhenFarAway", + "getAttribute", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the inventory with the equipment worn by the living entity. - pub fn equipment( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/EntityEquipment;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEquipment", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::EntityEquipment::from_raw( + Ok(Some(crate::attribute::AttributeInstance::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets whether or not the living entity can pick up items. - pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(pickup.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCanPickupItems", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Deals the given amount of damage to this entity from a specified + /// {@link DamageSource}. + pub fn damage( + &self, + amount: f64, + damage_source: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(amount); + args.push(val_1); + if let Some(a) = damage_source { + sig += "Lorg/bukkit/damage/DamageSource;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "damage", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the living entity can pick up items. - pub fn can_pickup_items(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCanPickupItems", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns whether the entity is currently leashed. - pub fn is_leashed(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. + pub fn health(&self) -> Result> { + let sig = String::from("()D"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isLeashed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the entity that is currently leading this entity. - pub fn leash_holder(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.d()?) } - /// Sets the leash on this entity to be held by the supplied entity. - /// - /// This method has no effect on EnderDragons, Withers, Players, or Bats. - /// Non-living entities excluding leashes will not persist as leash - /// holders. - pub fn set_leash_holder( - &self, - holder: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(holder.into().jni_object().clone()) - }); + /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is + /// dead. + pub fn set_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setHealth", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the entity's absorption amount. + pub fn absorption_amount(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref().call_method( &self.jni_object(), - "setLeashHolder", + "getAbsorptionAmount", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Checks to see if an entity is gliding, such as using an Elytra. - pub fn is_gliding(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Makes entity start or stop gliding. This will work even if an Elytra - /// is not equipped, but will be reverted by the server immediately after - /// unless an event-cancelling mechanism is put in place. - pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gliding.into()); + /// Sets the entity's absorption amount. + /// + /// Note: The amount is capped to the value of + /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on + /// that attribute is currently unspecified and subject to change. + pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "setGliding", + "setAbsorptionAmount", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks to see if an entity is swimming. - pub fn is_swimming(&self) -> Result> { - let sig = String::from("()Z"); + #[deprecated] + /// Gets the maximum health this entity has. + pub fn max_health(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Makes entity start or stop swimming. - /// This may have unexpected results if the entity is not in water. - pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(swimming.into()); + #[deprecated] + /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. + pub fn set_max_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "setSwimming", + "setMaxHealth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks to see if an entity is currently using the Riptide enchantment. - pub fn is_riptiding(&self) -> Result> { - let sig = String::from("()Z"); + #[deprecated] + /// Resets the max health to the original amount. + pub fn reset_max_health(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns whether this entity is slumbering. - pub fn is_sleeping(&self) -> Result> { - let sig = String::from("()Z"); + /// Launches a {@link Projectile} from the ProjectileSource with an + /// initial velocity. + pub fn launch_projectile( + &self, + projectile: jni::objects::JClass<'mc>, + velocity: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(projectile.into()); + args.push(val_1); + if let Some(a) = velocity { + sig += "Lorg/bukkit/util/Vector;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")LT;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "isSleeping", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Phantom<'mc> { + fn into(self) -> crate::entity::Flying<'mc> { + crate::entity::Flying::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Phantom into crate::entity::Flying") + } +} +impl<'mc> Into> for Phantom<'mc> { + fn into(self) -> crate::entity::Enemy<'mc> { + crate::entity::Enemy::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Phantom into crate::entity::Enemy") + } +} +#[repr(C)] +pub struct Drowned<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Drowned<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Drowned<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Drowned from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Drowned")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Drowned object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Drowned<'mc> { + #[deprecated] + /// Gets whether the zombie is a baby + pub fn is_baby(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isBaby", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets if the entity is climbing. - pub fn is_climbing(&self) -> Result> { + #[deprecated] + /// Sets whether the zombie is a baby + pub fn set_baby( + &self, + flag: std::option::Option, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = flag { + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_1); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setBaby", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets whether the zombie is a villager + pub fn is_villager(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isClimbing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isVillager", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether an entity will have AI. - /// The entity will be completely unable to move if it has no AI. - pub fn set_ai(&self, ai: bool) -> Result<(), Box> { + #[deprecated] + + pub fn set_villager(&self, flag: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(ai.into()); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setAI", + "setVillager", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks whether an entity has AI. - /// The entity will be completely unable to move if it has no AI. - pub fn has_ai(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasAI", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Makes this entity attack the given entity with a melee attack. - /// Attack damage is calculated by the server from the attributes and - /// equipment of this mob, and knockback is applied to {@code target} as - /// appropriate. - pub fn attack( + #[deprecated] + + pub fn set_villager_profession( &self, - target: impl Into>, + profession: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + let sig = String::from("(Lorg/bukkit/entity/Villager/Profession;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) + jni::objects::JObject::from_raw(profession.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "attack", + "setVillagerProfession", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Makes this entity swing their main hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their main hand. - pub fn swing_main_hand(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + #[deprecated] + + pub fn villager_profession( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Villager/Profession;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getVillagerProfession", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::VillagerProfession::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Makes this entity swing their off hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their off hand. - pub fn swing_off_hand(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Get if this entity is in the process of converting to a Drowned as a + /// result of being underwater. + pub fn is_converting(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "isConverting", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Makes this entity flash red as if they were damaged. - pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); + /// Gets the amount of ticks until this entity will be converted to a Drowned + /// as a result of being underwater. + /// When this reaches 0, the entity will be converted. + pub fn conversion_time(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "playHurtAnimation", + "getConversionTime", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Set if this entity will be subject to collisions with other entities. - /// - /// Exemptions to this rule can be managed with - /// {@link #getCollidableExemptions()} - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not working for player collisions. This - /// method should therefore only be used to set the collision status of - /// non-player entities. - /// - /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in - /// combination with a {@link Scoreboard} and a {@link Team}. - pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(collidable.into()); + /// Sets the amount of ticks until this entity will be converted to a Drowned + /// as a result of being underwater. + /// When this reaches 0, the entity will be converted. A value of less than 0 + /// will stop the current conversion process without converting the current + /// entity. + pub fn set_conversion_time(&self, time: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(time); let res = self.jni_ref().call_method( &self.jni_object(), - "setCollidable", + "setConversionTime", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if this entity is subject to collisions with other entities. - /// - /// Some entities might be exempted from the collidable rule of this entity. - /// Use {@link #getCollidableExemptions()} to get these. - /// - /// Please note that this method returns only the custom collidable state, - /// not whether the entity is non-collidable for other reasons such as being - /// dead. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not being accurate for player collisions. - /// This method should therefore only be used to check the collision status - /// of non-player entities. - /// - /// To check the collision behavior for a player, use - /// {@link Team.Option#COLLISION_RULE} in combination with a - /// {@link Scoreboard} and a {@link Team}. - pub fn is_collidable(&self) -> Result> { + /// Gets whether this zombie can break doors + pub fn can_break_doors(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCollidable", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "canBreakDoors", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets a mutable set of UUIDs of the entities which are exempt from the - /// entity's collidable rule and which's collision with this entity will - /// behave the opposite of it. - /// - /// This set can be modified to add or remove exemptions. - /// - /// For example if collidable is true and an entity is in the exemptions set - /// then it will not collide with it. Similarly if collidable is false and an - /// entity is in this set then it will still collide with it. - /// - /// Note these exemptions are not (currently) persistent. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in those exemptions not being accurate for player - /// collisions. This method should therefore only be used to exempt - /// non-player entities. - /// - /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} - /// in combination with a {@link Scoreboard} and a {@link Team}. - pub fn collidable_exemptions( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Sets whether this zombie can break doors + /// This will be ignored if the entity is a Drowned. Will also stop the action if + /// the entity is currently breaking a door. + pub fn set_can_break_doors(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getCollidableExemptions", + "setCanBreakDoors", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the age of this mob. + pub fn age(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getAge", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Returns the value of the memory specified. - /// - /// Note that the value is null when the specific entity does not have that - /// value by default. - pub fn get_memory( - &self, - memory_key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;)LT;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) - }); + /// Sets the age of this mob. + pub fn set_age(&self, age: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(age); let res = self.jni_ref().call_method( &self.jni_object(), - "getMemory", + "setAge", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Lock the age of the animal, setting this will prevent the animal from maturing or getting ready for mating. + pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(lock.into()); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setAgeLock", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the current agelock. + pub fn age_lock(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + Ok(res.z()?) + } + /// Sets the age of the mob to an adult + pub fn set_adult(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setAdult", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns true if the mob is an adult. + pub fn is_adult(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isAdult", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Return the ability to breed of the animal. + pub fn can_breed(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "canBreed", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Set breedability of the animal, if the animal is a baby and set to breed it will instantly grow up. + pub fn set_breed(&self, breed: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(breed.into()); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setBreed", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Drowned<'mc> { + fn into(self) -> crate::entity::Zombie<'mc> { + crate::entity::Zombie::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Drowned into crate::entity::Zombie") + } +} +#[repr(C)] +pub struct DragonFireball<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for DragonFireball<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for DragonFireball<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate DragonFireball from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/DragonFireball")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a DragonFireball object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - Ok(Some(res.l()?)) } - /// Sets the value of the memory specified. +} + +impl<'mc> DragonFireball<'mc> { + /// Sets the direction the fireball should be flying towards. /// - /// Note that the value will not be persisted when the specific entity does - /// not have that value by default. - pub fn set_memory( + /// This is a convenience method, it will change the velocity direction and + /// acceleration direction, while keeping the power the same. + /// + /// Note: This method only uses the direction of the vector and will + /// normalize (a copy of) it. + /// + /// Special Case: When the given direction is + /// {@link Vector#isZero() zero}, the velocity and acceleration will also be + /// set to zero without keeping the power. + pub fn set_direction( &self, - memory_key: impl Into>, - memory_value: jni::objects::JObject<'mc>, + direction: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/memory/MemoryKey;LT;)V"); + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + jni::objects::JObject::from_raw(direction.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Object(memory_value); let res = self.jni_ref().call_method( &self.jni_object(), - "setMemory", + "setDirection", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the {@link Sound} this entity will make when damaged. - pub fn hurt_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Get the {@link Sound} this entity will make on death. - pub fn death_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + #[deprecated] + /// Retrieve the direction this fireball is heading toward. The returned vector is not normalized. + pub fn direction(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + }) } - /// Get the {@link Sound} this entity will make when falling from the given - /// height (in blocks). The sound will often differ between either a small - /// or a big fall damage sound if the height exceeds 4 blocks. - pub fn get_fall_damage_sound( + /// Sets the acceleration of the fireball. + /// The acceleration gets applied to the velocity every tick, depending on + /// the specific type of the fireball a damping / drag factor is applied so + /// that the velocity does not grow into infinity. + /// + /// Note: that the client may not respect non-default acceleration + /// power and will therefore mispredict the location of the fireball, causing + /// visual stutter. + pub fn set_acceleration( &self, - fall_height: i32, - ) -> Result, Box> { - let sig = String::from("(I)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Int(fall_height); + acceleration: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(acceleration.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSound", + "setAcceleration", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the {@link Sound} this entity will make when falling from a small - /// height. - pub fn fall_damage_sound_small(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFallDamageSoundSmall", - sig.as_str(), - vec![], - ); + /// Retrieve the acceleration of this fireball. + pub fn acceleration(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAcceleration", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the {@link Sound} this entity will make when falling from a large - /// height. - pub fn fall_damage_sound_big(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFallDamageSoundBig", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Get the {@link Sound} this entity will make when drinking the given - /// {@link ItemStack}. - pub fn get_drinking_sound( +} +impl<'mc> Into> for DragonFireball<'mc> { + fn into(self) -> crate::entity::Fireball<'mc> { + crate::entity::Fireball::from_raw(&self.jni_ref(), self.1) + .expect("Error converting DragonFireball into crate::entity::Fireball") + } +} +#[repr(C)] +pub struct Ravager<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Ravager<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Ravager<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Ravager from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Ravager")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Ravager object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Ravager<'mc> { + /// Set the {@link Raid} that this raider is participating in. + pub fn set_raid( &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); + raid: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Raid;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + jni::objects::JObject::from_raw(raid.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getDrinkingSound", + "setRaid", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the {@link Raid} that this raider is participating in, if any. + pub fn raid(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Raid;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRaid", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Raid::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) + })?)) } - /// Get the {@link Sound} this entity will make when eating the given - /// {@link ItemStack}. - pub fn get_eating_sound( - &self, - item_stack: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/Sound;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getEatingSound", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Get the raid wave that this raider spawned as part of. + pub fn wave(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWave", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Returns true if this entity can breathe underwater and will not take - /// suffocation damage when its air supply reaches zero. - pub fn can_breathe_underwater(&self) -> Result> { - let sig = String::from("()Z"); + /// Set the raid wave that this raider was spawned as part of. + pub fn set_wave(&self, wave: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(wave); let res = self.jni_ref().call_method( &self.jni_object(), - "canBreatheUnderwater", + "setWave", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - #[deprecated] - /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. - pub fn category( + /// Gets the block the raider is targeting to patrol. + pub fn patrol_target( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityCategory;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPatrolTarget", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::block::Block::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets whether the entity is invisible or not. - pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(invisible.into()); + /// Sets the block the raider is targeting to patrol. + pub fn set_patrol_target( + &self, + block: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/Block;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(block.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setInvisible", + "setPatrolTarget", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invisible or not. - pub fn is_invisible(&self) -> Result> { + /// Gets whether this entity is a patrol leader. + pub fn is_patrol_leader(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isInvisible", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isPatrolLeader", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the specified attribute instance from the object. This instance will - /// be backed directly to the object and any changes will be visible at once. - pub fn get_attribute( - &self, - attribute: impl Into>, - ) -> Result>, Box> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); + /// Sets whether this entity is a patrol leader. + pub fn set_patrol_leader(&self, leader: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(leader.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getAttribute", + "setPatrolLeader", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::attribute::AttributeInstance::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Deals the given amount of damage to this entity from a specified - /// {@link DamageSource}. - pub fn damage( - &self, - amount: f64, - damage_source: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(amount); - args.push(val_1); - if let Some(a) = damage_source { - sig += "Lorg/bukkit/damage/DamageSource;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "damage", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. - pub fn health(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); + /// Gets whether this mob can join an active raid. + pub fn is_can_join_raid(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCanJoinRaid", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is - /// dead. - pub fn set_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); + /// Sets whether this mob can join an active raid. + pub fn set_can_join_raid(&self, join: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(join.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setHealth", + "setCanJoinRaid", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the entity's absorption amount. - pub fn absorption_amount(&self) -> Result> { - let sig = String::from("()D"); + /// Get the amount of ticks that this mob has exited the bounds of a village + /// as a raid participant. + /// + /// This value is increased only when the mob has had no action for 2,400 ticks + /// (according to {@link #getNoActionTicks()}). Once both the no action ticks have + /// reached that value and the ticks outside a raid exceeds 30, the mob will be + /// expelled from the raid. + pub fn ticks_outside_raid(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getAbsorptionAmount", + "getTicksOutsideRaid", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.i()?) } - /// Sets the entity's absorption amount. + /// Set the amount of ticks that this mob has exited the bounds of a village + /// as a raid participant. /// - /// Note: The amount is capped to the value of - /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on - /// that attribute is currently unspecified and subject to change. - pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(amount); + /// This value is considered only when the mob has had no action for 2,400 ticks + /// (according to {@link #getNoActionTicks()}). Once both the no action ticks have + /// reached that value and the ticks outside a raid exceeds 30, the mob will be + /// expelled from the raid. + pub fn set_ticks_outside_raid(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setAbsorptionAmount", + "setTicksOutsideRaid", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the maximum health this entity has. - pub fn max_health(&self) -> Result> { - let sig = String::from("()D"); + /// Check whether or not this raider is celebrating a raid victory. + pub fn is_celebrating(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCelebrating", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - #[deprecated] - /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. - pub fn set_max_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); + /// Set whether or not this mob is celebrating a raid victory. + pub fn set_celebrating(&self, celebrating: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(celebrating.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxHealth", + "setCelebrating", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Resets the max health to the original amount. - pub fn reset_max_health(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Launches a {@link Projectile} from the ProjectileSource with an - /// initial velocity. - pub fn launch_projectile( - &self, - projectile: jni::objects::JClass<'mc>, - velocity: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/Class;"; - let val_1 = jni::objects::JValueGen::Object(projectile.into()); - args.push(val_1); - if let Some(a) = velocity { - sig += "Lorg/bukkit/util/Vector;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")LT;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); + /// Get the {@link Sound} this entity will play when celebrating. + pub fn celebration_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCelebrationSound", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -80822,19 +91185,19 @@ impl<'mc> Giant<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Giant<'mc> { - fn into(self) -> crate::entity::Monster<'mc> { - crate::entity::Monster::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Giant into crate::entity::Monster") +impl<'mc> Into> for Ravager<'mc> { + fn into(self) -> crate::entity::Raider<'mc> { + crate::entity::Raider::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Ravager into crate::entity::Raider") } } #[repr(C)] -pub struct EnderCrystal<'mc>( +pub struct Pillager<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EnderCrystal<'mc> { +impl<'mc> JNIRaw<'mc> for Pillager<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -80842,1678 +91205,1716 @@ impl<'mc> JNIRaw<'mc> for EnderCrystal<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EnderCrystal<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Pillager<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate EnderCrystal from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Pillager from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EnderCrystal")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Pillager")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EnderCrystal object, got {}", + "Invalid argument passed. Expected a Pillager object, got {}", name ) .into()) } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> EnderCrystal<'mc> { - /// Return whether or not this end crystal is showing the - /// bedrock slate underneath it. - pub fn is_showing_bottom(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isShowingBottom", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether or not this end crystal is showing the - /// bedrock slate underneath it. - pub fn set_showing_bottom(&self, showing: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(showing.into()); + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Pillager<'mc> { + /// Set the {@link Raid} that this raider is participating in. + pub fn set_raid( + &self, + raid: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Raid;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(raid.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setShowingBottom", + "setRaid", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the location that this end crystal is pointing its beam to. - pub fn beam_target(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBeamTarget", sig.as_str(), vec![]); + /// Get the {@link Raid} that this raider is participating in, if any. + pub fn raid(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Raid;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRaid", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + Ok(Some(crate::Raid::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) })?)) } - /// Sets the location that this end crystal is pointing to. Passing a null - /// value will remove the current beam. - pub fn set_beam_target( - &self, - location: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Location;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); + /// Get the raid wave that this raider spawned as part of. + pub fn wave(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWave", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the raid wave that this raider was spawned as part of. + pub fn set_wave(&self, wave: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(wave); let res = self.jni_ref().call_method( &self.jni_object(), - "setBeamTarget", + "setWave", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Stores the entity's current position in the provided Location object. - /// - /// If the provided Location is null this method does nothing and returns - /// null. - pub fn get_location( + /// Gets the block the raider is targeting to patrol. + pub fn patrol_target( &self, - loc: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLocation", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPatrolTarget", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(Some(crate::block::Block::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets this entity's velocity in meters per tick - pub fn set_velocity( + /// Sets the block the raider is targeting to patrol. + pub fn set_patrol_target( &self, - velocity: impl Into>, + block: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let sig = String::from("(Lorg/bukkit/block/Block;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + jni::objects::JObject::from_raw(block.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVelocity", + "setPatrolTarget", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets this entity's current velocity - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the entity's height - pub fn height(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the entity's width - pub fn width(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the entity's current bounding box. - /// - /// The returned bounding box reflects the entity's current location and - /// size. - pub fn bounding_box( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns true if the entity is supported by a block. This value is a - /// state updated by the server and is not recalculated unless the entity - /// moves. - pub fn is_on_ground(&self) -> Result> { + /// Gets whether this entity is a patrol leader. + pub fn is_patrol_leader(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns true if the entity is in water. - pub fn is_in_water(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isPatrolLeader", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the current world this entity resides in - pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the entity's rotation. - /// - /// Note that if the entity is affected by AI, it may override this rotation. - pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { - let sig = String::from("(FF)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); - let val_2 = jni::objects::JValueGen::Float(pitch); + /// Sets whether this entity is a patrol leader. + pub fn set_patrol_leader(&self, leader: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(leader.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setRotation", + "setPatrolLeader", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Teleports this entity to the given location. If this entity is riding a - /// vehicle, it will be dismounted prior to teleportation. - pub fn teleport( - &self, - location: impl Into>, - cause: std::option::Option< - impl Into>, - >, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = cause { - sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "teleport", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns a list of entities within a bounding box centered around this - /// entity - pub fn get_nearby_entities( - &self, - x: f64, - y: f64, - z: f64, - ) -> Result>, Box> { - let sig = String::from("(DDD)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Double(x); - let val_2 = jni::objects::JValueGen::Double(y); - let val_3 = jni::objects::JValueGen::Double(z); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getNearbyEntities", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Returns a unique id for this entity - pub fn entity_id(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn fire_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the entity's maximum fire ticks. - pub fn max_fire_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Gets whether this mob can join an active raid. + pub fn is_can_join_raid(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCanJoinRaid", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFireTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.z()?) } - /// Sets if the entity has visual fire (it will always appear to be on fire). - pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { + /// Sets whether this mob can join an active raid. + pub fn set_can_join_raid(&self, join: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire.into()); + let val_1 = jni::objects::JValueGen::Bool(join.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisualFire", + "setCanJoinRaid", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity has visual fire (it will always appear to be on fire). - pub fn is_visual_fire(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the entity's maximum freeze ticks (amount of ticks before it will - /// be fully frozen) - pub fn max_freeze_ticks(&self) -> Result> { + /// Get the amount of ticks that this mob has exited the bounds of a village + /// as a raid participant. + /// + /// This value is increased only when the mob has had no action for 2,400 ticks + /// (according to {@link #getNoActionTicks()}). Once both the no action ticks have + /// reached that value and the ticks outside a raid exceeds 30, the mob will be + /// expelled from the raid. + pub fn ticks_outside_raid(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getMaxFreezeTicks", + "getTicksOutsideRaid", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Set the amount of ticks that this mob has exited the bounds of a village + /// as a raid participant. + /// + /// This value is considered only when the mob has had no action for 2,400 ticks + /// (according to {@link #getNoActionTicks()}). Once both the no action ticks have + /// reached that value and the ticks outside a raid exceeds 30, the mob will be + /// expelled from the raid. + pub fn set_ticks_outside_raid(&self, ticks: i32) -> Result<(), Box> { let sig = String::from("(I)V"); let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setFreezeTicks", + "setTicksOutsideRaid", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity is fully frozen (it has been in powdered snow for max - /// freeze ticks). - pub fn is_frozen(&self) -> Result> { + /// Check whether or not this raider is celebrating a raid victory. + pub fn is_celebrating(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCelebrating", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Mark the entity's removal. - pub fn remove(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); + /// Set whether or not this mob is celebrating a raid victory. + pub fn set_celebrating(&self, celebrating: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(celebrating.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCelebrating", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns true if this entity has been marked for removal. - pub fn is_dead(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns false if the entity has died, been despawned for some other - /// reason, or has not been added to the world. - pub fn is_valid(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the {@link Server} that contains this Entity - pub fn server(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Server;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); + /// Get the {@link Sound} this entity will play when celebrating. + pub fn celebration_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCelebrationSound", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::Server::from_raw(&self.jni_ref(), unsafe { + crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns true if the entity gets persisted. - /// - /// By default all entities are persistent. An entity will also not get - /// persisted, if it is riding an entity that is not persistent. - /// - /// The persistent flag on players controls whether or not to save their - /// playerdata file when they quit. If a player is directly or indirectly - /// riding a non-persistent entity, the vehicle at the root and all its - /// passengers won't get persisted. - /// - /// This should not be confused with - /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls - /// despawning of living entities. - pub fn is_persistent(&self) -> Result> { - let sig = String::from("()Z"); + /// Get the object's inventory. + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets whether or not the entity gets persisted. - pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(persistent.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPersistent", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - #[deprecated] - /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. - pub fn passenger( +} +impl<'mc> Into> for Pillager<'mc> { + fn into(self) -> crate::entity::Illager<'mc> { + crate::entity::Illager::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Pillager into crate::entity::Illager") + } +} +impl<'mc> Into> for Pillager<'mc> { + fn into(self) -> crate::inventory::InventoryHolder<'mc> { + crate::inventory::InventoryHolder::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Pillager into crate::inventory::InventoryHolder") + } +} +#[repr(C)] +pub struct Cow<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Cow<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Cow<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Cow from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Cow")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Cow object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Cow<'mc> { + /// Get the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn breed_cause( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/UUID;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Entity::from_raw( + Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - #[deprecated] - /// Set the passenger of a vehicle. - pub fn set_passenger( + /// Set the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn set_breed_cause( &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + uuid: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/UUID;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPassenger", + "setBreedCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets a list of passengers of this vehicle. - /// - /// The returned list will not be directly linked to the entity's current - /// passengers, and no guarantees are made as to its mutability. - pub fn passengers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + /// Get whether or not this entity is in love mode and will produce + /// offspring with another entity in love mode. Will return true if + /// and only if {@link #getLoveModeTicks()} is greater than 0. + pub fn is_love_mode(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(res.z()?) } - /// Add a passenger to the vehicle. - pub fn add_passenger( - &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); + /// Get the amount of ticks remaining for this entity in love mode. + /// If the entity is not in love mode, 0 will be returned. + pub fn love_mode_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "addPassenger", + "getLoveModeTicks", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Remove a passenger from the vehicle. - pub fn remove_passenger( - &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); + /// Set the amount of ticks for which this entity should be in love mode. + /// Setting the love mode ticks to 600 is the equivalent of a player + /// feeding the entity their breeding item of choice. + pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "removePassenger", + "setLoveModeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Check if the provided ItemStack is the correct item used for breeding + /// this entity.. + pub fn is_breed_item( + &self, + material: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Check if a vehicle has passengers. - pub fn is_empty(&self) -> Result> { - let sig = String::from("()Z"); + /// Lock the age of the animal, setting this will prevent the animal from + /// maturing or getting ready for mating. + pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(lock.into()); + args.push(val_1); + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "setAgeLock", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the current agelock. + pub fn age_lock(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Eject any passenger. - pub fn eject(&self) -> Result> { - let sig = String::from("()Z"); + /// Return the ability to breed of the animal. + pub fn can_breed(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "canBreed", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns the distance this entity has fallen - pub fn fall_distance(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); + /// Set breedability of the animal, if the animal is a baby and set to + /// breed it will instantly grow up. + pub fn set_breed(&self, breed: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(breed.into()); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setBreed", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Cow<'mc> { + fn into(self) -> crate::entity::Animals<'mc> { + crate::entity::Animals::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Cow into crate::entity::Animals") + } +} +#[repr(C)] +pub struct Wolf<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Wolf<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Wolf<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Wolf from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Wolf")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Wolf object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Wolf<'mc> { + /// Checks if this wolf is angry + pub fn is_angry(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isAngry", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + Ok(res.z()?) } - /// Sets the fall distance for this entity - pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(distance); + /// Sets the anger of this wolf. + /// + /// An angry wolf can not be fed or tamed. + pub fn set_angry(&self, angry: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(angry.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setFallDistance", + "setAngry", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Record the last {@link EntityDamageEvent} inflicted on this entity - pub fn set_last_damage_cause( + /// Get the collar color of this wolf + pub fn collar_color(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/DyeColor;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCollarColor", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::DyeColor::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Set the collar color of this wolf + pub fn set_collar_color( &self, - event: impl Into>, + color: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); + let sig = String::from("(Lorg/bukkit/DyeColor;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(event.into().jni_object().clone()) + jni::objects::JObject::from_raw(color.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDamageCause", + "setCollarColor", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. - /// This event may have been cancelled. - pub fn last_damage_cause( - &self, - ) -> Result>, Box> - { - let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLastDamageCause", - sig.as_str(), - vec![], - ); + /// Gets whether the wolf is wet + pub fn is_wet(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isWet", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Returns a unique and persistent id for this entity - pub fn unique_id( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); + /// Gets the wolf's tail angle in radians + pub fn tail_angle(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTailAngle", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.f()?) } - /// Gets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. - pub fn ticks_lived(&self) -> Result> { - let sig = String::from("()I"); + /// Gets if the wolf is interested + pub fn is_interested(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInterested", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. May not be less than one - /// tick. - pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(value); + /// Set wolf to be interested + pub fn set_interested(&self, interested: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(interested.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setTicksLived", + "setInterested", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Performs the specified {@link EntityEffect} for this entity. - /// - /// This will be viewable to all players near the entity. - /// - /// If the effect is not applicable to this class of entity, it will not play. - pub fn play_effect( + /// Get the variant of this wolf. + pub fn variant(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Wolf/Variant;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::WolfVariant::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Set the variant of this wolf. + pub fn set_variant( &self, - val_type: impl Into>, + variant: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); + let sig = String::from("(Lorg/bukkit/entity/Wolf/Variant;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(variant.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "playEffect", + "setVariant", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the type of the entity. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + /// Check if this is tamed + /// + /// If something is tamed then a player can not tame it through normal + /// methods, even if it does not belong to anyone in particular. + pub fn is_tamed(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity makes while swimming. - pub fn swim_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity makes when splashing in water. For most - /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_splash_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSwimSplashSound", - sig.as_str(), - vec![], - ); + .call_method(&self.jni_object(), "isTamed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Get the {@link Sound} this entity makes when splashing in water at high - /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_high_speed_splash_sound( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + /// Sets if this has been tamed. Not necessary if the method setOwner has + /// been used, as it tames automatically. + /// + /// If something is tamed then a player can not tame it through normal + /// methods, even if it does not belong to anyone in particular. + pub fn set_tamed(&self, tame: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(tame.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimHighSpeedSplashSound", + "setTamed", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns whether this entity is inside a vehicle. - pub fn is_inside_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Leave the current vehicle. If the entity is currently in a vehicle (and - /// is removed from it), true will be returned, otherwise false will be - /// returned. - pub fn leave_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the vehicle that this entity is inside. If there is no vehicle, - /// null will be returned. - pub fn vehicle( + /// Gets the current owning AnimalTamer + pub fn owner( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/AnimalTamer;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Entity::from_raw( + Ok(Some(crate::entity::AnimalTamer::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets whether or not to display the mob's custom name client side. The - /// name will be displayed above the mob similarly to a player. + /// Set this to be owned by given AnimalTamer. /// - /// This value has no effect on players, they will always display their - /// name. - pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// If the owner is not null, this will be tamed and will have any current + /// path it is following removed. If the owner is set to null, this will be + /// untamed, and the current owner removed. + pub fn set_owner( + &self, + tamer: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/AnimalTamer;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(tamer.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomNameVisible", + "setOwner", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not the mob's custom name is displayed client side. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn is_custom_name_visible(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isCustomNameVisible", - sig.as_str(), - vec![], - ); + /// Get the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn breed_cause( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(visible.into()); + /// Set the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn set_breed_cause( + &self, + uuid: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/UUID;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisibleByDefault", + "setBreedCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn is_visible_by_default(&self) -> Result> { + /// Get whether or not this entity is in love mode and will produce + /// offspring with another entity in love mode. Will return true if + /// and only if {@link #getLoveModeTicks()} is greater than 0. + pub fn is_love_mode(&self) -> Result> { let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the amount of ticks remaining for this entity in love mode. + /// If the entity is not in love mode, 0 will be returned. + pub fn love_mode_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "isVisibleByDefault", + "getLoveModeTicks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get all players that are currently tracking this entity. - /// - /// 'Tracking' means that this entity has been sent to the player and that - /// they are receiving updates on its state. Note that the client's {@code - /// 'Entity Distance'} setting does not affect the range at which entities - /// are tracked. - pub fn tracked_by( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Sets whether the entity has a team colored (default: white) glow. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Set the amount of ticks for which this entity should be in love mode. + /// Setting the love mode ticks to 600 is the equivalent of a player + /// feeding the entity their breeding item of choice. + pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setGlowing", + "setLoveModeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is glowing or not. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn is_glowing(&self) -> Result> { - let sig = String::from("()Z"); + /// Check if the provided ItemStack is the correct item used for breeding + /// this entity.. + pub fn is_breed_item( + &self, + material: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the entity is invulnerable or not. - /// - /// When an entity is invulnerable it can only be damaged by players in - /// creative mode. - pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setInvulnerable", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Lock the age of the animal, setting this will prevent the animal from + /// maturing or getting ready for mating. + pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(lock.into()); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setAgeLock", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invulnerable or not. - pub fn is_invulnerable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); + /// Gets the current agelock. + pub fn age_lock(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets whether the entity is silent or not. - pub fn is_silent(&self) -> Result> { - let sig = String::from("()Z"); + /// Return the ability to breed of the animal. + pub fn can_breed(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "canBreed", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the entity is silent or not. - /// - /// When an entity is silent it will not produce any sound. - pub fn set_silent(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSilent", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Set breedability of the animal, if the animal is a baby and set to + /// breed it will instantly grow up. + pub fn set_breed(&self, breed: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(breed.into()); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setBreed", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether gravity applies to this entity. - pub fn has_gravity(&self) -> Result> { + /// Checks if this animal is sitting + pub fn is_sitting(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSitting", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether gravity applies to this entity. - pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { + /// Sets if this animal is sitting. Will remove any path that the animal + /// was following beforehand. + pub fn set_sitting(&self, sitting: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gravity.into()); + let val_1 = jni::objects::JValueGen::Bool(sitting.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setGravity", + "setSitting", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the period of time (in ticks) before this entity can use a portal. - pub fn portal_cooldown(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPortalCooldown", - sig.as_str(), - vec![], - ); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Wolf<'mc> { + fn into(self) -> crate::entity::Tameable<'mc> { + crate::entity::Tameable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Wolf into crate::entity::Tameable") + } +} +impl<'mc> Into> for Wolf<'mc> { + fn into(self) -> crate::entity::Sittable<'mc> { + crate::entity::Sittable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Wolf into crate::entity::Sittable") + } +} +#[repr(C)] +pub struct WolfVariant<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for WolfVariant<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for WolfVariant<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate WolfVariant from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Wolf/Variant")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a WolfVariant object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> WolfVariant<'mc> { + /// Return the namespaced identifier for this object. + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the period of time (in ticks) before this entity can use a portal. - pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(cooldown); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for WolfVariant<'mc> { + fn into(self) -> crate::Keyed<'mc> { + crate::Keyed::from_raw(&self.jni_ref(), self.1) + .expect("Error converting WolfVariant into crate::Keyed") + } +} +#[repr(C)] +pub struct Fireball<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Fireball<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Fireball<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Fireball from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Fireball")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Fireball object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Fireball<'mc> { + /// Sets the direction the fireball should be flying towards. + /// + /// This is a convenience method, it will change the velocity direction and + /// acceleration direction, while keeping the power the same. + /// + /// Note: This method only uses the direction of the vector and will + /// normalize (a copy of) it. + /// + /// Special Case: When the given direction is + /// {@link Vector#isZero() zero}, the velocity and acceleration will also be + /// set to zero without keeping the power. + pub fn set_direction( + &self, + direction: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(direction.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPortalCooldown", + "setDirection", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a set of tags for this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn scoreboard_tags( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getScoreboardTags", - sig.as_str(), - vec![], - ); + #[deprecated] + /// Retrieve the direction this fireball is heading toward. The returned vector is not normalized. + pub fn direction(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Add a tag to this entity. + /// Sets the acceleration of the fireball. + /// The acceleration gets applied to the velocity every tick, depending on + /// the specific type of the fireball a damping / drag factor is applied so + /// that the velocity does not grow into infinity. /// - /// Entities can have no more than 1024 tags. - pub fn add_scoreboard_tag( + /// Note: that the client may not respect non-default acceleration + /// power and will therefore mispredict the location of the fireball, causing + /// visual stutter. + pub fn set_acceleration( &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); + acceleration: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(acceleration.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "addScoreboardTag", + "setAcceleration", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Retrieve the acceleration of this fireball. + pub fn acceleration(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAcceleration", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Removes a given tag from this entity. - pub fn remove_scoreboard_tag( + /// Retrieve the shooter of this projectile. + pub fn shooter( &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/projectiles/ProjectileSource;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getShooter", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::projectiles::ProjectileSource::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Set the shooter of this projectile. + pub fn set_shooter( + &self, + source: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/projectiles/ProjectileSource;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(source.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeScoreboardTag", + "setShooter", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Determine if this projectile should bounce or not when it hits. + pub fn does_bounce(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "doesBounce", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns the reaction of the entity when moved by a piston. - pub fn piston_move_reaction( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + #[deprecated] + /// Set whether or not this projectile should bounce or not when it hits something. + pub fn set_bounce(&self, does_bounce: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(does_bounce.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getPistonMoveReaction", + "setBounce", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Stores the entity's current position in the provided Location object. + /// + /// If the provided Location is null this method does nothing and returns + /// null. + pub fn get_location( + &self, + loc: impl Into>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Lorg/bukkit/Location;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLocation", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) + })?)) } - /// Get the closest cardinal {@link BlockFace} direction an entity is - /// currently facing. - /// - /// This will not return any non-cardinal directions such as - /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. - /// - /// {@link Hanging} entities will override this call and thus their behavior - /// may be different. - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + /// Sets this entity's velocity in meters per tick + pub fn set_velocity( + &self, + velocity: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/util/Vector;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "setVelocity", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets this entity's current velocity + pub fn velocity(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/util/Vector;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the entity's current pose. - /// Note that the pose is only updated at the end of a tick, so may be - /// inconsistent with other methods. eg {@link Player#isSneaking()} being - /// true does not imply the current pose will be {@link Pose#SNEAKING} - pub fn pose(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Pose;"); + /// Gets the entity's height + pub fn height(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")D"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHeight", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the entity's width + pub fn width(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")D"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getWidth", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.d()?) } - /// Get the category of spawn to which this entity belongs. - pub fn spawn_category( + /// Gets the entity's current bounding box. + /// + /// The returned bounding box reflects the entity's current location and + /// size. + pub fn bounding_box( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSpawnCategory", - sig.as_str(), - vec![], - ); + ) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/util/BoundingBox;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Checks if this entity has been spawned in a world. - /// - /// Entities not spawned in a world will not tick, be sent to players, or be - /// saved to the server files. - pub fn is_in_world(&self) -> Result> { - let sig = String::from("()Z"); + /// Returns true if the entity is supported by a block. This value is a + /// state updated by the server and is not recalculated unless the entity + /// moves. + pub fn is_on_ground(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isOnGround", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get this entity as an NBT string. - /// - /// This string should not be relied upon as a serializable value. - pub fn as_string(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + /// Returns true if the entity is in water. + pub fn is_in_water(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWater", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(res.z()?) } - /// Crates an {@link EntitySnapshot} representing the current state of this entity. - pub fn create_snapshot( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + /// Gets the current world this entity resides in + pub fn world(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/World;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::EntitySnapshot::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// Sets the entity's rotation. /// - /// Note: Players cannot be copied. - pub fn copy( + /// Note that if the entity is affected by AI, it may override this rotation. + pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "F"; + let val_1 = jni::objects::JValueGen::Float(yaw); + args.push(val_1); + sig += "F"; + let val_2 = jni::objects::JValueGen::Float(pitch); + args.push(val_2); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setRotation", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Teleports this entity to the given location. If this entity is riding a + /// vehicle, it will be dismounted prior to teleportation. + pub fn teleport( &self, - to: std::option::Option>>, - ) -> Result, Box> { + location: impl Into>, + cause: std::option::Option< + impl Into>, + >, + ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = to { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = cause { + sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); - args.push(val_1); + args.push(val_2); } - sig += ")Lorg/bukkit/entity/Entity;"; + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); + .call_method(&self.jni_object(), "teleport", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets a metadata value in the implementing object's metadata store. - pub fn set_metadata( - &self, - metadata_key: impl Into, - new_metadata_value: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMetadata", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.z()?) } - /// Returns a list of previously set metadata values from the implementing - /// object's metadata store. - pub fn get_metadata( + /// Returns a list of entities within a bounding box centered around this + /// entity + pub fn get_nearby_entities( &self, - metadata_key: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMetadata", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + x: f64, + y: f64, + z: f64, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(x); + args.push(val_1); + sig += "D"; + let val_2 = jni::objects::JValueGen::Double(y); + args.push(val_2); + sig += "D"; + let val_3 = jni::objects::JValueGen::Double(z); + args.push(val_3); + sig += ")Ljava/util/List;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getNearbyEntities", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::metadata::MetadataValue::from_raw( - &self.jni_ref(), - obj, - )?); + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); } Ok(new_vec) } - /// Tests to see whether the implementing object contains the given - /// metadata value in its metadata store. - pub fn has_metadata( - &self, - metadata_key: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasMetadata", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Returns a unique id for this entity + pub fn entity_id(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getEntityId", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Removes the given metadata value from the implementing object's - /// metadata store. - pub fn remove_metadata( - &self, - metadata_key: impl Into, - owning_plugin: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removeMetadata", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + /// Returns the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn fire_ticks(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the entity's maximum fire ticks. + pub fn max_fire_ticks(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setFireTicks", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sends this sender multiple messages - pub fn send_message( - &self, - sender: impl Into>, - messages: std::option::Option>, - ) -> Result<(), Box> { + /// Sets if the entity has visual fire (it will always appear to be on fire). + pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) - }); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(fire.into()); args.push(val_1); - if let Some(a) = messages { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_2); - } sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setVisualFire", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the name of this command sender - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + /// Gets if the entity has visual fire (it will always appear to be on fire). + pub fn is_visual_fire(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - /// Gets the custom name on a mob or block. If there is no name this method - /// will return null. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn custom_name(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); + /// Returns the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn freeze_ticks(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getCustomName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( + Ok(res.i()?) + } + /// Returns the entity's maximum freeze ticks (amount of ticks before it will + /// be fully frozen) + pub fn max_freeze_ticks(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; + let res = self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + .call_method(&self.jni_object(), "getMaxFreezeTicks", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Sets a custom name on a mob or block. This name will be used in death - /// messages and can be sent to the client as a nameplate over the mob. - /// - /// Setting the name to null or an empty string will clear it. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn set_custom_name( - &self, - name: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCustomName", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Sets the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setFreezeTicks", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPersistentDataContainer", - sig.as_str(), - vec![], - ); + /// Gets if the entity is fully frozen (it has been in powdered snow for max + /// freeze ticks). + pub fn is_frozen(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFrozen", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for EnderCrystal<'mc> { - fn into(self) -> crate::entity::Entity<'mc> { - crate::entity::Entity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EnderCrystal into crate::entity::Entity") - } -} -#[repr(C)] -pub struct EnderDragon<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for EnderDragon<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for EnderDragon<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate EnderDragon from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EnderDragon")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EnderDragon object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + Ok(res.z()?) } -} - -impl<'mc> EnderDragon<'mc> { - /// Gets the current phase that the dragon is performing. - pub fn phase( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EnderDragon/Phase;"); + /// Mark the entity's removal. + pub fn remove(&self) -> Result<(), Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getPhase", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::EnderDragonPhase::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the next phase for the dragon to perform. - pub fn set_phase( - &self, - phase: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/EnderDragon/Phase;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(phase.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPhase", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "remove", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the {@link DragonBattle} associated with this EnderDragon. - /// - /// This will return null for the following reasons: - ///
    - ///
  • The EnderDragon is not in the End dimension
  • - ///
  • The EnderDragon was summoned by command/API
  • - ///
- pub fn dragon_battle( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/boss/DragonBattle;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDragonBattle", sig.as_str(), vec![]); + /// Returns true if this entity has been marked for removal. + pub fn is_dead(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isDead", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::boss::DragonBattle::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Get the current time in ticks relative to the start of this dragon's - /// death animation. - /// If this dragon is alive, 0 will be returned. This value will never exceed - /// 200 (the length of the animation). - pub fn death_animation_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getDeathAnimationTicks", - sig.as_str(), - vec![], - ); + /// Returns false if the entity has died, been despawned for some other + /// reason, or has not been added to the world. + pub fn is_valid(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isValid", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Gets a list of parts that belong to this complex entity - pub fn parts(&self) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Gets the {@link Server} that contains this Entity + pub fn server(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Server;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getParts", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getServer", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + crate::Server::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the height of the living entity's eyes above its Location. - pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { + /// Returns true if the entity gets persisted. + /// + /// By default all entities are persistent. An entity will also not get + /// persisted, if it is riding an entity that is not persistent. + /// + /// The persistent flag on players controls whether or not to save their + /// playerdata file when they quit. If a player is directly or indirectly + /// riding a non-persistent entity, the vehicle at the root and all its + /// passengers won't get persisted. + /// + /// This should not be confused with + /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls + /// despawning of living entities. + pub fn is_persistent(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isPersistent", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether or not the entity gets persisted. + pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); + let val_1 = jni::objects::JValueGen::Bool(persistent.into()); args.push(val_1); - sig += ")D"; + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getEyeHeight", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + .call_method(&self.jni_object(), "setPersistent", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get a Location detailing the current eye position of the living entity. - pub fn eye_location(&self) -> Result, Box> { + #[deprecated] + /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. + pub fn passenger( + &self, + ) -> Result>, Box> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")Lorg/bukkit/Location;"; + sig += ")Lorg/bukkit/entity/Entity;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), args); + .call_method(&self.jni_object(), "getPassenger", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets all blocks along the living entity's line of sight. - /// - /// This list contains all blocks from the living entity's eye position to - /// target inclusive. This method considers all blocks as 1x1x1 in size. - pub fn get_line_of_sight( + #[deprecated] + /// Set the passenger of a vehicle. + pub fn set_passenger( &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { + passenger: impl Into>, + ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/util/Set;"; + sig += "Lorg/bukkit/entity/Entity;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); args.push(val_1); - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(max_distance); - args.push(val_2); + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setPassenger", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets a list of passengers of this vehicle. + /// + /// The returned list will not be directly linked to the entity's current + /// passengers, and no guarantees are made as to its mutability. + pub fn passengers( + &self, + ) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); sig += ")Ljava/util/List;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getLineOfSight", sig.as_str(), args); + .call_method(&self.jni_object(), "getPassengers", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); } Ok(new_vec) } - /// Gets the block that the living entity has targeted. - /// - /// This method considers all blocks as 1x1x1 in size. To take exact block - /// collision shapes into account, see {@link #getTargetBlockExact(int, - /// FluidCollisionMode)}. - pub fn get_target_block( + /// Add a passenger to the vehicle. + pub fn add_passenger( &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result, Box> { + passenger: impl Into>, + ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/util/Set;"; + sig += "Lorg/bukkit/entity/Entity;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); args.push(val_1); - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(max_distance); - args.push(val_2); - sig += ")Lorg/bukkit/block/Block;"; + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getTargetBlock", sig.as_str(), args); + .call_method(&self.jni_object(), "addPassenger", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Gets the last two blocks along the living entity's line of sight. - /// - /// The target block will be the last block in the list. This method - /// considers all blocks as 1x1x1 in size. - pub fn get_last_two_target_blocks( + /// Remove a passenger from the vehicle. + pub fn remove_passenger( &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { + passenger: impl Into>, + ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/util/Set;"; + sig += "Lorg/bukkit/entity/Entity;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); args.push(val_1); - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(max_distance); - args.push(val_2); - sig += ")Ljava/util/List;"; + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "removePassenger", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Check if a vehicle has passengers. + pub fn is_empty(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Eject any passenger. + pub fn eject(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "eject", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the distance this entity has fallen + pub fn fall_distance(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")F"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the fall distance for this entity + pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "F"; + let val_1 = jni::objects::JValueGen::Float(distance); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setFallDistance", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Record the last {@link EntityDamageEvent} inflicted on this entity + pub fn set_last_damage_cause( + &self, + event: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/event/entity/EntityDamageEvent;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(event.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; let res = self.jni_ref().call_method( &self.jni_object(), - "getLastTwoTargetBlocks", + "setLastDamageCause", sig.as_str(), args, ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the block that the living entity has targeted. - /// - /// This takes the blocks' precise collision shapes into account. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn get_target_block_exact( + /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. + /// This event may have been cancelled. + pub fn last_damage_cause( &self, - max_distance: i32, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); + ) -> Result>, Box> + { + let args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(max_distance); - args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/block/Block;"; + sig += ")Lorg/bukkit/event/entity/EntityDamageEvent;"; let res = self.jni_ref().call_method( &self.jni_object(), - "getTargetBlockExact", + "getLastDamageCause", sig.as_str(), args, ); @@ -82521,1127 +92922,1248 @@ impl<'mc> EnderDragon<'mc> { if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::block::Block::from_raw( + Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Performs a ray trace that provides information on the targeted block. - /// - /// This takes the blocks' precise collision shapes into account. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn ray_trace_blocks( + /// Returns a unique and persistent id for this entity + pub fn unique_id( &self, - max_distance: f64, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); + ) -> Result, Box> { + let args = Vec::new(); let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(max_distance); - args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/util/RayTraceResult;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); + sig += ")Ljava/util/UUID;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::util::RayTraceResult::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the amount of air that the living entity has remaining, in - /// ticks. - pub fn remaining_air(&self) -> Result> { + /// Gets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. + pub fn ticks_lived(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); sig += ")I"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), args); + .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the amount of air that the living entity has remaining, in ticks. - pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { + /// Sets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. May not be less than one + /// tick. + pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "I"; - let val_1 = jni::objects::JValueGen::Int(ticks); + let val_1 = jni::objects::JValueGen::Int(value); args.push(val_1); sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "setRemainingAir", sig.as_str(), args); + .call_method(&self.jni_object(), "setTicksLived", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the maximum amount of air the living entity can have, in ticks. - pub fn maximum_air(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")I"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the maximum amount of air the living entity can have, in ticks. - pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { + /// Performs the specified {@link EntityEffect} for this entity. + /// + /// This will be viewable to all players near the entity. + /// + /// If the effect is not applicable to this class of entity, it will not play. + pub fn play_effect( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(ticks); + sig += "Lorg/bukkit/EntityEffect;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); args.push(val_1); sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setMaximumAir", sig.as_str(), args); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "playEffect", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the item that the player is using (eating food, drawing back a bow, - /// blocking, etc.) - pub fn item_in_use( - &self, - ) -> Result>, Box> { + /// Get the type of the entity. + pub fn get_type(&self) -> Result, Box> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")Lorg/bukkit/inventory/ItemStack;"; + sig += ")Lorg/bukkit/entity/EntityType;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes while swimming. + pub fn swim_sound(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), args); + .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes when splashing in water. For most + /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_splash_sound(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Sound;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSwimSplashSound", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes when splashing in water at high + /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_high_speed_splash_sound( + &self, + ) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Sound;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSwimHighSpeedSplashSound", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the number of ticks remaining for the current item's usage. - pub fn item_in_use_ticks(&self) -> Result> { + /// Returns whether this entity is inside a vehicle. + pub fn is_inside_vehicle(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")I"; + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemInUseTicks", sig.as_str(), args); + .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the number of ticks that remain for the current item's usage. - /// Applies to items that take time to use, like eating food, drawing a bow, - /// or throwing a trident. - pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(ticks); - args.push(val_1); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setItemInUseTicks", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.z()?) } - /// Gets the time in ticks until the next arrow leaves the entity's body. - pub fn arrow_cooldown(&self) -> Result> { + /// Leave the current vehicle. If the entity is currently in a vehicle (and + /// is removed from it), true will be returned, otherwise false will be + /// returned. + pub fn leave_vehicle(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")I"; + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getArrowCooldown", sig.as_str(), args); + .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the time in ticks until the next arrow leaves the entity's body. - pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(ticks); - args.push(val_1); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setArrowCooldown", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.z()?) } - /// Gets the amount of arrows in an entity's body. - pub fn arrows_in_body(&self) -> Result> { + /// Get the vehicle that this entity is inside. If there is no vehicle, + /// null will be returned. + pub fn vehicle( + &self, + ) -> Result>, Box> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")I"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), args); + sig += ")Lorg/bukkit/entity/Entity;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getVehicle", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Set the amount of arrows in the entity's body. - pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { + /// Sets whether or not to display the mob's custom name client side. The + /// name will be displayed above the mob similarly to a player. + /// + /// This value has no effect on players, they will always display their + /// name. + pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(count); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(flag.into()); args.push(val_1); sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setArrowsInBody", sig.as_str(), args); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCustomNameVisible", + sig.as_str(), + args, + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's current maximum no damage ticks. + /// Gets whether or not the mob's custom name is displayed client side. /// - /// This is the maximum duration in which the living entity will not take - /// damage. - pub fn maximum_no_damage_ticks(&self) -> Result> { + /// This value has no effect on players, they will always display their + /// name. + pub fn is_custom_name_visible(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")I"; + sig += ")Z"; let res = self.jni_ref().call_method( &self.jni_object(), - "getMaximumNoDamageTicks", + "isCustomNameVisible", sig.as_str(), args, ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the living entity's current maximum no damage ticks. - pub fn set_maximum_no_damage_ticks( - &self, - ticks: i32, - ) -> Result<(), Box> { + /// Sets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(ticks); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(visible.into()); args.push(val_1); sig += ")V"; let res = self.jni_ref().call_method( &self.jni_object(), - "setMaximumNoDamageTicks", + "setVisibleByDefault", sig.as_str(), args, ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's last damage taken in the current no damage - /// ticks time. + /// Gets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn is_visible_by_default(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "isVisibleByDefault", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get all players that are currently tracking this entity. /// - /// Only damage higher than this amount will further damage the living - /// entity. - pub fn last_damage(&self) -> Result> { + /// 'Tracking' means that this entity has been sent to the player and that + /// they are receiving updates on its state. Note that the client's {@code + /// 'Entity Distance'} setting does not affect the range at which entities + /// are tracked. + pub fn tracked_by( + &self, + ) -> Result, Box> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")D"; + sig += ")Ljava/util/Set;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), args); + .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the damage dealt within the current no damage ticks time period. - pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { + /// Sets whether the entity has a team colored (default: white) glow. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(damage); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(flag.into()); args.push(val_1); sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setLastDamage", sig.as_str(), args); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setGlowing", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the living entity's current no damage ticks. - pub fn no_damage_ticks(&self) -> Result> { + /// Gets whether the entity is glowing or not. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn is_glowing(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")I"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getNoDamageTicks", sig.as_str(), args); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGlowing", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the living entity's current no damage ticks. - pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Sets whether the entity is invulnerable or not. + /// + /// When an entity is invulnerable it can only be damaged by players in + /// creative mode. + pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(ticks); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(flag.into()); args.push(val_1); sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "setNoDamageTicks", sig.as_str(), args); + .call_method(&self.jni_object(), "setInvulnerable", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the ticks that this entity has performed no action. - /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn no_action_ticks(&self) -> Result> { + /// Gets whether the entity is invulnerable or not. + pub fn is_invulnerable(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")I"; + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getNoActionTicks", sig.as_str(), args); + .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the ticks that this entity has performed no action. + /// Gets whether the entity is silent or not. + pub fn is_silent(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSilent", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the entity is silent or not. /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { + /// When an entity is silent it will not produce any sound. + pub fn set_silent(&self, flag: bool) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(ticks); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(flag.into()); args.push(val_1); sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setNoActionTicks", sig.as_str(), args); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setSilent", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the player identified as the killer of the living entity. - /// - /// May be null. - pub fn killer(&self) -> Result>, Box> { + /// Returns whether gravity applies to this entity. + pub fn has_gravity(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")Lorg/bukkit/entity/Player;"; + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getKiller", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Player::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - #[deprecated] - /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. - pub fn add_potion_effect( - &self, - effect: impl Into>, - force: std::option::Option, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/potion/PotionEffect;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(effect.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = force { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns whether the living entity already has an existing effect of - /// the given {@link PotionEffectType} applied to it. - pub fn has_potion_effect( - &self, - val_type: impl Into>, - ) -> Result> { + /// Sets whether gravity applies to this entity. + pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/potion/PotionEffectType;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(gravity.into()); args.push(val_1); - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasPotionEffect", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setGravity", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns the active {@link PotionEffect} of the specified type. - /// - /// If the effect is not present on the entity then null will be returned. - pub fn get_potion_effect( - &self, - val_type: impl Into>, - ) -> Result>, Box> { - let mut args = Vec::new(); + /// Gets the period of time (in ticks) before this entity can use a portal. + pub fn portal_cooldown(&self) -> Result> { + let args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/potion/PotionEffectType;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Lorg/bukkit/potion/PotionEffect;"; + sig += ")I"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getPotionEffect", sig.as_str(), args); + .call_method(&self.jni_object(), "getPortalCooldown", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::potion::PotionEffect::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - /// Removes any effects present of the given {@link PotionEffectType}. - pub fn remove_potion_effect( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { + /// Sets the period of time (in ticks) before this entity can use a portal. + pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/potion/PotionEffectType;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(cooldown); args.push(val_1); sig += ")V"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "removePotionEffect", - sig.as_str(), - args, - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setPortalCooldown", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns all currently active {@link PotionEffect}s on the living - /// entity. - pub fn active_potion_effects( + /// Returns a set of tags for this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn scoreboard_tags( &self, - ) -> Result>, Box> { + ) -> Result, Box> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")Ljava/util/Collection;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getActivePotionEffects", - sig.as_str(), - args, - ); + sig += ")Ljava/util/Set;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getScoreboardTags", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Checks whether the living entity has block line of sight to another. + /// Add a tag to this entity. /// - /// This uses the same algorithm that hostile mobs use to find the closest - /// player. - pub fn has_line_of_sight( + /// Entities can have no more than 1024 tags. + pub fn add_scoreboard_tag( &self, - other: impl Into>, + tag: impl Into, ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Entity;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) - }); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); args.push(val_1); sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "hasLineOfSight", sig.as_str(), args); + .call_method(&self.jni_object(), "addScoreboardTag", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns if the living entity despawns when away from players or not. - /// - /// By default, animals are not removed while other mobs are. - pub fn remove_when_far_away(&self) -> Result> { - let args = Vec::new(); + /// Removes a given tag from this entity. + pub fn remove_scoreboard_tag( + &self, + tag: impl Into, + ) -> Result> { + let mut args = Vec::new(); let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); + args.push(val_1); sig += ")Z"; let res = self.jni_ref().call_method( &self.jni_object(), - "getRemoveWhenFarAway", + "removeScoreboardTag", sig.as_str(), args, ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not the living entity despawns when away from players - /// or not. - pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { - let mut args = Vec::new(); + /// Returns the reaction of the entity when moved by a piston. + pub fn piston_move_reaction( + &self, + ) -> Result, Box> { + let args = Vec::new(); let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(remove.into()); - args.push(val_1); - sig += ")V"; + sig += ")Lorg/bukkit/block/PistonMoveReaction;"; let res = self.jni_ref().call_method( &self.jni_object(), - "setRemoveWhenFarAway", + "getPistonMoveReaction", sig.as_str(), args, ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the inventory with the equipment worn by the living entity. - pub fn equipment( - &self, - ) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/inventory/EntityEquipment;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEquipment", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::EntityEquipment::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Sets whether or not the living entity can pick up items. - pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(pickup.into()); - args.push(val_1); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setCanPickupItems", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets if the living entity can pick up items. - pub fn can_pickup_items(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCanPickupItems", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns whether the entity is currently leashed. - pub fn is_leashed(&self) -> Result> { + /// Get the closest cardinal {@link BlockFace} direction an entity is + /// currently facing. + /// + /// This will not return any non-cardinal directions such as + /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// + /// {@link Hanging} entities will override this call and thus their behavior + /// may be different. + pub fn facing(&self) -> Result, Box> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")Z"; + sig += ")Lorg/bukkit/block/BlockFace;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isLeashed", sig.as_str(), args); + .call_method(&self.jni_object(), "getFacing", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the entity that is currently leading this entity. - pub fn leash_holder(&self) -> Result, Box> { + /// Gets the entity's current pose. + /// Note that the pose is only updated at the end of a tick, so may be + /// inconsistent with other methods. eg {@link Player#isSneaking()} being + /// true does not imply the current pose will be {@link Pose#SNEAKING} + pub fn pose(&self) -> Result, Box> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")Lorg/bukkit/entity/Entity;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), args); + sig += ")Lorg/bukkit/entity/Pose;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPose", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the leash on this entity to be held by the supplied entity. - /// - /// This method has no effect on EnderDragons, Withers, Players, or Bats. - /// Non-living entities excluding leashes will not persist as leash - /// holders. - pub fn set_leash_holder( + /// Get the category of spawn to which this entity belongs. + pub fn spawn_category( &self, - holder: impl Into>, - ) -> Result> { - let mut args = Vec::new(); + ) -> Result, Box> { + let args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Entity;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(holder.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Z"; + sig += ")Lorg/bukkit/entity/SpawnCategory;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "setLeashHolder", sig.as_str(), args); + .call_method(&self.jni_object(), "getSpawnCategory", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Checks to see if an entity is gliding, such as using an Elytra. - pub fn is_gliding(&self) -> Result> { + /// Checks if this entity has been spawned in a world. + /// + /// Entities not spawned in a world will not tick, be sent to players, or be + /// saved to the server files. + pub fn is_in_world(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isGliding", sig.as_str(), args); + .call_method(&self.jni_object(), "isInWorld", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Makes entity start or stop gliding. This will work even if an Elytra - /// is not equipped, but will be reverted by the server immediately after - /// unless an event-cancelling mechanism is put in place. - pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { - let mut args = Vec::new(); + /// Get this entity as an NBT string. + /// + /// This string should not be relied upon as a serializable value. + pub fn as_string(&self) -> Result, Box> { + let args = Vec::new(); let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(gliding.into()); - args.push(val_1); - sig += ")V"; + sig += ")Ljava/lang/String;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "setGliding", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getAsString", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Checks to see if an entity is swimming. - pub fn is_swimming(&self) -> Result> { + /// Crates an {@link EntitySnapshot} representing the current state of this entity. + pub fn create_snapshot( + &self, + ) -> Result>, Box> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")Z"; + sig += ")Lorg/bukkit/entity/EntitySnapshot;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntitySnapshot::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// + /// Note: Players cannot be copied. + pub fn copy( + &self, + to: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = to { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Lorg/bukkit/entity/Entity;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isSwimming", sig.as_str(), args); + .call_method(&self.jni_object(), "copy", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Makes entity start or stop swimming. - /// This may have unexpected results if the entity is not in water. - pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { + /// Sets a metadata value in the implementing object's metadata store. + pub fn set_metadata( + &self, + metadata_key: impl Into, + new_metadata_value: impl Into>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(swimming.into()); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); args.push(val_1); + sig += "Lorg/bukkit/metadata/MetadataValue;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) + }); + args.push(val_2); sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "setSwimming", sig.as_str(), args); + .call_method(&self.jni_object(), "setMetadata", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks to see if an entity is currently using the Riptide enchantment. - pub fn is_riptiding(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns whether this entity is slumbering. - pub fn is_sleeping(&self) -> Result> { - let args = Vec::new(); + /// Returns a list of previously set metadata values from the implementing + /// object's metadata store. + pub fn get_metadata( + &self, + metadata_key: impl Into, + ) -> Result>, Box> { + let mut args = Vec::new(); let mut sig = String::from("("); - sig += ")Z"; + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += ")Ljava/util/List;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isSleeping", sig.as_str(), args); + .call_method(&self.jni_object(), "getMetadata", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::metadata::MetadataValue::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(new_vec) } - /// Gets if the entity is climbing. - pub fn is_climbing(&self) -> Result> { - let args = Vec::new(); + /// Tests to see whether the implementing object contains the given + /// metadata value in its metadata store. + pub fn has_metadata( + &self, + metadata_key: impl Into, + ) -> Result> { + let mut args = Vec::new(); let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isClimbing", sig.as_str(), args); + .call_method(&self.jni_object(), "hasMetadata", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether an entity will have AI. - /// The entity will be completely unable to move if it has no AI. - pub fn set_ai(&self, ai: bool) -> Result<(), Box> { + /// Removes the given metadata value from the implementing object's + /// metadata store. + pub fn remove_metadata( + &self, + metadata_key: impl Into, + owning_plugin: impl Into>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(ai.into()); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); args.push(val_1); + sig += "Lorg/bukkit/plugin/Plugin;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + }); + args.push(val_2); sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setAI", sig.as_str(), args); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "removeMetadata", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks whether an entity has AI. - /// The entity will be completely unable to move if it has no AI. - pub fn has_ai(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasAI", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Makes this entity attack the given entity with a melee attack. - /// Attack damage is calculated by the server from the attributes and - /// equipment of this mob, and knockback is applied to {@code target} as - /// appropriate. - pub fn attack( + /// Sends this sender multiple messages + pub fn send_message( &self, - target: impl Into>, + sender: impl Into>, + messages: std::option::Option>, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Entity;"; + sig += "Ljava/util/UUID;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) }); args.push(val_1); + if let Some(a) = messages { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_2); + } sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "attack", sig.as_str(), args); + .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Makes this entity swing their main hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their main hand. - pub fn swing_main_hand(&self) -> Result<(), Box> { + /// Gets the name of this command sender + pub fn name(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + sig += ")Ljava/lang/String;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Makes this entity swing their off hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their off hand. - pub fn swing_off_hand(&self) -> Result<(), Box> { + /// Gets the custom name on a mob or block. If there is no name this method + /// will return null. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn custom_name(&self) -> Result, Box> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")V"; + sig += ")Ljava/lang/String;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Makes this entity flash red as if they were damaged. - pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "F"; - let val_1 = jni::objects::JValueGen::Float(yaw); - args.push(val_1); - sig += ")V"; - let res = + .call_method(&self.jni_object(), "getCustomName", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( self.jni_ref() - .call_method(&self.jni_object(), "playHurtAnimation", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Set if this entity will be subject to collisions with other entities. - /// - /// Exemptions to this rule can be managed with - /// {@link #getCollidableExemptions()} + /// Sets a custom name on a mob or block. This name will be used in death + /// messages and can be sent to the client as a nameplate over the mob. /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not working for player collisions. This - /// method should therefore only be used to set the collision status of - /// non-player entities. + /// Setting the name to null or an empty string will clear it. /// - /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in - /// combination with a {@link Scoreboard} and a {@link Team}. - pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { + /// This value has no effect on players, they will always use their real + /// name. + pub fn set_custom_name( + &self, + name: impl Into, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(collidable.into()); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); args.push(val_1); sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "setCollidable", sig.as_str(), args); + .call_method(&self.jni_object(), "setCustomName", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if this entity is subject to collisions with other entities. - /// - /// Some entities might be exempted from the collidable rule of this entity. - /// Use {@link #getCollidableExemptions()} to get these. - /// - /// Please note that this method returns only the custom collidable state, - /// not whether the entity is non-collidable for other reasons such as being - /// dead. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not being accurate for player collisions. - /// This method should therefore only be used to check the collision status - /// of non-player entities. - /// - /// To check the collision behavior for a player, use - /// {@link Team.Option#COLLISION_RULE} in combination with a - /// {@link Scoreboard} and a {@link Team}. - pub fn is_collidable(&self) -> Result> { + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + pub fn persistent_data_container( + &self, + ) -> Result, Box> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")Z"; + sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPersistentDataContainer", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Set the radius affected by this explosive's explosion + pub fn set_yield(&self, val_yield: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(val_yield); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setYield", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Return the radius or yield of this explosive's explosion + pub fn get_yield(&self) -> Result> { + let sig = String::from("()F"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getYield", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Set whether or not this explosive's explosion causes fire + pub fn set_is_incendiary(&self, is_incendiary: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(is_incendiary.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setIsIncendiary", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Return whether or not this explosive creates a fire when exploding + pub fn is_incendiary(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCollidable", sig.as_str(), args); + .call_method(&self.jni_object(), "isIncendiary", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets a mutable set of UUIDs of the entities which are exempt from the - /// entity's collidable rule and which's collision with this entity will - /// behave the opposite of it. - /// - /// This set can be modified to add or remove exemptions. - /// - /// For example if collidable is true and an entity is in the exemptions set - /// then it will not collide with it. Similarly if collidable is false and an - /// entity is in this set then it will still collide with it. - /// - /// Note these exemptions are not (currently) persistent. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in those exemptions not being accurate for player - /// collisions. This method should therefore only be used to exempt - /// non-player entities. - /// - /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} - /// in combination with a {@link Scoreboard} and a {@link Team}. - pub fn collidable_exemptions( - &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/Set;"; + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Fireball<'mc> { + fn into(self) -> crate::entity::Projectile<'mc> { + crate::entity::Projectile::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Fireball into crate::entity::Projectile") + } +} +impl<'mc> Into> for Fireball<'mc> { + fn into(self) -> crate::entity::Explosive<'mc> { + crate::entity::Explosive::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Fireball into crate::entity::Explosive") + } +} +#[repr(C)] +pub struct AbstractArrow<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for AbstractArrow<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for AbstractArrow<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate AbstractArrow from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/AbstractArrow")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a AbstractArrow object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> AbstractArrow<'mc> { + #[deprecated] + /// Gets the knockback strength for an arrow, which is the {@link org.bukkit.enchantments.Enchantment#KNOCKBACK KnockBack} level of the bow that shot it. + pub fn knockback_strength(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCollidableExemptions", + "getKnockbackStrength", sig.as_str(), - args, + vec![], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Returns the value of the memory specified. - /// - /// Note that the value is null when the specific entity does not have that - /// value by default. - pub fn get_memory( + #[deprecated] + /// Sets the knockback strength for an arrow. + pub fn set_knockback_strength( &self, - memory_key: impl Into>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/memory/MemoryKey;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")LT;"; + knockback_strength: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(knockback_strength); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setKnockbackStrength", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the base amount of damage this arrow will do. + /// Defaults to 2.0 for a normal arrow with + /// 0.5 * (1 + power level) added for arrows fired from + /// enchanted bows. + pub fn damage(&self) -> Result> { + let sig = String::from("()D"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getMemory", sig.as_str(), args); + .call_method(&self.jni_object(), "getDamage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(res.l()?)) + Ok(res.d()?) } - /// Sets the value of the memory specified. - /// - /// Note that the value will not be persisted when the specific entity does - /// not have that value by default. - pub fn set_memory( - &self, - memory_key: impl Into>, - memory_value: jni::objects::JObject<'mc>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/memory/MemoryKey;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) - }); - args.push(val_1); - sig += "LT;"; - let val_2 = jni::objects::JValueGen::Object(memory_value); - args.push(val_2); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setMemory", sig.as_str(), args); + /// Sets the base amount of damage this arrow will do. + pub fn set_damage(&self, damage: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(damage); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDamage", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the {@link Sound} this entity will make when damaged. - pub fn hurt_sound(&self) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/Sound;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Get the {@link Sound} this entity will make on death. - pub fn death_sound(&self) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/Sound;"; + /// Gets the number of times this arrow can pierce through an entity. + pub fn pierce_level(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), args); + .call_method(&self.jni_object(), "getPierceLevel", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.i()?) } - /// Get the {@link Sound} this entity will make when falling from the given - /// height (in blocks). The sound will often differ between either a small - /// or a big fall damage sound if the height exceeds 4 blocks. - pub fn get_fall_damage_sound( - &self, - fall_height: i32, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(fall_height); - args.push(val_1); - sig += ")Lorg/bukkit/Sound;"; + /// Sets the number of times this arrow can pierce through an entity. + /// Must be between 0 and 127 times. + pub fn set_pierce_level(&self, pierce_level: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(pierce_level); let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSound", + "setPierceLevel", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether this arrow is critical. + /// + /// Critical arrows have increased damage and cause particle effects. + /// + /// Critical arrows generally occur when a player fully draws a bow before + /// firing. + pub fn is_critical(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCritical", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Get the {@link Sound} this entity will make when falling from a small - /// height. - pub fn fall_damage_sound_small(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/Sound;"; + /// Sets whether or not this arrow should be critical. + pub fn set_critical(&self, critical: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(critical.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSoundSmall", + "setCritical", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether this arrow is in a block or not. + /// + /// Arrows in a block are motionless and may be picked up by players. + pub fn is_in_block(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInBlock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Get the {@link Sound} this entity will make when falling from a large - /// height. - pub fn fall_damage_sound_big(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/Sound;"; + /// Gets the block to which this arrow is attached. + pub fn attached_block( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSoundBig", + "getAttachedBlock", sig.as_str(), - args, + vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::block::Block::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Get the {@link Sound} this entity will make when drinking the given - /// {@link ItemStack}. - pub fn get_drinking_sound( + /// Gets the current pickup status of this arrow. + pub fn pickup_status( &self, - item_stack: impl Into>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Lorg/bukkit/Sound;"; + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/AbstractArrow/PickupStatus;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDrinkingSound", sig.as_str(), args); + .call_method(&self.jni_object(), "getPickupStatus", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { + crate::entity::AbstractArrowPickupStatus::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the {@link Sound} this entity will make when eating the given - /// {@link ItemStack}. - pub fn get_eating_sound( + /// Sets the current pickup status of this arrow. + pub fn set_pickup_status( &self, - item_stack: impl Into>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; + status: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/AbstractArrow/PickupStatus;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + jni::objects::JObject::from_raw(status.into().jni_object().clone()) }); - args.push(val_1); - sig += ")Lorg/bukkit/Sound;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEatingSound", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPickupStatus", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns true if this entity can breathe underwater and will not take - /// suffocation damage when its air supply reaches zero. - pub fn can_breathe_underwater(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; + /// Gets if this arrow was shot from a crossbow. + pub fn is_shot_from_crossbow(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "canBreatheUnderwater", + "isShotFromCrossbow", sig.as_str(), - args, + vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } #[deprecated] - /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. - pub fn category( + /// Sets if this arrow was shot from a crossbow. + pub fn set_shot_from_crossbow( &self, - ) -> Result, Box> { + shot_from_crossbow: bool, + ) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(shot_from_crossbow.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setShotFromCrossbow", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the ItemStack which will be picked up from this arrow. + pub fn item(&self) -> Result, Box> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")Lorg/bukkit/entity/EntityCategory;"; + sig += ")Lorg/bukkit/inventory/ItemStack;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getCategory", sig.as_str(), args); + .call_method(&self.jni_object(), "getItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets whether the entity is invisible or not. - pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { + /// Sets the ItemStack which will be picked up from this arrow. + pub fn set_item( + &self, + item: impl Into>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(invisible.into()); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); args.push(val_1); sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setInvisible", sig.as_str(), args); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setItem", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invisible or not. - pub fn is_invisible(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; + /// Gets the ItemStack which fired this arrow. + pub fn weapon(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isInvisible", sig.as_str(), args); + .call_method(&self.jni_object(), "getWeapon", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the {@link BossBar} of the {@link Boss} - pub fn boss_bar( + /// Sets the ItemStack which fired this arrow. + pub fn set_weapon( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/boss/BossBar;"); + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setWeapon", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Retrieve the shooter of this projectile. + pub fn shooter( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/projectiles/ProjectileSource;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBossBar", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getShooter", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::boss::BossBar::from_raw( + Ok(Some(crate::projectiles::ProjectileSource::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } + /// Set the shooter of this projectile. + pub fn set_shooter( + &self, + source: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/projectiles/ProjectileSource;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(source.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setShooter", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Determine if this projectile should bounce or not when it hits. + pub fn does_bounce(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "doesBounce", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Set whether or not this projectile should bounce or not when it hits something. + pub fn set_bounce(&self, does_bounce: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(does_bounce.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBounce", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } /// Stores the entity's current position in the provided Location object. /// /// If the provided Location is null this method does nothing and returns @@ -83650,16 +94172,17 @@ impl<'mc> EnderDragon<'mc> { &self, loc: impl Into>, ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(loc.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLocation", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + sig += ")Lorg/bukkit/Location;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLocation", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); @@ -83673,25 +94196,28 @@ impl<'mc> EnderDragon<'mc> { &self, velocity: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/util/Vector;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setVelocity", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setVelocity", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } /// Gets this entity's current velocity pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/util/Vector;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) @@ -83699,19 +94225,23 @@ impl<'mc> EnderDragon<'mc> { } /// Gets the entity's height pub fn height(&self) -> Result> { - let sig = String::from("()D"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")D"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getHeight", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.d()?) } /// Gets the entity's width pub fn width(&self) -> Result> { - let sig = String::from("()D"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")D"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getWidth", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.d()?) } @@ -83722,10 +94252,12 @@ impl<'mc> EnderDragon<'mc> { pub fn bounding_box( &self, ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/util/BoundingBox;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) @@ -83735,28 +94267,34 @@ impl<'mc> EnderDragon<'mc> { /// state updated by the server and is not recalculated unless the entity /// moves. pub fn is_on_ground(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isOnGround", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } /// Returns true if the entity is in water. pub fn is_in_water(&self) -> Result> { - let sig = String::from("()Z"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInWater", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } /// Gets the current world this entity resides in pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/World;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getWorld", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; crate::World::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) @@ -83766,18 +94304,18 @@ impl<'mc> EnderDragon<'mc> { /// /// Note that if the entity is affected by AI, it may override this rotation. pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { - let sig = String::from("(FF)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); - let val_2 = jni::objects::JValueGen::Float(pitch); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRotation", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "F"; + let val_1 = jni::objects::JValueGen::Float(yaw); + args.push(val_1); + sig += "F"; + let val_2 = jni::objects::JValueGen::Float(pitch); + args.push(val_2); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setRotation", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } @@ -83819,20 +94357,21 @@ impl<'mc> EnderDragon<'mc> { y: f64, z: f64, ) -> Result>, Box> { - let sig = String::from("(DDD)Ljava/util/List;"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; let val_1 = jni::objects::JValueGen::Double(x); + args.push(val_1); + sig += "D"; let val_2 = jni::objects::JValueGen::Double(y); + args.push(val_2); + sig += "D"; let val_3 = jni::objects::JValueGen::Double(z); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getNearbyEntities", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); + args.push(val_3); + sig += ")Ljava/util/List;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getNearbyEntities", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; @@ -83845,149 +94384,171 @@ impl<'mc> EnderDragon<'mc> { } /// Returns a unique id for this entity pub fn entity_id(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getEntityId", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } /// Returns the entity's current fire ticks (ticks before the entity stops /// being on fire). pub fn fire_ticks(&self) -> Result> { - let sig = String::from("()I"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } /// Returns the entity's maximum fire ticks. pub fn max_fire_ticks(&self) -> Result> { - let sig = String::from("()I"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } /// Sets the entity's current fire ticks (ticks before the entity stops /// being on fire). pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFireTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setFireTicks", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } /// Sets if the entity has visual fire (it will always appear to be on fire). pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; let val_1 = jni::objects::JValueGen::Bool(fire.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setVisualFire", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setVisualFire", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } /// Gets if the entity has visual fire (it will always appear to be on fire). pub fn is_visual_fire(&self) -> Result> { - let sig = String::from("()Z"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } /// Returns the entity's current freeze ticks (amount of ticks the entity has /// been in powdered snow). pub fn freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } /// Returns the entity's maximum freeze ticks (amount of ticks before it will /// be fully frozen) pub fn max_freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMaxFreezeTicks", - sig.as_str(), - vec![], - ); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxFreezeTicks", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } /// Sets the entity's current freeze ticks (amount of ticks the entity has /// been in powdered snow). pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFreezeTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setFreezeTicks", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } /// Gets if the entity is fully frozen (it has been in powdered snow for max /// freeze ticks). pub fn is_frozen(&self) -> Result> { - let sig = String::from("()Z"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isFrozen", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } /// Mark the entity's removal. pub fn remove(&self) -> Result<(), Box> { - let sig = String::from("()V"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "remove", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } /// Returns true if this entity has been marked for removal. pub fn is_dead(&self) -> Result> { - let sig = String::from("()Z"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isDead", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } /// Returns false if the entity has died, been despawned for some other /// reason, or has not been added to the world. pub fn is_valid(&self) -> Result> { - let sig = String::from("()Z"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isValid", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } /// Gets the {@link Server} that contains this Entity pub fn server(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Server;"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Server;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getServer", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; crate::Server::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) @@ -84007,23 +94568,26 @@ impl<'mc> EnderDragon<'mc> { /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls /// despawning of living entities. pub fn is_persistent(&self) -> Result> { - let sig = String::from("()Z"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isPersistent", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } /// Sets whether or not the entity gets persisted. pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; let val_1 = jni::objects::JValueGen::Bool(persistent.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPersistent", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setPersistent", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } @@ -84032,10 +94596,12 @@ impl<'mc> EnderDragon<'mc> { pub fn passenger( &self, ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/entity/Entity;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPassenger", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); @@ -84051,16 +94617,17 @@ impl<'mc> EnderDragon<'mc> { &self, passenger: impl Into>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Entity;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPassenger", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setPassenger", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } @@ -84071,10 +94638,12 @@ impl<'mc> EnderDragon<'mc> { pub fn passengers( &self, ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/util/List;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPassengers", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; @@ -84090,16 +94659,17 @@ impl<'mc> EnderDragon<'mc> { &self, passenger: impl Into>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Entity;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addPassenger", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "addPassenger", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } @@ -84108,56 +94678,64 @@ impl<'mc> EnderDragon<'mc> { &self, passenger: impl Into>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Entity;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removePassenger", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "removePassenger", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } /// Check if a vehicle has passengers. pub fn is_empty(&self) -> Result> { - let sig = String::from("()Z"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } /// Eject any passenger. pub fn eject(&self) -> Result> { - let sig = String::from("()Z"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "eject", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } /// Returns the distance this entity has fallen pub fn fall_distance(&self) -> Result> { - let sig = String::from("()F"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")F"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.f()?) } /// Sets the fall distance for this entity pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "F"; let val_1 = jni::objects::JValueGen::Float(distance); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFallDistance", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setFallDistance", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } @@ -84167,15 +94745,19 @@ impl<'mc> EnderDragon<'mc> { &self, event: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/event/entity/EntityDamageEvent;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(event.into().jni_object().clone()) }); + args.push(val_1); + sig += ")V"; let res = self.jni_ref().call_method( &self.jni_object(), "setLastDamageCause", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); self.jni_ref().translate_error(res)?; Ok(()) @@ -84186,12 +94768,14 @@ impl<'mc> EnderDragon<'mc> { &self, ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/event/entity/EntityDamageEvent;"; let res = self.jni_ref().call_method( &self.jni_object(), "getLastDamageCause", sig.as_str(), - vec![], + args, ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { @@ -84206,10 +94790,12 @@ impl<'mc> EnderDragon<'mc> { pub fn unique_id( &self, ) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/util/UUID;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) @@ -84219,10 +94805,12 @@ impl<'mc> EnderDragon<'mc> { /// /// This is the equivalent to "age" in entities. pub fn ticks_lived(&self) -> Result> { - let sig = String::from("()I"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } @@ -84231,14 +94819,15 @@ impl<'mc> EnderDragon<'mc> { /// This is the equivalent to "age" in entities. May not be less than one /// tick. pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; let val_1 = jni::objects::JValueGen::Int(value); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTicksLived", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setTicksLived", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } @@ -84251,25 +94840,28 @@ impl<'mc> EnderDragon<'mc> { &self, val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/EntityEffect;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "playEffect", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "playEffect", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } /// Get the type of the entity. pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/entity/EntityType;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getType", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) @@ -84277,10 +94869,12 @@ impl<'mc> EnderDragon<'mc> { } /// Get the {@link Sound} this entity makes while swimming. pub fn swim_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) @@ -84289,12 +94883,14 @@ impl<'mc> EnderDragon<'mc> { /// Get the {@link Sound} this entity makes when splashing in water. For most /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. pub fn swim_splash_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref().call_method( &self.jni_object(), "getSwimSplashSound", sig.as_str(), - vec![], + args, ); let res = self.jni_ref().translate_error(res)?; crate::Sound::from_raw(&self.jni_ref(), unsafe { @@ -84306,12 +94902,14 @@ impl<'mc> EnderDragon<'mc> { pub fn swim_high_speed_splash_sound( &self, ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref().call_method( &self.jni_object(), "getSwimHighSpeedSplashSound", sig.as_str(), - vec![], + args, ); let res = self.jni_ref().translate_error(res)?; crate::Sound::from_raw(&self.jni_ref(), unsafe { @@ -84320,10 +94918,12 @@ impl<'mc> EnderDragon<'mc> { } /// Returns whether this entity is inside a vehicle. pub fn is_inside_vehicle(&self) -> Result> { - let sig = String::from("()Z"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } @@ -84331,10 +94931,12 @@ impl<'mc> EnderDragon<'mc> { /// is removed from it), true will be returned, otherwise false will be /// returned. pub fn leave_vehicle(&self) -> Result> { - let sig = String::from("()Z"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } @@ -84343,10 +94945,12 @@ impl<'mc> EnderDragon<'mc> { pub fn vehicle( &self, ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/entity/Entity;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getVehicle", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); @@ -84362,13 +94966,17 @@ impl<'mc> EnderDragon<'mc> { /// This value has no effect on players, they will always display their /// name. pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; let val_1 = jni::objects::JValueGen::Bool(flag.into()); + args.push(val_1); + sig += ")V"; let res = self.jni_ref().call_method( &self.jni_object(), "setCustomNameVisible", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); self.jni_ref().translate_error(res)?; Ok(()) @@ -84378,12 +94986,14 @@ impl<'mc> EnderDragon<'mc> { /// This value has no effect on players, they will always display their /// name. pub fn is_custom_name_visible(&self) -> Result> { - let sig = String::from("()Z"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self.jni_ref().call_method( &self.jni_object(), "isCustomNameVisible", sig.as_str(), - vec![], + args, ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) @@ -84393,13 +95003,17 @@ impl<'mc> EnderDragon<'mc> { /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} /// will need to be called before the entity is visible to a given player. pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; let val_1 = jni::objects::JValueGen::Bool(visible.into()); + args.push(val_1); + sig += ")V"; let res = self.jni_ref().call_method( &self.jni_object(), "setVisibleByDefault", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); self.jni_ref().translate_error(res)?; Ok(()) @@ -84409,12 +95023,14 @@ impl<'mc> EnderDragon<'mc> { /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} /// will need to be called before the entity is visible to a given player. pub fn is_visible_by_default(&self) -> Result> { - let sig = String::from("()Z"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self.jni_ref().call_method( &self.jni_object(), "isVisibleByDefault", sig.as_str(), - vec![], + args, ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) @@ -84428,10 +95044,12 @@ impl<'mc> EnderDragon<'mc> { pub fn tracked_by( &self, ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/util/Set;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) @@ -84441,14 +95059,15 @@ impl<'mc> EnderDragon<'mc> { /// nb: this refers to the 'Glowing' entity property, not whether a /// glowing potion effect is applied pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; let val_1 = jni::objects::JValueGen::Bool(flag.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setGlowing", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setGlowing", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } @@ -84456,10 +95075,12 @@ impl<'mc> EnderDragon<'mc> { /// nb: this refers to the 'Glowing' entity property, not whether a /// glowing potion effect is applied pub fn is_glowing(&self) -> Result> { - let sig = String::from("()Z"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isGlowing", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } @@ -84468,32 +95089,37 @@ impl<'mc> EnderDragon<'mc> { /// When an entity is invulnerable it can only be damaged by players in /// creative mode. pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; let val_1 = jni::objects::JValueGen::Bool(flag.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setInvulnerable", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setInvulnerable", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } /// Gets whether the entity is invulnerable or not. pub fn is_invulnerable(&self) -> Result> { - let sig = String::from("()Z"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } /// Gets whether the entity is silent or not. pub fn is_silent(&self) -> Result> { - let sig = String::from("()Z"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSilent", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } @@ -84501,61 +95127,65 @@ impl<'mc> EnderDragon<'mc> { /// /// When an entity is silent it will not produce any sound. pub fn set_silent(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; let val_1 = jni::objects::JValueGen::Bool(flag.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSilent", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setSilent", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } /// Returns whether gravity applies to this entity. pub fn has_gravity(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } /// Sets whether gravity applies to this entity. pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; let val_1 = jni::objects::JValueGen::Bool(gravity.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setGravity", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setGravity", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } /// Gets the period of time (in ticks) before this entity can use a portal. pub fn portal_cooldown(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPortalCooldown", - sig.as_str(), - vec![], - ); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPortalCooldown", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } /// Sets the period of time (in ticks) before this entity can use a portal. pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; let val_1 = jni::objects::JValueGen::Int(cooldown); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPortalCooldown", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setPortalCooldown", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } @@ -84565,13 +95195,12 @@ impl<'mc> EnderDragon<'mc> { pub fn scoreboard_tags( &self, ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getScoreboardTags", - sig.as_str(), - vec![], - ); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/util/Set;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getScoreboardTags", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) @@ -84584,16 +95213,17 @@ impl<'mc> EnderDragon<'mc> { &self, tag: impl Into, ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( self.jni_ref().new_string(tag.into())?, )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addScoreboardTag", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "addScoreboardTag", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } @@ -84602,15 +95232,19 @@ impl<'mc> EnderDragon<'mc> { &self, tag: impl Into, ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( self.jni_ref().new_string(tag.into())?, )); + args.push(val_1); + sig += ")Z"; let res = self.jni_ref().call_method( &self.jni_object(), "removeScoreboardTag", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) @@ -84619,12 +95253,14 @@ impl<'mc> EnderDragon<'mc> { pub fn piston_move_reaction( &self, ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/block/PistonMoveReaction;"; let res = self.jni_ref().call_method( &self.jni_object(), "getPistonMoveReaction", sig.as_str(), - vec![], + args, ); let res = self.jni_ref().translate_error(res)?; crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { @@ -84640,10 +95276,12 @@ impl<'mc> EnderDragon<'mc> { /// {@link Hanging} entities will override this call and thus their behavior /// may be different. pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/block/BlockFace;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFacing", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) @@ -84654,10 +95292,12 @@ impl<'mc> EnderDragon<'mc> { /// inconsistent with other methods. eg {@link Player#isSneaking()} being /// true does not imply the current pose will be {@link Pose#SNEAKING} pub fn pose(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Pose;"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/entity/Pose;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPose", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) @@ -84667,13 +95307,12 @@ impl<'mc> EnderDragon<'mc> { pub fn spawn_category( &self, ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSpawnCategory", - sig.as_str(), - vec![], - ); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/entity/SpawnCategory;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSpawnCategory", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) @@ -84684,10 +95323,12 @@ impl<'mc> EnderDragon<'mc> { /// Entities not spawned in a world will not tick, be sent to players, or be /// saved to the server files. pub fn is_in_world(&self) -> Result> { - let sig = String::from("()Z"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isInWorld", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } @@ -84695,10 +95336,12 @@ impl<'mc> EnderDragon<'mc> { /// /// This string should not be relied upon as a serializable value. pub fn as_string(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/lang/String;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getAsString", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); @@ -84714,10 +95357,12 @@ impl<'mc> EnderDragon<'mc> { pub fn create_snapshot( &self, ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/entity/EntitySnapshot;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); @@ -84752,255 +95397,217 @@ impl<'mc> EnderDragon<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Instructs this Mob to set the specified LivingEntity as its target. - /// - /// Hostile creatures may attack their target, and friendly creatures may - /// follow their target. - pub fn set_target( + /// Sets a metadata value in the implementing object's metadata store. + pub fn set_metadata( &self, - target: impl Into>, + metadata_key: impl Into, + new_metadata_value: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += "Lorg/bukkit/metadata/MetadataValue;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTarget", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_2); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setMetadata", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the current target of this Mob - pub fn target( + /// Returns a list of previously set metadata values from the implementing + /// object's metadata store. + pub fn get_metadata( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); + metadata_key: impl Into, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += ")Ljava/util/List;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getTarget", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMetadata", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::metadata::MetadataValue::from_raw( + &self.jni_ref(), + obj, + )?); } - Ok(Some(crate::entity::LivingEntity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Sets whether this mob is aware of its surroundings. - /// Unaware mobs will still move if pushed, attacked, etc. but will not move - /// or perform any actions on their own. Unaware mobs may also have other - /// unspecified behaviours disabled, such as drowning. - pub fn set_aware(&self, aware: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(aware.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAware", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(new_vec) } - /// Gets whether this mob is aware of its surroundings. - /// Unaware mobs will still move if pushed, attacked, etc. but will not move - /// or perform any actions on their own. Unaware mobs may also have other - /// unspecified behaviours disabled, such as drowning. - pub fn is_aware(&self) -> Result> { - let sig = String::from("()Z"); + /// Tests to see whether the implementing object contains the given + /// metadata value in its metadata store. + pub fn has_metadata( + &self, + metadata_key: impl Into, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isAware", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasMetadata", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get the {@link Sound} this mob makes while ambiently existing. This sound - /// may change depending on the current state of the entity, and may also - /// return null under specific conditions. This sound is not constant. - /// For instance, villagers will make different passive noises depending - /// on whether or not they are actively trading with a player, or make no - /// ambient noise while sleeping. - pub fn ambient_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAmbientSound", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Gets the specified attribute instance from the object. This instance will - /// be backed directly to the object and any changes will be visible at once. - pub fn get_attribute( + /// Removes the given metadata value from the implementing object's + /// metadata store. + pub fn remove_metadata( &self, - attribute: impl Into>, - ) -> Result>, Box> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + metadata_key: impl Into, + owning_plugin: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += "Lorg/bukkit/plugin/Plugin;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAttribute", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::attribute::AttributeInstance::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + args.push(val_2); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "removeMetadata", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Deals the given amount of damage to this entity from a specified - /// {@link DamageSource}. - pub fn damage( + /// Sends this sender multiple messages + pub fn send_message( &self, - amount: f64, - damage_source: std::option::Option>>, + sender: impl Into>, + messages: std::option::Option>, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(amount); + sig += "Ljava/util/UUID;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + }); args.push(val_1); - if let Some(a) = damage_source { - sig += "Lorg/bukkit/damage/DamageSource;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); + if let Some(a) = messages { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); args.push(val_2); } sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "damage", sig.as_str(), args); + .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. - pub fn health(&self) -> Result> { - let sig = String::from("()D"); + /// Gets the name of this command sender + pub fn name(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/lang/String;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is - /// dead. - pub fn set_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setHealth", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the entity's absorption amount. - pub fn absorption_amount(&self) -> Result> { - let sig = String::from("()D"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAbsorptionAmount", - sig.as_str(), - vec![], - ); + .call_method(&self.jni_object(), "getName", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets the entity's absorption amount. + /// Gets the custom name on a mob or block. If there is no name this method + /// will return null. /// - /// Note: The amount is capped to the value of - /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on - /// that attribute is currently unspecified and subject to change. - pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(amount); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAbsorptionAmount", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Gets the maximum health this entity has. - pub fn max_health(&self) -> Result> { - let sig = String::from("()D"); + /// This value has no effect on players, they will always use their real + /// name. + pub fn custom_name(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/lang/String;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCustomName", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - #[deprecated] - /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. - pub fn set_max_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaxHealth", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Resets the max health to the original amount. - pub fn reset_max_health(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( self.jni_ref() - .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Launches a {@link Projectile} from the ProjectileSource with an - /// initial velocity. - pub fn launch_projectile( + /// Sets a custom name on a mob or block. This name will be used in death + /// messages and can be sent to the client as a nameplate over the mob. + /// + /// Setting the name to null or an empty string will clear it. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn set_custom_name( &self, - projectile: jni::objects::JClass<'mc>, - velocity: std::option::Option>>, - ) -> Result, Box> { + name: impl Into, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/lang/Class;"; - let val_1 = jni::objects::JValueGen::Object(projectile.into()); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); args.push(val_1); - if let Some(a) = velocity { - sig += "Lorg/bukkit/util/Vector;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")LT;"; + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); + .call_method(&self.jni_object(), "setCustomName", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + pub fn persistent_data_container( + &self, + ) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPersistentDataContainer", + sig.as_str(), + args, + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -85008,49 +95615,55 @@ impl<'mc> EnderDragon<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for EnderDragon<'mc> { - fn into(self) -> crate::entity::ComplexLivingEntity<'mc> { - crate::entity::ComplexLivingEntity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EnderDragon into crate::entity::ComplexLivingEntity") - } -} -impl<'mc> Into> for EnderDragon<'mc> { - fn into(self) -> crate::entity::Boss<'mc> { - crate::entity::Boss::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EnderDragon into crate::entity::Boss") +impl<'mc> Into> for AbstractArrow<'mc> { + fn into(self) -> crate::entity::Projectile<'mc> { + crate::entity::Projectile::from_raw(&self.jni_ref(), self.1) + .expect("Error converting AbstractArrow into crate::entity::Projectile") } } -impl<'mc> Into> for EnderDragon<'mc> { - fn into(self) -> crate::entity::Mob<'mc> { - crate::entity::Mob::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EnderDragon into crate::entity::Mob") - } +pub enum AbstractArrowPickupStatus<'mc> { + Disallowed { + inner: AbstractArrowPickupStatusStruct<'mc>, + }, + Allowed { + inner: AbstractArrowPickupStatusStruct<'mc>, + }, + CreativeOnly { + inner: AbstractArrowPickupStatusStruct<'mc>, + }, } -impl<'mc> Into> for EnderDragon<'mc> { - fn into(self) -> crate::entity::Enemy<'mc> { - crate::entity::Enemy::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EnderDragon into crate::entity::Enemy") +impl<'mc> std::fmt::Display for AbstractArrowPickupStatus<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + AbstractArrowPickupStatus::Disallowed { .. } => f.write_str("DISALLOWED"), + AbstractArrowPickupStatus::Allowed { .. } => f.write_str("ALLOWED"), + AbstractArrowPickupStatus::CreativeOnly { .. } => f.write_str("CREATIVE_ONLY"), + } } } -pub enum EnderDragonPhase<'mc> {} -impl<'mc> std::fmt::Display for EnderDragonPhase<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} +impl<'mc> std::ops::Deref for AbstractArrowPickupStatus<'mc> { + type Target = AbstractArrowPickupStatusStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + AbstractArrowPickupStatus::Disallowed { inner } => inner, + AbstractArrowPickupStatus::Allowed { inner } => inner, + AbstractArrowPickupStatus::CreativeOnly { inner } => inner, + } } } -impl<'mc> EnderDragonPhase<'mc> { +impl<'mc> AbstractArrowPickupStatus<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/EnderDragon/Phase"); + let cls = env.find_class("org/bukkit/entity/AbstractArrow/PickupStatus"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/EnderDragon/Phase;", + "(Ljava/lang/String;)Lorg/bukkit/entity/AbstractArrow/PickupStatus;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -85062,39 +95675,63 @@ impl<'mc> EnderDragonPhase<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "DISALLOWED" => Ok(AbstractArrowPickupStatus::Disallowed { + inner: AbstractArrowPickupStatusStruct::from_raw(env, obj)?, + }), + "ALLOWED" => Ok(AbstractArrowPickupStatus::Allowed { + inner: AbstractArrowPickupStatusStruct::from_raw(env, obj)?, + }), + "CREATIVE_ONLY" => Ok(AbstractArrowPickupStatus::CreativeOnly { + inner: AbstractArrowPickupStatusStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct EnderDragonPhaseStruct<'mc>( +pub struct AbstractArrowPickupStatusStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EnderDragonPhase<'mc> { +impl<'mc> JNIRaw<'mc> for AbstractArrowPickupStatus<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Disallowed { inner } => inner.0.clone(), + Self::Allowed { inner } => inner.0.clone(), + Self::CreativeOnly { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Disallowed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Allowed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CreativeOnly { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } -impl<'mc> JNIInstantiatable<'mc> for EnderDragonPhase<'mc> { +impl<'mc> JNIInstantiatable<'mc> for AbstractArrowPickupStatus<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate EnderDragonPhase from null object.").into(), - ); + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate AbstractArrowPickupStatus from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EnderDragon/Phase")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/entity/AbstractArrow/PickupStatus")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EnderDragonPhase object, got {}", + "Invalid argument passed. Expected a AbstractArrowPickupStatus object, got {}", name ) .into()) @@ -85106,13 +95743,22 @@ impl<'mc> JNIInstantiatable<'mc> for EnderDragonPhase<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "DISALLOWED" => Ok(AbstractArrowPickupStatus::Disallowed { + inner: AbstractArrowPickupStatusStruct::from_raw(env, obj)?, + }), + "ALLOWED" => Ok(AbstractArrowPickupStatus::Allowed { + inner: AbstractArrowPickupStatusStruct::from_raw(env, obj)?, + }), + "CREATIVE_ONLY" => Ok(AbstractArrowPickupStatus::CreativeOnly { + inner: AbstractArrowPickupStatusStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for EnderDragonPhaseStruct<'mc> { +impl<'mc> JNIRaw<'mc> for AbstractArrowPickupStatusStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -85120,41 +95766,42 @@ impl<'mc> JNIRaw<'mc> for EnderDragonPhaseStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EnderDragonPhaseStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for AbstractArrowPickupStatusStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate EnderDragonPhaseStruct from null object." + "Tried to instantiate AbstractArrowPickupStatusStruct from null object." ) .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EnderDragon/Phase")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/entity/AbstractArrow/PickupStatus")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EnderDragonPhaseStruct object, got {}", - name - ) - .into()) + "Invalid argument passed. Expected a AbstractArrowPickupStatusStruct object, got {}", + name + ) + .into()) } else { Ok(Self(env.clone(), obj)) } } } -impl<'mc> EnderDragonPhaseStruct<'mc> { +impl<'mc> AbstractArrowPickupStatusStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EnderDragon/Phase;"); - let cls = jni.find_class("org/bukkit/entity/EnderDragon/Phase"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/AbstractArrow/PickupStatus;"); + let cls = jni.find_class("org/bukkit/entity/AbstractArrow/PickupStatus"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::entity::EnderDragonPhase::from_raw(&jni, obj) + crate::entity::AbstractArrowPickupStatus::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -85163,4130 +95810,3656 @@ impl<'mc> EnderDragonPhaseStruct<'mc> { } } #[repr(C)] -pub struct Minecart<'mc>( +pub struct Goat<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Minecart<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Minecart<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Minecart from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Minecart")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Minecart object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Minecart<'mc> { - /// Sets a minecart's damage. - pub fn set_damage(&self, damage: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(damage); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setDamage", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets a minecart's damage. - pub fn damage(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getDamage", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the maximum speed of a minecart. The speed is unrelated to the - /// velocity. - pub fn max_speed(&self) -> Result> { - let sig = String::from("()D"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaxSpeed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Sets the maximum speed of a minecart. Must be nonnegative. Default is - /// 0.4D. - pub fn set_max_speed(&self, speed: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(speed); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaxSpeed", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns whether this minecart will slow down faster without a passenger - /// occupying it - pub fn is_slow_when_empty(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isSlowWhenEmpty", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether this minecart will slow down faster without a passenger - /// occupying it - pub fn set_slow_when_empty(&self, slow: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(slow.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSlowWhenEmpty", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the flying velocity modifier. Used for minecarts that are in - /// mid-air. A flying minecart's velocity is multiplied by this factor each - /// tick. - pub fn flying_velocity_mod( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFlyingVelocityMod", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the flying velocity modifier. Used for minecarts that are in - /// mid-air. A flying minecart's velocity is multiplied by this factor each - /// tick. - pub fn set_flying_velocity_mod( - &self, - flying: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(flying.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFlyingVelocityMod", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the derailed velocity modifier. Used for minecarts that are on the - /// ground, but not on rails. - /// - /// A derailed minecart's velocity is multiplied by this factor each tick. - pub fn derailed_velocity_mod( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getDerailedVelocityMod", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the derailed velocity modifier. Used for minecarts that are on the - /// ground, but not on rails. A derailed minecart's velocity is multiplied - /// by this factor each tick. - pub fn set_derailed_velocity_mod( - &self, - derailed: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(derailed.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setDerailedVelocityMod", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Sets the display block for this minecart. - /// Passing a null value will set the minecart to have no display block. - pub fn set_display_block( - &self, - material: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/material/MaterialData;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setDisplayBlock", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the display block for this minecart. - /// This function will return the type AIR if none is set. - pub fn display_block( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/MaterialData;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDisplayBlock", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the display block for this minecart. - /// Passing a null value will set the minecart to have no display block. - pub fn set_display_block_data( - &self, - block_data: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block_data.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setDisplayBlockData", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the display block for this minecart. - /// This function will return the type AIR if none is set. - pub fn display_block_data( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getDisplayBlockData", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the offset of the display block. - pub fn set_display_block_offset(&self, offset: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(offset); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setDisplayBlockOffset", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the offset of the display block. - pub fn display_block_offset(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getDisplayBlockOffset", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the vehicle's velocity. - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the vehicle's velocity in meters per tick. - pub fn set_velocity( - &self, - vel: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(vel.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setVelocity", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Stores the entity's current position in the provided Location object. - /// - /// If the provided Location is null this method does nothing and returns - /// null. - pub fn get_location( - &self, - loc: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/Location;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLocation", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Gets the entity's height - pub fn height(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the entity's width - pub fn width(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the entity's current bounding box. - /// - /// The returned bounding box reflects the entity's current location and - /// size. - pub fn bounding_box( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns true if the entity is supported by a block. This value is a - /// state updated by the server and is not recalculated unless the entity - /// moves. - pub fn is_on_ground(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns true if the entity is in water. - pub fn is_in_water(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWater", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the current world this entity resides in - pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the entity's rotation. - /// - /// Note that if the entity is affected by AI, it may override this rotation. - pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { - let sig = String::from("(FF)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); - let val_2 = jni::objects::JValueGen::Float(pitch); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRotation", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Teleports this entity to the given location. If this entity is riding a - /// vehicle, it will be dismounted prior to teleportation. - pub fn teleport( - &self, - location: impl Into>, - cause: std::option::Option< - impl Into>, - >, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = cause { - sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "teleport", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns a list of entities within a bounding box centered around this - /// entity - pub fn get_nearby_entities( - &self, - x: f64, - y: f64, - z: f64, - ) -> Result>, Box> { - let sig = String::from("(DDD)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Double(x); - let val_2 = jni::objects::JValueGen::Double(y); - let val_3 = jni::objects::JValueGen::Double(z); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getNearbyEntities", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) +impl<'mc> JNIRaw<'mc> for Goat<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Returns a unique id for this entity - pub fn entity_id(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEntityId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Returns the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn fire_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) +} +impl<'mc> JNIInstantiatable<'mc> for Goat<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Goat from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Goat")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Goat object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } - /// Returns the entity's maximum fire ticks. - pub fn max_fire_ticks(&self) -> Result> { - let sig = String::from("()I"); +} + +impl<'mc> Goat<'mc> { + /// Gets if this goat has its left horn. + pub fn has_left_horn(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasLeftHorn", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFireTicks", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.z()?) } - /// Sets if the entity has visual fire (it will always appear to be on fire). - pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { + /// Sets if this goat has its left horn. + pub fn set_left_horn(&self, has_horn: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire.into()); + let val_1 = jni::objects::JValueGen::Bool(has_horn.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisualFire", + "setLeftHorn", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity has visual fire (it will always appear to be on fire). - pub fn is_visual_fire(&self) -> Result> { + /// Gets if this goat has its right horn. + pub fn has_right_horn(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasRightHorn", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the entity's maximum freeze ticks (amount of ticks before it will - /// be fully frozen) - pub fn max_freeze_ticks(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMaxFreezeTicks", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets if this goat has its right horn. + pub fn set_right_horn(&self, has_horn: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(has_horn.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setFreezeTicks", + "setRightHorn", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity is fully frozen (it has been in powdered snow for max - /// freeze ticks). - pub fn is_frozen(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isFrozen", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Mark the entity's removal. - pub fn remove(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns true if this entity has been marked for removal. - pub fn is_dead(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isDead", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns false if the entity has died, been despawned for some other - /// reason, or has not been added to the world. - pub fn is_valid(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the {@link Server} that contains this Entity - pub fn server(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Server;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getServer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Server::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns true if the entity gets persisted. - /// - /// By default all entities are persistent. An entity will also not get - /// persisted, if it is riding an entity that is not persistent. - /// - /// The persistent flag on players controls whether or not to save their - /// playerdata file when they quit. If a player is directly or indirectly - /// riding a non-persistent entity, the vehicle at the root and all its - /// passengers won't get persisted. - /// - /// This should not be confused with - /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls - /// despawning of living entities. - pub fn is_persistent(&self) -> Result> { + /// Gets if this is a screaming goat. + /// A screaming goat makes screaming sounds and rams more often. They do not + /// offer home loans. + pub fn is_screaming(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isPersistent", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isScreaming", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not the entity gets persisted. - pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { + /// Sets if this is a screaming goat. + /// A screaming goat makes screaming sounds and rams more often. They do not + /// offer home loans. + pub fn set_screaming(&self, screaming: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(persistent.into()); + let val_1 = jni::objects::JValueGen::Bool(screaming.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setPersistent", + "setScreaming", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. - pub fn passenger( + /// Get the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn breed_cause( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/UUID;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPassenger", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Entity::from_raw( + Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - #[deprecated] - /// Set the passenger of a vehicle. - pub fn set_passenger( + /// Set the UUID of the entity that caused this entity to enter the + /// {@link #canBreed()} state. + pub fn set_breed_cause( &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); + uuid: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/UUID;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPassenger", + "setBreedCause", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets a list of passengers of this vehicle. - /// - /// The returned list will not be directly linked to the entity's current - /// passengers, and no guarantees are made as to its mutability. - pub fn passengers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + /// Get whether or not this entity is in love mode and will produce + /// offspring with another entity in love mode. Will return true if + /// and only if {@link #getLoveModeTicks()} is greater than 0. + pub fn is_love_mode(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPassengers", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(res.z()?) } - /// Add a passenger to the vehicle. - pub fn add_passenger( - &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); + /// Get the amount of ticks remaining for this entity in love mode. + /// If the entity is not in love mode, 0 will be returned. + pub fn love_mode_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "addPassenger", + "getLoveModeTicks", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Remove a passenger from the vehicle. - pub fn remove_passenger( - &self, - passenger: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); + /// Set the amount of ticks for which this entity should be in love mode. + /// Setting the love mode ticks to 600 is the equivalent of a player + /// feeding the entity their breeding item of choice. + pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "removePassenger", + "setLoveModeTicks", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Check if a vehicle has passengers. - pub fn is_empty(&self) -> Result> { - let sig = String::from("()Z"); + /// Check if the provided ItemStack is the correct item used for breeding + /// this entity.. + pub fn is_breed_item( + &self, + material: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Eject any passenger. - pub fn eject(&self) -> Result> { - let sig = String::from("()Z"); + /// Lock the age of the animal, setting this will prevent the animal from + /// maturing or getting ready for mating. + pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(lock.into()); + args.push(val_1); + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "eject", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "setAgeLock", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the current agelock. + pub fn age_lock(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns the distance this entity has fallen - pub fn fall_distance(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), vec![]); + /// Return the ability to breed of the animal. + pub fn can_breed(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "canBreed", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Sets the fall distance for this entity - pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(distance); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFallDistance", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.z()?) } - #[deprecated] - /// Record the last {@link EntityDamageEvent} inflicted on this entity - pub fn set_last_damage_cause( - &self, - event: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(event.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLastDamageCause", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Set breedability of the animal, if the animal is a baby and set to + /// breed it will instantly grow up. + pub fn set_breed(&self, breed: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(breed.into()); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setBreed", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. - /// This event may have been cancelled. - pub fn last_damage_cause( - &self, - ) -> Result>, Box> - { - let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLastDamageCause", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Returns a unique and persistent id for this entity - pub fn unique_id( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} +impl<'mc> Into> for Goat<'mc> { + fn into(self) -> crate::entity::Animals<'mc> { + crate::entity::Animals::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Goat into crate::entity::Animals") } - /// Gets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. - pub fn ticks_lived(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) +} +#[repr(C)] +pub struct EnderDragonPart<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for EnderDragonPart<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Sets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. May not be less than one - /// tick. - pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(value); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTicksLived", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Performs the specified {@link EntityEffect} for this entity. - /// - /// This will be viewable to all players near the entity. - /// - /// If the effect is not applicable to this class of entity, it will not play. - pub fn play_effect( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/EntityEffect;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "playEffect", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +} +impl<'mc> JNIInstantiatable<'mc> for EnderDragonPart<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate EnderDragonPart from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EnderDragonPart")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EnderDragonPart object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } - /// Get the type of the entity. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); +} + +impl<'mc> EnderDragonPart<'mc> { + pub fn parent(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EnderDragon;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity makes while swimming. - pub fn swim_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getParent", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { + crate::entity::EnderDragon::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the {@link Sound} this entity makes when splashing in water. For most - /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_splash_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSwimSplashSound", - sig.as_str(), - vec![], - ); + /// Stores the entity's current position in the provided Location object. + /// + /// If the provided Location is null this method does nothing and returns + /// null. + pub fn get_location( + &self, + loc: impl Into>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Lorg/bukkit/Location;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLocation", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) + })?)) } - /// Get the {@link Sound} this entity makes when splashing in water at high - /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_high_speed_splash_sound( + /// Sets this entity's velocity in meters per tick + pub fn set_velocity( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSwimHighSpeedSplashSound", - sig.as_str(), - vec![], - ); + velocity: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/util/Vector;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setVelocity", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets this entity's current velocity + pub fn velocity(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/util/Vector;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns whether this entity is inside a vehicle. - pub fn is_inside_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), vec![]); + /// Gets the entity's height + pub fn height(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")D"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHeight", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Leave the current vehicle. If the entity is currently in a vehicle (and - /// is removed from it), true will be returned, otherwise false will be - /// returned. - pub fn leave_vehicle(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), vec![]); + /// Gets the entity's width + pub fn width(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")D"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWidth", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Get the vehicle that this entity is inside. If there is no vehicle, - /// null will be returned. - pub fn vehicle( + /// Gets the entity's current bounding box. + /// + /// The returned bounding box reflects the entity's current location and + /// size. + pub fn bounding_box( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + ) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/util/BoundingBox;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getVehicle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Sets whether or not to display the mob's custom name client side. The - /// name will be displayed above the mob similarly to a player. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCustomNameVisible", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets whether or not the mob's custom name is displayed client side. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn is_custom_name_visible(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isCustomNameVisible", - sig.as_str(), - vec![], - ); + /// Returns true if the entity is supported by a block. This value is a + /// state updated by the server and is not recalculated unless the entity + /// moves. + pub fn is_on_ground(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isOnGround", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(visible.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setVisibleByDefault", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn is_visible_by_default(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isVisibleByDefault", - sig.as_str(), - vec![], - ); + /// Returns true if the entity is in water. + pub fn is_in_water(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWater", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get all players that are currently tracking this entity. - /// - /// 'Tracking' means that this entity has been sent to the player and that - /// they are receiving updates on its state. Note that the client's {@code - /// 'Entity Distance'} setting does not affect the range at which entities - /// are tracked. - pub fn tracked_by( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), vec![]); + /// Gets the current world this entity resides in + pub fn world(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/World;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + crate::World::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets whether the entity has a team colored (default: white) glow. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setGlowing", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Sets the entity's rotation. + /// + /// Note that if the entity is affected by AI, it may override this rotation. + pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "F"; + let val_1 = jni::objects::JValueGen::Float(yaw); + args.push(val_1); + sig += "F"; + let val_2 = jni::objects::JValueGen::Float(pitch); + args.push(val_2); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setRotation", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is glowing or not. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn is_glowing(&self) -> Result> { - let sig = String::from("()Z"); + /// Teleports this entity to the given location. If this entity is riding a + /// vehicle, it will be dismounted prior to teleportation. + pub fn teleport( + &self, + location: impl Into>, + cause: std::option::Option< + impl Into>, + >, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = cause { + sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isGlowing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "teleport", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the entity is invulnerable or not. - /// - /// When an entity is invulnerable it can only be damaged by players in - /// creative mode. - pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setInvulnerable", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether the entity is invulnerable or not. - pub fn is_invulnerable(&self) -> Result> { - let sig = String::from("()Z"); + /// Returns a list of entities within a bounding box centered around this + /// entity + pub fn get_nearby_entities( + &self, + x: f64, + y: f64, + z: f64, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(x); + args.push(val_1); + sig += "D"; + let val_2 = jni::objects::JValueGen::Double(y); + args.push(val_2); + sig += "D"; + let val_3 = jni::objects::JValueGen::Double(z); + args.push(val_3); + sig += ")Ljava/util/List;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getNearbyEntities", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Gets whether the entity is silent or not. - pub fn is_silent(&self) -> Result> { - let sig = String::from("()Z"); + /// Returns a unique id for this entity + pub fn entity_id(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isSilent", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEntityId", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether the entity is silent or not. - /// - /// When an entity is silent it will not produce any sound. - pub fn set_silent(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSilent", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.i()?) } - /// Returns whether gravity applies to this entity. - pub fn has_gravity(&self) -> Result> { - let sig = String::from("()Z"); + /// Returns the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn fire_ticks(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; let res = self.jni_ref() - .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether gravity applies to this entity. - pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(gravity.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setGravity", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.i()?) } - /// Gets the period of time (in ticks) before this entity can use a portal. - pub fn portal_cooldown(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPortalCooldown", - sig.as_str(), - vec![], - ); + /// Returns the entity's maximum fire ticks. + pub fn max_fire_ticks(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the period of time (in ticks) before this entity can use a portal. - pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(cooldown); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPortalCooldown", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Sets the entity's current fire ticks (ticks before the entity stops + /// being on fire). + pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setFireTicks", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a set of tags for this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn scoreboard_tags( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getScoreboardTags", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Sets if the entity has visual fire (it will always appear to be on fire). + pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(fire.into()); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setVisualFire", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Add a tag to this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn add_scoreboard_tag( - &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addScoreboardTag", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Gets if the entity has visual fire (it will always appear to be on fire). + pub fn is_visual_fire(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes a given tag from this entity. - pub fn remove_scoreboard_tag( - &self, - tag: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removeScoreboardTag", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Returns the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn freeze_ticks(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Returns the reaction of the entity when moved by a piston. - pub fn piston_move_reaction( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/PistonMoveReaction;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPistonMoveReaction", - sig.as_str(), - vec![], - ); + /// Returns the entity's maximum freeze ticks (amount of ticks before it will + /// be fully frozen) + pub fn max_freeze_ticks(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")I"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxFreezeTicks", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Get the closest cardinal {@link BlockFace} direction an entity is - /// currently facing. - /// - /// This will not return any non-cardinal directions such as - /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. - /// - /// {@link Hanging} entities will override this call and thus their behavior - /// may be different. - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + /// Sets the entity's current freeze ticks (amount of ticks the entity has + /// been in powdered snow). + pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setFreezeTicks", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the entity is fully frozen (it has been in powdered snow for max + /// freeze ticks). + pub fn is_frozen(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isFrozen", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Gets the entity's current pose. - /// Note that the pose is only updated at the end of a tick, so may be - /// inconsistent with other methods. eg {@link Player#isSneaking()} being - /// true does not imply the current pose will be {@link Pose#SNEAKING} - pub fn pose(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Pose;"); + /// Mark the entity's removal. + pub fn remove(&self) -> Result<(), Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + .call_method(&self.jni_object(), "remove", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the category of spawn to which this entity belongs. - pub fn spawn_category( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/SpawnCategory;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSpawnCategory", - sig.as_str(), - vec![], - ); + /// Returns true if this entity has been marked for removal. + pub fn is_dead(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isDead", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Checks if this entity has been spawned in a world. - /// - /// Entities not spawned in a world will not tick, be sent to players, or be - /// saved to the server files. - pub fn is_in_world(&self) -> Result> { - let sig = String::from("()Z"); + /// Returns false if the entity has died, been despawned for some other + /// reason, or has not been added to the world. + pub fn is_valid(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isInWorld", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isValid", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get this entity as an NBT string. + /// Gets the {@link Server} that contains this Entity + pub fn server(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Server;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getServer", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::Server::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns true if the entity gets persisted. /// - /// This string should not be relied upon as a serializable value. - pub fn as_string(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); + /// By default all entities are persistent. An entity will also not get + /// persisted, if it is riding an entity that is not persistent. + /// + /// The persistent flag on players controls whether or not to save their + /// playerdata file when they quit. If a player is directly or indirectly + /// riding a non-persistent entity, the vehicle at the root and all its + /// passengers won't get persisted. + /// + /// This should not be confused with + /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls + /// despawning of living entities. + pub fn is_persistent(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isPersistent", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( + Ok(res.z()?) + } + /// Sets whether or not the entity gets persisted. + pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(persistent.into()); + args.push(val_1); + sig += ")V"; + let res = self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + .call_method(&self.jni_object(), "setPersistent", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Crates an {@link EntitySnapshot} representing the current state of this entity. - pub fn create_snapshot( + #[deprecated] + /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. + pub fn passenger( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + ) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/entity/Entity;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPassenger", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::EntitySnapshot::from_raw( + Ok(Some(crate::entity::Entity::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Creates a copy of this entity and all its data. Spawns the copy at the given location. - /// - /// Note: Players cannot be copied. - pub fn copy( + #[deprecated] + /// Set the passenger of a vehicle. + pub fn set_passenger( &self, - to: std::option::Option>>, - ) -> Result, Box> { + passenger: impl Into>, + ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = to { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")Lorg/bukkit/entity/Entity;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets a metadata value in the implementing object's metadata store. - pub fn set_metadata( - &self, - metadata_key: impl Into, - new_metadata_value: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) + sig += "Lorg/bukkit/entity/Entity;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMetadata", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + args.push(val_1); + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setPassenger", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Returns a list of previously set metadata values from the implementing - /// object's metadata store. - pub fn get_metadata( + /// Gets a list of passengers of this vehicle. + /// + /// The returned list will not be directly linked to the entity's current + /// passengers, and no guarantees are made as to its mutability. + pub fn passengers( &self, - metadata_key: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMetadata", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + ) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/util/List;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPassengers", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::metadata::MetadataValue::from_raw( - &self.jni_ref(), - obj, - )?); + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); } Ok(new_vec) } - /// Tests to see whether the implementing object contains the given - /// metadata value in its metadata store. - pub fn has_metadata( + /// Add a passenger to the vehicle. + pub fn add_passenger( &self, - metadata_key: impl Into, + passenger: impl Into>, ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasMetadata", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Entity;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "addPassenger", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes the given metadata value from the implementing object's - /// metadata store. - pub fn remove_metadata( - &self, - metadata_key: impl Into, - owning_plugin: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removeMetadata", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Sends this sender multiple messages - pub fn send_message( + /// Remove a passenger from the vehicle. + pub fn remove_passenger( &self, - sender: impl Into>, - messages: std::option::Option>, - ) -> Result<(), Box> { + passenger: impl Into>, + ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; + sig += "Lorg/bukkit/entity/Entity;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) }); args.push(val_1); - if let Some(a) = messages { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the name of this command sender - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Gets the custom name on a mob or block. If there is no name this method - /// will return null. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn custom_name(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getCustomName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// Sets a custom name on a mob or block. This name will be used in death - /// messages and can be sent to the client as a nameplate over the mob. - /// - /// Setting the name to null or an empty string will clear it. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn set_custom_name( - &self, - name: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCustomName", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/persistence/PersistentDataContainer;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPersistentDataContainer", - sig.as_str(), - vec![], - ); + .call_method(&self.jni_object(), "removePassenger", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Minecart<'mc> { - fn into(self) -> crate::entity::Vehicle<'mc> { - crate::entity::Vehicle::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Minecart into crate::entity::Vehicle") - } -} -#[repr(C)] -pub struct Phantom<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Phantom<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for Phantom<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Phantom from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Phantom")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Phantom object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Check if a vehicle has passengers. + pub fn is_empty(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} - -impl<'mc> Phantom<'mc> { - pub fn size(&self) -> Result> { - let sig = String::from("()I"); + /// Eject any passenger. + pub fn eject(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "eject", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - - pub fn set_size(&self, sz: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(sz); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSize", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Returns the distance this entity has fallen + pub fn fall_distance(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")F"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the fall distance for this entity + pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "F"; + let val_1 = jni::objects::JValueGen::Float(distance); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setFallDistance", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Instructs this Mob to set the specified LivingEntity as its target. - /// - /// Hostile creatures may attack their target, and friendly creatures may - /// follow their target. - pub fn set_target( + #[deprecated] + /// Record the last {@link EntityDamageEvent} inflicted on this entity + pub fn set_last_damage_cause( &self, - target: impl Into>, + event: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)V"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/event/entity/EntityDamageEvent;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) + jni::objects::JObject::from_raw(event.into().jni_object().clone()) }); + args.push(val_1); + sig += ")V"; let res = self.jni_ref().call_method( &self.jni_object(), - "setTarget", + "setLastDamageCause", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the current target of this Mob - pub fn target( + /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. + /// This event may have been cancelled. + pub fn last_damage_cause( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTarget", sig.as_str(), vec![]); + ) -> Result>, Box> + { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/event/entity/EntityDamageEvent;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLastDamageCause", + sig.as_str(), + args, + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::LivingEntity::from_raw( + Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets whether this mob is aware of its surroundings. - /// Unaware mobs will still move if pushed, attacked, etc. but will not move - /// or perform any actions on their own. Unaware mobs may also have other - /// unspecified behaviours disabled, such as drowning. - pub fn set_aware(&self, aware: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(aware.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAware", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether this mob is aware of its surroundings. - /// Unaware mobs will still move if pushed, attacked, etc. but will not move - /// or perform any actions on their own. Unaware mobs may also have other - /// unspecified behaviours disabled, such as drowning. - pub fn is_aware(&self) -> Result> { - let sig = String::from("()Z"); + /// Returns a unique and persistent id for this entity + pub fn unique_id( + &self, + ) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/util/UUID;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isAware", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the {@link Sound} this mob makes while ambiently existing. This sound - /// may change depending on the current state of the entity, and may also - /// return null under specific conditions. This sound is not constant. - /// For instance, villagers will make different passive noises depending - /// on whether or not they are actively trading with a player, or make no - /// ambient noise while sleeping. - pub fn ambient_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAmbientSound", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Gets the height of the living entity's eyes above its Location. - pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); - args.push(val_1); - sig += ")D"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEyeHeight", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + }) } - /// Get a Location detailing the current eye position of the living entity. - pub fn eye_location(&self) -> Result, Box> { + /// Gets the amount of ticks this entity has lived for. + /// + /// This is the equivalent to "age" in entities. + pub fn ticks_lived(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")Lorg/bukkit/Location;"; + sig += ")I"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), args); + .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Gets all blocks along the living entity's line of sight. + /// Sets the amount of ticks this entity has lived for. /// - /// This list contains all blocks from the living entity's eye position to - /// target inclusive. This method considers all blocks as 1x1x1 in size. - pub fn get_line_of_sight( - &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { + /// This is the equivalent to "age" in entities. May not be less than one + /// tick. + pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/util/Set;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) - }); - args.push(val_1); sig += "I"; - let val_2 = jni::objects::JValueGen::Int(max_distance); - args.push(val_2); - sig += ")Ljava/util/List;"; + let val_1 = jni::objects::JValueGen::Int(value); + args.push(val_1); + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getLineOfSight", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + .call_method(&self.jni_object(), "setTicksLived", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the block that the living entity has targeted. + /// Performs the specified {@link EntityEffect} for this entity. /// - /// This method considers all blocks as 1x1x1 in size. To take exact block - /// collision shapes into account, see {@link #getTargetBlockExact(int, - /// FluidCollisionMode)}. - pub fn get_target_block( + /// This will be viewable to all players near the entity. + /// + /// If the effect is not applicable to this class of entity, it will not play. + pub fn play_effect( &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result, Box> { + val_type: impl Into>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/util/Set;"; + sig += "Lorg/bukkit/EntityEffect;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); args.push(val_1); - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(max_distance); - args.push(val_2); - sig += ")Lorg/bukkit/block/Block;"; + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "playEffect", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the type of the entity. + pub fn get_type(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/entity/EntityType;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity makes while swimming. + pub fn swim_sound(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getTargetBlock", sig.as_str(), args); + .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { + crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the last two blocks along the living entity's line of sight. - /// - /// The target block will be the last block in the list. This method - /// considers all blocks as 1x1x1 in size. - pub fn get_last_two_target_blocks( - &self, - transparent: impl Into>, - max_distance: i32, - ) -> Result>, Box> { - let mut args = Vec::new(); + /// Get the {@link Sound} this entity makes when splashing in water. For most + /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_splash_sound(&self) -> Result, Box> { + let args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/util/Set;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) - }); - args.push(val_1); - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(max_distance); - args.push(val_2); - sig += ")Ljava/util/List;"; + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref().call_method( &self.jni_object(), - "getLastTwoTargetBlocks", + "getSwimSplashSound", sig.as_str(), args, ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the block that the living entity has targeted. - /// - /// This takes the blocks' precise collision shapes into account. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn get_target_block_exact( + /// Get the {@link Sound} this entity makes when splashing in water at high + /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. + pub fn swim_high_speed_splash_sound( &self, - max_distance: i32, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); + ) -> Result, Box> { + let args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(max_distance); - args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/block/Block;"; + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref().call_method( &self.jni_object(), - "getTargetBlockExact", + "getSwimHighSpeedSplashSound", sig.as_str(), args, ); let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns whether this entity is inside a vehicle. + pub fn is_inside_vehicle(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Leave the current vehicle. If the entity is currently in a vehicle (and + /// is removed from it), true will be returned, otherwise false will be + /// returned. + pub fn leave_vehicle(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the vehicle that this entity is inside. If there is no vehicle, + /// null will be returned. + pub fn vehicle( + &self, + ) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/entity/Entity;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getVehicle", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::block::Block::from_raw( + Ok(Some(crate::entity::Entity::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Performs a ray trace that provides information on the targeted block. + /// Sets whether or not to display the mob's custom name client side. The + /// name will be displayed above the mob similarly to a player. /// - /// This takes the blocks' precise collision shapes into account. + /// This value has no effect on players, they will always display their + /// name. + pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + args.push(val_1); + sig += ")V"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCustomNameVisible", + sig.as_str(), + args, + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether or not the mob's custom name is displayed client side. /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn ray_trace_blocks( - &self, - max_distance: f64, - fluid_collision_mode: std::option::Option>>, - ) -> Result>, Box> { + /// This value has no effect on players, they will always display their + /// name. + pub fn is_custom_name_visible(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "isCustomNameVisible", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(max_distance); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(visible.into()); args.push(val_1); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/util/RayTraceResult;"; + sig += ")V"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVisibleByDefault", + sig.as_str(), + args, + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether or not this entity is visible by default. + /// If this entity is not visible by default, then + /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} + /// will need to be called before the entity is visible to a given player. + pub fn is_visible_by_default(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "isVisibleByDefault", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get all players that are currently tracking this entity. + /// + /// 'Tracking' means that this entity has been sent to the player and that + /// they are receiving updates on its state. Note that the client's {@code + /// 'Entity Distance'} setting does not affect the range at which entities + /// are tracked. + pub fn tracked_by( + &self, + ) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/util/Set;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); + .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::util::RayTraceResult::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the amount of air that the living entity has remaining, in - /// ticks. - pub fn remaining_air(&self) -> Result> { + /// Sets whether the entity has a team colored (default: white) glow. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setGlowing", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether the entity is glowing or not. + /// nb: this refers to the 'Glowing' entity property, not whether a + /// glowing potion effect is applied + pub fn is_glowing(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")I"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), args); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGlowing", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the amount of air that the living entity has remaining, in ticks. - pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { + /// Sets whether the entity is invulnerable or not. + /// + /// When an entity is invulnerable it can only be damaged by players in + /// creative mode. + pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(ticks); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(flag.into()); args.push(val_1); sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "setRemainingAir", sig.as_str(), args); + .call_method(&self.jni_object(), "setInvulnerable", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the maximum amount of air the living entity can have, in ticks. - pub fn maximum_air(&self) -> Result> { + /// Gets whether the entity is invulnerable or not. + pub fn is_invulnerable(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")I"; + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), args); + .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the maximum amount of air the living entity can have, in ticks. - pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { + /// Gets whether the entity is silent or not. + pub fn is_silent(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSilent", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the entity is silent or not. + /// + /// When an entity is silent it will not produce any sound. + pub fn set_silent(&self, flag: bool) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(ticks); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(flag.into()); args.push(val_1); sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setMaximumAir", sig.as_str(), args); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setSilent", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the item that the player is using (eating food, drawing back a bow, - /// blocking, etc.) - pub fn item_in_use( - &self, - ) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/inventory/ItemStack;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Gets the number of ticks remaining for the current item's usage. - pub fn item_in_use_ticks(&self) -> Result> { + /// Returns whether gravity applies to this entity. + pub fn has_gravity(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")I"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemInUseTicks", sig.as_str(), args); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the number of ticks that remain for the current item's usage. - /// Applies to items that take time to use, like eating food, drawing a bow, - /// or throwing a trident. - pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Sets whether gravity applies to this entity. + pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(ticks); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(gravity.into()); args.push(val_1); sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setItemInUseTicks", sig.as_str(), args); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setGravity", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the time in ticks until the next arrow leaves the entity's body. - pub fn arrow_cooldown(&self) -> Result> { + /// Gets the period of time (in ticks) before this entity can use a portal. + pub fn portal_cooldown(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); sig += ")I"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getArrowCooldown", sig.as_str(), args); + .call_method(&self.jni_object(), "getPortalCooldown", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the time in ticks until the next arrow leaves the entity's body. - pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { + /// Sets the period of time (in ticks) before this entity can use a portal. + pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "I"; - let val_1 = jni::objects::JValueGen::Int(ticks); + let val_1 = jni::objects::JValueGen::Int(cooldown); args.push(val_1); sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "setArrowCooldown", sig.as_str(), args); + .call_method(&self.jni_object(), "setPortalCooldown", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the amount of arrows in an entity's body. - pub fn arrows_in_body(&self) -> Result> { + /// Returns a set of tags for this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn scoreboard_tags( + &self, + ) -> Result, Box> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")I"; + sig += ")Ljava/util/Set;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), args); + .call_method(&self.jni_object(), "getScoreboardTags", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the amount of arrows in the entity's body. - pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { + /// Add a tag to this entity. + /// + /// Entities can have no more than 1024 tags. + pub fn add_scoreboard_tag( + &self, + tag: impl Into, + ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(count); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); args.push(val_1); - sig += ")V"; + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "setArrowsInBody", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "addScoreboardTag", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Returns the living entity's current maximum no damage ticks. - /// - /// This is the maximum duration in which the living entity will not take - /// damage. - pub fn maximum_no_damage_ticks(&self) -> Result> { - let args = Vec::new(); + /// Removes a given tag from this entity. + pub fn remove_scoreboard_tag( + &self, + tag: impl Into, + ) -> Result> { + let mut args = Vec::new(); let mut sig = String::from("("); - sig += ")I"; + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(tag.into())?, + )); + args.push(val_1); + sig += ")Z"; let res = self.jni_ref().call_method( &self.jni_object(), - "getMaximumNoDamageTicks", + "removeScoreboardTag", sig.as_str(), args, ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the living entity's current maximum no damage ticks. - pub fn set_maximum_no_damage_ticks( + /// Returns the reaction of the entity when moved by a piston. + pub fn piston_move_reaction( &self, - ticks: i32, - ) -> Result<(), Box> { - let mut args = Vec::new(); + ) -> Result, Box> { + let args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(ticks); - args.push(val_1); - sig += ")V"; + sig += ")Lorg/bukkit/block/PistonMoveReaction;"; let res = self.jni_ref().call_method( &self.jni_object(), - "setMaximumNoDamageTicks", + "getPistonMoveReaction", sig.as_str(), args, ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the living entity's last damage taken in the current no damage - /// ticks time. + /// Get the closest cardinal {@link BlockFace} direction an entity is + /// currently facing. /// - /// Only damage higher than this amount will further damage the living - /// entity. - pub fn last_damage(&self) -> Result> { + /// This will not return any non-cardinal directions such as + /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. + /// + /// {@link Hanging} entities will override this call and thus their behavior + /// may be different. + pub fn facing(&self) -> Result, Box> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")D"; + sig += ")Lorg/bukkit/block/BlockFace;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFacing", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the entity's current pose. + /// Note that the pose is only updated at the end of a tick, so may be + /// inconsistent with other methods. eg {@link Player#isSneaking()} being + /// true does not imply the current pose will be {@link Pose#SNEAKING} + pub fn pose(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/entity/Pose;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPose", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the category of spawn to which this entity belongs. + pub fn spawn_category( + &self, + ) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/entity/SpawnCategory;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), args); + .call_method(&self.jni_object(), "getSpawnCategory", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the damage dealt within the current no damage ticks time period. - pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { - let mut args = Vec::new(); + /// Checks if this entity has been spawned in a world. + /// + /// Entities not spawned in a world will not tick, be sent to players, or be + /// saved to the server files. + pub fn is_in_world(&self) -> Result> { + let args = Vec::new(); let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(damage); - args.push(val_1); - sig += ")V"; - let res = + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInWorld", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get this entity as an NBT string. + /// + /// This string should not be relied upon as a serializable value. + pub fn as_string(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/lang/String;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getAsString", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( self.jni_ref() - .call_method(&self.jni_object(), "setLastDamage", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Returns the living entity's current no damage ticks. - pub fn no_damage_ticks(&self) -> Result> { + /// Crates an {@link EntitySnapshot} representing the current state of this entity. + pub fn create_snapshot( + &self, + ) -> Result>, Box> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")I"; + sig += ")Lorg/bukkit/entity/EntitySnapshot;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getNoDamageTicks", sig.as_str(), args); + .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntitySnapshot::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the living entity's current no damage ticks. - pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// + /// Note: Players cannot be copied. + pub fn copy( + &self, + to: std::option::Option>>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(ticks); + if let Some(a) = to { + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Lorg/bukkit/entity/Entity;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Deals the given amount of damage to this entity from a specified + /// {@link DamageSource}. + pub fn damage( + &self, + amount: f64, + damage_source: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(amount); args.push(val_1); + if let Some(a) = damage_source { + sig += "Lorg/bukkit/damage/DamageSource;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setNoDamageTicks", sig.as_str(), args); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "damage", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the ticks that this entity has performed no action. + /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. + pub fn health(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is + /// dead. + pub fn set_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setHealth", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the entity's absorption amount. + pub fn absorption_amount(&self) -> Result> { + let sig = String::from("()D"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAbsorptionAmount", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Sets the entity's absorption amount. /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn no_action_ticks(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")I"; + /// Note: The amount is capped to the value of + /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on + /// that attribute is currently unspecified and subject to change. + pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(amount); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAbsorptionAmount", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the maximum health this entity has. + pub fn max_health(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getNoActionTicks", sig.as_str(), args); + .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.d()?) } - /// Set the ticks that this entity has performed no action. - /// - /// The details of what "no action ticks" entails varies from entity to entity - /// and cannot be specifically defined. Some examples include squid using this - /// value to determine when to swim, raiders for when they are to be expelled - /// from raids, or creatures (such as withers) as a requirement to be despawned. - pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { + #[deprecated] + /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. + pub fn set_max_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaxHealth", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Resets the max health to the original amount. + pub fn reset_max_health(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets a metadata value in the implementing object's metadata store. + pub fn set_metadata( + &self, + metadata_key: impl Into, + new_metadata_value: impl Into>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(ticks); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); args.push(val_1); + sig += "Lorg/bukkit/metadata/MetadataValue;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) + }); + args.push(val_2); sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setNoActionTicks", sig.as_str(), args); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setMetadata", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the player identified as the killer of the living entity. - /// - /// May be null. - pub fn killer(&self) -> Result>, Box> { - let args = Vec::new(); + /// Returns a list of previously set metadata values from the implementing + /// object's metadata store. + pub fn get_metadata( + &self, + metadata_key: impl Into, + ) -> Result>, Box> { + let mut args = Vec::new(); let mut sig = String::from("("); - sig += ")Lorg/bukkit/entity/Player;"; + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += ")Ljava/util/List;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getKiller", sig.as_str(), args); + .call_method(&self.jni_object(), "getMetadata", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::metadata::MetadataValue::from_raw( + &self.jni_ref(), + obj, + )?); } - Ok(Some(crate::entity::Player::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(new_vec) } - #[deprecated] - /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. - pub fn add_potion_effect( + /// Tests to see whether the implementing object contains the given + /// metadata value in its metadata store. + pub fn has_metadata( &self, - effect: impl Into>, - force: std::option::Option, + metadata_key: impl Into, ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/potion/PotionEffect;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(effect.into().jni_object().clone()) - }); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); args.push(val_1); - if let Some(a) = force { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasMetadata", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns whether the living entity already has an existing effect of - /// the given {@link PotionEffectType} applied to it. - pub fn has_potion_effect( + /// Removes the given metadata value from the implementing object's + /// metadata store. + pub fn remove_metadata( &self, - val_type: impl Into>, - ) -> Result> { + metadata_key: impl Into, + owning_plugin: impl Into>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/potion/PotionEffectType;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); args.push(val_1); - sig += ")Z"; + sig += "Lorg/bukkit/plugin/Plugin;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + }); + args.push(val_2); + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "hasPotionEffect", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + .call_method(&self.jni_object(), "removeMetadata", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns the active {@link PotionEffect} of the specified type. - /// - /// If the effect is not present on the entity then null will be returned. - pub fn get_potion_effect( + /// Sends this sender multiple messages + pub fn send_message( &self, - val_type: impl Into>, - ) -> Result>, Box> { + sender: impl Into>, + messages: std::option::Option>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/potion/PotionEffectType;"; + sig += "Ljava/util/UUID;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) }); args.push(val_1); - sig += ")Lorg/bukkit/potion/PotionEffect;"; + if let Some(a) = messages { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_2); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the name of this command sender + pub fn name(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/lang/String;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gets the custom name on a mob or block. If there is no name this method + /// will return null. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn custom_name(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/lang/String;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getPotionEffect", sig.as_str(), args); + .call_method(&self.jni_object(), "getCustomName", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::potion::PotionEffect::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Removes any effects present of the given {@link PotionEffectType}. - pub fn remove_potion_effect( + /// Sets a custom name on a mob or block. This name will be used in death + /// messages and can be sent to the client as a nameplate over the mob. + /// + /// Setting the name to null or an empty string will clear it. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn set_custom_name( &self, - val_type: impl Into>, + name: impl Into, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/potion/PotionEffectType;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); args.push(val_1); sig += ")V"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "removePotionEffect", - sig.as_str(), - args, - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setCustomName", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns all currently active {@link PotionEffect}s on the living - /// entity. - pub fn active_potion_effects( + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + pub fn persistent_data_container( &self, - ) -> Result>, Box> { + ) -> Result, Box> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")Ljava/util/Collection;"; + sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; let res = self.jni_ref().call_method( &self.jni_object(), - "getActivePotionEffects", + "getPersistentDataContainer", sig.as_str(), args, ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for EnderDragonPart<'mc> { + fn into(self) -> crate::entity::ComplexEntityPart<'mc> { + crate::entity::ComplexEntityPart::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EnderDragonPart into crate::entity::ComplexEntityPart") + } +} +impl<'mc> Into> for EnderDragonPart<'mc> { + fn into(self) -> crate::entity::Damageable<'mc> { + crate::entity::Damageable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EnderDragonPart into crate::entity::Damageable") + } +} +#[repr(C)] +pub struct Ambient<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Ambient<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Ambient<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Ambient from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Ambient")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Ambient object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - Ok(new_vec) } - /// Checks whether the living entity has block line of sight to another. +} + +impl<'mc> Ambient<'mc> { + /// Instructs this Mob to set the specified LivingEntity as its target. /// - /// This uses the same algorithm that hostile mobs use to find the closest - /// player. - pub fn has_line_of_sight( + /// Hostile creatures may attack their target, and friendly creatures may + /// follow their target. + pub fn set_target( &self, - other: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Entity;"; + target: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) + jni::objects::JObject::from_raw(target.into().jni_object().clone()) }); - args.push(val_1); - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasLineOfSight", sig.as_str(), args); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTarget", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the current target of this Mob + pub fn target( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTarget", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::LivingEntity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Returns if the living entity despawns when away from players or not. - /// - /// By default, animals are not removed while other mobs are. - pub fn remove_when_far_away(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; + /// Sets whether this mob is aware of its surroundings. + /// Unaware mobs will still move if pushed, attacked, etc. but will not move + /// or perform any actions on their own. Unaware mobs may also have other + /// unspecified behaviours disabled, such as drowning. + pub fn set_aware(&self, aware: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(aware.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getRemoveWhenFarAway", + "setAware", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether this mob is aware of its surroundings. + /// Unaware mobs will still move if pushed, attacked, etc. but will not move + /// or perform any actions on their own. Unaware mobs may also have other + /// unspecified behaviours disabled, such as drowning. + pub fn is_aware(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isAware", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not the living entity despawns when away from players - /// or not. - pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(remove.into()); - args.push(val_1); - sig += ")V"; + /// Get the {@link Sound} this mob makes while ambiently existing. This sound + /// may change depending on the current state of the entity, and may also + /// return null under specific conditions. This sound is not constant. + /// For instance, villagers will make different passive noises depending + /// on whether or not they are actively trading with a player, or make no + /// ambient noise while sleeping. + pub fn ambient_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAmbientSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Ambient<'mc> { + fn into(self) -> crate::entity::Mob<'mc> { + crate::entity::Mob::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Ambient into crate::entity::Mob") + } +} +#[repr(C)] +pub struct Mob<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Mob<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Mob<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Mob from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Mob")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Mob object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Mob<'mc> { + /// Instructs this Mob to set the specified LivingEntity as its target. + /// + /// Hostile creatures may attack their target, and friendly creatures may + /// follow their target. + pub fn set_target( + &self, + target: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(target.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setRemoveWhenFarAway", + "setTarget", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the inventory with the equipment worn by the living entity. - pub fn equipment( + /// Gets the current target of this Mob + pub fn target( &self, - ) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/inventory/EntityEquipment;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEquipment", sig.as_str(), args); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTarget", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::EntityEquipment::from_raw( + Ok(Some(crate::entity::LivingEntity::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets whether or not the living entity can pick up items. - pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(pickup.into()); - args.push(val_1); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setCanPickupItems", sig.as_str(), args); + /// Sets whether this mob is aware of its surroundings. + /// Unaware mobs will still move if pushed, attacked, etc. but will not move + /// or perform any actions on their own. Unaware mobs may also have other + /// unspecified behaviours disabled, such as drowning. + pub fn set_aware(&self, aware: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(aware.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAware", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the living entity can pick up items. - pub fn can_pickup_items(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; + /// Gets whether this mob is aware of its surroundings. + /// Unaware mobs will still move if pushed, attacked, etc. but will not move + /// or perform any actions on their own. Unaware mobs may also have other + /// unspecified behaviours disabled, such as drowning. + pub fn is_aware(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isAware", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the {@link Sound} this mob makes while ambiently existing. This sound + /// may change depending on the current state of the entity, and may also + /// return null under specific conditions. This sound is not constant. + /// For instance, villagers will make different passive noises depending + /// on whether or not they are actively trading with a player, or make no + /// ambient noise while sleeping. + pub fn ambient_sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getCanPickupItems", sig.as_str(), args); + .call_method(&self.jni_object(), "getAmbientSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Returns whether the entity is currently leashed. - pub fn is_leashed(&self) -> Result> { - let args = Vec::new(); + /// Gets the height of the living entity's eyes above its Location. + pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { + let mut args = Vec::new(); let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isLeashed", sig.as_str(), args); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(ignore_pose.into()); + args.push(val_1); + sig += ")D"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEyeHeight", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Gets the entity that is currently leading this entity. - pub fn leash_holder(&self) -> Result, Box> { + /// Get a Location detailing the current eye position of the living entity. + pub fn eye_location(&self) -> Result, Box> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")Lorg/bukkit/entity/Entity;"; + sig += ")Lorg/bukkit/Location;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), args); + .call_method(&self.jni_object(), "getEyeLocation", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the leash on this entity to be held by the supplied entity. + /// Gets all blocks along the living entity's line of sight. /// - /// This method has no effect on EnderDragons, Withers, Players, or Bats. - /// Non-living entities excluding leashes will not persist as leash - /// holders. - pub fn set_leash_holder( + /// This list contains all blocks from the living entity's eye position to + /// target inclusive. This method considers all blocks as 1x1x1 in size. + pub fn get_line_of_sight( &self, - holder: impl Into>, - ) -> Result> { + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Entity;"; + sig += "Ljava/util/Set;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(holder.into().jni_object().clone()) + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) }); args.push(val_1); - sig += ")Z"; + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(max_distance); + args.push(val_2); + sig += ")Ljava/util/List;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "setLeashHolder", sig.as_str(), args); + .call_method(&self.jni_object(), "getLineOfSight", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Checks to see if an entity is gliding, such as using an Elytra. - pub fn is_gliding(&self) -> Result> { - let args = Vec::new(); + /// Gets the block that the living entity has targeted. + /// + /// This method considers all blocks as 1x1x1 in size. To take exact block + /// collision shapes into account, see {@link #getTargetBlockExact(int, + /// FluidCollisionMode)}. + pub fn get_target_block( + &self, + transparent: impl Into>, + max_distance: i32, + ) -> Result, Box> { + let mut args = Vec::new(); let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGliding", sig.as_str(), args); + sig += "Ljava/util/Set;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); + args.push(val_1); + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(max_distance); + args.push(val_2); + sig += ")Lorg/bukkit/block/Block;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTargetBlock", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Makes entity start or stop gliding. This will work even if an Elytra - /// is not equipped, but will be reverted by the server immediately after - /// unless an event-cancelling mechanism is put in place. - pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { + /// Gets the last two blocks along the living entity's line of sight. + /// + /// The target block will be the last block in the list. This method + /// considers all blocks as 1x1x1 in size. + pub fn get_last_two_target_blocks( + &self, + transparent: impl Into>, + max_distance: i32, + ) -> Result>, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(gliding.into()); + sig += "Ljava/util/Set;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transparent.into().jni_object().clone()) + }); args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setGliding", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks to see if an entity is swimming. - pub fn is_swimming(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSwimming", sig.as_str(), args); + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(max_distance); + args.push(val_2); + sig += ")Ljava/util/List;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLastTwoTargetBlocks", + sig.as_str(), + args, + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Makes entity start or stop swimming. - /// This may have unexpected results if the entity is not in water. - pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { + /// Gets the block that the living entity has targeted. + /// + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn get_target_block_exact( + &self, + max_distance: i32, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(swimming.into()); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(max_distance); args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setSwimming", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks to see if an entity is currently using the Riptide enchantment. - pub fn is_riptiding(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), args); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/block/Block;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTargetBlockExact", + sig.as_str(), + args, + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::block::Block::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Returns whether this entity is slumbering. - pub fn is_sleeping(&self) -> Result> { - let args = Vec::new(); + /// Performs a ray trace that provides information on the targeted block. + /// + /// This takes the blocks' precise collision shapes into account. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn ray_trace_blocks( + &self, + max_distance: f64, + fluid_collision_mode: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSleeping", sig.as_str(), args); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(max_distance); + args.push(val_1); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/util/RayTraceResult;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::util::RayTraceResult::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets if the entity is climbing. - pub fn is_climbing(&self) -> Result> { + /// Returns the amount of air that the living entity has remaining, in + /// ticks. + pub fn remaining_air(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isClimbing", sig.as_str(), args); + sig += ")I"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRemainingAir", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets whether an entity will have AI. - /// The entity will be completely unable to move if it has no AI. - pub fn set_ai(&self, ai: bool) -> Result<(), Box> { + /// Sets the amount of air that the living entity has remaining, in ticks. + pub fn set_remaining_air(&self, ticks: i32) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(ai.into()); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); args.push(val_1); sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setAI", sig.as_str(), args); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setRemainingAir", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks whether an entity has AI. - /// The entity will be completely unable to move if it has no AI. - pub fn has_ai(&self) -> Result> { + /// Returns the maximum amount of air the living entity can have, in ticks. + pub fn maximum_air(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasAI", sig.as_str(), args); + sig += ")I"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaximumAir", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Makes this entity attack the given entity with a melee attack. - /// Attack damage is calculated by the server from the attributes and - /// equipment of this mob, and knockback is applied to {@code target} as - /// appropriate. - pub fn attack( - &self, - target: impl Into>, - ) -> Result<(), Box> { + /// Sets the maximum amount of air the living entity can have, in ticks. + pub fn set_maximum_air(&self, ticks: i32) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Entity;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) - }); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); args.push(val_1); sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "attack", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Makes this entity swing their main hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their main hand. - pub fn swing_main_hand(&self) -> Result<(), Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), args); + .call_method(&self.jni_object(), "setMaximumAir", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Makes this entity swing their off hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their off hand. - pub fn swing_off_hand(&self) -> Result<(), Box> { + /// Gets the item that the player is using (eating food, drawing back a bow, + /// blocking, etc.) + pub fn item_in_use( + &self, + ) -> Result>, Box> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")V"; + sig += ")Lorg/bukkit/inventory/ItemStack;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getItemInUse", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Makes this entity flash red as if they were damaged. - pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { - let mut args = Vec::new(); + /// Gets the number of ticks remaining for the current item's usage. + pub fn item_in_use_ticks(&self) -> Result> { + let args = Vec::new(); let mut sig = String::from("("); - sig += "F"; - let val_1 = jni::objects::JValueGen::Float(yaw); - args.push(val_1); - sig += ")V"; + sig += ")I"; let res = self.jni_ref() - .call_method(&self.jni_object(), "playHurtAnimation", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getItemInUseTicks", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Set if this entity will be subject to collisions with other entities. - /// - /// Exemptions to this rule can be managed with - /// {@link #getCollidableExemptions()} - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not working for player collisions. This - /// method should therefore only be used to set the collision status of - /// non-player entities. - /// - /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in - /// combination with a {@link Scoreboard} and a {@link Team}. - pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { + /// Sets the number of ticks that remain for the current item's usage. + /// Applies to items that take time to use, like eating food, drawing a bow, + /// or throwing a trident. + pub fn set_item_in_use_ticks(&self, ticks: i32) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(collidable.into()); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); args.push(val_1); sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "setCollidable", sig.as_str(), args); + .call_method(&self.jni_object(), "setItemInUseTicks", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if this entity is subject to collisions with other entities. - /// - /// Some entities might be exempted from the collidable rule of this entity. - /// Use {@link #getCollidableExemptions()} to get these. - /// - /// Please note that this method returns only the custom collidable state, - /// not whether the entity is non-collidable for other reasons such as being - /// dead. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not being accurate for player collisions. - /// This method should therefore only be used to check the collision status - /// of non-player entities. - /// - /// To check the collision behavior for a player, use - /// {@link Team.Option#COLLISION_RULE} in combination with a - /// {@link Scoreboard} and a {@link Team}. - pub fn is_collidable(&self) -> Result> { + /// Gets the time in ticks until the next arrow leaves the entity's body. + pub fn arrow_cooldown(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")Z"; + sig += ")I"; let res = self.jni_ref() - .call_method(&self.jni_object(), "isCollidable", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets a mutable set of UUIDs of the entities which are exempt from the - /// entity's collidable rule and which's collision with this entity will - /// behave the opposite of it. - /// - /// This set can be modified to add or remove exemptions. - /// - /// For example if collidable is true and an entity is in the exemptions set - /// then it will not collide with it. Similarly if collidable is false and an - /// entity is in this set then it will still collide with it. - /// - /// Note these exemptions are not (currently) persistent. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in those exemptions not being accurate for player - /// collisions. This method should therefore only be used to exempt - /// non-player entities. - /// - /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} - /// in combination with a {@link Scoreboard} and a {@link Team}. - pub fn collidable_exemptions( - &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/Set;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCollidableExemptions", - sig.as_str(), - args, - ); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns the value of the memory specified. - /// - /// Note that the value is null when the specific entity does not have that - /// value by default. - pub fn get_memory( - &self, - memory_key: impl Into>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/memory/MemoryKey;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")LT;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getMemory", sig.as_str(), args); + .call_method(&self.jni_object(), "getArrowCooldown", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(res.l()?)) + Ok(res.i()?) } - /// Sets the value of the memory specified. - /// - /// Note that the value will not be persisted when the specific entity does - /// not have that value by default. - pub fn set_memory( - &self, - memory_key: impl Into>, - memory_value: jni::objects::JObject<'mc>, - ) -> Result<(), Box> { + /// Sets the time in ticks until the next arrow leaves the entity's body. + pub fn set_arrow_cooldown(&self, ticks: i32) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/memory/MemoryKey;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) - }); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); args.push(val_1); - sig += "LT;"; - let val_2 = jni::objects::JValueGen::Object(memory_value); - args.push(val_2); sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setMemory", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the {@link Sound} this entity will make when damaged. - pub fn hurt_sound(&self) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + .call_method(&self.jni_object(), "setArrowCooldown", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the {@link Sound} this entity will make on death. - pub fn death_sound(&self) -> Result>, Box> { + /// Gets the amount of arrows in an entity's body. + pub fn arrows_in_body(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")Lorg/bukkit/Sound;"; + sig += ")I"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), args); + .call_method(&self.jni_object(), "getArrowsInBody", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.i()?) } - /// Get the {@link Sound} this entity will make when falling from the given - /// height (in blocks). The sound will often differ between either a small - /// or a big fall damage sound if the height exceeds 4 blocks. - pub fn get_fall_damage_sound( - &self, - fall_height: i32, - ) -> Result, Box> { + /// Set the amount of arrows in the entity's body. + pub fn set_arrows_in_body(&self, count: i32) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "I"; - let val_1 = jni::objects::JValueGen::Int(fall_height); + let val_1 = jni::objects::JValueGen::Int(count); args.push(val_1); - sig += ")Lorg/bukkit/Sound;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFallDamageSound", - sig.as_str(), - args, - ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setArrowsInBody", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the {@link Sound} this entity will make when falling from a small - /// height. - pub fn fall_damage_sound_small(&self) -> Result, Box> { + /// Returns the living entity's current maximum no damage ticks. + /// + /// This is the maximum duration in which the living entity will not take + /// damage. + pub fn maximum_no_damage_ticks(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")Lorg/bukkit/Sound;"; + sig += ")I"; let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSoundSmall", + "getMaximumNoDamageTicks", sig.as_str(), args, ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Get the {@link Sound} this entity will make when falling from a large - /// height. - pub fn fall_damage_sound_big(&self) -> Result, Box> { - let args = Vec::new(); + /// Sets the living entity's current maximum no damage ticks. + pub fn set_maximum_no_damage_ticks( + &self, + ticks: i32, + ) -> Result<(), Box> { + let mut args = Vec::new(); let mut sig = String::from("("); - sig += ")Lorg/bukkit/Sound;"; + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); + args.push(val_1); + sig += ")V"; let res = self.jni_ref().call_method( &self.jni_object(), - "getFallDamageSoundBig", + "setMaximumNoDamageTicks", sig.as_str(), args, ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the {@link Sound} this entity will make when drinking the given - /// {@link ItemStack}. - pub fn get_drinking_sound( - &self, - item_stack: impl Into>, - ) -> Result, Box> { - let mut args = Vec::new(); + /// Returns the living entity's last damage taken in the current no damage + /// ticks time. + /// + /// Only damage higher than this amount will further damage the living + /// entity. + pub fn last_damage(&self) -> Result> { + let args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Lorg/bukkit/Sound;"; + sig += ")D"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getDrinkingSound", sig.as_str(), args); + .call_method(&self.jni_object(), "getLastDamage", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.d()?) } - /// Get the {@link Sound} this entity will make when eating the given - /// {@link ItemStack}. - pub fn get_eating_sound( - &self, - item_stack: impl Into>, - ) -> Result, Box> { + /// Sets the damage dealt within the current no damage ticks time period. + pub fn set_last_damage(&self, damage: f64) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) - }); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(damage); args.push(val_1); - sig += ")Lorg/bukkit/Sound;"; + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getEatingSound", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + .call_method(&self.jni_object(), "setLastDamage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns true if this entity can breathe underwater and will not take - /// suffocation damage when its air supply reaches zero. - pub fn can_breathe_underwater(&self) -> Result> { + /// Returns the living entity's current no damage ticks. + pub fn no_damage_ticks(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")Z"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "canBreatheUnderwater", - sig.as_str(), - args, - ); + sig += ")I"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getNoDamageTicks", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - #[deprecated] - /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. - pub fn category( - &self, - ) -> Result, Box> { + /// Sets the living entity's current no damage ticks. + pub fn set_no_damage_ticks(&self, ticks: i32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setNoDamageTicks", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn no_action_ticks(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")Lorg/bukkit/entity/EntityCategory;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getCategory", sig.as_str(), args); + sig += ")I"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getNoActionTicks", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Sets whether the entity is invisible or not. - pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { + /// Set the ticks that this entity has performed no action. + /// + /// The details of what "no action ticks" entails varies from entity to entity + /// and cannot be specifically defined. Some examples include squid using this + /// value to determine when to swim, raiders for when they are to be expelled + /// from raids, or creatures (such as withers) as a requirement to be despawned. + pub fn set_no_action_ticks(&self, ticks: i32) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(invisible.into()); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(ticks); args.push(val_1); sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "setInvisible", sig.as_str(), args); + .call_method(&self.jni_object(), "setNoActionTicks", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invisible or not. - pub fn is_invisible(&self) -> Result> { + /// Gets the player identified as the killer of the living entity. + /// + /// May be null. + pub fn killer(&self) -> Result>, Box> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")Z"; + sig += ")Lorg/bukkit/entity/Player;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isInvisible", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the specified attribute instance from the object. This instance will - /// be backed directly to the object and any changes will be visible at once. - pub fn get_attribute( - &self, - attribute: impl Into>, - ) -> Result>, Box> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAttribute", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "getKiller", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::attribute::AttributeInstance::from_raw( + Ok(Some(crate::entity::Player::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Deals the given amount of damage to this entity from a specified - /// {@link DamageSource}. - pub fn damage( + #[deprecated] + /// Adds the given {@link PotionEffect} to the living entity.Only one potion effect can be present for a given {@link PotionEffectType}. + pub fn add_potion_effect( &self, - amount: f64, - damage_source: std::option::Option>>, - ) -> Result<(), Box> { + effect: impl Into>, + force: std::option::Option, + ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(amount); + sig += "Lorg/bukkit/potion/PotionEffect;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) + }); args.push(val_1); - if let Some(a) = damage_source { - sig += "Lorg/bukkit/damage/DamageSource;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); + if let Some(a) = force { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); args.push(val_2); } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "damage", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. - pub fn health(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is - /// dead. - pub fn set_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setHealth", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the entity's absorption amount. - pub fn absorption_amount(&self) -> Result> { - let sig = String::from("()D"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAbsorptionAmount", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Sets the entity's absorption amount. - /// - /// Note: The amount is capped to the value of - /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on - /// that attribute is currently unspecified and subject to change. - pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(amount); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAbsorptionAmount", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Gets the maximum health this entity has. - pub fn max_health(&self) -> Result> { - let sig = String::from("()D"); + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "addPotionEffect", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - #[deprecated] - /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. - pub fn set_max_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaxHealth", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.z()?) } - #[deprecated] - /// Resets the max health to the original amount. - pub fn reset_max_health(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Returns whether the living entity already has an existing effect of + /// the given {@link PotionEffectType} applied to it. + pub fn has_potion_effect( + &self, + val_type: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/potion/PotionEffectType;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "hasPotionEffect", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Launches a {@link Projectile} from the ProjectileSource with an - /// initial velocity. - pub fn launch_projectile( + /// Returns the active {@link PotionEffect} of the specified type. + /// + /// If the effect is not present on the entity then null will be returned. + pub fn get_potion_effect( &self, - projectile: jni::objects::JClass<'mc>, - velocity: std::option::Option>>, - ) -> Result, Box> { + val_type: impl Into>, + ) -> Result>, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/lang/Class;"; - let val_1 = jni::objects::JValueGen::Object(projectile.into()); + sig += "Lorg/bukkit/potion/PotionEffectType;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); args.push(val_1); - if let Some(a) = velocity { - sig += "Lorg/bukkit/util/Vector;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")LT;"; + sig += ")Lorg/bukkit/potion/PotionEffect;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); + .call_method(&self.jni_object(), "getPotionEffect", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Phantom<'mc> { - fn into(self) -> crate::entity::Flying<'mc> { - crate::entity::Flying::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Phantom into crate::entity::Flying") - } -} -impl<'mc> Into> for Phantom<'mc> { - fn into(self) -> crate::entity::Enemy<'mc> { - crate::entity::Enemy::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Phantom into crate::entity::Enemy") - } -} -#[repr(C)] -pub struct Drowned<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Drowned<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Drowned<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Drowned from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Drowned")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Drowned object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some(crate::potion::PotionEffect::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } -} - -impl<'mc> Drowned<'mc> { - #[deprecated] - /// Gets whether the zombie is a baby - pub fn is_baby(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isBaby", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Sets whether the zombie is a baby - pub fn set_baby( + /// Removes any effects present of the given {@link PotionEffectType}. + pub fn remove_potion_effect( &self, - flag: std::option::Option, + val_type: impl Into>, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = flag { - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_1); - } + sig += "Lorg/bukkit/potion/PotionEffectType;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + args.push(val_1); sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setBaby", sig.as_str(), args); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removePotionEffect", + sig.as_str(), + args, + ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets whether the zombie is a villager - pub fn is_villager(&self) -> Result> { - let sig = String::from("()Z"); + /// Returns all currently active {@link PotionEffect}s on the living + /// entity. + pub fn active_potion_effects( + &self, + ) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/util/Collection;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getActivePotionEffects", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Checks whether the living entity has block line of sight to another. + /// + /// This uses the same algorithm that hostile mobs use to find the closest + /// player. + pub fn has_line_of_sight( + &self, + other: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Entity;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(other.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "isVillager", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasLineOfSight", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - - pub fn set_villager(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); + /// Returns if the living entity despawns when away from players or not. + /// + /// By default, animals are not removed while other mobs are. + pub fn remove_when_far_away(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self.jni_ref().call_method( &self.jni_object(), - "setVillager", + "getRemoveWhenFarAway", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - #[deprecated] - - pub fn set_villager_profession( - &self, - profession: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Villager/Profession;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(profession.into().jni_object().clone()) - }); + /// Sets whether or not the living entity despawns when away from players + /// or not. + pub fn set_remove_when_far_away(&self, remove: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(remove.into()); + args.push(val_1); + sig += ")V"; let res = self.jni_ref().call_method( &self.jni_object(), - "setVillagerProfession", + "setRemoveWhenFarAway", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - - pub fn villager_profession( + /// Gets the inventory with the equipment worn by the living entity. + pub fn equipment( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Villager/Profession;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getVillagerProfession", - sig.as_str(), - vec![], - ); + ) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/inventory/EntityEquipment;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEquipment", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::VillagerProfession::from_raw( + Ok(Some(crate::inventory::EntityEquipment::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Get if this entity is in the process of converting to a Drowned as a - /// result of being underwater. - pub fn is_converting(&self) -> Result> { - let sig = String::from("()Z"); + /// Sets whether or not the living entity can pick up items. + pub fn set_can_pickup_items(&self, pickup: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(pickup.into()); + args.push(val_1); + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "isConverting", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "setCanPickupItems", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the living entity can pick up items. + pub fn can_pickup_items(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCanPickupItems", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the amount of ticks until this entity will be converted to a Drowned - /// as a result of being underwater. - /// When this reaches 0, the entity will be converted. - pub fn conversion_time(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getConversionTime", - sig.as_str(), - vec![], - ); + /// Returns whether the entity is currently leashed. + pub fn is_leashed(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isLeashed", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the amount of ticks until this entity will be converted to a Drowned - /// as a result of being underwater. - /// When this reaches 0, the entity will be converted. A value of less than 0 - /// will stop the current conversion process without converting the current - /// entity. - pub fn set_conversion_time(&self, time: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(time); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setConversionTime", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Gets the entity that is currently leading this entity. + pub fn leash_holder(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/entity/Entity;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLeashHolder", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets whether this zombie can break doors - pub fn can_break_doors(&self) -> Result> { - let sig = String::from("()Z"); + /// Sets the leash on this entity to be held by the supplied entity. + /// + /// This method has no effect on EnderDragons, Withers, Players, or Bats. + /// Non-living entities excluding leashes will not persist as leash + /// holders. + pub fn set_leash_holder( + &self, + holder: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Entity;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(holder.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "canBreakDoors", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "setLeashHolder", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether this zombie can break doors - /// This will be ignored if the entity is a Drowned. Will also stop the action if - /// the entity is currently breaking a door. - pub fn set_can_break_doors(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCanBreakDoors", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the age of this mob. - pub fn age(&self) -> Result> { - let sig = String::from("()I"); + /// Checks to see if an entity is gliding, such as using an Elytra. + pub fn is_gliding(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getAge", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isGliding", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the age of this mob. - pub fn set_age(&self, age: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(age); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAge", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Makes entity start or stop gliding. This will work even if an Elytra + /// is not equipped, but will be reverted by the server immediately after + /// unless an event-cancelling mechanism is put in place. + pub fn set_gliding(&self, gliding: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(gliding.into()); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setGliding", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Lock the age of the animal, setting this will prevent the animal from maturing or getting ready for mating. - pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { + /// Checks to see if an entity is swimming. + pub fn is_swimming(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSwimming", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Makes entity start or stop swimming. + /// This may have unexpected results if the entity is not in water. + pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(lock.into()); + let val_1 = jni::objects::JValueGen::Bool(swimming.into()); args.push(val_1); sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "setAgeLock", sig.as_str(), args); + .call_method(&self.jni_object(), "setSwimming", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the current agelock. - pub fn age_lock(&self) -> Result> { + /// Checks to see if an entity is currently riptiding. + pub fn is_riptiding(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), args); + .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the age of the mob to an adult - pub fn set_adult(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setAdult", sig.as_str(), vec![]); + /// Makes entity start or stop riptiding. + /// + /// Note: This does not damage attackable entities. + pub fn set_riptiding(&self, riptiding: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(riptiding.into()); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setRiptiding", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns true if the mob is an adult. - pub fn is_adult(&self) -> Result> { - let sig = String::from("()Z"); + /// Returns whether this entity is slumbering. + pub fn is_sleeping(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isAdult", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSleeping", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Return the ability to breed of the animal. - pub fn can_breed(&self) -> Result> { + /// Gets if the entity is climbing. + pub fn is_climbing(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "canBreed", sig.as_str(), args); + .call_method(&self.jni_object(), "isClimbing", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Set breedability of the animal, if the animal is a baby and set to breed it will instantly grow up. - pub fn set_breed(&self, breed: bool) -> Result<(), Box> { + /// Sets whether an entity will have AI. + /// The entity will be completely unable to move if it has no AI. + pub fn set_ai(&self, ai: bool) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(breed.into()); + let val_1 = jni::objects::JValueGen::Bool(ai.into()); args.push(val_1); sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "setBreed", sig.as_str(), args); + .call_method(&self.jni_object(), "setAI", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + /// Checks whether an entity has AI. + /// The entity will be completely unable to move if it has no AI. + pub fn has_ai(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasAI", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> Into> for Drowned<'mc> { - fn into(self) -> crate::entity::Zombie<'mc> { - crate::entity::Zombie::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Drowned into crate::entity::Zombie") + /// Makes this entity attack the given entity with a melee attack. + /// Attack damage is calculated by the server from the attributes and + /// equipment of this mob, and knockback is applied to {@code target} as + /// appropriate. + pub fn attack( + &self, + target: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Entity;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(target.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "attack", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -#[repr(C)] -pub struct DragonFireball<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for DragonFireball<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Makes this entity swing their main hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their main hand. + pub fn swing_main_hand(&self) -> Result<(), Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Makes this entity swing their off hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their off hand. + pub fn swing_off_hand(&self) -> Result<(), Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -impl<'mc> JNIInstantiatable<'mc> for DragonFireball<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate DragonFireball from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/DragonFireball")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a DragonFireball object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Makes this entity flash red as if they were damaged. + pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "F"; + let val_1 = jni::objects::JValueGen::Float(yaw); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "playHurtAnimation", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> DragonFireball<'mc> { - /// Sets the direction the fireball should be flying towards. + /// Set if this entity will be subject to collisions with other entities. /// - /// This is a convenience method, it will change the velocity direction and - /// acceleration direction, while keeping the power the same. + /// Exemptions to this rule can be managed with + /// {@link #getCollidableExemptions()} /// - /// Note: This method only uses the direction of the vector and will - /// normalize (a copy of) it. + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not working for player collisions. This + /// method should therefore only be used to set the collision status of + /// non-player entities. /// - /// Special Case: When the given direction is - /// {@link Vector#isZero() zero}, the velocity and acceleration will also be - /// set to zero without keeping the power. - pub fn set_direction( - &self, - direction: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(direction.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setDirection", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in + /// combination with a {@link Scoreboard} and a {@link Team}. + pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(collidable.into()); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setCollidable", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Retrieve the direction this fireball is heading toward. The returned vector is not normalized. - pub fn direction(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); + /// Gets if this entity is subject to collisions with other entities. + /// + /// Some entities might be exempted from the collidable rule of this entity. + /// Use {@link #getCollidableExemptions()} to get these. + /// + /// Please note that this method returns only the custom collidable state, + /// not whether the entity is non-collidable for other reasons such as being + /// dead. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not being accurate for player collisions. + /// This method should therefore only be used to check the collision status + /// of non-player entities. + /// + /// To check the collision behavior for a player, use + /// {@link Team.Option#COLLISION_RULE} in combination with a + /// {@link Scoreboard} and a {@link Team}. + pub fn is_collidable(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCollidable", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets the acceleration of the fireball. - /// The acceleration gets applied to the velocity every tick, depending on - /// the specific type of the fireball a damping / drag factor is applied so - /// that the velocity does not grow into infinity. + /// Gets a mutable set of UUIDs of the entities which are exempt from the + /// entity's collidable rule and which's collision with this entity will + /// behave the opposite of it. /// - /// Note: that the client may not respect non-default acceleration - /// power and will therefore mispredict the location of the fireball, causing - /// visual stutter. - pub fn set_acceleration( - &self, - acceleration: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(acceleration.into().jni_object().clone()) - }); + /// This set can be modified to add or remove exemptions. + /// + /// For example if collidable is true and an entity is in the exemptions set + /// then it will not collide with it. Similarly if collidable is false and an + /// entity is in this set then it will still collide with it. + /// + /// Note these exemptions are not (currently) persistent. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in those exemptions not being accurate for player + /// collisions. This method should therefore only be used to exempt + /// non-player entities. + /// + /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} + /// in combination with a {@link Scoreboard} and a {@link Team}. + pub fn collidable_exemptions( + &self, + ) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/util/Set;"; let res = self.jni_ref().call_method( &self.jni_object(), - "setAcceleration", + "getCollidableExemptions", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Retrieve the acceleration of this fireball. - pub fn acceleration(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAcceleration", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for DragonFireball<'mc> { - fn into(self) -> crate::entity::Fireball<'mc> { - crate::entity::Fireball::from_raw(&self.jni_ref(), self.1) - .expect("Error converting DragonFireball into crate::entity::Fireball") - } -} -#[repr(C)] -pub struct Ravager<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Ravager<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Ravager<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Ravager from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Ravager")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Ravager object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Ravager<'mc> { - /// Set the {@link Raid} that this raider is participating in. - pub fn set_raid( + /// Returns the value of the memory specified. + /// + /// Note that the value is null when the specific entity does not have that + /// value by default. + pub fn get_memory( &self, - raid: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Raid;)V"); + memory_key: impl Into>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/memory/MemoryKey;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(raid.into().jni_object().clone()) + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRaid", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the {@link Raid} that this raider is participating in, if any. - pub fn raid(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Raid;"); + args.push(val_1); + sig += ")LT;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getRaid", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMemory", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Raid::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(Some(res.l()?)) } - /// Get the raid wave that this raider spawned as part of. - pub fn wave(&self) -> Result> { - let sig = String::from("()I"); + /// Sets the value of the memory specified. + /// + /// Note that the value will not be persisted when the specific entity does + /// not have that value by default. + pub fn set_memory( + &self, + memory_key: impl Into>, + memory_value: jni::objects::JObject<'mc>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/memory/MemoryKey;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + }); + args.push(val_1); + sig += "LT;"; + let val_2 = jni::objects::JValueGen::Object(memory_value); + args.push(val_2); + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getWave", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the raid wave that this raider was spawned as part of. - pub fn set_wave(&self, wave: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(wave); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setWave", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "setMemory", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the block the raider is targeting to patrol. - pub fn patrol_target( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); + /// Get the {@link Sound} this entity will make when damaged. + pub fn hurt_sound(&self) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getPatrolTarget", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::block::Block::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Sets the block the raider is targeting to patrol. - pub fn set_patrol_target( - &self, - block: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/Block;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPatrolTarget", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Gets whether this entity is a patrol leader. - pub fn is_patrol_leader(&self) -> Result> { - let sig = String::from("()Z"); + /// Get the {@link Sound} this entity will make on death. + pub fn death_sound(&self) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "isPatrolLeader", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Sets whether this entity is a patrol leader. - pub fn set_patrol_leader(&self, leader: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(leader.into()); + /// Get the {@link Sound} this entity will make when falling from the given + /// height (in blocks). The sound will often differ between either a small + /// or a big fall damage sound if the height exceeds 4 blocks. + pub fn get_fall_damage_sound( + &self, + fall_height: i32, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(fall_height); + args.push(val_1); + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref().call_method( &self.jni_object(), - "setPatrolLeader", + "getFallDamageSound", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether this mob can join an active raid. - pub fn is_can_join_raid(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCanJoinRaid", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets whether this mob can join an active raid. - pub fn set_can_join_raid(&self, join: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(join.into()); + /// Get the {@link Sound} this entity will make when falling from a small + /// height. + pub fn fall_damage_sound_small(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref().call_method( &self.jni_object(), - "setCanJoinRaid", + "getFallDamageSoundSmall", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get the amount of ticks that this mob has exited the bounds of a village - /// as a raid participant. - /// - /// This value is increased only when the mob has had no action for 2,400 ticks - /// (according to {@link #getNoActionTicks()}). Once both the no action ticks have - /// reached that value and the ticks outside a raid exceeds 30, the mob will be - /// expelled from the raid. - pub fn ticks_outside_raid(&self) -> Result> { - let sig = String::from("()I"); + /// Get the {@link Sound} this entity will make when falling from a large + /// height. + pub fn fall_damage_sound_big(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref().call_method( &self.jni_object(), - "getTicksOutsideRaid", + "getFallDamageSoundBig", sig.as_str(), - vec![], + args, ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the amount of ticks that this mob has exited the bounds of a village - /// as a raid participant. - /// - /// This value is considered only when the mob has had no action for 2,400 ticks - /// (according to {@link #getNoActionTicks()}). Once both the no action ticks have - /// reached that value and the ticks outside a raid exceeds 30, the mob will be - /// expelled from the raid. - pub fn set_ticks_outside_raid(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTicksOutsideRaid", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Get the {@link Sound} this entity will make when drinking the given + /// {@link ItemStack}. + pub fn get_drinking_sound( + &self, + item_stack: impl Into>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Lorg/bukkit/Sound;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDrinkingSound", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Check whether or not this raider is celebrating a raid victory. - pub fn is_celebrating(&self) -> Result> { - let sig = String::from("()Z"); + /// Get the {@link Sound} this entity will make when eating the given + /// {@link ItemStack}. + pub fn get_eating_sound( + &self, + item_stack: impl Into>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "isCelebrating", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEatingSound", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set whether or not this mob is celebrating a raid victory. - pub fn set_celebrating(&self, celebrating: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(celebrating.into()); + /// Returns true if this entity can breathe underwater and will not take + /// suffocation damage when its air supply reaches zero. + pub fn can_breathe_underwater(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self.jni_ref().call_method( &self.jni_object(), - "setCelebrating", + "canBreatheUnderwater", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Get the {@link Sound} this entity will play when celebrating. - pub fn celebration_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCelebrationSound", - sig.as_str(), - vec![], - ); + #[deprecated] + /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. + pub fn category( + &self, + ) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/entity/EntityCategory;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCategory", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { + crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Ravager<'mc> { - fn into(self) -> crate::entity::Raider<'mc> { - crate::entity::Raider::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Ravager into crate::entity::Raider") - } -} -#[repr(C)] -pub struct Pillager<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Pillager<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Sets whether the entity is invisible or not. + pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(invisible.into()); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setInvisible", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -impl<'mc> JNIInstantiatable<'mc> for Pillager<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Pillager from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Pillager")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Pillager object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Gets whether the entity is invisible or not. + pub fn is_invisible(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isInvisible", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} - -impl<'mc> Pillager<'mc> { - /// Set the {@link Raid} that this raider is participating in. - pub fn set_raid( + /// Gets the specified attribute instance from the object. This instance will + /// be backed directly to the object and any changes will be visible at once. + pub fn get_attribute( &self, - raid: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Raid;)V"); + attribute: impl Into>, + ) -> Result>, Box> { + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", + ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(raid.into().jni_object().clone()) + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setRaid", + "getAttribute", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the {@link Raid} that this raider is participating in, if any. - pub fn raid(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Raid;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getRaid", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Raid::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(Some(crate::attribute::AttributeInstance::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Get the raid wave that this raider spawned as part of. - pub fn wave(&self) -> Result> { - let sig = String::from("()I"); + /// Deals the given amount of damage to this entity from a specified + /// {@link DamageSource}. + pub fn damage( + &self, + amount: f64, + damage_source: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(amount); + args.push(val_1); + if let Some(a) = damage_source { + sig += "Lorg/bukkit/damage/DamageSource;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getWave", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "damage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. + pub fn health(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.d()?) } - /// Set the raid wave that this raider was spawned as part of. - pub fn set_wave(&self, wave: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(wave); + /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is + /// dead. + pub fn set_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "setWave", + "setHealth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the block the raider is targeting to patrol. - pub fn patrol_target( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPatrolTarget", sig.as_str(), vec![]); + /// Gets the entity's absorption amount. + pub fn absorption_amount(&self) -> Result> { + let sig = String::from("()D"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAbsorptionAmount", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::block::Block::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.d()?) } - /// Sets the block the raider is targeting to patrol. - pub fn set_patrol_target( - &self, - block: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/Block;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) - }); + /// Sets the entity's absorption amount. + /// + /// Note: The amount is capped to the value of + /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on + /// that attribute is currently unspecified and subject to change. + pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "setPatrolTarget", + "setAbsorptionAmount", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether this entity is a patrol leader. - pub fn is_patrol_leader(&self) -> Result> { - let sig = String::from("()Z"); + #[deprecated] + /// Gets the maximum health this entity has. + pub fn max_health(&self) -> Result> { + let sig = String::from("()D"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isPatrolLeader", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } - /// Sets whether this entity is a patrol leader. - pub fn set_patrol_leader(&self, leader: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(leader.into()); + #[deprecated] + /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. + pub fn set_max_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); let res = self.jni_ref().call_method( &self.jni_object(), - "setPatrolLeader", + "setMaxHealth", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether this mob can join an active raid. - pub fn is_can_join_raid(&self) -> Result> { - let sig = String::from("()Z"); + #[deprecated] + /// Resets the max health to the original amount. + pub fn reset_max_health(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCanJoinRaid", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether this mob can join an active raid. - pub fn set_can_join_raid(&self, join: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(join.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCanJoinRaid", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the amount of ticks that this mob has exited the bounds of a village - /// as a raid participant. - /// - /// This value is increased only when the mob has had no action for 2,400 ticks - /// (according to {@link #getNoActionTicks()}). Once both the no action ticks have - /// reached that value and the ticks outside a raid exceeds 30, the mob will be - /// expelled from the raid. - pub fn ticks_outside_raid(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTicksOutsideRaid", - sig.as_str(), - vec![], - ); + /// Launches a {@link Projectile} from the ProjectileSource with an + /// initial velocity. + pub fn launch_projectile( + &self, + projectile: jni::objects::JClass<'mc>, + velocity: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(projectile.into()); + args.push(val_1); + if let Some(a) = velocity { + sig += "Lorg/bukkit/util/Vector;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")LT;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.l()?) } - /// Set the amount of ticks that this mob has exited the bounds of a village - /// as a raid participant. + /// Set the loot table for a container or entity. /// - /// This value is considered only when the mob has had no action for 2,400 ticks - /// (according to {@link #getNoActionTicks()}). Once both the no action ticks have - /// reached that value and the ticks outside a raid exceeds 30, the mob will be - /// expelled from the raid. - pub fn set_ticks_outside_raid(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// To remove a loot table use null. Do not use {@link LootTables#EMPTY} to + /// clear a LootTable. + pub fn set_loot_table( + &self, + table: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/loot/LootTable;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(table.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setTicksOutsideRaid", + "setLootTable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check whether or not this raider is celebrating a raid victory. - pub fn is_celebrating(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the Loot Table attached to this block or entity. + /// + /// If an block/entity does not have a loot table, this will return null, NOT + /// an empty loot table. + pub fn loot_table( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/loot/LootTable;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCelebrating", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLootTable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::loot::LootTable::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Set whether or not this mob is celebrating a raid victory. - pub fn set_celebrating(&self, celebrating: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(celebrating.into()); + /// Set the seed used when this Loot Table generates loot. + pub fn set_seed(&self, seed: i64) -> Result<(), Box> { + let sig = String::from("(J)V"); + let val_1 = jni::objects::JValueGen::Long(seed); let res = self.jni_ref().call_method( &self.jni_object(), - "setCelebrating", + "setSeed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the {@link Sound} this entity will play when celebrating. - pub fn celebration_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCelebrationSound", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the object's inventory. - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + /// Get the Loot Table's seed. + /// + /// The seed is used when generating loot. + pub fn seed(&self) -> Result> { + let sig = String::from("()J"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSeed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.j()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -89294,25 +99467,25 @@ impl<'mc> Pillager<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Pillager<'mc> { - fn into(self) -> crate::entity::Illager<'mc> { - crate::entity::Illager::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Pillager into crate::entity::Illager") +impl<'mc> Into> for Mob<'mc> { + fn into(self) -> crate::entity::LivingEntity<'mc> { + crate::entity::LivingEntity::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Mob into crate::entity::LivingEntity") } } -impl<'mc> Into> for Pillager<'mc> { - fn into(self) -> crate::inventory::InventoryHolder<'mc> { - crate::inventory::InventoryHolder::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Pillager into crate::inventory::InventoryHolder") +impl<'mc> Into> for Mob<'mc> { + fn into(self) -> crate::loot::Lootable<'mc> { + crate::loot::Lootable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Mob into crate::loot::Lootable") } } #[repr(C)] -pub struct Cow<'mc>( +pub struct Axolotl<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Cow<'mc> { +impl<'mc> JNIRaw<'mc> for Axolotl<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -89320,18 +99493,18 @@ impl<'mc> JNIRaw<'mc> for Cow<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Cow<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Axolotl<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Cow from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Axolotl from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Cow")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Axolotl")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Cow object, got {}", + "Invalid argument passed. Expected a Axolotl object, got {}", name ) .into()) @@ -89341,7 +99514,62 @@ impl<'mc> JNIInstantiatable<'mc> for Cow<'mc> { } } -impl<'mc> Cow<'mc> { +impl<'mc> Axolotl<'mc> { + /// Gets if this axolotl is playing dead. + /// An axolotl may play dead when it is damaged underwater. + pub fn is_playing_dead(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isPlayingDead", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets if this axolotl is playing dead. + /// An axolotl may play dead when it is damaged underwater. + pub fn set_playing_dead(&self, playing_dead: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(playing_dead.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPlayingDead", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the variant of this axolotl. + pub fn variant( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Axolotl/Variant;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::AxolotlVariant::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Set the variant of this axolotl. + pub fn set_variant( + &self, + variant: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Axolotl/Variant;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(variant.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVariant", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } /// Get the UUID of the entity that caused this entity to enter the /// {@link #canBreed()} state. pub fn breed_cause( @@ -89496,238 +99724,244 @@ impl<'mc> Cow<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Cow<'mc> { +impl<'mc> Into> for Axolotl<'mc> { fn into(self) -> crate::entity::Animals<'mc> { crate::entity::Animals::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Cow into crate::entity::Animals") + .expect("Error converting Axolotl into crate::entity::Animals") + } +} +pub enum AxolotlVariant<'mc> { + Lucy { inner: AxolotlVariantStruct<'mc> }, + Wild { inner: AxolotlVariantStruct<'mc> }, + Gold { inner: AxolotlVariantStruct<'mc> }, + Cyan { inner: AxolotlVariantStruct<'mc> }, + Blue { inner: AxolotlVariantStruct<'mc> }, +} +impl<'mc> std::fmt::Display for AxolotlVariant<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + AxolotlVariant::Lucy { .. } => f.write_str("LUCY"), + AxolotlVariant::Wild { .. } => f.write_str("WILD"), + AxolotlVariant::Gold { .. } => f.write_str("GOLD"), + AxolotlVariant::Cyan { .. } => f.write_str("CYAN"), + AxolotlVariant::Blue { .. } => f.write_str("BLUE"), + } + } +} +impl<'mc> std::ops::Deref for AxolotlVariant<'mc> { + type Target = AxolotlVariantStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + AxolotlVariant::Lucy { inner } => inner, + AxolotlVariant::Wild { inner } => inner, + AxolotlVariant::Gold { inner } => inner, + AxolotlVariant::Cyan { inner } => inner, + AxolotlVariant::Blue { inner } => inner, + } + } +} + +impl<'mc> AxolotlVariant<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/entity/Axolotl/Variant"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/entity/Axolotl/Variant;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "LUCY" => Ok(AxolotlVariant::Lucy { + inner: AxolotlVariantStruct::from_raw(env, obj)?, + }), + "WILD" => Ok(AxolotlVariant::Wild { + inner: AxolotlVariantStruct::from_raw(env, obj)?, + }), + "GOLD" => Ok(AxolotlVariant::Gold { + inner: AxolotlVariantStruct::from_raw(env, obj)?, + }), + "CYAN" => Ok(AxolotlVariant::Cyan { + inner: AxolotlVariantStruct::from_raw(env, obj)?, + }), + "BLUE" => Ok(AxolotlVariant::Blue { + inner: AxolotlVariantStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } + #[repr(C)] -pub struct Wolf<'mc>( +pub struct AxolotlVariantStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Wolf<'mc> { +impl<'mc> JNIRaw<'mc> for AxolotlVariant<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + match self { + Self::Lucy { inner } => inner.0.clone(), + Self::Wild { inner } => inner.0.clone(), + Self::Gold { inner } => inner.0.clone(), + Self::Cyan { inner } => inner.0.clone(), + Self::Blue { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + match self { + Self::Lucy { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Wild { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Gold { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Cyan { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Blue { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for Wolf<'mc> { +impl<'mc> JNIInstantiatable<'mc> for AxolotlVariant<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Wolf from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate AxolotlVariant from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Wolf")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Axolotl/Variant")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Wolf object, got {}", + "Invalid argument passed. Expected a AxolotlVariant object, got {}", name ) .into()) } else { - Ok(Self(env.clone(), obj)) + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "LUCY" => Ok(AxolotlVariant::Lucy { + inner: AxolotlVariantStruct::from_raw(env, obj)?, + }), + "WILD" => Ok(AxolotlVariant::Wild { + inner: AxolotlVariantStruct::from_raw(env, obj)?, + }), + "GOLD" => Ok(AxolotlVariant::Gold { + inner: AxolotlVariantStruct::from_raw(env, obj)?, + }), + "CYAN" => Ok(AxolotlVariant::Cyan { + inner: AxolotlVariantStruct::from_raw(env, obj)?, + }), + "BLUE" => Ok(AxolotlVariant::Blue { + inner: AxolotlVariantStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } } -impl<'mc> Wolf<'mc> { - /// Checks if this wolf is angry - pub fn is_angry(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isAngry", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets the anger of this wolf. - /// - /// An angry wolf can not be fed or tamed. - pub fn set_angry(&self, angry: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(angry.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAngry", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the collar color of this wolf - pub fn collar_color(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/DyeColor;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCollarColor", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::DyeColor::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Set the collar color of this wolf - pub fn set_collar_color( - &self, - color: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/DyeColor;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCollarColor", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether the wolf is wet - pub fn is_wet(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isWet", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the wolf's tail angle in radians - pub fn tail_angle(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTailAngle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) +impl<'mc> JNIRaw<'mc> for AxolotlVariantStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Gets if the wolf is interested - pub fn is_interested(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInterested", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Set wolf to be interested - pub fn set_interested(&self, interested: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(interested.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setInterested", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +} +impl<'mc> JNIInstantiatable<'mc> for AxolotlVariantStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate AxolotlVariantStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Axolotl/Variant")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a AxolotlVariantStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } - /// Get the variant of this wolf. - pub fn variant(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Wolf/Variant;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::WolfVariant::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} + +impl<'mc> AxolotlVariantStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Axolotl/Variant;"); + let cls = jni.find_class("org/bukkit/entity/Axolotl/Variant"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::AxolotlVariant::from_raw(&jni, obj) } - /// Set the variant of this wolf. - pub fn set_variant( - &self, - variant: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Wolf/Variant;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(variant.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setVariant", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Check if this is tamed - /// - /// If something is tamed then a player can not tame it through normal - /// methods, even if it does not belong to anyone in particular. - pub fn is_tamed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isTamed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} +#[repr(C)] +pub struct PolarBear<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PolarBear<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Sets if this has been tamed. Not necessary if the method setOwner has - /// been used, as it tames automatically. - /// - /// If something is tamed then a player can not tame it through normal - /// methods, even if it does not belong to anyone in particular. - pub fn set_tamed(&self, tame: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(tame.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTamed", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Gets the current owning AnimalTamer - pub fn owner( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/AnimalTamer;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); +} +impl<'mc> JNIInstantiatable<'mc> for PolarBear<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate PolarBear from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/PolarBear")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PolarBear object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - Ok(Some(crate::entity::AnimalTamer::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Set this to be owned by given AnimalTamer. - /// - /// If the owner is not null, this will be tamed and will have any current - /// path it is following removed. If the owner is set to null, this will be - /// untamed, and the current owner removed. - pub fn set_owner( - &self, - tamer: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/AnimalTamer;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tamer.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setOwner", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) } +} + +impl<'mc> PolarBear<'mc> { /// Get the UUID of the entity that caused this entity to enter the /// {@link #canBreed()} state. pub fn breed_cause( @@ -89876,54 +100110,25 @@ impl<'mc> Wolf<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if this animal is sitting - pub fn is_sitting(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSitting", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets if this animal is sitting. Will remove any path that the animal - /// was following beforehand. - pub fn set_sitting(&self, sitting: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(sitting.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSitting", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Wolf<'mc> { - fn into(self) -> crate::entity::Tameable<'mc> { - crate::entity::Tameable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Wolf into crate::entity::Tameable") - } -} -impl<'mc> Into> for Wolf<'mc> { - fn into(self) -> crate::entity::Sittable<'mc> { - crate::entity::Sittable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Wolf into crate::entity::Sittable") +impl<'mc> Into> for PolarBear<'mc> { + fn into(self) -> crate::entity::Animals<'mc> { + crate::entity::Animals::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PolarBear into crate::entity::Animals") } } #[repr(C)] -pub struct WolfVariant<'mc>( +pub struct Player<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for WolfVariant<'mc> { +impl<'mc> JNIRaw<'mc> for Player<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -89931,18 +100136,18 @@ impl<'mc> JNIRaw<'mc> for WolfVariant<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for WolfVariant<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Player<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate WolfVariant from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Player from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Wolf/Variant")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Player")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a WolfVariant object, got {}", + "Invalid argument passed. Expected a Player object, got {}", name ) .into()) @@ -89952,3856 +100157,3277 @@ impl<'mc> JNIInstantiatable<'mc> for WolfVariant<'mc> { } } -impl<'mc> WolfVariant<'mc> { - /// Return the namespaced identifier for this object. - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); +impl<'mc> Player<'mc> { + /// Gets the "friendly" name to display of this player. This may include + /// color. + /// + /// Note that this name will not be displayed in game, only in chat and + /// places defined by plugins. + pub fn display_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDisplayName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } -} -impl<'mc> Into> for WolfVariant<'mc> { - fn into(self) -> crate::Keyed<'mc> { - crate::Keyed::from_raw(&self.jni_ref(), self.1) - .expect("Error converting WolfVariant into crate::Keyed") + /// Sets the "friendly" name to display of this player. This may include + /// color. + /// + /// Note that this name will not be displayed in game, only in chat and + /// places defined by plugins. + pub fn set_display_name( + &self, + name: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDisplayName", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -#[repr(C)] -pub struct Fireball<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Fireball<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Gets the name that is shown on the player list. + pub fn player_list_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPlayerListName", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Sets the name that is shown on the in-game player list. + /// + /// If the value is null, the name will be identical to {@link #getName()}. + pub fn set_player_list_name( + &self, + name: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPlayerListName", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -impl<'mc> JNIInstantiatable<'mc> for Fireball<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Fireball from null object.").into()); + /// Gets the currently displayed player list header for this player. + pub fn player_list_header(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPlayerListHeader", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Fireball")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Fireball object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Gets the currently displayed player list footer for this player. + pub fn player_list_footer(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPlayerListFooter", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } -} - -impl<'mc> Fireball<'mc> { - /// Sets the direction the fireball should be flying towards. - /// - /// This is a convenience method, it will change the velocity direction and - /// acceleration direction, while keeping the power the same. - /// - /// Note: This method only uses the direction of the vector and will - /// normalize (a copy of) it. - /// - /// Special Case: When the given direction is - /// {@link Vector#isZero() zero}, the velocity and acceleration will also be - /// set to zero without keeping the power. - pub fn set_direction( + /// Sets the currently displayed player list header for this player. + pub fn set_player_list_header( &self, - direction: impl Into>, + header: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(header.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPlayerListHeader", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets the currently displayed player list footer for this player. + pub fn set_player_list_footer( + &self, + footer: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(footer.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPlayerListFooter", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets the currently displayed player list header and footer for this + /// player. + pub fn set_player_list_header_footer( + &self, + header: impl Into, + footer: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(header.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(footer.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPlayerListHeaderFooter", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Set the target of the player's compass. + pub fn set_compass_target( + &self, + loc: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Location;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(direction.into().jni_object().clone()) + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setDirection", + "setCompassTarget", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Retrieve the direction this fireball is heading toward. The returned vector is not normalized. - pub fn direction(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); + /// Get the previously set compass target. + pub fn compass_target(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCompassTarget", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the acceleration of the fireball. - /// The acceleration gets applied to the velocity every tick, depending on - /// the specific type of the fireball a damping / drag factor is applied so - /// that the velocity does not grow into infinity. - /// - /// Note: that the client may not respect non-default acceleration - /// power and will therefore mispredict the location of the fireball, causing - /// visual stutter. - pub fn set_acceleration( + /// Gets the socket address of this player + pub fn address( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/net/InetSocketAddress;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAddress", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) + } + /// Gets if this connection has been transferred from another server. + pub fn is_transferred(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isTransferred", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Stores a cookie in this player's client. + pub fn store_cookie( + &self, + key: impl Into>, + value: i8, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;B)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(key.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Byte(value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "storeCookie", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Requests this player to connect to a different server specified by host + /// and port. + pub fn transfer( + &self, + host: impl Into, + port: i32, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;I)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(host.into())?, + )); + let val_2 = jni::objects::JValueGen::Int(port); + let res = self.jni_ref().call_method( + &self.jni_object(), + "transfer", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sends this sender a message raw + pub fn send_raw_message( &self, - acceleration: impl Into>, + message: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(acceleration.into().jni_object().clone()) - }); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(message.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setAcceleration", + "sendRawMessage", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the acceleration of this fireball. - pub fn acceleration(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAcceleration", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Retrieve the shooter of this projectile. - pub fn shooter( - &self, - ) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/projectiles/ProjectileSource;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getShooter", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::projectiles::ProjectileSource::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Set the shooter of this projectile. - pub fn set_shooter( + /// Kicks player with custom kick message. + pub fn kick_player( &self, - source: impl Into>, + message: impl Into, ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/projectiles/ProjectileSource;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(source.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setShooter", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Determine if this projectile should bounce or not when it hits. - pub fn does_bounce(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "doesBounce", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Set whether or not this projectile should bounce or not when it hits something. - pub fn set_bounce(&self, does_bounce: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(does_bounce.into()); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setBounce", sig.as_str(), args); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(message.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "kickPlayer", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Stores the entity's current position in the provided Location object. - /// - /// If the provided Location is null this method does nothing and returns - /// null. - pub fn get_location( + /// Adds this user to the {@link ProfileBanList}. If a previous ban exists, this will + /// update the entry. + pub fn ban( &self, - loc: impl Into>, - ) -> Result>, Box> { + reason: impl Into, + duration: jni::objects::JObject<'mc>, + source: impl Into, + kick_player: std::option::Option, + ) -> Result>, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) - }); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(reason.into())?, + )); args.push(val_1); - sig += ")Lorg/bukkit/Location;"; + sig += "Ljava/time/Duration;"; + let val_2 = jni::objects::JValueGen::Object(duration); + args.push(val_2); + sig += "Ljava/lang/String;"; + let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(source.into())?, + )); + args.push(val_3); + if let Some(a) = kick_player { + sig += "Z"; + let val_4 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_4); + } + sig += ")Lorg/bukkit/BanEntry;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getLocation", sig.as_str(), args); + .call_method(&self.jni_object(), "ban", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + Ok(Some(crate::BanEntry::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) })?)) } - /// Sets this entity's velocity in meters per tick - pub fn set_velocity( + /// Adds this user's current IP address to the {@link IpBanList}. If a previous ban exists, this will + /// update the entry. If {@link #getAddress()} is null this method will throw an exception. + pub fn ban_ip( &self, - velocity: impl Into>, - ) -> Result<(), Box> { + reason: impl Into, + duration: jni::objects::JObject<'mc>, + source: impl Into, + kick_player: bool, + ) -> Result>, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/util/Vector;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) - }); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(reason.into())?, + )); args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setVelocity", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets this entity's current velocity - pub fn velocity(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/util/Vector;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the entity's height - pub fn height(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")D"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHeight", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the entity's width - pub fn width(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")D"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWidth", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the entity's current bounding box. - /// - /// The returned bounding box reflects the entity's current location and - /// size. - pub fn bounding_box( - &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/util/BoundingBox;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns true if the entity is supported by a block. This value is a - /// state updated by the server and is not recalculated unless the entity - /// moves. - pub fn is_on_ground(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isOnGround", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns true if the entity is in water. - pub fn is_in_water(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWater", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the current world this entity resides in - pub fn world(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/World;"; + sig += "Ljava/time/Duration;"; + let val_2 = jni::objects::JValueGen::Object(duration); + args.push(val_2); + sig += "Ljava/lang/String;"; + let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(source.into())?, + )); + args.push(val_3); + sig += "Z"; + let val_4 = jni::objects::JValueGen::Bool(kick_player.into()); + args.push(val_4); + sig += ")Lorg/bukkit/BanEntry;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), args); + .call_method(&self.jni_object(), "banIp", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::BanEntry::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) + })?)) } - /// Sets the entity's rotation. - /// - /// Note that if the entity is affected by AI, it may override this rotation. - pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "F"; - let val_1 = jni::objects::JValueGen::Float(yaw); - args.push(val_1); - sig += "F"; - let val_2 = jni::objects::JValueGen::Float(pitch); - args.push(val_2); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setRotation", sig.as_str(), args); + /// Says a message (or runs a command). + pub fn chat(&self, msg: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(msg.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "chat", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Teleports this entity to the given location. If this entity is riding a - /// vehicle, it will be dismounted prior to teleportation. - pub fn teleport( + /// Makes the player perform the given command + pub fn perform_command( &self, - location: impl Into>, - cause: std::option::Option< - impl Into>, - >, + command: impl Into, ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = cause { - sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "teleport", sig.as_str(), args); + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(command.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "performCommand", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns a list of entities within a bounding box centered around this - /// entity - pub fn get_nearby_entities( - &self, - x: f64, - y: f64, - z: f64, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(x); - args.push(val_1); - sig += "D"; - let val_2 = jni::objects::JValueGen::Double(y); - args.push(val_2); - sig += "D"; - let val_3 = jni::objects::JValueGen::Double(z); - args.push(val_3); - sig += ")Ljava/util/List;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getNearbyEntities", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Returns a unique id for this entity - pub fn entity_id(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")I"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getEntityId", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn fire_ticks(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")I"; + #[deprecated] + /// Returns true if the entity is supported by a block. This value is a state updated by the client after each movement. + pub fn is_on_ground(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), args); + .call_method(&self.jni_object(), "isOnGround", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Returns the entity's maximum fire ticks. - pub fn max_fire_ticks(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")I"; + /// Returns if the player is in sneak mode + pub fn is_sneaking(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), args); + .call_method(&self.jni_object(), "isSneaking", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(ticks); - args.push(val_1); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setFireTicks", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.z()?) } - /// Sets if the entity has visual fire (it will always appear to be on fire). - pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(fire.into()); - args.push(val_1); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setVisualFire", sig.as_str(), args); + /// Sets the sneak mode the player + pub fn set_sneaking(&self, sneak: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(sneak.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSneaking", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity has visual fire (it will always appear to be on fire). - pub fn is_visual_fire(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; + /// Gets whether the player is sprinting or not. + pub fn is_sprinting(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), args); + .call_method(&self.jni_object(), "isSprinting", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn freeze_ticks(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")I"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the entity's maximum freeze ticks (amount of ticks before it will - /// be fully frozen) - pub fn max_freeze_ticks(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")I"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaxFreezeTicks", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(ticks); - args.push(val_1); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setFreezeTicks", sig.as_str(), args); + /// Sets whether the player is sprinting or not. + pub fn set_sprinting(&self, sprinting: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(sprinting.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSprinting", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity is fully frozen (it has been in powdered snow for max - /// freeze ticks). - pub fn is_frozen(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; + /// Saves the players current location, health, inventory, motion, and + /// other information into the username.dat file, in the world/player + /// folder + pub fn save_data(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isFrozen", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + .call_method(&self.jni_object(), "saveData", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Mark the entity's removal. - pub fn remove(&self) -> Result<(), Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")V"; + /// Loads the players current location, health, inventory, motion, and + /// other information from the username.dat file, in the world/player + /// folder. + /// + /// Note: This will overwrite the players current inventory, health, + /// motion, etc, with the state from the saved dat file. + pub fn load_data(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), args); + .call_method(&self.jni_object(), "loadData", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns true if this entity has been marked for removal. - pub fn is_dead(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isDead", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Sets whether the player is ignored as not sleeping. If everyone is + /// either sleeping or has this flag set, then time will advance to the + /// next day. If everyone has this flag set but no one is actually in bed, + /// then nothing will happen. + pub fn set_sleeping_ignored( + &self, + is_sleeping: bool, + ) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(is_sleeping.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSleepingIgnored", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns false if the entity has died, been despawned for some other - /// reason, or has not been added to the world. - pub fn is_valid(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isValid", sig.as_str(), args); + /// Returns whether the player is sleeping ignored. + pub fn is_sleeping_ignored(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isSleepingIgnored", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the {@link Server} that contains this Entity - pub fn server(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/Server;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getServer", sig.as_str(), args); + #[deprecated] + /// Gets the Location where the player will spawn at their bed, null if they have not slept in one or their current bed spawn is invalid. + pub fn bed_spawn_location( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBedSpawnLocation", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::Server::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns true if the entity gets persisted. - /// - /// By default all entities are persistent. An entity will also not get - /// persisted, if it is riding an entity that is not persistent. - /// - /// The persistent flag on players controls whether or not to save their - /// playerdata file when they quit. If a player is directly or indirectly - /// riding a non-persistent entity, the vehicle at the root and all its - /// passengers won't get persisted. - /// - /// This should not be confused with - /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls - /// despawning of living entities. - pub fn is_persistent(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isPersistent", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether or not the entity gets persisted. - pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(persistent.into()); - args.push(val_1); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setPersistent", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + })?)) } - #[deprecated] - /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. - pub fn passenger( + /// Gets the Location where the player will spawn at, null if they + /// don't have a valid respawn point. + pub fn respawn_location( &self, - ) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/entity/Entity;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPassenger", sig.as_str(), args); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getRespawnLocation", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } #[deprecated] - /// Set the passenger of a vehicle. - pub fn set_passenger( + /// Sets the Location where the player will spawn at their bed. + pub fn set_bed_spawn_location( &self, - passenger: impl Into>, - ) -> Result> { + location: impl Into>, + force: std::option::Option, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Entity;"; + sig += "Lorg/bukkit/Location;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(location.into().jni_object().clone()) }); args.push(val_1); - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setPassenger", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets a list of passengers of this vehicle. - /// - /// The returned list will not be directly linked to the entity's current - /// passengers, and no guarantees are made as to its mutability. - pub fn passengers( - &self, - ) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/List;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPassengers", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + if let Some(a) = force { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); } - Ok(new_vec) + sig += ")V"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBedSpawnLocation", + sig.as_str(), + args, + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Add a passenger to the vehicle. - pub fn add_passenger( + /// Sets the Location where the player will respawn. + pub fn set_respawn_location( &self, - passenger: impl Into>, - ) -> Result> { + location: impl Into>, + force: std::option::Option, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Entity;"; + sig += "Lorg/bukkit/Location;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(location.into().jni_object().clone()) }); args.push(val_1); - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "addPassenger", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if let Some(a) = force { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")V"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRespawnLocation", + sig.as_str(), + args, + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Remove a passenger from the vehicle. - pub fn remove_passenger( + /// Play a note for the player at a location. + /// + /// This will work with cake. + /// + /// This method will fail silently when called with {@link Instrument#CUSTOM_HEAD}. + pub fn play_note( &self, - passenger: impl Into>, - ) -> Result> { + loc: impl Into>, + instrument: impl Into>, + note: impl Into>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Entity;"; + sig += "Lorg/bukkit/Location;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) }); args.push(val_1); - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "removePassenger", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Check if a vehicle has passengers. - pub fn is_empty(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; + sig += "Lorg/bukkit/Instrument;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(instrument.into().jni_object().clone()) + }); + args.push(val_2); + sig += "Lorg/bukkit/Note;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(note.into().jni_object().clone()) + }); + args.push(val_3); + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + .call_method(&self.jni_object(), "playNote", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Eject any passenger. - pub fn eject(&self) -> Result> { - let args = Vec::new(); + /// Play a sound for a player at the location. For sounds with multiple + /// variations passing the same seed will always play the same variation. + /// + /// This function will fail silently if Location or Sound are null. No sound + /// will be heard by the player if their client does not have the respective + /// sound for the value passed. + pub fn play_sound( + &self, + location: impl Into>, + sound: impl Into, + category: impl Into>, + volume: f32, + pitch: std::option::Option, + seed: std::option::Option, + ) -> Result<(), Box> { + let mut args = Vec::new(); let mut sig = String::from("("); - sig += ")Z"; + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(sound.into())?, + )); + args.push(val_2); + sig += "Lorg/bukkit/SoundCategory;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(category.into().jni_object().clone()) + }); + args.push(val_3); + sig += "F"; + let val_4 = jni::objects::JValueGen::Float(volume); + args.push(val_4); + if let Some(a) = pitch { + sig += "F"; + let val_5 = jni::objects::JValueGen::Float(a); + args.push(val_5); + } + if let Some(a) = seed { + sig += "J"; + let val_6 = jni::objects::JValueGen::Long(a); + args.push(val_6); + } + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "eject", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the distance this entity has fallen - pub fn fall_distance(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")F"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + .call_method(&self.jni_object(), "playSound", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the fall distance for this entity - pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { + /// Stop the specified sound from playing. + pub fn stop_sound( + &self, + sound: impl Into, + category: std::option::Option>>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "F"; - let val_1 = jni::objects::JValueGen::Float(distance); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(sound.into())?, + )); args.push(val_1); + if let Some(a) = category { + sig += "Lorg/bukkit/SoundCategory;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "stopSound", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Stop all sounds from playing. + pub fn stop_all_sounds(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref() - .call_method(&self.jni_object(), "setFallDistance", sig.as_str(), args); + .call_method(&self.jni_object(), "stopAllSounds", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Record the last {@link EntityDamageEvent} inflicted on this entity - pub fn set_last_damage_cause( + /// Plays an effect to just this player. + pub fn play_effect( &self, - event: impl Into>, + loc: impl Into>, + effect: impl Into>, + data: jni::objects::JObject<'mc>, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/event/entity/EntityDamageEvent;"; + sig += "Lorg/bukkit/Location;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(event.into().jni_object().clone()) + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) }); args.push(val_1); + sig += "Lorg/bukkit/Effect;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) + }); + args.push(val_2); + sig += "LT;"; + let val_3 = jni::objects::JValueGen::Object(data); + args.push(val_3); sig += ")V"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLastDamageCause", - sig.as_str(), - args, - ); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "playEffect", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. - /// This event may have been cancelled. - pub fn last_damage_cause( + /// Force this player to break a Block using the item in their main hand. + /// This method will respect enchantments, handle item durability (if + /// applicable) and drop experience and the correct items according to the + /// tool/item in the player's hand. + /// + /// Note that this method will call a {@link BlockBreakEvent}, meaning that + /// this method may not be successful in breaking the block if the event was + /// cancelled by a third party plugin. Care should be taken if running this + /// method in a BlockBreakEvent listener as recursion may be possible if it + /// is invoked on the same {@link Block} being broken in the event. + /// + /// Additionally, a {@link BlockDropItemEvent} is called for the items + /// dropped by this method (if successful). + /// + /// The block must be in the same world as the player. + pub fn break_block( &self, - ) -> Result>, Box> - { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/event/entity/EntityDamageEvent;"; + block: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/block/Block;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(block.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getLastDamageCause", + "breakBlock", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Returns a unique and persistent id for this entity - pub fn unique_id( + #[deprecated] + /// Send a block change. This fakes a block change packet for a user at a certain location. This will not actually change the world in any way. + pub fn send_block_change( &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/UUID;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the amount of ticks this entity has lived for. - /// - /// This is the equivalent to "age" in entities. - pub fn ticks_lived(&self) -> Result> { - let args = Vec::new(); + loc: impl Into>, + material: impl Into>, + data: std::option::Option, + ) -> Result<(), Box> { + let mut args = Vec::new(); let mut sig = String::from("("); - sig += ")I"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Lorg/bukkit/Material;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + args.push(val_2); + if let Some(a) = data { + sig += "B"; + let val_3 = jni::objects::JValueGen::Byte(a); + args.push(val_3); + } + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "sendBlockChange", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the amount of ticks this entity has lived for. + /// Send block damage. This fakes block break progress at a certain location + /// sourced by the provided entity id. This will not actually change the block's + /// break progress in any way. /// - /// This is the equivalent to "age" in entities. May not be less than one - /// tick. - pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { + /// At the same location for each unique damage source sent to the player, a + /// separate damage overlay will be displayed with the given progress. This allows + /// for block damage at different progress from multiple entities at once. + pub fn send_block_damage( + &self, + loc: impl Into>, + progress: f32, + source_id: std::option::Option, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(value); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); args.push(val_1); + sig += "F"; + let val_2 = jni::objects::JValueGen::Float(progress); + args.push(val_2); + if let Some(a) = source_id { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "setTicksLived", sig.as_str(), args); + .call_method(&self.jni_object(), "sendBlockDamage", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Performs the specified {@link EntityEffect} for this entity. - /// - /// This will be viewable to all players near the entity. - /// - /// If the effect is not applicable to this class of entity, it will not play. - pub fn play_effect( + /// Send an equipment change for the target entity. This will not + /// actually change the entity's equipment in any way. + pub fn send_equipment_change( &self, - val_type: impl Into>, + entity: impl Into>, + slot: impl Into>, + item: std::option::Option>>, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/EntityEffect;"; + sig += "Lorg/bukkit/entity/LivingEntity;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) }); args.push(val_1); + sig += "Lorg/bukkit/inventory/EquipmentSlot;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(slot.into().jni_object().clone()) + }); + args.push(val_2); + if let Some(a) = item { + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_3); + } sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "playEffect", sig.as_str(), args); + let res = self.jni_ref().call_method( + &self.jni_object(), + "sendEquipmentChange", + sig.as_str(), + args, + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the type of the entity. - pub fn get_type(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/entity/EntityType;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity makes while swimming. - pub fn swim_sound(&self) -> Result, Box> { - let args = Vec::new(); + /// Send a sign change. This fakes a sign change packet for a user at + /// a certain location. This will not actually change the world in any way. + /// This method will use a sign at the location's block or a faked sign + /// sent via + /// {@link #sendBlockChange(org.bukkit.Location, org.bukkit.block.data.BlockData)}. + /// + /// If the client does not have a sign at the given location it will + /// display an error message to the user. + /// + /// To change all attributes of a sign, including the back Side, use + /// {@link #sendBlockUpdate(org.bukkit.Location, org.bukkit.block.TileState)}. + pub fn send_sign_change( + &self, + loc: impl Into>, + lines: impl Into, + dye_color: std::option::Option>>, + has_glowing_text: std::option::Option, + ) -> Result<(), Box> { + let mut args = Vec::new(); let mut sig = String::from("("); - sig += ")Lorg/bukkit/Sound;"; + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(lines.into())?, + )); + args.push(val_2); + if let Some(a) = dye_color { + sig += "Lorg/bukkit/DyeColor;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_3); + } + if let Some(a) = has_glowing_text { + sig += "Z"; + let val_4 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_4); + } + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + .call_method(&self.jni_object(), "sendSignChange", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the {@link Sound} this entity makes when splashing in water. For most - /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_splash_sound(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/Sound;"; + /// Send a TileState change. This fakes a TileState change for a user at + /// the given location. This will not actually change the world in any way. + /// This method will use a TileState at the location's block or a faked TileState + /// sent via + /// {@link #sendBlockChange(org.bukkit.Location, org.bukkit.block.data.BlockData)}. + /// + /// If the client does not have an appropriate tile at the given location it + /// may display an error message to the user. + /// + /// {@link BlockData#createBlockState()} can be used to create a {@link BlockState}. + pub fn send_block_update( + &self, + loc: impl Into>, + tile_state: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Location;Lorg/bukkit/block/TileState;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(tile_state.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimSplashSound", + "sendBlockUpdate", sig.as_str(), - args, + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the {@link Sound} this entity makes when splashing in water at high - /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_high_speed_splash_sound( + /// Change a potion effect for the target entity. This will not actually + /// change the entity's potion effects in any way. + /// + /// Note: Sending an effect change to a player for themselves may + /// cause unexpected behavior on the client. Effects sent this way will also + /// not be removed when their timer reaches 0, they can be removed with + /// {@link #sendPotionEffectChangeRemove(LivingEntity, PotionEffectType)} + pub fn send_potion_effect_change( &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/Sound;"; + entity: impl Into>, + effect: impl Into>, + ) -> Result<(), Box> { + let sig = + String::from("(Lorg/bukkit/entity/LivingEntity;Lorg/bukkit/potion/PotionEffect;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimHighSpeedSplashSound", + "sendPotionEffectChange", sig.as_str(), - args, + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns whether this entity is inside a vehicle. - pub fn is_inside_vehicle(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Leave the current vehicle. If the entity is currently in a vehicle (and - /// is removed from it), true will be returned, otherwise false will be - /// returned. - pub fn leave_vehicle(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the vehicle that this entity is inside. If there is no vehicle, - /// null will be returned. - pub fn vehicle( - &self, - ) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/entity/Entity;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getVehicle", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets whether or not to display the mob's custom name client side. The - /// name will be displayed above the mob similarly to a player. + /// Remove a potion effect for the target entity. This will not actually + /// change the entity's potion effects in any way. /// - /// This value has no effect on players, they will always display their - /// name. - pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(flag.into()); - args.push(val_1); - sig += ")V"; + /// Note: Sending an effect change to a player for themselves may + /// cause unexpected behavior on the client. + pub fn send_potion_effect_change_remove( + &self, + entity: impl Into>, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = + String::from("(Lorg/bukkit/entity/LivingEntity;Lorg/bukkit/potion/PotionEffectType;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomNameVisible", + "sendPotionEffectChangeRemove", sig.as_str(), - args, + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not the mob's custom name is displayed client side. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn is_custom_name_visible(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; + /// Render a map and send it to the player in its entirety. This may be + /// used when streaming the map in the normal manner is not desirable. + pub fn send_map( + &self, + map: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/map/MapView;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(map.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "isCustomNameVisible", + "sendMap", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(visible.into()); - args.push(val_1); - sig += ")V"; + /// Send a hurt animation. This fakes incoming damage towards the player from + /// the given yaw relative to the player's direction. + pub fn send_hurt_animation(&self, yaw: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisibleByDefault", + "sendHurtAnimation", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn is_visible_by_default(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; + /// Sends the given server links to the player. + pub fn send_links( + &self, + links: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/ServerLinks;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(links.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "isVisibleByDefault", + "sendLinks", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get all players that are currently tracking this entity. - /// - /// 'Tracking' means that this entity has been sent to the player and that - /// they are receiving updates on its state. Note that the client's {@code - /// 'Entity Distance'} setting does not affect the range at which entities - /// are tracked. - pub fn tracked_by( - &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/Set;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets whether the entity has a team colored (default: white) glow. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(flag.into()); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setGlowing", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is glowing or not. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn is_glowing(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGlowing", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether the entity is invulnerable or not. - /// - /// When an entity is invulnerable it can only be damaged by players in - /// creative mode. - pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(flag.into()); - args.push(val_1); - sig += ")V"; + /// Forces an update of the player's entire inventory. + pub fn update_inventory(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref() - .call_method(&self.jni_object(), "setInvulnerable", sig.as_str(), args); + .call_method(&self.jni_object(), "updateInventory", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invulnerable or not. - pub fn is_invulnerable(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets whether the entity is silent or not. - pub fn is_silent(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSilent", sig.as_str(), args); + /// Gets this player's previous {@link GameMode} + pub fn previous_game_mode( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/GameMode;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPreviousGameMode", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::GameMode::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Sets whether the entity is silent or not. + /// Sets the current time on the player's client. When relative is true the + /// player's time will be kept synchronized to its world time with the + /// specified offset. /// - /// When an entity is silent it will not produce any sound. - pub fn set_silent(&self, flag: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(flag.into()); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setSilent", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns whether gravity applies to this entity. - pub fn has_gravity(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasGravity", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether gravity applies to this entity. - pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(gravity.into()); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setGravity", sig.as_str(), args); + /// When using non relative time the player's time will stay fixed at the + /// specified time parameter. It's up to the caller to continue updating + /// the player's time. To restore player time to normal use + /// resetPlayerTime(). + pub fn set_player_time( + &self, + time: i64, + relative: bool, + ) -> Result<(), Box> { + let sig = String::from("(JZ)V"); + let val_1 = jni::objects::JValueGen::Long(time); + let val_2 = jni::objects::JValueGen::Bool(relative.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPlayerTime", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the period of time (in ticks) before this entity can use a portal. - pub fn portal_cooldown(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")I"; + /// Returns the player's current timestamp. + pub fn player_time(&self) -> Result> { + let sig = String::from("()J"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPortalCooldown", sig.as_str(), args); + .call_method(&self.jni_object(), "getPlayerTime", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.j()?) } - /// Sets the period of time (in ticks) before this entity can use a portal. - pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(cooldown); - args.push(val_1); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setPortalCooldown", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Returns the player's current time offset relative to server time, or + /// the current player's fixed time if the player's time is absolute. + pub fn player_time_offset(&self) -> Result> { + let sig = String::from("()J"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPlayerTimeOffset", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.j()?) } - /// Returns a set of tags for this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn scoreboard_tags( - &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/Set;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getScoreboardTags", sig.as_str(), args); + /// Returns true if the player's time is relative to the server time, + /// otherwise the player's time is absolute and will not change its current + /// time unless done so with setPlayerTime(). + pub fn is_player_time_relative(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isPlayerTimeRelative", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Add a tag to this entity. + /// Restores the normal condition where the player's time is synchronized + /// with the server time. /// - /// Entities can have no more than 1024 tags. - pub fn add_scoreboard_tag( - &self, - tag: impl Into, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); - args.push(val_1); - sig += ")Z"; + /// Equivalent to calling setPlayerTime(0, true). + pub fn reset_player_time(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref() - .call_method(&self.jni_object(), "addScoreboardTag", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + .call_method(&self.jni_object(), "resetPlayerTime", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Removes a given tag from this entity. - pub fn remove_scoreboard_tag( + /// Sets the type of weather the player will see.When used, the weather + /// status of the player is locked until {@link #resetPlayerWeather()} is + /// used. + pub fn set_player_weather( &self, - tag: impl Into, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); - args.push(val_1); - sig += ")Z"; + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/WeatherType;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeScoreboardTag", + "setPlayerWeather", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns the reaction of the entity when moved by a piston. - pub fn piston_move_reaction( + /// Returns the type of weather the player is currently experiencing. + pub fn player_weather( &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/block/PistonMoveReaction;"; + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/WeatherType;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPistonMoveReaction", + "getPlayerWeather", sig.as_str(), - args, + vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the closest cardinal {@link BlockFace} direction an entity is - /// currently facing. - /// - /// This will not return any non-cardinal directions such as - /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. - /// - /// {@link Hanging} entities will override this call and thus their behavior - /// may be different. - pub fn facing(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/block/BlockFace;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::WeatherType::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets the entity's current pose. - /// Note that the pose is only updated at the end of a tick, so may be - /// inconsistent with other methods. eg {@link Player#isSneaking()} being - /// true does not imply the current pose will be {@link Pose#SNEAKING} - pub fn pose(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/entity/Pose;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPose", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Restores the normal condition where the player's weather is controlled + /// by server conditions. + pub fn reset_player_weather(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "resetPlayerWeather", + sig.as_str(), + vec![], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the category of spawn to which this entity belongs. - pub fn spawn_category( - &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/entity/SpawnCategory;"; + /// Gets the player's cooldown between picking up experience orbs. + pub fn exp_cooldown(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getSpawnCategory", sig.as_str(), args); + .call_method(&self.jni_object(), "getExpCooldown", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Checks if this entity has been spawned in a world. + /// Sets the player's cooldown between picking up experience orbs.. + /// Note: Setting this to 0 allows the player to pick up + /// instantly, but setting this to a negative value will cause the player to + /// be unable to pick up xp-orbs. + /// Calling this Method will result in {@link PlayerExpCooldownChangeEvent} + /// being called. + pub fn set_exp_cooldown(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setExpCooldown", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gives the player the amount of experience specified. + pub fn give_exp(&self, amount: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(amount); + let res = self.jni_ref().call_method( + &self.jni_object(), + "giveExp", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gives the player the amount of experience levels specified. Levels can + /// be taken by specifying a negative amount. + pub fn give_exp_levels(&self, amount: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(amount); + let res = self.jni_ref().call_method( + &self.jni_object(), + "giveExpLevels", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the players current experience points towards the next level. /// - /// Entities not spawned in a world will not tick, be sent to players, or be - /// saved to the server files. - pub fn is_in_world(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; + /// This is a percentage value. 0 is "no progress" and 1 is "next level". + pub fn exp(&self) -> Result> { + let sig = String::from("()F"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isInWorld", sig.as_str(), args); + .call_method(&self.jni_object(), "getExp", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.f()?) } - /// Get this entity as an NBT string. + /// Sets the players current experience points towards the next level /// - /// This string should not be relied upon as a serializable value. - pub fn as_string(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/lang/String;"; + /// This is a percentage value. 0 is "no progress" and 1 is "next level". + pub fn set_exp(&self, exp: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(exp); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setExp", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the players current experience level + pub fn level(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), args); + .call_method(&self.jni_object(), "getLevel", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(res.i()?) } - /// Crates an {@link EntitySnapshot} representing the current state of this entity. - pub fn create_snapshot( - &self, - ) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/entity/EntitySnapshot;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::EntitySnapshot::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + /// Sets the players current experience level + pub fn set_level(&self, level: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(level); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLevel", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + /// Gets the players total experience points. /// - /// Note: Players cannot be copied. - pub fn copy( - &self, - to: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = to { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")Lorg/bukkit/entity/Entity;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); + /// This refers to the total amount of experience the player has collected + /// over time and is not currently displayed to the client. + pub fn total_experience(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTotalExperience", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Sets a metadata value in the implementing object's metadata store. - pub fn set_metadata( - &self, - metadata_key: impl Into, - new_metadata_value: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += "Lorg/bukkit/metadata/MetadataValue;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) - }); - args.push(val_2); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setMetadata", sig.as_str(), args); + /// Sets the players current experience points. + /// + /// This refers to the total amount of experience the player has collected + /// over time and is not currently displayed to the client. + pub fn set_total_experience(&self, exp: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(exp); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTotalExperience", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a list of previously set metadata values from the implementing - /// object's metadata store. - pub fn get_metadata( + /// Send an experience change. + /// This fakes an experience change packet for a user. This will not actually + /// change the experience points in any way. + pub fn send_experience_change( &self, - metadata_key: impl Into, - ) -> Result>, Box> { + progress: f32, + level: std::option::Option, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); + sig += "F"; + let val_1 = jni::objects::JValueGen::Float(progress); args.push(val_1); - sig += ")Ljava/util/List;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getMetadata", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::metadata::MetadataValue::from_raw( - &self.jni_ref(), - obj, - )?); + if let Some(a) = level { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); } - Ok(new_vec) + sig += ")V"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "sendExperienceChange", + sig.as_str(), + args, + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Tests to see whether the implementing object contains the given - /// metadata value in its metadata store. - pub fn has_metadata( - &self, - metadata_key: impl Into, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasMetadata", sig.as_str(), args); + /// Determines if the Player is allowed to fly via jump key double-tap like + /// in creative mode. + pub fn allow_flight(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAllowFlight", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes the given metadata value from the implementing object's - /// metadata store. - pub fn remove_metadata( + /// Sets if the Player is allowed to fly via jump key double-tap like in + /// creative mode. + pub fn set_allow_flight(&self, flight: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flight.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAllowFlight", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Hides a player from this player + pub fn hide_player( &self, - metadata_key: impl Into, - owning_plugin: impl Into>, + plugin: impl Into>, + player: std::option::Option>>, ) -> Result<(), Box> { let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); + let mut sig = String::from("("); sig += "Lorg/bukkit/plugin/Plugin;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) }); - args.push(val_2); + args.push(val_1); + if let Some(a) = player { + sig += "Lorg/bukkit/entity/Player;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "removeMetadata", sig.as_str(), args); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hidePlayer", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sends this sender multiple messages - pub fn send_message( + /// Allows this player to see a player that was previously hidden. If + /// another another plugin had hidden the player too, then the player will + /// remain hidden until the other plugin calls this method too. + pub fn show_player( &self, - sender: impl Into>, - messages: std::option::Option>, + plugin: impl Into>, + player: std::option::Option>>, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; + sig += "Lorg/bukkit/plugin/Plugin;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) }); args.push(val_1); - if let Some(a) = messages { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); + if let Some(a) = player { + sig += "Lorg/bukkit/entity/Player;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); args.push(val_2); } sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); + .call_method(&self.jni_object(), "showPlayer", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the name of this command sender - pub fn name(&self) -> Result> { - let args = Vec::new(); + /// Checks to see if an entity has been visually hidden from this player. + pub fn can_see( + &self, + entity: impl Into>, + ) -> Result> { + let mut args = Vec::new(); let mut sig = String::from("("); - sig += ")Ljava/lang/String;"; + sig += "Lorg/bukkit/entity/Entity;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Gets the custom name on a mob or block. If there is no name this method - /// will return null. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn custom_name(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/lang/String;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCustomName", sig.as_str(), args); + .call_method(&self.jni_object(), "canSee", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(res.z()?) } - /// Sets a custom name on a mob or block. This name will be used in death - /// messages and can be sent to the client as a nameplate over the mob. - /// - /// Setting the name to null or an empty string will clear it. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn set_custom_name( + /// Visually hides an entity from this player. + pub fn hide_entity( &self, - name: impl Into, + plugin: impl Into>, + entity: impl Into>, ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); - args.push(val_1); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setCustomName", sig.as_str(), args); + let sig = String::from("(Lorg/bukkit/plugin/Plugin;Lorg/bukkit/entity/Entity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hideEntity", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( + /// Allows this player to see an entity that was previously hidden. If + /// another another plugin had hidden the entity too, then the entity will + /// remain hidden until the other plugin calls this method too. + pub fn show_entity( &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; + plugin: impl Into>, + entity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;Lorg/bukkit/entity/Entity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "showEntity", sig.as_str(), - args, + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks to see if this player is currently flying or not. + pub fn is_flying(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFlying", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Set the radius affected by this explosive's explosion - pub fn set_yield(&self, val_yield: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(val_yield); + /// Makes this player start or stop flying. + pub fn set_flying(&self, value: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(value.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setYield", + "setFlying", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Return the radius or yield of this explosive's explosion - pub fn get_yield(&self) -> Result> { - let sig = String::from("()F"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getYield", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + /// Sets the speed at which a client will fly. Negative values indicate + /// reverse directions. + pub fn set_fly_speed(&self, value: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFlySpeed", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Set whether or not this explosive's explosion causes fire - pub fn set_is_incendiary(&self, is_incendiary: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(is_incendiary.into()); + /// Sets the speed at which a client will walk. Negative values indicate + /// reverse directions. + pub fn set_walk_speed(&self, value: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(value); let res = self.jni_ref().call_method( &self.jni_object(), - "setIsIncendiary", + "setWalkSpeed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Return whether or not this explosive creates a fire when exploding - pub fn is_incendiary(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the current allowed speed that a client can fly. + pub fn fly_speed(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isIncendiary", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFlySpeed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Fireball<'mc> { - fn into(self) -> crate::entity::Projectile<'mc> { - crate::entity::Projectile::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Fireball into crate::entity::Projectile") - } -} -impl<'mc> Into> for Fireball<'mc> { - fn into(self) -> crate::entity::Explosive<'mc> { - crate::entity::Explosive::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Fireball into crate::entity::Explosive") - } -} -#[repr(C)] -pub struct Goat<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Goat<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Goat<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Goat from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Goat")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Goat object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + Ok(res.f()?) } -} - -impl<'mc> Goat<'mc> { - /// Gets if this goat has its left horn. - pub fn has_left_horn(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the current allowed speed that a client can walk. + pub fn walk_speed(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasLeftHorn", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getWalkSpeed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.f()?) } - /// Sets if this goat has its left horn. - pub fn set_left_horn(&self, has_horn: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(has_horn.into()); + #[deprecated] + /// Request that the player's client download and switch texture packs.The player's client will download the new texture pack asynchronously in the background, and will automatically switch to it once the download is complete. If the client has downloaded and cached the same texture pack in the past, it will perform a file size check against the response content to determine if the texture pack has changed and needs to be downloaded again. When this request is sent for the very first time from a given server, the client will first display a confirmation GUI to the player before proceeding with the download.Notes:
  • Players can disable server textures on their client, in which case this method will have no affect on them. Use the {@link PlayerResourcePackStatusEvent} to figure out whether or not the player loaded the pack!
  • There is no concept of resetting texture packs back to default within Minecraft, so players will have to relog to do so or you have to send an empty pack.
  • The request is send with "null" as the hash. This might result in newer versions not loading the pack correctly.
+ pub fn set_texture_pack( + &self, + url: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(url.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setLeftHorn", + "setTexturePack", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if this goat has its right horn. - pub fn has_right_horn(&self) -> Result> { - let sig = String::from("()Z"); + /// Request that the player's client download and switch resource packs. + /// + /// The player's client will download the new resource pack asynchronously + /// in the background, and will automatically switch to it once the + /// download is complete. If the client has downloaded and cached a + /// resource pack with the same hash in the past it will not download but + /// directly apply the cached pack. If the hash is null and the client has + /// downloaded and cached the same resource pack in the past, it will + /// perform a file size check against the response content to determine if + /// the resource pack has changed and needs to be downloaded again. When + /// this request is sent for the very first time from a given server, the + /// client will first display a confirmation GUI to the player before + /// proceeding with the download. + /// + /// Notes: + ///
    + ///
  • Players can disable server resources on their client, in which + /// case this method will have no affect on them. Use the + /// {@link PlayerResourcePackStatusEvent} to figure out whether or not + /// the player loaded the pack! + ///
  • To remove a resource pack you can use + /// {@link #removeResourcePack(UUID)} or {@link #removeResourcePacks()}. + ///
  • The request is sent with empty string as the hash when the hash is + /// not provided. This might result in newer versions not loading the + /// pack correctly. + ///
+ pub fn set_resource_pack( + &self, + id: impl Into>, + url: std::option::Option>, + hash: std::option::Option, + prompt: std::option::Option>, + force: std::option::Option, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/util/UUID;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(id.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = url { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_2); + } + if let Some(a) = hash { + sig += "B"; + let val_3 = jni::objects::JValueGen::Byte(a); + args.push(val_3); + } + if let Some(a) = prompt { + sig += "Ljava/lang/String;"; + let val_4 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_4); + } + if let Some(a) = force { + sig += "Z"; + let val_5 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_5); + } + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "hasRightHorn", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + .call_method(&self.jni_object(), "setResourcePack", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets if this goat has its right horn. - pub fn set_right_horn(&self, has_horn: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(has_horn.into()); + /// Request that the player's client download and include another resource pack. + /// + /// The player's client will download the new resource pack asynchronously + /// in the background, and will automatically add to it once the + /// download is complete. If the client has downloaded and cached a + /// resource pack with the same hash in the past it will not download but + /// directly apply the cached pack. If the hash is null and the client has + /// downloaded and cached the same resource pack in the past, it will + /// perform a file size check against the response content to determine if + /// the resource pack has changed and needs to be downloaded again. When + /// this request is sent for the very first time from a given server, the + /// client will first display a confirmation GUI to the player before + /// proceeding with the download. + /// + /// Notes: + ///
    + ///
  • Players can disable server resources on their client, in which + /// case this method will have no affect on them. Use the + /// {@link PlayerResourcePackStatusEvent} to figure out whether or not + /// the player loaded the pack! + ///
  • To remove a resource pack you can use + /// {@link #removeResourcePack(UUID)} or {@link #removeResourcePacks()}. + ///
  • The request is sent with empty string as the hash when the hash is + /// not provided. This might result in newer versions not loading the + /// pack correctly. + ///
+ pub fn add_resource_pack( + &self, + id: impl Into>, + url: impl Into, + hash: i8, + prompt: impl Into, + force: bool, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/UUID;Ljava/lang/String;BLjava/lang/String;Z)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(id.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(url.into())?, + )); + let val_3 = jni::objects::JValueGen::Byte(hash); + let val_4 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(prompt.into())?, + )); + let val_5 = jni::objects::JValueGen::Bool(force.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setRightHorn", + "addResourcePack", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + jni::objects::JValueGen::from(val_5), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Request that the player's client remove a resource pack sent by the + /// server. + pub fn remove_resource_pack( + &self, + id: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/UUID;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(id.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeResourcePack", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if this is a screaming goat. - /// A screaming goat makes screaming sounds and rams more often. They do not - /// offer home loans. - pub fn is_screaming(&self) -> Result> { - let sig = String::from("()Z"); + /// Request that the player's client remove all loaded resource pack sent by + /// the server. + pub fn remove_resource_packs(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeResourcePacks", + sig.as_str(), + vec![], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the Scoreboard displayed to this player + pub fn scoreboard( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/scoreboard/Scoreboard;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isScreaming", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getScoreboard", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::scoreboard::Scoreboard::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets if this is a screaming goat. - /// A screaming goat makes screaming sounds and rams more often. They do not - /// offer home loans. - pub fn set_screaming(&self, screaming: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(screaming.into()); + /// Sets the player's visible Scoreboard. + pub fn set_scoreboard( + &self, + scoreboard: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/scoreboard/Scoreboard;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(scoreboard.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setScreaming", + "setScoreboard", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn breed_cause( + /// Gets the {@link WorldBorder} visible to this Player, or null if viewing + /// the world's world border. + pub fn world_border( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/UUID;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/WorldBorder;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getWorldBorder", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( + Ok(Some(crate::WorldBorder::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Set the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn set_breed_cause( + /// Sets the {@link WorldBorder} visible to this Player. + pub fn set_world_border( &self, - uuid: impl Into>, + border: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/UUID;)V"); + let sig = String::from("(Lorg/bukkit/WorldBorder;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) + jni::objects::JObject::from_raw(border.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreedCause", + "setWorldBorder", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get whether or not this entity is in love mode and will produce - /// offspring with another entity in love mode. Will return true if - /// and only if {@link #getLoveModeTicks()} is greater than 0. - pub fn is_love_mode(&self) -> Result> { + /// Send a health update to the player. This will adjust the health, food, and + /// saturation on the client and will not affect the player's actual values on + /// the server. As soon as any of these values change on the server, changes sent + /// by this method will no longer be visible. + pub fn send_health_update( + &self, + health: std::option::Option, + food_level: std::option::Option, + saturation: std::option::Option, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = health { + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(a); + args.push(val_1); + } + if let Some(a) = food_level { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + if let Some(a) = saturation { + sig += "F"; + let val_3 = jni::objects::JValueGen::Float(a); + args.push(val_3); + } + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "sendHealthUpdate", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the client is displayed a 'scaled' health, that is, health on a + /// scale from 0-{@link #getHealthScale()}. + pub fn is_health_scaled(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isHealthScaled", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get the amount of ticks remaining for this entity in love mode. - /// If the entity is not in love mode, 0 will be returned. - pub fn love_mode_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Sets if the client is displayed a 'scaled' health, that is, health on a + /// scale from 0-{@link #getHealthScale()}. + /// + /// Displayed health follows a simple formula displayedHealth = + /// getHealth() / getMaxHealth() * getHealthScale(). + pub fn set_health_scaled(&self, scale: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(scale.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getLoveModeTicks", + "setHealthScaled", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Set the amount of ticks for which this entity should be in love mode. - /// Setting the love mode ticks to 600 is the equivalent of a player - /// feeding the entity their breeding item of choice. - pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Sets the number to scale health to for the client; this will also + /// {@link #setHealthScaled(boolean) setHealthScaled(true)}. + /// + /// Displayed health follows a simple formula displayedHealth = + /// getHealth() / getMaxHealth() * getHealthScale(). + pub fn set_health_scale(&self, scale: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(scale); let res = self.jni_ref().call_method( &self.jni_object(), - "setLoveModeTicks", + "setHealthScale", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check if the provided ItemStack is the correct item used for breeding - /// this entity.. - pub fn is_breed_item( - &self, - material: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Lock the age of the animal, setting this will prevent the animal from - /// maturing or getting ready for mating. - pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(lock.into()); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setAgeLock", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the current agelock. - pub fn age_lock(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Return the ability to breed of the animal. - pub fn can_breed(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "canBreed", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Set breedability of the animal, if the animal is a baby and set to - /// breed it will instantly grow up. - pub fn set_breed(&self, breed: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(breed.into()); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setBreed", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Goat<'mc> { - fn into(self) -> crate::entity::Animals<'mc> { - crate::entity::Animals::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Goat into crate::entity::Animals") - } -} -#[repr(C)] -pub struct EnderDragonPart<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for EnderDragonPart<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for EnderDragonPart<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate EnderDragonPart from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/EnderDragonPart")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EnderDragonPart object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> EnderDragonPart<'mc> { - pub fn parent(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EnderDragon;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getParent", sig.as_str(), vec![]); + /// Gets the number that health is scaled to for the client. + pub fn health_scale(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHealthScale", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::EnderDragon::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.d()?) } - /// Stores the entity's current position in the provided Location object. - /// - /// If the provided Location is null this method does nothing and returns - /// null. - pub fn get_location( + /// Gets the entity which is followed by the camera when in + /// {@link GameMode#SPECTATOR}. + pub fn spectator_target( &self, - loc: impl Into>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Lorg/bukkit/Location;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getLocation", sig.as_str(), args); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSpectatorTarget", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Sets this entity's velocity in meters per tick - pub fn set_velocity( - &self, - velocity: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/util/Vector;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setVelocity", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets this entity's current velocity - pub fn velocity(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/util/Vector;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the entity's height - pub fn height(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")D"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHeight", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the entity's width - pub fn width(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")D"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWidth", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the entity's current bounding box. - /// - /// The returned bounding box reflects the entity's current location and - /// size. - pub fn bounding_box( - &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/util/BoundingBox;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBoundingBox", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns true if the entity is supported by a block. This value is a - /// state updated by the server and is not recalculated unless the entity - /// moves. - pub fn is_on_ground(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isOnGround", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns true if the entity is in water. - pub fn is_in_water(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWater", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the current world this entity resides in - pub fn world(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/World;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the entity's rotation. - /// - /// Note that if the entity is affected by AI, it may override this rotation. - pub fn set_rotation(&self, yaw: f32, pitch: f32) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "F"; - let val_1 = jni::objects::JValueGen::Float(yaw); - args.push(val_1); - sig += "F"; - let val_2 = jni::objects::JValueGen::Float(pitch); - args.push(val_2); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setRotation", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Teleports this entity to the given location. If this entity is riding a - /// vehicle, it will be dismounted prior to teleportation. - pub fn teleport( - &self, - location: impl Into>, - cause: std::option::Option< - impl Into>, - >, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = cause { - sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "teleport", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Returns a list of entities within a bounding box centered around this - /// entity - pub fn get_nearby_entities( + /// Sets the entity which is followed by the camera when in + /// {@link GameMode#SPECTATOR}. + pub fn set_spectator_target( &self, - x: f64, - y: f64, - z: f64, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(x); - args.push(val_1); - sig += "D"; - let val_2 = jni::objects::JValueGen::Double(y); - args.push(val_2); - sig += "D"; - let val_3 = jni::objects::JValueGen::Double(z); - args.push(val_3); - sig += ")Ljava/util/List;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getNearbyEntities", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Returns a unique id for this entity - pub fn entity_id(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")I"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getEntityId", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn fire_ticks(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")I"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFireTicks", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the entity's maximum fire ticks. - pub fn max_fire_ticks(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")I"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaxFireTicks", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the entity's current fire ticks (ticks before the entity stops - /// being on fire). - pub fn set_fire_ticks(&self, ticks: i32) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(ticks); - args.push(val_1); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setFireTicks", sig.as_str(), args); + entity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSpectatorTarget", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets if the entity has visual fire (it will always appear to be on fire). - pub fn set_visual_fire(&self, fire: bool) -> Result<(), Box> { + /// Sends a title and a subtitle message to the player. If either of these + /// values are null, they will not be sent and the display will remain + /// unchanged. If they are empty strings, the display will be updated as + /// such. If the strings contain a new line, only the first line will be + /// sent. All timings values may take a value of -1 to indicate that they + /// will use the last value sent (or the defaults if no title has been + /// displayed). + pub fn send_title( + &self, + title: impl Into, + subtitle: impl Into, + fade_in: std::option::Option, + stay: std::option::Option, + fade_out: std::option::Option, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(fire.into()); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(title.into())?, + )); args.push(val_1); + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(subtitle.into())?, + )); + args.push(val_2); + if let Some(a) = fade_in { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + if let Some(a) = stay { + sig += "I"; + let val_4 = jni::objects::JValueGen::Int(a); + args.push(val_4); + } + if let Some(a) = fade_out { + sig += "I"; + let val_5 = jni::objects::JValueGen::Int(a); + args.push(val_5); + } sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setVisualFire", sig.as_str(), args); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "sendTitle", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity has visual fire (it will always appear to be on fire). - pub fn is_visual_fire(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isVisualFire", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn freeze_ticks(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")I"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFreezeTicks", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the entity's maximum freeze ticks (amount of ticks before it will - /// be fully frozen) - pub fn max_freeze_ticks(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")I"; + /// Resets the title displayed to the player. This will clear the displayed + /// title / subtitle and reset timings to their default values. + pub fn reset_title(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxFreezeTicks", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + .call_method(&self.jni_object(), "resetTitle", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the entity's current freeze ticks (amount of ticks the entity has - /// been in powdered snow). - pub fn set_freeze_ticks(&self, ticks: i32) -> Result<(), Box> { + /// Spawns the particle (the number of times specified by count) + /// at the target location. The position of each particle will be + /// randomized positively and negatively by the offset parameters + /// on each axis. + pub fn spawn_particle( + &self, + particle: impl Into>, + x: f64, + y: f64, + z: std::option::Option, + count: std::option::Option, + offset_x: std::option::Option, + offset_y: std::option::Option, + offset_z: std::option::Option, + extra: std::option::Option, + data: std::option::Option>, + force: std::option::Option, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(ticks); + sig += "Lorg/bukkit/Particle;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(particle.into().jni_object().clone()) + }); args.push(val_1); + sig += "D"; + let val_2 = jni::objects::JValueGen::Double(x); + args.push(val_2); + sig += "D"; + let val_3 = jni::objects::JValueGen::Double(y); + args.push(val_3); + if let Some(a) = z { + sig += "D"; + let val_4 = jni::objects::JValueGen::Double(a); + args.push(val_4); + } + if let Some(a) = count { + sig += "I"; + let val_5 = jni::objects::JValueGen::Int(a); + args.push(val_5); + } + if let Some(a) = offset_x { + sig += "D"; + let val_6 = jni::objects::JValueGen::Double(a); + args.push(val_6); + } + if let Some(a) = offset_y { + sig += "D"; + let val_7 = jni::objects::JValueGen::Double(a); + args.push(val_7); + } + if let Some(a) = offset_z { + sig += "D"; + let val_8 = jni::objects::JValueGen::Double(a); + args.push(val_8); + } + if let Some(a) = extra { + sig += "D"; + let val_9 = jni::objects::JValueGen::Double(a); + args.push(val_9); + } + if let Some(a) = data { + sig += "LT;"; + let val_10 = jni::objects::JValueGen::Object(a); + args.push(val_10); + } + if let Some(a) = force { + sig += "Z"; + let val_11 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_11); + } sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "setFreezeTicks", sig.as_str(), args); + .call_method(&self.jni_object(), "spawnParticle", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the entity is fully frozen (it has been in powdered snow for max - /// freeze ticks). - pub fn is_frozen(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isFrozen", sig.as_str(), args); + /// Return the player's progression on the specified advancement. + pub fn get_advancement_progress( + &self, + advancement: impl Into>, + ) -> Result, Box> { + let sig = String::from( + "(Lorg/bukkit/advancement/Advancement;)Lorg/bukkit/advancement/AdvancementProgress;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(advancement.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAdvancementProgress", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Mark the entity's removal. - pub fn remove(&self) -> Result<(), Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::advancement::AdvancementProgress::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns true if this entity has been marked for removal. - pub fn is_dead(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isDead", sig.as_str(), args); + /// Get the player's current client side view distance. + /// + /// Will default to the server view distance if the client has not yet + /// communicated this information, + pub fn client_view_distance(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getClientViewDistance", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Returns false if the entity has died, been despawned for some other - /// reason, or has not been added to the world. - pub fn is_valid(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; + /// Gets the player's estimated ping in milliseconds. + /// In Vanilla this value represents a weighted average of the response time + /// to application layer ping packets sent. This value does not represent the + /// network round trip time and as such may have less granularity and be + /// impacted by other sources. For these reasons it should not be used + /// for anti-cheat purposes. Its recommended use is only as a + /// qualitative indicator of connection quality (Vanilla uses it for + /// this purpose in the tab list). + pub fn ping(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isValid", sig.as_str(), args); + .call_method(&self.jni_object(), "getPing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Gets the {@link Server} that contains this Entity - pub fn server(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/Server;"; + /// Gets the player's current locale. + /// The value of the locale String is not defined properly. + /// + /// The vanilla Minecraft client will use lowercase language / country pairs + /// separated by an underscore, but custom resource packs may use any format + /// they wish. + pub fn locale(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getServer", sig.as_str(), args); + .call_method(&self.jni_object(), "getLocale", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Server::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Returns true if the entity gets persisted. - /// - /// By default all entities are persistent. An entity will also not get - /// persisted, if it is riding an entity that is not persistent. - /// - /// The persistent flag on players controls whether or not to save their - /// playerdata file when they quit. If a player is directly or indirectly - /// riding a non-persistent entity, the vehicle at the root and all its - /// passengers won't get persisted. + /// Update the list of commands sent to the client. /// - /// This should not be confused with - /// {@link LivingEntity#setRemoveWhenFarAway(boolean)} which controls - /// despawning of living entities. - pub fn is_persistent(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isPersistent", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether or not the entity gets persisted. - pub fn set_persistent(&self, persistent: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(persistent.into()); - args.push(val_1); - sig += ")V"; + /// Generally useful to ensure the client has a complete list of commands + /// after permission changes are done. + pub fn update_commands(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref() - .call_method(&self.jni_object(), "setPersistent", sig.as_str(), args); + .call_method(&self.jni_object(), "updateCommands", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the primary passenger of a vehicle. For vehicles that could have multiple passengers, this will only return the primary passenger. - pub fn passenger( + /// Open a {@link Material#WRITTEN_BOOK} for a Player + pub fn open_book( &self, - ) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/entity/Entity;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPassenger", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + book: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(book.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "openBook", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - #[deprecated] - /// Set the passenger of a vehicle. - pub fn set_passenger( + /// Open a Sign for editing by the Player. + /// The Sign must be placed in the same world as the player. + pub fn open_sign( &self, - passenger: impl Into>, - ) -> Result> { + sign: impl Into>, + side: std::option::Option>>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Entity;"; + sig += "Lorg/bukkit/block/Sign;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) + jni::objects::JObject::from_raw(sign.into().jni_object().clone()) }); args.push(val_1); - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setPassenger", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if let Some(a) = side { + sig += "Lorg/bukkit/block/sign/Side;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "openSign", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets a list of passengers of this vehicle. + /// Shows the demo screen to the player, this screen is normally only seen in + /// the demo version of the game. /// - /// The returned list will not be directly linked to the entity's current - /// passengers, and no guarantees are made as to its mutability. - pub fn passengers( - &self, - ) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/List;"; + /// Servers can modify the text on this screen using a resource pack. + pub fn show_demo_screen(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPassengers", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + .call_method(&self.jni_object(), "showDemoScreen", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Add a passenger to the vehicle. - pub fn add_passenger( - &self, - passenger: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Entity;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "addPassenger", sig.as_str(), args); + /// Gets whether the player has the "Allow Server Listings" setting enabled. + pub fn is_allowing_server_listings(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isAllowingServerListings", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Remove a passenger from the vehicle. - pub fn remove_passenger( + /// Get the player's inventory. + pub fn inventory( &self, - passenger: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Entity;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(passenger.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Z"; + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/PlayerInventory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "removePassenger", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Check if a vehicle has passengers. - pub fn is_empty(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Eject any passenger. - pub fn eject(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "eject", sig.as_str(), args); + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::PlayerInventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the distance this entity has fallen - pub fn fall_distance(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")F"; + /// Get the player's EnderChest inventory + pub fn ender_chest( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFallDistance", sig.as_str(), args); + .call_method(&self.jni_object(), "getEnderChest", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the fall distance for this entity - pub fn set_fall_distance(&self, distance: f32) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "F"; - let val_1 = jni::objects::JValueGen::Float(distance); - args.push(val_1); - sig += ")V"; + /// Gets the player's selected main hand + pub fn main_hand(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/MainHand;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "setFallDistance", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getMainHand", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::MainHand::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } #[deprecated] - /// Record the last {@link EntityDamageEvent} inflicted on this entity - pub fn set_last_damage_cause( + /// If the player currently has an inventory window open, this method will set a property of that window, such as the state of a progress bar. + pub fn set_window_property( &self, - event: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/event/entity/EntityDamageEvent;"; + prop: impl Into>, + value: i32, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/InventoryView/Property;I)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(event.into().jni_object().clone()) + jni::objects::JObject::from_raw(prop.into().jni_object().clone()) }); - args.push(val_1); - sig += ")V"; + let val_2 = jni::objects::JValueGen::Int(value); let res = self.jni_ref().call_method( &self.jni_object(), - "setLastDamageCause", + "setWindowProperty", sig.as_str(), - args, + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Retrieve the last {@link EntityDamageEvent} inflicted on this entity. - /// This event may have been cancelled. - pub fn last_damage_cause( - &self, - ) -> Result>, Box> - { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/event/entity/EntityDamageEvent;"; + /// Gets the player's current enchantment seed. + /// The Seed is used to generate enchantment options in the enchanting table + /// for the player. + pub fn enchantment_seed(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLastDamageCause", + "getEnchantmentSeed", sig.as_str(), - args, + vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::event::entity::EntityDamageEvent::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - /// Returns a unique and persistent id for this entity - pub fn unique_id( - &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/UUID;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Sets the player's enchantment seed. + /// The Seed is used to generate enchantment options in the enchanting table + /// for the player. + pub fn set_enchantment_seed(&self, seed: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(seed); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setEnchantmentSeed", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the amount of ticks this entity has lived for. + /// Opens an inventory window to the specified inventory view. /// - /// This is the equivalent to "age" in entities. - pub fn ticks_lived(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")I"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTicksLived", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the amount of ticks this entity has lived for. + /// The player associated with the InventoryView must be the same as this + /// instance of HumanEntity. /// - /// This is the equivalent to "age" in entities. May not be less than one - /// tick. - pub fn set_ticks_lived(&self, value: i32) -> Result<(), Box> { + /// The player of the InventoryView can be checked using + /// {@link InventoryView#getPlayer()}. + pub fn open_inventory( + &self, + inventory: std::option::Option>>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(value); - args.push(val_1); + if let Some(a) = inventory { + sig += "Lorg/bukkit/inventory/InventoryView;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "setTicksLived", sig.as_str(), args); + .call_method(&self.jni_object(), "getOpenInventory", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Performs the specified {@link EntityEffect} for this entity. + /// Opens an inventory window to the specified inventory view. /// - /// This will be viewable to all players near the entity. + /// The player associated with the InventoryView must be the same as this + /// instance of HumanEntity. /// - /// If the effect is not applicable to this class of entity, it will not play. - pub fn play_effect( + /// The player of the InventoryView can be checked using + /// {@link InventoryView#getPlayer()}. + pub fn open_inventory_with_inventory( &self, - val_type: impl Into>, + inventory: std::option::Option>>, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/EntityEffect;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - args.push(val_1); + if let Some(a) = inventory { + sig += "Lorg/bukkit/inventory/InventoryView;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "playEffect", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the type of the entity. - pub fn get_type(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/entity/EntityType;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity makes while swimming. - pub fn swim_sound(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getSwimSound", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + .call_method(&self.jni_object(), "openInventory", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the {@link Sound} this entity makes when splashing in water. For most - /// entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_splash_sound(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/Sound;"; + /// Opens an empty workbench inventory window with the player's inventory + /// on the bottom. + pub fn open_workbench( + &self, + location: impl Into>, + force: bool, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;Z)Lorg/bukkit/inventory/InventoryView;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Bool(force.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimSplashSound", + "openWorkbench", sig.as_str(), - args, + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::InventoryView::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Get the {@link Sound} this entity makes when splashing in water at high - /// speeds. For most entities, this is just {@link Sound#ENTITY_GENERIC_SPLASH}. - pub fn swim_high_speed_splash_sound( + /// Opens an empty enchanting inventory window with the player's inventory + /// on the bottom. + pub fn open_enchanting( &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/Sound;"; + location: impl Into>, + force: bool, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;Z)Lorg/bukkit/inventory/InventoryView;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Bool(force.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getSwimHighSpeedSplashSound", + "openEnchanting", sig.as_str(), - args, + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns whether this entity is inside a vehicle. - pub fn is_inside_vehicle(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInsideVehicle", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::InventoryView::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Leave the current vehicle. If the entity is currently in a vehicle (and - /// is removed from it), true will be returned, otherwise false will be - /// returned. - pub fn leave_vehicle(&self) -> Result> { - let args = Vec::new(); + /// Starts a trade between the player and the merchant. + /// Note that only one player may trade with a merchant at once. You must use + /// the force parameter for this. + pub fn open_merchant( + &self, + merchant: impl Into>, + force: bool, + ) -> Result>, Box> { + let mut args = Vec::new(); let mut sig = String::from("("); - sig += ")Z"; + sig += "Lorg/bukkit/inventory/Merchant;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(merchant.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(force.into()); + args.push(val_2); + sig += ")Lorg/bukkit/inventory/InventoryView;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "leaveVehicle", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the vehicle that this entity is inside. If there is no vehicle, - /// null will be returned. - pub fn vehicle( - &self, - ) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/entity/Entity;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getVehicle", sig.as_str(), args); + .call_method(&self.jni_object(), "openMerchant", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Entity::from_raw( + Ok(Some(crate::inventory::InventoryView::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets whether or not to display the mob's custom name client side. The - /// name will be displayed above the mob similarly to a player. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn set_custom_name_visible(&self, flag: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(flag.into()); - args.push(val_1); - sig += ")V"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCustomNameVisible", - sig.as_str(), - args, - ); + /// Force-closes the currently open inventory view for this player, if any. + pub fn close_inventory(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "closeInventory", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not the mob's custom name is displayed client side. - /// - /// This value has no effect on players, they will always display their - /// name. - pub fn is_custom_name_visible(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; + #[deprecated] + /// Returns the ItemStack currently in your hand, can be empty. + pub fn item_in_hand( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemInHand", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + #[deprecated] + /// Sets the item to the given ItemStack, this will replace whatever the user was holding. + pub fn set_item_in_hand( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "isCustomNameVisible", + "setItemInHand", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the ItemStack currently on your cursor, can be empty. Will + /// always be empty if the player currently has no open window. + pub fn item_on_cursor( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemOnCursor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn set_visible_by_default(&self, visible: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(visible.into()); - args.push(val_1); - sig += ")V"; + /// Sets the item to the given ItemStack, this will replace whatever the + /// user was moving. Will always be empty if the player currently has no + /// open window. + pub fn set_item_on_cursor( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisibleByDefault", + "setItemOnCursor", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether or not this entity is visible by default. - /// If this entity is not visible by default, then - /// {@link Player#showEntity(org.bukkit.plugin.Plugin, org.bukkit.entity.Entity)} - /// will need to be called before the entity is visible to a given player. - pub fn is_visible_by_default(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; + /// Check whether a cooldown is active on the specified material. + pub fn has_cooldown( + &self, + material: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/Material;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "isVisibleByDefault", + "hasCooldown", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get all players that are currently tracking this entity. - /// - /// 'Tracking' means that this entity has been sent to the player and that - /// they are receiving updates on its state. Note that the client's {@code - /// 'Entity Distance'} setting does not affect the range at which entities - /// are tracked. - pub fn tracked_by( + /// Get the cooldown time in ticks remaining for the specified material. + pub fn get_cooldown( &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/Set;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTrackedBy", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets whether the entity has a team colored (default: white) glow. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn set_glowing(&self, flag: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(flag.into()); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setGlowing", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether the entity is glowing or not. - /// nb: this refers to the 'Glowing' entity property, not whether a - /// glowing potion effect is applied - pub fn is_glowing(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isGlowing", sig.as_str(), args); + material: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/Material;)I"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCooldown", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets whether the entity is invulnerable or not. + /// Set a cooldown on the specified material for a certain amount of ticks. + /// ticks. 0 ticks will result in the removal of the cooldown. /// - /// When an entity is invulnerable it can only be damaged by players in - /// creative mode. - pub fn set_invulnerable(&self, flag: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(flag.into()); - args.push(val_1); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setInvulnerable", sig.as_str(), args); + /// Cooldowns are used by the server for items such as ender pearls and + /// shields to prevent them from being used repeatedly. + /// + /// Note that cooldowns will not by themselves stop an item from being used + /// for attacking. + pub fn set_cooldown( + &self, + material: impl Into>, + ticks: i32, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Material;I)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCooldown", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invulnerable or not. - pub fn is_invulnerable(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; + /// Get the sleep ticks of the player. This value may be capped. + pub fn sleep_ticks(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isInvulnerable", sig.as_str(), args); + .call_method(&self.jni_object(), "getSleepTicks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Gets whether the entity is silent or not. - pub fn is_silent(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSilent", sig.as_str(), args); + /// Attempts to make the entity sleep at the given location. + /// + /// The location must be in the current world and have a bed placed at the + /// location. The game may also enforce other requirements such as proximity + /// to bed, monsters, and dimension type if force is not set. + pub fn sleep( + &self, + location: impl Into>, + force: bool, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/Location;Z)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Bool(force.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "sleep", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the entity is silent or not. - /// - /// When an entity is silent it will not produce any sound. - pub fn set_silent(&self, flag: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(flag.into()); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setSilent", sig.as_str(), args); + /// Causes the player to wakeup if they are currently sleeping. + pub fn wakeup(&self, set_spawn_location: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(set_spawn_location.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "wakeup", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns whether gravity applies to this entity. - pub fn has_gravity(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasGravity", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether gravity applies to this entity. - pub fn set_gravity(&self, gravity: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(gravity.into()); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setGravity", sig.as_str(), args); + /// Make the player start a riptide spin attack. + pub fn start_riptide_attack( + &self, + duration: i32, + attack_strength: f32, + attack_item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(IFLorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Int(duration); + let val_2 = jni::objects::JValueGen::Float(attack_strength); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attack_item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "startRiptideAttack", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the period of time (in ticks) before this entity can use a portal. - pub fn portal_cooldown(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")I"; + /// Gets the location of the bed the player is currently sleeping in + pub fn bed_location(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPortalCooldown", sig.as_str(), args); + .call_method(&self.jni_object(), "getBedLocation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the period of time (in ticks) before this entity can use a portal. - pub fn set_portal_cooldown(&self, cooldown: i32) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(cooldown); - args.push(val_1); - sig += ")V"; + /// Gets this human's current {@link GameMode} + pub fn game_mode(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/GameMode;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "setPortalCooldown", sig.as_str(), args); + .call_method(&self.jni_object(), "getGameMode", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::GameMode::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets this human's current {@link GameMode} + pub fn set_game_mode( + &self, + mode: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/GameMode;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(mode.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setGameMode", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a set of tags for this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn scoreboard_tags( - &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/Set;"; + /// Check if the player is currently blocking (ie with a shield). + pub fn is_blocking(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getScoreboardTags", sig.as_str(), args); + .call_method(&self.jni_object(), "isBlocking", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Add a tag to this entity. - /// - /// Entities can have no more than 1024 tags. - pub fn add_scoreboard_tag( - &self, - tag: impl Into, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); - args.push(val_1); - sig += ")Z"; + /// Check if the player currently has their hand raised (ie about to begin + /// blocking). + pub fn is_hand_raised(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "addScoreboardTag", sig.as_str(), args); + .call_method(&self.jni_object(), "isHandRaised", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes a given tag from this entity. - pub fn remove_scoreboard_tag( + /// Get the total amount of experience required for the player to level + pub fn exp_to_level(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getExpToLevel", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the current cooldown for a player's attack. + /// This is used to calculate damage, with 1.0 representing a fully charged + /// attack and 0.0 representing a non-charged attack + pub fn attack_cooldown(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAttackCooldown", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Discover a recipe for this player such that it has not already been + /// discovered. This method will add the key's associated recipe to the + /// player's recipe book. + pub fn discover_recipe( &self, - tag: impl Into, + recipe: impl Into>, ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(tag.into())?, - )); - args.push(val_1); - sig += ")Z"; + let sig = String::from("(Lorg/bukkit/NamespacedKey;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeScoreboardTag", + "discoverRecipe", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns the reaction of the entity when moved by a piston. - pub fn piston_move_reaction( + /// Undiscover a recipe for this player such that it has already been + /// discovered. This method will remove the key's associated recipe from the + /// player's recipe book. + pub fn undiscover_recipe( &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/block/PistonMoveReaction;"; + recipe: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getPistonMoveReaction", + "undiscoverRecipe", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::block::PistonMoveReaction::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the closest cardinal {@link BlockFace} direction an entity is - /// currently facing. - /// - /// This will not return any non-cardinal directions such as - /// {@link BlockFace#UP} or {@link BlockFace#DOWN}. - /// - /// {@link Hanging} entities will override this call and thus their behavior - /// may be different. - pub fn facing(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/block/BlockFace;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Gets the entity's current pose. - /// Note that the pose is only updated at the end of a tick, so may be - /// inconsistent with other methods. eg {@link Player#isSneaking()} being - /// true does not imply the current pose will be {@link Pose#SNEAKING} - pub fn pose(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/entity/Pose;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPose", sig.as_str(), args); + /// Check whether or not this entity has discovered the specified recipe. + pub fn has_discovered_recipe( + &self, + recipe: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasDiscoveredRecipe", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Get the category of spawn to which this entity belongs. - pub fn spawn_category( + /// Get an immutable set of recipes this entity has discovered. + pub fn discovered_recipes( &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/entity/SpawnCategory;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSpawnCategory", sig.as_str(), args); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDiscoveredRecipes", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::entity::SpawnCategory::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Checks if this entity has been spawned in a world. - /// - /// Entities not spawned in a world will not tick, be sent to players, or be - /// saved to the server files. - pub fn is_in_world(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isInWorld", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get this entity as an NBT string. + #[deprecated] + /// Gets the entity currently perched on the left shoulder or null if no entity. /// - /// This string should not be relied upon as a serializable value. - pub fn as_string(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/lang/String;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// Crates an {@link EntitySnapshot} representing the current state of this entity. - pub fn create_snapshot( + /// The returned entity will not be spawned within the world, so most operations are invalid unless the entity is first spawned in. + pub fn shoulder_entity_left( &self, - ) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/entity/EntitySnapshot;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "createSnapshot", sig.as_str(), args); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getShoulderEntityLeft", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::EntitySnapshot::from_raw( + Ok(Some(crate::entity::Entity::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Creates a copy of this entity and all its data. Spawns the copy at the given location. + #[deprecated] + /// Sets the entity currently perched on the left shoulder, or null to remove. This method will remove the entity from the world. /// - /// Note: Players cannot be copied. - pub fn copy( - &self, - to: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = to { - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")Lorg/bukkit/entity/Entity;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Deals the given amount of damage to this entity from a specified - /// {@link DamageSource}. - pub fn damage( + /// Note that only a copy of the entity will be set to display on the shoulder. + /// + /// Also note that the client will currently only render {@link Parrot} entities. + pub fn set_shoulder_entity_left( &self, - amount: f64, - damage_source: std::option::Option>>, + entity: impl Into>, ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(amount); - args.push(val_1); - if let Some(a) = damage_source { - sig += "Lorg/bukkit/damage/DamageSource;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "damage", sig.as_str(), args); + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setShoulderEntityLeft", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. - pub fn health(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); + #[deprecated] + /// Gets the entity currently perched on the right shoulder or null if no entity. + /// + /// The returned entity will not be spawned within the world, so most operations are invalid unless the entity is first spawned in. + pub fn shoulder_entity_right( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getShoulderEntityRight", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is - /// dead. - pub fn set_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); + #[deprecated] + /// Sets the entity currently perched on the right shoulder, or null to remove. This method will remove the entity from the world. + /// + /// Note that only a copy of the entity will be set to display on the shoulder. + /// + /// Also note that the client will currently only render {@link Parrot} entities. + pub fn set_shoulder_entity_right( + &self, + entity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setHealth", + "setShoulderEntityRight", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the entity's absorption amount. - pub fn absorption_amount(&self) -> Result> { - let sig = String::from("()D"); + /// Make the entity drop the item in their hand. + /// + /// This will force the entity to drop the item they are holding with + /// an option to drop the entire {@link ItemStack} or just 1 of the items. + pub fn drop_item(&self, drop_all: bool) -> Result> { + let sig = String::from("(Z)Z"); + let val_1 = jni::objects::JValueGen::Bool(drop_all.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getAbsorptionAmount", + "dropItem", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Sets the entity's absorption amount. + /// Gets the players current exhaustion level. /// - /// Note: The amount is capped to the value of - /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on - /// that attribute is currently unspecified and subject to change. - pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(amount); + /// Exhaustion controls how fast the food level drops. While you have a + /// certain amount of exhaustion, your saturation will drop to zero, and + /// then your food will drop to zero. + pub fn exhaustion(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getExhaustion", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the players current exhaustion level + pub fn set_exhaustion(&self, value: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(value); let res = self.jni_ref().call_method( &self.jni_object(), - "setAbsorptionAmount", + "setExhaustion", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the maximum health this entity has. - pub fn max_health(&self) -> Result> { - let sig = String::from("()D"); + /// Gets the players current saturation level. + /// + /// Saturation is a buffer for food level. Your food level will not drop if + /// you are saturated {@literal >} 0. + pub fn saturation(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSaturation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.f()?) } - #[deprecated] - /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. - pub fn set_max_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); + /// Sets the players current saturation level + pub fn set_saturation(&self, value: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(value); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxHealth", + "setSaturation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Resets the max health to the original amount. - pub fn reset_max_health(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Gets the players current food level + pub fn food_level(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Sets a metadata value in the implementing object's metadata store. - pub fn set_metadata( - &self, - metadata_key: impl Into, - new_metadata_value: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += "Lorg/bukkit/metadata/MetadataValue;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) - }); - args.push(val_2); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setMetadata", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns a list of previously set metadata values from the implementing - /// object's metadata store. - pub fn get_metadata( - &self, - metadata_key: impl Into, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += ")Ljava/util/List;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getMetadata", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::metadata::MetadataValue::from_raw( - &self.jni_ref(), - obj, - )?); - } - Ok(new_vec) - } - /// Tests to see whether the implementing object contains the given - /// metadata value in its metadata store. - pub fn has_metadata( - &self, - metadata_key: impl Into, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasMetadata", sig.as_str(), args); + .call_method(&self.jni_object(), "getFoodLevel", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Removes the given metadata value from the implementing object's - /// metadata store. - pub fn remove_metadata( - &self, - metadata_key: impl Into, - owning_plugin: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += "Lorg/bukkit/plugin/Plugin;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) - }); - args.push(val_2); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "removeMetadata", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.i()?) } - /// Sends this sender multiple messages - pub fn send_message( - &self, - sender: impl Into>, - messages: std::option::Option>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = messages { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "sendMessage", sig.as_str(), args); + /// Sets the players current food level + pub fn set_food_level(&self, value: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFoodLevel", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the name of this command sender - pub fn name(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/lang/String;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Gets the custom name on a mob or block. If there is no name this method - /// will return null. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn custom_name(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/lang/String;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCustomName", sig.as_str(), args); + /// Get the regeneration rate (1 health per x ticks) of + /// the HumanEntity when they have saturation and + /// their food level is {@literal >=} 20. Default is 10. + pub fn saturated_regen_rate(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSaturatedRegenRate", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(res.i()?) } - /// Sets a custom name on a mob or block. This name will be used in death - /// messages and can be sent to the client as a nameplate over the mob. - /// - /// Setting the name to null or an empty string will clear it. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn set_custom_name( - &self, - name: impl Into, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); - args.push(val_1); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setCustomName", sig.as_str(), args); + /// Set the regeneration rate (1 health per x ticks) of + /// the HumanEntity when they have saturation and + /// their food level is {@literal >=} 20. Default is 10. + /// Not affected if the world's difficulty is peaceful. + pub fn set_saturated_regen_rate(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSaturatedRegenRate", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; + /// Get the regeneration rate (1 health per x ticks) of + /// the HumanEntity when they have no saturation and + /// their food level is {@literal >=} 18. Default is 80. + pub fn unsaturated_regen_rate(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "getUnsaturatedRegenRate", sig.as_str(), - args, + vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for EnderDragonPart<'mc> { - fn into(self) -> crate::entity::ComplexEntityPart<'mc> { - crate::entity::ComplexEntityPart::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EnderDragonPart into crate::entity::ComplexEntityPart") - } -} -impl<'mc> Into> for EnderDragonPart<'mc> { - fn into(self) -> crate::entity::Damageable<'mc> { - crate::entity::Damageable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EnderDragonPart into crate::entity::Damageable") - } -} -#[repr(C)] -pub struct Ambient<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Ambient<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Ambient<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Ambient from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Ambient")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Ambient object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + Ok(res.i()?) } -} - -impl<'mc> Ambient<'mc> { - /// Instructs this Mob to set the specified LivingEntity as its target. - /// - /// Hostile creatures may attack their target, and friendly creatures may - /// follow their target. - pub fn set_target( - &self, - target: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) - }); + /// Get the regeneration rate (1 health per x ticks) of + /// the HumanEntity when they have no saturation and + /// their food level is {@literal >=} 18. Default is 80. + /// Not affected if the world's difficulty is peaceful. + pub fn set_unsaturated_regen_rate(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setTarget", + "setUnsaturatedRegenRate", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the current target of this Mob - pub fn target( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTarget", sig.as_str(), vec![]); + /// Get the starvation rate (1 health per x ticks) of + /// the HumanEntity. Default is 80. + pub fn starvation_rate(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getStarvationRate", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::LivingEntity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - /// Sets whether this mob is aware of its surroundings. - /// Unaware mobs will still move if pushed, attacked, etc. but will not move - /// or perform any actions on their own. Unaware mobs may also have other - /// unspecified behaviours disabled, such as drowning. - pub fn set_aware(&self, aware: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(aware.into()); + /// Get the starvation rate (1 health per x ticks) of + /// the HumanEntity. Default is 80. + pub fn set_starvation_rate(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setAware", + "setStarvationRate", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether this mob is aware of its surroundings. - /// Unaware mobs will still move if pushed, attacked, etc. but will not move - /// or perform any actions on their own. Unaware mobs may also have other - /// unspecified behaviours disabled, such as drowning. - pub fn is_aware(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isAware", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the {@link Sound} this mob makes while ambiently existing. This sound - /// may change depending on the current state of the entity, and may also - /// return null under specific conditions. This sound is not constant. - /// For instance, villagers will make different passive noises depending - /// on whether or not they are actively trading with a player, or make no - /// ambient noise while sleeping. - pub fn ambient_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAmbientSound", sig.as_str(), vec![]); + /// Gets the player's last death location. + pub fn last_death_location( + &self, + ) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Location;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLastDeathLocation", + sig.as_str(), + args, + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Ambient<'mc> { - fn into(self) -> crate::entity::Mob<'mc> { - crate::entity::Mob::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Ambient into crate::entity::Mob") - } -} -#[repr(C)] -pub struct Mob<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Mob<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Mob<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Mob from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Mob")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Mob object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + return Ok(None); } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } -} - -impl<'mc> Mob<'mc> { - /// Instructs this Mob to set the specified LivingEntity as its target. + /// Sets the player's last death location. /// - /// Hostile creatures may attack their target, and friendly creatures may - /// follow their target. - pub fn set_target( + /// Note: This data is updated in the player's client only when the + /// player respawns. + pub fn set_last_death_location( &self, - target: impl Into>, + location: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)V"); + let sig = String::from("(Lorg/bukkit/Location;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) + jni::objects::JObject::from_raw(location.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setTarget", + "setLastDeathLocation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the current target of this Mob - pub fn target( + /// Perform a firework boost. + /// + /// This method will only work such that {@link #isGliding()} is true and + /// the entity is actively gliding with an elytra. Additionally, the supplied + /// {@code fireworkItemStack} must be a firework rocket. The power of the boost + /// will directly correlate to {@link FireworkMeta#getPower()}. + pub fn firework_boost( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTarget", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::LivingEntity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Sets whether this mob is aware of its surroundings. - /// Unaware mobs will still move if pushed, attacked, etc. but will not move - /// or perform any actions on their own. Unaware mobs may also have other - /// unspecified behaviours disabled, such as drowning. - pub fn set_aware(&self, aware: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(aware.into()); + firework_item_stack: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Lorg/bukkit/entity/Firework;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(firework_item_stack.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setAware", + "fireworkBoost", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether this mob is aware of its surroundings. - /// Unaware mobs will still move if pushed, attacked, etc. but will not move - /// or perform any actions on their own. Unaware mobs may also have other - /// unspecified behaviours disabled, such as drowning. - pub fn is_aware(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isAware", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the {@link Sound} this mob makes while ambiently existing. This sound - /// may change depending on the current state of the entity, and may also - /// return null under specific conditions. This sound is not constant. - /// For instance, villagers will make different passive noises depending - /// on whether or not they are actively trading with a player, or make no - /// ambient noise while sleeping. - pub fn ambient_sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAmbientSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(Some(crate::entity::Firework::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } /// Gets the height of the living entity's eyes above its Location. pub fn get_eye_height(&self, ignore_pose: bool) -> Result> { @@ -94582,1312 +104208,1120 @@ impl<'mc> Mob<'mc> { sig += "Z"; let val_1 = jni::objects::JValueGen::Bool(gliding.into()); args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setGliding", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks to see if an entity is swimming. - pub fn is_swimming(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSwimming", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Makes entity start or stop swimming. - /// This may have unexpected results if the entity is not in water. - pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(swimming.into()); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setSwimming", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks to see if an entity is currently using the Riptide enchantment. - pub fn is_riptiding(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns whether this entity is slumbering. - pub fn is_sleeping(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSleeping", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets if the entity is climbing. - pub fn is_climbing(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isClimbing", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether an entity will have AI. - /// The entity will be completely unable to move if it has no AI. - pub fn set_ai(&self, ai: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(ai.into()); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setAI", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks whether an entity has AI. - /// The entity will be completely unable to move if it has no AI. - pub fn has_ai(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasAI", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Makes this entity attack the given entity with a melee attack. - /// Attack damage is calculated by the server from the attributes and - /// equipment of this mob, and knockback is applied to {@code target} as - /// appropriate. - pub fn attack( - &self, - target: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Entity;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "attack", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Makes this entity swing their main hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their main hand. - pub fn swing_main_hand(&self) -> Result<(), Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Makes this entity swing their off hand. - /// This method does nothing if this entity does not have an animation for - /// swinging their off hand. - pub fn swing_off_hand(&self) -> Result<(), Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Makes this entity flash red as if they were damaged. - pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "F"; - let val_1 = jni::objects::JValueGen::Float(yaw); - args.push(val_1); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "playHurtAnimation", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Set if this entity will be subject to collisions with other entities. - /// - /// Exemptions to this rule can be managed with - /// {@link #getCollidableExemptions()} - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not working for player collisions. This - /// method should therefore only be used to set the collision status of - /// non-player entities. - /// - /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in - /// combination with a {@link Scoreboard} and a {@link Team}. - pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(collidable.into()); - args.push(val_1); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setCollidable", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets if this entity is subject to collisions with other entities. - /// - /// Some entities might be exempted from the collidable rule of this entity. - /// Use {@link #getCollidableExemptions()} to get these. - /// - /// Please note that this method returns only the custom collidable state, - /// not whether the entity is non-collidable for other reasons such as being - /// dead. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in this flag not being accurate for player collisions. - /// This method should therefore only be used to check the collision status - /// of non-player entities. - /// - /// To check the collision behavior for a player, use - /// {@link Team.Option#COLLISION_RULE} in combination with a - /// {@link Scoreboard} and a {@link Team}. - pub fn is_collidable(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCollidable", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets a mutable set of UUIDs of the entities which are exempt from the - /// entity's collidable rule and which's collision with this entity will - /// behave the opposite of it. - /// - /// This set can be modified to add or remove exemptions. - /// - /// For example if collidable is true and an entity is in the exemptions set - /// then it will not collide with it. Similarly if collidable is false and an - /// entity is in this set then it will still collide with it. - /// - /// Note these exemptions are not (currently) persistent. - /// - /// Note that the client may predict the collision between itself and another - /// entity, resulting in those exemptions not being accurate for player - /// collisions. This method should therefore only be used to exempt - /// non-player entities. - /// - /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} - /// in combination with a {@link Scoreboard} and a {@link Team}. - pub fn collidable_exemptions( - &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/Set;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCollidableExemptions", - sig.as_str(), - args, - ); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns the value of the memory specified. - /// - /// Note that the value is null when the specific entity does not have that - /// value by default. - pub fn get_memory( - &self, - memory_key: impl Into>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/memory/MemoryKey;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")LT;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getMemory", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(res.l()?)) - } - /// Sets the value of the memory specified. - /// - /// Note that the value will not be persisted when the specific entity does - /// not have that value by default. - pub fn set_memory( - &self, - memory_key: impl Into>, - memory_value: jni::objects::JObject<'mc>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/memory/MemoryKey;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) - }); - args.push(val_1); - sig += "LT;"; - let val_2 = jni::objects::JValueGen::Object(memory_value); - args.push(val_2); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setMemory", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the {@link Sound} this entity will make when damaged. - pub fn hurt_sound(&self) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/Sound;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Get the {@link Sound} this entity will make on death. - pub fn death_sound(&self) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/Sound;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Get the {@link Sound} this entity will make when falling from the given - /// height (in blocks). The sound will often differ between either a small - /// or a big fall damage sound if the height exceeds 4 blocks. - pub fn get_fall_damage_sound( - &self, - fall_height: i32, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(fall_height); - args.push(val_1); - sig += ")Lorg/bukkit/Sound;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFallDamageSound", - sig.as_str(), - args, - ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity will make when falling from a small - /// height. - pub fn fall_damage_sound_small(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/Sound;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFallDamageSoundSmall", - sig.as_str(), - args, - ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity will make when falling from a large - /// height. - pub fn fall_damage_sound_big(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/Sound;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFallDamageSoundBig", - sig.as_str(), - args, - ); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity will make when drinking the given - /// {@link ItemStack}. - pub fn get_drinking_sound( - &self, - item_stack: impl Into>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Lorg/bukkit/Sound;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDrinkingSound", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link Sound} this entity will make when eating the given - /// {@link ItemStack}. - pub fn get_eating_sound( - &self, - item_stack: impl Into>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Lorg/bukkit/Sound;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEatingSound", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setGliding", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns true if this entity can breathe underwater and will not take - /// suffocation damage when its air supply reaches zero. - pub fn can_breathe_underwater(&self) -> Result> { + /// Checks to see if an entity is swimming. + pub fn is_swimming(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); sig += ")Z"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "canBreatheUnderwater", - sig.as_str(), - args, - ); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSwimming", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. - pub fn category( - &self, - ) -> Result, Box> { + /// Makes entity start or stop swimming. + /// This may have unexpected results if the entity is not in water. + pub fn set_swimming(&self, swimming: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(swimming.into()); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setSwimming", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks to see if an entity is currently riptiding. + pub fn is_riptiding(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); - sig += ")Lorg/bukkit/entity/EntityCategory;"; + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getCategory", sig.as_str(), args); + .call_method(&self.jni_object(), "isRiptiding", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets whether the entity is invisible or not. - pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { + /// Makes entity start or stop riptiding. + /// + /// Note: This does not damage attackable entities. + pub fn set_riptiding(&self, riptiding: bool) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(invisible.into()); + let val_1 = jni::objects::JValueGen::Bool(riptiding.into()); args.push(val_1); sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "setInvisible", sig.as_str(), args); + .call_method(&self.jni_object(), "setRiptiding", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the entity is invisible or not. - pub fn is_invisible(&self) -> Result> { + /// Returns whether this entity is slumbering. + pub fn is_sleeping(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isInvisible", sig.as_str(), args); + .call_method(&self.jni_object(), "isSleeping", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the specified attribute instance from the object. This instance will - /// be backed directly to the object and any changes will be visible at once. - pub fn get_attribute( - &self, - attribute: impl Into>, - ) -> Result>, Box> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAttribute", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Gets if the entity is climbing. + pub fn is_climbing(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isClimbing", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::attribute::AttributeInstance::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Deals the given amount of damage to this entity from a specified - /// {@link DamageSource}. - pub fn damage( - &self, - amount: f64, - damage_source: std::option::Option>>, - ) -> Result<(), Box> { + /// Sets whether an entity will have AI. + /// The entity will be completely unable to move if it has no AI. + pub fn set_ai(&self, ai: bool) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(amount); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(ai.into()); args.push(val_1); - if let Some(a) = damage_source { - sig += "Lorg/bukkit/damage/DamageSource;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "damage", sig.as_str(), args); + .call_method(&self.jni_object(), "setAI", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. - pub fn health(&self) -> Result> { - let sig = String::from("()D"); + /// Checks whether an entity has AI. + /// The entity will be completely unable to move if it has no AI. + pub fn has_ai(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is - /// dead. - pub fn set_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setHealth", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the entity's absorption amount. - pub fn absorption_amount(&self) -> Result> { - let sig = String::from("()D"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAbsorptionAmount", - sig.as_str(), - vec![], - ); + .call_method(&self.jni_object(), "hasAI", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Sets the entity's absorption amount. - /// - /// Note: The amount is capped to the value of - /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on - /// that attribute is currently unspecified and subject to change. - pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(amount); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAbsorptionAmount", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Makes this entity attack the given entity with a melee attack. + /// Attack damage is calculated by the server from the attributes and + /// equipment of this mob, and knockback is applied to {@code target} as + /// appropriate. + pub fn attack( + &self, + target: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Entity;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(target.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "attack", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the maximum health this entity has. - pub fn max_health(&self) -> Result> { - let sig = String::from("()D"); + /// Makes this entity swing their main hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their main hand. + pub fn swing_main_hand(&self) -> Result<(), Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - #[deprecated] - /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. - pub fn set_max_health(&self, health: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(health); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaxHealth", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "swingMainHand", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Resets the max health to the original amount. - pub fn reset_max_health(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Makes this entity swing their off hand. + /// This method does nothing if this entity does not have an animation for + /// swinging their off hand. + pub fn swing_off_hand(&self) -> Result<(), Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "swingOffHand", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Launches a {@link Projectile} from the ProjectileSource with an - /// initial velocity. - pub fn launch_projectile( - &self, - projectile: jni::objects::JClass<'mc>, - velocity: std::option::Option>>, - ) -> Result, Box> { + /// Makes this entity flash red as if they were damaged. + pub fn play_hurt_animation(&self, yaw: f32) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/lang/Class;"; - let val_1 = jni::objects::JValueGen::Object(projectile.into()); + sig += "F"; + let val_1 = jni::objects::JValueGen::Float(yaw); args.push(val_1); - if let Some(a) = velocity { - sig += "Lorg/bukkit/util/Vector;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")LT;"; + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) - } - /// Set the loot table for a container or entity. - /// - /// To remove a loot table use null. Do not use {@link LootTables#EMPTY} to - /// clear a LootTable. - pub fn set_loot_table( - &self, - table: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/loot/LootTable;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(table.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLootTable", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "playHurtAnimation", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the Loot Table attached to this block or entity. + /// Set if this entity will be subject to collisions with other entities. /// - /// If an block/entity does not have a loot table, this will return null, NOT - /// an empty loot table. - pub fn loot_table( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/loot/LootTable;"); + /// Exemptions to this rule can be managed with + /// {@link #getCollidableExemptions()} + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not working for player collisions. This + /// method should therefore only be used to set the collision status of + /// non-player entities. + /// + /// To control player collisions, use {@link Team.Option#COLLISION_RULE} in + /// combination with a {@link Scoreboard} and a {@link Team}. + pub fn set_collidable(&self, collidable: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(collidable.into()); + args.push(val_1); + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getLootTable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::loot::LootTable::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Set the seed used when this Loot Table generates loot. - pub fn set_seed(&self, seed: i64) -> Result<(), Box> { - let sig = String::from("(J)V"); - let val_1 = jni::objects::JValueGen::Long(seed); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSeed", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "setCollidable", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the Loot Table's seed. + /// Gets if this entity is subject to collisions with other entities. /// - /// The seed is used when generating loot. - pub fn seed(&self) -> Result> { - let sig = String::from("()J"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSeed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Mob<'mc> { - fn into(self) -> crate::entity::LivingEntity<'mc> { - crate::entity::LivingEntity::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Mob into crate::entity::LivingEntity") - } -} -impl<'mc> Into> for Mob<'mc> { - fn into(self) -> crate::loot::Lootable<'mc> { - crate::loot::Lootable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Mob into crate::loot::Lootable") - } -} -#[repr(C)] -pub struct Axolotl<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Axolotl<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Axolotl<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Axolotl from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Axolotl")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Axolotl object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Axolotl<'mc> { - /// Gets if this axolotl is playing dead. - /// An axolotl may play dead when it is damaged underwater. - pub fn is_playing_dead(&self) -> Result> { - let sig = String::from("()Z"); + /// Some entities might be exempted from the collidable rule of this entity. + /// Use {@link #getCollidableExemptions()} to get these. + /// + /// Please note that this method returns only the custom collidable state, + /// not whether the entity is non-collidable for other reasons such as being + /// dead. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in this flag not being accurate for player collisions. + /// This method should therefore only be used to check the collision status + /// of non-player entities. + /// + /// To check the collision behavior for a player, use + /// {@link Team.Option#COLLISION_RULE} in combination with a + /// {@link Scoreboard} and a {@link Team}. + pub fn is_collidable(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "isPlayingDead", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCollidable", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets if this axolotl is playing dead. - /// An axolotl may play dead when it is damaged underwater. - pub fn set_playing_dead(&self, playing_dead: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(playing_dead.into()); + /// Gets a mutable set of UUIDs of the entities which are exempt from the + /// entity's collidable rule and which's collision with this entity will + /// behave the opposite of it. + /// + /// This set can be modified to add or remove exemptions. + /// + /// For example if collidable is true and an entity is in the exemptions set + /// then it will not collide with it. Similarly if collidable is false and an + /// entity is in this set then it will still collide with it. + /// + /// Note these exemptions are not (currently) persistent. + /// + /// Note that the client may predict the collision between itself and another + /// entity, resulting in those exemptions not being accurate for player + /// collisions. This method should therefore only be used to exempt + /// non-player entities. + /// + /// To exempt collisions for a player, use {@link Team.Option#COLLISION_RULE} + /// in combination with a {@link Scoreboard} and a {@link Team}. + pub fn collidable_exemptions( + &self, + ) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/util/Set;"; let res = self.jni_ref().call_method( &self.jni_object(), - "setPlayingDead", + "getCollidableExemptions", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the variant of this axolotl. - pub fn variant( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Axolotl/Variant;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::AxolotlVariant::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Set the variant of this axolotl. - pub fn set_variant( + /// Returns the value of the memory specified. + /// + /// Note that the value is null when the specific entity does not have that + /// value by default. + pub fn get_memory( &self, - variant: impl Into>, + memory_key: impl Into>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/memory/MemoryKey;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")LT;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getMemory", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) + } + /// Sets the value of the memory specified. + /// + /// Note that the value will not be persisted when the specific entity does + /// not have that value by default. + pub fn set_memory( + &self, + memory_key: impl Into>, + memory_value: jni::objects::JObject<'mc>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Axolotl/Variant;)V"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/memory/MemoryKey;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(variant.into().jni_object().clone()) + jni::objects::JObject::from_raw(memory_key.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setVariant", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + sig += "LT;"; + let val_2 = jni::objects::JValueGen::Object(memory_value); + args.push(val_2); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setMemory", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn breed_cause( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/UUID;"); + /// Get the {@link Sound} this entity will make when damaged. + pub fn hurt_sound(&self) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getHurtSound", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Set the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn set_breed_cause( + /// Get the {@link Sound} this entity will make on death. + pub fn death_sound(&self) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Sound;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDeathSound", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Get the {@link Sound} this entity will make when falling from the given + /// height (in blocks). The sound will often differ between either a small + /// or a big fall damage sound if the height exceeds 4 blocks. + pub fn get_fall_damage_sound( &self, - uuid: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/UUID;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) - }); + fall_height: i32, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(fall_height); + args.push(val_1); + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref().call_method( &self.jni_object(), - "setBreedCause", + "getFallDamageSound", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get whether or not this entity is in love mode and will produce - /// offspring with another entity in love mode. Will return true if - /// and only if {@link #getLoveModeTicks()} is greater than 0. - pub fn is_love_mode(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get the amount of ticks remaining for this entity in love mode. - /// If the entity is not in love mode, 0 will be returned. - pub fn love_mode_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Get the {@link Sound} this entity will make when falling from a small + /// height. + pub fn fall_damage_sound_small(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref().call_method( &self.jni_object(), - "getLoveModeTicks", + "getFallDamageSoundSmall", sig.as_str(), - vec![], + args, ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the amount of ticks for which this entity should be in love mode. - /// Setting the love mode ticks to 600 is the equivalent of a player - /// feeding the entity their breeding item of choice. - pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Get the {@link Sound} this entity will make when falling from a large + /// height. + pub fn fall_damage_sound_big(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Sound;"; let res = self.jni_ref().call_method( &self.jni_object(), - "setLoveModeTicks", + "getFallDamageSoundBig", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Check if the provided ItemStack is the correct item used for breeding - /// this entity.. - pub fn is_breed_item( + /// Get the {@link Sound} this entity will make when drinking the given + /// {@link ItemStack}. + pub fn get_drinking_sound( &self, - material: impl Into>, - ) -> Result> { + item_stack: impl Into>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; + sig += "Lorg/bukkit/inventory/ItemStack;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Lorg/bukkit/Sound;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDrinkingSound", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link Sound} this entity will make when eating the given + /// {@link ItemStack}. + pub fn get_eating_sound( + &self, + item_stack: impl Into>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) }); args.push(val_1); + sig += ")Lorg/bukkit/Sound;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEatingSound", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns true if this entity can breathe underwater and will not take + /// suffocation damage when its air supply reaches zero. + pub fn can_breathe_underwater(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); sig += ")Z"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "canBreatheUnderwater", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs. + pub fn category( + &self, + ) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/entity/EntityCategory;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); + .call_method(&self.jni_object(), "getCategory", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::EntityCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Lock the age of the animal, setting this will prevent the animal from - /// maturing or getting ready for mating. - pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { + /// Sets whether the entity is invisible or not. + pub fn set_invisible(&self, invisible: bool) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(lock.into()); + let val_1 = jni::objects::JValueGen::Bool(invisible.into()); args.push(val_1); sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setAgeLock", sig.as_str(), args); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setInvisible", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the current agelock. - pub fn age_lock(&self) -> Result> { + /// Gets whether the entity is invisible or not. + pub fn is_invisible(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), args); + .call_method(&self.jni_object(), "isInvisible", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Return the ability to breed of the animal. - pub fn can_breed(&self) -> Result> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "canBreed", sig.as_str(), args); + /// Gets the specified attribute instance from the object. This instance will + /// be backed directly to the object and any changes will be visible at once. + pub fn get_attribute( + &self, + attribute: impl Into>, + ) -> Result>, Box> { + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;)Lorg/bukkit/attribute/AttributeInstance;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAttribute", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::attribute::AttributeInstance::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Set breedability of the animal, if the animal is a baby and set to - /// breed it will instantly grow up. - pub fn set_breed(&self, breed: bool) -> Result<(), Box> { + /// Deals the given amount of damage to this entity from a specified + /// {@link DamageSource}. + pub fn damage( + &self, + amount: f64, + damage_source: std::option::Option>>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(breed.into()); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(amount); args.push(val_1); + if let Some(a) = damage_source { + sig += "Lorg/bukkit/damage/DamageSource;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "setBreed", sig.as_str(), args); + .call_method(&self.jni_object(), "damage", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Axolotl<'mc> { - fn into(self) -> crate::entity::Animals<'mc> { - crate::entity::Animals::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Axolotl into crate::entity::Animals") - } -} -pub enum AxolotlVariant<'mc> {} -impl<'mc> std::fmt::Display for AxolotlVariant<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + /// Gets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is dead. + pub fn health(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHealth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } -} - -impl<'mc> AxolotlVariant<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/entity/Axolotl/Variant"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/entity/Axolotl/Variant;", + /// Sets the entity's health from 0 to {@link #getMaxHealth()}, where 0 is + /// dead. + pub fn set_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setHealth", + sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct AxolotlVariantStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for AxolotlVariant<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for AxolotlVariant<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate AxolotlVariant from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Axolotl/Variant")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a AxolotlVariant object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for AxolotlVariantStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + self.jni_ref().translate_error(res)?; + Ok(()) } -} -impl<'mc> JNIInstantiatable<'mc> for AxolotlVariantStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate AxolotlVariantStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/Axolotl/Variant")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a AxolotlVariantStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Gets the entity's absorption amount. + pub fn absorption_amount(&self) -> Result> { + let sig = String::from("()D"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAbsorptionAmount", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } -} - -impl<'mc> AxolotlVariantStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Axolotl/Variant;"); - let cls = jni.find_class("org/bukkit/entity/Axolotl/Variant"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::AxolotlVariant::from_raw(&jni, obj) + /// Sets the entity's absorption amount. + /// + /// Note: The amount is capped to the value of + /// {@link Attribute#GENERIC_MAX_ABSORPTION}. The effect of this method on + /// that attribute is currently unspecified and subject to change. + pub fn set_absorption_amount(&self, amount: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(amount); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAbsorptionAmount", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + #[deprecated] + /// Gets the maximum health this entity has. + pub fn max_health(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxHealth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } -} -#[repr(C)] -pub struct PolarBear<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PolarBear<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + #[deprecated] + /// Sets the maximum health this entity can have.If the health of the entity is above the value provided it will be set to that value.Note: An entity with a health bar ({@link Player}, {@link EnderDragon}, {@link Wither}, etc...} will have their bar scaled accordingly. + pub fn set_max_health(&self, health: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(health); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaxHealth", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + #[deprecated] + /// Resets the max health to the original amount. + pub fn reset_max_health(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "resetMaxHealth", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -impl<'mc> JNIInstantiatable<'mc> for PolarBear<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate PolarBear from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/entity/PolarBear")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PolarBear object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + /// Launches a {@link Projectile} from the ProjectileSource with an + /// initial velocity. + pub fn launch_projectile( + &self, + projectile: jni::objects::JClass<'mc>, + velocity: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(projectile.into()); + args.push(val_1); + if let Some(a) = velocity { + sig += "Lorg/bukkit/util/Vector;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); } + sig += ")LT;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "launchProjectile", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) } -} - -impl<'mc> PolarBear<'mc> { - /// Get the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn breed_cause( + /// Returns the UUID of this player + pub fn unique_id( &self, - ) -> Result>, Box> { + ) -> Result, Box> { let sig = String::from("()Ljava/util/UUID;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBreedCause", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(blackboxmc_java::util::JavaUUID::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the UUID of the entity that caused this entity to enter the - /// {@link #canBreed()} state. - pub fn set_breed_cause( + /// Tests to see of a Conversable object is actively engaged in a + /// conversation. + pub fn is_conversing(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isConversing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Accepts input into the active conversation. If no conversation is in + /// progress, this method does nothing. + pub fn accept_conversation_input( &self, - uuid: impl Into>, + input: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/UUID;)V"); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(input.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "acceptConversationInput", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Enters into a dialog with a Conversation object. + pub fn begin_conversation( + &self, + conversation: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/conversations/Conversation;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) + jni::objects::JObject::from_raw(conversation.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBreedCause", + "beginConversation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Abandons an active conversation. + pub fn abandon_conversation( + &self, + conversation: impl Into>, + details: std::option::Option< + impl Into>, + >, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/conversations/Conversation;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(conversation.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = details { + sig += "Lorg/bukkit/conversations/ConversationAbandonedEvent;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "abandonConversation", + sig.as_str(), + args, + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get whether or not this entity is in love mode and will produce - /// offspring with another entity in love mode. Will return true if - /// and only if {@link #getLoveModeTicks()} is greater than 0. - pub fn is_love_mode(&self) -> Result> { + /// Checks if this player is currently online + pub fn is_online(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isLoveMode", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isOnline", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get the amount of ticks remaining for this entity in love mode. - /// If the entity is not in love mode, 0 will be returned. - pub fn love_mode_ticks(&self) -> Result> { - let sig = String::from("()I"); + /// Returns the name of this player + /// + /// Names are no longer unique past a single game session. For persistent storage + /// it is recommended that you use {@link #getUniqueId()} instead. + pub fn name(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Gets a copy of the player's profile. + /// + /// If the player is online, the returned profile will be complete. + /// Otherwise, only the unique id is guaranteed to be present. You can use + /// {@link PlayerProfile#update()} to complete the returned profile. + pub fn player_profile( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/profile/PlayerProfile;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLoveModeTicks", + "getPlayerProfile", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::profile::PlayerProfile::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the amount of ticks for which this entity should be in love mode. - /// Setting the love mode ticks to 600 is the equivalent of a player - /// feeding the entity their breeding item of choice. - pub fn set_love_mode_ticks(&self, ticks: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Checks if this player has had their profile banned. + pub fn is_banned(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isBanned", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks if this player is whitelisted or not + pub fn is_whitelisted(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isWhitelisted", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets if this player is whitelisted or not + pub fn set_whitelisted(&self, value: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(value.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLoveModeTicks", + "setWhitelisted", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check if the provided ItemStack is the correct item used for breeding - /// this entity.. - pub fn is_breed_item( - &self, - material: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Z"; + /// Gets a {@link Player} object that this represents, if there is one + /// + /// If the player is online, this will return that player. Otherwise, + /// it will return null. + pub fn player(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isBreedItem", sig.as_str(), args); + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Player::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the first date and time that this player was witnessed on this + /// server. + /// + /// If the player has never played before, this will return 0. Otherwise, + /// it will be the amount of milliseconds since midnight, January 1, 1970 + /// UTC. + pub fn first_played(&self) -> Result> { + let sig = String::from("()J"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFirstPlayed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.j()?) + } + /// Gets the last date and time that this player was witnessed on this + /// server. + /// + /// If the player has never played before, this will return 0. Otherwise, + /// it will be the amount of milliseconds since midnight, January 1, 1970 + /// UTC. + pub fn last_played(&self) -> Result> { + let sig = String::from("()J"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLastPlayed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.j()?) + } + /// Checks if this player has played on this server before. + pub fn has_played_before(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasPlayedBefore", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Lock the age of the animal, setting this will prevent the animal from - /// maturing or getting ready for mating. - pub fn set_age_lock(&self, lock: bool) -> Result<(), Box> { + /// Increments the given statistic for this player for the given entity. + pub fn increment_statistic( + &self, + statistic: impl Into>, + entity_type: std::option::Option>>, + amount: std::option::Option, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(lock.into()); + sig += "Lorg/bukkit/Statistic;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(statistic.into().jni_object().clone()) + }); args.push(val_1); + if let Some(a) = entity_type { + sig += "Lorg/bukkit/entity/EntityType;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + if let Some(a) = amount { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setAgeLock", sig.as_str(), args); + let res = self.jni_ref().call_method( + &self.jni_object(), + "incrementStatistic", + sig.as_str(), + args, + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the current agelock. - pub fn age_lock(&self) -> Result> { - let args = Vec::new(); + /// Decrements the given statistic for this player for the given entity. + pub fn decrement_statistic( + &self, + statistic: impl Into>, + entity_type: std::option::Option>>, + amount: std::option::Option, + ) -> Result<(), Box> { + let mut args = Vec::new(); let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getAgeLock", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + sig += "Lorg/bukkit/Statistic;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(statistic.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = entity_type { + sig += "Lorg/bukkit/entity/EntityType;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + if let Some(a) = amount { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + sig += ")V"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "decrementStatistic", + sig.as_str(), + args, + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Return the ability to breed of the animal. - pub fn can_breed(&self) -> Result> { - let args = Vec::new(); + /// Sets the given statistic for this player for the given entity. + pub fn set_statistic( + &self, + statistic: impl Into>, + entity_type: impl Into>, + new_value: std::option::Option, + ) -> Result<(), Box> { + let mut args = Vec::new(); let mut sig = String::from("("); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "canBreed", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + sig += "Lorg/bukkit/Statistic;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(statistic.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Lorg/bukkit/entity/EntityType;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(entity_type.into().jni_object().clone()) + }); + args.push(val_2); + if let Some(a) = new_value { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setStatistic", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Set breedability of the animal, if the animal is a baby and set to - /// breed it will instantly grow up. - pub fn set_breed(&self, breed: bool) -> Result<(), Box> { + /// Gets the value of the given statistic for this player. + pub fn get_statistic( + &self, + statistic: impl Into>, + entity_type: std::option::Option>>, + ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(breed.into()); + sig += "Lorg/bukkit/Statistic;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(statistic.into().jni_object().clone()) + }); args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setBreed", sig.as_str(), args); + if let Some(a) = entity_type { + sig += "Lorg/bukkit/entity/EntityType;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")I"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getStatistic", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the player's current location. + pub fn location(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Sends this recipient a Plugin Message on the specified outgoing + /// channel. + /// + /// The message may not be larger than {@link Messenger#MAX_MESSAGE_SIZE} + /// bytes, and the plugin must be registered to send messages on the + /// specified channel. + pub fn send_plugin_message( + &self, + source: impl Into>, + channel: impl Into, + message: i8, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;Ljava/lang/String;B)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(source.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(channel.into())?, + )); + let val_3 = jni::objects::JValueGen::Byte(message); + let res = self.jni_ref().call_method( + &self.jni_object(), + "sendPluginMessage", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); self.jni_ref().translate_error(res)?; Ok(()) } + /// Gets a set containing all the Plugin Channels that this client is + /// listening on. + pub fn listening_plugin_channels( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getListeningPluginChannels", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PolarBear<'mc> { - fn into(self) -> crate::entity::Animals<'mc> { - crate::entity::Animals::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PolarBear into crate::entity::Animals") +impl<'mc> Into> for Player<'mc> { + fn into(self) -> crate::entity::HumanEntity<'mc> { + crate::entity::HumanEntity::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Player into crate::entity::HumanEntity") + } +} +impl<'mc> Into> for Player<'mc> { + fn into(self) -> crate::conversations::Conversable<'mc> { + crate::conversations::Conversable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Player into crate::conversations::Conversable") + } +} +impl<'mc> Into> for Player<'mc> { + fn into(self) -> crate::OfflinePlayer<'mc> { + crate::OfflinePlayer::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Player into crate::OfflinePlayer") + } +} +impl<'mc> Into> for Player<'mc> { + fn into(self) -> crate::plugin::messaging::PluginMessageRecipient<'mc> { + crate::plugin::messaging::PluginMessageRecipient::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Player into crate::plugin::messaging::PluginMessageRecipient") } } #[repr(C)] @@ -96773,7 +106207,7 @@ impl<'mc> AbstractSkeleton<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks to see if an entity is currently using the Riptide enchantment. + /// Checks to see if an entity is currently riptiding. pub fn is_riptiding(&self) -> Result> { let args = Vec::new(); let mut sig = String::from("("); @@ -96784,6 +106218,22 @@ impl<'mc> AbstractSkeleton<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } + /// Makes entity start or stop riptiding. + /// + /// Note: This does not damage attackable entities. + pub fn set_riptiding(&self, riptiding: bool) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(riptiding.into()); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setRiptiding", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } /// Returns whether this entity is slumbering. pub fn is_sleeping(&self) -> Result> { let args = Vec::new(); diff --git a/blackboxmc-rs-bukkit/src/event/block/mod.rs b/blackboxmc-rs-bukkit/src/event/block/mod.rs index edd196a..20c8f3c 100644 --- a/blackboxmc-rs-bukkit/src/event/block/mod.rs +++ b/blackboxmc-rs-bukkit/src/event/block/mod.rs @@ -3,12 +3,12 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] -pub struct InventoryBlockStartEvent<'mc>( +pub struct NotePlayEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for InventoryBlockStartEvent<'mc> { +impl<'mc> JNIRaw<'mc> for NotePlayEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -16,22 +16,18 @@ impl<'mc> JNIRaw<'mc> for InventoryBlockStartEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for InventoryBlockStartEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for NotePlayEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate InventoryBlockStartEvent from null object." - ) - .into()); + return Err(eyre::eyre!("Tried to instantiate NotePlayEvent from null object.").into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/block/InventoryBlockStartEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/NotePlayEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a InventoryBlockStartEvent object, got {}", + "Invalid argument passed. Expected a NotePlayEvent object, got {}", name ) .into()) @@ -41,21 +37,25 @@ impl<'mc> JNIInstantiatable<'mc> for InventoryBlockStartEvent<'mc> { } } -impl<'mc> InventoryBlockStartEvent<'mc> { +impl<'mc> NotePlayEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, block: impl Into>, - source: impl Into>, - ) -> Result, Box> - { - let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/inventory/ItemStack;)V"); + instrument: impl Into>, + note: impl Into>, + ) -> Result, Box> { + let sig = + String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/Instrument;Lorg/bukkit/Note;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(block.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(source.into().jni_object().clone()) + jni::objects::JObject::from_raw(instrument.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/block/InventoryBlockStartEvent"); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(note.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/block/NotePlayEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -63,22 +63,94 @@ impl<'mc> InventoryBlockStartEvent<'mc> { vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::block::InventoryBlockStartEvent::from_raw(&jni, res) + crate::event::block::NotePlayEvent::from_raw(&jni, res) } - /// Gets the source ItemStack for this event. - pub fn source(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the {@link Instrument} to be used. + pub fn instrument(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Instrument;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInstrument", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Instrument::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the {@link Note} to be played. + pub fn note(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Note;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getSource", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getNote", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + crate::Note::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } + #[deprecated] + /// Overrides the {@link Instrument} to be used. + pub fn set_instrument( + &self, + instrument: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Instrument;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(instrument.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setInstrument", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Overrides the {@link Note} to be played. + pub fn set_note( + &self, + note: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Note;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(note.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setNote", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -95,14 +167,14 @@ impl<'mc> InventoryBlockStartEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/InventoryBlockStartEvent"); + let cls = jni.find_class("org/bukkit/event/block/NotePlayEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getSource', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['isCancelled', 'setCancelled', 'getInstrument', 'getNote', 'setInstrument', 'setNote', 'getHandlers', 'getHandlerList']) /// Gets the block involved in this event. pub fn block(&self) -> Result, Box> { let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { @@ -117,20 +189,25 @@ impl<'mc> InventoryBlockStartEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for InventoryBlockStartEvent<'mc> { +impl<'mc> Into> for NotePlayEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting NotePlayEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for NotePlayEvent<'mc> { fn into(self) -> crate::event::block::BlockEvent<'mc> { - crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting InventoryBlockStartEvent into crate::event::block::BlockEvent", - ) + crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting NotePlayEvent into crate::event::block::BlockEvent") } } #[repr(C)] -pub struct BlockFertilizeEvent<'mc>( +pub struct CauldronLevelChangeEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockFertilizeEvent<'mc> { +impl<'mc> JNIRaw<'mc> for CauldronLevelChangeEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -138,21 +215,22 @@ impl<'mc> JNIRaw<'mc> for BlockFertilizeEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockFertilizeEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CauldronLevelChangeEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate BlockFertilizeEvent from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate CauldronLevelChangeEvent from null object." + ) + .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/block/BlockFertilizeEvent")?; + env.validate_name(&obj, "org/bukkit/event/block/CauldronLevelChangeEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockFertilizeEvent object, got {}", + "Invalid argument passed. Expected a CauldronLevelChangeEvent object, got {}", name ) .into()) @@ -162,33 +240,29 @@ impl<'mc> JNIInstantiatable<'mc> for BlockFertilizeEvent<'mc> { } } -impl<'mc> BlockFertilizeEvent<'mc> { +impl<'mc> CauldronLevelChangeEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - the_block: impl Into>, - player: impl Into>, - blocks: Vec>, - ) -> Result, Box> { - let sig = - String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/entity/Player;Ljava/util/List;)V"); + block: impl Into>, + entity: impl Into>, + reason: impl Into>, + new_block: impl Into>, + ) -> Result, Box> + { + let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/entity/Entity;Lorg/bukkit/event/block/CauldronLevelChangeEvent/ChangeReason;Lorg/bukkit/block/BlockState;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(the_block.into().jni_object().clone()) + jni::objects::JObject::from_raw(block.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) }); - let raw_val_3 = jni.new_object("java/util/ArrayList", "()V", vec![])?; - for v in blocks { - let map_val_0 = jni::objects::JValueGen::Object(v); - jni.call_method( - &raw_val_3, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_3 = jni::objects::JValueGen::Object(raw_val_3); - let cls = jni.find_class("org/bukkit/event/block/BlockFertilizeEvent"); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(reason.into().jni_object().clone()) + }); + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(new_block.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/block/CauldronLevelChangeEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -197,207 +271,88 @@ impl<'mc> BlockFertilizeEvent<'mc> { jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::block::BlockFertilizeEvent::from_raw(&jni, res) + crate::event::block::CauldronLevelChangeEvent::from_raw(&jni, res) } - /// Gets the player that triggered the fertilization. - pub fn player(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Player;"); + /// Get entity which did this. May be null. + pub fn entity(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Player::from_raw( + Ok(Some(crate::entity::Entity::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Gets a list of all blocks changed by the fertilization. - pub fn blocks(&self) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + + pub fn reason( + &self, + ) -> Result< + crate::event::block::CauldronLevelChangeEventChangeReason<'mc>, + Box, + > { + let sig = String::from("()Lorg/bukkit/event/block/CauldronLevelChangeEvent/ChangeReason;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getBlocks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getReason", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::BlockState::from_raw(&self.0, obj)?); - } - Ok(new_vec) + crate::event::block::CauldronLevelChangeEventChangeReason::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + ) } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the new state of the cauldron. + pub fn new_state(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockState;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getNewState", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_cancelled(&self, cancelled: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancelled.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + #[deprecated] + /// Gets the old level of the cauldron. + pub fn old_level(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getOldLevel", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn handler_list( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/BlockFertilizeEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getPlayer', 'getBlocks', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) - /// Gets the block involved in this event. - pub fn block(&self) -> Result, Box> { - let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockEvent = temp_clone.into(); - real.block() - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for BlockFertilizeEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockFertilizeEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for BlockFertilizeEvent<'mc> { - fn into(self) -> crate::event::block::BlockEvent<'mc> { - crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockFertilizeEvent into crate::event::block::BlockEvent") - } -} -#[repr(C)] -pub struct BlockShearEntityEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for BlockShearEntityEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + Ok(res.i()?) } -} -impl<'mc> JNIInstantiatable<'mc> for BlockShearEntityEvent<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate BlockShearEntityEvent from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/block/BlockShearEntityEvent")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockShearEntityEvent object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + #[deprecated] + /// Gets the new level of the cauldron. + pub fn new_level(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getNewLevel", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} - -impl<'mc> BlockShearEntityEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - dispenser: impl Into>, - sheared: impl Into>, - tool: impl Into>, - ) -> Result, Box> { - let sig = String::from( - "(Lorg/bukkit/block/Block;Lorg/bukkit/entity/Entity;Lorg/bukkit/inventory/ItemStack;)V", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(dispenser.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sheared.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tool.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/event/block/BlockShearEntityEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, + #[deprecated] + /// Sets the new level of the cauldron. + pub fn set_new_level(&self, new_level: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(new_level); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setNewLevel", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error_no_gen(res)?; - crate::event::block::BlockShearEntityEvent::from_raw(&jni, res) - } - /// Gets the entity that was sheared. - pub fn entity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the item used to shear this sheep. - pub fn tool(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn is_cancelled(&self) -> Result> { @@ -437,14 +392,14 @@ impl<'mc> BlockShearEntityEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/BlockShearEntityEvent"); + let cls = jni.find_class("org/bukkit/event/block/CauldronLevelChangeEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getEntity', 'getTool', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getEntity', 'getReason', 'getNewState', 'getOldLevel', 'getNewLevel', 'setNewLevel', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) /// Gets the block involved in this event. pub fn block(&self) -> Result, Box> { let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { @@ -459,37 +414,102 @@ impl<'mc> BlockShearEntityEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockShearEntityEvent<'mc> { +impl<'mc> Into> for CauldronLevelChangeEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockShearEntityEvent into crate::event::Cancellable") + .expect("Error converting CauldronLevelChangeEvent into crate::event::Cancellable") } } -impl<'mc> Into> for BlockShearEntityEvent<'mc> { +impl<'mc> Into> for CauldronLevelChangeEvent<'mc> { fn into(self) -> crate::event::block::BlockEvent<'mc> { - crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockShearEntityEvent into crate::event::block::BlockEvent") + crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting CauldronLevelChangeEvent into crate::event::block::BlockEvent", + ) } } -pub enum Action<'mc> {} -impl<'mc> std::fmt::Display for Action<'mc> { +pub enum CauldronLevelChangeEventChangeReason<'mc> { + BucketFill { + inner: CauldronLevelChangeEventChangeReasonStruct<'mc>, + }, + BucketEmpty { + inner: CauldronLevelChangeEventChangeReasonStruct<'mc>, + }, + BottleFill { + inner: CauldronLevelChangeEventChangeReasonStruct<'mc>, + }, + BottleEmpty { + inner: CauldronLevelChangeEventChangeReasonStruct<'mc>, + }, + BannerWash { + inner: CauldronLevelChangeEventChangeReasonStruct<'mc>, + }, + ArmorWash { + inner: CauldronLevelChangeEventChangeReasonStruct<'mc>, + }, + ShulkerWash { + inner: CauldronLevelChangeEventChangeReasonStruct<'mc>, + }, + Extinguish { + inner: CauldronLevelChangeEventChangeReasonStruct<'mc>, + }, + Evaporate { + inner: CauldronLevelChangeEventChangeReasonStruct<'mc>, + }, + NaturalFill { + inner: CauldronLevelChangeEventChangeReasonStruct<'mc>, + }, + Unknown { + inner: CauldronLevelChangeEventChangeReasonStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for CauldronLevelChangeEventChangeReason<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + CauldronLevelChangeEventChangeReason::BucketFill { .. } => f.write_str("BUCKET_FILL"), + CauldronLevelChangeEventChangeReason::BucketEmpty { .. } => f.write_str("BUCKET_EMPTY"), + CauldronLevelChangeEventChangeReason::BottleFill { .. } => f.write_str("BOTTLE_FILL"), + CauldronLevelChangeEventChangeReason::BottleEmpty { .. } => f.write_str("BOTTLE_EMPTY"), + CauldronLevelChangeEventChangeReason::BannerWash { .. } => f.write_str("BANNER_WASH"), + CauldronLevelChangeEventChangeReason::ArmorWash { .. } => f.write_str("ARMOR_WASH"), + CauldronLevelChangeEventChangeReason::ShulkerWash { .. } => f.write_str("SHULKER_WASH"), + CauldronLevelChangeEventChangeReason::Extinguish { .. } => f.write_str("EXTINGUISH"), + CauldronLevelChangeEventChangeReason::Evaporate { .. } => f.write_str("EVAPORATE"), + CauldronLevelChangeEventChangeReason::NaturalFill { .. } => f.write_str("NATURAL_FILL"), + CauldronLevelChangeEventChangeReason::Unknown { .. } => f.write_str("UNKNOWN"), + } + } +} +impl<'mc> std::ops::Deref for CauldronLevelChangeEventChangeReason<'mc> { + type Target = CauldronLevelChangeEventChangeReasonStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + CauldronLevelChangeEventChangeReason::BucketFill { inner } => inner, + CauldronLevelChangeEventChangeReason::BucketEmpty { inner } => inner, + CauldronLevelChangeEventChangeReason::BottleFill { inner } => inner, + CauldronLevelChangeEventChangeReason::BottleEmpty { inner } => inner, + CauldronLevelChangeEventChangeReason::BannerWash { inner } => inner, + CauldronLevelChangeEventChangeReason::ArmorWash { inner } => inner, + CauldronLevelChangeEventChangeReason::ShulkerWash { inner } => inner, + CauldronLevelChangeEventChangeReason::Extinguish { inner } => inner, + CauldronLevelChangeEventChangeReason::Evaporate { inner } => inner, + CauldronLevelChangeEventChangeReason::NaturalFill { inner } => inner, + CauldronLevelChangeEventChangeReason::Unknown { inner } => inner, + } } } -impl<'mc> Action<'mc> { +impl<'mc> CauldronLevelChangeEventChangeReason<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/event/block/Action"); + let cls = env.find_class("org/bukkit/event/block/CauldronLevelChangeEvent/ChangeReason"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/event/block/Action;", + "(Ljava/lang/String;)Lorg/bukkit/event/block/CauldronLevelChangeEvent/ChangeReason;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -501,40 +521,124 @@ impl<'mc> Action<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "BUCKET_FILL" => Ok(CauldronLevelChangeEventChangeReason::BucketFill { + inner: CauldronLevelChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + "BUCKET_EMPTY" => Ok(CauldronLevelChangeEventChangeReason::BucketEmpty { + inner: CauldronLevelChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + "BOTTLE_FILL" => Ok(CauldronLevelChangeEventChangeReason::BottleFill { + inner: CauldronLevelChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + "BOTTLE_EMPTY" => Ok(CauldronLevelChangeEventChangeReason::BottleEmpty { + inner: CauldronLevelChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + "BANNER_WASH" => Ok(CauldronLevelChangeEventChangeReason::BannerWash { + inner: CauldronLevelChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + "ARMOR_WASH" => Ok(CauldronLevelChangeEventChangeReason::ArmorWash { + inner: CauldronLevelChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + "SHULKER_WASH" => Ok(CauldronLevelChangeEventChangeReason::ShulkerWash { + inner: CauldronLevelChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + "EXTINGUISH" => Ok(CauldronLevelChangeEventChangeReason::Extinguish { + inner: CauldronLevelChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + "EVAPORATE" => Ok(CauldronLevelChangeEventChangeReason::Evaporate { + inner: CauldronLevelChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + "NATURAL_FILL" => Ok(CauldronLevelChangeEventChangeReason::NaturalFill { + inner: CauldronLevelChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(CauldronLevelChangeEventChangeReason::Unknown { + inner: CauldronLevelChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct ActionStruct<'mc>( +pub struct CauldronLevelChangeEventChangeReasonStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Action<'mc> { +impl<'mc> JNIRaw<'mc> for CauldronLevelChangeEventChangeReason<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::BucketFill { inner } => inner.0.clone(), + Self::BucketEmpty { inner } => inner.0.clone(), + Self::BottleFill { inner } => inner.0.clone(), + Self::BottleEmpty { inner } => inner.0.clone(), + Self::BannerWash { inner } => inner.0.clone(), + Self::ArmorWash { inner } => inner.0.clone(), + Self::ShulkerWash { inner } => inner.0.clone(), + Self::Extinguish { inner } => inner.0.clone(), + Self::Evaporate { inner } => inner.0.clone(), + Self::NaturalFill { inner } => inner.0.clone(), + Self::Unknown { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::BucketFill { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BucketEmpty { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BottleFill { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BottleEmpty { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BannerWash { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ArmorWash { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ShulkerWash { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Extinguish { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Evaporate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NaturalFill { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Unknown { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for Action<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CauldronLevelChangeEventChangeReason<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Action from null object.").into()); + return Err(eyre::eyre!( + "Tried to instantiate CauldronLevelChangeEventChangeReason from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/Action")?; + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/event/block/CauldronLevelChangeEvent/ChangeReason", + )?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Action object, got {}", - name - ) - .into()) + "Invalid argument passed. Expected a CauldronLevelChangeEventChangeReason object, got {}", + name + ) + .into()) } else { let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); let variant = env.translate_error(variant)?; @@ -543,13 +647,46 @@ impl<'mc> JNIInstantiatable<'mc> for Action<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "BUCKET_FILL" => Ok(CauldronLevelChangeEventChangeReason::BucketFill { + inner: CauldronLevelChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + "BUCKET_EMPTY" => Ok(CauldronLevelChangeEventChangeReason::BucketEmpty { + inner: CauldronLevelChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + "BOTTLE_FILL" => Ok(CauldronLevelChangeEventChangeReason::BottleFill { + inner: CauldronLevelChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + "BOTTLE_EMPTY" => Ok(CauldronLevelChangeEventChangeReason::BottleEmpty { + inner: CauldronLevelChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + "BANNER_WASH" => Ok(CauldronLevelChangeEventChangeReason::BannerWash { + inner: CauldronLevelChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + "ARMOR_WASH" => Ok(CauldronLevelChangeEventChangeReason::ArmorWash { + inner: CauldronLevelChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + "SHULKER_WASH" => Ok(CauldronLevelChangeEventChangeReason::ShulkerWash { + inner: CauldronLevelChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + "EXTINGUISH" => Ok(CauldronLevelChangeEventChangeReason::Extinguish { + inner: CauldronLevelChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + "EVAPORATE" => Ok(CauldronLevelChangeEventChangeReason::Evaporate { + inner: CauldronLevelChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + "NATURAL_FILL" => Ok(CauldronLevelChangeEventChangeReason::NaturalFill { + inner: CauldronLevelChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(CauldronLevelChangeEventChangeReason::Unknown { + inner: CauldronLevelChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for ActionStruct<'mc> { +impl<'mc> JNIRaw<'mc> for CauldronLevelChangeEventChangeReasonStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -557,38 +694,47 @@ impl<'mc> JNIRaw<'mc> for ActionStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ActionStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CauldronLevelChangeEventChangeReasonStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ActionStruct from null object.").into()); + return Err(eyre::eyre!( + "Tried to instantiate CauldronLevelChangeEventChangeReasonStruct from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/Action")?; + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/event/block/CauldronLevelChangeEvent/ChangeReason", + )?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ActionStruct object, got {}", - name - ) - .into()) + "Invalid argument passed. Expected a CauldronLevelChangeEventChangeReasonStruct object, got {}", + name + ) + .into()) } else { Ok(Self(env.clone(), obj)) } } } -impl<'mc> ActionStruct<'mc> { +impl<'mc> CauldronLevelChangeEventChangeReasonStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/block/Action;"); - let cls = jni.find_class("org/bukkit/event/block/Action"); + ) -> Result< + crate::event::block::CauldronLevelChangeEventChangeReason<'mc>, + Box, + > { + let sig = String::from("()Lorg/bukkit/event/block/CauldronLevelChangeEvent/ChangeReason;"); + let cls = jni.find_class("org/bukkit/event/block/CauldronLevelChangeEvent/ChangeReason"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::event::block::Action::from_raw(&jni, obj) + crate::event::block::CauldronLevelChangeEventChangeReason::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -597,12 +743,12 @@ impl<'mc> ActionStruct<'mc> { } } #[repr(C)] -pub struct BlockBreakEvent<'mc>( +pub struct BlockPistonExtendEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockBreakEvent<'mc> { +impl<'mc> JNIRaw<'mc> for BlockPistonExtendEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -610,20 +756,22 @@ impl<'mc> JNIRaw<'mc> for BlockBreakEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockBreakEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockPistonExtendEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate BlockBreakEvent from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate BlockPistonExtendEvent from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockBreakEvent")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/block/BlockPistonExtendEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockBreakEvent object, got {}", + "Invalid argument passed. Expected a BlockPistonExtendEvent object, got {}", name ) .into()) @@ -633,109 +781,72 @@ impl<'mc> JNIInstantiatable<'mc> for BlockBreakEvent<'mc> { } } -impl<'mc> BlockBreakEvent<'mc> { +impl<'mc> BlockPistonExtendEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - the_block: impl Into>, - player: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/entity/Player;)V"); + block: impl Into>, + blocks: Vec>, + direction: impl Into>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/block/Block;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(the_block.into().jni_object().clone()) + jni::objects::JObject::from_raw(block.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) + args.push(val_1); + sig += "Ljava/util/List;"; + let raw_val_2 = jni.new_object("java/util/ArrayList", "()V", vec![])?; + for v in blocks { + sig += "Ljava/lang/java/lang/Object;"; + let map_val_0 = jni::objects::JValueGen::Object(v); + jni.call_method( + &raw_val_2, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_2 = jni::objects::JValueGen::Object(raw_val_2); + args.push(val_2); + sig += "Lorg/bukkit/block/BlockFace;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(direction.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/block/BlockBreakEvent"); + args.push(val_3); + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/block/BlockPistonExtendEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::block::BlockBreakEvent::from_raw(&jni, res) + crate::event::block::BlockPistonExtendEvent::from_raw(&jni, res) } - /// Gets the Player that is breaking the block involved in this event. - pub fn player(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Player;"); + #[deprecated] + /// Get the amount of blocks which will be moved while extending. + pub fn length(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Player::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets whether or not the block will attempt to drop items as it normally - /// would. - /// If and only if this is false then {@link BlockDropItemEvent} will not be - /// called after this event. - pub fn set_drop_items(&self, drop_items: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(drop_items.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setDropItems", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether or not the block will attempt to drop items. - /// If and only if this is false then {@link BlockDropItemEvent} will not be - /// called after this event. - pub fn is_drop_items(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isDropItems", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLength", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + /// Get an immutable list of the blocks which will be moved by the + /// extending. + pub fn blocks(&self) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBlocks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - // SUPER CLASS: org.bukkit.event.block.BlockExpEvent ( ['getPlayer', 'setDropItems', 'isDropItems', 'isCancelled', 'setCancelled']) - /// Get the experience dropped by the block after the event has processed - pub fn exp_to_drop(&self) -> Result> { - let temp_clone = crate::event::block::BlockExpEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockExpEvent = temp_clone.into(); - real.exp_to_drop() - } - /// Set the amount of experience dropped by the block after the event has - /// processed - pub fn set_exp_to_drop(&self, exp: i32) -> Result<(), Box> { - let temp_clone = crate::event::block::BlockExpEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockExpEvent = temp_clone.into(); - real.set_exp_to_drop(exp) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.0, obj)?); + } + Ok(new_vec) } pub fn handlers(&self) -> Result, Box> { @@ -752,7 +863,46 @@ impl<'mc> BlockBreakEvent<'mc> { pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { - crate::event::block::BlockExpEvent::handler_list(jni) + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/block/BlockPistonExtendEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.block.BlockPistonEvent ( ['getLength', 'getBlocks', 'getHandlers', 'getHandlerList']) + + pub fn is_cancelled(&self) -> Result> { + let temp_clone = crate::event::block::BlockPistonEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockPistonEvent = temp_clone.into(); + real.is_cancelled() + } + + pub fn set_cancelled(&self, cancelled: bool) -> Result<(), Box> { + let temp_clone = crate::event::block::BlockPistonEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockPistonEvent = temp_clone.into(); + real.set_cancelled(cancelled) + } + /// Returns true if the Piston in the event is sticky. + pub fn is_sticky(&self) -> Result> { + let temp_clone = crate::event::block::BlockPistonEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockPistonEvent = temp_clone.into(); + real.is_sticky() + } + /// Return the direction in which the piston will operate. + pub fn direction(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockPistonEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockPistonEvent = temp_clone.into(); + real.direction() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -760,25 +910,20 @@ impl<'mc> BlockBreakEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockBreakEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockBreakEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for BlockBreakEvent<'mc> { - fn into(self) -> crate::event::block::BlockExpEvent<'mc> { - crate::event::block::BlockExpEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockBreakEvent into crate::event::block::BlockExpEvent") +impl<'mc> Into> for BlockPistonExtendEvent<'mc> { + fn into(self) -> crate::event::block::BlockPistonEvent<'mc> { + crate::event::block::BlockPistonEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting BlockPistonExtendEvent into crate::event::block::BlockPistonEvent", + ) } } #[repr(C)] -pub struct SpongeAbsorbEvent<'mc>( +pub struct BlockIgniteEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for SpongeAbsorbEvent<'mc> { +impl<'mc> JNIRaw<'mc> for BlockIgniteEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -786,20 +931,20 @@ impl<'mc> JNIRaw<'mc> for SpongeAbsorbEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for SpongeAbsorbEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockIgniteEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate SpongeAbsorbEvent from null object.").into(), + eyre::eyre!("Tried to instantiate BlockIgniteEvent from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/SpongeAbsorbEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockIgniteEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SpongeAbsorbEvent object, got {}", + "Invalid argument passed. Expected a BlockIgniteEvent object, got {}", name ) .into()) @@ -809,181 +954,19 @@ impl<'mc> JNIInstantiatable<'mc> for SpongeAbsorbEvent<'mc> { } } -impl<'mc> SpongeAbsorbEvent<'mc> { +impl<'mc> BlockIgniteEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - block: impl Into>, - waterblocks: Vec>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/block/Block;Ljava/util/List;)V"); + the_block: impl Into>, + cause: impl Into>, + igniting_entity: impl Into>, + igniting_block: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/block/Block;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) - }); - let raw_val_2 = jni.new_object("java/util/ArrayList", "()V", vec![])?; - for v in waterblocks { - let map_val_0 = jni::objects::JValueGen::Object(v); - jni.call_method( - &raw_val_2, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_2 = jni::objects::JValueGen::Object(raw_val_2); - let cls = jni.find_class("org/bukkit/event/block/SpongeAbsorbEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = jni.translate_error_no_gen(res)?; - crate::event::block::SpongeAbsorbEvent::from_raw(&jni, res) - } - /// Get a list of all blocks to be removed by the sponge. - /// - /// This list is mutable and contains the blocks in their removed state, i.e. - /// having a type of {@link Material#AIR}. - pub fn blocks(&self) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBlocks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::BlockState::from_raw(&self.0, obj)?); - } - Ok(new_vec) - } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn handler_list( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/SpongeAbsorbEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getBlocks', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) - /// Gets the block involved in this event. - pub fn block(&self) -> Result, Box> { - let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockEvent = temp_clone.into(); - real.block() - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for SpongeAbsorbEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SpongeAbsorbEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for SpongeAbsorbEvent<'mc> { - fn into(self) -> crate::event::block::BlockEvent<'mc> { - crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SpongeAbsorbEvent into crate::event::block::BlockEvent") - } -} -#[repr(C)] -pub struct BlockIgniteEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for BlockIgniteEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for BlockIgniteEvent<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate BlockIgniteEvent from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockIgniteEvent")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockIgniteEvent object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> BlockIgniteEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - the_block: impl Into>, - cause: impl Into>, - igniting_entity: impl Into>, - igniting_block: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/block/Block;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(the_block.into().jni_object().clone()) + jni::objects::JObject::from_raw(the_block.into().jni_object().clone()) }); args.push(val_1); sig += "Lorg/bukkit/event/block/BlockIgniteEvent/IgniteCause;"; @@ -1151,10 +1134,59 @@ impl<'mc> Into> for BlockIgniteEvent<'mc> { .expect("Error converting BlockIgniteEvent into crate::event::block::BlockEvent") } } -pub enum BlockIgniteEventIgniteCause<'mc> {} +pub enum BlockIgniteEventIgniteCause<'mc> { + Lava { + inner: BlockIgniteEventIgniteCauseStruct<'mc>, + }, + FlintAndSteel { + inner: BlockIgniteEventIgniteCauseStruct<'mc>, + }, + Spread { + inner: BlockIgniteEventIgniteCauseStruct<'mc>, + }, + Lightning { + inner: BlockIgniteEventIgniteCauseStruct<'mc>, + }, + Fireball { + inner: BlockIgniteEventIgniteCauseStruct<'mc>, + }, + EnderCrystal { + inner: BlockIgniteEventIgniteCauseStruct<'mc>, + }, + Explosion { + inner: BlockIgniteEventIgniteCauseStruct<'mc>, + }, + Arrow { + inner: BlockIgniteEventIgniteCauseStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for BlockIgniteEventIgniteCause<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + BlockIgniteEventIgniteCause::Lava { .. } => f.write_str("LAVA"), + BlockIgniteEventIgniteCause::FlintAndSteel { .. } => f.write_str("FLINT_AND_STEEL"), + BlockIgniteEventIgniteCause::Spread { .. } => f.write_str("SPREAD"), + BlockIgniteEventIgniteCause::Lightning { .. } => f.write_str("LIGHTNING"), + BlockIgniteEventIgniteCause::Fireball { .. } => f.write_str("FIREBALL"), + BlockIgniteEventIgniteCause::EnderCrystal { .. } => f.write_str("ENDER_CRYSTAL"), + BlockIgniteEventIgniteCause::Explosion { .. } => f.write_str("EXPLOSION"), + BlockIgniteEventIgniteCause::Arrow { .. } => f.write_str("ARROW"), + } + } +} +impl<'mc> std::ops::Deref for BlockIgniteEventIgniteCause<'mc> { + type Target = BlockIgniteEventIgniteCauseStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + BlockIgniteEventIgniteCause::Lava { inner } => inner, + BlockIgniteEventIgniteCause::FlintAndSteel { inner } => inner, + BlockIgniteEventIgniteCause::Spread { inner } => inner, + BlockIgniteEventIgniteCause::Lightning { inner } => inner, + BlockIgniteEventIgniteCause::Fireball { inner } => inner, + BlockIgniteEventIgniteCause::EnderCrystal { inner } => inner, + BlockIgniteEventIgniteCause::Explosion { inner } => inner, + BlockIgniteEventIgniteCause::Arrow { inner } => inner, + } } } @@ -1181,6 +1213,31 @@ impl<'mc> BlockIgniteEventIgniteCause<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "LAVA" => Ok(BlockIgniteEventIgniteCause::Lava { + inner: BlockIgniteEventIgniteCauseStruct::from_raw(env, obj)?, + }), + "FLINT_AND_STEEL" => Ok(BlockIgniteEventIgniteCause::FlintAndSteel { + inner: BlockIgniteEventIgniteCauseStruct::from_raw(env, obj)?, + }), + "SPREAD" => Ok(BlockIgniteEventIgniteCause::Spread { + inner: BlockIgniteEventIgniteCauseStruct::from_raw(env, obj)?, + }), + "LIGHTNING" => Ok(BlockIgniteEventIgniteCause::Lightning { + inner: BlockIgniteEventIgniteCauseStruct::from_raw(env, obj)?, + }), + "FIREBALL" => Ok(BlockIgniteEventIgniteCause::Fireball { + inner: BlockIgniteEventIgniteCauseStruct::from_raw(env, obj)?, + }), + "ENDER_CRYSTAL" => Ok(BlockIgniteEventIgniteCause::EnderCrystal { + inner: BlockIgniteEventIgniteCauseStruct::from_raw(env, obj)?, + }), + "EXPLOSION" => Ok(BlockIgniteEventIgniteCause::Explosion { + inner: BlockIgniteEventIgniteCauseStruct::from_raw(env, obj)?, + }), + "ARROW" => Ok(BlockIgniteEventIgniteCause::Arrow { + inner: BlockIgniteEventIgniteCauseStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -1194,10 +1251,36 @@ pub struct BlockIgniteEventIgniteCauseStruct<'mc>( impl<'mc> JNIRaw<'mc> for BlockIgniteEventIgniteCause<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Lava { inner } => inner.0.clone(), + Self::FlintAndSteel { inner } => inner.0.clone(), + Self::Spread { inner } => inner.0.clone(), + Self::Lightning { inner } => inner.0.clone(), + Self::Fireball { inner } => inner.0.clone(), + Self::EnderCrystal { inner } => inner.0.clone(), + Self::Explosion { inner } => inner.0.clone(), + Self::Arrow { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Lava { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::FlintAndSteel { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Spread { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Lightning { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Fireball { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::EnderCrystal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Explosion { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Arrow { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for BlockIgniteEventIgniteCause<'mc> { @@ -1227,6 +1310,30 @@ impl<'mc> JNIInstantiatable<'mc> for BlockIgniteEventIgniteCause<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "LAVA" => Ok(BlockIgniteEventIgniteCause::Lava { + inner: BlockIgniteEventIgniteCauseStruct::from_raw(env, obj)?, + }), + "FLINT_AND_STEEL" => Ok(BlockIgniteEventIgniteCause::FlintAndSteel { + inner: BlockIgniteEventIgniteCauseStruct::from_raw(env, obj)?, + }), + "SPREAD" => Ok(BlockIgniteEventIgniteCause::Spread { + inner: BlockIgniteEventIgniteCauseStruct::from_raw(env, obj)?, + }), + "LIGHTNING" => Ok(BlockIgniteEventIgniteCause::Lightning { + inner: BlockIgniteEventIgniteCauseStruct::from_raw(env, obj)?, + }), + "FIREBALL" => Ok(BlockIgniteEventIgniteCause::Fireball { + inner: BlockIgniteEventIgniteCauseStruct::from_raw(env, obj)?, + }), + "ENDER_CRYSTAL" => Ok(BlockIgniteEventIgniteCause::EnderCrystal { + inner: BlockIgniteEventIgniteCauseStruct::from_raw(env, obj)?, + }), + "EXPLOSION" => Ok(BlockIgniteEventIgniteCause::Explosion { + inner: BlockIgniteEventIgniteCauseStruct::from_raw(env, obj)?, + }), + "ARROW" => Ok(BlockIgniteEventIgniteCause::Arrow { + inner: BlockIgniteEventIgniteCauseStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -1286,12 +1393,12 @@ impl<'mc> BlockIgniteEventIgniteCauseStruct<'mc> { } } #[repr(C)] -pub struct BlockPistonEvent<'mc>( +pub struct BlockFromToEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockPistonEvent<'mc> { +impl<'mc> JNIRaw<'mc> for BlockFromToEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1299,20 +1406,20 @@ impl<'mc> JNIRaw<'mc> for BlockPistonEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockPistonEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockFromToEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate BlockPistonEvent from null object.").into(), + eyre::eyre!("Tried to instantiate BlockFromToEvent from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockPistonEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockFromToEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockPistonEvent object, got {}", + "Invalid argument passed. Expected a BlockFromToEvent object, got {}", name ) .into()) @@ -1322,31 +1429,52 @@ impl<'mc> JNIInstantiatable<'mc> for BlockPistonEvent<'mc> { } } -impl<'mc> BlockPistonEvent<'mc> { +impl<'mc> BlockFromToEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, block: impl Into>, - direction: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/block/BlockFace;)V"); + to_block: impl Into>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/block/Block;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(block.into().jni_object().clone()) }); + args.push(val_1); + sig += "Lorg/bukkit/block/Block;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(direction.into().jni_object().clone()) + jni::objects::JObject::from_raw(to_block.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/block/BlockPistonEvent"); + args.push(val_2); + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/block/BlockFromToEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::block::BlockPistonEvent::from_raw(&jni, res) + crate::event::block::BlockFromToEvent::from_raw(&jni, res) + } + /// Gets the BlockFace that the block is moving to. + pub fn face(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFace", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Convenience method for getting the faced Block. + pub fn to_block(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getToBlock", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn is_cancelled(&self) -> Result> { @@ -1358,9 +1486,9 @@ impl<'mc> BlockPistonEvent<'mc> { Ok(res.z()?) } - pub fn set_cancelled(&self, cancelled: bool) -> Result<(), Box> { + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancelled.into()); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); let res = self.jni_ref().call_method( &self.jni_object(), "setCancelled", @@ -1370,27 +1498,30 @@ impl<'mc> BlockPistonEvent<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns true if the Piston in the event is sticky. - pub fn is_sticky(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSticky", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Return the direction in which the piston will operate. - pub fn direction(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['isCancelled', 'setCancelled', 'isSticky', 'getDirection']) + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/block/BlockFromToEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getFace', 'getToBlock', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) /// Gets the block involved in this event. pub fn block(&self) -> Result, Box> { let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { @@ -1405,25 +1536,25 @@ impl<'mc> BlockPistonEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockPistonEvent<'mc> { +impl<'mc> Into> for BlockFromToEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockPistonEvent into crate::event::Cancellable") + .expect("Error converting BlockFromToEvent into crate::event::Cancellable") } } -impl<'mc> Into> for BlockPistonEvent<'mc> { +impl<'mc> Into> for BlockFromToEvent<'mc> { fn into(self) -> crate::event::block::BlockEvent<'mc> { crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockPistonEvent into crate::event::block::BlockEvent") + .expect("Error converting BlockFromToEvent into crate::event::block::BlockEvent") } } #[repr(C)] -pub struct BlockPistonRetractEvent<'mc>( +pub struct BlockFertilizeEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockPistonRetractEvent<'mc> { +impl<'mc> JNIRaw<'mc> for BlockFertilizeEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1431,22 +1562,21 @@ impl<'mc> JNIRaw<'mc> for BlockPistonRetractEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockPistonRetractEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockFertilizeEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate BlockPistonRetractEvent from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate BlockFertilizeEvent from null object.").into(), + ); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/block/BlockPistonRetractEvent")?; + env.validate_name(&obj, "org/bukkit/event/block/BlockFertilizeEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockPistonRetractEvent object, got {}", + "Invalid argument passed. Expected a BlockFertilizeEvent object, got {}", name ) .into()) @@ -1456,33 +1586,33 @@ impl<'mc> JNIInstantiatable<'mc> for BlockPistonRetractEvent<'mc> { } } -impl<'mc> BlockPistonRetractEvent<'mc> { +impl<'mc> BlockFertilizeEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - block: impl Into>, + the_block: impl Into>, + player: impl Into>, blocks: Vec>, - direction: impl Into>, - ) -> Result, Box> { + ) -> Result, Box> { let sig = - String::from("(Lorg/bukkit/block/Block;Ljava/util/List;Lorg/bukkit/block/BlockFace;)V"); + String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/entity/Player;Ljava/util/List;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) + jni::objects::JObject::from_raw(the_block.into().jni_object().clone()) }); - let raw_val_2 = jni.new_object("java/util/ArrayList", "()V", vec![])?; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(player.into().jni_object().clone()) + }); + let raw_val_3 = jni.new_object("java/util/ArrayList", "()V", vec![])?; for v in blocks { let map_val_0 = jni::objects::JValueGen::Object(v); jni.call_method( - &raw_val_2, + &raw_val_3, "add", "(Ljava/lang/Object;)Z", vec![jni::objects::JValueGen::from(map_val_0)], )?; } - let val_2 = jni::objects::JValueGen::Object(raw_val_2); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(direction.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/event/block/BlockPistonRetractEvent"); + let val_3 = jni::objects::JValueGen::Object(raw_val_3); + let cls = jni.find_class("org/bukkit/event/block/BlockFertilizeEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -1494,26 +1624,25 @@ impl<'mc> BlockPistonRetractEvent<'mc> { ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::block::BlockPistonRetractEvent::from_raw(&jni, res) + crate::event::block::BlockFertilizeEvent::from_raw(&jni, res) } - #[deprecated] - /// Gets the location where the possible moving block might be if the retracting piston is sticky. - pub fn retract_location(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getRetractLocation", - sig.as_str(), - vec![], - ); + /// Gets the player that triggered the fertilization. + pub fn player(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Player::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Get an immutable list of the blocks which will be moved by the - /// extending. - pub fn blocks(&self) -> Result>, Box> { + /// Gets a list of all blocks changed by the fertilization. + pub fn blocks(&self) -> Result>, Box> { let sig = String::from("()Ljava/util/List;"); let res = self .jni_ref() @@ -1524,11 +1653,33 @@ impl<'mc> BlockPistonRetractEvent<'mc> { let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.0, obj)?); + new_vec.push(crate::block::BlockState::from_raw(&self.0, obj)?); } Ok(new_vec) } + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancelled: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancelled.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); let res = @@ -1544,45 +1695,21 @@ impl<'mc> BlockPistonRetractEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/BlockPistonRetractEvent"); + let cls = jni.find_class("org/bukkit/event/block/BlockFertilizeEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.block.BlockPistonEvent ( ['getRetractLocation', 'getBlocks', 'getHandlers', 'getHandlerList']) - - pub fn is_cancelled(&self) -> Result> { - let temp_clone = crate::event::block::BlockPistonEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockPistonEvent = temp_clone.into(); - real.is_cancelled() - } - - pub fn set_cancelled(&self, cancelled: bool) -> Result<(), Box> { - let temp_clone = crate::event::block::BlockPistonEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockPistonEvent = temp_clone.into(); - real.set_cancelled(cancelled) - } - /// Returns true if the Piston in the event is sticky. - pub fn is_sticky(&self) -> Result> { - let temp_clone = crate::event::block::BlockPistonEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockPistonEvent = temp_clone.into(); - real.is_sticky() - } - /// Return the direction in which the piston will operate. - pub fn direction(&self) -> Result, Box> { - let temp_clone = crate::event::block::BlockPistonEvent::from_raw(&self.0, unsafe { + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getPlayer', 'getBlocks', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + /// Gets the block involved in this event. + pub fn block(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::block::BlockPistonEvent = temp_clone.into(); - real.direction() + let real: crate::event::block::BlockEvent = temp_clone.into(); + real.block() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1590,20 +1717,25 @@ impl<'mc> BlockPistonRetractEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockPistonRetractEvent<'mc> { - fn into(self) -> crate::event::block::BlockPistonEvent<'mc> { - crate::event::block::BlockPistonEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting BlockPistonRetractEvent into crate::event::block::BlockPistonEvent", - ) +impl<'mc> Into> for BlockFertilizeEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockFertilizeEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for BlockFertilizeEvent<'mc> { + fn into(self) -> crate::event::block::BlockEvent<'mc> { + crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockFertilizeEvent into crate::event::block::BlockEvent") } } #[repr(C)] -pub struct BlockDispenseArmorEvent<'mc>( +pub struct BlockShearEntityEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockDispenseArmorEvent<'mc> { +impl<'mc> JNIRaw<'mc> for BlockShearEntityEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1611,22 +1743,22 @@ impl<'mc> JNIRaw<'mc> for BlockDispenseArmorEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockDispenseArmorEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockShearEntityEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate BlockDispenseArmorEvent from null object." + "Tried to instantiate BlockShearEntityEvent from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/block/BlockDispenseArmorEvent")?; + env.validate_name(&obj, "org/bukkit/event/block/BlockShearEntityEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockDispenseArmorEvent object, got {}", + "Invalid argument passed. Expected a BlockShearEntityEvent object, got {}", name ) .into()) @@ -1636,24 +1768,26 @@ impl<'mc> JNIInstantiatable<'mc> for BlockDispenseArmorEvent<'mc> { } } -impl<'mc> BlockDispenseArmorEvent<'mc> { +impl<'mc> BlockShearEntityEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - block: impl Into>, - dispensed: impl Into>, - target: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/inventory/ItemStack;Lorg/bukkit/entity/LivingEntity;)V"); + dispenser: impl Into>, + sheared: impl Into>, + tool: impl Into>, + ) -> Result, Box> { + let sig = String::from( + "(Lorg/bukkit/block/Block;Lorg/bukkit/entity/Entity;Lorg/bukkit/inventory/ItemStack;)V", + ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) + jni::objects::JObject::from_raw(dispenser.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(dispensed.into().jni_object().clone()) + jni::objects::JObject::from_raw(sheared.into().jni_object().clone()) }); let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) + jni::objects::JObject::from_raw(tool.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/block/BlockDispenseArmorEvent"); + let cls = jni.find_class("org/bukkit/event/block/BlockShearEntityEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -1665,80 +1799,51 @@ impl<'mc> BlockDispenseArmorEvent<'mc> { ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::block::BlockDispenseArmorEvent::from_raw(&jni, res) + crate::event::block::BlockShearEntityEvent::from_raw(&jni, res) } - /// Get the living entity on which the armor was dispensed. - pub fn tarentity( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTargetEntity", sig.as_str(), vec![]); + /// Gets the entity that was sheared. + pub fn entity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::LivingEntity::from_raw(&self.jni_ref(), unsafe { + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.event.block.BlockDispenseEvent ( ['getTargetEntity']) - /// Gets the item that is being dispensed. Modifying the returned item will - /// have no effect, you must use {@link - /// #setItem(org.bukkit.inventory.ItemStack)} instead. - pub fn item(&self) -> Result, Box> { - let temp_clone = crate::event::block::BlockDispenseEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockDispenseEvent = temp_clone.into(); - real.item() + /// Gets the item used to shear this sheep. + pub fn tool(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the item being dispensed. - pub fn set_item( - &self, - item: impl Into>, - ) -> Result<(), Box> { - let temp_clone = crate::event::block::BlockDispenseEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockDispenseEvent = temp_clone.into(); - real.set_item(item) - } - /// Gets the velocity in meters per tick. - /// - /// Note: Modifying the returned Vector will not change the velocity, you - /// must use {@link #setVelocity(org.bukkit.util.Vector)} instead. - pub fn velocity(&self) -> Result, Box> { - let temp_clone = crate::event::block::BlockDispenseEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockDispenseEvent = temp_clone.into(); - real.velocity() - } - /// Sets the velocity of the item being dispensed in meters per tick. - pub fn set_velocity( - &self, - vel: impl Into>, - ) -> Result<(), Box> { - let temp_clone = crate::event::block::BlockDispenseEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockDispenseEvent = temp_clone.into(); - real.set_velocity(vel) + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - pub fn is_cancelled(&self) -> Result> { - let temp_clone = crate::event::block::BlockDispenseEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockDispenseEvent = temp_clone.into(); - real.is_cancelled() - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let temp_clone = crate::event::block::BlockDispenseEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockDispenseEvent = temp_clone.into(); - real.set_cancelled(cancel) + pub fn set_cancelled(&self, cancelled: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancelled.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn handlers(&self) -> Result, Box> { @@ -1755,7 +1860,22 @@ impl<'mc> BlockDispenseArmorEvent<'mc> { pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { - crate::event::block::BlockDispenseEvent::handler_list(jni) + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/block/BlockShearEntityEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getEntity', 'getTool', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + /// Gets the block involved in this event. + pub fn block(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockEvent = temp_clone.into(); + real.block() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1763,112 +1883,211 @@ impl<'mc> BlockDispenseArmorEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockDispenseArmorEvent<'mc> { - fn into(self) -> crate::event::block::BlockDispenseEvent<'mc> { - crate::event::block::BlockDispenseEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting BlockDispenseArmorEvent into crate::event::block::BlockDispenseEvent", - ) +impl<'mc> Into> for BlockShearEntityEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockShearEntityEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for BlockShearEntityEvent<'mc> { + fn into(self) -> crate::event::block::BlockEvent<'mc> { + crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockShearEntityEvent into crate::event::block::BlockEvent") + } +} +pub enum Action<'mc> { + LeftClickBlock { inner: ActionStruct<'mc> }, + RightClickBlock { inner: ActionStruct<'mc> }, + LeftClickAir { inner: ActionStruct<'mc> }, + RightClickAir { inner: ActionStruct<'mc> }, + Physical { inner: ActionStruct<'mc> }, +} +impl<'mc> std::fmt::Display for Action<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Action::LeftClickBlock { .. } => f.write_str("LEFT_CLICK_BLOCK"), + Action::RightClickBlock { .. } => f.write_str("RIGHT_CLICK_BLOCK"), + Action::LeftClickAir { .. } => f.write_str("LEFT_CLICK_AIR"), + Action::RightClickAir { .. } => f.write_str("RIGHT_CLICK_AIR"), + Action::Physical { .. } => f.write_str("PHYSICAL"), + } + } +} +impl<'mc> std::ops::Deref for Action<'mc> { + type Target = ActionStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + Action::LeftClickBlock { inner } => inner, + Action::RightClickBlock { inner } => inner, + Action::LeftClickAir { inner } => inner, + Action::RightClickAir { inner } => inner, + Action::Physical { inner } => inner, + } + } +} + +impl<'mc> Action<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/event/block/Action"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/event/block/Action;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "LEFT_CLICK_BLOCK" => Ok(Action::LeftClickBlock { + inner: ActionStruct::from_raw(env, obj)?, + }), + "RIGHT_CLICK_BLOCK" => Ok(Action::RightClickBlock { + inner: ActionStruct::from_raw(env, obj)?, + }), + "LEFT_CLICK_AIR" => Ok(Action::LeftClickAir { + inner: ActionStruct::from_raw(env, obj)?, + }), + "RIGHT_CLICK_AIR" => Ok(Action::RightClickAir { + inner: ActionStruct::from_raw(env, obj)?, + }), + "PHYSICAL" => Ok(Action::Physical { + inner: ActionStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } + #[repr(C)] -pub struct EntityBlockFormEvent<'mc>( +pub struct ActionStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EntityBlockFormEvent<'mc> { +impl<'mc> JNIRaw<'mc> for Action<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + match self { + Self::LeftClickBlock { inner } => inner.0.clone(), + Self::RightClickBlock { inner } => inner.0.clone(), + Self::LeftClickAir { inner } => inner.0.clone(), + Self::RightClickAir { inner } => inner.0.clone(), + Self::Physical { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + match self { + Self::LeftClickBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RightClickBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LeftClickAir { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RightClickAir { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Physical { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for EntityBlockFormEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Action<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate EntityBlockFormEvent from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate Action from null object.").into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/block/EntityBlockFormEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/Action")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityBlockFormEvent object, got {}", + "Invalid argument passed. Expected a Action object, got {}", name ) .into()) } else { - Ok(Self(env.clone(), obj)) + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "LEFT_CLICK_BLOCK" => Ok(Action::LeftClickBlock { + inner: ActionStruct::from_raw(env, obj)?, + }), + "RIGHT_CLICK_BLOCK" => Ok(Action::RightClickBlock { + inner: ActionStruct::from_raw(env, obj)?, + }), + "LEFT_CLICK_AIR" => Ok(Action::LeftClickAir { + inner: ActionStruct::from_raw(env, obj)?, + }), + "RIGHT_CLICK_AIR" => Ok(Action::RightClickAir { + inner: ActionStruct::from_raw(env, obj)?, + }), + "PHYSICAL" => Ok(Action::Physical { + inner: ActionStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } } -impl<'mc> EntityBlockFormEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - entity: impl Into>, - block: impl Into>, - blockstate: impl Into>, - ) -> Result, Box> { - let sig = String::from( - "(Lorg/bukkit/entity/Entity;Lorg/bukkit/block/Block;Lorg/bukkit/block/BlockState;)V", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(blockstate.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/event/block/EntityBlockFormEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = jni.translate_error_no_gen(res)?; - crate::event::block::EntityBlockFormEvent::from_raw(&jni, res) +impl<'mc> JNIRaw<'mc> for ActionStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Get the entity that formed the block. - pub fn entity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - // SUPER CLASS: org.bukkit.event.block.BlockFormEvent ( ['getEntity']) - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} +impl<'mc> JNIInstantiatable<'mc> for ActionStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate ActionStruct from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/Action")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ActionStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } +} - pub fn handler_list( +impl<'mc> ActionStruct<'mc> { + pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - crate::event::block::BlockFormEvent::handler_list(jni) + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/block/Action;"); + let cls = jni.find_class("org/bukkit/event/block/Action"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::block::Action::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1876,20 +2095,13 @@ impl<'mc> EntityBlockFormEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for EntityBlockFormEvent<'mc> { - fn into(self) -> crate::event::block::BlockFormEvent<'mc> { - crate::event::block::BlockFormEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting EntityBlockFormEvent into crate::event::block::BlockFormEvent", - ) - } -} #[repr(C)] -pub struct SignChangeEvent<'mc>( +pub struct BlockBreakEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for SignChangeEvent<'mc> { +impl<'mc> JNIRaw<'mc> for BlockBreakEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1897,20 +2109,20 @@ impl<'mc> JNIRaw<'mc> for SignChangeEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for SignChangeEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockBreakEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate SignChangeEvent from null object.").into(), + eyre::eyre!("Tried to instantiate BlockBreakEvent from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/SignChangeEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockBreakEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SignChangeEvent object, got {}", + "Invalid argument passed. Expected a BlockBreakEvent object, got {}", name ) .into()) @@ -1920,46 +2132,33 @@ impl<'mc> JNIInstantiatable<'mc> for SignChangeEvent<'mc> { } } -impl<'mc> SignChangeEvent<'mc> { +impl<'mc> BlockBreakEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, the_block: impl Into>, - the_player: impl Into>, - the_lines: impl Into, - side: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/block/Block;"; + player: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/entity/Player;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(the_block.into().jni_object().clone()) }); - args.push(val_1); - sig += "Lorg/bukkit/entity/Player;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(the_player.into().jni_object().clone()) + jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); - args.push(val_2); - sig += "Ljava/lang/String;"; - let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(the_lines.into())?, - )); - args.push(val_3); - if let Some(a) = side { - sig += "Lorg/bukkit/block/sign/Side;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_4); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/event/block/SignChangeEvent"); + let cls = jni.find_class("org/bukkit/event/block/BlockBreakEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); let res = jni.translate_error_no_gen(res)?; - crate::event::block::SignChangeEvent::from_raw(&jni, res) + crate::event::block::BlockBreakEvent::from_raw(&jni, res) } - /// Gets the player changing the sign involved in this event. + /// Gets the Player that is breaking the block involved in this event. pub fn player(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/entity/Player;"); let res = self @@ -1970,73 +2169,32 @@ impl<'mc> SignChangeEvent<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets all of the lines of text from the sign involved in this event. - pub fn lines(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getLines", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Gets a single line of text from the sign involved in this event. - pub fn get_line(&self, index: i32) -> Result, Box> { - let sig = String::from("(I)Ljava/lang/String;"); - let val_1 = jni::objects::JValueGen::Int(index); + /// Sets whether or not the block will attempt to drop items as it normally + /// would. + /// If and only if this is false then {@link BlockDropItemEvent} will not be + /// called after this event. + pub fn set_drop_items(&self, drop_items: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(drop_items.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getLine", + "setDropItems", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// Sets a single line for the sign involved in this event - pub fn set_line( - &self, - index: i32, - line: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(ILjava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Int(index); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(line.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLine", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns which side is changed. - pub fn side(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/sign/Side;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSide", sig.as_str(), vec![]); + /// Gets whether or not the block will attempt to drop items. + /// If and only if this is false then {@link BlockDropItemEvent} will not be + /// called after this event. + pub fn is_drop_items(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isDropItems", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::sign::Side::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } pub fn is_cancelled(&self) -> Result> { @@ -2060,6 +2218,24 @@ impl<'mc> SignChangeEvent<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } + // SUPER CLASS: org.bukkit.event.block.BlockExpEvent ( ['getPlayer', 'setDropItems', 'isDropItems', 'isCancelled', 'setCancelled']) + /// Get the experience dropped by the block after the event has processed + pub fn exp_to_drop(&self) -> Result> { + let temp_clone = crate::event::block::BlockExpEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockExpEvent = temp_clone.into(); + real.exp_to_drop() + } + /// Set the amount of experience dropped by the block after the event has + /// processed + pub fn set_exp_to_drop(&self, exp: i32) -> Result<(), Box> { + let temp_clone = crate::event::block::BlockExpEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockExpEvent = temp_clone.into(); + real.set_exp_to_drop(exp) + } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -2075,22 +2251,7 @@ impl<'mc> SignChangeEvent<'mc> { pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/SignChangeEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getPlayer', 'getLines', 'getLine', 'setLine', 'getSide', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) - /// Gets the block involved in this event. - pub fn block(&self) -> Result, Box> { - let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockEvent = temp_clone.into(); - real.block() + crate::event::block::BlockExpEvent::handler_list(jni) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -2098,25 +2259,25 @@ impl<'mc> SignChangeEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for SignChangeEvent<'mc> { +impl<'mc> Into> for BlockBreakEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SignChangeEvent into crate::event::Cancellable") + .expect("Error converting BlockBreakEvent into crate::event::Cancellable") } } -impl<'mc> Into> for SignChangeEvent<'mc> { - fn into(self) -> crate::event::block::BlockEvent<'mc> { - crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SignChangeEvent into crate::event::block::BlockEvent") +impl<'mc> Into> for BlockBreakEvent<'mc> { + fn into(self) -> crate::event::block::BlockExpEvent<'mc> { + crate::event::block::BlockExpEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockBreakEvent into crate::event::block::BlockExpEvent") } } #[repr(C)] -pub struct BlockMultiPlaceEvent<'mc>( +pub struct SpongeAbsorbEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockMultiPlaceEvent<'mc> { +impl<'mc> JNIRaw<'mc> for SpongeAbsorbEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2124,21 +2285,20 @@ impl<'mc> JNIRaw<'mc> for BlockMultiPlaceEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockMultiPlaceEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for SpongeAbsorbEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate BlockMultiPlaceEvent from null object.").into(), + eyre::eyre!("Tried to instantiate SpongeAbsorbEvent from null object.").into(), ); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/block/BlockMultiPlaceEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/SpongeAbsorbEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockMultiPlaceEvent object, got {}", + "Invalid argument passed. Expected a SpongeAbsorbEvent object, got {}", name ) .into()) @@ -2148,38 +2308,28 @@ impl<'mc> JNIInstantiatable<'mc> for BlockMultiPlaceEvent<'mc> { } } -impl<'mc> BlockMultiPlaceEvent<'mc> { +impl<'mc> SpongeAbsorbEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - states: Vec>, - clicked: impl Into>, - item_in_hand: impl Into>, - the_player: impl Into>, - can_build: bool, - ) -> Result, Box> { - let sig = String::from("(Ljava/util/List;Lorg/bukkit/block/Block;Lorg/bukkit/inventory/ItemStack;Lorg/bukkit/entity/Player;Z)V"); - let raw_val_1 = jni.new_object("java/util/ArrayList", "()V", vec![])?; - for v in states { + block: impl Into>, + waterblocks: Vec>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/block/Block;Ljava/util/List;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(block.into().jni_object().clone()) + }); + let raw_val_2 = jni.new_object("java/util/ArrayList", "()V", vec![])?; + for v in waterblocks { let map_val_0 = jni::objects::JValueGen::Object(v); jni.call_method( - &raw_val_1, + &raw_val_2, "add", "(Ljava/lang/Object;)Z", vec![jni::objects::JValueGen::from(map_val_0)], )?; } - let val_1 = jni::objects::JValueGen::Object(raw_val_1); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(clicked.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_in_hand.into().jni_object().clone()) - }); - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(the_player.into().jni_object().clone()) - }); - let val_5 = jni::objects::JValueGen::Bool(can_build.into()); - let cls = jni.find_class("org/bukkit/event/block/BlockMultiPlaceEvent"); + let val_2 = jni::objects::JValueGen::Object(raw_val_2); + let cls = jni.find_class("org/bukkit/event/block/SpongeAbsorbEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -2187,27 +2337,20 @@ impl<'mc> BlockMultiPlaceEvent<'mc> { vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - jni::objects::JValueGen::from(val_5), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::block::BlockMultiPlaceEvent::from_raw(&jni, res) + crate::event::block::SpongeAbsorbEvent::from_raw(&jni, res) } - /// Gets a list of blockstates for all blocks which were replaced by the - /// placement of the new blocks. Most of these blocks will just have a - /// Material type of AIR. - pub fn replaced_block_states( - &self, - ) -> Result>, Box> { + /// Get a list of all blocks to be removed by the sponge. + /// + /// This list is mutable and contains the blocks in their removed state, i.e. + /// having a type of {@link Material#AIR}. + pub fn blocks(&self) -> Result>, Box> { let sig = String::from("()Ljava/util/List;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getReplacedBlockStates", - sig.as_str(), - vec![], - ); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBlocks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; @@ -2218,97 +2361,27 @@ impl<'mc> BlockMultiPlaceEvent<'mc> { } Ok(new_vec) } - // SUPER CLASS: org.bukkit.event.block.BlockPlaceEvent ( ['getReplacedBlockStates']) pub fn is_cancelled(&self) -> Result> { - let temp_clone = crate::event::block::BlockPlaceEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockPlaceEvent = temp_clone.into(); - real.is_cancelled() + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let temp_clone = crate::event::block::BlockPlaceEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockPlaceEvent = temp_clone.into(); - real.set_cancelled(cancel) - } - /// Gets the player who placed the block involved in this event. - pub fn player(&self) -> Result, Box> { - let temp_clone = crate::event::block::BlockPlaceEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockPlaceEvent = temp_clone.into(); - real.player() - } - /// Clarity method for getting the placed block. Not really needed except - /// for reasons of clarity. - pub fn block_placed(&self) -> Result, Box> { - let temp_clone = crate::event::block::BlockPlaceEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockPlaceEvent = temp_clone.into(); - real.block_placed() - } - /// Gets the BlockState for the block which was replaced. Material type air - /// mostly. - pub fn block_replaced_state( - &self, - ) -> Result, Box> { - let temp_clone = crate::event::block::BlockPlaceEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockPlaceEvent = temp_clone.into(); - real.block_replaced_state() - } - /// Gets the block that this block was placed against - pub fn block_against(&self) -> Result, Box> { - let temp_clone = crate::event::block::BlockPlaceEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockPlaceEvent = temp_clone.into(); - real.block_against() - } - /// Gets the item in the player's hand when they placed the block. - pub fn item_in_hand( - &self, - ) -> Result, Box> { - let temp_clone = crate::event::block::BlockPlaceEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockPlaceEvent = temp_clone.into(); - real.item_in_hand() - } - /// Gets the hand which placed the block - pub fn hand(&self) -> Result, Box> { - let temp_clone = crate::event::block::BlockPlaceEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockPlaceEvent = temp_clone.into(); - real.hand() - } - /// Gets the value whether the player would be allowed to build here. - /// Defaults to spawn if the server was going to stop them (such as, the - /// player is in Spawn). Note that this is an entirely different check - /// than BLOCK_CANBUILD, as this refers to a player, not universe-physics - /// rule like cactus on dirt. - pub fn can_build(&self) -> Result> { - let temp_clone = crate::event::block::BlockPlaceEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockPlaceEvent = temp_clone.into(); - real.can_build() - } - /// Sets the canBuild state of this event. Set to true if you want the - /// player to be able to build. - pub fn set_build(&self, can_build: bool) -> Result<(), Box> { - let temp_clone = crate::event::block::BlockPlaceEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockPlaceEvent = temp_clone.into(); - real.set_build(can_build) + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn handlers(&self) -> Result, Box> { @@ -2325,7 +2398,22 @@ impl<'mc> BlockMultiPlaceEvent<'mc> { pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { - crate::event::block::BlockPlaceEvent::handler_list(jni) + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/block/SpongeAbsorbEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getBlocks', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + /// Gets the block involved in this event. + pub fn block(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockEvent = temp_clone.into(); + real.block() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -2333,20 +2421,25 @@ impl<'mc> BlockMultiPlaceEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockMultiPlaceEvent<'mc> { - fn into(self) -> crate::event::block::BlockPlaceEvent<'mc> { - crate::event::block::BlockPlaceEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting BlockMultiPlaceEvent into crate::event::block::BlockPlaceEvent", - ) +impl<'mc> Into> for SpongeAbsorbEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting SpongeAbsorbEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for SpongeAbsorbEvent<'mc> { + fn into(self) -> crate::event::block::BlockEvent<'mc> { + crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting SpongeAbsorbEvent into crate::event::block::BlockEvent") } } #[repr(C)] -pub struct BlockBurnEvent<'mc>( +pub struct BlockPistonEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockBurnEvent<'mc> { +impl<'mc> JNIRaw<'mc> for BlockPistonEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2354,20 +2447,20 @@ impl<'mc> JNIRaw<'mc> for BlockBurnEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockBurnEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockPistonEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate BlockBurnEvent from null object.").into(), + eyre::eyre!("Tried to instantiate BlockPistonEvent from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockBurnEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockPistonEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockBurnEvent object, got {}", + "Invalid argument passed. Expected a BlockPistonEvent object, got {}", name ) .into()) @@ -2377,52 +2470,31 @@ impl<'mc> JNIInstantiatable<'mc> for BlockBurnEvent<'mc> { } } -impl<'mc> BlockBurnEvent<'mc> { +impl<'mc> BlockPistonEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, block: impl Into>, - igniting_block: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/block/Block;"; + direction: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/block/BlockFace;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(block.into().jni_object().clone()) }); - args.push(val_1); - if let Some(a) = igniting_block { - sig += "Lorg/bukkit/block/Block;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/event/block/BlockBurnEvent"); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(direction.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/block/BlockPistonEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::event::block::BlockBurnEvent::from_raw(&jni, res) - } - /// Gets the block which ignited this block. - pub fn igniting_block( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getIgnitingBlock", + let res = jni.new_object( + cls, sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::block::Block::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + let res = jni.translate_error_no_gen(res)?; + crate::event::block::BlockPistonEvent::from_raw(&jni, res) } pub fn is_cancelled(&self) -> Result> { @@ -2434,9 +2506,9 @@ impl<'mc> BlockBurnEvent<'mc> { Ok(res.z()?) } - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + pub fn set_cancelled(&self, cancelled: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let val_1 = jni::objects::JValueGen::Bool(cancelled.into()); let res = self.jni_ref().call_method( &self.jni_object(), "setCancelled", @@ -2446,30 +2518,27 @@ impl<'mc> BlockBurnEvent<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + /// Returns true if the Piston in the event is sticky. + pub fn is_sticky(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSticky", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Return the direction in which the piston will operate. + pub fn direction(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn handler_list( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/BlockBurnEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getIgnitingBlock', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['isCancelled', 'setCancelled', 'isSticky', 'getDirection']) /// Gets the block involved in this event. pub fn block(&self) -> Result, Box> { let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { @@ -2484,25 +2553,25 @@ impl<'mc> BlockBurnEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockBurnEvent<'mc> { +impl<'mc> Into> for BlockPistonEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockBurnEvent into crate::event::Cancellable") + .expect("Error converting BlockPistonEvent into crate::event::Cancellable") } } -impl<'mc> Into> for BlockBurnEvent<'mc> { +impl<'mc> Into> for BlockPistonEvent<'mc> { fn into(self) -> crate::event::block::BlockEvent<'mc> { crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockBurnEvent into crate::event::block::BlockEvent") + .expect("Error converting BlockPistonEvent into crate::event::block::BlockEvent") } } #[repr(C)] -pub struct BlockDropItemEvent<'mc>( +pub struct BlockPistonRetractEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockDropItemEvent<'mc> { +impl<'mc> JNIRaw<'mc> for BlockPistonRetractEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2510,20 +2579,22 @@ impl<'mc> JNIRaw<'mc> for BlockDropItemEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockDropItemEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockPistonRetractEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate BlockDropItemEvent from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate BlockPistonRetractEvent from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockDropItemEvent")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/block/BlockPistonRetractEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockDropItemEvent object, got {}", + "Invalid argument passed. Expected a BlockPistonRetractEvent object, got {}", name ) .into()) @@ -2533,36 +2604,33 @@ impl<'mc> JNIInstantiatable<'mc> for BlockDropItemEvent<'mc> { } } -impl<'mc> BlockDropItemEvent<'mc> { +impl<'mc> BlockPistonRetractEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, block: impl Into>, - block_state: impl Into>, - player: impl Into>, - items: Vec>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/block/BlockState;Lorg/bukkit/entity/Player;Ljava/util/List;)V"); + blocks: Vec>, + direction: impl Into>, + ) -> Result, Box> { + let sig = + String::from("(Lorg/bukkit/block/Block;Ljava/util/List;Lorg/bukkit/block/BlockFace;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(block.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block_state.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) - }); - let raw_val_4 = jni.new_object("java/util/ArrayList", "()V", vec![])?; - for v in items { + let raw_val_2 = jni.new_object("java/util/ArrayList", "()V", vec![])?; + for v in blocks { let map_val_0 = jni::objects::JValueGen::Object(v); jni.call_method( - &raw_val_4, + &raw_val_2, "add", "(Ljava/lang/Object;)Z", vec![jni::objects::JValueGen::from(map_val_0)], )?; } - let val_4 = jni::objects::JValueGen::Object(raw_val_4); - let cls = jni.find_class("org/bukkit/event/block/BlockDropItemEvent"); + let val_2 = jni::objects::JValueGen::Object(raw_val_2); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(direction.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/block/BlockPistonRetractEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -2571,76 +2639,44 @@ impl<'mc> BlockDropItemEvent<'mc> { jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::block::BlockDropItemEvent::from_raw(&jni, res) - } - /// Gets the Player that is breaking the block involved in this event. - pub fn player(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Player;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Player::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + crate::event::block::BlockPistonRetractEvent::from_raw(&jni, res) } - /// Gets the BlockState of the block involved in this event before it was - /// broken. - pub fn block_state(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockState;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBlockState", sig.as_str(), vec![]); + #[deprecated] + /// Gets the location where the possible moving block might be if the retracting piston is sticky. + pub fn retract_location(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getRetractLocation", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { + crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets list of the Item drops caused by the block break. - /// This list is mutable - removing an item from it will cause it to not - /// drop. It is not legal however to add new items to the list. - pub fn items(&self) -> Result>, Box> { + /// Get an immutable list of the blocks which will be moved by the + /// extending. + pub fn blocks(&self) -> Result>, Box> { let sig = String::from("()Ljava/util/List;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getItems", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBlocks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::entity::Item::from_raw(&self.0, obj)?); + new_vec.push(crate::block::Block::from_raw(&self.0, obj)?); } Ok(new_vec) } - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); let res = @@ -2656,21 +2692,45 @@ impl<'mc> BlockDropItemEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/BlockDropItemEvent"); + let cls = jni.find_class("org/bukkit/event/block/BlockPistonRetractEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getPlayer', 'getBlockState', 'getItems', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) - /// Gets the block involved in this event. - pub fn block(&self) -> Result, Box> { - let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { + // SUPER CLASS: org.bukkit.event.block.BlockPistonEvent ( ['getRetractLocation', 'getBlocks', 'getHandlers', 'getHandlerList']) + + pub fn is_cancelled(&self) -> Result> { + let temp_clone = crate::event::block::BlockPistonEvent::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::block::BlockEvent = temp_clone.into(); - real.block() + let real: crate::event::block::BlockPistonEvent = temp_clone.into(); + real.is_cancelled() + } + + pub fn set_cancelled(&self, cancelled: bool) -> Result<(), Box> { + let temp_clone = crate::event::block::BlockPistonEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockPistonEvent = temp_clone.into(); + real.set_cancelled(cancelled) + } + /// Returns true if the Piston in the event is sticky. + pub fn is_sticky(&self) -> Result> { + let temp_clone = crate::event::block::BlockPistonEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockPistonEvent = temp_clone.into(); + real.is_sticky() + } + /// Return the direction in which the piston will operate. + pub fn direction(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockPistonEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockPistonEvent = temp_clone.into(); + real.direction() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -2678,25 +2738,20 @@ impl<'mc> BlockDropItemEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockDropItemEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockDropItemEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for BlockDropItemEvent<'mc> { - fn into(self) -> crate::event::block::BlockEvent<'mc> { - crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockDropItemEvent into crate::event::block::BlockEvent") +impl<'mc> Into> for BlockPistonRetractEvent<'mc> { + fn into(self) -> crate::event::block::BlockPistonEvent<'mc> { + crate::event::block::BlockPistonEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting BlockPistonRetractEvent into crate::event::block::BlockPistonEvent", + ) } } #[repr(C)] -pub struct BlockSpreadEvent<'mc>( +pub struct BlockDispenseArmorEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockSpreadEvent<'mc> { +impl<'mc> JNIRaw<'mc> for BlockDispenseArmorEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2704,20 +2759,22 @@ impl<'mc> JNIRaw<'mc> for BlockSpreadEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockSpreadEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockDispenseArmorEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate BlockSpreadEvent from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate BlockDispenseArmorEvent from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockSpreadEvent")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/block/BlockDispenseArmorEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockSpreadEvent object, got {}", + "Invalid argument passed. Expected a BlockDispenseArmorEvent object, got {}", name ) .into()) @@ -2727,26 +2784,24 @@ impl<'mc> JNIInstantiatable<'mc> for BlockSpreadEvent<'mc> { } } -impl<'mc> BlockSpreadEvent<'mc> { +impl<'mc> BlockDispenseArmorEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, block: impl Into>, - source: impl Into>, - new_state: impl Into>, - ) -> Result, Box> { - let sig = String::from( - "(Lorg/bukkit/block/Block;Lorg/bukkit/block/Block;Lorg/bukkit/block/BlockState;)V", - ); + dispensed: impl Into>, + target: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/inventory/ItemStack;Lorg/bukkit/entity/LivingEntity;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(block.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(source.into().jni_object().clone()) + jni::objects::JObject::from_raw(dispensed.into().jni_object().clone()) }); let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_state.into().jni_object().clone()) + jni::objects::JObject::from_raw(target.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/block/BlockSpreadEvent"); + let cls = jni.find_class("org/bukkit/event/block/BlockDispenseArmorEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -2758,19 +2813,81 @@ impl<'mc> BlockSpreadEvent<'mc> { ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::block::BlockSpreadEvent::from_raw(&jni, res) + crate::event::block::BlockDispenseArmorEvent::from_raw(&jni, res) } - /// Gets the source block involved in this event. - pub fn source(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSource", sig.as_str(), vec![]); + /// Get the living entity on which the armor was dispensed. + pub fn tarentity( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTargetEntity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { + crate::entity::LivingEntity::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } + // SUPER CLASS: org.bukkit.event.block.BlockDispenseEvent ( ['getTargetEntity']) + /// Gets the item that is being dispensed. Modifying the returned item will + /// have no effect, you must use {@link + /// #setItem(org.bukkit.inventory.ItemStack)} instead. + pub fn item(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockDispenseEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockDispenseEvent = temp_clone.into(); + real.item() + } + /// Sets the item being dispensed. + pub fn set_item( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let temp_clone = crate::event::block::BlockDispenseEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockDispenseEvent = temp_clone.into(); + real.set_item(item) + } + /// Gets the velocity in meters per tick. + /// + /// Note: Modifying the returned Vector will not change the velocity, you + /// must use {@link #setVelocity(org.bukkit.util.Vector)} instead. + pub fn velocity(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockDispenseEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockDispenseEvent = temp_clone.into(); + real.velocity() + } + /// Sets the velocity of the item being dispensed in meters per tick. + pub fn set_velocity( + &self, + vel: impl Into>, + ) -> Result<(), Box> { + let temp_clone = crate::event::block::BlockDispenseEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockDispenseEvent = temp_clone.into(); + real.set_velocity(vel) + } + + pub fn is_cancelled(&self) -> Result> { + let temp_clone = crate::event::block::BlockDispenseEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockDispenseEvent = temp_clone.into(); + real.is_cancelled() + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let temp_clone = crate::event::block::BlockDispenseEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockDispenseEvent = temp_clone.into(); + real.set_cancelled(cancel) + } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -2786,34 +2903,28 @@ impl<'mc> BlockSpreadEvent<'mc> { pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/BlockSpreadEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) + crate::event::block::BlockDispenseEvent::handler_list(jni) } - // SUPER CLASS: org.bukkit.event.block.BlockFormEvent ( ['getSource', 'getHandlers', 'getHandlerList']) pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockSpreadEvent<'mc> { - fn into(self) -> crate::event::block::BlockFormEvent<'mc> { - crate::event::block::BlockFormEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockSpreadEvent into crate::event::block::BlockFormEvent") +impl<'mc> Into> for BlockDispenseArmorEvent<'mc> { + fn into(self) -> crate::event::block::BlockDispenseEvent<'mc> { + crate::event::block::BlockDispenseEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting BlockDispenseArmorEvent into crate::event::block::BlockDispenseEvent", + ) } } #[repr(C)] -pub struct BlockGrowEvent<'mc>( +pub struct EntityBlockFormEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockGrowEvent<'mc> { +impl<'mc> JNIRaw<'mc> for EntityBlockFormEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2821,20 +2932,21 @@ impl<'mc> JNIRaw<'mc> for BlockGrowEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockGrowEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EntityBlockFormEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate BlockGrowEvent from null object.").into(), + eyre::eyre!("Tried to instantiate EntityBlockFormEvent from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockGrowEvent")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/block/EntityBlockFormEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockGrowEvent object, got {}", + "Invalid argument passed. Expected a EntityBlockFormEvent object, got {}", name ) .into()) @@ -2844,20 +2956,26 @@ impl<'mc> JNIInstantiatable<'mc> for BlockGrowEvent<'mc> { } } -impl<'mc> BlockGrowEvent<'mc> { +impl<'mc> EntityBlockFormEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, + entity: impl Into>, block: impl Into>, - new_state: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/block/BlockState;)V"); + blockstate: impl Into>, + ) -> Result, Box> { + let sig = String::from( + "(Lorg/bukkit/entity/Entity;Lorg/bukkit/block/Block;Lorg/bukkit/block/BlockState;)V", + ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_state.into().jni_object().clone()) + jni::objects::JObject::from_raw(block.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/block/BlockGrowEvent"); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(blockstate.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/block/EntityBlockFormEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -2865,44 +2983,24 @@ impl<'mc> BlockGrowEvent<'mc> { vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::block::BlockGrowEvent::from_raw(&jni, res) + crate::event::block::EntityBlockFormEvent::from_raw(&jni, res) } - /// Gets the state of the block where it will form or spread to. - pub fn new_state(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockState;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getNewState", sig.as_str(), vec![]); + /// Get the entity that formed the block. + pub fn entity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } + // SUPER CLASS: org.bukkit.event.block.BlockFormEvent ( ['getEntity']) pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -2918,22 +3016,7 @@ impl<'mc> BlockGrowEvent<'mc> { pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/BlockGrowEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getNewState', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) - /// Gets the block involved in this event. - pub fn block(&self) -> Result, Box> { - let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockEvent = temp_clone.into(); - real.block() + crate::event::block::BlockFormEvent::handler_list(jni) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -2941,25 +3024,20 @@ impl<'mc> BlockGrowEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockGrowEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockGrowEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for BlockGrowEvent<'mc> { - fn into(self) -> crate::event::block::BlockEvent<'mc> { - crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockGrowEvent into crate::event::block::BlockEvent") +impl<'mc> Into> for EntityBlockFormEvent<'mc> { + fn into(self) -> crate::event::block::BlockFormEvent<'mc> { + crate::event::block::BlockFormEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting EntityBlockFormEvent into crate::event::block::BlockFormEvent", + ) } } #[repr(C)] -pub struct BlockFormEvent<'mc>( +pub struct SignChangeEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockFormEvent<'mc> { +impl<'mc> JNIRaw<'mc> for SignChangeEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2967,20 +3045,20 @@ impl<'mc> JNIRaw<'mc> for BlockFormEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockFormEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for SignChangeEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate BlockFormEvent from null object.").into(), + eyre::eyre!("Tried to instantiate SignChangeEvent from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockFormEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/SignChangeEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockFormEvent object, got {}", + "Invalid argument passed. Expected a SignChangeEvent object, got {}", name ) .into()) @@ -2990,156 +3068,132 @@ impl<'mc> JNIInstantiatable<'mc> for BlockFormEvent<'mc> { } } -impl<'mc> BlockFormEvent<'mc> { +impl<'mc> SignChangeEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - block: impl Into>, - new_state: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/block/BlockState;)V"); + the_block: impl Into>, + the_player: impl Into>, + the_lines: impl Into, + side: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/block/Block;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) + jni::objects::JObject::from_raw(the_block.into().jni_object().clone()) }); + args.push(val_1); + sig += "Lorg/bukkit/entity/Player;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_state.into().jni_object().clone()) + jni::objects::JObject::from_raw(the_player.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/block/BlockFormEvent"); + args.push(val_2); + sig += "Ljava/lang/String;"; + let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(the_lines.into())?, + )); + args.push(val_3); + if let Some(a) = side { + sig += "Lorg/bukkit/block/sign/Side;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_4); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/block/SignChangeEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::event::block::SignChangeEvent::from_raw(&jni, res) + } + /// Gets the player changing the sign involved in this event. + pub fn player(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Player::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets all of the lines of text from the sign involved in this event. + pub fn lines(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLines", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gets a single line of text from the sign involved in this event. + pub fn get_line(&self, index: i32) -> Result, Box> { + let sig = String::from("(I)Ljava/lang/String;"); + let val_1 = jni::objects::JValueGen::Int(index); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLine", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Sets a single line for the sign involved in this event + pub fn set_line( + &self, + index: i32, + line: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(ILjava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Int(index); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(line.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLine", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), ], ); - let res = jni.translate_error_no_gen(res)?; - crate::event::block::BlockFormEvent::from_raw(&jni, res) + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns which side is changed. + pub fn side(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/sign/Side;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSide", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::sign::Side::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn handler_list( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/BlockFormEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.block.BlockGrowEvent ( ['getHandlers', 'getHandlerList']) - /// Gets the state of the block where it will form or spread to. - pub fn new_state(&self) -> Result, Box> { - let temp_clone = crate::event::block::BlockGrowEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockGrowEvent = temp_clone.into(); - real.new_state() - } - - pub fn is_cancelled(&self) -> Result> { - let temp_clone = crate::event::block::BlockGrowEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockGrowEvent = temp_clone.into(); - real.is_cancelled() - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let temp_clone = crate::event::block::BlockGrowEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockGrowEvent = temp_clone.into(); - real.set_cancelled(cancel) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for BlockFormEvent<'mc> { - fn into(self) -> crate::event::block::BlockGrowEvent<'mc> { - crate::event::block::BlockGrowEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockFormEvent into crate::event::block::BlockGrowEvent") - } -} -#[repr(C)] -pub struct LeavesDecayEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for LeavesDecayEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for LeavesDecayEvent<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate LeavesDecayEvent from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/LeavesDecayEvent")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a LeavesDecayEvent object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> LeavesDecayEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - block: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/block/Block;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/event/block/LeavesDecayEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error_no_gen(res)?; - crate::event::block::LeavesDecayEvent::from_raw(&jni, res) - } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.z()?) } pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { @@ -3170,14 +3224,14 @@ impl<'mc> LeavesDecayEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/LeavesDecayEvent"); + let cls = jni.find_class("org/bukkit/event/block/SignChangeEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getPlayer', 'getLines', 'getLine', 'setLine', 'getSide', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) /// Gets the block involved in this event. pub fn block(&self) -> Result, Box> { let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { @@ -3192,25 +3246,25 @@ impl<'mc> LeavesDecayEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for LeavesDecayEvent<'mc> { +impl<'mc> Into> for SignChangeEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting LeavesDecayEvent into crate::event::Cancellable") + .expect("Error converting SignChangeEvent into crate::event::Cancellable") } } -impl<'mc> Into> for LeavesDecayEvent<'mc> { +impl<'mc> Into> for SignChangeEvent<'mc> { fn into(self) -> crate::event::block::BlockEvent<'mc> { crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting LeavesDecayEvent into crate::event::block::BlockEvent") + .expect("Error converting SignChangeEvent into crate::event::block::BlockEvent") } } #[repr(C)] -pub struct BlockFromToEvent<'mc>( +pub struct BlockMultiPlaceEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockFromToEvent<'mc> { +impl<'mc> JNIRaw<'mc> for BlockMultiPlaceEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3218,20 +3272,21 @@ impl<'mc> JNIRaw<'mc> for BlockFromToEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockFromToEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockMultiPlaceEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate BlockFromToEvent from null object.").into(), + eyre::eyre!("Tried to instantiate BlockMultiPlaceEvent from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockFromToEvent")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/block/BlockMultiPlaceEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockFromToEvent object, got {}", + "Invalid argument passed. Expected a BlockMultiPlaceEvent object, got {}", name ) .into()) @@ -3241,74 +3296,167 @@ impl<'mc> JNIInstantiatable<'mc> for BlockFromToEvent<'mc> { } } -impl<'mc> BlockFromToEvent<'mc> { +impl<'mc> BlockMultiPlaceEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - block: impl Into>, - to_block: impl Into>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/block/Block;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/block/Block;"; + states: Vec>, + clicked: impl Into>, + item_in_hand: impl Into>, + the_player: impl Into>, + can_build: bool, + ) -> Result, Box> { + let sig = String::from("(Ljava/util/List;Lorg/bukkit/block/Block;Lorg/bukkit/inventory/ItemStack;Lorg/bukkit/entity/Player;Z)V"); + let raw_val_1 = jni.new_object("java/util/ArrayList", "()V", vec![])?; + for v in states { + let map_val_0 = jni::objects::JValueGen::Object(v); + jni.call_method( + &raw_val_1, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_1 = jni::objects::JValueGen::Object(raw_val_1); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(to_block.into().jni_object().clone()) + jni::objects::JObject::from_raw(clicked.into().jni_object().clone()) }); - args.push(val_2); - sig += ")V"; - let cls = jni.find_class("org/bukkit/event/block/BlockFromToEvent"); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_in_hand.into().jni_object().clone()) + }); + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(the_player.into().jni_object().clone()) + }); + let val_5 = jni::objects::JValueGen::Bool(can_build.into()); + let cls = jni.find_class("org/bukkit/event/block/BlockMultiPlaceEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + jni::objects::JValueGen::from(val_5), + ], + ); let res = jni.translate_error_no_gen(res)?; - crate::event::block::BlockFromToEvent::from_raw(&jni, res) - } - /// Gets the BlockFace that the block is moving to. - pub fn face(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFace", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + crate::event::block::BlockMultiPlaceEvent::from_raw(&jni, res) } - /// Convenience method for getting the faced Block. - pub fn to_block(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getToBlock", sig.as_str(), vec![]); + /// Gets a list of blockstates for all blocks which were replaced by the + /// placement of the new blocks. Most of these blocks will just have a + /// Material type of AIR. + pub fn replaced_block_states( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getReplacedBlockStates", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::BlockState::from_raw(&self.0, obj)?); + } + Ok(new_vec) } + // SUPER CLASS: org.bukkit.event.block.BlockPlaceEvent ( ['getReplacedBlockStates']) pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let temp_clone = crate::event::block::BlockPlaceEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockPlaceEvent = temp_clone.into(); + real.is_cancelled() } pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + let temp_clone = crate::event::block::BlockPlaceEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockPlaceEvent = temp_clone.into(); + real.set_cancelled(cancel) + } + /// Gets the player who placed the block involved in this event. + pub fn player(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockPlaceEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockPlaceEvent = temp_clone.into(); + real.player() + } + /// Clarity method for getting the placed block. Not really needed except + /// for reasons of clarity. + pub fn block_placed(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockPlaceEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockPlaceEvent = temp_clone.into(); + real.block_placed() + } + /// Gets the BlockState for the block which was replaced. Material type air + /// mostly. + pub fn block_replaced_state( + &self, + ) -> Result, Box> { + let temp_clone = crate::event::block::BlockPlaceEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockPlaceEvent = temp_clone.into(); + real.block_replaced_state() + } + /// Gets the block that this block was placed against + pub fn block_against(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockPlaceEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockPlaceEvent = temp_clone.into(); + real.block_against() + } + /// Gets the item in the player's hand when they placed the block. + pub fn item_in_hand( + &self, + ) -> Result, Box> { + let temp_clone = crate::event::block::BlockPlaceEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockPlaceEvent = temp_clone.into(); + real.item_in_hand() + } + /// Gets the hand which placed the block + pub fn hand(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockPlaceEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockPlaceEvent = temp_clone.into(); + real.hand() + } + /// Gets the value whether the player would be allowed to build here. + /// Defaults to spawn if the server was going to stop them (such as, the + /// player is in Spawn). Note that this is an entirely different check + /// than BLOCK_CANBUILD, as this refers to a player, not universe-physics + /// rule like cactus on dirt. + pub fn can_build(&self) -> Result> { + let temp_clone = crate::event::block::BlockPlaceEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockPlaceEvent = temp_clone.into(); + real.can_build() + } + /// Sets the canBuild state of this event. Set to true if you want the + /// player to be able to build. + pub fn set_build(&self, can_build: bool) -> Result<(), Box> { + let temp_clone = crate::event::block::BlockPlaceEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockPlaceEvent = temp_clone.into(); + real.set_build(can_build) } pub fn handlers(&self) -> Result, Box> { @@ -3325,22 +3473,7 @@ impl<'mc> BlockFromToEvent<'mc> { pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/BlockFromToEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getFace', 'getToBlock', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) - /// Gets the block involved in this event. - pub fn block(&self) -> Result, Box> { - let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockEvent = temp_clone.into(); - real.block() + crate::event::block::BlockPlaceEvent::handler_list(jni) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -3348,25 +3481,20 @@ impl<'mc> BlockFromToEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockFromToEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockFromToEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for BlockFromToEvent<'mc> { - fn into(self) -> crate::event::block::BlockEvent<'mc> { - crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockFromToEvent into crate::event::block::BlockEvent") +impl<'mc> Into> for BlockMultiPlaceEvent<'mc> { + fn into(self) -> crate::event::block::BlockPlaceEvent<'mc> { + crate::event::block::BlockPlaceEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting BlockMultiPlaceEvent into crate::event::block::BlockPlaceEvent", + ) } } #[repr(C)] -pub struct CampfireStartEvent<'mc>( +pub struct BlockBurnEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for CampfireStartEvent<'mc> { +impl<'mc> JNIRaw<'mc> for BlockBurnEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3374,20 +3502,20 @@ impl<'mc> JNIRaw<'mc> for CampfireStartEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for CampfireStartEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockBurnEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate CampfireStartEvent from null object.").into(), + eyre::eyre!("Tried to instantiate BlockBurnEvent from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/CampfireStartEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockBurnEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a CampfireStartEvent object, got {}", + "Invalid argument passed. Expected a BlockBurnEvent object, got {}", name ) .into()) @@ -3397,69 +3525,69 @@ impl<'mc> JNIInstantiatable<'mc> for CampfireStartEvent<'mc> { } } -impl<'mc> CampfireStartEvent<'mc> { +impl<'mc> BlockBurnEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - furnace: impl Into>, - source: impl Into>, - recipe: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/inventory/ItemStack;Lorg/bukkit/inventory/CampfireRecipe;)V"); + block: impl Into>, + igniting_block: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/block/Block;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(furnace.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(source.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) + jni::objects::JObject::from_raw(block.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/block/CampfireStartEvent"); + args.push(val_1); + if let Some(a) = igniting_block { + sig += "Lorg/bukkit/block/Block;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/block/BlockBurnEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); + let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::block::CampfireStartEvent::from_raw(&jni, res) + crate::event::block::BlockBurnEvent::from_raw(&jni, res) } - /// Gets the CampfireRecipe associated with this event. - pub fn recipe( + /// Gets the block which ignited this block. + pub fn igniting_block( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/CampfireRecipe;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getRecipe", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::CampfireRecipe::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the total cook time associated with this event. - pub fn total_cook_time(&self) -> Result> { - let sig = String::from("()I"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getTotalCookTime", + "getIgnitingBlock", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::block::Block::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the total cook time for this event. - pub fn set_total_cook_time(&self, cook_time: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(cook_time); + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setTotalCookTime", + "setCancelled", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -3482,22 +3610,21 @@ impl<'mc> CampfireStartEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/CampfireStartEvent"); + let cls = jni.find_class("org/bukkit/event/block/BlockBurnEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.block.InventoryBlockStartEvent ( ['getRecipe', 'getTotalCookTime', 'setTotalCookTime', 'getHandlers', 'getHandlerList']) - /// Gets the source ItemStack for this event. - pub fn source(&self) -> Result, Box> { - let temp_clone = - crate::event::block::InventoryBlockStartEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::InventoryBlockStartEvent = temp_clone.into(); - real.source() + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getIgnitingBlock', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + /// Gets the block involved in this event. + pub fn block(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockEvent = temp_clone.into(); + real.block() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -3505,18 +3632,25 @@ impl<'mc> CampfireStartEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for CampfireStartEvent<'mc> { - fn into(self) -> crate::event::block::InventoryBlockStartEvent<'mc> { - crate::event::block::InventoryBlockStartEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting CampfireStartEvent into crate::event::block::InventoryBlockStartEvent") +impl<'mc> Into> for BlockBurnEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockBurnEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for BlockBurnEvent<'mc> { + fn into(self) -> crate::event::block::BlockEvent<'mc> { + crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockBurnEvent into crate::event::block::BlockEvent") } } #[repr(C)] -pub struct BlockExplodeEvent<'mc>( +pub struct BlockDropItemEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockExplodeEvent<'mc> { +impl<'mc> JNIRaw<'mc> for BlockDropItemEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3524,20 +3658,20 @@ impl<'mc> JNIRaw<'mc> for BlockExplodeEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockExplodeEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockDropItemEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate BlockExplodeEvent from null object.").into(), + eyre::eyre!("Tried to instantiate BlockDropItemEvent from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockExplodeEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockDropItemEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockExplodeEvent object, got {}", + "Invalid argument passed. Expected a BlockDropItemEvent object, got {}", name ) .into()) @@ -3547,123 +3681,107 @@ impl<'mc> JNIInstantiatable<'mc> for BlockExplodeEvent<'mc> { } } -impl<'mc> BlockExplodeEvent<'mc> { +impl<'mc> BlockDropItemEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - what: impl Into>, + block: impl Into>, block_state: impl Into>, - blocks: Vec>, - val_yield: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/block/Block;"; + player: impl Into>, + items: Vec>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/block/BlockState;Lorg/bukkit/entity/Player;Ljava/util/List;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(what.into().jni_object().clone()) + jni::objects::JObject::from_raw(block.into().jni_object().clone()) }); - args.push(val_1); - sig += "Lorg/bukkit/block/BlockState;"; let val_2 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(block_state.into().jni_object().clone()) }); - args.push(val_2); - sig += "Ljava/util/List;"; - let raw_val_3 = jni.new_object("java/util/ArrayList", "()V", vec![])?; - for v in blocks { - sig += "Ljava/lang/java/lang/Object;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(player.into().jni_object().clone()) + }); + let raw_val_4 = jni.new_object("java/util/ArrayList", "()V", vec![])?; + for v in items { let map_val_0 = jni::objects::JValueGen::Object(v); jni.call_method( - &raw_val_3, + &raw_val_4, "add", "(Ljava/lang/Object;)Z", vec![jni::objects::JValueGen::from(map_val_0)], )?; } - let val_3 = jni::objects::JValueGen::Object(raw_val_3); - args.push(val_3); - if let Some(a) = val_yield { - sig += "F"; - let val_4 = jni::objects::JValueGen::Float(a); - args.push(val_4); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/event/block/BlockExplodeEvent"); + let val_4 = jni::objects::JValueGen::Object(raw_val_4); + let cls = jni.find_class("org/bukkit/event/block/BlockDropItemEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + ], + ); let res = jni.translate_error_no_gen(res)?; - crate::event::block::BlockExplodeEvent::from_raw(&jni, res) + crate::event::block::BlockDropItemEvent::from_raw(&jni, res) } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + /// Gets the Player that is breaking the block involved in this event. + pub fn player(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::entity::Player::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the captured BlockState of the block that exploded. - pub fn exploded_block_state( - &self, - ) -> Result, Box> { + /// Gets the BlockState of the block involved in this event before it was + /// broken. + pub fn block_state(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/block/BlockState;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getExplodedBlockState", - sig.as_str(), - vec![], - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBlockState", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns the list of blocks that would have been removed or were removed - /// from the explosion event. - pub fn block_list(&self) -> Result>, Box> { + /// Gets list of the Item drops caused by the block break. + /// This list is mutable - removing an item from it will cause it to not + /// drop. It is not legal however to add new items to the list. + pub fn items(&self) -> Result>, Box> { let sig = String::from("()Ljava/util/List;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "blockList", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItems", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.0, obj)?); + new_vec.push(crate::entity::Item::from_raw(&self.0, obj)?); } Ok(new_vec) } - /// Returns the percentage of blocks to drop from this explosion - pub fn get_yield(&self) -> Result> { - let sig = String::from("()F"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getYield", sig.as_str(), vec![]); + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + Ok(res.z()?) } - /// Sets the percentage of blocks to drop from this explosion - pub fn set_yield(&self, val_yield: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(val_yield); + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setYield", + "setCancelled", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -3686,14 +3804,14 @@ impl<'mc> BlockExplodeEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/BlockExplodeEvent"); + let cls = jni.find_class("org/bukkit/event/block/BlockDropItemEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['isCancelled', 'setCancelled', 'getExplodedBlockState', 'blockList', 'getYield', 'setYield', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getPlayer', 'getBlockState', 'getItems', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) /// Gets the block involved in this event. pub fn block(&self) -> Result, Box> { let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { @@ -3708,25 +3826,25 @@ impl<'mc> BlockExplodeEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockExplodeEvent<'mc> { +impl<'mc> Into> for BlockDropItemEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockExplodeEvent into crate::event::Cancellable") + .expect("Error converting BlockDropItemEvent into crate::event::Cancellable") } } -impl<'mc> Into> for BlockExplodeEvent<'mc> { +impl<'mc> Into> for BlockDropItemEvent<'mc> { fn into(self) -> crate::event::block::BlockEvent<'mc> { crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockExplodeEvent into crate::event::block::BlockEvent") + .expect("Error converting BlockDropItemEvent into crate::event::block::BlockEvent") } } #[repr(C)] -pub struct BlockCanBuildEvent<'mc>( +pub struct BlockSpreadEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockCanBuildEvent<'mc> { +impl<'mc> JNIRaw<'mc> for BlockSpreadEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3734,20 +3852,20 @@ impl<'mc> JNIRaw<'mc> for BlockCanBuildEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockCanBuildEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockSpreadEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate BlockCanBuildEvent from null object.").into(), + eyre::eyre!("Tried to instantiate BlockSpreadEvent from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockCanBuildEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockSpreadEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockCanBuildEvent object, got {}", + "Invalid argument passed. Expected a BlockSpreadEvent object, got {}", name ) .into()) @@ -3757,117 +3875,58 @@ impl<'mc> JNIInstantiatable<'mc> for BlockCanBuildEvent<'mc> { } } -impl<'mc> BlockCanBuildEvent<'mc> { +impl<'mc> BlockSpreadEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, block: impl Into>, - player: impl Into>, - val_type: impl Into>, - can_build: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/block/Block;"; + source: impl Into>, + new_state: impl Into>, + ) -> Result, Box> { + let sig = String::from( + "(Lorg/bukkit/block/Block;Lorg/bukkit/block/Block;Lorg/bukkit/block/BlockState;)V", + ); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(block.into().jni_object().clone()) }); - args.push(val_1); - sig += "Lorg/bukkit/entity/Player;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) + jni::objects::JObject::from_raw(source.into().jni_object().clone()) }); - args.push(val_2); - sig += "Lorg/bukkit/block/data/BlockData;"; let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(new_state.into().jni_object().clone()) }); - args.push(val_3); - if let Some(a) = can_build { - sig += "Z"; - let val_4 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_4); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/event/block/BlockCanBuildEvent"); + let cls = jni.find_class("org/bukkit/event/block/BlockSpreadEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::event::block::BlockCanBuildEvent::from_raw(&jni, res) - } - /// Gets whether or not the block can be built here. - /// - /// By default, returns Minecraft's answer on whether the block can be - /// built here or not. - pub fn is_buildable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isBuildable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether the block can be built here or not. - pub fn set_buildable(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setBuildable", + let res = jni.new_object( + cls, sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = jni.translate_error_no_gen(res)?; + crate::event::block::BlockSpreadEvent::from_raw(&jni, res) } - /// Gets the Material that we are trying to place. - pub fn material(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaterial", sig.as_str(), vec![]); + /// Gets the source block involved in this event. + pub fn source(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSource", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { + crate::block::Block::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the BlockData that we are trying to place. - pub fn block_data( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBlockData", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the player who placed the block involved in this event. - /// - /// May be null for legacy calls of the event. - pub fn player(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Player;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Player::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -3876,41 +3935,33 @@ impl<'mc> BlockCanBuildEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/BlockCanBuildEvent"); + let cls = jni.find_class("org/bukkit/event/block/BlockSpreadEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['isBuildable', 'setBuildable', 'getMaterial', 'getBlockData', 'getPlayer', 'getHandlers', 'getHandlerList']) - /// Gets the block involved in this event. - pub fn block(&self) -> Result, Box> { - let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockEvent = temp_clone.into(); - real.block() - } + // SUPER CLASS: org.bukkit.event.block.BlockFormEvent ( ['getSource', 'getHandlers', 'getHandlerList']) pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockCanBuildEvent<'mc> { - fn into(self) -> crate::event::block::BlockEvent<'mc> { - crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockCanBuildEvent into crate::event::block::BlockEvent") +impl<'mc> Into> for BlockSpreadEvent<'mc> { + fn into(self) -> crate::event::block::BlockFormEvent<'mc> { + crate::event::block::BlockFormEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockSpreadEvent into crate::event::block::BlockFormEvent") } } #[repr(C)] -pub struct MoistureChangeEvent<'mc>( +pub struct BlockGrowEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for MoistureChangeEvent<'mc> { +impl<'mc> JNIRaw<'mc> for BlockGrowEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3918,21 +3969,20 @@ impl<'mc> JNIRaw<'mc> for MoistureChangeEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for MoistureChangeEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockGrowEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate MoistureChangeEvent from null object.").into(), + eyre::eyre!("Tried to instantiate BlockGrowEvent from null object.").into(), ); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/block/MoistureChangeEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockGrowEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a MoistureChangeEvent object, got {}", + "Invalid argument passed. Expected a BlockGrowEvent object, got {}", name ) .into()) @@ -3942,12 +3992,12 @@ impl<'mc> JNIInstantiatable<'mc> for MoistureChangeEvent<'mc> { } } -impl<'mc> MoistureChangeEvent<'mc> { +impl<'mc> BlockGrowEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, block: impl Into>, new_state: impl Into>, - ) -> Result, Box> { + ) -> Result, Box> { let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/block/BlockState;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(block.into().jni_object().clone()) @@ -3955,7 +4005,7 @@ impl<'mc> MoistureChangeEvent<'mc> { let val_2 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(new_state.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/block/MoistureChangeEvent"); + let cls = jni.find_class("org/bukkit/event/block/BlockGrowEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -3966,9 +4016,9 @@ impl<'mc> MoistureChangeEvent<'mc> { ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::block::MoistureChangeEvent::from_raw(&jni, res) + crate::event::block::BlockGrowEvent::from_raw(&jni, res) } - /// Gets the new state of the affected block. + /// Gets the state of the block where it will form or spread to. pub fn new_state(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/block/BlockState;"); let res = @@ -4017,7 +4067,7 @@ impl<'mc> MoistureChangeEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/MoistureChangeEvent"); + let cls = jni.find_class("org/bukkit/event/block/BlockGrowEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; @@ -4039,25 +4089,25 @@ impl<'mc> MoistureChangeEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for MoistureChangeEvent<'mc> { +impl<'mc> Into> for BlockGrowEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting MoistureChangeEvent into crate::event::Cancellable") + .expect("Error converting BlockGrowEvent into crate::event::Cancellable") } } -impl<'mc> Into> for MoistureChangeEvent<'mc> { +impl<'mc> Into> for BlockGrowEvent<'mc> { fn into(self) -> crate::event::block::BlockEvent<'mc> { crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting MoistureChangeEvent into crate::event::block::BlockEvent") + .expect("Error converting BlockGrowEvent into crate::event::block::BlockEvent") } } #[repr(C)] -pub struct TNTPrimeEvent<'mc>( +pub struct BlockFormEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for TNTPrimeEvent<'mc> { +impl<'mc> JNIRaw<'mc> for BlockFormEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -4065,18 +4115,20 @@ impl<'mc> JNIRaw<'mc> for TNTPrimeEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for TNTPrimeEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockFormEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate TNTPrimeEvent from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate BlockFormEvent from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/TNTPrimeEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockFormEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a TNTPrimeEvent object, got {}", + "Invalid argument passed. Expected a BlockFormEvent object, got {}", name ) .into()) @@ -4086,28 +4138,20 @@ impl<'mc> JNIInstantiatable<'mc> for TNTPrimeEvent<'mc> { } } -impl<'mc> TNTPrimeEvent<'mc> { +impl<'mc> BlockFormEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, block: impl Into>, - ignite_cause: impl Into>, - priming_entity: impl Into>, - priming_block: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/event/block/TNTPrimeEvent/PrimeCause;Lorg/bukkit/entity/Entity;Lorg/bukkit/block/Block;)V"); + new_state: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/block/BlockState;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(block.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ignite_cause.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(priming_entity.into().jni_object().clone()) - }); - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(priming_block.into().jni_object().clone()) + jni::objects::JObject::from_raw(new_state.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/block/TNTPrimeEvent"); + let cls = jni.find_class("org/bukkit/event/block/BlockFormEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -4115,84 +4159,10 @@ impl<'mc> TNTPrimeEvent<'mc> { vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::block::TNTPrimeEvent::from_raw(&jni, res) - } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the cause of the TNT becoming primed. - pub fn cause( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/block/TNTPrimeEvent/PrimeCause;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getCause", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::block::TNTPrimeEventPrimeCause::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the entity that caused the TNT to be primed. - pub fn priming_entity( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPrimingEntity", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Get the block that caused the TNT to be primed. - pub fn priming_block( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPrimingBlock", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::block::Block::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::event::block::BlockFormEvent::from_raw(&jni, res) } pub fn handlers(&self) -> Result, Box> { @@ -4210,21 +4180,37 @@ impl<'mc> TNTPrimeEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/TNTPrimeEvent"); + let cls = jni.find_class("org/bukkit/event/block/BlockFormEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['isCancelled', 'setCancelled', 'getCause', 'getPrimingEntity', 'getPrimingBlock', 'getHandlers', 'getHandlerList']) - /// Gets the block involved in this event. - pub fn block(&self) -> Result, Box> { - let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { + // SUPER CLASS: org.bukkit.event.block.BlockGrowEvent ( ['getHandlers', 'getHandlerList']) + /// Gets the state of the block where it will form or spread to. + pub fn new_state(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockGrowEvent::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::block::BlockEvent = temp_clone.into(); - real.block() + let real: crate::event::block::BlockGrowEvent = temp_clone.into(); + real.new_state() + } + + pub fn is_cancelled(&self) -> Result> { + let temp_clone = crate::event::block::BlockGrowEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockGrowEvent = temp_clone.into(); + real.is_cancelled() + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let temp_clone = crate::event::block::BlockGrowEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockGrowEvent = temp_clone.into(); + real.set_cancelled(cancel) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -4232,177 +4218,40 @@ impl<'mc> TNTPrimeEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for TNTPrimeEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting TNTPrimeEvent into crate::event::Cancellable") +impl<'mc> Into> for BlockFormEvent<'mc> { + fn into(self) -> crate::event::block::BlockGrowEvent<'mc> { + crate::event::block::BlockGrowEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockFormEvent into crate::event::block::BlockGrowEvent") } } -impl<'mc> Into> for TNTPrimeEvent<'mc> { - fn into(self) -> crate::event::block::BlockEvent<'mc> { - crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting TNTPrimeEvent into crate::event::block::BlockEvent") +#[repr(C)] +pub struct LeavesDecayEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for LeavesDecayEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } -} -pub enum TNTPrimeEventPrimeCause<'mc> {} -impl<'mc> std::fmt::Display for TNTPrimeEventPrimeCause<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } - -impl<'mc> TNTPrimeEventPrimeCause<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/event/block/TNTPrimeEvent/PrimeCause"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/event/block/TNTPrimeEvent/PrimeCause;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct TNTPrimeEventPrimeCauseStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for TNTPrimeEventPrimeCause<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for TNTPrimeEventPrimeCause<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate TNTPrimeEventPrimeCause from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/block/TNTPrimeEvent/PrimeCause")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a TNTPrimeEventPrimeCause object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for TNTPrimeEventPrimeCauseStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for TNTPrimeEventPrimeCauseStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate TNTPrimeEventPrimeCauseStruct from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/block/TNTPrimeEvent/PrimeCause")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a TNTPrimeEventPrimeCauseStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> TNTPrimeEventPrimeCauseStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/block/TNTPrimeEvent/PrimeCause;"); - let cls = jni.find_class("org/bukkit/event/block/TNTPrimeEvent/PrimeCause"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::block::TNTPrimeEventPrimeCause::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct NotePlayEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for NotePlayEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for NotePlayEvent<'mc> { - fn from_raw( +impl<'mc> JNIInstantiatable<'mc> for LeavesDecayEvent<'mc> { + fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate NotePlayEvent from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate LeavesDecayEvent from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/NotePlayEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/LeavesDecayEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a NotePlayEvent object, got {}", + "Invalid argument passed. Expected a LeavesDecayEvent object, got {}", name ) .into()) @@ -4412,37 +4261,24 @@ impl<'mc> JNIInstantiatable<'mc> for NotePlayEvent<'mc> { } } -impl<'mc> NotePlayEvent<'mc> { +impl<'mc> LeavesDecayEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, block: impl Into>, - instrument: impl Into>, - note: impl Into>, - ) -> Result, Box> { - let sig = - String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/Instrument;Lorg/bukkit/Note;)V"); + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/block/Block;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(block.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(instrument.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(note.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/event/block/NotePlayEvent"); + let cls = jni.find_class("org/bukkit/event/block/LeavesDecayEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = jni.translate_error_no_gen(res)?; - crate::event::block::NotePlayEvent::from_raw(&jni, res) + crate::event::block::LeavesDecayEvent::from_raw(&jni, res) } pub fn is_cancelled(&self) -> Result> { @@ -4466,66 +4302,6 @@ impl<'mc> NotePlayEvent<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the {@link Instrument} to be used. - pub fn instrument(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Instrument;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInstrument", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Instrument::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the {@link Note} to be played. - pub fn note(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Note;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getNote", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Note::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - #[deprecated] - /// Overrides the {@link Instrument} to be used. - pub fn set_instrument( - &self, - instrument: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Instrument;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(instrument.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setInstrument", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Overrides the {@link Note} to be played. - pub fn set_note( - &self, - note: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Note;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(note.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setNote", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -4542,14 +4318,14 @@ impl<'mc> NotePlayEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/NotePlayEvent"); + let cls = jni.find_class("org/bukkit/event/block/LeavesDecayEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['isCancelled', 'setCancelled', 'getInstrument', 'getNote', 'setInstrument', 'setNote', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) /// Gets the block involved in this event. pub fn block(&self) -> Result, Box> { let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { @@ -4564,25 +4340,25 @@ impl<'mc> NotePlayEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for NotePlayEvent<'mc> { +impl<'mc> Into> for LeavesDecayEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting NotePlayEvent into crate::event::Cancellable") + .expect("Error converting LeavesDecayEvent into crate::event::Cancellable") } } -impl<'mc> Into> for NotePlayEvent<'mc> { +impl<'mc> Into> for LeavesDecayEvent<'mc> { fn into(self) -> crate::event::block::BlockEvent<'mc> { crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting NotePlayEvent into crate::event::block::BlockEvent") + .expect("Error converting LeavesDecayEvent into crate::event::block::BlockEvent") } } #[repr(C)] -pub struct BlockExpEvent<'mc>( +pub struct CampfireStartEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockExpEvent<'mc> { +impl<'mc> JNIRaw<'mc> for CampfireStartEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -4590,18 +4366,20 @@ impl<'mc> JNIRaw<'mc> for BlockExpEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockExpEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CampfireStartEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate BlockExpEvent from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate CampfireStartEvent from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockExpEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/CampfireStartEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockExpEvent object, got {}", + "Invalid argument passed. Expected a CampfireStartEvent object, got {}", name ) .into()) @@ -4611,18 +4389,24 @@ impl<'mc> JNIInstantiatable<'mc> for BlockExpEvent<'mc> { } } -impl<'mc> BlockExpEvent<'mc> { +impl<'mc> CampfireStartEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - block: impl Into>, - exp: i32, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/block/Block;I)V"); + furnace: impl Into>, + source: impl Into>, + recipe: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/inventory/ItemStack;Lorg/bukkit/inventory/CampfireRecipe;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) + jni::objects::JObject::from_raw(furnace.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(exp); - let cls = jni.find_class("org/bukkit/event/block/BlockExpEvent"); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(source.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/block/CampfireStartEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -4630,28 +4414,44 @@ impl<'mc> BlockExpEvent<'mc> { vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::block::BlockExpEvent::from_raw(&jni, res) + crate::event::block::CampfireStartEvent::from_raw(&jni, res) } - /// Get the experience dropped by the block after the event has processed - pub fn exp_to_drop(&self) -> Result> { + /// Gets the CampfireRecipe associated with this event. + pub fn recipe( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/CampfireRecipe;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRecipe", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::CampfireRecipe::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the total cook time associated with this event. + pub fn total_cook_time(&self) -> Result> { let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getExpToDrop", sig.as_str(), vec![]); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTotalCookTime", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Set the amount of experience dropped by the block after the event has - /// processed - pub fn set_exp_to_drop(&self, exp: i32) -> Result<(), Box> { + /// Sets the total cook time for this event. + pub fn set_total_cook_time(&self, cook_time: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(exp); + let val_1 = jni::objects::JValueGen::Int(cook_time); let res = self.jni_ref().call_method( &self.jni_object(), - "setExpToDrop", + "setTotalCookTime", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -4674,21 +4474,22 @@ impl<'mc> BlockExpEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/BlockExpEvent"); + let cls = jni.find_class("org/bukkit/event/block/CampfireStartEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getExpToDrop', 'setExpToDrop', 'getHandlers', 'getHandlerList']) - /// Gets the block involved in this event. - pub fn block(&self) -> Result, Box> { - let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockEvent = temp_clone.into(); - real.block() + // SUPER CLASS: org.bukkit.event.block.InventoryBlockStartEvent ( ['getRecipe', 'getTotalCookTime', 'setTotalCookTime', 'getHandlers', 'getHandlerList']) + /// Gets the source ItemStack for this event. + pub fn source(&self) -> Result, Box> { + let temp_clone = + crate::event::block::InventoryBlockStartEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::InventoryBlockStartEvent = temp_clone.into(); + real.source() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -4696,19 +4497,18 @@ impl<'mc> BlockExpEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockExpEvent<'mc> { - fn into(self) -> crate::event::block::BlockEvent<'mc> { - crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockExpEvent into crate::event::block::BlockEvent") +impl<'mc> Into> for CampfireStartEvent<'mc> { + fn into(self) -> crate::event::block::InventoryBlockStartEvent<'mc> { + crate::event::block::InventoryBlockStartEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting CampfireStartEvent into crate::event::block::InventoryBlockStartEvent") } } #[repr(C)] -pub struct BlockDamageAbortEvent<'mc>( +pub struct BlockExplodeEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockDamageAbortEvent<'mc> { +impl<'mc> JNIRaw<'mc> for BlockExplodeEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -4716,22 +4516,20 @@ impl<'mc> JNIRaw<'mc> for BlockDamageAbortEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockDamageAbortEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockExplodeEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate BlockDamageAbortEvent from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate BlockExplodeEvent from null object.").into(), + ); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/block/BlockDamageAbortEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockExplodeEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockDamageAbortEvent object, got {}", + "Invalid argument passed. Expected a BlockExplodeEvent object, got {}", name ) .into()) @@ -4741,26 +4539,38 @@ impl<'mc> JNIInstantiatable<'mc> for BlockDamageAbortEvent<'mc> { } } -impl<'mc> BlockDamageAbortEvent<'mc> { +impl<'mc> BlockExplodeEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - player: impl Into>, - block: impl Into>, - item_in_hand: impl Into>, - ) -> Result, Box> { - let sig = String::from( - "(Lorg/bukkit/entity/Player;Lorg/bukkit/block/Block;Lorg/bukkit/inventory/ItemStack;)V", - ); + what: impl Into>, + block_state: impl Into>, + blocks: Vec>, + val_yield: f32, + result: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/block/BlockState;Ljava/util/List;FLorg/bukkit/ExplosionResult;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) + jni::objects::JObject::from_raw(what.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) + jni::objects::JObject::from_raw(block_state.into().jni_object().clone()) }); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_in_hand.into().jni_object().clone()) + let raw_val_3 = jni.new_object("java/util/ArrayList", "()V", vec![])?; + for v in blocks { + let map_val_0 = jni::objects::JValueGen::Object(v); + jni.call_method( + &raw_val_3, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_3 = jni::objects::JValueGen::Object(raw_val_3); + let val_4 = jni::objects::JValueGen::Float(val_yield); + let val_5 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(result.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/block/BlockDamageAbortEvent"); + let cls = jni.find_class("org/bukkit/event/block/BlockExplodeEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -4769,35 +4579,106 @@ impl<'mc> BlockDamageAbortEvent<'mc> { jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + jni::objects::JValueGen::from(val_5), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::block::BlockDamageAbortEvent::from_raw(&jni, res) + crate::event::block::BlockExplodeEvent::from_raw(&jni, res) } - /// Gets the player that stopped damaging the block involved in this event. - pub fn player(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Player;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Player::from_raw(&self.jni_ref(), unsafe { + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the result of the explosion if it is not cancelled. + pub fn explosion_result( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/ExplosionResult;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getExplosionResult", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::ExplosionResult::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the ItemStack for the item currently in the player's hand. - pub fn item_in_hand( + /// Returns the captured BlockState of the block that exploded. + pub fn exploded_block_state( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemInHand", sig.as_str(), vec![]); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockState;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getExplodedBlockState", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } + /// Returns the list of blocks that would have been removed or were removed + /// from the explosion event. + pub fn block_list(&self) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "blockList", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::Block::from_raw(&self.0, obj)?); + } + Ok(new_vec) + } + /// Returns the percentage of blocks to drop from this explosion + pub fn get_yield(&self) -> Result> { + let sig = String::from("()F"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getYield", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the percentage of blocks to drop from this explosion + pub fn set_yield(&self, val_yield: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(val_yield); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setYield", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -4814,14 +4695,14 @@ impl<'mc> BlockDamageAbortEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/BlockDamageAbortEvent"); + let cls = jni.find_class("org/bukkit/event/block/BlockExplodeEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getPlayer', 'getItemInHand', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['isCancelled', 'setCancelled', 'getExplosionResult', 'getExplodedBlockState', 'blockList', 'getYield', 'setYield', 'getHandlers', 'getHandlerList']) /// Gets the block involved in this event. pub fn block(&self) -> Result, Box> { let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { @@ -4836,19 +4717,25 @@ impl<'mc> BlockDamageAbortEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockDamageAbortEvent<'mc> { +impl<'mc> Into> for BlockExplodeEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockExplodeEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for BlockExplodeEvent<'mc> { fn into(self) -> crate::event::block::BlockEvent<'mc> { crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockDamageAbortEvent into crate::event::block::BlockEvent") + .expect("Error converting BlockExplodeEvent into crate::event::block::BlockEvent") } } #[repr(C)] -pub struct BlockFadeEvent<'mc>( +pub struct BlockCanBuildEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockFadeEvent<'mc> { +impl<'mc> JNIRaw<'mc> for BlockCanBuildEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -4856,20 +4743,20 @@ impl<'mc> JNIRaw<'mc> for BlockFadeEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockFadeEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockCanBuildEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate BlockFadeEvent from null object.").into(), + eyre::eyre!("Tried to instantiate BlockCanBuildEvent from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockFadeEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockCanBuildEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockFadeEvent object, got {}", + "Invalid argument passed. Expected a BlockCanBuildEvent object, got {}", name ) .into()) @@ -4879,66 +4766,109 @@ impl<'mc> JNIInstantiatable<'mc> for BlockFadeEvent<'mc> { } } -impl<'mc> BlockFadeEvent<'mc> { +impl<'mc> BlockCanBuildEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, block: impl Into>, - new_state: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/block/BlockState;)V"); + player: impl Into>, + val_type: impl Into>, + can_build: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/block/Block;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(block.into().jni_object().clone()) }); + args.push(val_1); + sig += "Lorg/bukkit/entity/Player;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_state.into().jni_object().clone()) + jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/block/BlockFadeEvent"); + args.push(val_2); + sig += "Lorg/bukkit/block/data/BlockData;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + args.push(val_3); + if let Some(a) = can_build { + sig += "Z"; + let val_4 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_4); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/block/BlockCanBuildEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::block::BlockFadeEvent::from_raw(&jni, res) - } - /// Gets the state of the block that will be fading, melting or - /// disappearing. - pub fn new_state(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockState;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getNewState", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + crate::event::block::BlockCanBuildEvent::from_raw(&jni, res) } - - pub fn is_cancelled(&self) -> Result> { + /// Gets whether or not the block can be built here. + /// + /// By default, returns Minecraft's answer on whether the block can be + /// built here or not. + pub fn is_buildable(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isBuildable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + /// Sets whether the block can be built here or not. + pub fn set_buildable(&self, cancel: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); let val_1 = jni::objects::JValueGen::Bool(cancel.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCancelled", + "setBuildable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } + /// Gets the Material that we are trying to place. + pub fn material(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaterial", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the BlockData that we are trying to place. + pub fn block_data( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBlockData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the player who placed the block involved in this event. + /// + /// May be null for legacy calls of the event. + pub fn player(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Player::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -4955,14 +4885,14 @@ impl<'mc> BlockFadeEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/BlockFadeEvent"); + let cls = jni.find_class("org/bukkit/event/block/BlockCanBuildEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getNewState', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['isBuildable', 'setBuildable', 'getMaterial', 'getBlockData', 'getPlayer', 'getHandlers', 'getHandlerList']) /// Gets the block involved in this event. pub fn block(&self) -> Result, Box> { let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { @@ -4977,25 +4907,19 @@ impl<'mc> BlockFadeEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockFadeEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockFadeEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for BlockFadeEvent<'mc> { +impl<'mc> Into> for BlockCanBuildEvent<'mc> { fn into(self) -> crate::event::block::BlockEvent<'mc> { crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockFadeEvent into crate::event::block::BlockEvent") + .expect("Error converting BlockCanBuildEvent into crate::event::block::BlockEvent") } } #[repr(C)] -pub struct BellResonateEvent<'mc>( +pub struct InventoryBlockStartEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BellResonateEvent<'mc> { +impl<'mc> JNIRaw<'mc> for InventoryBlockStartEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -5003,20 +4927,22 @@ impl<'mc> JNIRaw<'mc> for BellResonateEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BellResonateEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for InventoryBlockStartEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate BellResonateEvent from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate InventoryBlockStartEvent from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BellResonateEvent")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/block/InventoryBlockStartEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BellResonateEvent object, got {}", + "Invalid argument passed. Expected a InventoryBlockStartEvent object, got {}", name ) .into()) @@ -5026,28 +4952,21 @@ impl<'mc> JNIInstantiatable<'mc> for BellResonateEvent<'mc> { } } -impl<'mc> BellResonateEvent<'mc> { +impl<'mc> InventoryBlockStartEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - the_block: impl Into>, - resonated_entities: Vec>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/block/Block;Ljava/util/List;)V"); + block: impl Into>, + source: impl Into>, + ) -> Result, Box> + { + let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(the_block.into().jni_object().clone()) + jni::objects::JObject::from_raw(block.into().jni_object().clone()) }); - let raw_val_2 = jni.new_object("java/util/ArrayList", "()V", vec![])?; - for v in resonated_entities { - let map_val_0 = jni::objects::JValueGen::Object(v); - jni.call_method( - &raw_val_2, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_2 = jni::objects::JValueGen::Object(raw_val_2); - let cls = jni.find_class("org/bukkit/event/block/BellResonateEvent"); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(source.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/block/InventoryBlockStartEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -5058,35 +4977,18 @@ impl<'mc> BellResonateEvent<'mc> { ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::block::BellResonateEvent::from_raw(&jni, res) + crate::event::block::InventoryBlockStartEvent::from_raw(&jni, res) } - /// Get a mutable list of all {@link LivingEntity LivingEntities} to be - /// highlighted by the bell's resonating. This list can be added to or - /// removed from to change which entities are highlighted, and may be empty - /// if no entities were resonated as a result of this event. - /// - /// While the highlighted entities will change, the particles that display - /// over a resonated entity and their colors will not. This is handled by the - /// client and cannot be controlled by the server. - pub fn resonated_entities( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getResonatedEntities", - sig.as_str(), - vec![], - ); + /// Gets the source ItemStack for this event. + pub fn source(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSource", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::LivingEntity::from_raw(&self.0, obj)?); - } - Ok(new_vec) + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn handlers(&self) -> Result, Box> { @@ -5104,14 +5006,14 @@ impl<'mc> BellResonateEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/BellResonateEvent"); + let cls = jni.find_class("org/bukkit/event/block/InventoryBlockStartEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getResonatedEntities', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getSource', 'getHandlers', 'getHandlerList']) /// Gets the block involved in this event. pub fn block(&self) -> Result, Box> { let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { @@ -5126,19 +5028,20 @@ impl<'mc> BellResonateEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BellResonateEvent<'mc> { +impl<'mc> Into> for InventoryBlockStartEvent<'mc> { fn into(self) -> crate::event::block::BlockEvent<'mc> { - crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BellResonateEvent into crate::event::block::BlockEvent") + crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting InventoryBlockStartEvent into crate::event::block::BlockEvent", + ) } } #[repr(C)] -pub struct BlockDispenseEvent<'mc>( +pub struct MoistureChangeEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockDispenseEvent<'mc> { +impl<'mc> JNIRaw<'mc> for MoistureChangeEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -5146,20 +5049,21 @@ impl<'mc> JNIRaw<'mc> for BlockDispenseEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockDispenseEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for MoistureChangeEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate BlockDispenseEvent from null object.").into(), + eyre::eyre!("Tried to instantiate MoistureChangeEvent from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockDispenseEvent")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/block/MoistureChangeEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockDispenseEvent object, got {}", + "Invalid argument passed. Expected a MoistureChangeEvent object, got {}", name ) .into()) @@ -5169,26 +5073,20 @@ impl<'mc> JNIInstantiatable<'mc> for BlockDispenseEvent<'mc> { } } -impl<'mc> BlockDispenseEvent<'mc> { +impl<'mc> MoistureChangeEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, block: impl Into>, - dispensed: impl Into>, - velocity: impl Into>, - ) -> Result, Box> { - let sig = String::from( - "(Lorg/bukkit/block/Block;Lorg/bukkit/inventory/ItemStack;Lorg/bukkit/util/Vector;)V", - ); + new_state: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/block/BlockState;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(block.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(dispensed.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + jni::objects::JObject::from_raw(new_state.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/block/BlockDispenseEvent"); + let cls = jni.find_class("org/bukkit/event/block/MoistureChangeEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -5196,75 +5094,22 @@ impl<'mc> BlockDispenseEvent<'mc> { vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::block::BlockDispenseEvent::from_raw(&jni, res) + crate::event::block::MoistureChangeEvent::from_raw(&jni, res) } - /// Gets the item that is being dispensed. Modifying the returned item will - /// have no effect, you must use {@link - /// #setItem(org.bukkit.inventory.ItemStack)} instead. - pub fn item(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the item being dispensed. - pub fn set_item( - &self, - item: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setItem", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the velocity in meters per tick. - /// - /// Note: Modifying the returned Vector will not change the velocity, you - /// must use {@link #setVelocity(org.bukkit.util.Vector)} instead. - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); + /// Gets the new state of the affected block. + pub fn new_state(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockState;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getNewState", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the velocity of the item being dispensed in meters per tick. - pub fn set_velocity( - &self, - vel: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(vel.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setVelocity", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } pub fn is_cancelled(&self) -> Result> { let sig = String::from("()Z"); @@ -5303,14 +5148,14 @@ impl<'mc> BlockDispenseEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/BlockDispenseEvent"); + let cls = jni.find_class("org/bukkit/event/block/MoistureChangeEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getItem', 'setItem', 'getVelocity', 'setVelocity', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getNewState', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) /// Gets the block involved in this event. pub fn block(&self) -> Result, Box> { let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { @@ -5325,25 +5170,25 @@ impl<'mc> BlockDispenseEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockDispenseEvent<'mc> { +impl<'mc> Into> for MoistureChangeEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockDispenseEvent into crate::event::Cancellable") + .expect("Error converting MoistureChangeEvent into crate::event::Cancellable") } } -impl<'mc> Into> for BlockDispenseEvent<'mc> { +impl<'mc> Into> for MoistureChangeEvent<'mc> { fn into(self) -> crate::event::block::BlockEvent<'mc> { crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockDispenseEvent into crate::event::block::BlockEvent") + .expect("Error converting MoistureChangeEvent into crate::event::block::BlockEvent") } } #[repr(C)] -pub struct BlockDamageEvent<'mc>( +pub struct TNTPrimeEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockDamageEvent<'mc> { +impl<'mc> JNIRaw<'mc> for TNTPrimeEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -5351,20 +5196,18 @@ impl<'mc> JNIRaw<'mc> for BlockDamageEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockDamageEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for TNTPrimeEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate BlockDamageEvent from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate TNTPrimeEvent from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockDamageEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/TNTPrimeEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockDamageEvent object, got {}", + "Invalid argument passed. Expected a TNTPrimeEvent object, got {}", name ) .into()) @@ -5374,26 +5217,28 @@ impl<'mc> JNIInstantiatable<'mc> for BlockDamageEvent<'mc> { } } -impl<'mc> BlockDamageEvent<'mc> { +impl<'mc> TNTPrimeEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - player: impl Into>, block: impl Into>, - item_in_hand: impl Into>, - insta_break: bool, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/block/Block;Lorg/bukkit/inventory/ItemStack;Z)V"); + ignite_cause: impl Into>, + priming_entity: impl Into>, + priming_block: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/event/block/TNTPrimeEvent/PrimeCause;Lorg/bukkit/entity/Entity;Lorg/bukkit/block/Block;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) + jni::objects::JObject::from_raw(block.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) + jni::objects::JObject::from_raw(ignite_cause.into().jni_object().clone()) }); let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_in_hand.into().jni_object().clone()) + jni::objects::JObject::from_raw(priming_entity.into().jni_object().clone()) }); - let val_4 = jni::objects::JValueGen::Bool(insta_break.into()); - let cls = jni.find_class("org/bukkit/event/block/BlockDamageEvent"); + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(priming_block.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/block/TNTPrimeEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -5406,75 +5251,79 @@ impl<'mc> BlockDamageEvent<'mc> { ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::block::BlockDamageEvent::from_raw(&jni, res) - } - /// Gets the player damaging the block involved in this event. - pub fn player(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Player;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Player::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + crate::event::block::TNTPrimeEvent::from_raw(&jni, res) } - /// Gets if the block is set to instantly break when damaged by the player. - pub fn insta_break(&self) -> Result> { + + pub fn is_cancelled(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getInstaBreak", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets if the block should instantly break when damaged by the player. - pub fn set_insta_break(&self, bool: bool) -> Result<(), Box> { + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(bool.into()); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setInstaBreak", + "setCancelled", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the ItemStack for the item currently in the player's hand. - pub fn item_in_hand( + /// Get the cause of the TNT becoming primed. + pub fn cause( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemInHand", sig.as_str(), vec![]); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/block/TNTPrimeEvent/PrimeCause;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCause", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + crate::event::block::TNTPrimeEventPrimeCause::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + /// Get the entity that caused the TNT to be primed. + pub fn priming_entity( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setCancelled", + "getPrimingEntity", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Get the block that caused the TNT to be primed. + pub fn priming_block( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPrimingBlock", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::block::Block::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } pub fn handlers(&self) -> Result, Box> { @@ -5492,14 +5341,14 @@ impl<'mc> BlockDamageEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/BlockDamageEvent"); + let cls = jni.find_class("org/bukkit/event/block/TNTPrimeEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getPlayer', 'getInstaBreak', 'setInstaBreak', 'getItemInHand', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['isCancelled', 'setCancelled', 'getCause', 'getPrimingEntity', 'getPrimingBlock', 'getHandlers', 'getHandlerList']) /// Gets the block involved in this event. pub fn block(&self) -> Result, Box> { let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { @@ -5514,48 +5363,235 @@ impl<'mc> BlockDamageEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockDamageEvent<'mc> { +impl<'mc> Into> for TNTPrimeEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockDamageEvent into crate::event::Cancellable") + .expect("Error converting TNTPrimeEvent into crate::event::Cancellable") } } -impl<'mc> Into> for BlockDamageEvent<'mc> { +impl<'mc> Into> for TNTPrimeEvent<'mc> { fn into(self) -> crate::event::block::BlockEvent<'mc> { crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockDamageEvent into crate::event::block::BlockEvent") + .expect("Error converting TNTPrimeEvent into crate::event::block::BlockEvent") + } +} +pub enum TNTPrimeEventPrimeCause<'mc> { + Fire { + inner: TNTPrimeEventPrimeCauseStruct<'mc>, + }, + Redstone { + inner: TNTPrimeEventPrimeCauseStruct<'mc>, + }, + Player { + inner: TNTPrimeEventPrimeCauseStruct<'mc>, + }, + Explosion { + inner: TNTPrimeEventPrimeCauseStruct<'mc>, + }, + Projectile { + inner: TNTPrimeEventPrimeCauseStruct<'mc>, + }, + BlockBreak { + inner: TNTPrimeEventPrimeCauseStruct<'mc>, + }, + Dispenser { + inner: TNTPrimeEventPrimeCauseStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for TNTPrimeEventPrimeCause<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + TNTPrimeEventPrimeCause::Fire { .. } => f.write_str("FIRE"), + TNTPrimeEventPrimeCause::Redstone { .. } => f.write_str("REDSTONE"), + TNTPrimeEventPrimeCause::Player { .. } => f.write_str("PLAYER"), + TNTPrimeEventPrimeCause::Explosion { .. } => f.write_str("EXPLOSION"), + TNTPrimeEventPrimeCause::Projectile { .. } => f.write_str("PROJECTILE"), + TNTPrimeEventPrimeCause::BlockBreak { .. } => f.write_str("BLOCK_BREAK"), + TNTPrimeEventPrimeCause::Dispenser { .. } => f.write_str("DISPENSER"), + } + } +} +impl<'mc> std::ops::Deref for TNTPrimeEventPrimeCause<'mc> { + type Target = TNTPrimeEventPrimeCauseStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + TNTPrimeEventPrimeCause::Fire { inner } => inner, + TNTPrimeEventPrimeCause::Redstone { inner } => inner, + TNTPrimeEventPrimeCause::Player { inner } => inner, + TNTPrimeEventPrimeCause::Explosion { inner } => inner, + TNTPrimeEventPrimeCause::Projectile { inner } => inner, + TNTPrimeEventPrimeCause::BlockBreak { inner } => inner, + TNTPrimeEventPrimeCause::Dispenser { inner } => inner, + } + } +} + +impl<'mc> TNTPrimeEventPrimeCause<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/event/block/TNTPrimeEvent/PrimeCause"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/event/block/TNTPrimeEvent/PrimeCause;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "FIRE" => Ok(TNTPrimeEventPrimeCause::Fire { + inner: TNTPrimeEventPrimeCauseStruct::from_raw(env, obj)?, + }), + "REDSTONE" => Ok(TNTPrimeEventPrimeCause::Redstone { + inner: TNTPrimeEventPrimeCauseStruct::from_raw(env, obj)?, + }), + "PLAYER" => Ok(TNTPrimeEventPrimeCause::Player { + inner: TNTPrimeEventPrimeCauseStruct::from_raw(env, obj)?, + }), + "EXPLOSION" => Ok(TNTPrimeEventPrimeCause::Explosion { + inner: TNTPrimeEventPrimeCauseStruct::from_raw(env, obj)?, + }), + "PROJECTILE" => Ok(TNTPrimeEventPrimeCause::Projectile { + inner: TNTPrimeEventPrimeCauseStruct::from_raw(env, obj)?, + }), + "BLOCK_BREAK" => Ok(TNTPrimeEventPrimeCause::BlockBreak { + inner: TNTPrimeEventPrimeCauseStruct::from_raw(env, obj)?, + }), + "DISPENSER" => Ok(TNTPrimeEventPrimeCause::Dispenser { + inner: TNTPrimeEventPrimeCauseStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } + #[repr(C)] -pub struct CauldronLevelChangeEvent<'mc>( +pub struct TNTPrimeEventPrimeCauseStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for CauldronLevelChangeEvent<'mc> { +impl<'mc> JNIRaw<'mc> for TNTPrimeEventPrimeCause<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + match self { + Self::Fire { inner } => inner.0.clone(), + Self::Redstone { inner } => inner.0.clone(), + Self::Player { inner } => inner.0.clone(), + Self::Explosion { inner } => inner.0.clone(), + Self::Projectile { inner } => inner.0.clone(), + Self::BlockBreak { inner } => inner.0.clone(), + Self::Dispenser { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + match self { + Self::Fire { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Redstone { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Player { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Explosion { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Projectile { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Dispenser { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } -impl<'mc> JNIInstantiatable<'mc> for CauldronLevelChangeEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for TNTPrimeEventPrimeCause<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate CauldronLevelChangeEvent from null object." + "Tried to instantiate TNTPrimeEventPrimeCause from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/block/CauldronLevelChangeEvent")?; + env.validate_name(&obj, "org/bukkit/event/block/TNTPrimeEvent/PrimeCause")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a CauldronLevelChangeEvent object, got {}", + "Invalid argument passed. Expected a TNTPrimeEventPrimeCause object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "FIRE" => Ok(TNTPrimeEventPrimeCause::Fire { + inner: TNTPrimeEventPrimeCauseStruct::from_raw(env, obj)?, + }), + "REDSTONE" => Ok(TNTPrimeEventPrimeCause::Redstone { + inner: TNTPrimeEventPrimeCauseStruct::from_raw(env, obj)?, + }), + "PLAYER" => Ok(TNTPrimeEventPrimeCause::Player { + inner: TNTPrimeEventPrimeCauseStruct::from_raw(env, obj)?, + }), + "EXPLOSION" => Ok(TNTPrimeEventPrimeCause::Explosion { + inner: TNTPrimeEventPrimeCauseStruct::from_raw(env, obj)?, + }), + "PROJECTILE" => Ok(TNTPrimeEventPrimeCause::Projectile { + inner: TNTPrimeEventPrimeCauseStruct::from_raw(env, obj)?, + }), + "BLOCK_BREAK" => Ok(TNTPrimeEventPrimeCause::BlockBreak { + inner: TNTPrimeEventPrimeCauseStruct::from_raw(env, obj)?, + }), + "DISPENSER" => Ok(TNTPrimeEventPrimeCause::Dispenser { + inner: TNTPrimeEventPrimeCauseStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for TNTPrimeEventPrimeCauseStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for TNTPrimeEventPrimeCauseStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate TNTPrimeEventPrimeCauseStruct from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/block/TNTPrimeEvent/PrimeCause")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a TNTPrimeEventPrimeCauseStruct object, got {}", name ) .into()) @@ -5565,29 +5601,71 @@ impl<'mc> JNIInstantiatable<'mc> for CauldronLevelChangeEvent<'mc> { } } -impl<'mc> CauldronLevelChangeEvent<'mc> { +impl<'mc> TNTPrimeEventPrimeCauseStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/block/TNTPrimeEvent/PrimeCause;"); + let cls = jni.find_class("org/bukkit/event/block/TNTPrimeEvent/PrimeCause"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::block::TNTPrimeEventPrimeCause::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct BlockExpEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for BlockExpEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for BlockExpEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate BlockExpEvent from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockExpEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BlockExpEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> BlockExpEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, block: impl Into>, - entity: impl Into>, - reason: impl Into>, - new_block: impl Into>, - ) -> Result, Box> - { - let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/entity/Entity;Lorg/bukkit/event/block/CauldronLevelChangeEvent/ChangeReason;Lorg/bukkit/block/BlockState;)V"); + exp: i32, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/block/Block;I)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(block.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(reason.into().jni_object().clone()) - }); - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_block.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/event/block/CauldronLevelChangeEvent"); + let val_2 = jni::objects::JValueGen::Int(exp); + let cls = jni.find_class("org/bukkit/event/block/BlockExpEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -5595,106 +5673,28 @@ impl<'mc> CauldronLevelChangeEvent<'mc> { vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::block::CauldronLevelChangeEvent::from_raw(&jni, res) - } - /// Get entity which did this. May be null. - pub fn entity(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - - pub fn reason( - &self, - ) -> Result< - crate::event::block::CauldronLevelChangeEventChangeReason<'mc>, - Box, - > { - let sig = String::from("()Lorg/bukkit/event/block/CauldronLevelChangeEvent/ChangeReason;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getReason", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::block::CauldronLevelChangeEventChangeReason::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - ) - } - /// Gets the new state of the cauldron. - pub fn new_state(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockState;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getNewState", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - #[deprecated] - /// Gets the old level of the cauldron. - pub fn old_level(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getOldLevel", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::event::block::BlockExpEvent::from_raw(&jni, res) } - #[deprecated] - /// Gets the new level of the cauldron. - pub fn new_level(&self) -> Result> { + /// Get the experience dropped by the block after the event has processed + pub fn exp_to_drop(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getNewLevel", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getExpToDrop", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - #[deprecated] - /// Sets the new level of the cauldron. - pub fn set_new_level(&self, new_level: i32) -> Result<(), Box> { + /// Set the amount of experience dropped by the block after the event has + /// processed + pub fn set_exp_to_drop(&self, exp: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(new_level); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setNewLevel", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_cancelled(&self, cancelled: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancelled.into()); + let val_1 = jni::objects::JValueGen::Int(exp); let res = self.jni_ref().call_method( &self.jni_object(), - "setCancelled", + "setExpToDrop", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -5717,14 +5717,14 @@ impl<'mc> CauldronLevelChangeEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/CauldronLevelChangeEvent"); + let cls = jni.find_class("org/bukkit/event/block/BlockExpEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getEntity', 'getReason', 'getNewState', 'getOldLevel', 'getNewLevel', 'setNewLevel', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getExpToDrop', 'setExpToDrop', 'getHandlers', 'getHandlerList']) /// Gets the block involved in this event. pub fn block(&self) -> Result, Box> { let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { @@ -5739,104 +5739,843 @@ impl<'mc> CauldronLevelChangeEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for CauldronLevelChangeEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting CauldronLevelChangeEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for CauldronLevelChangeEvent<'mc> { +impl<'mc> Into> for BlockExpEvent<'mc> { fn into(self) -> crate::event::block::BlockEvent<'mc> { - crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting CauldronLevelChangeEvent into crate::event::block::BlockEvent", - ) + crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockExpEvent into crate::event::block::BlockEvent") } } -pub enum CauldronLevelChangeEventChangeReason<'mc> {} -impl<'mc> std::fmt::Display for CauldronLevelChangeEventChangeReason<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} +#[repr(C)] +pub struct BlockDamageAbortEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for BlockDamageAbortEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } - -impl<'mc> CauldronLevelChangeEventChangeReason<'mc> { - pub fn value_of( +impl<'mc> JNIInstantiatable<'mc> for BlockDamageAbortEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate BlockDamageAbortEvent from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/block/BlockDamageAbortEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BlockDamageAbortEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> BlockDamageAbortEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + player: impl Into>, + block: impl Into>, + item_in_hand: impl Into>, + ) -> Result, Box> { + let sig = String::from( + "(Lorg/bukkit/entity/Player;Lorg/bukkit/block/Block;Lorg/bukkit/inventory/ItemStack;)V", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(player.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(block.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_in_hand.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/block/BlockDamageAbortEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::event::block::BlockDamageAbortEvent::from_raw(&jni, res) + } + /// Gets the player that stopped damaging the block involved in this event. + pub fn player(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Player::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the ItemStack for the item currently in the player's hand. + pub fn item_in_hand( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemInHand", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/block/BlockDamageAbortEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getPlayer', 'getItemInHand', 'getHandlers', 'getHandlerList']) + /// Gets the block involved in this event. + pub fn block(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockEvent = temp_clone.into(); + real.block() + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for BlockDamageAbortEvent<'mc> { + fn into(self) -> crate::event::block::BlockEvent<'mc> { + crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockDamageAbortEvent into crate::event::block::BlockEvent") + } +} +#[repr(C)] +pub struct BlockFadeEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for BlockFadeEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for BlockFadeEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate BlockFadeEvent from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockFadeEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BlockFadeEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> BlockFadeEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + block: impl Into>, + new_state: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/block/BlockState;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(block.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(new_state.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/block/BlockFadeEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::event::block::BlockFadeEvent::from_raw(&jni, res) + } + /// Gets the state of the block that will be fading, melting or + /// disappearing. + pub fn new_state(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockState;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getNewState", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/block/BlockFadeEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getNewState', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + /// Gets the block involved in this event. + pub fn block(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockEvent = temp_clone.into(); + real.block() + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for BlockFadeEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockFadeEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for BlockFadeEvent<'mc> { + fn into(self) -> crate::event::block::BlockEvent<'mc> { + crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockFadeEvent into crate::event::block::BlockEvent") + } +} +#[repr(C)] +pub struct BellResonateEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for BellResonateEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for BellResonateEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate BellResonateEvent from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BellResonateEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BellResonateEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> BellResonateEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + the_block: impl Into>, + resonated_entities: Vec>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/block/Block;Ljava/util/List;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(the_block.into().jni_object().clone()) + }); + let raw_val_2 = jni.new_object("java/util/ArrayList", "()V", vec![])?; + for v in resonated_entities { + let map_val_0 = jni::objects::JValueGen::Object(v); + jni.call_method( + &raw_val_2, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_2 = jni::objects::JValueGen::Object(raw_val_2); + let cls = jni.find_class("org/bukkit/event/block/BellResonateEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::event::block::BellResonateEvent::from_raw(&jni, res) + } + /// Get a mutable list of all {@link LivingEntity LivingEntities} to be + /// highlighted by the bell's resonating. This list can be added to or + /// removed from to change which entities are highlighted, and may be empty + /// if no entities were resonated as a result of this event. + /// + /// While the highlighted entities will change, the particles that display + /// over a resonated entity and their colors will not. This is handled by the + /// client and cannot be controlled by the server. + pub fn resonated_entities( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getResonatedEntities", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::LivingEntity::from_raw(&self.0, obj)?); + } + Ok(new_vec) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/block/BellResonateEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getResonatedEntities', 'getHandlers', 'getHandlerList']) + /// Gets the block involved in this event. + pub fn block(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockEvent = temp_clone.into(); + real.block() + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for BellResonateEvent<'mc> { + fn into(self) -> crate::event::block::BlockEvent<'mc> { + crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BellResonateEvent into crate::event::block::BlockEvent") + } +} +#[repr(C)] +pub struct BlockDispenseEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for BlockDispenseEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for BlockDispenseEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate BlockDispenseEvent from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockDispenseEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BlockDispenseEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> BlockDispenseEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + block: impl Into>, + dispensed: impl Into>, + velocity: impl Into>, + ) -> Result, Box> { + let sig = String::from( + "(Lorg/bukkit/block/Block;Lorg/bukkit/inventory/ItemStack;Lorg/bukkit/util/Vector;)V", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(block.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(dispensed.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(velocity.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/block/BlockDispenseEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::event::block::BlockDispenseEvent::from_raw(&jni, res) + } + /// Gets the item that is being dispensed. Modifying the returned item will + /// have no effect, you must use {@link + /// #setItem(org.bukkit.inventory.ItemStack)} instead. + pub fn item(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the item being dispensed. + pub fn set_item( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the velocity in meters per tick. + /// + /// Note: Modifying the returned Vector will not change the velocity, you + /// must use {@link #setVelocity(org.bukkit.util.Vector)} instead. + pub fn velocity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the velocity of the item being dispensed in meters per tick. + pub fn set_velocity( + &self, + vel: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(vel.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVelocity", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/block/BlockDispenseEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getItem', 'setItem', 'getVelocity', 'setVelocity', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + /// Gets the block involved in this event. + pub fn block(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockEvent = temp_clone.into(); + real.block() + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for BlockDispenseEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockDispenseEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for BlockDispenseEvent<'mc> { + fn into(self) -> crate::event::block::BlockEvent<'mc> { + crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockDispenseEvent into crate::event::block::BlockEvent") + } +} +#[repr(C)] +pub struct BlockDamageEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for BlockDamageEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for BlockDamageEvent<'mc> { + fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/event/block/CauldronLevelChangeEvent/ChangeReason"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate BlockDamageEvent from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockDamageEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BlockDamageEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> BlockDamageEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + player: impl Into>, + block: impl Into>, + item_in_hand: impl Into>, + insta_break: bool, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/block/Block;Lorg/bukkit/inventory/ItemStack;Z)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(player.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(block.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_in_hand.into().jni_object().clone()) + }); + let val_4 = jni::objects::JValueGen::Bool(insta_break.into()); + let cls = jni.find_class("org/bukkit/event/block/BlockDamageEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/event/block/CauldronLevelChangeEvent/ChangeReason;", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::event::block::BlockDamageEvent::from_raw(&jni, res) + } + /// Gets the player damaging the block involved in this event. + pub fn player(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Player::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets if the block is set to instantly break when damaged by the player. + pub fn insta_break(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInstaBreak", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets if the block should instantly break when damaged by the player. + pub fn set_insta_break(&self, bool: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(bool.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setInstaBreak", + sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = env.translate_error(res)?; + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the ItemStack for the item currently in the player's hand. + pub fn item_in_hand( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemInHand", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/block/BlockDamageEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getPlayer', 'getInstaBreak', 'setInstaBreak', 'getItemInHand', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + /// Gets the block involved in this event. + pub fn block(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockEvent = temp_clone.into(); + real.block() + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for BlockDamageEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockDamageEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for BlockDamageEvent<'mc> { + fn into(self) -> crate::event::block::BlockEvent<'mc> { + crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockDamageEvent into crate::event::block::BlockEvent") } } - #[repr(C)] -pub struct CauldronLevelChangeEventChangeReasonStruct<'mc>( +pub struct BlockEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for CauldronLevelChangeEventChangeReason<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for CauldronLevelChangeEventChangeReason<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate CauldronLevelChangeEventChangeReason from null object." - ) - .into()); - } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/event/block/CauldronLevelChangeEvent/ChangeReason", - )?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a CauldronLevelChangeEventChangeReason object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for CauldronLevelChangeEventChangeReasonStruct<'mc> { +impl<'mc> JNIRaw<'mc> for BlockEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -5844,47 +6583,93 @@ impl<'mc> JNIRaw<'mc> for CauldronLevelChangeEventChangeReasonStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for CauldronLevelChangeEventChangeReasonStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate CauldronLevelChangeEventChangeReasonStruct from null object." - ) - .into()); + return Err(eyre::eyre!("Tried to instantiate BlockEvent from null object.").into()); } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/event/block/CauldronLevelChangeEvent/ChangeReason", - )?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a CauldronLevelChangeEventChangeReasonStruct object, got {}", - name - ) - .into()) + "Invalid argument passed. Expected a BlockEvent object, got {}", + name + ) + .into()) } else { Ok(Self(env.clone(), obj)) } } } -impl<'mc> CauldronLevelChangeEventChangeReasonStruct<'mc> { - pub fn values( +impl<'mc> BlockEvent<'mc> { + pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result< - crate::event::block::CauldronLevelChangeEventChangeReason<'mc>, - Box, - > { - let sig = String::from("()Lorg/bukkit/event/block/CauldronLevelChangeEvent/ChangeReason;"); - let cls = jni.find_class("org/bukkit/event/block/CauldronLevelChangeEvent/ChangeReason"); + the_block: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/block/Block;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(the_block.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/block/BlockEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::block::CauldronLevelChangeEventChangeReason::from_raw(&jni, obj) + let res = jni.new_object( + cls, + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error_no_gen(res)?; + crate::event::block::BlockEvent::from_raw(&jni, res) + } + /// Gets the block involved in this event. + pub fn block(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + // SUPER CLASS: org.bukkit.event.Event ( ['getBlock']) + /// Convenience method for providing a user-friendly identifier. By + /// default, it is the event's class's {@linkplain Class#getSimpleName() + /// simple name}. + pub fn event_name(&self) -> Result> { + let temp_clone = crate::event::Event::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::Event = temp_clone.into(); + real.event_name() + } + /// Any custom event that should not by synchronized with other events must + /// use the specific constructor. These are the caveats of using an + /// asynchronous event: + ///
    + ///
  • The event is never fired from inside code triggered by a + /// synchronous event. Attempting to do so results in an {@link + /// java.lang.IllegalStateException}. + ///
  • However, asynchronous event handlers may fire synchronous or + /// asynchronous events + ///
  • The event may be fired multiple times simultaneously and in any + /// order. + ///
  • Any newly registered or unregistered handler is ignored after an + /// event starts execution. + ///
  • The handlers for this event may block for any length of time. + ///
  • Some implementations may selectively declare a specific event use + /// as asynchronous. This behavior should be clearly defined. + ///
  • Asynchronous calls are not calculated in the plugin timing system. + ///
+ pub fn is_asynchronous(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isAsynchronous", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -5892,13 +6677,19 @@ impl<'mc> CauldronLevelChangeEventChangeReasonStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for BlockEvent<'mc> { + fn into(self) -> crate::event::Event<'mc> { + crate::event::Event::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockEvent into crate::event::Event") + } +} #[repr(C)] -pub struct BlockEvent<'mc>( +pub struct BlockDispenseLootEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockEvent<'mc> { +impl<'mc> JNIRaw<'mc> for BlockDispenseLootEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -5906,18 +6697,22 @@ impl<'mc> JNIRaw<'mc> for BlockEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockDispenseLootEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate BlockEvent from null object.").into()); + return Err(eyre::eyre!( + "Tried to instantiate BlockDispenseLootEvent from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/BlockEvent")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/block/BlockDispenseLootEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockEvent object, got {}", + "Invalid argument passed. Expected a BlockDispenseLootEvent object, got {}", name ) .into()) @@ -5925,74 +6720,169 @@ impl<'mc> JNIInstantiatable<'mc> for BlockEvent<'mc> { Ok(Self(env.clone(), obj)) } } -} +} + +impl<'mc> BlockDispenseLootEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + player: impl Into>, + the_block: impl Into>, + dispensed_loot: Vec>, + ) -> Result, Box> { + let sig = + String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/block/Block;Ljava/util/List;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(player.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(the_block.into().jni_object().clone()) + }); + let raw_val_3 = jni.new_object("java/util/ArrayList", "()V", vec![])?; + for v in dispensed_loot { + let map_val_0 = jni::objects::JValueGen::Object(v); + jni.call_method( + &raw_val_3, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_3 = jni::objects::JValueGen::Object(raw_val_3); + let cls = jni.find_class("org/bukkit/event/block/BlockDispenseLootEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::event::block::BlockDispenseLootEvent::from_raw(&jni, res) + } + /// Gets the loot that will be dispensed. + pub fn dispensed_loot( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDispensedLoot", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::inventory::ItemStack::from_raw(&self.0, obj)?); + } + Ok(new_vec) + } + /// Sets the loot that will be dispensed. + pub fn set_dispensed_loot( + &self, + dispensed_loot: Vec>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/List;)V"); + let raw_val_1 = self + .jni_ref() + .new_object("java/util/ArrayList", "()V", vec![])?; + for v in dispensed_loot { + let map_val_0 = jni::objects::JValueGen::Object(v); + self.jni_ref().call_method( + &raw_val_1, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_1 = jni::objects::JValueGen::Object(raw_val_1); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDispensedLoot", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the player associated with this event. + /// + /// Warning: Some event instances like a + /// {@link org.bukkit.block.TrialSpawner} dispensing its reward loot may not + /// have a player associated with them and will return null. + pub fn player(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Player::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } -impl<'mc> BlockEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - the_block: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/block/Block;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(the_block.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/event/block/BlockEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, + pub fn set_cancelled(&self, cancelled: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancelled.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error_no_gen(res)?; - crate::event::block::BlockEvent::from_raw(&jni, res) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the block involved in this event. - pub fn block(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.event.Event ( ['getBlock']) - /// Convenience method for providing a user-friendly identifier. By - /// default, it is the event's class's {@linkplain Class#getSimpleName() - /// simple name}. - pub fn event_name(&self) -> Result> { - let temp_clone = crate::event::Event::from_raw(&self.0, unsafe { + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/block/BlockDispenseLootEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getDispensedLoot', 'setDispensedLoot', 'getPlayer', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + /// Gets the block involved in this event. + pub fn block(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::Event = temp_clone.into(); - real.event_name() - } - /// Any custom event that should not by synchronized with other events must - /// use the specific constructor. These are the caveats of using an - /// asynchronous event: - ///
    - ///
  • The event is never fired from inside code triggered by a - /// synchronous event. Attempting to do so results in an {@link - /// java.lang.IllegalStateException}. - ///
  • However, asynchronous event handlers may fire synchronous or - /// asynchronous events - ///
  • The event may be fired multiple times simultaneously and in any - /// order. - ///
  • Any newly registered or unregistered handler is ignored after an - /// event starts execution. - ///
  • The handlers for this event may block for any length of time. - ///
  • Some implementations may selectively declare a specific event use - /// as asynchronous. This behavior should be clearly defined. - ///
  • Asynchronous calls are not calculated in the plugin timing system. - ///
- pub fn is_asynchronous(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isAsynchronous", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let real: crate::event::block::BlockEvent = temp_clone.into(); + real.block() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -6000,10 +6890,16 @@ impl<'mc> BlockEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockEvent<'mc> { - fn into(self) -> crate::event::Event<'mc> { - crate::event::Event::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockEvent into crate::event::Event") +impl<'mc> Into> for BlockDispenseLootEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockDispenseLootEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for BlockDispenseLootEvent<'mc> { + fn into(self) -> crate::event::block::BlockEvent<'mc> { + crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockDispenseLootEvent into crate::event::block::BlockEvent") } } #[repr(C)] @@ -6630,12 +7526,178 @@ impl<'mc> BlockReceiveGameEvent<'mc> { jni::objects::JObject::from_raw(event.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) + jni::objects::JObject::from_raw(block.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/block/BlockReceiveGameEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::event::block::BlockReceiveGameEvent::from_raw(&jni, res) + } + /// Get the underlying event. + pub fn event(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/GameEvent;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getEvent", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::GameEvent::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the entity which triggered this event, if present. + pub fn entity(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/block/BlockReceiveGameEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getEvent', 'getEntity', 'setCancelled', 'isCancelled', 'getHandlers', 'getHandlerList']) + /// Gets the block involved in this event. + pub fn block(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockEvent = temp_clone.into(); + real.block() + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for BlockReceiveGameEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockReceiveGameEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for BlockReceiveGameEvent<'mc> { + fn into(self) -> crate::event::block::BlockEvent<'mc> { + crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockReceiveGameEvent into crate::event::block::BlockEvent") + } +} +#[repr(C)] +pub struct CrafterCraftEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for CrafterCraftEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for CrafterCraftEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate CrafterCraftEvent from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/block/CrafterCraftEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a CrafterCraftEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> CrafterCraftEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + the_block: impl Into>, + recipe: impl Into>, + result: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/inventory/CraftingRecipe;Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(the_block.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) }); let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + jni::objects::JObject::from_raw(result.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/block/BlockReceiveGameEvent"); + let cls = jni.find_class("org/bukkit/event/block/CrafterCraftEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -6647,47 +7709,50 @@ impl<'mc> BlockReceiveGameEvent<'mc> { ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::block::BlockReceiveGameEvent::from_raw(&jni, res) + crate::event::block::CrafterCraftEvent::from_raw(&jni, res) } - /// Get the underlying event. - pub fn event(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/GameEvent;"); + /// Gets the result for the craft. + pub fn result(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getEvent", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getResult", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::GameEvent::from_raw(&self.jni_ref(), unsafe { + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the entity which triggered this event, if present. - pub fn entity(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + /// Sets the result of the craft. + pub fn set_result( + &self, + result: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(result.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCancelled", + "setResult", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } + /// Gets the recipe that was used to craft this item. + pub fn recipe( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/CraftingRecipe;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRecipe", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::CraftingRecipe::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } pub fn is_cancelled(&self) -> Result> { let sig = String::from("()Z"); @@ -6698,6 +7763,19 @@ impl<'mc> BlockReceiveGameEvent<'mc> { Ok(res.z()?) } + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); let res = @@ -6713,14 +7791,14 @@ impl<'mc> BlockReceiveGameEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/BlockReceiveGameEvent"); + let cls = jni.find_class("org/bukkit/event/block/CrafterCraftEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getEvent', 'getEntity', 'setCancelled', 'isCancelled', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getResult', 'setResult', 'getRecipe', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) /// Gets the block involved in this event. pub fn block(&self) -> Result, Box> { let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { @@ -6735,16 +7813,16 @@ impl<'mc> BlockReceiveGameEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockReceiveGameEvent<'mc> { +impl<'mc> Into> for CrafterCraftEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockReceiveGameEvent into crate::event::Cancellable") + .expect("Error converting CrafterCraftEvent into crate::event::Cancellable") } } -impl<'mc> Into> for BlockReceiveGameEvent<'mc> { +impl<'mc> Into> for CrafterCraftEvent<'mc> { fn into(self) -> crate::event::block::BlockEvent<'mc> { crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockReceiveGameEvent into crate::event::block::BlockEvent") + .expect("Error converting CrafterCraftEvent into crate::event::block::BlockEvent") } } #[repr(C)] @@ -7130,209 +8208,53 @@ impl<'mc> SculkBloomEvent<'mc> { let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getCharge", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the charge of the cursor. - /// - /// Increasing the charge of a cursor makes the cursor last longer, giving - /// it more time to spread sculk blocks across a larger range. - /// - /// Typically, charges should be set to the exp reward of a mob - /// ({@link EntityDeathEvent#getDroppedExp()}), which is usually - /// 3-5 for animals, and 5-10 for the average mob (up to 50 for - /// wither skeletons). Roughly speaking, for each charge, 1 more - /// sculk block will be placed. - pub fn set_charge(&self, charge: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(charge); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCharge", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn handler_list( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/SculkBloomEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getCharge', 'setCharge', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) - /// Gets the block involved in this event. - pub fn block(&self) -> Result, Box> { - let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockEvent = temp_clone.into(); - real.block() - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for SculkBloomEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SculkBloomEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for SculkBloomEvent<'mc> { - fn into(self) -> crate::event::block::BlockEvent<'mc> { - crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SculkBloomEvent into crate::event::block::BlockEvent") - } -} -#[repr(C)] -pub struct BlockPistonExtendEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for BlockPistonExtendEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for BlockPistonExtendEvent<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate BlockPistonExtendEvent from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/block/BlockPistonExtendEvent")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockPistonExtendEvent object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> BlockPistonExtendEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - block: impl Into>, - blocks: Vec>, - direction: impl Into>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/block/Block;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Ljava/util/List;"; - let raw_val_2 = jni.new_object("java/util/ArrayList", "()V", vec![])?; - for v in blocks { - sig += "Ljava/lang/java/lang/Object;"; - let map_val_0 = jni::objects::JValueGen::Object(v); - jni.call_method( - &raw_val_2, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_2 = jni::objects::JValueGen::Object(raw_val_2); - args.push(val_2); - sig += "Lorg/bukkit/block/BlockFace;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(direction.into().jni_object().clone()) - }); - args.push(val_3); - sig += ")V"; - let cls = jni.find_class("org/bukkit/event/block/BlockPistonExtendEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::event::block::BlockPistonExtendEvent::from_raw(&jni, res) - } - #[deprecated] - /// Get the amount of blocks which will be moved while extending. - pub fn length(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getLength", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCharge", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Get an immutable list of the blocks which will be moved by the - /// extending. - pub fn blocks(&self) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBlocks", sig.as_str(), vec![]); + /// Sets the charge of the cursor. + /// + /// Increasing the charge of a cursor makes the cursor last longer, giving + /// it more time to spread sculk blocks across a larger range. + /// + /// Typically, charges should be set to the exp reward of a mob + /// ({@link EntityDeathEvent#getDroppedExp()}), which is usually + /// 3-5 for animals, and 5-10 for the average mob (up to 50 for + /// wither skeletons). Roughly speaking, for each charge, 1 more + /// sculk block will be placed. + pub fn set_charge(&self, charge: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(charge); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCharge", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::Block::from_raw(&self.0, obj)?); - } - Ok(new_vec) + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn handlers(&self) -> Result, Box> { @@ -7350,45 +8272,21 @@ impl<'mc> BlockPistonExtendEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/block/BlockPistonExtendEvent"); + let cls = jni.find_class("org/bukkit/event/block/SculkBloomEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.block.BlockPistonEvent ( ['getLength', 'getBlocks', 'getHandlers', 'getHandlerList']) - - pub fn is_cancelled(&self) -> Result> { - let temp_clone = crate::event::block::BlockPistonEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockPistonEvent = temp_clone.into(); - real.is_cancelled() - } - - pub fn set_cancelled(&self, cancelled: bool) -> Result<(), Box> { - let temp_clone = crate::event::block::BlockPistonEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockPistonEvent = temp_clone.into(); - real.set_cancelled(cancelled) - } - /// Returns true if the Piston in the event is sticky. - pub fn is_sticky(&self) -> Result> { - let temp_clone = crate::event::block::BlockPistonEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockPistonEvent = temp_clone.into(); - real.is_sticky() - } - /// Return the direction in which the piston will operate. - pub fn direction(&self) -> Result, Box> { - let temp_clone = crate::event::block::BlockPistonEvent::from_raw(&self.0, unsafe { + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getCharge', 'setCharge', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + /// Gets the block involved in this event. + pub fn block(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::block::BlockPistonEvent = temp_clone.into(); - real.direction() + let real: crate::event::block::BlockEvent = temp_clone.into(); + real.block() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -7396,11 +8294,16 @@ impl<'mc> BlockPistonExtendEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockPistonExtendEvent<'mc> { - fn into(self) -> crate::event::block::BlockPistonEvent<'mc> { - crate::event::block::BlockPistonEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting BlockPistonExtendEvent into crate::event::block::BlockPistonEvent", - ) +impl<'mc> Into> for SculkBloomEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting SculkBloomEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for SculkBloomEvent<'mc> { + fn into(self) -> crate::event::block::BlockEvent<'mc> { + crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting SculkBloomEvent into crate::event::block::BlockEvent") } } #[repr(C)] @@ -7569,6 +8472,178 @@ impl<'mc> Into> for BlockPhysicsEvent<'mc> } } #[repr(C)] +pub struct VaultDisplayItemEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for VaultDisplayItemEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for VaultDisplayItemEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate VaultDisplayItemEvent from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/block/VaultDisplayItemEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a VaultDisplayItemEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> VaultDisplayItemEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + the_block: impl Into>, + display_item: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(the_block.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(display_item.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/block/VaultDisplayItemEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::event::block::VaultDisplayItemEvent::from_raw(&jni, res) + } + /// Gets the item that will be displayed inside the vault. + pub fn display_item( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDisplayItem", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets the item that will be displayed inside the vault. + pub fn set_display_item( + &self, + display_item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(display_item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDisplayItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancelled: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancelled.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/block/VaultDisplayItemEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getDisplayItem', 'setDisplayItem', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + /// Gets the block involved in this event. + pub fn block(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockEvent = temp_clone.into(); + real.block() + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for VaultDisplayItemEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting VaultDisplayItemEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for VaultDisplayItemEvent<'mc> { + fn into(self) -> crate::event::block::BlockEvent<'mc> { + crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting VaultDisplayItemEvent into crate::event::block::BlockEvent") + } +} +#[repr(C)] pub struct FluidLevelChangeEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, diff --git a/blackboxmc-rs-bukkit/src/event/enchantment/mod.rs b/blackboxmc-rs-bukkit/src/event/enchantment/mod.rs index 656dc90..20a0f5c 100644 --- a/blackboxmc-rs-bukkit/src/event/enchantment/mod.rs +++ b/blackboxmc-rs-bukkit/src/event/enchantment/mod.rs @@ -45,14 +45,14 @@ impl<'mc> PrepareItemEnchantEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, enchanter: impl Into>, - view: impl Into>, + view: impl Into>, table: impl Into>, item: impl Into>, offers: impl Into>, bonus: i32, ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/inventory/InventoryView;Lorg/bukkit/block/Block;Lorg/bukkit/inventory/ItemStack;Lorg/bukkit/enchantments/EnchantmentOffer;I)V"); + let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/inventory/view/EnchantmentView;Lorg/bukkit/block/Block;Lorg/bukkit/inventory/ItemStack;Lorg/bukkit/enchantments/EnchantmentOffer;I)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(enchanter.into().jni_object().clone()) }); @@ -161,6 +161,19 @@ impl<'mc> PrepareItemEnchantEvent<'mc> { Ok(res.i()?) } + pub fn view( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/view/EnchantmentView;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getView", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::view::EnchantmentView::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + pub fn is_cancelled(&self) -> Result> { let sig = String::from("()Z"); let res = @@ -205,7 +218,7 @@ impl<'mc> PrepareItemEnchantEvent<'mc> { let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.inventory.InventoryEvent ( ['getEnchanter', 'getEnchantBlock', 'getItem', 'getExpLevelCostsOffered', 'getOffers', 'getEnchantmentBonus', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.inventory.InventoryEvent ( ['getEnchanter', 'getEnchantBlock', 'getItem', 'getExpLevelCostsOffered', 'getOffers', 'getEnchantmentBonus', 'getView', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) /// Gets the primary Inventory involved in this transaction pub fn inventory( &self, @@ -235,14 +248,6 @@ impl<'mc> PrepareItemEnchantEvent<'mc> { } Ok(new_vec) } - /// Gets the view object itself - pub fn view(&self) -> Result, Box> { - let temp_clone = crate::event::inventory::InventoryEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryEvent = temp_clone.into(); - real.view() - } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; diff --git a/blackboxmc-rs-bukkit/src/event/entity/mod.rs b/blackboxmc-rs-bukkit/src/event/entity/mod.rs index 3546754..3daf2f8 100644 --- a/blackboxmc-rs-bukkit/src/event/entity/mod.rs +++ b/blackboxmc-rs-bukkit/src/event/entity/mod.rs @@ -3,12 +3,12 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] -pub struct EntityDamageEvent<'mc>( +pub struct PotionSplashEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EntityDamageEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PotionSplashEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -16,20 +16,20 @@ impl<'mc> JNIRaw<'mc> for EntityDamageEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EntityDamageEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PotionSplashEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate EntityDamageEvent from null object.").into(), + eyre::eyre!("Tried to instantiate PotionSplashEvent from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/entity/EntityDamageEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/entity/PotionSplashEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityDamageEvent object, got {}", + "Invalid argument passed. Expected a PotionSplashEvent object, got {}", name ) .into()) @@ -39,40 +39,42 @@ impl<'mc> JNIInstantiatable<'mc> for EntityDamageEvent<'mc> { } } -impl<'mc> EntityDamageEvent<'mc> { +impl<'mc> PotionSplashEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - damagee: impl Into>, - cause: impl Into>, - damage_source: impl Into>, - modifiers: std::option::Option>>, - modifier_functions: std::option::Option>>, - ) -> Result, Box> { + potion: impl Into>, + hit_entity: impl Into>, + hit_block: std::option::Option>>, + hit_face: std::option::Option>>, + affected_entities: std::option::Option>>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Entity;"; + sig += "Lorg/bukkit/entity/ThrownPotion;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(damagee.into().jni_object().clone()) + jni::objects::JObject::from_raw(potion.into().jni_object().clone()) }); args.push(val_1); - sig += "Lorg/bukkit/event/entity/EntityDamageEvent/DamageCause;"; + sig += "Lorg/bukkit/entity/Entity;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(cause.into().jni_object().clone()) + jni::objects::JObject::from_raw(hit_entity.into().jni_object().clone()) }); args.push(val_2); - sig += "Lorg/bukkit/damage/DamageSource;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(damage_source.into().jni_object().clone()) - }); - args.push(val_3); - if let Some(a) = modifiers { - sig += "Ljava/util/Map;"; + if let Some(a) = hit_block { + sig += "Lorg/bukkit/block/Block;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_3); + } + if let Some(a) = hit_face { + sig += "Lorg/bukkit/block/BlockFace;"; let val_4 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); args.push(val_4); } - if let Some(a) = modifier_functions { + if let Some(a) = affected_entities { sig += "Ljava/util/Map;"; let val_5 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) @@ -80,153 +82,118 @@ impl<'mc> EntityDamageEvent<'mc> { args.push(val_5); } sig += ")V"; - let cls = jni.find_class("org/bukkit/event/entity/EntityDamageEvent"); + let cls = jni.find_class("org/bukkit/event/entity/PotionSplashEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::entity::EntityDamageEvent::from_raw(&jni, res) + crate::event::entity::PotionSplashEvent::from_raw(&jni, res) } - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + pub fn entity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/ThrownPotion;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::ThrownPotion::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + /// Gets the potion which caused this event + pub fn potion(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/ThrownPotion;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPotion", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::ThrownPotion::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Retrieves a list of all effected entities + pub fn affected_entities( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setCancelled", + "getAffectedEntities", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::LivingEntity::from_raw(&self.0, obj)?); + } + Ok(new_vec) } - /// Gets the original damage for the specified modifier, as defined at this - /// event's construction. - pub fn get_original_damage( + /// Gets the intensity of the potion's effects for given entity; This + /// depends on the distance to the impact center + pub fn get_intensity( &self, - val_type: impl Into>, + entity: impl Into>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent/DamageModifier;)D"); + let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)D"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getOriginalDamage", + "getIntensity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.d()?) } - /// Sets the damage for the specified modifier. - pub fn set_damage( + /// Overwrites the intensity for a given entity + pub fn set_intensity( &self, - val_type: impl Into>, - damage: std::option::Option, + entity: impl Into>, + intensity: f64, ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/event/entity/EntityDamageEvent/DamageModifier;"; + let sig = String::from("(Lorg/bukkit/entity/LivingEntity;D)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) }); - args.push(val_1); - if let Some(a) = damage { - sig += "D"; - let val_2 = jni::objects::JValueGen::Double(a); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setDamage", sig.as_str(), args); + let val_2 = jni::objects::JValueGen::Double(intensity); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setIntensity", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the raw amount of damage caused by the event - pub fn damage(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getDamage", sig.as_str(), vec![]); + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// This checks to see if a particular modifier is valid for this event's - /// caller, such that, {@link #setDamage(DamageModifier, double)} will not - /// throw an {@link UnsupportedOperationException}. - /// - /// {@link DamageModifier#BASE} is always applicable. - pub fn is_applicable( - &self, - val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent/DamageModifier;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "isApplicable", + "setCancelled", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the amount of damage caused by the event after all damage - /// reduction is applied. - pub fn final_damage(&self) -> Result> { - let sig = String::from("()D"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFinalDamage", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the cause of the damage. - /// - /// While a DamageCause may indicate a specific Bukkit-assigned cause of damage, - /// {@link #getDamageSource()} may expose additional types of damage such as custom - /// damage types provided by data packs, as well as any direct or indirect entities, - /// locations, or other contributing factors to the damage being inflicted. The - /// alternative is generally preferred, but DamageCauses provided to this event - /// should largely encompass most common use cases for developers if a simple cause - /// is required. - pub fn cause( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent/DamageCause;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getCause", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::entity::EntityDamageEventDamageCause::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the source of damage. - pub fn damage_source( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/damage/DamageSource;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDamageSource", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::damage::DamageSource::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn handlers(&self) -> Result, Box> { @@ -244,31 +211,44 @@ impl<'mc> EntityDamageEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/entity/EntityDamageEvent"); + let cls = jni.find_class("org/bukkit/event/entity/PotionSplashEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['isCancelled', 'setCancelled', 'getOriginalDamage', 'setDamage', 'getDamage', 'isApplicable', 'getFinalDamage', 'getCause', 'getDamageSource', 'getHandlers', 'getHandlerList']) - /// Returns the Entity involved in this event - pub fn entity(&self) -> Result, Box> { - let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { + // SUPER CLASS: org.bukkit.event.entity.ProjectileHitEvent ( ['getEntity', 'getPotion', 'getAffectedEntities', 'getIntensity', 'setIntensity', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + /// Gets the block that was hit, if it was a block that was hit. + pub fn hit_block( + &self, + ) -> Result>, Box> { + let temp_clone = crate::event::entity::ProjectileHitEvent::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::entity::EntityEvent = temp_clone.into(); - real.entity() + let real: crate::event::entity::ProjectileHitEvent = temp_clone.into(); + real.hit_block() } - /// Gets the EntityType of the Entity involved in this event. - pub fn entity_type( + /// Gets the block face that was hit, if it was a block that was hit and the + /// face was provided in the event. + pub fn hit_block_face( &self, - ) -> Result, Box> { - let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { + ) -> Result>, Box> { + let temp_clone = crate::event::entity::ProjectileHitEvent::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::entity::EntityEvent = temp_clone.into(); - real.entity_type() + let real: crate::event::entity::ProjectileHitEvent = temp_clone.into(); + real.hit_block_face() + } + /// Gets the entity that was hit, if it was an entity that was hit. + pub fn hit_entity( + &self, + ) -> Result>, Box> { + let temp_clone = crate::event::entity::ProjectileHitEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::ProjectileHitEvent = temp_clone.into(); + real.hit_entity() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -276,243 +256,26 @@ impl<'mc> EntityDamageEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for EntityDamageEvent<'mc> { +impl<'mc> Into> for PotionSplashEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EntityDamageEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for EntityDamageEvent<'mc> { - fn into(self) -> crate::event::entity::EntityEvent<'mc> { - crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EntityDamageEvent into crate::event::entity::EntityEvent") - } -} -pub enum EntityDamageEventDamageModifier<'mc> {} -impl<'mc> std::fmt::Display for EntityDamageEventDamageModifier<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> EntityDamageEventDamageModifier<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/event/entity/EntityDamageEvent/DamageModifier"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/event/entity/EntityDamageEvent/DamageModifier;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct EntityDamageEventDamageModifierStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for EntityDamageEventDamageModifier<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for EntityDamageEventDamageModifier<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate EntityDamageEventDamageModifier from null object." - ) - .into()); - } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/event/entity/EntityDamageEvent/DamageModifier", - )?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityDamageEventDamageModifier object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for EntityDamageEventDamageModifierStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for EntityDamageEventDamageModifierStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate EntityDamageEventDamageModifierStruct from null object." - ) - .into()); - } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/event/entity/EntityDamageEvent/DamageModifier", - )?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityDamageEventDamageModifierStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> EntityDamageEventDamageModifierStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result< - crate::event::entity::EntityDamageEventDamageModifier<'mc>, - Box, - > { - let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent/DamageModifier;"); - let cls = jni.find_class("org/bukkit/event/entity/EntityDamageEvent/DamageModifier"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::entity::EntityDamageEventDamageModifier::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -pub enum EntityDamageEventDamageCause<'mc> {} -impl<'mc> std::fmt::Display for EntityDamageEventDamageCause<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + .expect("Error converting PotionSplashEvent into crate::event::Cancellable") } } - -impl<'mc> EntityDamageEventDamageCause<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/event/entity/EntityDamageEvent/DamageCause"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/event/entity/EntityDamageEvent/DamageCause;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } +impl<'mc> Into> for PotionSplashEvent<'mc> { + fn into(self) -> crate::event::entity::ProjectileHitEvent<'mc> { + crate::event::entity::ProjectileHitEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting PotionSplashEvent into crate::event::entity::ProjectileHitEvent", + ) } } - #[repr(C)] -pub struct EntityDamageEventDamageCauseStruct<'mc>( +pub struct EntityTargetLivingEntityEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EntityDamageEventDamageCause<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for EntityDamageEventDamageCause<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate EntityDamageEventDamageCause from null object." - ) - .into()); - } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/event/entity/EntityDamageEvent/DamageCause", - )?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityDamageEventDamageCause object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for EntityDamageEventDamageCauseStruct<'mc> { +impl<'mc> JNIRaw<'mc> for EntityTargetLivingEntityEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -520,81 +283,24 @@ impl<'mc> JNIRaw<'mc> for EntityDamageEventDamageCauseStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EntityDamageEventDamageCauseStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EntityTargetLivingEntityEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate EntityDamageEventDamageCauseStruct from null object." + "Tried to instantiate EntityTargetLivingEntityEvent from null object." ) .into()); } let (valid, name) = env.validate_name( &obj, - "org/bukkit/event/entity/EntityDamageEvent/DamageCause", + "org/bukkit/event/entity/EntityTargetLivingEntityEvent", )?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityDamageEventDamageCauseStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> EntityDamageEventDamageCauseStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent/DamageCause;"); - let cls = jni.find_class("org/bukkit/event/entity/EntityDamageEvent/DamageCause"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::entity::EntityDamageEventDamageCause::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct EntityCombustEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for EntityCombustEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for EntityCombustEvent<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate EntityCombustEvent from null object.").into(), - ); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/entity/EntityCombustEvent")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityCombustEvent object, got {}", + "Invalid argument passed. Expected a EntityTargetLivingEntityEvent object, got {}", name ) .into()) @@ -604,18 +310,25 @@ impl<'mc> JNIInstantiatable<'mc> for EntityCombustEvent<'mc> { } } -impl<'mc> EntityCombustEvent<'mc> { +impl<'mc> EntityTargetLivingEntityEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - combustee: impl Into>, - duration: i32, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;I)V"); + entity: impl Into>, + target: impl Into>, + reason: impl Into>, + ) -> Result, Box> + { + let sig = String::from("(Lorg/bukkit/entity/Entity;Lorg/bukkit/entity/LivingEntity;Lorg/bukkit/event/entity/EntityTargetEvent/TargetReason;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(combustee.into().jni_object().clone()) + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(duration); - let cls = jni.find_class("org/bukkit/event/entity/EntityCombustEvent"); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(target.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(reason.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/entity/EntityTargetLivingEntityEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -623,57 +336,79 @@ impl<'mc> EntityCombustEvent<'mc> { vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::entity::EntityCombustEvent::from_raw(&jni, res) + crate::event::entity::EntityTargetLivingEntityEvent::from_raw(&jni, res) } - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + pub fn target( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTarget", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::LivingEntity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + /// Set the Entity that you want the mob to target. + /// + /// It is possible to be null, null will cause the entity to be + /// target-less. + /// + /// Must be a LivingEntity, or null. + pub fn set_target( + &self, + target: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(target.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCancelled", + "setTarget", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } + // SUPER CLASS: org.bukkit.event.entity.EntityTargetEvent ( ['getTarget', 'setTarget']) - pub fn duration(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDuration", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + pub fn is_cancelled(&self) -> Result> { + let temp_clone = crate::event::entity::EntityTargetEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityTargetEvent = temp_clone.into(); + real.is_cancelled() } - /// The number of seconds the combustee should be alight for. - /// - /// This value will only ever increase the combustion time, not decrease - /// existing combustion times. - pub fn set_duration(&self, duration: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(duration); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setDuration", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let temp_clone = crate::event::entity::EntityTargetEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityTargetEvent = temp_clone.into(); + real.set_cancelled(cancel) + } + /// Returns the reason for the targeting + pub fn reason( + &self, + ) -> Result, Box> + { + let temp_clone = crate::event::entity::EntityTargetEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityTargetEvent = temp_clone.into(); + real.reason() } pub fn handlers(&self) -> Result, Box> { @@ -690,58 +425,28 @@ impl<'mc> EntityCombustEvent<'mc> { pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/entity/EntityCombustEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['isCancelled', 'setCancelled', 'getDuration', 'setDuration', 'getHandlers', 'getHandlerList']) - /// Returns the Entity involved in this event - pub fn entity(&self) -> Result, Box> { - let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityEvent = temp_clone.into(); - real.entity() - } - /// Gets the EntityType of the Entity involved in this event. - pub fn entity_type( - &self, - ) -> Result, Box> { - let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityEvent = temp_clone.into(); - real.entity_type() + crate::event::entity::EntityTargetEvent::handler_list(jni) } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for EntityCombustEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EntityCombustEvent into crate::event::Cancellable") + self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for EntityCombustEvent<'mc> { - fn into(self) -> crate::event::entity::EntityEvent<'mc> { - crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EntityCombustEvent into crate::event::entity::EntityEvent") +impl<'mc> Into> + for EntityTargetLivingEntityEvent<'mc> +{ + fn into(self) -> crate::event::entity::EntityTargetEvent<'mc> { + crate::event::entity::EntityTargetEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting EntityTargetLivingEntityEvent into crate::event::entity::EntityTargetEvent") } } #[repr(C)] -pub struct CreatureSpawnEvent<'mc>( +pub struct EntityDamageEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for CreatureSpawnEvent<'mc> { +impl<'mc> JNIRaw<'mc> for EntityDamageEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -749,21 +454,20 @@ impl<'mc> JNIRaw<'mc> for CreatureSpawnEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for CreatureSpawnEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EntityDamageEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate CreatureSpawnEvent from null object.").into(), + eyre::eyre!("Tried to instantiate EntityDamageEvent from null object.").into(), ); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/entity/CreatureSpawnEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/entity/EntityDamageEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a CreatureSpawnEvent object, got {}", + "Invalid argument passed. Expected a EntityDamageEvent object, got {}", name ) .into()) @@ -773,82 +477,195 @@ impl<'mc> JNIInstantiatable<'mc> for CreatureSpawnEvent<'mc> { } } -impl<'mc> CreatureSpawnEvent<'mc> { +impl<'mc> EntityDamageEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - spawnee: impl Into>, - spawn_reason: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/LivingEntity;Lorg/bukkit/event/entity/CreatureSpawnEvent/SpawnReason;)V"); + damagee: impl Into>, + cause: impl Into>, + damage_source: impl Into>, + modifiers: std::option::Option>>, + modifier_functions: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Entity;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(spawnee.into().jni_object().clone()) + jni::objects::JObject::from_raw(damagee.into().jni_object().clone()) }); + args.push(val_1); + sig += "Lorg/bukkit/event/entity/EntityDamageEvent/DamageCause;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(spawn_reason.into().jni_object().clone()) + jni::objects::JObject::from_raw(cause.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/entity/CreatureSpawnEvent"); + args.push(val_2); + sig += "Lorg/bukkit/damage/DamageSource;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(damage_source.into().jni_object().clone()) + }); + args.push(val_3); + if let Some(a) = modifiers { + sig += "Ljava/util/Map;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_4); + } + if let Some(a) = modifier_functions { + sig += "Ljava/util/Map;"; + let val_5 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_5); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/entity/EntityDamageEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::entity::CreatureSpawnEvent::from_raw(&jni, res) + crate::event::entity::EntityDamageEvent::from_raw(&jni, res) } - pub fn entity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the original damage for the specified modifier, as defined at this + /// event's construction. + pub fn get_original_damage( + &self, + val_type: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent/DamageModifier;)D"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getOriginalDamage", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Sets the damage for the specified modifier. + pub fn set_damage( + &self, + val_type: impl Into>, + damage: std::option::Option, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/event/entity/EntityDamageEvent/DamageModifier;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = damage { + sig += "D"; + let val_2 = jni::objects::JValueGen::Double(a); + args.push(val_2); + } + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "setDamage", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the raw amount of damage caused by the event + pub fn damage(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getDamage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::LivingEntity::from_raw(&self.jni_ref(), unsafe { + Ok(res.d()?) + } + /// This checks to see if a particular modifier is valid for this event's + /// caller, such that, {@link #setDamage(DamageModifier, double)} will not + /// throw an {@link UnsupportedOperationException}. + /// + /// {@link DamageModifier#BASE} is always applicable. + pub fn is_applicable( + &self, + val_type: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/event/entity/EntityDamageEvent/DamageModifier;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isApplicable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the amount of damage caused by the event after all damage + /// reduction is applied. + pub fn final_damage(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFinalDamage", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the cause of the damage. + /// + /// While a DamageCause may indicate a specific Bukkit-assigned cause of damage, + /// {@link #getDamageSource()} may expose additional types of damage such as custom + /// damage types provided by data packs, as well as any direct or indirect entities, + /// locations, or other contributing factors to the damage being inflicted. The + /// alternative is generally preferred, but DamageCauses provided to this event + /// should largely encompass most common use cases for developers if a simple cause + /// is required. + pub fn cause( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent/DamageCause;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCause", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::entity::EntityDamageEventDamageCause::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the reason for why the creature is being spawned. - pub fn spawn_reason( + /// Get the source of damage. + pub fn damage_source( &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/event/entity/CreatureSpawnEvent/SpawnReason;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/damage/DamageSource;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getSpawnReason", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDamageSource", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::event::entity::CreatureSpawnEventSpawnReason::from_raw(&self.jni_ref(), unsafe { + crate::damage::DamageSource::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.event.entity.EntitySpawnEvent ( ['getEntity', 'getSpawnReason']) - - pub fn is_cancelled(&self) -> Result> { - let temp_clone = crate::event::entity::EntitySpawnEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntitySpawnEvent = temp_clone.into(); - real.is_cancelled() - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let temp_clone = crate::event::entity::EntitySpawnEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntitySpawnEvent = temp_clone.into(); - real.set_cancelled(cancel) - } - /// Gets the location at which the entity is spawning. - pub fn location(&self) -> Result, Box> { - let temp_clone = crate::event::entity::EntitySpawnEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntitySpawnEvent = temp_clone.into(); - real.location() - } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -864,7 +681,32 @@ impl<'mc> CreatureSpawnEvent<'mc> { pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { - crate::event::entity::EntitySpawnEvent::handler_list(jni) + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/entity/EntityDamageEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['isCancelled', 'setCancelled', 'getOriginalDamage', 'setDamage', 'getDamage', 'isApplicable', 'getFinalDamage', 'getCause', 'getDamageSource', 'getHandlers', 'getHandlerList']) + /// Returns the Entity involved in this event + pub fn entity(&self) -> Result, Box> { + let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityEvent = temp_clone.into(); + real.entity() + } + /// Gets the EntityType of the Entity involved in this event. + pub fn entity_type( + &self, + ) -> Result, Box> { + let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityEvent = temp_clone.into(); + real.entity_type() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -872,32 +714,86 @@ impl<'mc> CreatureSpawnEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for CreatureSpawnEvent<'mc> { - fn into(self) -> crate::event::entity::EntitySpawnEvent<'mc> { - crate::event::entity::EntitySpawnEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting CreatureSpawnEvent into crate::event::entity::EntitySpawnEvent", - ) +impl<'mc> Into> for EntityDamageEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EntityDamageEvent into crate::event::Cancellable") } } -pub enum CreatureSpawnEventSpawnReason<'mc> {} -impl<'mc> std::fmt::Display for CreatureSpawnEventSpawnReason<'mc> { +impl<'mc> Into> for EntityDamageEvent<'mc> { + fn into(self) -> crate::event::entity::EntityEvent<'mc> { + crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EntityDamageEvent into crate::event::entity::EntityEvent") + } +} +pub enum EntityDamageEventDamageModifier<'mc> { + Base { + inner: EntityDamageEventDamageModifierStruct<'mc>, + }, + Freezing { + inner: EntityDamageEventDamageModifierStruct<'mc>, + }, + HardHat { + inner: EntityDamageEventDamageModifierStruct<'mc>, + }, + Blocking { + inner: EntityDamageEventDamageModifierStruct<'mc>, + }, + Armor { + inner: EntityDamageEventDamageModifierStruct<'mc>, + }, + Resistance { + inner: EntityDamageEventDamageModifierStruct<'mc>, + }, + Magic { + inner: EntityDamageEventDamageModifierStruct<'mc>, + }, + Absorption { + inner: EntityDamageEventDamageModifierStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for EntityDamageEventDamageModifier<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + EntityDamageEventDamageModifier::Base { .. } => f.write_str("BASE"), + EntityDamageEventDamageModifier::Freezing { .. } => f.write_str("FREEZING"), + EntityDamageEventDamageModifier::HardHat { .. } => f.write_str("HARD_HAT"), + EntityDamageEventDamageModifier::Blocking { .. } => f.write_str("BLOCKING"), + EntityDamageEventDamageModifier::Armor { .. } => f.write_str("ARMOR"), + EntityDamageEventDamageModifier::Resistance { .. } => f.write_str("RESISTANCE"), + EntityDamageEventDamageModifier::Magic { .. } => f.write_str("MAGIC"), + EntityDamageEventDamageModifier::Absorption { .. } => f.write_str("ABSORPTION"), + } + } +} +impl<'mc> std::ops::Deref for EntityDamageEventDamageModifier<'mc> { + type Target = EntityDamageEventDamageModifierStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + EntityDamageEventDamageModifier::Base { inner } => inner, + EntityDamageEventDamageModifier::Freezing { inner } => inner, + EntityDamageEventDamageModifier::HardHat { inner } => inner, + EntityDamageEventDamageModifier::Blocking { inner } => inner, + EntityDamageEventDamageModifier::Armor { inner } => inner, + EntityDamageEventDamageModifier::Resistance { inner } => inner, + EntityDamageEventDamageModifier::Magic { inner } => inner, + EntityDamageEventDamageModifier::Absorption { inner } => inner, + } } } -impl<'mc> CreatureSpawnEventSpawnReason<'mc> { +impl<'mc> EntityDamageEventDamageModifier<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/event/entity/CreatureSpawnEvent/SpawnReason"); + let cls = env.find_class("org/bukkit/event/entity/EntityDamageEvent/DamageModifier"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/event/entity/CreatureSpawnEvent/SpawnReason;", + "(Ljava/lang/String;)Lorg/bukkit/event/entity/EntityDamageEvent/DamageModifier;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -909,46 +805,93 @@ impl<'mc> CreatureSpawnEventSpawnReason<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "BASE" => Ok(EntityDamageEventDamageModifier::Base { + inner: EntityDamageEventDamageModifierStruct::from_raw(env, obj)?, + }), + "FREEZING" => Ok(EntityDamageEventDamageModifier::Freezing { + inner: EntityDamageEventDamageModifierStruct::from_raw(env, obj)?, + }), + "HARD_HAT" => Ok(EntityDamageEventDamageModifier::HardHat { + inner: EntityDamageEventDamageModifierStruct::from_raw(env, obj)?, + }), + "BLOCKING" => Ok(EntityDamageEventDamageModifier::Blocking { + inner: EntityDamageEventDamageModifierStruct::from_raw(env, obj)?, + }), + "ARMOR" => Ok(EntityDamageEventDamageModifier::Armor { + inner: EntityDamageEventDamageModifierStruct::from_raw(env, obj)?, + }), + "RESISTANCE" => Ok(EntityDamageEventDamageModifier::Resistance { + inner: EntityDamageEventDamageModifierStruct::from_raw(env, obj)?, + }), + "MAGIC" => Ok(EntityDamageEventDamageModifier::Magic { + inner: EntityDamageEventDamageModifierStruct::from_raw(env, obj)?, + }), + "ABSORPTION" => Ok(EntityDamageEventDamageModifier::Absorption { + inner: EntityDamageEventDamageModifierStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct CreatureSpawnEventSpawnReasonStruct<'mc>( +pub struct EntityDamageEventDamageModifierStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for CreatureSpawnEventSpawnReason<'mc> { +impl<'mc> JNIRaw<'mc> for EntityDamageEventDamageModifier<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Base { inner } => inner.0.clone(), + Self::Freezing { inner } => inner.0.clone(), + Self::HardHat { inner } => inner.0.clone(), + Self::Blocking { inner } => inner.0.clone(), + Self::Armor { inner } => inner.0.clone(), + Self::Resistance { inner } => inner.0.clone(), + Self::Magic { inner } => inner.0.clone(), + Self::Absorption { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Base { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Freezing { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::HardHat { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Blocking { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Armor { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Resistance { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Magic { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Absorption { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } -impl<'mc> JNIInstantiatable<'mc> for CreatureSpawnEventSpawnReason<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EntityDamageEventDamageModifier<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate CreatureSpawnEventSpawnReason from null object." + "Tried to instantiate EntityDamageEventDamageModifier from null object." ) .into()); } let (valid, name) = env.validate_name( &obj, - "org/bukkit/event/entity/CreatureSpawnEvent/SpawnReason", + "org/bukkit/event/entity/EntityDamageEvent/DamageModifier", )?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a CreatureSpawnEventSpawnReason object, got {}", - name - ) - .into()) + "Invalid argument passed. Expected a EntityDamageEventDamageModifier object, got {}", + name + ) + .into()) } else { let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); let variant = env.translate_error(variant)?; @@ -957,13 +900,37 @@ impl<'mc> JNIInstantiatable<'mc> for CreatureSpawnEventSpawnReason<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "BASE" => Ok(EntityDamageEventDamageModifier::Base { + inner: EntityDamageEventDamageModifierStruct::from_raw(env, obj)?, + }), + "FREEZING" => Ok(EntityDamageEventDamageModifier::Freezing { + inner: EntityDamageEventDamageModifierStruct::from_raw(env, obj)?, + }), + "HARD_HAT" => Ok(EntityDamageEventDamageModifier::HardHat { + inner: EntityDamageEventDamageModifierStruct::from_raw(env, obj)?, + }), + "BLOCKING" => Ok(EntityDamageEventDamageModifier::Blocking { + inner: EntityDamageEventDamageModifierStruct::from_raw(env, obj)?, + }), + "ARMOR" => Ok(EntityDamageEventDamageModifier::Armor { + inner: EntityDamageEventDamageModifierStruct::from_raw(env, obj)?, + }), + "RESISTANCE" => Ok(EntityDamageEventDamageModifier::Resistance { + inner: EntityDamageEventDamageModifierStruct::from_raw(env, obj)?, + }), + "MAGIC" => Ok(EntityDamageEventDamageModifier::Magic { + inner: EntityDamageEventDamageModifierStruct::from_raw(env, obj)?, + }), + "ABSORPTION" => Ok(EntityDamageEventDamageModifier::Absorption { + inner: EntityDamageEventDamageModifierStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for CreatureSpawnEventSpawnReasonStruct<'mc> { +impl<'mc> JNIRaw<'mc> for EntityDamageEventDamageModifierStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -971,24 +938,24 @@ impl<'mc> JNIRaw<'mc> for CreatureSpawnEventSpawnReasonStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for CreatureSpawnEventSpawnReasonStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EntityDamageEventDamageModifierStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate CreatureSpawnEventSpawnReasonStruct from null object." + "Tried to instantiate EntityDamageEventDamageModifierStruct from null object." ) .into()); } let (valid, name) = env.validate_name( &obj, - "org/bukkit/event/entity/CreatureSpawnEvent/SpawnReason", + "org/bukkit/event/entity/EntityDamageEvent/DamageModifier", )?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a CreatureSpawnEventSpawnReasonStruct object, got {}", + "Invalid argument passed. Expected a EntityDamageEventDamageModifierStruct object, got {}", name ) .into()) @@ -998,18 +965,20 @@ impl<'mc> JNIInstantiatable<'mc> for CreatureSpawnEventSpawnReasonStruct<'mc> { } } -impl<'mc> CreatureSpawnEventSpawnReasonStruct<'mc> { +impl<'mc> EntityDamageEventDamageModifierStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/event/entity/CreatureSpawnEvent/SpawnReason;"); - let cls = jni.find_class("org/bukkit/event/entity/CreatureSpawnEvent/SpawnReason"); + ) -> Result< + crate::event::entity::EntityDamageEventDamageModifier<'mc>, + Box, + > { + let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent/DamageModifier;"); + let cls = jni.find_class("org/bukkit/event/entity/EntityDamageEvent/DamageModifier"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::event::entity::CreatureSpawnEventSpawnReason::from_raw(&jni, obj) + crate::event::entity::EntityDamageEventDamageModifier::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1017,165 +986,560 @@ impl<'mc> CreatureSpawnEventSpawnReasonStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +pub enum EntityDamageEventDamageCause<'mc> { + Kill { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + WorldBorder { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + Contact { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + EntityAttack { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + EntitySweepAttack { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + Projectile { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + Suffocation { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + Fall { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + Fire { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + FireTick { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + Melting { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + Lava { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + Drowning { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + BlockExplosion { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + EntityExplosion { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + Void { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + Lightning { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + Suicide { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + Starvation { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + Poison { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + Magic { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + Wither { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + FallingBlock { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + Thorns { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + DragonBreath { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + Custom { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + FlyIntoWall { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + HotFloor { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + Campfire { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + Cramming { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + Dryout { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + Freeze { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, + SonicBoom { + inner: EntityDamageEventDamageCauseStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for EntityDamageEventDamageCause<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + EntityDamageEventDamageCause::Kill { .. } => f.write_str("KILL"), + EntityDamageEventDamageCause::WorldBorder { .. } => f.write_str("WORLD_BORDER"), + EntityDamageEventDamageCause::Contact { .. } => f.write_str("CONTACT"), + EntityDamageEventDamageCause::EntityAttack { .. } => f.write_str("ENTITY_ATTACK"), + EntityDamageEventDamageCause::EntitySweepAttack { .. } => { + f.write_str("ENTITY_SWEEP_ATTACK") + } + EntityDamageEventDamageCause::Projectile { .. } => f.write_str("PROJECTILE"), + EntityDamageEventDamageCause::Suffocation { .. } => f.write_str("SUFFOCATION"), + EntityDamageEventDamageCause::Fall { .. } => f.write_str("FALL"), + EntityDamageEventDamageCause::Fire { .. } => f.write_str("FIRE"), + EntityDamageEventDamageCause::FireTick { .. } => f.write_str("FIRE_TICK"), + EntityDamageEventDamageCause::Melting { .. } => f.write_str("MELTING"), + EntityDamageEventDamageCause::Lava { .. } => f.write_str("LAVA"), + EntityDamageEventDamageCause::Drowning { .. } => f.write_str("DROWNING"), + EntityDamageEventDamageCause::BlockExplosion { .. } => f.write_str("BLOCK_EXPLOSION"), + EntityDamageEventDamageCause::EntityExplosion { .. } => f.write_str("ENTITY_EXPLOSION"), + EntityDamageEventDamageCause::Void { .. } => f.write_str("VOID"), + EntityDamageEventDamageCause::Lightning { .. } => f.write_str("LIGHTNING"), + EntityDamageEventDamageCause::Suicide { .. } => f.write_str("SUICIDE"), + EntityDamageEventDamageCause::Starvation { .. } => f.write_str("STARVATION"), + EntityDamageEventDamageCause::Poison { .. } => f.write_str("POISON"), + EntityDamageEventDamageCause::Magic { .. } => f.write_str("MAGIC"), + EntityDamageEventDamageCause::Wither { .. } => f.write_str("WITHER"), + EntityDamageEventDamageCause::FallingBlock { .. } => f.write_str("FALLING_BLOCK"), + EntityDamageEventDamageCause::Thorns { .. } => f.write_str("THORNS"), + EntityDamageEventDamageCause::DragonBreath { .. } => f.write_str("DRAGON_BREATH"), + EntityDamageEventDamageCause::Custom { .. } => f.write_str("CUSTOM"), + EntityDamageEventDamageCause::FlyIntoWall { .. } => f.write_str("FLY_INTO_WALL"), + EntityDamageEventDamageCause::HotFloor { .. } => f.write_str("HOT_FLOOR"), + EntityDamageEventDamageCause::Campfire { .. } => f.write_str("CAMPFIRE"), + EntityDamageEventDamageCause::Cramming { .. } => f.write_str("CRAMMING"), + EntityDamageEventDamageCause::Dryout { .. } => f.write_str("DRYOUT"), + EntityDamageEventDamageCause::Freeze { .. } => f.write_str("FREEZE"), + EntityDamageEventDamageCause::SonicBoom { .. } => f.write_str("SONIC_BOOM"), + } + } +} +impl<'mc> std::ops::Deref for EntityDamageEventDamageCause<'mc> { + type Target = EntityDamageEventDamageCauseStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + EntityDamageEventDamageCause::Kill { inner } => inner, + EntityDamageEventDamageCause::WorldBorder { inner } => inner, + EntityDamageEventDamageCause::Contact { inner } => inner, + EntityDamageEventDamageCause::EntityAttack { inner } => inner, + EntityDamageEventDamageCause::EntitySweepAttack { inner } => inner, + EntityDamageEventDamageCause::Projectile { inner } => inner, + EntityDamageEventDamageCause::Suffocation { inner } => inner, + EntityDamageEventDamageCause::Fall { inner } => inner, + EntityDamageEventDamageCause::Fire { inner } => inner, + EntityDamageEventDamageCause::FireTick { inner } => inner, + EntityDamageEventDamageCause::Melting { inner } => inner, + EntityDamageEventDamageCause::Lava { inner } => inner, + EntityDamageEventDamageCause::Drowning { inner } => inner, + EntityDamageEventDamageCause::BlockExplosion { inner } => inner, + EntityDamageEventDamageCause::EntityExplosion { inner } => inner, + EntityDamageEventDamageCause::Void { inner } => inner, + EntityDamageEventDamageCause::Lightning { inner } => inner, + EntityDamageEventDamageCause::Suicide { inner } => inner, + EntityDamageEventDamageCause::Starvation { inner } => inner, + EntityDamageEventDamageCause::Poison { inner } => inner, + EntityDamageEventDamageCause::Magic { inner } => inner, + EntityDamageEventDamageCause::Wither { inner } => inner, + EntityDamageEventDamageCause::FallingBlock { inner } => inner, + EntityDamageEventDamageCause::Thorns { inner } => inner, + EntityDamageEventDamageCause::DragonBreath { inner } => inner, + EntityDamageEventDamageCause::Custom { inner } => inner, + EntityDamageEventDamageCause::FlyIntoWall { inner } => inner, + EntityDamageEventDamageCause::HotFloor { inner } => inner, + EntityDamageEventDamageCause::Campfire { inner } => inner, + EntityDamageEventDamageCause::Cramming { inner } => inner, + EntityDamageEventDamageCause::Dryout { inner } => inner, + EntityDamageEventDamageCause::Freeze { inner } => inner, + EntityDamageEventDamageCause::SonicBoom { inner } => inner, + } + } +} + +impl<'mc> EntityDamageEventDamageCause<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/event/entity/EntityDamageEvent/DamageCause"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/event/entity/EntityDamageEvent/DamageCause;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "KILL" => Ok(EntityDamageEventDamageCause::Kill { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "WORLD_BORDER" => Ok(EntityDamageEventDamageCause::WorldBorder { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "CONTACT" => Ok(EntityDamageEventDamageCause::Contact { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "ENTITY_ATTACK" => Ok(EntityDamageEventDamageCause::EntityAttack { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "ENTITY_SWEEP_ATTACK" => Ok(EntityDamageEventDamageCause::EntitySweepAttack { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "PROJECTILE" => Ok(EntityDamageEventDamageCause::Projectile { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "SUFFOCATION" => Ok(EntityDamageEventDamageCause::Suffocation { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "FALL" => Ok(EntityDamageEventDamageCause::Fall { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "FIRE" => Ok(EntityDamageEventDamageCause::Fire { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "FIRE_TICK" => Ok(EntityDamageEventDamageCause::FireTick { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "MELTING" => Ok(EntityDamageEventDamageCause::Melting { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "LAVA" => Ok(EntityDamageEventDamageCause::Lava { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "DROWNING" => Ok(EntityDamageEventDamageCause::Drowning { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "BLOCK_EXPLOSION" => Ok(EntityDamageEventDamageCause::BlockExplosion { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "ENTITY_EXPLOSION" => Ok(EntityDamageEventDamageCause::EntityExplosion { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "VOID" => Ok(EntityDamageEventDamageCause::Void { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "LIGHTNING" => Ok(EntityDamageEventDamageCause::Lightning { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "SUICIDE" => Ok(EntityDamageEventDamageCause::Suicide { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "STARVATION" => Ok(EntityDamageEventDamageCause::Starvation { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "POISON" => Ok(EntityDamageEventDamageCause::Poison { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "MAGIC" => Ok(EntityDamageEventDamageCause::Magic { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "WITHER" => Ok(EntityDamageEventDamageCause::Wither { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "FALLING_BLOCK" => Ok(EntityDamageEventDamageCause::FallingBlock { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "THORNS" => Ok(EntityDamageEventDamageCause::Thorns { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "DRAGON_BREATH" => Ok(EntityDamageEventDamageCause::DragonBreath { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "CUSTOM" => Ok(EntityDamageEventDamageCause::Custom { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "FLY_INTO_WALL" => Ok(EntityDamageEventDamageCause::FlyIntoWall { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "HOT_FLOOR" => Ok(EntityDamageEventDamageCause::HotFloor { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "CAMPFIRE" => Ok(EntityDamageEventDamageCause::Campfire { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "CRAMMING" => Ok(EntityDamageEventDamageCause::Cramming { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "DRYOUT" => Ok(EntityDamageEventDamageCause::Dryout { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "FREEZE" => Ok(EntityDamageEventDamageCause::Freeze { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "SONIC_BOOM" => Ok(EntityDamageEventDamageCause::SonicBoom { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + #[repr(C)] -pub struct EntityCombustByBlockEvent<'mc>( +pub struct EntityDamageEventDamageCauseStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EntityCombustByBlockEvent<'mc> { +impl<'mc> JNIRaw<'mc> for EntityDamageEventDamageCause<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + match self { + Self::Kill { inner } => inner.0.clone(), + Self::WorldBorder { inner } => inner.0.clone(), + Self::Contact { inner } => inner.0.clone(), + Self::EntityAttack { inner } => inner.0.clone(), + Self::EntitySweepAttack { inner } => inner.0.clone(), + Self::Projectile { inner } => inner.0.clone(), + Self::Suffocation { inner } => inner.0.clone(), + Self::Fall { inner } => inner.0.clone(), + Self::Fire { inner } => inner.0.clone(), + Self::FireTick { inner } => inner.0.clone(), + Self::Melting { inner } => inner.0.clone(), + Self::Lava { inner } => inner.0.clone(), + Self::Drowning { inner } => inner.0.clone(), + Self::BlockExplosion { inner } => inner.0.clone(), + Self::EntityExplosion { inner } => inner.0.clone(), + Self::Void { inner } => inner.0.clone(), + Self::Lightning { inner } => inner.0.clone(), + Self::Suicide { inner } => inner.0.clone(), + Self::Starvation { inner } => inner.0.clone(), + Self::Poison { inner } => inner.0.clone(), + Self::Magic { inner } => inner.0.clone(), + Self::Wither { inner } => inner.0.clone(), + Self::FallingBlock { inner } => inner.0.clone(), + Self::Thorns { inner } => inner.0.clone(), + Self::DragonBreath { inner } => inner.0.clone(), + Self::Custom { inner } => inner.0.clone(), + Self::FlyIntoWall { inner } => inner.0.clone(), + Self::HotFloor { inner } => inner.0.clone(), + Self::Campfire { inner } => inner.0.clone(), + Self::Cramming { inner } => inner.0.clone(), + Self::Dryout { inner } => inner.0.clone(), + Self::Freeze { inner } => inner.0.clone(), + Self::SonicBoom { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + match self { + Self::Kill { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::WorldBorder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Contact { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::EntityAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySweepAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Projectile { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Suffocation { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Fall { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Fire { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::FireTick { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Melting { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Lava { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Drowning { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BlockExplosion { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityExplosion { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Void { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Lightning { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Suicide { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Starvation { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Poison { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Magic { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Wither { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::FallingBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Thorns { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DragonBreath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Custom { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::FlyIntoWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HotFloor { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Campfire { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Cramming { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Dryout { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Freeze { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SonicBoom { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } -impl<'mc> JNIInstantiatable<'mc> for EntityCombustByBlockEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EntityDamageEventDamageCause<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate EntityCombustByBlockEvent from null object." + "Tried to instantiate EntityDamageEventDamageCause from null object." ) .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/entity/EntityCombustByBlockEvent")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityCombustByBlockEvent object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> EntityCombustByBlockEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - combuster: impl Into>, - combustee: impl Into>, - duration: i32, - ) -> Result, Box> - { - let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/entity/Entity;I)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(combuster.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(combustee.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Int(duration); - let cls = jni.find_class("org/bukkit/event/entity/EntityCombustByBlockEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = jni.translate_error_no_gen(res)?; - crate::event::entity::EntityCombustByBlockEvent::from_raw(&jni, res) - } - /// The combuster can be lava or a block that is on fire. - /// - /// WARNING: block may be null. - pub fn combuster( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCombuster", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::block::Block::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - // SUPER CLASS: org.bukkit.event.entity.EntityCombustEvent ( ['getCombuster']) - - pub fn is_cancelled(&self) -> Result> { - let temp_clone = crate::event::entity::EntityCombustEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityCombustEvent = temp_clone.into(); - real.is_cancelled() - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let temp_clone = crate::event::entity::EntityCombustEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityCombustEvent = temp_clone.into(); - real.set_cancelled(cancel) - } - - pub fn duration(&self) -> Result> { - let temp_clone = crate::event::entity::EntityCombustEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityCombustEvent = temp_clone.into(); - real.duration() - } - /// The number of seconds the combustee should be alight for. - /// - /// This value will only ever increase the combustion time, not decrease - /// existing combustion times. - pub fn set_duration(&self, duration: i32) -> Result<(), Box> { - let temp_clone = crate::event::entity::EntityCombustEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityCombustEvent = temp_clone.into(); - real.set_duration(duration) - } - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn handler_list( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - crate::event::entity::EntityCombustEvent::handler_list(jni) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for EntityCombustByBlockEvent<'mc> { - fn into(self) -> crate::event::entity::EntityCombustEvent<'mc> { - crate::event::entity::EntityCombustEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting EntityCombustByBlockEvent into crate::event::entity::EntityCombustEvent") + } + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/event/entity/EntityDamageEvent/DamageCause", + )?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EntityDamageEventDamageCause object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "KILL" => Ok(EntityDamageEventDamageCause::Kill { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "WORLD_BORDER" => Ok(EntityDamageEventDamageCause::WorldBorder { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "CONTACT" => Ok(EntityDamageEventDamageCause::Contact { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "ENTITY_ATTACK" => Ok(EntityDamageEventDamageCause::EntityAttack { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "ENTITY_SWEEP_ATTACK" => Ok(EntityDamageEventDamageCause::EntitySweepAttack { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "PROJECTILE" => Ok(EntityDamageEventDamageCause::Projectile { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "SUFFOCATION" => Ok(EntityDamageEventDamageCause::Suffocation { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "FALL" => Ok(EntityDamageEventDamageCause::Fall { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "FIRE" => Ok(EntityDamageEventDamageCause::Fire { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "FIRE_TICK" => Ok(EntityDamageEventDamageCause::FireTick { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "MELTING" => Ok(EntityDamageEventDamageCause::Melting { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "LAVA" => Ok(EntityDamageEventDamageCause::Lava { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "DROWNING" => Ok(EntityDamageEventDamageCause::Drowning { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "BLOCK_EXPLOSION" => Ok(EntityDamageEventDamageCause::BlockExplosion { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "ENTITY_EXPLOSION" => Ok(EntityDamageEventDamageCause::EntityExplosion { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "VOID" => Ok(EntityDamageEventDamageCause::Void { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "LIGHTNING" => Ok(EntityDamageEventDamageCause::Lightning { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "SUICIDE" => Ok(EntityDamageEventDamageCause::Suicide { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "STARVATION" => Ok(EntityDamageEventDamageCause::Starvation { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "POISON" => Ok(EntityDamageEventDamageCause::Poison { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "MAGIC" => Ok(EntityDamageEventDamageCause::Magic { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "WITHER" => Ok(EntityDamageEventDamageCause::Wither { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "FALLING_BLOCK" => Ok(EntityDamageEventDamageCause::FallingBlock { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "THORNS" => Ok(EntityDamageEventDamageCause::Thorns { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "DRAGON_BREATH" => Ok(EntityDamageEventDamageCause::DragonBreath { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "CUSTOM" => Ok(EntityDamageEventDamageCause::Custom { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "FLY_INTO_WALL" => Ok(EntityDamageEventDamageCause::FlyIntoWall { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "HOT_FLOOR" => Ok(EntityDamageEventDamageCause::HotFloor { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "CAMPFIRE" => Ok(EntityDamageEventDamageCause::Campfire { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "CRAMMING" => Ok(EntityDamageEventDamageCause::Cramming { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "DRYOUT" => Ok(EntityDamageEventDamageCause::Dryout { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "FREEZE" => Ok(EntityDamageEventDamageCause::Freeze { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + "SONIC_BOOM" => Ok(EntityDamageEventDamageCause::SonicBoom { + inner: EntityDamageEventDamageCauseStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } } } -#[repr(C)] -pub struct EntityCombustByEntityEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); -impl<'mc> JNIRaw<'mc> for EntityCombustByEntityEvent<'mc> { +impl<'mc> JNIRaw<'mc> for EntityDamageEventDamageCauseStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1183,124 +1547,45 @@ impl<'mc> JNIRaw<'mc> for EntityCombustByEntityEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EntityCombustByEntityEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EntityDamageEventDamageCauseStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate EntityCombustByEntityEvent from null object." + "Tried to instantiate EntityDamageEventDamageCauseStruct from null object." ) .into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/entity/EntityCombustByEntityEvent")?; + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/event/entity/EntityDamageEvent/DamageCause", + )?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityCombustByEntityEvent object, got {}", - name - ) - .into()) + "Invalid argument passed. Expected a EntityDamageEventDamageCauseStruct object, got {}", + name + ) + .into()) } else { Ok(Self(env.clone(), obj)) } } } -impl<'mc> EntityCombustByEntityEvent<'mc> { - pub fn new( +impl<'mc> EntityDamageEventDamageCauseStruct<'mc> { + pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - combuster: impl Into>, - combustee: impl Into>, - duration: i32, - ) -> Result, Box> + ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;Lorg/bukkit/entity/Entity;I)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(combuster.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(combustee.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Int(duration); - let cls = jni.find_class("org/bukkit/event/entity/EntityCombustByEntityEvent"); + let sig = String::from("()Lorg/bukkit/event/entity/EntityDamageEvent/DamageCause;"); + let cls = jni.find_class("org/bukkit/event/entity/EntityDamageEvent/DamageCause"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = jni.translate_error_no_gen(res)?; - crate::event::entity::EntityCombustByEntityEvent::from_raw(&jni, res) - } - /// Get the entity that caused the combustion event. - pub fn combuster(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCombuster", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - // SUPER CLASS: org.bukkit.event.entity.EntityCombustEvent ( ['getCombuster']) - - pub fn is_cancelled(&self) -> Result> { - let temp_clone = crate::event::entity::EntityCombustEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityCombustEvent = temp_clone.into(); - real.is_cancelled() - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let temp_clone = crate::event::entity::EntityCombustEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityCombustEvent = temp_clone.into(); - real.set_cancelled(cancel) - } - - pub fn duration(&self) -> Result> { - let temp_clone = crate::event::entity::EntityCombustEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityCombustEvent = temp_clone.into(); - real.duration() - } - /// The number of seconds the combustee should be alight for. - /// - /// This value will only ever increase the combustion time, not decrease - /// existing combustion times. - pub fn set_duration(&self, duration: i32) -> Result<(), Box> { - let temp_clone = crate::event::entity::EntityCombustEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityCombustEvent = temp_clone.into(); - real.set_duration(duration) - } - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn handler_list( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - crate::event::entity::EntityCombustEvent::handler_list(jni) + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::entity::EntityDamageEventDamageCause::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1308,11 +1593,6 @@ impl<'mc> EntityCombustByEntityEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for EntityCombustByEntityEvent<'mc> { - fn into(self) -> crate::event::entity::EntityCombustEvent<'mc> { - crate::event::entity::EntityCombustEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting EntityCombustByEntityEvent into crate::event::entity::EntityCombustEvent") - } -} #[repr(C)] pub struct SheepRegrowWoolEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, @@ -2230,10 +2510,73 @@ impl<'mc> Into> for EntityTransformEvent< .expect("Error converting EntityTransformEvent into crate::event::entity::EntityEvent") } } -pub enum EntityTransformEventTransformReason<'mc> {} +pub enum EntityTransformEventTransformReason<'mc> { + Cured { + inner: EntityTransformEventTransformReasonStruct<'mc>, + }, + Frozen { + inner: EntityTransformEventTransformReasonStruct<'mc>, + }, + Infection { + inner: EntityTransformEventTransformReasonStruct<'mc>, + }, + Drowned { + inner: EntityTransformEventTransformReasonStruct<'mc>, + }, + Sheared { + inner: EntityTransformEventTransformReasonStruct<'mc>, + }, + Lightning { + inner: EntityTransformEventTransformReasonStruct<'mc>, + }, + Split { + inner: EntityTransformEventTransformReasonStruct<'mc>, + }, + PiglinZombified { + inner: EntityTransformEventTransformReasonStruct<'mc>, + }, + Metamorphosis { + inner: EntityTransformEventTransformReasonStruct<'mc>, + }, + Unknown { + inner: EntityTransformEventTransformReasonStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for EntityTransformEventTransformReason<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + EntityTransformEventTransformReason::Cured { .. } => f.write_str("CURED"), + EntityTransformEventTransformReason::Frozen { .. } => f.write_str("FROZEN"), + EntityTransformEventTransformReason::Infection { .. } => f.write_str("INFECTION"), + EntityTransformEventTransformReason::Drowned { .. } => f.write_str("DROWNED"), + EntityTransformEventTransformReason::Sheared { .. } => f.write_str("SHEARED"), + EntityTransformEventTransformReason::Lightning { .. } => f.write_str("LIGHTNING"), + EntityTransformEventTransformReason::Split { .. } => f.write_str("SPLIT"), + EntityTransformEventTransformReason::PiglinZombified { .. } => { + f.write_str("PIGLIN_ZOMBIFIED") + } + EntityTransformEventTransformReason::Metamorphosis { .. } => { + f.write_str("METAMORPHOSIS") + } + EntityTransformEventTransformReason::Unknown { .. } => f.write_str("UNKNOWN"), + } + } +} +impl<'mc> std::ops::Deref for EntityTransformEventTransformReason<'mc> { + type Target = EntityTransformEventTransformReasonStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + EntityTransformEventTransformReason::Cured { inner } => inner, + EntityTransformEventTransformReason::Frozen { inner } => inner, + EntityTransformEventTransformReason::Infection { inner } => inner, + EntityTransformEventTransformReason::Drowned { inner } => inner, + EntityTransformEventTransformReason::Sheared { inner } => inner, + EntityTransformEventTransformReason::Lightning { inner } => inner, + EntityTransformEventTransformReason::Split { inner } => inner, + EntityTransformEventTransformReason::PiglinZombified { inner } => inner, + EntityTransformEventTransformReason::Metamorphosis { inner } => inner, + EntityTransformEventTransformReason::Unknown { inner } => inner, + } } } @@ -2260,6 +2603,37 @@ impl<'mc> EntityTransformEventTransformReason<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "CURED" => Ok(EntityTransformEventTransformReason::Cured { + inner: EntityTransformEventTransformReasonStruct::from_raw(env, obj)?, + }), + "FROZEN" => Ok(EntityTransformEventTransformReason::Frozen { + inner: EntityTransformEventTransformReasonStruct::from_raw(env, obj)?, + }), + "INFECTION" => Ok(EntityTransformEventTransformReason::Infection { + inner: EntityTransformEventTransformReasonStruct::from_raw(env, obj)?, + }), + "DROWNED" => Ok(EntityTransformEventTransformReason::Drowned { + inner: EntityTransformEventTransformReasonStruct::from_raw(env, obj)?, + }), + "SHEARED" => Ok(EntityTransformEventTransformReason::Sheared { + inner: EntityTransformEventTransformReasonStruct::from_raw(env, obj)?, + }), + "LIGHTNING" => Ok(EntityTransformEventTransformReason::Lightning { + inner: EntityTransformEventTransformReasonStruct::from_raw(env, obj)?, + }), + "SPLIT" => Ok(EntityTransformEventTransformReason::Split { + inner: EntityTransformEventTransformReasonStruct::from_raw(env, obj)?, + }), + "PIGLIN_ZOMBIFIED" => Ok(EntityTransformEventTransformReason::PiglinZombified { + inner: EntityTransformEventTransformReasonStruct::from_raw(env, obj)?, + }), + "METAMORPHOSIS" => Ok(EntityTransformEventTransformReason::Metamorphosis { + inner: EntityTransformEventTransformReasonStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(EntityTransformEventTransformReason::Unknown { + inner: EntityTransformEventTransformReasonStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -2273,10 +2647,40 @@ pub struct EntityTransformEventTransformReasonStruct<'mc>( impl<'mc> JNIRaw<'mc> for EntityTransformEventTransformReason<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Cured { inner } => inner.0.clone(), + Self::Frozen { inner } => inner.0.clone(), + Self::Infection { inner } => inner.0.clone(), + Self::Drowned { inner } => inner.0.clone(), + Self::Sheared { inner } => inner.0.clone(), + Self::Lightning { inner } => inner.0.clone(), + Self::Split { inner } => inner.0.clone(), + Self::PiglinZombified { inner } => inner.0.clone(), + Self::Metamorphosis { inner } => inner.0.clone(), + Self::Unknown { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Cured { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Frozen { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Infection { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Drowned { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Sheared { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Lightning { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Split { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PiglinZombified { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Metamorphosis { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Unknown { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for EntityTransformEventTransformReason<'mc> { @@ -2308,6 +2712,36 @@ impl<'mc> JNIInstantiatable<'mc> for EntityTransformEventTransformReason<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "CURED" => Ok(EntityTransformEventTransformReason::Cured { + inner: EntityTransformEventTransformReasonStruct::from_raw(env, obj)?, + }), + "FROZEN" => Ok(EntityTransformEventTransformReason::Frozen { + inner: EntityTransformEventTransformReasonStruct::from_raw(env, obj)?, + }), + "INFECTION" => Ok(EntityTransformEventTransformReason::Infection { + inner: EntityTransformEventTransformReasonStruct::from_raw(env, obj)?, + }), + "DROWNED" => Ok(EntityTransformEventTransformReason::Drowned { + inner: EntityTransformEventTransformReasonStruct::from_raw(env, obj)?, + }), + "SHEARED" => Ok(EntityTransformEventTransformReason::Sheared { + inner: EntityTransformEventTransformReasonStruct::from_raw(env, obj)?, + }), + "LIGHTNING" => Ok(EntityTransformEventTransformReason::Lightning { + inner: EntityTransformEventTransformReasonStruct::from_raw(env, obj)?, + }), + "SPLIT" => Ok(EntityTransformEventTransformReason::Split { + inner: EntityTransformEventTransformReasonStruct::from_raw(env, obj)?, + }), + "PIGLIN_ZOMBIFIED" => Ok(EntityTransformEventTransformReason::PiglinZombified { + inner: EntityTransformEventTransformReasonStruct::from_raw(env, obj)?, + }), + "METAMORPHOSIS" => Ok(EntityTransformEventTransformReason::Metamorphosis { + inner: EntityTransformEventTransformReasonStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(EntityTransformEventTransformReason::Unknown { + inner: EntityTransformEventTransformReasonStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -2830,16 +3264,179 @@ impl<'mc> EntityTeleportEvent<'mc> { ) -> Result<(), Box> { let sig = String::from("(Lorg/bukkit/Location;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(to.into().jni_object().clone()) + jni::objects::JObject::from_raw(to.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTo", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/entity/EntityTeleportEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['isCancelled', 'setCancelled', 'getFrom', 'setFrom', 'getTo', 'setTo', 'getHandlers', 'getHandlerList']) + /// Returns the Entity involved in this event + pub fn entity(&self) -> Result, Box> { + let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityEvent = temp_clone.into(); + real.entity() + } + /// Gets the EntityType of the Entity involved in this event. + pub fn entity_type( + &self, + ) -> Result, Box> { + let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityEvent = temp_clone.into(); + real.entity_type() + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for EntityTeleportEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EntityTeleportEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for EntityTeleportEvent<'mc> { + fn into(self) -> crate::event::entity::EntityEvent<'mc> { + crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EntityTeleportEvent into crate::event::entity::EntityEvent") + } +} +#[repr(C)] +pub struct TrialSpawnerSpawnEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for TrialSpawnerSpawnEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for TrialSpawnerSpawnEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate TrialSpawnerSpawnEvent from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/entity/TrialSpawnerSpawnEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a TrialSpawnerSpawnEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> TrialSpawnerSpawnEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + spawnee: impl Into>, + spawner: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;Lorg/bukkit/block/TrialSpawner;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(spawnee.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTo", + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(spawner.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/entity/TrialSpawnerSpawnEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = jni.translate_error_no_gen(res)?; + crate::event::entity::TrialSpawnerSpawnEvent::from_raw(&jni, res) + } + + pub fn trial_spawner( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/TrialSpawner;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTrialSpawner", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::TrialSpawner::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + // SUPER CLASS: org.bukkit.event.entity.EntitySpawnEvent ( ['getTrialSpawner']) + + pub fn is_cancelled(&self) -> Result> { + let temp_clone = crate::event::entity::EntitySpawnEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntitySpawnEvent = temp_clone.into(); + real.is_cancelled() + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let temp_clone = crate::event::entity::EntitySpawnEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntitySpawnEvent = temp_clone.into(); + real.set_cancelled(cancel) + } + /// Gets the location at which the entity is spawning. + pub fn location(&self) -> Result, Box> { + let temp_clone = crate::event::entity::EntitySpawnEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntitySpawnEvent = temp_clone.into(); + real.location() } pub fn handlers(&self) -> Result, Box> { @@ -2856,32 +3453,7 @@ impl<'mc> EntityTeleportEvent<'mc> { pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/entity/EntityTeleportEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['isCancelled', 'setCancelled', 'getFrom', 'setFrom', 'getTo', 'setTo', 'getHandlers', 'getHandlerList']) - /// Returns the Entity involved in this event - pub fn entity(&self) -> Result, Box> { - let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityEvent = temp_clone.into(); - real.entity() - } - /// Gets the EntityType of the Entity involved in this event. - pub fn entity_type( - &self, - ) -> Result, Box> { - let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityEvent = temp_clone.into(); - real.entity_type() + crate::event::entity::EntitySpawnEvent::handler_list(jni) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -2889,16 +3461,11 @@ impl<'mc> EntityTeleportEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for EntityTeleportEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EntityTeleportEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for EntityTeleportEvent<'mc> { - fn into(self) -> crate::event::entity::EntityEvent<'mc> { - crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EntityTeleportEvent into crate::event::entity::EntityEvent") +impl<'mc> Into> for TrialSpawnerSpawnEvent<'mc> { + fn into(self) -> crate::event::entity::EntitySpawnEvent<'mc> { + crate::event::entity::EntitySpawnEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting TrialSpawnerSpawnEvent into crate::event::entity::EntitySpawnEvent", + ) } } #[repr(C)] @@ -3671,10 +4238,34 @@ impl<'mc> Into> for CreeperPowerEvent<'mc .expect("Error converting CreeperPowerEvent into crate::event::entity::EntityEvent") } } -pub enum CreeperPowerEventPowerCause<'mc> {} +pub enum CreeperPowerEventPowerCause<'mc> { + Lightning { + inner: CreeperPowerEventPowerCauseStruct<'mc>, + }, + SetOn { + inner: CreeperPowerEventPowerCauseStruct<'mc>, + }, + SetOff { + inner: CreeperPowerEventPowerCauseStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for CreeperPowerEventPowerCause<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + CreeperPowerEventPowerCause::Lightning { .. } => f.write_str("LIGHTNING"), + CreeperPowerEventPowerCause::SetOn { .. } => f.write_str("SET_ON"), + CreeperPowerEventPowerCause::SetOff { .. } => f.write_str("SET_OFF"), + } + } +} +impl<'mc> std::ops::Deref for CreeperPowerEventPowerCause<'mc> { + type Target = CreeperPowerEventPowerCauseStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + CreeperPowerEventPowerCause::Lightning { inner } => inner, + CreeperPowerEventPowerCause::SetOn { inner } => inner, + CreeperPowerEventPowerCause::SetOff { inner } => inner, + } } } @@ -3701,6 +4292,16 @@ impl<'mc> CreeperPowerEventPowerCause<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "LIGHTNING" => Ok(CreeperPowerEventPowerCause::Lightning { + inner: CreeperPowerEventPowerCauseStruct::from_raw(env, obj)?, + }), + "SET_ON" => Ok(CreeperPowerEventPowerCause::SetOn { + inner: CreeperPowerEventPowerCauseStruct::from_raw(env, obj)?, + }), + "SET_OFF" => Ok(CreeperPowerEventPowerCause::SetOff { + inner: CreeperPowerEventPowerCauseStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -3714,10 +4315,20 @@ pub struct CreeperPowerEventPowerCauseStruct<'mc>( impl<'mc> JNIRaw<'mc> for CreeperPowerEventPowerCause<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Lightning { inner } => inner.0.clone(), + Self::SetOn { inner } => inner.0.clone(), + Self::SetOff { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Lightning { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SetOn { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SetOff { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for CreeperPowerEventPowerCause<'mc> { @@ -3747,6 +4358,15 @@ impl<'mc> JNIInstantiatable<'mc> for CreeperPowerEventPowerCause<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "LIGHTNING" => Ok(CreeperPowerEventPowerCause::Lightning { + inner: CreeperPowerEventPowerCauseStruct::from_raw(env, obj)?, + }), + "SET_ON" => Ok(CreeperPowerEventPowerCause::SetOn { + inner: CreeperPowerEventPowerCauseStruct::from_raw(env, obj)?, + }), + "SET_OFF" => Ok(CreeperPowerEventPowerCause::SetOff { + inner: CreeperPowerEventPowerCauseStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -4050,10 +4670,49 @@ impl<'mc> Into> for EntityKnockbackEvent< .expect("Error converting EntityKnockbackEvent into crate::event::entity::EntityEvent") } } -pub enum EntityKnockbackEventKnockbackCause<'mc> {} +pub enum EntityKnockbackEventKnockbackCause<'mc> { + Damage { + inner: EntityKnockbackEventKnockbackCauseStruct<'mc>, + }, + EntityAttack { + inner: EntityKnockbackEventKnockbackCauseStruct<'mc>, + }, + Explosion { + inner: EntityKnockbackEventKnockbackCauseStruct<'mc>, + }, + ShieldBlock { + inner: EntityKnockbackEventKnockbackCauseStruct<'mc>, + }, + SweepAttack { + inner: EntityKnockbackEventKnockbackCauseStruct<'mc>, + }, + Unknown { + inner: EntityKnockbackEventKnockbackCauseStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for EntityKnockbackEventKnockbackCause<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + EntityKnockbackEventKnockbackCause::Damage { .. } => f.write_str("DAMAGE"), + EntityKnockbackEventKnockbackCause::EntityAttack { .. } => f.write_str("ENTITY_ATTACK"), + EntityKnockbackEventKnockbackCause::Explosion { .. } => f.write_str("EXPLOSION"), + EntityKnockbackEventKnockbackCause::ShieldBlock { .. } => f.write_str("SHIELD_BLOCK"), + EntityKnockbackEventKnockbackCause::SweepAttack { .. } => f.write_str("SWEEP_ATTACK"), + EntityKnockbackEventKnockbackCause::Unknown { .. } => f.write_str("UNKNOWN"), + } + } +} +impl<'mc> std::ops::Deref for EntityKnockbackEventKnockbackCause<'mc> { + type Target = EntityKnockbackEventKnockbackCauseStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + EntityKnockbackEventKnockbackCause::Damage { inner } => inner, + EntityKnockbackEventKnockbackCause::EntityAttack { inner } => inner, + EntityKnockbackEventKnockbackCause::Explosion { inner } => inner, + EntityKnockbackEventKnockbackCause::ShieldBlock { inner } => inner, + EntityKnockbackEventKnockbackCause::SweepAttack { inner } => inner, + EntityKnockbackEventKnockbackCause::Unknown { inner } => inner, + } } } @@ -4080,6 +4739,25 @@ impl<'mc> EntityKnockbackEventKnockbackCause<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "DAMAGE" => Ok(EntityKnockbackEventKnockbackCause::Damage { + inner: EntityKnockbackEventKnockbackCauseStruct::from_raw(env, obj)?, + }), + "ENTITY_ATTACK" => Ok(EntityKnockbackEventKnockbackCause::EntityAttack { + inner: EntityKnockbackEventKnockbackCauseStruct::from_raw(env, obj)?, + }), + "EXPLOSION" => Ok(EntityKnockbackEventKnockbackCause::Explosion { + inner: EntityKnockbackEventKnockbackCauseStruct::from_raw(env, obj)?, + }), + "SHIELD_BLOCK" => Ok(EntityKnockbackEventKnockbackCause::ShieldBlock { + inner: EntityKnockbackEventKnockbackCauseStruct::from_raw(env, obj)?, + }), + "SWEEP_ATTACK" => Ok(EntityKnockbackEventKnockbackCause::SweepAttack { + inner: EntityKnockbackEventKnockbackCauseStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(EntityKnockbackEventKnockbackCause::Unknown { + inner: EntityKnockbackEventKnockbackCauseStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -4093,10 +4771,32 @@ pub struct EntityKnockbackEventKnockbackCauseStruct<'mc>( impl<'mc> JNIRaw<'mc> for EntityKnockbackEventKnockbackCause<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Damage { inner } => inner.0.clone(), + Self::EntityAttack { inner } => inner.0.clone(), + Self::Explosion { inner } => inner.0.clone(), + Self::ShieldBlock { inner } => inner.0.clone(), + Self::SweepAttack { inner } => inner.0.clone(), + Self::Unknown { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Damage { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::EntityAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Explosion { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ShieldBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SweepAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Unknown { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for EntityKnockbackEventKnockbackCause<'mc> { @@ -4128,6 +4828,24 @@ impl<'mc> JNIInstantiatable<'mc> for EntityKnockbackEventKnockbackCause<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "DAMAGE" => Ok(EntityKnockbackEventKnockbackCause::Damage { + inner: EntityKnockbackEventKnockbackCauseStruct::from_raw(env, obj)?, + }), + "ENTITY_ATTACK" => Ok(EntityKnockbackEventKnockbackCause::EntityAttack { + inner: EntityKnockbackEventKnockbackCauseStruct::from_raw(env, obj)?, + }), + "EXPLOSION" => Ok(EntityKnockbackEventKnockbackCause::Explosion { + inner: EntityKnockbackEventKnockbackCauseStruct::from_raw(env, obj)?, + }), + "SHIELD_BLOCK" => Ok(EntityKnockbackEventKnockbackCause::ShieldBlock { + inner: EntityKnockbackEventKnockbackCauseStruct::from_raw(env, obj)?, + }), + "SWEEP_ATTACK" => Ok(EntityKnockbackEventKnockbackCause::SweepAttack { + inner: EntityKnockbackEventKnockbackCauseStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(EntityKnockbackEventKnockbackCause::Unknown { + inner: EntityKnockbackEventKnockbackCauseStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -4605,10 +5323,39 @@ impl<'mc> Into> for EntityUnleashEvent<'m .expect("Error converting EntityUnleashEvent into crate::event::entity::EntityEvent") } } -pub enum EntityUnleashEventUnleashReason<'mc> {} +pub enum EntityUnleashEventUnleashReason<'mc> { + HolderGone { + inner: EntityUnleashEventUnleashReasonStruct<'mc>, + }, + PlayerUnleash { + inner: EntityUnleashEventUnleashReasonStruct<'mc>, + }, + Distance { + inner: EntityUnleashEventUnleashReasonStruct<'mc>, + }, + Unknown { + inner: EntityUnleashEventUnleashReasonStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for EntityUnleashEventUnleashReason<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + EntityUnleashEventUnleashReason::HolderGone { .. } => f.write_str("HOLDER_GONE"), + EntityUnleashEventUnleashReason::PlayerUnleash { .. } => f.write_str("PLAYER_UNLEASH"), + EntityUnleashEventUnleashReason::Distance { .. } => f.write_str("DISTANCE"), + EntityUnleashEventUnleashReason::Unknown { .. } => f.write_str("UNKNOWN"), + } + } +} +impl<'mc> std::ops::Deref for EntityUnleashEventUnleashReason<'mc> { + type Target = EntityUnleashEventUnleashReasonStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + EntityUnleashEventUnleashReason::HolderGone { inner } => inner, + EntityUnleashEventUnleashReason::PlayerUnleash { inner } => inner, + EntityUnleashEventUnleashReason::Distance { inner } => inner, + EntityUnleashEventUnleashReason::Unknown { inner } => inner, + } } } @@ -4635,6 +5382,19 @@ impl<'mc> EntityUnleashEventUnleashReason<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "HOLDER_GONE" => Ok(EntityUnleashEventUnleashReason::HolderGone { + inner: EntityUnleashEventUnleashReasonStruct::from_raw(env, obj)?, + }), + "PLAYER_UNLEASH" => Ok(EntityUnleashEventUnleashReason::PlayerUnleash { + inner: EntityUnleashEventUnleashReasonStruct::from_raw(env, obj)?, + }), + "DISTANCE" => Ok(EntityUnleashEventUnleashReason::Distance { + inner: EntityUnleashEventUnleashReasonStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(EntityUnleashEventUnleashReason::Unknown { + inner: EntityUnleashEventUnleashReasonStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -4648,10 +5408,24 @@ pub struct EntityUnleashEventUnleashReasonStruct<'mc>( impl<'mc> JNIRaw<'mc> for EntityUnleashEventUnleashReason<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::HolderGone { inner } => inner.0.clone(), + Self::PlayerUnleash { inner } => inner.0.clone(), + Self::Distance { inner } => inner.0.clone(), + Self::Unknown { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::HolderGone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PlayerUnleash { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Distance { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Unknown { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for EntityUnleashEventUnleashReason<'mc> { @@ -4683,6 +5457,18 @@ impl<'mc> JNIInstantiatable<'mc> for EntityUnleashEventUnleashReason<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "HOLDER_GONE" => Ok(EntityUnleashEventUnleashReason::HolderGone { + inner: EntityUnleashEventUnleashReasonStruct::from_raw(env, obj)?, + }), + "PLAYER_UNLEASH" => Ok(EntityUnleashEventUnleashReason::PlayerUnleash { + inner: EntityUnleashEventUnleashReasonStruct::from_raw(env, obj)?, + }), + "DISTANCE" => Ok(EntityUnleashEventUnleashReason::Distance { + inner: EntityUnleashEventUnleashReasonStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(EntityUnleashEventUnleashReason::Unknown { + inner: EntityUnleashEventUnleashReasonStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -4835,36 +5621,209 @@ impl<'mc> EntityPickupItemEvent<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the amount remaining on the ground, if any - pub fn remaining(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the amount remaining on the ground, if any + pub fn remaining(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRemaining", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/entity/EntityPickupItemEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['getEntity', 'getItem', 'getRemaining', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + /// Gets the EntityType of the Entity involved in this event. + pub fn entity_type( + &self, + ) -> Result, Box> { + let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityEvent = temp_clone.into(); + real.entity_type() + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for EntityPickupItemEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EntityPickupItemEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for EntityPickupItemEvent<'mc> { + fn into(self) -> crate::event::entity::EntityEvent<'mc> { + crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EntityPickupItemEvent into crate::event::entity::EntityEvent") + } +} +#[repr(C)] +pub struct EntityCombustByBlockEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for EntityCombustByBlockEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for EntityCombustByBlockEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate EntityCombustByBlockEvent from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/entity/EntityCombustByBlockEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EntityCombustByBlockEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> EntityCombustByBlockEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + combuster: impl Into>, + combustee: impl Into>, + duration: f32, + ) -> Result, Box> + { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/block/Block;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(combuster.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Lorg/bukkit/entity/Entity;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(combustee.into().jni_object().clone()) + }); + args.push(val_2); + sig += "F"; + let val_3 = jni::objects::JValueGen::Float(duration); + args.push(val_3); + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/entity/EntityCombustByBlockEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::event::entity::EntityCombustByBlockEvent::from_raw(&jni, res) + } + /// The combuster can be lava or a block that is on fire. + /// + /// WARNING: block may be null. + pub fn combuster( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getRemaining", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCombuster", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::block::Block::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } + // SUPER CLASS: org.bukkit.event.entity.EntityCombustEvent ( ['getCombuster']) pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let temp_clone = crate::event::entity::EntityCombustEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityCombustEvent = temp_clone.into(); + real.is_cancelled() } pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + let temp_clone = crate::event::entity::EntityCombustEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityCombustEvent = temp_clone.into(); + real.set_cancelled(cancel) + } + + pub fn duration(&self) -> Result> { + let temp_clone = crate::event::entity::EntityCombustEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityCombustEvent = temp_clone.into(); + real.duration() + } + /// The number of seconds the combustee should be alight for.This value will only ever increase the combustion time, not decrease existing combustion times. + pub fn set_duration(&self, duration: i32) -> Result<(), Box> { + let temp_clone = crate::event::entity::EntityCombustEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityCombustEvent = temp_clone.into(); + real.set_duration(duration) } pub fn handlers(&self) -> Result, Box> { @@ -4881,24 +5840,7 @@ impl<'mc> EntityPickupItemEvent<'mc> { pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/entity/EntityPickupItemEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['getEntity', 'getItem', 'getRemaining', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) - /// Gets the EntityType of the Entity involved in this event. - pub fn entity_type( - &self, - ) -> Result, Box> { - let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityEvent = temp_clone.into(); - real.entity_type() + crate::event::entity::EntityCombustEvent::handler_list(jni) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -4906,16 +5848,9 @@ impl<'mc> EntityPickupItemEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for EntityPickupItemEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EntityPickupItemEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for EntityPickupItemEvent<'mc> { - fn into(self) -> crate::event::entity::EntityEvent<'mc> { - crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EntityPickupItemEvent into crate::event::entity::EntityEvent") +impl<'mc> Into> for EntityCombustByBlockEvent<'mc> { + fn into(self) -> crate::event::entity::EntityCombustEvent<'mc> { + crate::event::entity::EntityCombustEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting EntityCombustByBlockEvent into crate::event::entity::EntityCombustEvent") } } #[repr(C)] @@ -5261,19 +6196,168 @@ impl<'mc> Into> for EntityTameEvent<'mc> { .expect("Error converting EntityTameEvent into crate::event::Cancellable") } } -impl<'mc> Into> for EntityTameEvent<'mc> { +impl<'mc> Into> for EntityTameEvent<'mc> { + fn into(self) -> crate::event::entity::EntityEvent<'mc> { + crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EntityTameEvent into crate::event::entity::EntityEvent") + } +} +#[repr(C)] +pub struct EntitySpawnEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for EntitySpawnEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for EntitySpawnEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate EntitySpawnEvent from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/entity/EntitySpawnEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EntitySpawnEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> EntitySpawnEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + spawnee: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(spawnee.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/entity/EntitySpawnEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error_no_gen(res)?; + crate::event::entity::EntitySpawnEvent::from_raw(&jni, res) + } + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the location at which the entity is spawning. + pub fn location(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/entity/EntitySpawnEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['isCancelled', 'setCancelled', 'getLocation', 'getHandlers', 'getHandlerList']) + /// Returns the Entity involved in this event + pub fn entity(&self) -> Result, Box> { + let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityEvent = temp_clone.into(); + real.entity() + } + /// Gets the EntityType of the Entity involved in this event. + pub fn entity_type( + &self, + ) -> Result, Box> { + let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityEvent = temp_clone.into(); + real.entity_type() + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for EntitySpawnEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EntitySpawnEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for EntitySpawnEvent<'mc> { fn into(self) -> crate::event::entity::EntityEvent<'mc> { crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EntityTameEvent into crate::event::entity::EntityEvent") + .expect("Error converting EntitySpawnEvent into crate::event::entity::EntityEvent") } } #[repr(C)] -pub struct EntitySpawnEvent<'mc>( +pub struct EntityCombustEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EntitySpawnEvent<'mc> { +impl<'mc> JNIRaw<'mc> for EntityCombustEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -5281,20 +6365,21 @@ impl<'mc> JNIRaw<'mc> for EntitySpawnEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EntitySpawnEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EntityCombustEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate EntitySpawnEvent from null object.").into(), + eyre::eyre!("Tried to instantiate EntityCombustEvent from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/entity/EntitySpawnEvent")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/entity/EntityCombustEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EntitySpawnEvent object, got {}", + "Invalid argument passed. Expected a EntityCombustEvent object, got {}", name ) .into()) @@ -5304,24 +6389,28 @@ impl<'mc> JNIInstantiatable<'mc> for EntitySpawnEvent<'mc> { } } -impl<'mc> EntitySpawnEvent<'mc> { +impl<'mc> EntityCombustEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - spawnee: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + combustee: impl Into>, + duration: f32, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Entity;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(spawnee.into().jni_object().clone()) + jni::objects::JObject::from_raw(combustee.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/entity/EntitySpawnEvent"); + args.push(val_1); + sig += "F"; + let val_2 = jni::objects::JValueGen::Float(duration); + args.push(val_2); + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/entity/EntityCombustEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::entity::EntitySpawnEvent::from_raw(&jni, res) + crate::event::entity::EntityCombustEvent::from_raw(&jni, res) } pub fn is_cancelled(&self) -> Result> { @@ -5345,16 +6434,29 @@ impl<'mc> EntitySpawnEvent<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the location at which the entity is spawning. - pub fn location(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); + + pub fn duration(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDuration", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.f()?) + } + #[deprecated] + /// The number of seconds the combustee should be alight for.This value will only ever increase the combustion time, not decrease existing combustion times. + pub fn set_duration(&self, duration: i32) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(duration); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setDuration", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn handlers(&self) -> Result, Box> { @@ -5372,14 +6474,14 @@ impl<'mc> EntitySpawnEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/entity/EntitySpawnEvent"); + let cls = jni.find_class("org/bukkit/event/entity/EntityCombustEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['isCancelled', 'setCancelled', 'getLocation', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['isCancelled', 'setCancelled', 'getDuration', 'setDuration', 'getHandlers', 'getHandlerList']) /// Returns the Entity involved in this event pub fn entity(&self) -> Result, Box> { let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { @@ -5404,16 +6506,16 @@ impl<'mc> EntitySpawnEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for EntitySpawnEvent<'mc> { +impl<'mc> Into> for EntityCombustEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EntitySpawnEvent into crate::event::Cancellable") + .expect("Error converting EntityCombustEvent into crate::event::Cancellable") } } -impl<'mc> Into> for EntitySpawnEvent<'mc> { +impl<'mc> Into> for EntityCombustEvent<'mc> { fn into(self) -> crate::event::entity::EntityEvent<'mc> { crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EntitySpawnEvent into crate::event::entity::EntityEvent") + .expect("Error converting EntityCombustEvent into crate::event::entity::EntityEvent") } } #[repr(C)] @@ -5716,39 +6818,207 @@ impl<'mc> EntityCreatePortalEvent<'mc> { .jni_ref() .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::LivingEntity::from_raw(&self.jni_ref(), unsafe { + crate::entity::LivingEntity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets a list of all blocks associated with the portal. + pub fn blocks(&self) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBlocks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::BlockState::from_raw(&self.0, obj)?); + } + Ok(new_vec) + } + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the type of portal that is trying to be created. + pub fn portal_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/PortalType;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPortalType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::PortalType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/entity/EntityCreatePortalEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['getEntity', 'getBlocks', 'isCancelled', 'setCancelled', 'getPortalType', 'getHandlers', 'getHandlerList']) + /// Gets the EntityType of the Entity involved in this event. + pub fn entity_type( + &self, + ) -> Result, Box> { + let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityEvent = temp_clone.into(); + real.entity_type() + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for EntityCreatePortalEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EntityCreatePortalEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for EntityCreatePortalEvent<'mc> { + fn into(self) -> crate::event::entity::EntityEvent<'mc> { + crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting EntityCreatePortalEvent into crate::event::entity::EntityEvent", + ) + } +} +#[repr(C)] +pub struct EntitySpellCastEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for EntitySpellCastEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for EntitySpellCastEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate EntitySpellCastEvent from null object.").into(), + ); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/entity/EntitySpellCastEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EntitySpellCastEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> EntitySpellCastEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + what: impl Into>, + spell: impl Into>, + ) -> Result, Box> { + let sig = + String::from("(Lorg/bukkit/entity/Spellcaster;Lorg/bukkit/entity/Spellcaster/Spell;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(what.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(spell.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/entity/EntitySpellCastEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::event::entity::EntitySpellCastEvent::from_raw(&jni, res) + } + + pub fn entity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Spellcaster;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Spellcaster::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets a list of all blocks associated with the portal. - pub fn blocks(&self) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + /// Get the spell to be cast in this event. + /// This is a convenience method equivalent to + /// {@link Spellcaster#getSpell()}. + pub fn spell( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Spellcaster/Spell;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getBlocks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::BlockState::from_raw(&self.0, obj)?); - } - Ok(new_vec) - } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSpell", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::SpellcasterSpell::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + pub fn set_cancelled(&self, cancelled: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let val_1 = jni::objects::JValueGen::Bool(cancelled.into()); let res = self.jni_ref().call_method( &self.jni_object(), "setCancelled", @@ -5758,16 +7028,14 @@ impl<'mc> EntityCreatePortalEvent<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the type of portal that is trying to be created. - pub fn portal_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/PortalType;"); + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPortalType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::PortalType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } pub fn handlers(&self) -> Result, Box> { @@ -5785,14 +7053,14 @@ impl<'mc> EntityCreatePortalEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/entity/EntityCreatePortalEvent"); + let cls = jni.find_class("org/bukkit/event/entity/EntitySpellCastEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['getEntity', 'getBlocks', 'isCancelled', 'setCancelled', 'getPortalType', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['getEntity', 'getSpell', 'setCancelled', 'isCancelled', 'getHandlers', 'getHandlerList']) /// Gets the EntityType of the Entity involved in this event. pub fn entity_type( &self, @@ -5809,26 +7077,25 @@ impl<'mc> EntityCreatePortalEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for EntityCreatePortalEvent<'mc> { +impl<'mc> Into> for EntitySpellCastEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EntityCreatePortalEvent into crate::event::Cancellable") + .expect("Error converting EntitySpellCastEvent into crate::event::Cancellable") } } -impl<'mc> Into> for EntityCreatePortalEvent<'mc> { +impl<'mc> Into> for EntitySpellCastEvent<'mc> { fn into(self) -> crate::event::entity::EntityEvent<'mc> { - crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting EntityCreatePortalEvent into crate::event::entity::EntityEvent", - ) + crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EntitySpellCastEvent into crate::event::entity::EntityEvent") } } #[repr(C)] -pub struct PotionSplashEvent<'mc>( +pub struct EntityPortalExitEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PotionSplashEvent<'mc> { +impl<'mc> JNIRaw<'mc> for EntityPortalExitEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -5836,20 +7103,22 @@ impl<'mc> JNIRaw<'mc> for PotionSplashEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PotionSplashEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EntityPortalExitEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate PotionSplashEvent from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate EntityPortalExitEvent from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/entity/PotionSplashEvent")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/entity/EntityPortalExitEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PotionSplashEvent object, got {}", + "Invalid argument passed. Expected a EntityPortalExitEvent object, got {}", name ) .into()) @@ -5859,156 +7128,83 @@ impl<'mc> JNIInstantiatable<'mc> for PotionSplashEvent<'mc> { } } -impl<'mc> PotionSplashEvent<'mc> { +impl<'mc> EntityPortalExitEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - potion: impl Into>, - hit_entity: impl Into>, - hit_block: std::option::Option>>, - hit_face: std::option::Option>>, - affected_entities: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/ThrownPotion;"; + entity: impl Into>, + from: impl Into>, + to: impl Into>, + before: impl Into>, + after: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;Lorg/bukkit/Location;Lorg/bukkit/Location;Lorg/bukkit/util/Vector;Lorg/bukkit/util/Vector;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(potion.into().jni_object().clone()) + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) }); - args.push(val_1); - sig += "Lorg/bukkit/entity/Entity;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(hit_entity.into().jni_object().clone()) + jni::objects::JObject::from_raw(from.into().jni_object().clone()) }); - args.push(val_2); - if let Some(a) = hit_block { - sig += "Lorg/bukkit/block/Block;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_3); - } - if let Some(a) = hit_face { - sig += "Lorg/bukkit/block/BlockFace;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_4); - } - if let Some(a) = affected_entities { - sig += "Ljava/util/Map;"; - let val_5 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_5); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/event/entity/PotionSplashEvent"); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(to.into().jni_object().clone()) + }); + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(before.into().jni_object().clone()) + }); + let val_5 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(after.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/entity/EntityPortalExitEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + jni::objects::JValueGen::from(val_5), + ], + ); let res = jni.translate_error_no_gen(res)?; - crate::event::entity::PotionSplashEvent::from_raw(&jni, res) + crate::event::entity::EntityPortalExitEvent::from_raw(&jni, res) } - - pub fn entity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/ThrownPotion;"); + /// Gets a copy of the velocity that the entity has before entering the + /// portal. + pub fn before(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBefore", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::ThrownPotion::from_raw(&self.jni_ref(), unsafe { + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the potion which caused this event - pub fn potion(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/ThrownPotion;"); + /// Gets a copy of the velocity that the entity will have after exiting the + /// portal. + pub fn after(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getPotion", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAfter", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::ThrownPotion::from_raw(&self.jni_ref(), unsafe { + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Retrieves a list of all effected entities - pub fn affected_entities( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAffectedEntities", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::LivingEntity::from_raw(&self.0, obj)?); - } - Ok(new_vec) - } - /// Gets the intensity of the potion's effects for given entity; This - /// depends on the distance to the impact center - pub fn get_intensity( - &self, - entity: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/LivingEntity;)D"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getIntensity", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Overwrites the intensity for a given entity - pub fn set_intensity( + /// Sets the velocity that the entity will have after exiting the portal. + pub fn set_after( &self, - entity: impl Into>, - intensity: f64, + after: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/LivingEntity;D)V"); + let sig = String::from("(Lorg/bukkit/util/Vector;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + jni::objects::JObject::from_raw(after.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Double(intensity); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setIntensity", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCancelled", + "setAfter", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -6031,44 +7227,67 @@ impl<'mc> PotionSplashEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/entity/PotionSplashEvent"); + let cls = jni.find_class("org/bukkit/event/entity/EntityPortalExitEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.entity.ProjectileHitEvent ( ['getEntity', 'getPotion', 'getAffectedEntities', 'getIntensity', 'setIntensity', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) - /// Gets the block that was hit, if it was a block that was hit. - pub fn hit_block( - &self, - ) -> Result>, Box> { - let temp_clone = crate::event::entity::ProjectileHitEvent::from_raw(&self.0, unsafe { + // SUPER CLASS: org.bukkit.event.entity.EntityTeleportEvent ( ['getBefore', 'getAfter', 'setAfter', 'getHandlers', 'getHandlerList']) + + pub fn is_cancelled(&self) -> Result> { + let temp_clone = crate::event::entity::EntityTeleportEvent::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::entity::ProjectileHitEvent = temp_clone.into(); - real.hit_block() + let real: crate::event::entity::EntityTeleportEvent = temp_clone.into(); + real.is_cancelled() } - /// Gets the block face that was hit, if it was a block that was hit and the - /// face was provided in the event. - pub fn hit_block_face( + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let temp_clone = crate::event::entity::EntityTeleportEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityTeleportEvent = temp_clone.into(); + real.set_cancelled(cancel) + } + /// Gets the location that this entity moved from + pub fn from(&self) -> Result, Box> { + let temp_clone = crate::event::entity::EntityTeleportEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityTeleportEvent = temp_clone.into(); + real.from() + } + /// Sets the location that this entity moved from + pub fn set_from( &self, - ) -> Result>, Box> { - let temp_clone = crate::event::entity::ProjectileHitEvent::from_raw(&self.0, unsafe { + from: impl Into>, + ) -> Result<(), Box> { + let temp_clone = crate::event::entity::EntityTeleportEvent::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::entity::ProjectileHitEvent = temp_clone.into(); - real.hit_block_face() + let real: crate::event::entity::EntityTeleportEvent = temp_clone.into(); + real.set_from(from) } - /// Gets the entity that was hit, if it was an entity that was hit. - pub fn hit_entity( + /// Gets the location that this entity moved to + pub fn to(&self) -> Result>, Box> { + let temp_clone = crate::event::entity::EntityTeleportEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityTeleportEvent = temp_clone.into(); + real.to() + } + /// Sets the location that this entity moved to + pub fn set_to( &self, - ) -> Result>, Box> { - let temp_clone = crate::event::entity::ProjectileHitEvent::from_raw(&self.0, unsafe { + to: impl Into>, + ) -> Result<(), Box> { + let temp_clone = crate::event::entity::EntityTeleportEvent::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::entity::ProjectileHitEvent = temp_clone.into(); - real.hit_entity() + let real: crate::event::entity::EntityTeleportEvent = temp_clone.into(); + real.set_to(to) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -6076,26 +7295,20 @@ impl<'mc> PotionSplashEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PotionSplashEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PotionSplashEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for PotionSplashEvent<'mc> { - fn into(self) -> crate::event::entity::ProjectileHitEvent<'mc> { - crate::event::entity::ProjectileHitEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting PotionSplashEvent into crate::event::entity::ProjectileHitEvent", +impl<'mc> Into> for EntityPortalExitEvent<'mc> { + fn into(self) -> crate::event::entity::EntityTeleportEvent<'mc> { + crate::event::entity::EntityTeleportEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting EntityPortalExitEvent into crate::event::entity::EntityTeleportEvent", ) } } #[repr(C)] -pub struct EntitySpellCastEvent<'mc>( +pub struct EntityDeathEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EntitySpellCastEvent<'mc> { +impl<'mc> JNIRaw<'mc> for EntityDeathEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6103,21 +7316,20 @@ impl<'mc> JNIRaw<'mc> for EntitySpellCastEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EntitySpellCastEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EntityDeathEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate EntitySpellCastEvent from null object.").into(), + eyre::eyre!("Tried to instantiate EntityDeathEvent from null object.").into(), ); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/entity/EntitySpellCastEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/entity/EntityDeathEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EntitySpellCastEvent object, got {}", + "Invalid argument passed. Expected a EntityDeathEvent object, got {}", name ) .into()) @@ -6127,80 +7339,121 @@ impl<'mc> JNIInstantiatable<'mc> for EntitySpellCastEvent<'mc> { } } -impl<'mc> EntitySpellCastEvent<'mc> { +impl<'mc> EntityDeathEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - what: impl Into>, - spell: impl Into>, - ) -> Result, Box> { - let sig = - String::from("(Lorg/bukkit/entity/Spellcaster;Lorg/bukkit/entity/Spellcaster/Spell;)V"); + what: impl Into>, + damage_source: impl Into>, + drops: Vec>, + dropped_exp: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/LivingEntity;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(what.into().jni_object().clone()) }); + args.push(val_1); + sig += "Lorg/bukkit/damage/DamageSource;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(spell.into().jni_object().clone()) + jni::objects::JObject::from_raw(damage_source.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/entity/EntitySpellCastEvent"); + args.push(val_2); + sig += "Ljava/util/List;"; + let raw_val_3 = jni.new_object("java/util/ArrayList", "()V", vec![])?; + for v in drops { + sig += "Ljava/lang/java/lang/Object;"; + let map_val_0 = jni::objects::JValueGen::Object(v); + jni.call_method( + &raw_val_3, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_3 = jni::objects::JValueGen::Object(raw_val_3); + args.push(val_3); + if let Some(a) = dropped_exp { + sig += "I"; + let val_4 = jni::objects::JValueGen::Int(a); + args.push(val_4); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/entity/EntityDeathEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::entity::EntitySpellCastEvent::from_raw(&jni, res) + crate::event::entity::EntityDeathEvent::from_raw(&jni, res) } - pub fn entity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Spellcaster;"); + pub fn entity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); let res = self .jni_ref() .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Spellcaster::from_raw(&self.jni_ref(), unsafe { + crate::entity::LivingEntity::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the spell to be cast in this event. - /// This is a convenience method equivalent to - /// {@link Spellcaster#getSpell()}. - pub fn spell( + /// Gets the source of damage which caused the death. + pub fn damage_source( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Spellcaster/Spell;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSpell", sig.as_str(), vec![]); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/damage/DamageSource;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDamageSource", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::SpellcasterSpell::from_raw(&self.jni_ref(), unsafe { + crate::damage::DamageSource::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn set_cancelled(&self, cancelled: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancelled.into()); + /// Gets how much EXP should be dropped from this death. + /// + /// This does not indicate how much EXP should be taken from the entity in + /// question, merely how much should be created after its death. + pub fn dropped_exp(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDroppedExp", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets how much EXP should be dropped from this death. + /// + /// This does not indicate how much EXP should be taken from the entity in + /// question, merely how much should be created after its death. + pub fn set_dropped_exp(&self, exp: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(exp); let res = self.jni_ref().call_method( &self.jni_object(), - "setCancelled", + "setDroppedExp", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + /// Gets all the items which will drop when the entity dies + pub fn drops( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getDrops", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::inventory::ItemStack::from_raw(&self.0, obj)?); + } + Ok(new_vec) } pub fn handlers(&self) -> Result, Box> { @@ -6218,14 +7471,14 @@ impl<'mc> EntitySpellCastEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/entity/EntitySpellCastEvent"); + let cls = jni.find_class("org/bukkit/event/entity/EntityDeathEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['getEntity', 'getSpell', 'setCancelled', 'isCancelled', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['getEntity', 'getDamageSource', 'getDroppedExp', 'setDroppedExp', 'getDrops', 'getHandlers', 'getHandlerList']) /// Gets the EntityType of the Entity involved in this event. pub fn entity_type( &self, @@ -6242,25 +7495,19 @@ impl<'mc> EntitySpellCastEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for EntitySpellCastEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EntitySpellCastEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for EntitySpellCastEvent<'mc> { +impl<'mc> Into> for EntityDeathEvent<'mc> { fn into(self) -> crate::event::entity::EntityEvent<'mc> { crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EntitySpellCastEvent into crate::event::entity::EntityEvent") + .expect("Error converting EntityDeathEvent into crate::event::entity::EntityEvent") } } #[repr(C)] -pub struct EntityPortalExitEvent<'mc>( +pub struct EntityToggleGlideEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EntityPortalExitEvent<'mc> { +impl<'mc> JNIRaw<'mc> for EntityToggleGlideEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6268,22 +7515,22 @@ impl<'mc> JNIRaw<'mc> for EntityPortalExitEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EntityPortalExitEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EntityToggleGlideEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate EntityPortalExitEvent from null object." + "Tried to instantiate EntityToggleGlideEvent from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/entity/EntityPortalExitEvent")?; + env.validate_name(&obj, "org/bukkit/event/entity/EntityToggleGlideEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityPortalExitEvent object, got {}", + "Invalid argument passed. Expected a EntityToggleGlideEvent object, got {}", name ) .into()) @@ -6293,32 +7540,18 @@ impl<'mc> JNIInstantiatable<'mc> for EntityPortalExitEvent<'mc> { } } -impl<'mc> EntityPortalExitEvent<'mc> { +impl<'mc> EntityToggleGlideEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - entity: impl Into>, - from: impl Into>, - to: impl Into>, - before: impl Into>, - after: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;Lorg/bukkit/Location;Lorg/bukkit/Location;Lorg/bukkit/util/Vector;Lorg/bukkit/util/Vector;)V"); + who: impl Into>, + is_gliding: bool, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/LivingEntity;Z)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(from.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(to.into().jni_object().clone()) - }); - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(before.into().jni_object().clone()) - }); - let val_5 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(after.into().jni_object().clone()) + jni::objects::JObject::from_raw(who.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/entity/EntityPortalExitEvent"); + let val_2 = jni::objects::JValueGen::Bool(is_gliding.into()); + let cls = jni.find_class("org/bukkit/event/entity/EntityToggleGlideEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -6326,56 +7559,43 @@ impl<'mc> EntityPortalExitEvent<'mc> { vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - jni::objects::JValueGen::from(val_5), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::entity::EntityPortalExitEvent::from_raw(&jni, res) - } - /// Gets a copy of the velocity that the entity has before entering the - /// portal. - pub fn before(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBefore", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + crate::event::entity::EntityToggleGlideEvent::from_raw(&jni, res) } - /// Gets a copy of the velocity that the entity will have after exiting the - /// portal. - pub fn after(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getAfter", sig.as_str(), vec![]); + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets the velocity that the entity will have after exiting the portal. - pub fn set_after( - &self, - after: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(after.into().jni_object().clone()) - }); + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setAfter", + "setCancelled", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } + /// Returns true if the entity is now gliding or + /// false if the entity stops gliding. + pub fn is_gliding(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -6392,67 +7612,31 @@ impl<'mc> EntityPortalExitEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/entity/EntityPortalExitEvent"); + let cls = jni.find_class("org/bukkit/event/entity/EntityToggleGlideEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.entity.EntityTeleportEvent ( ['getBefore', 'getAfter', 'setAfter', 'getHandlers', 'getHandlerList']) - - pub fn is_cancelled(&self) -> Result> { - let temp_clone = crate::event::entity::EntityTeleportEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityTeleportEvent = temp_clone.into(); - real.is_cancelled() - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let temp_clone = crate::event::entity::EntityTeleportEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityTeleportEvent = temp_clone.into(); - real.set_cancelled(cancel) - } - /// Gets the location that this entity moved from - pub fn from(&self) -> Result, Box> { - let temp_clone = crate::event::entity::EntityTeleportEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityTeleportEvent = temp_clone.into(); - real.from() - } - /// Sets the location that this entity moved from - pub fn set_from( - &self, - from: impl Into>, - ) -> Result<(), Box> { - let temp_clone = crate::event::entity::EntityTeleportEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityTeleportEvent = temp_clone.into(); - real.set_from(from) - } - /// Gets the location that this entity moved to - pub fn to(&self) -> Result>, Box> { - let temp_clone = crate::event::entity::EntityTeleportEvent::from_raw(&self.0, unsafe { + // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['isCancelled', 'setCancelled', 'isGliding', 'getHandlers', 'getHandlerList']) + /// Returns the Entity involved in this event + pub fn entity(&self) -> Result, Box> { + let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::entity::EntityTeleportEvent = temp_clone.into(); - real.to() + let real: crate::event::entity::EntityEvent = temp_clone.into(); + real.entity() } - /// Sets the location that this entity moved to - pub fn set_to( + /// Gets the EntityType of the Entity involved in this event. + pub fn entity_type( &self, - to: impl Into>, - ) -> Result<(), Box> { - let temp_clone = crate::event::entity::EntityTeleportEvent::from_raw(&self.0, unsafe { + ) -> Result, Box> { + let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::entity::EntityTeleportEvent = temp_clone.into(); - real.set_to(to) + let real: crate::event::entity::EntityEvent = temp_clone.into(); + real.entity_type() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -6460,20 +7644,26 @@ impl<'mc> EntityPortalExitEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for EntityPortalExitEvent<'mc> { - fn into(self) -> crate::event::entity::EntityTeleportEvent<'mc> { - crate::event::entity::EntityTeleportEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting EntityPortalExitEvent into crate::event::entity::EntityTeleportEvent", +impl<'mc> Into> for EntityToggleGlideEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EntityToggleGlideEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for EntityToggleGlideEvent<'mc> { + fn into(self) -> crate::event::entity::EntityEvent<'mc> { + crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting EntityToggleGlideEvent into crate::event::entity::EntityEvent", ) } } #[repr(C)] -pub struct EntityDeathEvent<'mc>( +pub struct StriderTemperatureChangeEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EntityDeathEvent<'mc> { +impl<'mc> JNIRaw<'mc> for StriderTemperatureChangeEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6481,20 +7671,24 @@ impl<'mc> JNIRaw<'mc> for EntityDeathEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EntityDeathEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for StriderTemperatureChangeEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate EntityDeathEvent from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate StriderTemperatureChangeEvent from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/entity/EntityDeathEvent")?; + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/event/entity/StriderTemperatureChangeEvent", + )?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityDeathEvent object, got {}", + "Invalid argument passed. Expected a StriderTemperatureChangeEvent object, got {}", name ) .into()) @@ -6504,122 +7698,73 @@ impl<'mc> JNIInstantiatable<'mc> for EntityDeathEvent<'mc> { } } -impl<'mc> EntityDeathEvent<'mc> { +impl<'mc> StriderTemperatureChangeEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - what: impl Into>, - damage_source: impl Into>, - drops: Vec>, - dropped_exp: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/LivingEntity;"; + what: impl Into>, + shivering: bool, + ) -> Result, Box> + { + let sig = String::from("(Lorg/bukkit/entity/Strider;Z)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(what.into().jni_object().clone()) }); - args.push(val_1); - sig += "Lorg/bukkit/damage/DamageSource;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(damage_source.into().jni_object().clone()) - }); - args.push(val_2); - sig += "Ljava/util/List;"; - let raw_val_3 = jni.new_object("java/util/ArrayList", "()V", vec![])?; - for v in drops { - sig += "Ljava/lang/java/lang/Object;"; - let map_val_0 = jni::objects::JValueGen::Object(v); - jni.call_method( - &raw_val_3, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_3 = jni::objects::JValueGen::Object(raw_val_3); - args.push(val_3); - if let Some(a) = dropped_exp { - sig += "I"; - let val_4 = jni::objects::JValueGen::Int(a); - args.push(val_4); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/event/entity/EntityDeathEvent"); + let val_2 = jni::objects::JValueGen::Bool(shivering.into()); + let cls = jni.find_class("org/bukkit/event/entity/StriderTemperatureChangeEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); let res = jni.translate_error_no_gen(res)?; - crate::event::entity::EntityDeathEvent::from_raw(&jni, res) + crate::event::entity::StriderTemperatureChangeEvent::from_raw(&jni, res) } - pub fn entity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); + pub fn entity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Strider;"); let res = self .jni_ref() .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::LivingEntity::from_raw(&self.jni_ref(), unsafe { + crate::entity::Strider::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the source of damage which caused the death. - pub fn damage_source( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/damage/DamageSource;"); + /// Get the Strider's new shivering state. + pub fn is_shivering(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDamageSource", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isShivering", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::damage::DamageSource::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Gets how much EXP should be dropped from this death. - /// - /// This does not indicate how much EXP should be taken from the entity in - /// question, merely how much should be created after its death. - pub fn dropped_exp(&self) -> Result> { - let sig = String::from("()I"); + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDroppedExp", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets how much EXP should be dropped from this death. - /// - /// This does not indicate how much EXP should be taken from the entity in - /// question, merely how much should be created after its death. - pub fn set_dropped_exp(&self, exp: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(exp); + + pub fn set_cancelled(&self, cancelled: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancelled.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setDroppedExp", + "setCancelled", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets all the items which will drop when the entity dies - pub fn drops( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getDrops", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::inventory::ItemStack::from_raw(&self.0, obj)?); - } - Ok(new_vec) - } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -6636,14 +7781,14 @@ impl<'mc> EntityDeathEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/entity/EntityDeathEvent"); + let cls = jni.find_class("org/bukkit/event/entity/StriderTemperatureChangeEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['getEntity', 'getDamageSource', 'getDroppedExp', 'setDroppedExp', 'getDrops', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['getEntity', 'isShivering', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) /// Gets the EntityType of the Entity involved in this event. pub fn entity_type( &self, @@ -6660,19 +7805,26 @@ impl<'mc> EntityDeathEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for EntityDeathEvent<'mc> { +impl<'mc> Into> for StriderTemperatureChangeEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting StriderTemperatureChangeEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for StriderTemperatureChangeEvent<'mc> { fn into(self) -> crate::event::entity::EntityEvent<'mc> { - crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EntityDeathEvent into crate::event::entity::EntityEvent") + crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting StriderTemperatureChangeEvent into crate::event::entity::EntityEvent", + ) } } #[repr(C)] -pub struct EntityToggleGlideEvent<'mc>( +pub struct EntityRemoveEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EntityToggleGlideEvent<'mc> { +impl<'mc> JNIRaw<'mc> for EntityRemoveEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6680,22 +7832,20 @@ impl<'mc> JNIRaw<'mc> for EntityToggleGlideEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EntityToggleGlideEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EntityRemoveEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate EntityToggleGlideEvent from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate EntityRemoveEvent from null object.").into(), + ); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/entity/EntityToggleGlideEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/entity/EntityRemoveEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityToggleGlideEvent object, got {}", + "Invalid argument passed. Expected a EntityRemoveEvent object, got {}", name ) .into()) @@ -6705,18 +7855,22 @@ impl<'mc> JNIInstantiatable<'mc> for EntityToggleGlideEvent<'mc> { } } -impl<'mc> EntityToggleGlideEvent<'mc> { +impl<'mc> EntityRemoveEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - who: impl Into>, - is_gliding: bool, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/LivingEntity;Z)V"); + what: impl Into>, + cause: impl Into>, + ) -> Result, Box> { + let sig = String::from( + "(Lorg/bukkit/entity/Entity;Lorg/bukkit/event/entity/EntityRemoveEvent/Cause;)V", + ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(who.into().jni_object().clone()) + jni::objects::JObject::from_raw(what.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Bool(is_gliding.into()); - let cls = jni.find_class("org/bukkit/event/entity/EntityToggleGlideEvent"); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(cause.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/entity/EntityRemoveEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -6727,39 +7881,20 @@ impl<'mc> EntityToggleGlideEvent<'mc> { ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::entity::EntityToggleGlideEvent::from_raw(&jni, res) - } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::event::entity::EntityRemoveEvent::from_raw(&jni, res) } - /// Returns true if the entity is now gliding or - /// false if the entity stops gliding. - pub fn is_gliding(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the cause why the entity got removed. + pub fn cause( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/entity/EntityRemoveEvent/Cause;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isGliding", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCause", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::event::entity::EntityRemoveEventCause::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn handlers(&self) -> Result, Box> { @@ -6773,35 +7908,363 @@ impl<'mc> EntityToggleGlideEvent<'mc> { }) } - pub fn handler_list( + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/entity/EntityRemoveEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['getCause', 'getHandlers', 'getHandlerList']) + /// Returns the Entity involved in this event + pub fn entity(&self) -> Result, Box> { + let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityEvent = temp_clone.into(); + real.entity() + } + /// Gets the EntityType of the Entity involved in this event. + pub fn entity_type( + &self, + ) -> Result, Box> { + let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityEvent = temp_clone.into(); + real.entity_type() + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for EntityRemoveEvent<'mc> { + fn into(self) -> crate::event::entity::EntityEvent<'mc> { + crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EntityRemoveEvent into crate::event::entity::EntityEvent") + } +} +pub enum EntityRemoveEventCause<'mc> { + Death { + inner: EntityRemoveEventCauseStruct<'mc>, + }, + Despawn { + inner: EntityRemoveEventCauseStruct<'mc>, + }, + Drop { + inner: EntityRemoveEventCauseStruct<'mc>, + }, + EnterBlock { + inner: EntityRemoveEventCauseStruct<'mc>, + }, + Explode { + inner: EntityRemoveEventCauseStruct<'mc>, + }, + Hit { + inner: EntityRemoveEventCauseStruct<'mc>, + }, + Merge { + inner: EntityRemoveEventCauseStruct<'mc>, + }, + OutOfWorld { + inner: EntityRemoveEventCauseStruct<'mc>, + }, + Pickup { + inner: EntityRemoveEventCauseStruct<'mc>, + }, + PlayerQuit { + inner: EntityRemoveEventCauseStruct<'mc>, + }, + Plugin { + inner: EntityRemoveEventCauseStruct<'mc>, + }, + Transformation { + inner: EntityRemoveEventCauseStruct<'mc>, + }, + Unload { + inner: EntityRemoveEventCauseStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for EntityRemoveEventCause<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + EntityRemoveEventCause::Death { .. } => f.write_str("DEATH"), + EntityRemoveEventCause::Despawn { .. } => f.write_str("DESPAWN"), + EntityRemoveEventCause::Drop { .. } => f.write_str("DROP"), + EntityRemoveEventCause::EnterBlock { .. } => f.write_str("ENTER_BLOCK"), + EntityRemoveEventCause::Explode { .. } => f.write_str("EXPLODE"), + EntityRemoveEventCause::Hit { .. } => f.write_str("HIT"), + EntityRemoveEventCause::Merge { .. } => f.write_str("MERGE"), + EntityRemoveEventCause::OutOfWorld { .. } => f.write_str("OUT_OF_WORLD"), + EntityRemoveEventCause::Pickup { .. } => f.write_str("PICKUP"), + EntityRemoveEventCause::PlayerQuit { .. } => f.write_str("PLAYER_QUIT"), + EntityRemoveEventCause::Plugin { .. } => f.write_str("PLUGIN"), + EntityRemoveEventCause::Transformation { .. } => f.write_str("TRANSFORMATION"), + EntityRemoveEventCause::Unload { .. } => f.write_str("UNLOAD"), + } + } +} +impl<'mc> std::ops::Deref for EntityRemoveEventCause<'mc> { + type Target = EntityRemoveEventCauseStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + EntityRemoveEventCause::Death { inner } => inner, + EntityRemoveEventCause::Despawn { inner } => inner, + EntityRemoveEventCause::Drop { inner } => inner, + EntityRemoveEventCause::EnterBlock { inner } => inner, + EntityRemoveEventCause::Explode { inner } => inner, + EntityRemoveEventCause::Hit { inner } => inner, + EntityRemoveEventCause::Merge { inner } => inner, + EntityRemoveEventCause::OutOfWorld { inner } => inner, + EntityRemoveEventCause::Pickup { inner } => inner, + EntityRemoveEventCause::PlayerQuit { inner } => inner, + EntityRemoveEventCause::Plugin { inner } => inner, + EntityRemoveEventCause::Transformation { inner } => inner, + EntityRemoveEventCause::Unload { inner } => inner, + } + } +} + +impl<'mc> EntityRemoveEventCause<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/event/entity/EntityRemoveEvent/Cause"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/event/entity/EntityRemoveEvent/Cause;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "DEATH" => Ok(EntityRemoveEventCause::Death { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + "DESPAWN" => Ok(EntityRemoveEventCause::Despawn { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + "DROP" => Ok(EntityRemoveEventCause::Drop { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + "ENTER_BLOCK" => Ok(EntityRemoveEventCause::EnterBlock { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + "EXPLODE" => Ok(EntityRemoveEventCause::Explode { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + "HIT" => Ok(EntityRemoveEventCause::Hit { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + "MERGE" => Ok(EntityRemoveEventCause::Merge { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + "OUT_OF_WORLD" => Ok(EntityRemoveEventCause::OutOfWorld { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + "PICKUP" => Ok(EntityRemoveEventCause::Pickup { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + "PLAYER_QUIT" => Ok(EntityRemoveEventCause::PlayerQuit { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + "PLUGIN" => Ok(EntityRemoveEventCause::Plugin { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + "TRANSFORMATION" => Ok(EntityRemoveEventCause::Transformation { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + "UNLOAD" => Ok(EntityRemoveEventCause::Unload { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct EntityRemoveEventCauseStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for EntityRemoveEventCause<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Death { inner } => inner.0.clone(), + Self::Despawn { inner } => inner.0.clone(), + Self::Drop { inner } => inner.0.clone(), + Self::EnterBlock { inner } => inner.0.clone(), + Self::Explode { inner } => inner.0.clone(), + Self::Hit { inner } => inner.0.clone(), + Self::Merge { inner } => inner.0.clone(), + Self::OutOfWorld { inner } => inner.0.clone(), + Self::Pickup { inner } => inner.0.clone(), + Self::PlayerQuit { inner } => inner.0.clone(), + Self::Plugin { inner } => inner.0.clone(), + Self::Transformation { inner } => inner.0.clone(), + Self::Unload { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Death { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Despawn { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Drop { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::EnterBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Explode { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Hit { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Merge { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::OutOfWorld { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Pickup { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PlayerQuit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Plugin { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Transformation { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Unload { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for EntityRemoveEventCause<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate EntityRemoveEventCause from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/entity/EntityRemoveEvent/Cause")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EntityRemoveEventCause object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "DEATH" => Ok(EntityRemoveEventCause::Death { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + "DESPAWN" => Ok(EntityRemoveEventCause::Despawn { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + "DROP" => Ok(EntityRemoveEventCause::Drop { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + "ENTER_BLOCK" => Ok(EntityRemoveEventCause::EnterBlock { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + "EXPLODE" => Ok(EntityRemoveEventCause::Explode { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + "HIT" => Ok(EntityRemoveEventCause::Hit { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + "MERGE" => Ok(EntityRemoveEventCause::Merge { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + "OUT_OF_WORLD" => Ok(EntityRemoveEventCause::OutOfWorld { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + "PICKUP" => Ok(EntityRemoveEventCause::Pickup { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + "PLAYER_QUIT" => Ok(EntityRemoveEventCause::PlayerQuit { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + "PLUGIN" => Ok(EntityRemoveEventCause::Plugin { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + "TRANSFORMATION" => Ok(EntityRemoveEventCause::Transformation { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + "UNLOAD" => Ok(EntityRemoveEventCause::Unload { + inner: EntityRemoveEventCauseStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for EntityRemoveEventCauseStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for EntityRemoveEventCauseStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate EntityRemoveEventCauseStruct from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/entity/EntityRemoveEvent/Cause")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EntityRemoveEventCauseStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> EntityRemoveEventCauseStruct<'mc> { + pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/entity/EntityToggleGlideEvent"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/entity/EntityRemoveEvent/Cause;"); + let cls = jni.find_class("org/bukkit/event/entity/EntityRemoveEvent/Cause"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['isCancelled', 'setCancelled', 'isGliding', 'getHandlers', 'getHandlerList']) - /// Returns the Entity involved in this event - pub fn entity(&self) -> Result, Box> { - let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityEvent = temp_clone.into(); - real.entity() - } - /// Gets the EntityType of the Entity involved in this event. - pub fn entity_type( - &self, - ) -> Result, Box> { - let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityEvent = temp_clone.into(); - real.entity_type() + crate::event::entity::EntityRemoveEventCause::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -6809,26 +8272,13 @@ impl<'mc> EntityToggleGlideEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for EntityToggleGlideEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EntityToggleGlideEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for EntityToggleGlideEvent<'mc> { - fn into(self) -> crate::event::entity::EntityEvent<'mc> { - crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting EntityToggleGlideEvent into crate::event::entity::EntityEvent", - ) - } -} #[repr(C)] -pub struct StriderTemperatureChangeEvent<'mc>( +pub struct EntityPoseChangeEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for StriderTemperatureChangeEvent<'mc> { +impl<'mc> JNIRaw<'mc> for EntityPoseChangeEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6836,24 +8286,22 @@ impl<'mc> JNIRaw<'mc> for StriderTemperatureChangeEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for StriderTemperatureChangeEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EntityPoseChangeEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate StriderTemperatureChangeEvent from null object." + "Tried to instantiate EntityPoseChangeEvent from null object." ) .into()); } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/event/entity/StriderTemperatureChangeEvent", - )?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/entity/EntityPoseChangeEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a StriderTemperatureChangeEvent object, got {}", + "Invalid argument passed. Expected a EntityPoseChangeEvent object, got {}", name ) .into()) @@ -6863,19 +8311,20 @@ impl<'mc> JNIInstantiatable<'mc> for StriderTemperatureChangeEvent<'mc> { } } -impl<'mc> StriderTemperatureChangeEvent<'mc> { +impl<'mc> EntityPoseChangeEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - what: impl Into>, - shivering: bool, - ) -> Result, Box> - { - let sig = String::from("(Lorg/bukkit/entity/Strider;Z)V"); + who: impl Into>, + pose: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;Lorg/bukkit/entity/Pose;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(what.into().jni_object().clone()) + jni::objects::JObject::from_raw(who.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Bool(shivering.into()); - let cls = jni.find_class("org/bukkit/event/entity/StriderTemperatureChangeEvent"); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(pose.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/entity/EntityPoseChangeEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -6886,50 +8335,19 @@ impl<'mc> StriderTemperatureChangeEvent<'mc> { ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::entity::StriderTemperatureChangeEvent::from_raw(&jni, res) + crate::event::entity::EntityPoseChangeEvent::from_raw(&jni, res) } - - pub fn entity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Strider;"); + /// Gets the entity's new pose. + pub fn pose(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Pose;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Strider::from_raw(&self.jni_ref(), unsafe { + crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the Strider's new shivering state. - pub fn is_shivering(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isShivering", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_cancelled(&self, cancelled: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancelled.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -6946,14 +8364,22 @@ impl<'mc> StriderTemperatureChangeEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/entity/StriderTemperatureChangeEvent"); + let cls = jni.find_class("org/bukkit/event/entity/EntityPoseChangeEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['getEntity', 'isShivering', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['getPose', 'getHandlers', 'getHandlerList']) + /// Returns the Entity involved in this event + pub fn entity(&self) -> Result, Box> { + let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityEvent = temp_clone.into(); + real.entity() + } /// Gets the EntityType of the Entity involved in this event. pub fn entity_type( &self, @@ -6970,26 +8396,19 @@ impl<'mc> StriderTemperatureChangeEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for StriderTemperatureChangeEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting StriderTemperatureChangeEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for StriderTemperatureChangeEvent<'mc> { +impl<'mc> Into> for EntityPoseChangeEvent<'mc> { fn into(self) -> crate::event::entity::EntityEvent<'mc> { - crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting StriderTemperatureChangeEvent into crate::event::entity::EntityEvent", - ) + crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EntityPoseChangeEvent into crate::event::entity::EntityEvent") } } #[repr(C)] -pub struct EntityRemoveEvent<'mc>( +pub struct LingeringPotionSplashEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EntityRemoveEvent<'mc> { +impl<'mc> JNIRaw<'mc> for LingeringPotionSplashEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6997,20 +8416,22 @@ impl<'mc> JNIRaw<'mc> for EntityRemoveEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EntityRemoveEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for LingeringPotionSplashEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate EntityRemoveEvent from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate LingeringPotionSplashEvent from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/entity/EntityRemoveEvent")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/entity/LingeringPotionSplashEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityRemoveEvent object, got {}", + "Invalid argument passed. Expected a LingeringPotionSplashEvent object, got {}", name ) .into()) @@ -7020,48 +8441,106 @@ impl<'mc> JNIInstantiatable<'mc> for EntityRemoveEvent<'mc> { } } -impl<'mc> EntityRemoveEvent<'mc> { +impl<'mc> LingeringPotionSplashEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - what: impl Into>, - cause: impl Into>, - ) -> Result, Box> { - let sig = String::from( - "(Lorg/bukkit/entity/Entity;Lorg/bukkit/event/entity/EntityRemoveEvent/Cause;)V", - ); + potion: impl Into>, + hit_entity: impl Into>, + hit_block: std::option::Option>>, + hit_face: std::option::Option>>, + entity: std::option::Option>>, + ) -> Result, Box> + { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/ThrownPotion;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(what.into().jni_object().clone()) + jni::objects::JObject::from_raw(potion.into().jni_object().clone()) }); + args.push(val_1); + sig += "Lorg/bukkit/entity/Entity;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(cause.into().jni_object().clone()) + jni::objects::JObject::from_raw(hit_entity.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/entity/EntityRemoveEvent"); + args.push(val_2); + if let Some(a) = hit_block { + sig += "Lorg/bukkit/block/Block;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_3); + } + if let Some(a) = hit_face { + sig += "Lorg/bukkit/block/BlockFace;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_4); + } + if let Some(a) = entity { + sig += "Lorg/bukkit/entity/AreaEffectCloud;"; + let val_5 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_5); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/entity/LingeringPotionSplashEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::entity::EntityRemoveEvent::from_raw(&jni, res) + crate::event::entity::LingeringPotionSplashEvent::from_raw(&jni, res) } - /// Gets the cause why the entity got removed. - pub fn cause( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/entity/EntityRemoveEvent/Cause;"); + + pub fn entity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/ThrownPotion;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getCause", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::event::entity::EntityRemoveEventCause::from_raw(&self.jni_ref(), unsafe { + crate::entity::ThrownPotion::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the AreaEffectCloud spawned + pub fn area_effect_cloud( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/AreaEffectCloud;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAreaEffectCloud", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::entity::AreaEffectCloud::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); let res = @@ -7077,31 +8556,44 @@ impl<'mc> EntityRemoveEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/entity/EntityRemoveEvent"); + let cls = jni.find_class("org/bukkit/event/entity/LingeringPotionSplashEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['getCause', 'getHandlers', 'getHandlerList']) - /// Returns the Entity involved in this event - pub fn entity(&self) -> Result, Box> { - let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { + // SUPER CLASS: org.bukkit.event.entity.ProjectileHitEvent ( ['getEntity', 'getAreaEffectCloud', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + /// Gets the block that was hit, if it was a block that was hit. + pub fn hit_block( + &self, + ) -> Result>, Box> { + let temp_clone = crate::event::entity::ProjectileHitEvent::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::entity::EntityEvent = temp_clone.into(); - real.entity() + let real: crate::event::entity::ProjectileHitEvent = temp_clone.into(); + real.hit_block() } - /// Gets the EntityType of the Entity involved in this event. - pub fn entity_type( + /// Gets the block face that was hit, if it was a block that was hit and the + /// face was provided in the event. + pub fn hit_block_face( &self, - ) -> Result, Box> { - let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { + ) -> Result>, Box> { + let temp_clone = crate::event::entity::ProjectileHitEvent::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::entity::EntityEvent = temp_clone.into(); - real.entity_type() + let real: crate::event::entity::ProjectileHitEvent = temp_clone.into(); + real.hit_block_face() + } + /// Gets the entity that was hit, if it was an entity that was hit. + pub fn hit_entity( + &self, + ) -> Result>, Box> { + let temp_clone = crate::event::entity::ProjectileHitEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::ProjectileHitEvent = temp_clone.into(); + real.hit_entity() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -7109,138 +8601,146 @@ impl<'mc> EntityRemoveEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for EntityRemoveEvent<'mc> { - fn into(self) -> crate::event::entity::EntityEvent<'mc> { - crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EntityRemoveEvent into crate::event::entity::EntityEvent") - } -} -pub enum EntityRemoveEventCause<'mc> {} -impl<'mc> std::fmt::Display for EntityRemoveEventCause<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} +impl<'mc> Into> for LingeringPotionSplashEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting LingeringPotionSplashEvent into crate::event::Cancellable") } } - -impl<'mc> EntityRemoveEventCause<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/event/entity/EntityRemoveEvent/Cause"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/event/entity/EntityRemoveEvent/Cause;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } +impl<'mc> Into> for LingeringPotionSplashEvent<'mc> { + fn into(self) -> crate::event::entity::ProjectileHitEvent<'mc> { + crate::event::entity::ProjectileHitEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting LingeringPotionSplashEvent into crate::event::entity::ProjectileHitEvent") } } - #[repr(C)] -pub struct EntityRemoveEventCauseStruct<'mc>( +pub struct EntityCombustByEntityEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EntityRemoveEventCause<'mc> { +impl<'mc> JNIRaw<'mc> for EntityCombustByEntityEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + self.0.clone() } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EntityRemoveEventCause<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EntityCombustByEntityEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate EntityRemoveEventCause from null object." + "Tried to instantiate EntityCombustByEntityEvent from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/entity/EntityRemoveEvent/Cause")?; + env.validate_name(&obj, "org/bukkit/event/entity/EntityCombustByEntityEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityRemoveEventCause object, got {}", + "Invalid argument passed. Expected a EntityCombustByEntityEvent object, got {}", name ) .into()) } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + Ok(Self(env.clone(), obj)) } } } -impl<'mc> JNIRaw<'mc> for EntityRemoveEventCauseStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() +impl<'mc> EntityCombustByEntityEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + combuster: impl Into>, + combustee: impl Into>, + duration: f32, + ) -> Result, Box> + { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Entity;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(combuster.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Lorg/bukkit/entity/Entity;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(combustee.into().jni_object().clone()) + }); + args.push(val_2); + sig += "F"; + let val_3 = jni::objects::JValueGen::Float(duration); + args.push(val_3); + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/entity/EntityCombustByEntityEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::event::entity::EntityCombustByEntityEvent::from_raw(&jni, res) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Get the entity that caused the combustion event. + pub fn combuster(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCombuster", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> JNIInstantiatable<'mc> for EntityRemoveEventCauseStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate EntityRemoveEventCauseStruct from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/entity/EntityRemoveEvent/Cause")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityRemoveEventCauseStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + // SUPER CLASS: org.bukkit.event.entity.EntityCombustEvent ( ['getCombuster']) + + pub fn is_cancelled(&self) -> Result> { + let temp_clone = crate::event::entity::EntityCombustEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityCombustEvent = temp_clone.into(); + real.is_cancelled() + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let temp_clone = crate::event::entity::EntityCombustEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityCombustEvent = temp_clone.into(); + real.set_cancelled(cancel) + } + + pub fn duration(&self) -> Result> { + let temp_clone = crate::event::entity::EntityCombustEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityCombustEvent = temp_clone.into(); + real.duration() + } + /// The number of seconds the combustee should be alight for.This value will only ever increase the combustion time, not decrease existing combustion times. + pub fn set_duration(&self, duration: i32) -> Result<(), Box> { + let temp_clone = crate::event::entity::EntityCombustEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityCombustEvent = temp_clone.into(); + real.set_duration(duration) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> EntityRemoveEventCauseStruct<'mc> { - pub fn values( + pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/entity/EntityRemoveEvent/Cause;"); - let cls = jni.find_class("org/bukkit/event/entity/EntityRemoveEvent/Cause"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::entity::EntityRemoveEventCause::from_raw(&jni, obj) + ) -> Result, Box> { + crate::event::entity::EntityCombustEvent::handler_list(jni) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -7248,13 +8748,18 @@ impl<'mc> EntityRemoveEventCauseStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for EntityCombustByEntityEvent<'mc> { + fn into(self) -> crate::event::entity::EntityCombustEvent<'mc> { + crate::event::entity::EntityCombustEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting EntityCombustByEntityEvent into crate::event::entity::EntityCombustEvent") + } +} #[repr(C)] -pub struct EntityPoseChangeEvent<'mc>( +pub struct EntityToggleSwimEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EntityPoseChangeEvent<'mc> { +impl<'mc> JNIRaw<'mc> for EntityToggleSwimEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -7262,22 +8767,22 @@ impl<'mc> JNIRaw<'mc> for EntityPoseChangeEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EntityPoseChangeEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EntityToggleSwimEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate EntityPoseChangeEvent from null object." + "Tried to instantiate EntityToggleSwimEvent from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/entity/EntityPoseChangeEvent")?; + env.validate_name(&obj, "org/bukkit/event/entity/EntityToggleSwimEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityPoseChangeEvent object, got {}", + "Invalid argument passed. Expected a EntityToggleSwimEvent object, got {}", name ) .into()) @@ -7287,20 +8792,18 @@ impl<'mc> JNIInstantiatable<'mc> for EntityPoseChangeEvent<'mc> { } } -impl<'mc> EntityPoseChangeEvent<'mc> { +impl<'mc> EntityToggleSwimEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - who: impl Into>, - pose: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;Lorg/bukkit/entity/Pose;)V"); + who: impl Into>, + is_swimming: bool, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/LivingEntity;Z)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(who.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(pose.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/event/entity/EntityPoseChangeEvent"); + let val_2 = jni::objects::JValueGen::Bool(is_swimming.into()); + let cls = jni.find_class("org/bukkit/event/entity/EntityToggleSwimEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -7311,18 +8814,39 @@ impl<'mc> EntityPoseChangeEvent<'mc> { ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::entity::EntityPoseChangeEvent::from_raw(&jni, res) + crate::event::entity::EntityToggleSwimEvent::from_raw(&jni, res) } - /// Gets the entity's new pose. - pub fn pose(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Pose;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPose", sig.as_str(), vec![]); + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Pose::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns true if the entity is now swims or + /// false if the entity stops swimming. + pub fn is_swimming(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } pub fn handlers(&self) -> Result, Box> { @@ -7340,14 +8864,14 @@ impl<'mc> EntityPoseChangeEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/entity/EntityPoseChangeEvent"); + let cls = jni.find_class("org/bukkit/event/entity/EntityToggleSwimEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['getPose', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['isCancelled', 'setCancelled', 'isSwimming', 'getHandlers', 'getHandlerList']) /// Returns the Entity involved in this event pub fn entity(&self) -> Result, Box> { let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { @@ -7372,19 +8896,25 @@ impl<'mc> EntityPoseChangeEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for EntityPoseChangeEvent<'mc> { +impl<'mc> Into> for EntityToggleSwimEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EntityToggleSwimEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for EntityToggleSwimEvent<'mc> { fn into(self) -> crate::event::entity::EntityEvent<'mc> { crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EntityPoseChangeEvent into crate::event::entity::EntityEvent") + .expect("Error converting EntityToggleSwimEvent into crate::event::entity::EntityEvent") } } #[repr(C)] -pub struct LingeringPotionSplashEvent<'mc>( +pub struct FireworkExplodeEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for LingeringPotionSplashEvent<'mc> { +impl<'mc> JNIRaw<'mc> for FireworkExplodeEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -7392,22 +8922,21 @@ impl<'mc> JNIRaw<'mc> for LingeringPotionSplashEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for LingeringPotionSplashEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for FireworkExplodeEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate LingeringPotionSplashEvent from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate FireworkExplodeEvent from null object.").into(), + ); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/entity/LingeringPotionSplashEvent")?; + env.validate_name(&obj, "org/bukkit/event/entity/FireworkExplodeEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a LingeringPotionSplashEvent object, got {}", + "Invalid argument passed. Expected a FireworkExplodeEvent object, got {}", name ) .into()) @@ -7417,82 +8946,24 @@ impl<'mc> JNIInstantiatable<'mc> for LingeringPotionSplashEvent<'mc> { } } -impl<'mc> LingeringPotionSplashEvent<'mc> { +impl<'mc> FireworkExplodeEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - potion: impl Into>, - hit_entity: impl Into>, - hit_block: std::option::Option>>, - hit_face: std::option::Option>>, - entity: std::option::Option>>, - ) -> Result, Box> - { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/ThrownPotion;"; + what: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/Firework;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(potion.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/entity/Entity;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(hit_entity.into().jni_object().clone()) + jni::objects::JObject::from_raw(what.into().jni_object().clone()) }); - args.push(val_2); - if let Some(a) = hit_block { - sig += "Lorg/bukkit/block/Block;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_3); - } - if let Some(a) = hit_face { - sig += "Lorg/bukkit/block/BlockFace;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_4); - } - if let Some(a) = entity { - sig += "Lorg/bukkit/entity/AreaEffectCloud;"; - let val_5 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_5); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/event/entity/LingeringPotionSplashEvent"); + let cls = jni.find_class("org/bukkit/event/entity/FireworkExplodeEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::event::entity::LingeringPotionSplashEvent::from_raw(&jni, res) - } - - pub fn entity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/ThrownPotion;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::ThrownPotion::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the AreaEffectCloud spawned - pub fn area_effect_cloud( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/AreaEffectCloud;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAreaEffectCloud", + let res = jni.new_object( + cls, sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::entity::AreaEffectCloud::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let res = jni.translate_error_no_gen(res)?; + crate::event::entity::FireworkExplodeEvent::from_raw(&jni, res) } pub fn is_cancelled(&self) -> Result> { @@ -7503,7 +8974,9 @@ impl<'mc> LingeringPotionSplashEvent<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - + /// Set the cancelled state of this event. If the firework explosion is + /// cancelled, the firework will still be removed, but no particles will be + /// displayed. pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); let val_1 = jni::objects::JValueGen::Bool(cancel.into()); @@ -7517,6 +8990,17 @@ impl<'mc> LingeringPotionSplashEvent<'mc> { Ok(()) } + pub fn entity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Firework;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Firework::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); let res = @@ -7532,44 +9016,23 @@ impl<'mc> LingeringPotionSplashEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/entity/LingeringPotionSplashEvent"); + let cls = jni.find_class("org/bukkit/event/entity/FireworkExplodeEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.entity.ProjectileHitEvent ( ['getEntity', 'getAreaEffectCloud', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) - /// Gets the block that was hit, if it was a block that was hit. - pub fn hit_block( - &self, - ) -> Result>, Box> { - let temp_clone = crate::event::entity::ProjectileHitEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::ProjectileHitEvent = temp_clone.into(); - real.hit_block() - } - /// Gets the block face that was hit, if it was a block that was hit and the - /// face was provided in the event. - pub fn hit_block_face( - &self, - ) -> Result>, Box> { - let temp_clone = crate::event::entity::ProjectileHitEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::ProjectileHitEvent = temp_clone.into(); - real.hit_block_face() - } - /// Gets the entity that was hit, if it was an entity that was hit. - pub fn hit_entity( + // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['isCancelled', 'setCancelled', 'getEntity', 'getHandlers', 'getHandlerList']) + /// Gets the EntityType of the Entity involved in this event. + pub fn entity_type( &self, - ) -> Result>, Box> { - let temp_clone = crate::event::entity::ProjectileHitEvent::from_raw(&self.0, unsafe { + ) -> Result, Box> { + let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::entity::ProjectileHitEvent = temp_clone.into(); - real.hit_entity() + let real: crate::event::entity::EntityEvent = temp_clone.into(); + real.entity_type() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -7577,24 +9040,25 @@ impl<'mc> LingeringPotionSplashEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for LingeringPotionSplashEvent<'mc> { +impl<'mc> Into> for FireworkExplodeEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting LingeringPotionSplashEvent into crate::event::Cancellable") + .expect("Error converting FireworkExplodeEvent into crate::event::Cancellable") } } -impl<'mc> Into> for LingeringPotionSplashEvent<'mc> { - fn into(self) -> crate::event::entity::ProjectileHitEvent<'mc> { - crate::event::entity::ProjectileHitEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting LingeringPotionSplashEvent into crate::event::entity::ProjectileHitEvent") +impl<'mc> Into> for FireworkExplodeEvent<'mc> { + fn into(self) -> crate::event::entity::EntityEvent<'mc> { + crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting FireworkExplodeEvent into crate::event::entity::EntityEvent") } } #[repr(C)] -pub struct EntityToggleSwimEvent<'mc>( +pub struct EntityChangeBlockEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EntityToggleSwimEvent<'mc> { +impl<'mc> JNIRaw<'mc> for EntityChangeBlockEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -7602,22 +9066,22 @@ impl<'mc> JNIRaw<'mc> for EntityToggleSwimEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EntityToggleSwimEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EntityChangeBlockEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate EntityToggleSwimEvent from null object." + "Tried to instantiate EntityChangeBlockEvent from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/entity/EntityToggleSwimEvent")?; + env.validate_name(&obj, "org/bukkit/event/entity/EntityChangeBlockEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityToggleSwimEvent object, got {}", + "Invalid argument passed. Expected a EntityChangeBlockEvent object, got {}", name ) .into()) @@ -7627,18 +9091,24 @@ impl<'mc> JNIInstantiatable<'mc> for EntityToggleSwimEvent<'mc> { } } -impl<'mc> EntityToggleSwimEvent<'mc> { +impl<'mc> EntityChangeBlockEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - who: impl Into>, - is_swimming: bool, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/LivingEntity;Z)V"); + what: impl Into>, + block: impl Into>, + to: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;Lorg/bukkit/block/Block;Lorg/bukkit/block/data/BlockData;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(who.into().jni_object().clone()) + jni::objects::JObject::from_raw(what.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Bool(is_swimming.into()); - let cls = jni.find_class("org/bukkit/event/entity/EntityToggleSwimEvent"); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(block.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(to.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/entity/EntityChangeBlockEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -7646,10 +9116,22 @@ impl<'mc> EntityToggleSwimEvent<'mc> { vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::entity::EntityToggleSwimEvent::from_raw(&jni, res) + crate::event::entity::EntityChangeBlockEvent::from_raw(&jni, res) + } + /// Gets the block the entity is changing + pub fn block(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn is_cancelled(&self) -> Result> { @@ -7673,15 +9155,29 @@ impl<'mc> EntityToggleSwimEvent<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns true if the entity is now swims or - /// false if the entity stops swimming. - pub fn is_swimming(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the Material that the block is changing into + pub fn to(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTo", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the data for the block that would be changed into + pub fn block_data( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isSwimming", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBlockData", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn handlers(&self) -> Result, Box> { @@ -7699,14 +9195,14 @@ impl<'mc> EntityToggleSwimEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/entity/EntityToggleSwimEvent"); + let cls = jni.find_class("org/bukkit/event/entity/EntityChangeBlockEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['isCancelled', 'setCancelled', 'isSwimming', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['getBlock', 'isCancelled', 'setCancelled', 'getTo', 'getBlockData', 'getHandlers', 'getHandlerList']) /// Returns the Entity involved in this event pub fn entity(&self) -> Result, Box> { let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { @@ -7731,25 +9227,26 @@ impl<'mc> EntityToggleSwimEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for EntityToggleSwimEvent<'mc> { +impl<'mc> Into> for EntityChangeBlockEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EntityToggleSwimEvent into crate::event::Cancellable") + .expect("Error converting EntityChangeBlockEvent into crate::event::Cancellable") } } -impl<'mc> Into> for EntityToggleSwimEvent<'mc> { +impl<'mc> Into> for EntityChangeBlockEvent<'mc> { fn into(self) -> crate::event::entity::EntityEvent<'mc> { - crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EntityToggleSwimEvent into crate::event::entity::EntityEvent") + crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting EntityChangeBlockEvent into crate::event::entity::EntityEvent", + ) } } #[repr(C)] -pub struct FireworkExplodeEvent<'mc>( +pub struct EntityDamageByEntityEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for FireworkExplodeEvent<'mc> { +impl<'mc> JNIRaw<'mc> for EntityDamageByEntityEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -7757,21 +9254,22 @@ impl<'mc> JNIRaw<'mc> for FireworkExplodeEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for FireworkExplodeEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EntityDamageByEntityEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate FireworkExplodeEvent from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate EntityDamageByEntityEvent from null object." + ) + .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/entity/FireworkExplodeEvent")?; + env.validate_name(&obj, "org/bukkit/event/entity/EntityDamageByEntityEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a FireworkExplodeEvent object, got {}", + "Invalid argument passed. Expected a EntityDamageByEntityEvent object, got {}", name ) .into()) @@ -7781,59 +9279,172 @@ impl<'mc> JNIInstantiatable<'mc> for FireworkExplodeEvent<'mc> { } } -impl<'mc> FireworkExplodeEvent<'mc> { +impl<'mc> EntityDamageByEntityEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - what: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Firework;)V"); + damager: impl Into>, + damagee: impl Into>, + cause: impl Into>, + damage_source: impl Into>, + modifiers: std::option::Option>>, + modifier_functions: std::option::Option>>, + ) -> Result, Box> + { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Entity;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(what.into().jni_object().clone()) + jni::objects::JObject::from_raw(damager.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/entity/FireworkExplodeEvent"); + args.push(val_1); + sig += "Lorg/bukkit/entity/Entity;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(damagee.into().jni_object().clone()) + }); + args.push(val_2); + sig += "Lorg/bukkit/event/entity/EntityDamageEvent/DamageCause;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(cause.into().jni_object().clone()) + }); + args.push(val_3); + sig += "Lorg/bukkit/damage/DamageSource;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(damage_source.into().jni_object().clone()) + }); + args.push(val_4); + if let Some(a) = modifiers { + sig += "Ljava/util/Map;"; + let val_5 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_5); + } + if let Some(a) = modifier_functions { + sig += "Ljava/util/Map;"; + let val_6 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_6); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/entity/EntityDamageByEntityEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::entity::FireworkExplodeEvent::from_raw(&jni, res) + crate::event::entity::EntityDamageByEntityEvent::from_raw(&jni, res) } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); + /// Returns the entity that damaged the defender. + pub fn damager(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDamager", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + // SUPER CLASS: org.bukkit.event.entity.EntityDamageEvent ( ['getDamager']) + + pub fn is_cancelled(&self) -> Result> { + let temp_clone = crate::event::entity::EntityDamageEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityDamageEvent = temp_clone.into(); + real.is_cancelled() + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let temp_clone = crate::event::entity::EntityDamageEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityDamageEvent = temp_clone.into(); + real.set_cancelled(cancel) + } + /// Gets the original damage for the specified modifier, as defined at this + /// event's construction. + pub fn get_original_damage( + &self, + val_type: impl Into>, + ) -> Result> { + let temp_clone = crate::event::entity::EntityDamageEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityDamageEvent = temp_clone.into(); + real.get_original_damage(val_type) + } + /// Sets the damage for the specified modifier. + pub fn set_damage( + &self, + val_type: impl Into>, + damage: std::option::Option, + ) -> Result<(), Box> { + let temp_clone = crate::event::entity::EntityDamageEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityDamageEvent = temp_clone.into(); + real.set_damage(val_type, damage) + } + /// Gets the raw amount of damage caused by the event + pub fn damage(&self) -> Result> { + let temp_clone = crate::event::entity::EntityDamageEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityDamageEvent = temp_clone.into(); + real.damage() + } + /// This checks to see if a particular modifier is valid for this event's + /// caller, such that, {@link #setDamage(DamageModifier, double)} will not + /// throw an {@link UnsupportedOperationException}. + /// + /// {@link DamageModifier#BASE} is always applicable. + pub fn is_applicable( + &self, + val_type: impl Into>, + ) -> Result> { + let temp_clone = crate::event::entity::EntityDamageEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityDamageEvent = temp_clone.into(); + real.is_applicable(val_type) + } + /// Gets the amount of damage caused by the event after all damage + /// reduction is applied. + pub fn final_damage(&self) -> Result> { + let temp_clone = crate::event::entity::EntityDamageEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityDamageEvent = temp_clone.into(); + real.final_damage() } - /// Set the cancelled state of this event. If the firework explosion is - /// cancelled, the firework will still be removed, but no particles will be - /// displayed. - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Gets the cause of the damage. + /// + /// While a DamageCause may indicate a specific Bukkit-assigned cause of damage, + /// {@link #getDamageSource()} may expose additional types of damage such as custom + /// damage types provided by data packs, as well as any direct or indirect entities, + /// locations, or other contributing factors to the damage being inflicted. The + /// alternative is generally preferred, but DamageCauses provided to this event + /// should largely encompass most common use cases for developers if a simple cause + /// is required. + pub fn cause( + &self, + ) -> Result, Box> + { + let temp_clone = crate::event::entity::EntityDamageEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityDamageEvent = temp_clone.into(); + real.cause() } - - pub fn entity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Firework;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Firework::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Get the source of damage. + pub fn damage_source( + &self, + ) -> Result, Box> { + let temp_clone = crate::event::entity::EntityDamageEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityDamageEvent = temp_clone.into(); + real.damage_source() } pub fn handlers(&self) -> Result, Box> { @@ -7850,24 +9461,7 @@ impl<'mc> FireworkExplodeEvent<'mc> { pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/entity/FireworkExplodeEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['isCancelled', 'setCancelled', 'getEntity', 'getHandlers', 'getHandlerList']) - /// Gets the EntityType of the Entity involved in this event. - pub fn entity_type( - &self, - ) -> Result, Box> { - let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityEvent = temp_clone.into(); - real.entity_type() + crate::event::entity::EntityDamageEvent::handler_list(jni) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -7875,25 +9469,18 @@ impl<'mc> FireworkExplodeEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for FireworkExplodeEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting FireworkExplodeEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for FireworkExplodeEvent<'mc> { - fn into(self) -> crate::event::entity::EntityEvent<'mc> { - crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting FireworkExplodeEvent into crate::event::entity::EntityEvent") +impl<'mc> Into> for EntityDamageByEntityEvent<'mc> { + fn into(self) -> crate::event::entity::EntityDamageEvent<'mc> { + crate::event::entity::EntityDamageEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting EntityDamageByEntityEvent into crate::event::entity::EntityDamageEvent") } } #[repr(C)] -pub struct EntityChangeBlockEvent<'mc>( +pub struct EntityBreedEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EntityChangeBlockEvent<'mc> { +impl<'mc> JNIRaw<'mc> for EntityBreedEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -7901,22 +9488,20 @@ impl<'mc> JNIRaw<'mc> for EntityChangeBlockEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EntityChangeBlockEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EntityBreedEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate EntityChangeBlockEvent from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate EntityBreedEvent from null object.").into(), + ); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/entity/EntityChangeBlockEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/entity/EntityBreedEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityChangeBlockEvent object, got {}", + "Invalid argument passed. Expected a EntityBreedEvent object, got {}", name ) .into()) @@ -7926,24 +9511,34 @@ impl<'mc> JNIInstantiatable<'mc> for EntityChangeBlockEvent<'mc> { } } -impl<'mc> EntityChangeBlockEvent<'mc> { +impl<'mc> EntityBreedEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - what: impl Into>, - block: impl Into>, - to: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;Lorg/bukkit/block/Block;Lorg/bukkit/block/data/BlockData;)V"); + child: impl Into>, + mother: impl Into>, + father: impl Into>, + breeder: impl Into>, + bred_with: impl Into>, + experience: i32, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/LivingEntity;Lorg/bukkit/entity/LivingEntity;Lorg/bukkit/entity/LivingEntity;Lorg/bukkit/entity/LivingEntity;Lorg/bukkit/inventory/ItemStack;I)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(what.into().jni_object().clone()) + jni::objects::JObject::from_raw(child.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) + jni::objects::JObject::from_raw(mother.into().jni_object().clone()) }); let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(to.into().jni_object().clone()) + jni::objects::JObject::from_raw(father.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/entity/EntityChangeBlockEvent"); + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(breeder.into().jni_object().clone()) + }); + let val_5 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(bred_with.into().jni_object().clone()) + }); + let val_6 = jni::objects::JValueGen::Int(experience); + let cls = jni.find_class("org/bukkit/event/entity/EntityBreedEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -7952,22 +9547,104 @@ impl<'mc> EntityChangeBlockEvent<'mc> { jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + jni::objects::JValueGen::from(val_5), + jni::objects::JValueGen::from(val_6), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::entity::EntityChangeBlockEvent::from_raw(&jni, res) + crate::event::entity::EntityBreedEvent::from_raw(&jni, res) } - /// Gets the block the entity is changing - pub fn block(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); + + pub fn entity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { + crate::entity::LivingEntity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the parent creating this entity. + pub fn mother(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getMother", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::LivingEntity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the other parent of the newly born entity. + pub fn father(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFather", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::LivingEntity::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } + /// Gets the Entity responsible for breeding. Breeder is null for spontaneous + /// conception. + pub fn breeder( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBreeder", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::LivingEntity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// The ItemStack that was used to initiate breeding, if present. + pub fn bred_with( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBredWith", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Get the amount of experience granted by breeding. + pub fn experience(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getExperience", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the amount of experience granted by breeding. + pub fn set_experience(&self, experience: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(experience); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setExperience", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } pub fn is_cancelled(&self) -> Result> { let sig = String::from("()Z"); @@ -7990,30 +9667,6 @@ impl<'mc> EntityChangeBlockEvent<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the Material that the block is changing into - pub fn to(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTo", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the data for the block that would be changed into - pub fn block_data( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/data/BlockData;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBlockData", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -8030,22 +9683,14 @@ impl<'mc> EntityChangeBlockEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/entity/EntityChangeBlockEvent"); + let cls = jni.find_class("org/bukkit/event/entity/EntityBreedEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['getBlock', 'isCancelled', 'setCancelled', 'getTo', 'getBlockData', 'getHandlers', 'getHandlerList']) - /// Returns the Entity involved in this event - pub fn entity(&self) -> Result, Box> { - let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityEvent = temp_clone.into(); - real.entity() - } + // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['getEntity', 'getMother', 'getFather', 'getBreeder', 'getBredWith', 'getExperience', 'setExperience', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) /// Gets the EntityType of the Entity involved in this event. pub fn entity_type( &self, @@ -8062,26 +9707,25 @@ impl<'mc> EntityChangeBlockEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for EntityChangeBlockEvent<'mc> { +impl<'mc> Into> for EntityBreedEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EntityChangeBlockEvent into crate::event::Cancellable") + .expect("Error converting EntityBreedEvent into crate::event::Cancellable") } } -impl<'mc> Into> for EntityChangeBlockEvent<'mc> { +impl<'mc> Into> for EntityBreedEvent<'mc> { fn into(self) -> crate::event::entity::EntityEvent<'mc> { - crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting EntityChangeBlockEvent into crate::event::entity::EntityEvent", - ) + crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EntityBreedEvent into crate::event::entity::EntityEvent") } } #[repr(C)] -pub struct EntityDamageByEntityEvent<'mc>( +pub struct AreaEffectCloudApplyEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EntityDamageByEntityEvent<'mc> { +impl<'mc> JNIRaw<'mc> for AreaEffectCloudApplyEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -8089,22 +9733,22 @@ impl<'mc> JNIRaw<'mc> for EntityDamageByEntityEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EntityDamageByEntityEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for AreaEffectCloudApplyEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate EntityDamageByEntityEvent from null object." + "Tried to instantiate AreaEffectCloudApplyEvent from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/entity/EntityDamageByEntityEvent")?; + env.validate_name(&obj, "org/bukkit/event/entity/AreaEffectCloudApplyEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityDamageByEntityEvent object, got {}", + "Invalid argument passed. Expected a AreaEffectCloudApplyEvent object, got {}", name ) .into()) @@ -8114,172 +9758,101 @@ impl<'mc> JNIInstantiatable<'mc> for EntityDamageByEntityEvent<'mc> { } } -impl<'mc> EntityDamageByEntityEvent<'mc> { +impl<'mc> AreaEffectCloudApplyEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - damager: impl Into>, - damagee: impl Into>, - cause: impl Into>, - damage_source: impl Into>, - modifiers: std::option::Option>>, - modifier_functions: std::option::Option>>, - ) -> Result, Box> + entity: impl Into>, + affected_entities: Vec>, + ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Entity;"; + let sig = String::from("(Lorg/bukkit/entity/AreaEffectCloud;Ljava/util/List;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(damager.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/entity/Entity;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(damagee.into().jni_object().clone()) - }); - args.push(val_2); - sig += "Lorg/bukkit/event/entity/EntityDamageEvent/DamageCause;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(cause.into().jni_object().clone()) - }); - args.push(val_3); - sig += "Lorg/bukkit/damage/DamageSource;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(damage_source.into().jni_object().clone()) + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) }); - args.push(val_4); - if let Some(a) = modifiers { - sig += "Ljava/util/Map;"; - let val_5 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_5); - } - if let Some(a) = modifier_functions { - sig += "Ljava/util/Map;"; - let val_6 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_6); + let raw_val_2 = jni.new_object("java/util/ArrayList", "()V", vec![])?; + for v in affected_entities { + let map_val_0 = jni::objects::JValueGen::Object(v); + jni.call_method( + &raw_val_2, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; } - sig += ")V"; - let cls = jni.find_class("org/bukkit/event/entity/EntityDamageByEntityEvent"); + let val_2 = jni::objects::JValueGen::Object(raw_val_2); + let cls = jni.find_class("org/bukkit/event/entity/AreaEffectCloudApplyEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); let res = jni.translate_error_no_gen(res)?; - crate::event::entity::EntityDamageByEntityEvent::from_raw(&jni, res) + crate::event::entity::AreaEffectCloudApplyEvent::from_raw(&jni, res) } - /// Returns the entity that damaged the defender. - pub fn damager(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDamager", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - // SUPER CLASS: org.bukkit.event.entity.EntityDamageEvent ( ['getDamager']) - - pub fn is_cancelled(&self) -> Result> { - let temp_clone = crate::event::entity::EntityDamageEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityDamageEvent = temp_clone.into(); - real.is_cancelled() + Ok(res.z()?) } pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let temp_clone = crate::event::entity::EntityDamageEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityDamageEvent = temp_clone.into(); - real.set_cancelled(cancel) - } - /// Gets the original damage for the specified modifier, as defined at this - /// event's construction. - pub fn get_original_damage( - &self, - val_type: impl Into>, - ) -> Result> { - let temp_clone = crate::event::entity::EntityDamageEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityDamageEvent = temp_clone.into(); - real.get_original_damage(val_type) - } - /// Sets the damage for the specified modifier. - pub fn set_damage( - &self, - val_type: impl Into>, - damage: std::option::Option, - ) -> Result<(), Box> { - let temp_clone = crate::event::entity::EntityDamageEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityDamageEvent = temp_clone.into(); - real.set_damage(val_type, damage) - } - /// Gets the raw amount of damage caused by the event - pub fn damage(&self) -> Result> { - let temp_clone = crate::event::entity::EntityDamageEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityDamageEvent = temp_clone.into(); - real.damage() + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// This checks to see if a particular modifier is valid for this event's - /// caller, such that, {@link #setDamage(DamageModifier, double)} will not - /// throw an {@link UnsupportedOperationException}. - /// - /// {@link DamageModifier#BASE} is always applicable. - pub fn is_applicable( + + pub fn entity( &self, - val_type: impl Into>, - ) -> Result> { - let temp_clone = crate::event::entity::EntityDamageEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityDamageEvent = temp_clone.into(); - real.is_applicable(val_type) - } - /// Gets the amount of damage caused by the event after all damage - /// reduction is applied. - pub fn final_damage(&self) -> Result> { - let temp_clone = crate::event::entity::EntityDamageEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityDamageEvent = temp_clone.into(); - real.final_damage() + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/AreaEffectCloud;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::AreaEffectCloud::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the cause of the damage. + /// Retrieves a mutable list of the effected entities /// - /// While a DamageCause may indicate a specific Bukkit-assigned cause of damage, - /// {@link #getDamageSource()} may expose additional types of damage such as custom - /// damage types provided by data packs, as well as any direct or indirect entities, - /// locations, or other contributing factors to the damage being inflicted. The - /// alternative is generally preferred, but DamageCauses provided to this event - /// should largely encompass most common use cases for developers if a simple cause - /// is required. - pub fn cause( - &self, - ) -> Result, Box> - { - let temp_clone = crate::event::entity::EntityDamageEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityDamageEvent = temp_clone.into(); - real.cause() - } - /// Get the source of damage. - pub fn damage_source( + /// It is important to note that not every entity in this list + /// is guaranteed to be effected.The cloud may die during the + /// application of its effects due to the depletion of {@link AreaEffectCloud#getDurationOnUse()} + /// or {@link AreaEffectCloud#getRadiusOnUse()} + pub fn affected_entities( &self, - ) -> Result, Box> { - let temp_clone = crate::event::entity::EntityDamageEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityDamageEvent = temp_clone.into(); - real.damage_source() + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAffectedEntities", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::LivingEntity::from_raw(&self.0, obj)?); + } + Ok(new_vec) } pub fn handlers(&self) -> Result, Box> { @@ -8296,7 +9869,24 @@ impl<'mc> EntityDamageByEntityEvent<'mc> { pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { - crate::event::entity::EntityDamageEvent::handler_list(jni) + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/entity/AreaEffectCloudApplyEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['isCancelled', 'setCancelled', 'getEntity', 'getAffectedEntities', 'getHandlers', 'getHandlerList']) + /// Gets the EntityType of the Entity involved in this event. + pub fn entity_type( + &self, + ) -> Result, Box> { + let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntityEvent = temp_clone.into(); + real.entity_type() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -8304,18 +9894,26 @@ impl<'mc> EntityDamageByEntityEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for EntityDamageByEntityEvent<'mc> { - fn into(self) -> crate::event::entity::EntityDamageEvent<'mc> { - crate::event::entity::EntityDamageEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting EntityDamageByEntityEvent into crate::event::entity::EntityDamageEvent") +impl<'mc> Into> for AreaEffectCloudApplyEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting AreaEffectCloudApplyEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for AreaEffectCloudApplyEvent<'mc> { + fn into(self) -> crate::event::entity::EntityEvent<'mc> { + crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting AreaEffectCloudApplyEvent into crate::event::entity::EntityEvent", + ) } } #[repr(C)] -pub struct EntityBreedEvent<'mc>( +pub struct CreatureSpawnEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EntityBreedEvent<'mc> { +impl<'mc> JNIRaw<'mc> for CreatureSpawnEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -8323,20 +9921,21 @@ impl<'mc> JNIRaw<'mc> for EntityBreedEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EntityBreedEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CreatureSpawnEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate EntityBreedEvent from null object.").into(), + eyre::eyre!("Tried to instantiate CreatureSpawnEvent from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/entity/EntityBreedEvent")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/entity/CreatureSpawnEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityBreedEvent object, got {}", + "Invalid argument passed. Expected a CreatureSpawnEvent object, got {}", name ) .into()) @@ -8346,34 +9945,20 @@ impl<'mc> JNIInstantiatable<'mc> for EntityBreedEvent<'mc> { } } -impl<'mc> EntityBreedEvent<'mc> { +impl<'mc> CreatureSpawnEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - child: impl Into>, - mother: impl Into>, - father: impl Into>, - breeder: impl Into>, - bred_with: impl Into>, - experience: i32, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/LivingEntity;Lorg/bukkit/entity/LivingEntity;Lorg/bukkit/entity/LivingEntity;Lorg/bukkit/entity/LivingEntity;Lorg/bukkit/inventory/ItemStack;I)V"); + spawnee: impl Into>, + spawn_reason: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/LivingEntity;Lorg/bukkit/event/entity/CreatureSpawnEvent/SpawnReason;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(child.into().jni_object().clone()) + jni::objects::JObject::from_raw(spawnee.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(mother.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(father.into().jni_object().clone()) - }); - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(breeder.into().jni_object().clone()) - }); - let val_5 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(bred_with.into().jni_object().clone()) + jni::objects::JObject::from_raw(spawn_reason.into().jni_object().clone()) }); - let val_6 = jni::objects::JValueGen::Int(experience); - let cls = jni.find_class("org/bukkit/event/entity/EntityBreedEvent"); + let cls = jni.find_class("org/bukkit/event/entity/CreatureSpawnEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -8381,14 +9966,10 @@ impl<'mc> EntityBreedEvent<'mc> { vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - jni::objects::JValueGen::from(val_5), - jni::objects::JValueGen::from(val_6), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::entity::EntityBreedEvent::from_raw(&jni, res) + crate::event::entity::CreatureSpawnEvent::from_raw(&jni, res) } pub fn entity(&self) -> Result, Box> { @@ -8401,106 +9982,44 @@ impl<'mc> EntityBreedEvent<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the parent creating this entity. - pub fn mother(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getMother", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::LivingEntity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the other parent of the newly born entity. - pub fn father(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFather", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::LivingEntity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the Entity responsible for breeding. Breeder is null for spontaneous - /// conception. - pub fn breeder( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBreeder", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::LivingEntity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// The ItemStack that was used to initiate breeding, if present. - pub fn bred_with( + /// Gets the reason for why the creature is being spawned. + pub fn spawn_reason( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBredWith", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Get the amount of experience granted by breeding. - pub fn experience(&self) -> Result> { - let sig = String::from("()I"); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/event/entity/CreatureSpawnEvent/SpawnReason;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getExperience", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSpawnReason", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the amount of experience granted by breeding. - pub fn set_experience(&self, experience: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(experience); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setExperience", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::event::entity::CreatureSpawnEventSpawnReason::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } + // SUPER CLASS: org.bukkit.event.entity.EntitySpawnEvent ( ['getEntity', 'getSpawnReason']) pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let temp_clone = crate::event::entity::EntitySpawnEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntitySpawnEvent = temp_clone.into(); + real.is_cancelled() } pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + let temp_clone = crate::event::entity::EntitySpawnEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntitySpawnEvent = temp_clone.into(); + real.set_cancelled(cancel) + } + /// Gets the location at which the entity is spawning. + pub fn location(&self) -> Result, Box> { + let temp_clone = crate::event::entity::EntitySpawnEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::entity::EntitySpawnEvent = temp_clone.into(); + real.location() } pub fn handlers(&self) -> Result, Box> { @@ -8517,211 +10036,762 @@ impl<'mc> EntityBreedEvent<'mc> { pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/entity/EntityBreedEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) + crate::event::entity::EntitySpawnEvent::handler_list(jni) } - // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['getEntity', 'getMother', 'getFather', 'getBreeder', 'getBredWith', 'getExperience', 'setExperience', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) - /// Gets the EntityType of the Entity involved in this event. - pub fn entity_type( - &self, - ) -> Result, Box> { - let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityEvent = temp_clone.into(); - real.entity_type() + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for CreatureSpawnEvent<'mc> { + fn into(self) -> crate::event::entity::EntitySpawnEvent<'mc> { + crate::event::entity::EntitySpawnEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting CreatureSpawnEvent into crate::event::entity::EntitySpawnEvent", + ) + } +} +pub enum CreatureSpawnEventSpawnReason<'mc> { + Natural { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + Jockey { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + ChunkGen { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + Spawner { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + TrialSpawner { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + Egg { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + SpawnerEgg { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + Lightning { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + BuildSnowman { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + BuildIrongolem { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + BuildWither { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + VillageDefense { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + VillageInvasion { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + Breeding { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + SlimeSplit { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + Reinforcements { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + NetherPortal { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + DispenseEgg { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + Infection { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + Cured { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + OcelotBaby { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + SilverfishBlock { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + Mount { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + Trap { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + EnderPearl { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + ShoulderEntity { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + Drowned { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + Sheared { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + Explosion { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + Raid { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + Patrol { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + Beehive { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + PiglinZombified { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + Spell { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + Frozen { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + Metamorphosis { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + Duplication { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + Command { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + Enchantment { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + PotionEffect { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + Custom { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, + Default { + inner: CreatureSpawnEventSpawnReasonStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for CreatureSpawnEventSpawnReason<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + CreatureSpawnEventSpawnReason::Natural { .. } => f.write_str("NATURAL"), + CreatureSpawnEventSpawnReason::Jockey { .. } => f.write_str("JOCKEY"), + CreatureSpawnEventSpawnReason::ChunkGen { .. } => f.write_str("CHUNK_GEN"), + CreatureSpawnEventSpawnReason::Spawner { .. } => f.write_str("SPAWNER"), + CreatureSpawnEventSpawnReason::TrialSpawner { .. } => f.write_str("TRIAL_SPAWNER"), + CreatureSpawnEventSpawnReason::Egg { .. } => f.write_str("EGG"), + CreatureSpawnEventSpawnReason::SpawnerEgg { .. } => f.write_str("SPAWNER_EGG"), + CreatureSpawnEventSpawnReason::Lightning { .. } => f.write_str("LIGHTNING"), + CreatureSpawnEventSpawnReason::BuildSnowman { .. } => f.write_str("BUILD_SNOWMAN"), + CreatureSpawnEventSpawnReason::BuildIrongolem { .. } => f.write_str("BUILD_IRONGOLEM"), + CreatureSpawnEventSpawnReason::BuildWither { .. } => f.write_str("BUILD_WITHER"), + CreatureSpawnEventSpawnReason::VillageDefense { .. } => f.write_str("VILLAGE_DEFENSE"), + CreatureSpawnEventSpawnReason::VillageInvasion { .. } => { + f.write_str("VILLAGE_INVASION") + } + CreatureSpawnEventSpawnReason::Breeding { .. } => f.write_str("BREEDING"), + CreatureSpawnEventSpawnReason::SlimeSplit { .. } => f.write_str("SLIME_SPLIT"), + CreatureSpawnEventSpawnReason::Reinforcements { .. } => f.write_str("REINFORCEMENTS"), + CreatureSpawnEventSpawnReason::NetherPortal { .. } => f.write_str("NETHER_PORTAL"), + CreatureSpawnEventSpawnReason::DispenseEgg { .. } => f.write_str("DISPENSE_EGG"), + CreatureSpawnEventSpawnReason::Infection { .. } => f.write_str("INFECTION"), + CreatureSpawnEventSpawnReason::Cured { .. } => f.write_str("CURED"), + CreatureSpawnEventSpawnReason::OcelotBaby { .. } => f.write_str("OCELOT_BABY"), + CreatureSpawnEventSpawnReason::SilverfishBlock { .. } => { + f.write_str("SILVERFISH_BLOCK") + } + CreatureSpawnEventSpawnReason::Mount { .. } => f.write_str("MOUNT"), + CreatureSpawnEventSpawnReason::Trap { .. } => f.write_str("TRAP"), + CreatureSpawnEventSpawnReason::EnderPearl { .. } => f.write_str("ENDER_PEARL"), + CreatureSpawnEventSpawnReason::ShoulderEntity { .. } => f.write_str("SHOULDER_ENTITY"), + CreatureSpawnEventSpawnReason::Drowned { .. } => f.write_str("DROWNED"), + CreatureSpawnEventSpawnReason::Sheared { .. } => f.write_str("SHEARED"), + CreatureSpawnEventSpawnReason::Explosion { .. } => f.write_str("EXPLOSION"), + CreatureSpawnEventSpawnReason::Raid { .. } => f.write_str("RAID"), + CreatureSpawnEventSpawnReason::Patrol { .. } => f.write_str("PATROL"), + CreatureSpawnEventSpawnReason::Beehive { .. } => f.write_str("BEEHIVE"), + CreatureSpawnEventSpawnReason::PiglinZombified { .. } => { + f.write_str("PIGLIN_ZOMBIFIED") + } + CreatureSpawnEventSpawnReason::Spell { .. } => f.write_str("SPELL"), + CreatureSpawnEventSpawnReason::Frozen { .. } => f.write_str("FROZEN"), + CreatureSpawnEventSpawnReason::Metamorphosis { .. } => f.write_str("METAMORPHOSIS"), + CreatureSpawnEventSpawnReason::Duplication { .. } => f.write_str("DUPLICATION"), + CreatureSpawnEventSpawnReason::Command { .. } => f.write_str("COMMAND"), + CreatureSpawnEventSpawnReason::Enchantment { .. } => f.write_str("ENCHANTMENT"), + CreatureSpawnEventSpawnReason::PotionEffect { .. } => f.write_str("POTION_EFFECT"), + CreatureSpawnEventSpawnReason::Custom { .. } => f.write_str("CUSTOM"), + CreatureSpawnEventSpawnReason::Default { .. } => f.write_str("DEFAULT"), + } + } +} +impl<'mc> std::ops::Deref for CreatureSpawnEventSpawnReason<'mc> { + type Target = CreatureSpawnEventSpawnReasonStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + CreatureSpawnEventSpawnReason::Natural { inner } => inner, + CreatureSpawnEventSpawnReason::Jockey { inner } => inner, + CreatureSpawnEventSpawnReason::ChunkGen { inner } => inner, + CreatureSpawnEventSpawnReason::Spawner { inner } => inner, + CreatureSpawnEventSpawnReason::TrialSpawner { inner } => inner, + CreatureSpawnEventSpawnReason::Egg { inner } => inner, + CreatureSpawnEventSpawnReason::SpawnerEgg { inner } => inner, + CreatureSpawnEventSpawnReason::Lightning { inner } => inner, + CreatureSpawnEventSpawnReason::BuildSnowman { inner } => inner, + CreatureSpawnEventSpawnReason::BuildIrongolem { inner } => inner, + CreatureSpawnEventSpawnReason::BuildWither { inner } => inner, + CreatureSpawnEventSpawnReason::VillageDefense { inner } => inner, + CreatureSpawnEventSpawnReason::VillageInvasion { inner } => inner, + CreatureSpawnEventSpawnReason::Breeding { inner } => inner, + CreatureSpawnEventSpawnReason::SlimeSplit { inner } => inner, + CreatureSpawnEventSpawnReason::Reinforcements { inner } => inner, + CreatureSpawnEventSpawnReason::NetherPortal { inner } => inner, + CreatureSpawnEventSpawnReason::DispenseEgg { inner } => inner, + CreatureSpawnEventSpawnReason::Infection { inner } => inner, + CreatureSpawnEventSpawnReason::Cured { inner } => inner, + CreatureSpawnEventSpawnReason::OcelotBaby { inner } => inner, + CreatureSpawnEventSpawnReason::SilverfishBlock { inner } => inner, + CreatureSpawnEventSpawnReason::Mount { inner } => inner, + CreatureSpawnEventSpawnReason::Trap { inner } => inner, + CreatureSpawnEventSpawnReason::EnderPearl { inner } => inner, + CreatureSpawnEventSpawnReason::ShoulderEntity { inner } => inner, + CreatureSpawnEventSpawnReason::Drowned { inner } => inner, + CreatureSpawnEventSpawnReason::Sheared { inner } => inner, + CreatureSpawnEventSpawnReason::Explosion { inner } => inner, + CreatureSpawnEventSpawnReason::Raid { inner } => inner, + CreatureSpawnEventSpawnReason::Patrol { inner } => inner, + CreatureSpawnEventSpawnReason::Beehive { inner } => inner, + CreatureSpawnEventSpawnReason::PiglinZombified { inner } => inner, + CreatureSpawnEventSpawnReason::Spell { inner } => inner, + CreatureSpawnEventSpawnReason::Frozen { inner } => inner, + CreatureSpawnEventSpawnReason::Metamorphosis { inner } => inner, + CreatureSpawnEventSpawnReason::Duplication { inner } => inner, + CreatureSpawnEventSpawnReason::Command { inner } => inner, + CreatureSpawnEventSpawnReason::Enchantment { inner } => inner, + CreatureSpawnEventSpawnReason::PotionEffect { inner } => inner, + CreatureSpawnEventSpawnReason::Custom { inner } => inner, + CreatureSpawnEventSpawnReason::Default { inner } => inner, + } } +} + +impl<'mc> CreatureSpawnEventSpawnReason<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/event/entity/CreatureSpawnEvent/SpawnReason"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/event/entity/CreatureSpawnEvent/SpawnReason;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "NATURAL" => Ok(CreatureSpawnEventSpawnReason::Natural { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "JOCKEY" => Ok(CreatureSpawnEventSpawnReason::Jockey { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "CHUNK_GEN" => Ok(CreatureSpawnEventSpawnReason::ChunkGen { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "SPAWNER" => Ok(CreatureSpawnEventSpawnReason::Spawner { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "TRIAL_SPAWNER" => Ok(CreatureSpawnEventSpawnReason::TrialSpawner { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "EGG" => Ok(CreatureSpawnEventSpawnReason::Egg { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "SPAWNER_EGG" => Ok(CreatureSpawnEventSpawnReason::SpawnerEgg { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "LIGHTNING" => Ok(CreatureSpawnEventSpawnReason::Lightning { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "BUILD_SNOWMAN" => Ok(CreatureSpawnEventSpawnReason::BuildSnowman { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "BUILD_IRONGOLEM" => Ok(CreatureSpawnEventSpawnReason::BuildIrongolem { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "BUILD_WITHER" => Ok(CreatureSpawnEventSpawnReason::BuildWither { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "VILLAGE_DEFENSE" => Ok(CreatureSpawnEventSpawnReason::VillageDefense { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "VILLAGE_INVASION" => Ok(CreatureSpawnEventSpawnReason::VillageInvasion { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "BREEDING" => Ok(CreatureSpawnEventSpawnReason::Breeding { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "SLIME_SPLIT" => Ok(CreatureSpawnEventSpawnReason::SlimeSplit { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "REINFORCEMENTS" => Ok(CreatureSpawnEventSpawnReason::Reinforcements { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "NETHER_PORTAL" => Ok(CreatureSpawnEventSpawnReason::NetherPortal { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "DISPENSE_EGG" => Ok(CreatureSpawnEventSpawnReason::DispenseEgg { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "INFECTION" => Ok(CreatureSpawnEventSpawnReason::Infection { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "CURED" => Ok(CreatureSpawnEventSpawnReason::Cured { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "OCELOT_BABY" => Ok(CreatureSpawnEventSpawnReason::OcelotBaby { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "SILVERFISH_BLOCK" => Ok(CreatureSpawnEventSpawnReason::SilverfishBlock { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "MOUNT" => Ok(CreatureSpawnEventSpawnReason::Mount { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "TRAP" => Ok(CreatureSpawnEventSpawnReason::Trap { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "ENDER_PEARL" => Ok(CreatureSpawnEventSpawnReason::EnderPearl { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "SHOULDER_ENTITY" => Ok(CreatureSpawnEventSpawnReason::ShoulderEntity { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "DROWNED" => Ok(CreatureSpawnEventSpawnReason::Drowned { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "SHEARED" => Ok(CreatureSpawnEventSpawnReason::Sheared { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "EXPLOSION" => Ok(CreatureSpawnEventSpawnReason::Explosion { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "RAID" => Ok(CreatureSpawnEventSpawnReason::Raid { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "PATROL" => Ok(CreatureSpawnEventSpawnReason::Patrol { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "BEEHIVE" => Ok(CreatureSpawnEventSpawnReason::Beehive { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "PIGLIN_ZOMBIFIED" => Ok(CreatureSpawnEventSpawnReason::PiglinZombified { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "SPELL" => Ok(CreatureSpawnEventSpawnReason::Spell { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "FROZEN" => Ok(CreatureSpawnEventSpawnReason::Frozen { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "METAMORPHOSIS" => Ok(CreatureSpawnEventSpawnReason::Metamorphosis { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "DUPLICATION" => Ok(CreatureSpawnEventSpawnReason::Duplication { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "COMMAND" => Ok(CreatureSpawnEventSpawnReason::Command { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "ENCHANTMENT" => Ok(CreatureSpawnEventSpawnReason::Enchantment { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "POTION_EFFECT" => Ok(CreatureSpawnEventSpawnReason::PotionEffect { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "CUSTOM" => Ok(CreatureSpawnEventSpawnReason::Custom { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "DEFAULT" => Ok(CreatureSpawnEventSpawnReason::Default { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for EntityBreedEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EntityBreedEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for EntityBreedEvent<'mc> { - fn into(self) -> crate::event::entity::EntityEvent<'mc> { - crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EntityBreedEvent into crate::event::entity::EntityEvent") + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } + #[repr(C)] -pub struct AreaEffectCloudApplyEvent<'mc>( +pub struct CreatureSpawnEventSpawnReasonStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for AreaEffectCloudApplyEvent<'mc> { +impl<'mc> JNIRaw<'mc> for CreatureSpawnEventSpawnReason<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + match self { + Self::Natural { inner } => inner.0.clone(), + Self::Jockey { inner } => inner.0.clone(), + Self::ChunkGen { inner } => inner.0.clone(), + Self::Spawner { inner } => inner.0.clone(), + Self::TrialSpawner { inner } => inner.0.clone(), + Self::Egg { inner } => inner.0.clone(), + Self::SpawnerEgg { inner } => inner.0.clone(), + Self::Lightning { inner } => inner.0.clone(), + Self::BuildSnowman { inner } => inner.0.clone(), + Self::BuildIrongolem { inner } => inner.0.clone(), + Self::BuildWither { inner } => inner.0.clone(), + Self::VillageDefense { inner } => inner.0.clone(), + Self::VillageInvasion { inner } => inner.0.clone(), + Self::Breeding { inner } => inner.0.clone(), + Self::SlimeSplit { inner } => inner.0.clone(), + Self::Reinforcements { inner } => inner.0.clone(), + Self::NetherPortal { inner } => inner.0.clone(), + Self::DispenseEgg { inner } => inner.0.clone(), + Self::Infection { inner } => inner.0.clone(), + Self::Cured { inner } => inner.0.clone(), + Self::OcelotBaby { inner } => inner.0.clone(), + Self::SilverfishBlock { inner } => inner.0.clone(), + Self::Mount { inner } => inner.0.clone(), + Self::Trap { inner } => inner.0.clone(), + Self::EnderPearl { inner } => inner.0.clone(), + Self::ShoulderEntity { inner } => inner.0.clone(), + Self::Drowned { inner } => inner.0.clone(), + Self::Sheared { inner } => inner.0.clone(), + Self::Explosion { inner } => inner.0.clone(), + Self::Raid { inner } => inner.0.clone(), + Self::Patrol { inner } => inner.0.clone(), + Self::Beehive { inner } => inner.0.clone(), + Self::PiglinZombified { inner } => inner.0.clone(), + Self::Spell { inner } => inner.0.clone(), + Self::Frozen { inner } => inner.0.clone(), + Self::Metamorphosis { inner } => inner.0.clone(), + Self::Duplication { inner } => inner.0.clone(), + Self::Command { inner } => inner.0.clone(), + Self::Enchantment { inner } => inner.0.clone(), + Self::PotionEffect { inner } => inner.0.clone(), + Self::Custom { inner } => inner.0.clone(), + Self::Default { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + match self { + Self::Natural { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Jockey { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ChunkGen { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Spawner { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::TrialSpawner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Egg { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SpawnerEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Lightning { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BuildSnowman { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BuildIrongolem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BuildWither { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VillageDefense { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VillageInvasion { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Breeding { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SlimeSplit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Reinforcements { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetherPortal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DispenseEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Infection { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Cured { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::OcelotBaby { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SilverfishBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Mount { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Trap { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::EnderPearl { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ShoulderEntity { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Drowned { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Sheared { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Explosion { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Raid { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Patrol { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Beehive { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PiglinZombified { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Spell { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Frozen { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Metamorphosis { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Duplication { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Command { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Enchantment { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PotionEffect { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Custom { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Default { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for AreaEffectCloudApplyEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CreatureSpawnEventSpawnReason<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate AreaEffectCloudApplyEvent from null object." + "Tried to instantiate CreatureSpawnEventSpawnReason from null object." ) .into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/entity/AreaEffectCloudApplyEvent")?; + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/event/entity/CreatureSpawnEvent/SpawnReason", + )?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a AreaEffectCloudApplyEvent object, got {}", + "Invalid argument passed. Expected a CreatureSpawnEventSpawnReason object, got {}", name ) .into()) } else { - Ok(Self(env.clone(), obj)) + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "NATURAL" => Ok(CreatureSpawnEventSpawnReason::Natural { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "JOCKEY" => Ok(CreatureSpawnEventSpawnReason::Jockey { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "CHUNK_GEN" => Ok(CreatureSpawnEventSpawnReason::ChunkGen { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "SPAWNER" => Ok(CreatureSpawnEventSpawnReason::Spawner { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "TRIAL_SPAWNER" => Ok(CreatureSpawnEventSpawnReason::TrialSpawner { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "EGG" => Ok(CreatureSpawnEventSpawnReason::Egg { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "SPAWNER_EGG" => Ok(CreatureSpawnEventSpawnReason::SpawnerEgg { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "LIGHTNING" => Ok(CreatureSpawnEventSpawnReason::Lightning { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "BUILD_SNOWMAN" => Ok(CreatureSpawnEventSpawnReason::BuildSnowman { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "BUILD_IRONGOLEM" => Ok(CreatureSpawnEventSpawnReason::BuildIrongolem { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "BUILD_WITHER" => Ok(CreatureSpawnEventSpawnReason::BuildWither { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "VILLAGE_DEFENSE" => Ok(CreatureSpawnEventSpawnReason::VillageDefense { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "VILLAGE_INVASION" => Ok(CreatureSpawnEventSpawnReason::VillageInvasion { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "BREEDING" => Ok(CreatureSpawnEventSpawnReason::Breeding { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "SLIME_SPLIT" => Ok(CreatureSpawnEventSpawnReason::SlimeSplit { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "REINFORCEMENTS" => Ok(CreatureSpawnEventSpawnReason::Reinforcements { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "NETHER_PORTAL" => Ok(CreatureSpawnEventSpawnReason::NetherPortal { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "DISPENSE_EGG" => Ok(CreatureSpawnEventSpawnReason::DispenseEgg { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "INFECTION" => Ok(CreatureSpawnEventSpawnReason::Infection { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "CURED" => Ok(CreatureSpawnEventSpawnReason::Cured { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "OCELOT_BABY" => Ok(CreatureSpawnEventSpawnReason::OcelotBaby { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "SILVERFISH_BLOCK" => Ok(CreatureSpawnEventSpawnReason::SilverfishBlock { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "MOUNT" => Ok(CreatureSpawnEventSpawnReason::Mount { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "TRAP" => Ok(CreatureSpawnEventSpawnReason::Trap { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "ENDER_PEARL" => Ok(CreatureSpawnEventSpawnReason::EnderPearl { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "SHOULDER_ENTITY" => Ok(CreatureSpawnEventSpawnReason::ShoulderEntity { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "DROWNED" => Ok(CreatureSpawnEventSpawnReason::Drowned { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "SHEARED" => Ok(CreatureSpawnEventSpawnReason::Sheared { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "EXPLOSION" => Ok(CreatureSpawnEventSpawnReason::Explosion { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "RAID" => Ok(CreatureSpawnEventSpawnReason::Raid { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "PATROL" => Ok(CreatureSpawnEventSpawnReason::Patrol { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "BEEHIVE" => Ok(CreatureSpawnEventSpawnReason::Beehive { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "PIGLIN_ZOMBIFIED" => Ok(CreatureSpawnEventSpawnReason::PiglinZombified { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "SPELL" => Ok(CreatureSpawnEventSpawnReason::Spell { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "FROZEN" => Ok(CreatureSpawnEventSpawnReason::Frozen { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "METAMORPHOSIS" => Ok(CreatureSpawnEventSpawnReason::Metamorphosis { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "DUPLICATION" => Ok(CreatureSpawnEventSpawnReason::Duplication { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "COMMAND" => Ok(CreatureSpawnEventSpawnReason::Command { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "ENCHANTMENT" => Ok(CreatureSpawnEventSpawnReason::Enchantment { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "POTION_EFFECT" => Ok(CreatureSpawnEventSpawnReason::PotionEffect { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "CUSTOM" => Ok(CreatureSpawnEventSpawnReason::Custom { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + "DEFAULT" => Ok(CreatureSpawnEventSpawnReason::Default { + inner: CreatureSpawnEventSpawnReasonStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } } -impl<'mc> AreaEffectCloudApplyEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - entity: impl Into>, - affected_entities: Vec>, - ) -> Result, Box> - { - let sig = String::from("(Lorg/bukkit/entity/AreaEffectCloud;Ljava/util/List;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) - }); - let raw_val_2 = jni.new_object("java/util/ArrayList", "()V", vec![])?; - for v in affected_entities { - let map_val_0 = jni::objects::JValueGen::Object(v); - jni.call_method( - &raw_val_2, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_2 = jni::objects::JValueGen::Object(raw_val_2); - let cls = jni.find_class("org/bukkit/event/entity/AreaEffectCloudApplyEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = jni.translate_error_no_gen(res)?; - crate::event::entity::AreaEffectCloudApplyEvent::from_raw(&jni, res) - } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +impl<'mc> JNIRaw<'mc> for CreatureSpawnEventSpawnReasonStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - - pub fn entity( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/AreaEffectCloud;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::AreaEffectCloud::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Retrieves a mutable list of the effected entities - /// - /// It is important to note that not every entity in this list - /// is guaranteed to be effected.The cloud may die during the - /// application of its effects due to the depletion of {@link AreaEffectCloud#getDurationOnUse()} - /// or {@link AreaEffectCloud#getRadiusOnUse()} - pub fn affected_entities( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAffectedEntities", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::LivingEntity::from_raw(&self.0, obj)?); +} +impl<'mc> JNIInstantiatable<'mc> for CreatureSpawnEventSpawnReasonStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate CreatureSpawnEventSpawnReasonStruct from null object." + ) + .into()); + } + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/event/entity/CreatureSpawnEvent/SpawnReason", + )?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a CreatureSpawnEventSpawnReasonStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - Ok(new_vec) - } - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) } +} - pub fn handler_list( +impl<'mc> CreatureSpawnEventSpawnReasonStruct<'mc> { + pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/entity/AreaEffectCloudApplyEvent"); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/event/entity/CreatureSpawnEvent/SpawnReason;"); + let cls = jni.find_class("org/bukkit/event/entity/CreatureSpawnEvent/SpawnReason"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['isCancelled', 'setCancelled', 'getEntity', 'getAffectedEntities', 'getHandlers', 'getHandlerList']) - /// Gets the EntityType of the Entity involved in this event. - pub fn entity_type( - &self, - ) -> Result, Box> { - let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityEvent = temp_clone.into(); - real.entity_type() + crate::event::entity::CreatureSpawnEventSpawnReason::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -8729,19 +10799,6 @@ impl<'mc> AreaEffectCloudApplyEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for AreaEffectCloudApplyEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting AreaEffectCloudApplyEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for AreaEffectCloudApplyEvent<'mc> { - fn into(self) -> crate::event::entity::EntityEvent<'mc> { - crate::event::entity::EntityEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting AreaEffectCloudApplyEvent into crate::event::entity::EntityEvent", - ) - } -} #[repr(C)] pub struct HorseJumpEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, @@ -9576,10 +11633,66 @@ impl<'mc> Into> for EntityRegainHealthEve ) } } -pub enum EntityRegainHealthEventRegainReason<'mc> {} +pub enum EntityRegainHealthEventRegainReason<'mc> { + Regen { + inner: EntityRegainHealthEventRegainReasonStruct<'mc>, + }, + Satiated { + inner: EntityRegainHealthEventRegainReasonStruct<'mc>, + }, + Eating { + inner: EntityRegainHealthEventRegainReasonStruct<'mc>, + }, + EnderCrystal { + inner: EntityRegainHealthEventRegainReasonStruct<'mc>, + }, + Magic { + inner: EntityRegainHealthEventRegainReasonStruct<'mc>, + }, + MagicRegen { + inner: EntityRegainHealthEventRegainReasonStruct<'mc>, + }, + WitherSpawn { + inner: EntityRegainHealthEventRegainReasonStruct<'mc>, + }, + Wither { + inner: EntityRegainHealthEventRegainReasonStruct<'mc>, + }, + Custom { + inner: EntityRegainHealthEventRegainReasonStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for EntityRegainHealthEventRegainReason<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + EntityRegainHealthEventRegainReason::Regen { .. } => f.write_str("REGEN"), + EntityRegainHealthEventRegainReason::Satiated { .. } => f.write_str("SATIATED"), + EntityRegainHealthEventRegainReason::Eating { .. } => f.write_str("EATING"), + EntityRegainHealthEventRegainReason::EnderCrystal { .. } => { + f.write_str("ENDER_CRYSTAL") + } + EntityRegainHealthEventRegainReason::Magic { .. } => f.write_str("MAGIC"), + EntityRegainHealthEventRegainReason::MagicRegen { .. } => f.write_str("MAGIC_REGEN"), + EntityRegainHealthEventRegainReason::WitherSpawn { .. } => f.write_str("WITHER_SPAWN"), + EntityRegainHealthEventRegainReason::Wither { .. } => f.write_str("WITHER"), + EntityRegainHealthEventRegainReason::Custom { .. } => f.write_str("CUSTOM"), + } + } +} +impl<'mc> std::ops::Deref for EntityRegainHealthEventRegainReason<'mc> { + type Target = EntityRegainHealthEventRegainReasonStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + EntityRegainHealthEventRegainReason::Regen { inner } => inner, + EntityRegainHealthEventRegainReason::Satiated { inner } => inner, + EntityRegainHealthEventRegainReason::Eating { inner } => inner, + EntityRegainHealthEventRegainReason::EnderCrystal { inner } => inner, + EntityRegainHealthEventRegainReason::Magic { inner } => inner, + EntityRegainHealthEventRegainReason::MagicRegen { inner } => inner, + EntityRegainHealthEventRegainReason::WitherSpawn { inner } => inner, + EntityRegainHealthEventRegainReason::Wither { inner } => inner, + EntityRegainHealthEventRegainReason::Custom { inner } => inner, + } } } @@ -9606,6 +11719,34 @@ impl<'mc> EntityRegainHealthEventRegainReason<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "REGEN" => Ok(EntityRegainHealthEventRegainReason::Regen { + inner: EntityRegainHealthEventRegainReasonStruct::from_raw(env, obj)?, + }), + "SATIATED" => Ok(EntityRegainHealthEventRegainReason::Satiated { + inner: EntityRegainHealthEventRegainReasonStruct::from_raw(env, obj)?, + }), + "EATING" => Ok(EntityRegainHealthEventRegainReason::Eating { + inner: EntityRegainHealthEventRegainReasonStruct::from_raw(env, obj)?, + }), + "ENDER_CRYSTAL" => Ok(EntityRegainHealthEventRegainReason::EnderCrystal { + inner: EntityRegainHealthEventRegainReasonStruct::from_raw(env, obj)?, + }), + "MAGIC" => Ok(EntityRegainHealthEventRegainReason::Magic { + inner: EntityRegainHealthEventRegainReasonStruct::from_raw(env, obj)?, + }), + "MAGIC_REGEN" => Ok(EntityRegainHealthEventRegainReason::MagicRegen { + inner: EntityRegainHealthEventRegainReasonStruct::from_raw(env, obj)?, + }), + "WITHER_SPAWN" => Ok(EntityRegainHealthEventRegainReason::WitherSpawn { + inner: EntityRegainHealthEventRegainReasonStruct::from_raw(env, obj)?, + }), + "WITHER" => Ok(EntityRegainHealthEventRegainReason::Wither { + inner: EntityRegainHealthEventRegainReasonStruct::from_raw(env, obj)?, + }), + "CUSTOM" => Ok(EntityRegainHealthEventRegainReason::Custom { + inner: EntityRegainHealthEventRegainReasonStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -9619,10 +11760,36 @@ pub struct EntityRegainHealthEventRegainReasonStruct<'mc>( impl<'mc> JNIRaw<'mc> for EntityRegainHealthEventRegainReason<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Regen { inner } => inner.0.clone(), + Self::Satiated { inner } => inner.0.clone(), + Self::Eating { inner } => inner.0.clone(), + Self::EnderCrystal { inner } => inner.0.clone(), + Self::Magic { inner } => inner.0.clone(), + Self::MagicRegen { inner } => inner.0.clone(), + Self::WitherSpawn { inner } => inner.0.clone(), + Self::Wither { inner } => inner.0.clone(), + Self::Custom { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Regen { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Satiated { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Eating { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::EnderCrystal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Magic { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::MagicRegen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WitherSpawn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Wither { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Custom { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for EntityRegainHealthEventRegainReason<'mc> { @@ -9654,6 +11821,33 @@ impl<'mc> JNIInstantiatable<'mc> for EntityRegainHealthEventRegainReason<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "REGEN" => Ok(EntityRegainHealthEventRegainReason::Regen { + inner: EntityRegainHealthEventRegainReasonStruct::from_raw(env, obj)?, + }), + "SATIATED" => Ok(EntityRegainHealthEventRegainReason::Satiated { + inner: EntityRegainHealthEventRegainReasonStruct::from_raw(env, obj)?, + }), + "EATING" => Ok(EntityRegainHealthEventRegainReason::Eating { + inner: EntityRegainHealthEventRegainReasonStruct::from_raw(env, obj)?, + }), + "ENDER_CRYSTAL" => Ok(EntityRegainHealthEventRegainReason::EnderCrystal { + inner: EntityRegainHealthEventRegainReasonStruct::from_raw(env, obj)?, + }), + "MAGIC" => Ok(EntityRegainHealthEventRegainReason::Magic { + inner: EntityRegainHealthEventRegainReasonStruct::from_raw(env, obj)?, + }), + "MAGIC_REGEN" => Ok(EntityRegainHealthEventRegainReason::MagicRegen { + inner: EntityRegainHealthEventRegainReasonStruct::from_raw(env, obj)?, + }), + "WITHER_SPAWN" => Ok(EntityRegainHealthEventRegainReason::WitherSpawn { + inner: EntityRegainHealthEventRegainReasonStruct::from_raw(env, obj)?, + }), + "WITHER" => Ok(EntityRegainHealthEventRegainReason::Wither { + inner: EntityRegainHealthEventRegainReasonStruct::from_raw(env, obj)?, + }), + "CUSTOM" => Ok(EntityRegainHealthEventRegainReason::Custom { + inner: EntityRegainHealthEventRegainReasonStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -10799,10 +12993,95 @@ impl<'mc> Into> for EntityExhaustionEvent .expect("Error converting EntityExhaustionEvent into crate::event::entity::EntityEvent") } } -pub enum EntityExhaustionEventExhaustionReason<'mc> {} +pub enum EntityExhaustionEventExhaustionReason<'mc> { + BlockMined { + inner: EntityExhaustionEventExhaustionReasonStruct<'mc>, + }, + HungerEffect { + inner: EntityExhaustionEventExhaustionReasonStruct<'mc>, + }, + Damaged { + inner: EntityExhaustionEventExhaustionReasonStruct<'mc>, + }, + Attack { + inner: EntityExhaustionEventExhaustionReasonStruct<'mc>, + }, + JumpSprint { + inner: EntityExhaustionEventExhaustionReasonStruct<'mc>, + }, + Jump { + inner: EntityExhaustionEventExhaustionReasonStruct<'mc>, + }, + Swim { + inner: EntityExhaustionEventExhaustionReasonStruct<'mc>, + }, + WalkUnderwater { + inner: EntityExhaustionEventExhaustionReasonStruct<'mc>, + }, + WalkOnWater { + inner: EntityExhaustionEventExhaustionReasonStruct<'mc>, + }, + Sprint { + inner: EntityExhaustionEventExhaustionReasonStruct<'mc>, + }, + Crouch { + inner: EntityExhaustionEventExhaustionReasonStruct<'mc>, + }, + Walk { + inner: EntityExhaustionEventExhaustionReasonStruct<'mc>, + }, + Regen { + inner: EntityExhaustionEventExhaustionReasonStruct<'mc>, + }, + Unknown { + inner: EntityExhaustionEventExhaustionReasonStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for EntityExhaustionEventExhaustionReason<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + EntityExhaustionEventExhaustionReason::BlockMined { .. } => f.write_str("BLOCK_MINED"), + EntityExhaustionEventExhaustionReason::HungerEffect { .. } => { + f.write_str("HUNGER_EFFECT") + } + EntityExhaustionEventExhaustionReason::Damaged { .. } => f.write_str("DAMAGED"), + EntityExhaustionEventExhaustionReason::Attack { .. } => f.write_str("ATTACK"), + EntityExhaustionEventExhaustionReason::JumpSprint { .. } => f.write_str("JUMP_SPRINT"), + EntityExhaustionEventExhaustionReason::Jump { .. } => f.write_str("JUMP"), + EntityExhaustionEventExhaustionReason::Swim { .. } => f.write_str("SWIM"), + EntityExhaustionEventExhaustionReason::WalkUnderwater { .. } => { + f.write_str("WALK_UNDERWATER") + } + EntityExhaustionEventExhaustionReason::WalkOnWater { .. } => { + f.write_str("WALK_ON_WATER") + } + EntityExhaustionEventExhaustionReason::Sprint { .. } => f.write_str("SPRINT"), + EntityExhaustionEventExhaustionReason::Crouch { .. } => f.write_str("CROUCH"), + EntityExhaustionEventExhaustionReason::Walk { .. } => f.write_str("WALK"), + EntityExhaustionEventExhaustionReason::Regen { .. } => f.write_str("REGEN"), + EntityExhaustionEventExhaustionReason::Unknown { .. } => f.write_str("UNKNOWN"), + } + } +} +impl<'mc> std::ops::Deref for EntityExhaustionEventExhaustionReason<'mc> { + type Target = EntityExhaustionEventExhaustionReasonStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + EntityExhaustionEventExhaustionReason::BlockMined { inner } => inner, + EntityExhaustionEventExhaustionReason::HungerEffect { inner } => inner, + EntityExhaustionEventExhaustionReason::Damaged { inner } => inner, + EntityExhaustionEventExhaustionReason::Attack { inner } => inner, + EntityExhaustionEventExhaustionReason::JumpSprint { inner } => inner, + EntityExhaustionEventExhaustionReason::Jump { inner } => inner, + EntityExhaustionEventExhaustionReason::Swim { inner } => inner, + EntityExhaustionEventExhaustionReason::WalkUnderwater { inner } => inner, + EntityExhaustionEventExhaustionReason::WalkOnWater { inner } => inner, + EntityExhaustionEventExhaustionReason::Sprint { inner } => inner, + EntityExhaustionEventExhaustionReason::Crouch { inner } => inner, + EntityExhaustionEventExhaustionReason::Walk { inner } => inner, + EntityExhaustionEventExhaustionReason::Regen { inner } => inner, + EntityExhaustionEventExhaustionReason::Unknown { inner } => inner, + } } } @@ -10829,6 +13108,49 @@ impl<'mc> EntityExhaustionEventExhaustionReason<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "BLOCK_MINED" => Ok(EntityExhaustionEventExhaustionReason::BlockMined { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "HUNGER_EFFECT" => Ok(EntityExhaustionEventExhaustionReason::HungerEffect { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "DAMAGED" => Ok(EntityExhaustionEventExhaustionReason::Damaged { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "ATTACK" => Ok(EntityExhaustionEventExhaustionReason::Attack { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "JUMP_SPRINT" => Ok(EntityExhaustionEventExhaustionReason::JumpSprint { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "JUMP" => Ok(EntityExhaustionEventExhaustionReason::Jump { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "SWIM" => Ok(EntityExhaustionEventExhaustionReason::Swim { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "WALK_UNDERWATER" => Ok(EntityExhaustionEventExhaustionReason::WalkUnderwater { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "WALK_ON_WATER" => Ok(EntityExhaustionEventExhaustionReason::WalkOnWater { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "SPRINT" => Ok(EntityExhaustionEventExhaustionReason::Sprint { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "CROUCH" => Ok(EntityExhaustionEventExhaustionReason::Crouch { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "WALK" => Ok(EntityExhaustionEventExhaustionReason::Walk { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "REGEN" => Ok(EntityExhaustionEventExhaustionReason::Regen { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(EntityExhaustionEventExhaustionReason::Unknown { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -10842,10 +13164,50 @@ pub struct EntityExhaustionEventExhaustionReasonStruct<'mc>( impl<'mc> JNIRaw<'mc> for EntityExhaustionEventExhaustionReason<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::BlockMined { inner } => inner.0.clone(), + Self::HungerEffect { inner } => inner.0.clone(), + Self::Damaged { inner } => inner.0.clone(), + Self::Attack { inner } => inner.0.clone(), + Self::JumpSprint { inner } => inner.0.clone(), + Self::Jump { inner } => inner.0.clone(), + Self::Swim { inner } => inner.0.clone(), + Self::WalkUnderwater { inner } => inner.0.clone(), + Self::WalkOnWater { inner } => inner.0.clone(), + Self::Sprint { inner } => inner.0.clone(), + Self::Crouch { inner } => inner.0.clone(), + Self::Walk { inner } => inner.0.clone(), + Self::Regen { inner } => inner.0.clone(), + Self::Unknown { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::BlockMined { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HungerEffect { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Damaged { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Attack { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::JumpSprint { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Jump { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Swim { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::WalkUnderwater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WalkOnWater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Sprint { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Crouch { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Walk { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Regen { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Unknown { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for EntityExhaustionEventExhaustionReason<'mc> { @@ -10877,6 +13239,48 @@ impl<'mc> JNIInstantiatable<'mc> for EntityExhaustionEventExhaustionReason<'mc> .to_string_lossy() .to_string(); match variant_str.as_str() { + "BLOCK_MINED" => Ok(EntityExhaustionEventExhaustionReason::BlockMined { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "HUNGER_EFFECT" => Ok(EntityExhaustionEventExhaustionReason::HungerEffect { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "DAMAGED" => Ok(EntityExhaustionEventExhaustionReason::Damaged { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "ATTACK" => Ok(EntityExhaustionEventExhaustionReason::Attack { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "JUMP_SPRINT" => Ok(EntityExhaustionEventExhaustionReason::JumpSprint { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "JUMP" => Ok(EntityExhaustionEventExhaustionReason::Jump { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "SWIM" => Ok(EntityExhaustionEventExhaustionReason::Swim { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "WALK_UNDERWATER" => Ok(EntityExhaustionEventExhaustionReason::WalkUnderwater { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "WALK_ON_WATER" => Ok(EntityExhaustionEventExhaustionReason::WalkOnWater { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "SPRINT" => Ok(EntityExhaustionEventExhaustionReason::Sprint { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "CROUCH" => Ok(EntityExhaustionEventExhaustionReason::Crouch { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "WALK" => Ok(EntityExhaustionEventExhaustionReason::Walk { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "REGEN" => Ok(EntityExhaustionEventExhaustionReason::Regen { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(EntityExhaustionEventExhaustionReason::Unknown { + inner: EntityExhaustionEventExhaustionReasonStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -11298,10 +13702,29 @@ impl<'mc> Into> for VillagerCareerChangeE ) } } -pub enum VillagerCareerChangeEventChangeReason<'mc> {} +pub enum VillagerCareerChangeEventChangeReason<'mc> { + LosingJob { + inner: VillagerCareerChangeEventChangeReasonStruct<'mc>, + }, + Employed { + inner: VillagerCareerChangeEventChangeReasonStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for VillagerCareerChangeEventChangeReason<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + VillagerCareerChangeEventChangeReason::LosingJob { .. } => f.write_str("LOSING_JOB"), + VillagerCareerChangeEventChangeReason::Employed { .. } => f.write_str("EMPLOYED"), + } + } +} +impl<'mc> std::ops::Deref for VillagerCareerChangeEventChangeReason<'mc> { + type Target = VillagerCareerChangeEventChangeReasonStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + VillagerCareerChangeEventChangeReason::LosingJob { inner } => inner, + VillagerCareerChangeEventChangeReason::Employed { inner } => inner, + } } } @@ -11328,6 +13751,13 @@ impl<'mc> VillagerCareerChangeEventChangeReason<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "LOSING_JOB" => Ok(VillagerCareerChangeEventChangeReason::LosingJob { + inner: VillagerCareerChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + "EMPLOYED" => Ok(VillagerCareerChangeEventChangeReason::Employed { + inner: VillagerCareerChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -11341,10 +13771,18 @@ pub struct VillagerCareerChangeEventChangeReasonStruct<'mc>( impl<'mc> JNIRaw<'mc> for VillagerCareerChangeEventChangeReason<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::LosingJob { inner } => inner.0.clone(), + Self::Employed { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::LosingJob { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Employed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for VillagerCareerChangeEventChangeReason<'mc> { @@ -11376,6 +13814,12 @@ impl<'mc> JNIInstantiatable<'mc> for VillagerCareerChangeEventChangeReason<'mc> .to_string_lossy() .to_string(); match variant_str.as_str() { + "LOSING_JOB" => Ok(VillagerCareerChangeEventChangeReason::LosingJob { + inner: VillagerCareerChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + "EMPLOYED" => Ok(VillagerCareerChangeEventChangeReason::Employed { + inner: VillagerCareerChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -11911,10 +14355,116 @@ impl<'mc> Into> for EntityTargetEvent<'mc .expect("Error converting EntityTargetEvent into crate::event::entity::EntityEvent") } } -pub enum EntityTargetEventTargetReason<'mc> {} +pub enum EntityTargetEventTargetReason<'mc> { + TargetDied { + inner: EntityTargetEventTargetReasonStruct<'mc>, + }, + ClosestPlayer { + inner: EntityTargetEventTargetReasonStruct<'mc>, + }, + TargetAttackedEntity { + inner: EntityTargetEventTargetReasonStruct<'mc>, + }, + PigZombieTarget { + inner: EntityTargetEventTargetReasonStruct<'mc>, + }, + ForgotTarget { + inner: EntityTargetEventTargetReasonStruct<'mc>, + }, + TargetAttackedOwner { + inner: EntityTargetEventTargetReasonStruct<'mc>, + }, + OwnerAttackedTarget { + inner: EntityTargetEventTargetReasonStruct<'mc>, + }, + RandomTarget { + inner: EntityTargetEventTargetReasonStruct<'mc>, + }, + DefendVillage { + inner: EntityTargetEventTargetReasonStruct<'mc>, + }, + TargetAttackedNearbyEntity { + inner: EntityTargetEventTargetReasonStruct<'mc>, + }, + ReinforcementTarget { + inner: EntityTargetEventTargetReasonStruct<'mc>, + }, + Collision { + inner: EntityTargetEventTargetReasonStruct<'mc>, + }, + Custom { + inner: EntityTargetEventTargetReasonStruct<'mc>, + }, + ClosestEntity { + inner: EntityTargetEventTargetReasonStruct<'mc>, + }, + FollowLeader { + inner: EntityTargetEventTargetReasonStruct<'mc>, + }, + Tempt { + inner: EntityTargetEventTargetReasonStruct<'mc>, + }, + Unknown { + inner: EntityTargetEventTargetReasonStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for EntityTargetEventTargetReason<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + EntityTargetEventTargetReason::TargetDied { .. } => f.write_str("TARGET_DIED"), + EntityTargetEventTargetReason::ClosestPlayer { .. } => f.write_str("CLOSEST_PLAYER"), + EntityTargetEventTargetReason::TargetAttackedEntity { .. } => { + f.write_str("TARGET_ATTACKED_ENTITY") + } + EntityTargetEventTargetReason::PigZombieTarget { .. } => { + f.write_str("PIG_ZOMBIE_TARGET") + } + EntityTargetEventTargetReason::ForgotTarget { .. } => f.write_str("FORGOT_TARGET"), + EntityTargetEventTargetReason::TargetAttackedOwner { .. } => { + f.write_str("TARGET_ATTACKED_OWNER") + } + EntityTargetEventTargetReason::OwnerAttackedTarget { .. } => { + f.write_str("OWNER_ATTACKED_TARGET") + } + EntityTargetEventTargetReason::RandomTarget { .. } => f.write_str("RANDOM_TARGET"), + EntityTargetEventTargetReason::DefendVillage { .. } => f.write_str("DEFEND_VILLAGE"), + EntityTargetEventTargetReason::TargetAttackedNearbyEntity { .. } => { + f.write_str("TARGET_ATTACKED_NEARBY_ENTITY") + } + EntityTargetEventTargetReason::ReinforcementTarget { .. } => { + f.write_str("REINFORCEMENT_TARGET") + } + EntityTargetEventTargetReason::Collision { .. } => f.write_str("COLLISION"), + EntityTargetEventTargetReason::Custom { .. } => f.write_str("CUSTOM"), + EntityTargetEventTargetReason::ClosestEntity { .. } => f.write_str("CLOSEST_ENTITY"), + EntityTargetEventTargetReason::FollowLeader { .. } => f.write_str("FOLLOW_LEADER"), + EntityTargetEventTargetReason::Tempt { .. } => f.write_str("TEMPT"), + EntityTargetEventTargetReason::Unknown { .. } => f.write_str("UNKNOWN"), + } + } +} +impl<'mc> std::ops::Deref for EntityTargetEventTargetReason<'mc> { + type Target = EntityTargetEventTargetReasonStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + EntityTargetEventTargetReason::TargetDied { inner } => inner, + EntityTargetEventTargetReason::ClosestPlayer { inner } => inner, + EntityTargetEventTargetReason::TargetAttackedEntity { inner } => inner, + EntityTargetEventTargetReason::PigZombieTarget { inner } => inner, + EntityTargetEventTargetReason::ForgotTarget { inner } => inner, + EntityTargetEventTargetReason::TargetAttackedOwner { inner } => inner, + EntityTargetEventTargetReason::OwnerAttackedTarget { inner } => inner, + EntityTargetEventTargetReason::RandomTarget { inner } => inner, + EntityTargetEventTargetReason::DefendVillage { inner } => inner, + EntityTargetEventTargetReason::TargetAttackedNearbyEntity { inner } => inner, + EntityTargetEventTargetReason::ReinforcementTarget { inner } => inner, + EntityTargetEventTargetReason::Collision { inner } => inner, + EntityTargetEventTargetReason::Custom { inner } => inner, + EntityTargetEventTargetReason::ClosestEntity { inner } => inner, + EntityTargetEventTargetReason::FollowLeader { inner } => inner, + EntityTargetEventTargetReason::Tempt { inner } => inner, + EntityTargetEventTargetReason::Unknown { inner } => inner, + } } } @@ -11941,6 +14491,60 @@ impl<'mc> EntityTargetEventTargetReason<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "TARGET_DIED" => Ok(EntityTargetEventTargetReason::TargetDied { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "CLOSEST_PLAYER" => Ok(EntityTargetEventTargetReason::ClosestPlayer { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "TARGET_ATTACKED_ENTITY" => Ok(EntityTargetEventTargetReason::TargetAttackedEntity { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "PIG_ZOMBIE_TARGET" => Ok(EntityTargetEventTargetReason::PigZombieTarget { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "FORGOT_TARGET" => Ok(EntityTargetEventTargetReason::ForgotTarget { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "TARGET_ATTACKED_OWNER" => Ok(EntityTargetEventTargetReason::TargetAttackedOwner { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "OWNER_ATTACKED_TARGET" => Ok(EntityTargetEventTargetReason::OwnerAttackedTarget { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "RANDOM_TARGET" => Ok(EntityTargetEventTargetReason::RandomTarget { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "DEFEND_VILLAGE" => Ok(EntityTargetEventTargetReason::DefendVillage { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "TARGET_ATTACKED_NEARBY_ENTITY" => { + Ok(EntityTargetEventTargetReason::TargetAttackedNearbyEntity { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }) + } + "REINFORCEMENT_TARGET" => Ok(EntityTargetEventTargetReason::ReinforcementTarget { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "COLLISION" => Ok(EntityTargetEventTargetReason::Collision { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "CUSTOM" => Ok(EntityTargetEventTargetReason::Custom { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "CLOSEST_ENTITY" => Ok(EntityTargetEventTargetReason::ClosestEntity { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "FOLLOW_LEADER" => Ok(EntityTargetEventTargetReason::FollowLeader { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "TEMPT" => Ok(EntityTargetEventTargetReason::Tempt { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(EntityTargetEventTargetReason::Unknown { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -11954,10 +14558,74 @@ pub struct EntityTargetEventTargetReasonStruct<'mc>( impl<'mc> JNIRaw<'mc> for EntityTargetEventTargetReason<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::TargetDied { inner } => inner.0.clone(), + Self::ClosestPlayer { inner } => inner.0.clone(), + Self::TargetAttackedEntity { inner } => inner.0.clone(), + Self::PigZombieTarget { inner } => inner.0.clone(), + Self::ForgotTarget { inner } => inner.0.clone(), + Self::TargetAttackedOwner { inner } => inner.0.clone(), + Self::OwnerAttackedTarget { inner } => inner.0.clone(), + Self::RandomTarget { inner } => inner.0.clone(), + Self::DefendVillage { inner } => inner.0.clone(), + Self::TargetAttackedNearbyEntity { inner } => inner.0.clone(), + Self::ReinforcementTarget { inner } => inner.0.clone(), + Self::Collision { inner } => inner.0.clone(), + Self::Custom { inner } => inner.0.clone(), + Self::ClosestEntity { inner } => inner.0.clone(), + Self::FollowLeader { inner } => inner.0.clone(), + Self::Tempt { inner } => inner.0.clone(), + Self::Unknown { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::TargetDied { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ClosestPlayer { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TargetAttackedEntity { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PigZombieTarget { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ForgotTarget { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TargetAttackedOwner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OwnerAttackedTarget { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RandomTarget { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DefendVillage { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TargetAttackedNearbyEntity { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ReinforcementTarget { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Collision { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Custom { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ClosestEntity { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FollowLeader { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Tempt { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Unknown { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for EntityTargetEventTargetReason<'mc> { @@ -11989,6 +14657,61 @@ impl<'mc> JNIInstantiatable<'mc> for EntityTargetEventTargetReason<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "TARGET_DIED" => Ok(EntityTargetEventTargetReason::TargetDied { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "CLOSEST_PLAYER" => Ok(EntityTargetEventTargetReason::ClosestPlayer { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "TARGET_ATTACKED_ENTITY" => { + Ok(EntityTargetEventTargetReason::TargetAttackedEntity { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }) + } + "PIG_ZOMBIE_TARGET" => Ok(EntityTargetEventTargetReason::PigZombieTarget { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "FORGOT_TARGET" => Ok(EntityTargetEventTargetReason::ForgotTarget { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "TARGET_ATTACKED_OWNER" => Ok(EntityTargetEventTargetReason::TargetAttackedOwner { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "OWNER_ATTACKED_TARGET" => Ok(EntityTargetEventTargetReason::OwnerAttackedTarget { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "RANDOM_TARGET" => Ok(EntityTargetEventTargetReason::RandomTarget { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "DEFEND_VILLAGE" => Ok(EntityTargetEventTargetReason::DefendVillage { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "TARGET_ATTACKED_NEARBY_ENTITY" => { + Ok(EntityTargetEventTargetReason::TargetAttackedNearbyEntity { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }) + } + "REINFORCEMENT_TARGET" => Ok(EntityTargetEventTargetReason::ReinforcementTarget { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "COLLISION" => Ok(EntityTargetEventTargetReason::Collision { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "CUSTOM" => Ok(EntityTargetEventTargetReason::Custom { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "CLOSEST_ENTITY" => Ok(EntityTargetEventTargetReason::ClosestEntity { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "FOLLOW_LEADER" => Ok(EntityTargetEventTargetReason::FollowLeader { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "TEMPT" => Ok(EntityTargetEventTargetReason::Tempt { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(EntityTargetEventTargetReason::Unknown { + inner: EntityTargetEventTargetReasonStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -13347,10 +16070,39 @@ impl<'mc> Into> for EntityPotionEffectEve ) } } -pub enum EntityPotionEffectEventAction<'mc> {} +pub enum EntityPotionEffectEventAction<'mc> { + Added { + inner: EntityPotionEffectEventActionStruct<'mc>, + }, + Changed { + inner: EntityPotionEffectEventActionStruct<'mc>, + }, + Cleared { + inner: EntityPotionEffectEventActionStruct<'mc>, + }, + Removed { + inner: EntityPotionEffectEventActionStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for EntityPotionEffectEventAction<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + EntityPotionEffectEventAction::Added { .. } => f.write_str("ADDED"), + EntityPotionEffectEventAction::Changed { .. } => f.write_str("CHANGED"), + EntityPotionEffectEventAction::Cleared { .. } => f.write_str("CLEARED"), + EntityPotionEffectEventAction::Removed { .. } => f.write_str("REMOVED"), + } + } +} +impl<'mc> std::ops::Deref for EntityPotionEffectEventAction<'mc> { + type Target = EntityPotionEffectEventActionStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + EntityPotionEffectEventAction::Added { inner } => inner, + EntityPotionEffectEventAction::Changed { inner } => inner, + EntityPotionEffectEventAction::Cleared { inner } => inner, + EntityPotionEffectEventAction::Removed { inner } => inner, + } } } @@ -13377,6 +16129,19 @@ impl<'mc> EntityPotionEffectEventAction<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "ADDED" => Ok(EntityPotionEffectEventAction::Added { + inner: EntityPotionEffectEventActionStruct::from_raw(env, obj)?, + }), + "CHANGED" => Ok(EntityPotionEffectEventAction::Changed { + inner: EntityPotionEffectEventActionStruct::from_raw(env, obj)?, + }), + "CLEARED" => Ok(EntityPotionEffectEventAction::Cleared { + inner: EntityPotionEffectEventActionStruct::from_raw(env, obj)?, + }), + "REMOVED" => Ok(EntityPotionEffectEventAction::Removed { + inner: EntityPotionEffectEventActionStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -13390,10 +16155,20 @@ pub struct EntityPotionEffectEventActionStruct<'mc>( impl<'mc> JNIRaw<'mc> for EntityPotionEffectEventAction<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Added { inner } => inner.0.clone(), + Self::Changed { inner } => inner.0.clone(), + Self::Cleared { inner } => inner.0.clone(), + Self::Removed { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Added { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Changed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Cleared { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Removed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for EntityPotionEffectEventAction<'mc> { @@ -13425,6 +16200,18 @@ impl<'mc> JNIInstantiatable<'mc> for EntityPotionEffectEventAction<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "ADDED" => Ok(EntityPotionEffectEventAction::Added { + inner: EntityPotionEffectEventActionStruct::from_raw(env, obj)?, + }), + "CHANGED" => Ok(EntityPotionEffectEventAction::Changed { + inner: EntityPotionEffectEventActionStruct::from_raw(env, obj)?, + }), + "CLEARED" => Ok(EntityPotionEffectEventAction::Cleared { + inner: EntityPotionEffectEventActionStruct::from_raw(env, obj)?, + }), + "REMOVED" => Ok(EntityPotionEffectEventAction::Removed { + inner: EntityPotionEffectEventActionStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -13485,10 +16272,146 @@ impl<'mc> EntityPotionEffectEventActionStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum EntityPotionEffectEventCause<'mc> {} +pub enum EntityPotionEffectEventCause<'mc> { + AreaEffectCloud { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, + Arrow { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, + Attack { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, + Axolotl { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, + Beacon { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, + Command { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, + Conduit { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, + Conversion { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, + Death { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, + Dolphin { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, + Expiration { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, + Food { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, + Illusion { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, + Milk { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, + PatrolCaptain { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, + Plugin { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, + PotionDrink { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, + PotionSplash { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, + SpiderSpawn { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, + Totem { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, + TurtleHelmet { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, + Unknown { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, + VillagerTrade { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, + Warden { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, + WitherRose { + inner: EntityPotionEffectEventCauseStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for EntityPotionEffectEventCause<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + EntityPotionEffectEventCause::AreaEffectCloud { .. } => { + f.write_str("AREA_EFFECT_CLOUD") + } + EntityPotionEffectEventCause::Arrow { .. } => f.write_str("ARROW"), + EntityPotionEffectEventCause::Attack { .. } => f.write_str("ATTACK"), + EntityPotionEffectEventCause::Axolotl { .. } => f.write_str("AXOLOTL"), + EntityPotionEffectEventCause::Beacon { .. } => f.write_str("BEACON"), + EntityPotionEffectEventCause::Command { .. } => f.write_str("COMMAND"), + EntityPotionEffectEventCause::Conduit { .. } => f.write_str("CONDUIT"), + EntityPotionEffectEventCause::Conversion { .. } => f.write_str("CONVERSION"), + EntityPotionEffectEventCause::Death { .. } => f.write_str("DEATH"), + EntityPotionEffectEventCause::Dolphin { .. } => f.write_str("DOLPHIN"), + EntityPotionEffectEventCause::Expiration { .. } => f.write_str("EXPIRATION"), + EntityPotionEffectEventCause::Food { .. } => f.write_str("FOOD"), + EntityPotionEffectEventCause::Illusion { .. } => f.write_str("ILLUSION"), + EntityPotionEffectEventCause::Milk { .. } => f.write_str("MILK"), + EntityPotionEffectEventCause::PatrolCaptain { .. } => f.write_str("PATROL_CAPTAIN"), + EntityPotionEffectEventCause::Plugin { .. } => f.write_str("PLUGIN"), + EntityPotionEffectEventCause::PotionDrink { .. } => f.write_str("POTION_DRINK"), + EntityPotionEffectEventCause::PotionSplash { .. } => f.write_str("POTION_SPLASH"), + EntityPotionEffectEventCause::SpiderSpawn { .. } => f.write_str("SPIDER_SPAWN"), + EntityPotionEffectEventCause::Totem { .. } => f.write_str("TOTEM"), + EntityPotionEffectEventCause::TurtleHelmet { .. } => f.write_str("TURTLE_HELMET"), + EntityPotionEffectEventCause::Unknown { .. } => f.write_str("UNKNOWN"), + EntityPotionEffectEventCause::VillagerTrade { .. } => f.write_str("VILLAGER_TRADE"), + EntityPotionEffectEventCause::Warden { .. } => f.write_str("WARDEN"), + EntityPotionEffectEventCause::WitherRose { .. } => f.write_str("WITHER_ROSE"), + } + } +} +impl<'mc> std::ops::Deref for EntityPotionEffectEventCause<'mc> { + type Target = EntityPotionEffectEventCauseStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + EntityPotionEffectEventCause::AreaEffectCloud { inner } => inner, + EntityPotionEffectEventCause::Arrow { inner } => inner, + EntityPotionEffectEventCause::Attack { inner } => inner, + EntityPotionEffectEventCause::Axolotl { inner } => inner, + EntityPotionEffectEventCause::Beacon { inner } => inner, + EntityPotionEffectEventCause::Command { inner } => inner, + EntityPotionEffectEventCause::Conduit { inner } => inner, + EntityPotionEffectEventCause::Conversion { inner } => inner, + EntityPotionEffectEventCause::Death { inner } => inner, + EntityPotionEffectEventCause::Dolphin { inner } => inner, + EntityPotionEffectEventCause::Expiration { inner } => inner, + EntityPotionEffectEventCause::Food { inner } => inner, + EntityPotionEffectEventCause::Illusion { inner } => inner, + EntityPotionEffectEventCause::Milk { inner } => inner, + EntityPotionEffectEventCause::PatrolCaptain { inner } => inner, + EntityPotionEffectEventCause::Plugin { inner } => inner, + EntityPotionEffectEventCause::PotionDrink { inner } => inner, + EntityPotionEffectEventCause::PotionSplash { inner } => inner, + EntityPotionEffectEventCause::SpiderSpawn { inner } => inner, + EntityPotionEffectEventCause::Totem { inner } => inner, + EntityPotionEffectEventCause::TurtleHelmet { inner } => inner, + EntityPotionEffectEventCause::Unknown { inner } => inner, + EntityPotionEffectEventCause::VillagerTrade { inner } => inner, + EntityPotionEffectEventCause::Warden { inner } => inner, + EntityPotionEffectEventCause::WitherRose { inner } => inner, + } } } @@ -13515,6 +16438,82 @@ impl<'mc> EntityPotionEffectEventCause<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "AREA_EFFECT_CLOUD" => Ok(EntityPotionEffectEventCause::AreaEffectCloud { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "ARROW" => Ok(EntityPotionEffectEventCause::Arrow { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "ATTACK" => Ok(EntityPotionEffectEventCause::Attack { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "AXOLOTL" => Ok(EntityPotionEffectEventCause::Axolotl { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "BEACON" => Ok(EntityPotionEffectEventCause::Beacon { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "COMMAND" => Ok(EntityPotionEffectEventCause::Command { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "CONDUIT" => Ok(EntityPotionEffectEventCause::Conduit { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "CONVERSION" => Ok(EntityPotionEffectEventCause::Conversion { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "DEATH" => Ok(EntityPotionEffectEventCause::Death { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "DOLPHIN" => Ok(EntityPotionEffectEventCause::Dolphin { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "EXPIRATION" => Ok(EntityPotionEffectEventCause::Expiration { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "FOOD" => Ok(EntityPotionEffectEventCause::Food { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "ILLUSION" => Ok(EntityPotionEffectEventCause::Illusion { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "MILK" => Ok(EntityPotionEffectEventCause::Milk { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "PATROL_CAPTAIN" => Ok(EntityPotionEffectEventCause::PatrolCaptain { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "PLUGIN" => Ok(EntityPotionEffectEventCause::Plugin { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "POTION_DRINK" => Ok(EntityPotionEffectEventCause::PotionDrink { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "POTION_SPLASH" => Ok(EntityPotionEffectEventCause::PotionSplash { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "SPIDER_SPAWN" => Ok(EntityPotionEffectEventCause::SpiderSpawn { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "TOTEM" => Ok(EntityPotionEffectEventCause::Totem { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "TURTLE_HELMET" => Ok(EntityPotionEffectEventCause::TurtleHelmet { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(EntityPotionEffectEventCause::Unknown { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "VILLAGER_TRADE" => Ok(EntityPotionEffectEventCause::VillagerTrade { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "WARDEN" => Ok(EntityPotionEffectEventCause::Warden { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "WITHER_ROSE" => Ok(EntityPotionEffectEventCause::WitherRose { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -13528,10 +16527,82 @@ pub struct EntityPotionEffectEventCauseStruct<'mc>( impl<'mc> JNIRaw<'mc> for EntityPotionEffectEventCause<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::AreaEffectCloud { inner } => inner.0.clone(), + Self::Arrow { inner } => inner.0.clone(), + Self::Attack { inner } => inner.0.clone(), + Self::Axolotl { inner } => inner.0.clone(), + Self::Beacon { inner } => inner.0.clone(), + Self::Command { inner } => inner.0.clone(), + Self::Conduit { inner } => inner.0.clone(), + Self::Conversion { inner } => inner.0.clone(), + Self::Death { inner } => inner.0.clone(), + Self::Dolphin { inner } => inner.0.clone(), + Self::Expiration { inner } => inner.0.clone(), + Self::Food { inner } => inner.0.clone(), + Self::Illusion { inner } => inner.0.clone(), + Self::Milk { inner } => inner.0.clone(), + Self::PatrolCaptain { inner } => inner.0.clone(), + Self::Plugin { inner } => inner.0.clone(), + Self::PotionDrink { inner } => inner.0.clone(), + Self::PotionSplash { inner } => inner.0.clone(), + Self::SpiderSpawn { inner } => inner.0.clone(), + Self::Totem { inner } => inner.0.clone(), + Self::TurtleHelmet { inner } => inner.0.clone(), + Self::Unknown { inner } => inner.0.clone(), + Self::VillagerTrade { inner } => inner.0.clone(), + Self::Warden { inner } => inner.0.clone(), + Self::WitherRose { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::AreaEffectCloud { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Arrow { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Attack { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Axolotl { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Beacon { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Command { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Conduit { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Conversion { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Death { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Dolphin { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Expiration { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Food { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Illusion { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Milk { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PatrolCaptain { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Plugin { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PotionDrink { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PotionSplash { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SpiderSpawn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Totem { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::TurtleHelmet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Unknown { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::VillagerTrade { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Warden { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::WitherRose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } impl<'mc> JNIInstantiatable<'mc> for EntityPotionEffectEventCause<'mc> { @@ -13563,6 +16634,81 @@ impl<'mc> JNIInstantiatable<'mc> for EntityPotionEffectEventCause<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "AREA_EFFECT_CLOUD" => Ok(EntityPotionEffectEventCause::AreaEffectCloud { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "ARROW" => Ok(EntityPotionEffectEventCause::Arrow { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "ATTACK" => Ok(EntityPotionEffectEventCause::Attack { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "AXOLOTL" => Ok(EntityPotionEffectEventCause::Axolotl { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "BEACON" => Ok(EntityPotionEffectEventCause::Beacon { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "COMMAND" => Ok(EntityPotionEffectEventCause::Command { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "CONDUIT" => Ok(EntityPotionEffectEventCause::Conduit { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "CONVERSION" => Ok(EntityPotionEffectEventCause::Conversion { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "DEATH" => Ok(EntityPotionEffectEventCause::Death { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "DOLPHIN" => Ok(EntityPotionEffectEventCause::Dolphin { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "EXPIRATION" => Ok(EntityPotionEffectEventCause::Expiration { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "FOOD" => Ok(EntityPotionEffectEventCause::Food { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "ILLUSION" => Ok(EntityPotionEffectEventCause::Illusion { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "MILK" => Ok(EntityPotionEffectEventCause::Milk { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "PATROL_CAPTAIN" => Ok(EntityPotionEffectEventCause::PatrolCaptain { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "PLUGIN" => Ok(EntityPotionEffectEventCause::Plugin { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "POTION_DRINK" => Ok(EntityPotionEffectEventCause::PotionDrink { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "POTION_SPLASH" => Ok(EntityPotionEffectEventCause::PotionSplash { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "SPIDER_SPAWN" => Ok(EntityPotionEffectEventCause::SpiderSpawn { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "TOTEM" => Ok(EntityPotionEffectEventCause::Totem { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "TURTLE_HELMET" => Ok(EntityPotionEffectEventCause::TurtleHelmet { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(EntityPotionEffectEventCause::Unknown { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "VILLAGER_TRADE" => Ok(EntityPotionEffectEventCause::VillagerTrade { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "WARDEN" => Ok(EntityPotionEffectEventCause::Warden { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), + "WITHER_ROSE" => Ok(EntityPotionEffectEventCause::WitherRose { + inner: EntityPotionEffectEventCauseStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -14124,177 +17270,6 @@ impl<'mc> Into> } } #[repr(C)] -pub struct EntityTargetLivingEntityEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for EntityTargetLivingEntityEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for EntityTargetLivingEntityEvent<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate EntityTargetLivingEntityEvent from null object." - ) - .into()); - } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/event/entity/EntityTargetLivingEntityEvent", - )?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityTargetLivingEntityEvent object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> EntityTargetLivingEntityEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - entity: impl Into>, - target: impl Into>, - reason: impl Into>, - ) -> Result, Box> - { - let sig = String::from("(Lorg/bukkit/entity/Entity;Lorg/bukkit/entity/LivingEntity;Lorg/bukkit/event/entity/EntityTargetEvent/TargetReason;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(reason.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/event/entity/EntityTargetLivingEntityEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = jni.translate_error_no_gen(res)?; - crate::event::entity::EntityTargetLivingEntityEvent::from_raw(&jni, res) - } - - pub fn target( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/LivingEntity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTarget", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::LivingEntity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Set the Entity that you want the mob to target. - /// - /// It is possible to be null, null will cause the entity to be - /// target-less. - /// - /// Must be a LivingEntity, or null. - pub fn set_target( - &self, - target: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(target.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTarget", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - // SUPER CLASS: org.bukkit.event.entity.EntityTargetEvent ( ['getTarget', 'setTarget']) - - pub fn is_cancelled(&self) -> Result> { - let temp_clone = crate::event::entity::EntityTargetEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityTargetEvent = temp_clone.into(); - real.is_cancelled() - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let temp_clone = crate::event::entity::EntityTargetEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityTargetEvent = temp_clone.into(); - real.set_cancelled(cancel) - } - /// Returns the reason for the targeting - pub fn reason( - &self, - ) -> Result, Box> - { - let temp_clone = crate::event::entity::EntityTargetEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::entity::EntityTargetEvent = temp_clone.into(); - real.reason() - } - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn handler_list( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - crate::event::entity::EntityTargetEvent::handler_list(jni) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> - for EntityTargetLivingEntityEvent<'mc> -{ - fn into(self) -> crate::event::entity::EntityTargetEvent<'mc> { - crate::event::entity::EntityTargetEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting EntityTargetLivingEntityEvent into crate::event::entity::EntityTargetEvent") - } -} -#[repr(C)] pub struct PigZapEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, @@ -14935,9 +17910,9 @@ impl<'mc> EntityExplodeEvent<'mc> { location: impl Into>, blocks: Vec>, val_yield: f32, + result: impl Into>, ) -> Result, Box> { - let sig = - String::from("(Lorg/bukkit/entity/Entity;Lorg/bukkit/Location;Ljava/util/List;F)V"); + let sig = String::from("(Lorg/bukkit/entity/Entity;Lorg/bukkit/Location;Ljava/util/List;FLorg/bukkit/ExplosionResult;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(what.into().jni_object().clone()) }); @@ -14956,6 +17931,9 @@ impl<'mc> EntityExplodeEvent<'mc> { } let val_3 = jni::objects::JValueGen::Object(raw_val_3); let val_4 = jni::objects::JValueGen::Float(val_yield); + let val_5 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(result.into().jni_object().clone()) + }); let cls = jni.find_class("org/bukkit/event/entity/EntityExplodeEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( @@ -14966,6 +17944,7 @@ impl<'mc> EntityExplodeEvent<'mc> { jni::objects::JValueGen::from(val_2), jni::objects::JValueGen::from(val_3), jni::objects::JValueGen::from(val_4), + jni::objects::JValueGen::from(val_5), ], ); let res = jni.translate_error_no_gen(res)?; @@ -14993,6 +17972,22 @@ impl<'mc> EntityExplodeEvent<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } + /// Returns the result of the explosion if it is not cancelled. + pub fn explosion_result( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/ExplosionResult;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getExplosionResult", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::ExplosionResult::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } /// Returns the list of blocks that would have been removed or were removed /// from the explosion event. pub fn block_list(&self) -> Result>, Box> { @@ -15069,7 +18064,7 @@ impl<'mc> EntityExplodeEvent<'mc> { let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['isCancelled', 'setCancelled', 'blockList', 'getLocation', 'getYield', 'setYield', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.entity.EntityEvent ( ['isCancelled', 'setCancelled', 'getExplosionResult', 'blockList', 'getLocation', 'getYield', 'setYield', 'getHandlers', 'getHandlerList']) /// Returns the Entity involved in this event pub fn entity(&self) -> Result, Box> { let temp_clone = crate::event::entity::EntityEvent::from_raw(&self.0, unsafe { @@ -15309,6 +18304,8 @@ impl<'mc> EntityPortalEvent<'mc> { from: impl Into>, to: impl Into>, search_radius: std::option::Option, + can_create_portal: std::option::Option, + creation_radius: std::option::Option, ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); @@ -15332,6 +18329,16 @@ impl<'mc> EntityPortalEvent<'mc> { let val_4 = jni::objects::JValueGen::Int(a); args.push(val_4); } + if let Some(a) = can_create_portal { + sig += "Z"; + let val_5 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_5); + } + if let Some(a) = creation_radius { + sig += "I"; + let val_6 = jni::objects::JValueGen::Int(a); + args.push(val_6); + } sig += ")V"; let cls = jni.find_class("org/bukkit/event/entity/EntityPortalEvent"); let cls = jni.translate_error_with_class(cls)?; @@ -15361,6 +18368,74 @@ impl<'mc> EntityPortalEvent<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } + /// Returns whether the server will attempt to create a destination portal or + /// not. + pub fn can_create_portal(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCanCreatePortal", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the server should attempt to create a destination portal or + /// not. + pub fn set_can_create_portal( + &self, + can_create_portal: bool, + ) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(can_create_portal.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCanCreatePortal", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets the maximum radius the world is searched for a free space from the + /// given location. + /// If enough free space is found then the portal will be created there, if + /// not it will force create with air-space at the target location. + /// Does not apply to end portal target platforms which will always appear at + /// the target location. + pub fn set_creation_radius( + &self, + creation_radius: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(creation_radius); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCreationRadius", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the maximum radius the world is searched for a free space from the + /// given location. + /// If enough free space is found then the portal will be created there, if + /// not it will force create with air-space at the target location. + /// Does not apply to end portal target platforms which will always appear at + /// the target location. + pub fn creation_radius(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCreationRadius", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -15384,7 +18459,7 @@ impl<'mc> EntityPortalEvent<'mc> { let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.entity.EntityTeleportEvent ( ['setSearchRadius', 'getSearchRadius', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.entity.EntityTeleportEvent ( ['setSearchRadius', 'getSearchRadius', 'getCanCreatePortal', 'setCanCreatePortal', 'setCreationRadius', 'getCreationRadius', 'getHandlers', 'getHandlerList']) pub fn is_cancelled(&self) -> Result> { let temp_clone = crate::event::entity::EntityTeleportEvent::from_raw(&self.0, unsafe { diff --git a/blackboxmc-rs-bukkit/src/event/hanging/mod.rs b/blackboxmc-rs-bukkit/src/event/hanging/mod.rs index 8792b75..c22d877 100644 --- a/blackboxmc-rs-bukkit/src/event/hanging/mod.rs +++ b/blackboxmc-rs-bukkit/src/event/hanging/mod.rs @@ -152,10 +152,44 @@ impl<'mc> Into> for HangingBreakEvent<' .expect("Error converting HangingBreakEvent into crate::event::hanging::HangingEvent") } } -pub enum HangingBreakEventRemoveCause<'mc> {} +pub enum HangingBreakEventRemoveCause<'mc> { + Entity { + inner: HangingBreakEventRemoveCauseStruct<'mc>, + }, + Explosion { + inner: HangingBreakEventRemoveCauseStruct<'mc>, + }, + Obstruction { + inner: HangingBreakEventRemoveCauseStruct<'mc>, + }, + Physics { + inner: HangingBreakEventRemoveCauseStruct<'mc>, + }, + Default { + inner: HangingBreakEventRemoveCauseStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for HangingBreakEventRemoveCause<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + HangingBreakEventRemoveCause::Entity { .. } => f.write_str("ENTITY"), + HangingBreakEventRemoveCause::Explosion { .. } => f.write_str("EXPLOSION"), + HangingBreakEventRemoveCause::Obstruction { .. } => f.write_str("OBSTRUCTION"), + HangingBreakEventRemoveCause::Physics { .. } => f.write_str("PHYSICS"), + HangingBreakEventRemoveCause::Default { .. } => f.write_str("DEFAULT"), + } + } +} +impl<'mc> std::ops::Deref for HangingBreakEventRemoveCause<'mc> { + type Target = HangingBreakEventRemoveCauseStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + HangingBreakEventRemoveCause::Entity { inner } => inner, + HangingBreakEventRemoveCause::Explosion { inner } => inner, + HangingBreakEventRemoveCause::Obstruction { inner } => inner, + HangingBreakEventRemoveCause::Physics { inner } => inner, + HangingBreakEventRemoveCause::Default { inner } => inner, + } } } @@ -182,6 +216,22 @@ impl<'mc> HangingBreakEventRemoveCause<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "ENTITY" => Ok(HangingBreakEventRemoveCause::Entity { + inner: HangingBreakEventRemoveCauseStruct::from_raw(env, obj)?, + }), + "EXPLOSION" => Ok(HangingBreakEventRemoveCause::Explosion { + inner: HangingBreakEventRemoveCauseStruct::from_raw(env, obj)?, + }), + "OBSTRUCTION" => Ok(HangingBreakEventRemoveCause::Obstruction { + inner: HangingBreakEventRemoveCauseStruct::from_raw(env, obj)?, + }), + "PHYSICS" => Ok(HangingBreakEventRemoveCause::Physics { + inner: HangingBreakEventRemoveCauseStruct::from_raw(env, obj)?, + }), + "DEFAULT" => Ok(HangingBreakEventRemoveCause::Default { + inner: HangingBreakEventRemoveCauseStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -195,10 +245,26 @@ pub struct HangingBreakEventRemoveCauseStruct<'mc>( impl<'mc> JNIRaw<'mc> for HangingBreakEventRemoveCause<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Entity { inner } => inner.0.clone(), + Self::Explosion { inner } => inner.0.clone(), + Self::Obstruction { inner } => inner.0.clone(), + Self::Physics { inner } => inner.0.clone(), + Self::Default { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Entity { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Explosion { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Obstruction { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Physics { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Default { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for HangingBreakEventRemoveCause<'mc> { @@ -230,6 +296,21 @@ impl<'mc> JNIInstantiatable<'mc> for HangingBreakEventRemoveCause<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "ENTITY" => Ok(HangingBreakEventRemoveCause::Entity { + inner: HangingBreakEventRemoveCauseStruct::from_raw(env, obj)?, + }), + "EXPLOSION" => Ok(HangingBreakEventRemoveCause::Explosion { + inner: HangingBreakEventRemoveCauseStruct::from_raw(env, obj)?, + }), + "OBSTRUCTION" => Ok(HangingBreakEventRemoveCause::Obstruction { + inner: HangingBreakEventRemoveCauseStruct::from_raw(env, obj)?, + }), + "PHYSICS" => Ok(HangingBreakEventRemoveCause::Physics { + inner: HangingBreakEventRemoveCauseStruct::from_raw(env, obj)?, + }), + "DEFAULT" => Ok(HangingBreakEventRemoveCause::Default { + inner: HangingBreakEventRemoveCauseStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } diff --git a/blackboxmc-rs-bukkit/src/event/inventory/mod.rs b/blackboxmc-rs-bukkit/src/event/inventory/mod.rs index 58201b6..728921f 100644 --- a/blackboxmc-rs-bukkit/src/event/inventory/mod.rs +++ b/blackboxmc-rs-bukkit/src/event/inventory/mod.rs @@ -2,10 +2,109 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; -pub enum InventoryType<'mc> {} +pub enum InventoryType<'mc> { + Chest { inner: InventoryTypeStruct<'mc> }, + Dispenser { inner: InventoryTypeStruct<'mc> }, + Dropper { inner: InventoryTypeStruct<'mc> }, + Furnace { inner: InventoryTypeStruct<'mc> }, + Workbench { inner: InventoryTypeStruct<'mc> }, + Crafting { inner: InventoryTypeStruct<'mc> }, + Enchanting { inner: InventoryTypeStruct<'mc> }, + Brewing { inner: InventoryTypeStruct<'mc> }, + Player { inner: InventoryTypeStruct<'mc> }, + Creative { inner: InventoryTypeStruct<'mc> }, + Merchant { inner: InventoryTypeStruct<'mc> }, + EnderChest { inner: InventoryTypeStruct<'mc> }, + Anvil { inner: InventoryTypeStruct<'mc> }, + Smithing { inner: InventoryTypeStruct<'mc> }, + Beacon { inner: InventoryTypeStruct<'mc> }, + Hopper { inner: InventoryTypeStruct<'mc> }, + ShulkerBox { inner: InventoryTypeStruct<'mc> }, + Barrel { inner: InventoryTypeStruct<'mc> }, + BlastFurnace { inner: InventoryTypeStruct<'mc> }, + Lectern { inner: InventoryTypeStruct<'mc> }, + Smoker { inner: InventoryTypeStruct<'mc> }, + Loom { inner: InventoryTypeStruct<'mc> }, + Cartography { inner: InventoryTypeStruct<'mc> }, + Grindstone { inner: InventoryTypeStruct<'mc> }, + Stonecutter { inner: InventoryTypeStruct<'mc> }, + Composter { inner: InventoryTypeStruct<'mc> }, + ChiseledBookshelf { inner: InventoryTypeStruct<'mc> }, + Jukebox { inner: InventoryTypeStruct<'mc> }, + Crafter { inner: InventoryTypeStruct<'mc> }, + SmithingNew { inner: InventoryTypeStruct<'mc> }, +} impl<'mc> std::fmt::Display for InventoryType<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + InventoryType::Chest { .. } => f.write_str("CHEST"), + InventoryType::Dispenser { .. } => f.write_str("DISPENSER"), + InventoryType::Dropper { .. } => f.write_str("DROPPER"), + InventoryType::Furnace { .. } => f.write_str("FURNACE"), + InventoryType::Workbench { .. } => f.write_str("WORKBENCH"), + InventoryType::Crafting { .. } => f.write_str("CRAFTING"), + InventoryType::Enchanting { .. } => f.write_str("ENCHANTING"), + InventoryType::Brewing { .. } => f.write_str("BREWING"), + InventoryType::Player { .. } => f.write_str("PLAYER"), + InventoryType::Creative { .. } => f.write_str("CREATIVE"), + InventoryType::Merchant { .. } => f.write_str("MERCHANT"), + InventoryType::EnderChest { .. } => f.write_str("ENDER_CHEST"), + InventoryType::Anvil { .. } => f.write_str("ANVIL"), + InventoryType::Smithing { .. } => f.write_str("SMITHING"), + InventoryType::Beacon { .. } => f.write_str("BEACON"), + InventoryType::Hopper { .. } => f.write_str("HOPPER"), + InventoryType::ShulkerBox { .. } => f.write_str("SHULKER_BOX"), + InventoryType::Barrel { .. } => f.write_str("BARREL"), + InventoryType::BlastFurnace { .. } => f.write_str("BLAST_FURNACE"), + InventoryType::Lectern { .. } => f.write_str("LECTERN"), + InventoryType::Smoker { .. } => f.write_str("SMOKER"), + InventoryType::Loom { .. } => f.write_str("LOOM"), + InventoryType::Cartography { .. } => f.write_str("CARTOGRAPHY"), + InventoryType::Grindstone { .. } => f.write_str("GRINDSTONE"), + InventoryType::Stonecutter { .. } => f.write_str("STONECUTTER"), + InventoryType::Composter { .. } => f.write_str("COMPOSTER"), + InventoryType::ChiseledBookshelf { .. } => f.write_str("CHISELED_BOOKSHELF"), + InventoryType::Jukebox { .. } => f.write_str("JUKEBOX"), + InventoryType::Crafter { .. } => f.write_str("CRAFTER"), + InventoryType::SmithingNew { .. } => f.write_str("SMITHING_NEW"), + } + } +} +impl<'mc> std::ops::Deref for InventoryType<'mc> { + type Target = InventoryTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + InventoryType::Chest { inner } => inner, + InventoryType::Dispenser { inner } => inner, + InventoryType::Dropper { inner } => inner, + InventoryType::Furnace { inner } => inner, + InventoryType::Workbench { inner } => inner, + InventoryType::Crafting { inner } => inner, + InventoryType::Enchanting { inner } => inner, + InventoryType::Brewing { inner } => inner, + InventoryType::Player { inner } => inner, + InventoryType::Creative { inner } => inner, + InventoryType::Merchant { inner } => inner, + InventoryType::EnderChest { inner } => inner, + InventoryType::Anvil { inner } => inner, + InventoryType::Smithing { inner } => inner, + InventoryType::Beacon { inner } => inner, + InventoryType::Hopper { inner } => inner, + InventoryType::ShulkerBox { inner } => inner, + InventoryType::Barrel { inner } => inner, + InventoryType::BlastFurnace { inner } => inner, + InventoryType::Lectern { inner } => inner, + InventoryType::Smoker { inner } => inner, + InventoryType::Loom { inner } => inner, + InventoryType::Cartography { inner } => inner, + InventoryType::Grindstone { inner } => inner, + InventoryType::Stonecutter { inner } => inner, + InventoryType::Composter { inner } => inner, + InventoryType::ChiseledBookshelf { inner } => inner, + InventoryType::Jukebox { inner } => inner, + InventoryType::Crafter { inner } => inner, + InventoryType::SmithingNew { inner } => inner, + } } } @@ -32,6 +131,97 @@ impl<'mc> InventoryType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "CHEST" => Ok(InventoryType::Chest { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "DISPENSER" => Ok(InventoryType::Dispenser { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "DROPPER" => Ok(InventoryType::Dropper { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "FURNACE" => Ok(InventoryType::Furnace { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "WORKBENCH" => Ok(InventoryType::Workbench { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "CRAFTING" => Ok(InventoryType::Crafting { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "ENCHANTING" => Ok(InventoryType::Enchanting { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "BREWING" => Ok(InventoryType::Brewing { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "PLAYER" => Ok(InventoryType::Player { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "CREATIVE" => Ok(InventoryType::Creative { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "MERCHANT" => Ok(InventoryType::Merchant { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "ENDER_CHEST" => Ok(InventoryType::EnderChest { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "ANVIL" => Ok(InventoryType::Anvil { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "SMITHING" => Ok(InventoryType::Smithing { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "BEACON" => Ok(InventoryType::Beacon { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "HOPPER" => Ok(InventoryType::Hopper { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "SHULKER_BOX" => Ok(InventoryType::ShulkerBox { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "BARREL" => Ok(InventoryType::Barrel { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "BLAST_FURNACE" => Ok(InventoryType::BlastFurnace { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "LECTERN" => Ok(InventoryType::Lectern { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "SMOKER" => Ok(InventoryType::Smoker { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "LOOM" => Ok(InventoryType::Loom { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "CARTOGRAPHY" => Ok(InventoryType::Cartography { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "GRINDSTONE" => Ok(InventoryType::Grindstone { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "STONECUTTER" => Ok(InventoryType::Stonecutter { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "COMPOSTER" => Ok(InventoryType::Composter { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "CHISELED_BOOKSHELF" => Ok(InventoryType::ChiseledBookshelf { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "JUKEBOX" => Ok(InventoryType::Jukebox { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "CRAFTER" => Ok(InventoryType::Crafter { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "SMITHING_NEW" => Ok(InventoryType::SmithingNew { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -45,10 +235,96 @@ pub struct InventoryTypeStruct<'mc>( impl<'mc> JNIRaw<'mc> for InventoryType<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Chest { inner } => inner.0.clone(), + Self::Dispenser { inner } => inner.0.clone(), + Self::Dropper { inner } => inner.0.clone(), + Self::Furnace { inner } => inner.0.clone(), + Self::Workbench { inner } => inner.0.clone(), + Self::Crafting { inner } => inner.0.clone(), + Self::Enchanting { inner } => inner.0.clone(), + Self::Brewing { inner } => inner.0.clone(), + Self::Player { inner } => inner.0.clone(), + Self::Creative { inner } => inner.0.clone(), + Self::Merchant { inner } => inner.0.clone(), + Self::EnderChest { inner } => inner.0.clone(), + Self::Anvil { inner } => inner.0.clone(), + Self::Smithing { inner } => inner.0.clone(), + Self::Beacon { inner } => inner.0.clone(), + Self::Hopper { inner } => inner.0.clone(), + Self::ShulkerBox { inner } => inner.0.clone(), + Self::Barrel { inner } => inner.0.clone(), + Self::BlastFurnace { inner } => inner.0.clone(), + Self::Lectern { inner } => inner.0.clone(), + Self::Smoker { inner } => inner.0.clone(), + Self::Loom { inner } => inner.0.clone(), + Self::Cartography { inner } => inner.0.clone(), + Self::Grindstone { inner } => inner.0.clone(), + Self::Stonecutter { inner } => inner.0.clone(), + Self::Composter { inner } => inner.0.clone(), + Self::ChiseledBookshelf { inner } => inner.0.clone(), + Self::Jukebox { inner } => inner.0.clone(), + Self::Crafter { inner } => inner.0.clone(), + Self::SmithingNew { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Chest { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Dispenser { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Dropper { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Furnace { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Workbench { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Crafting { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Enchanting { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Brewing { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Player { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Creative { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Merchant { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::EnderChest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Anvil { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Smithing { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Beacon { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Hopper { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Barrel { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BlastFurnace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Lectern { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Smoker { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Loom { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Cartography { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Grindstone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Stonecutter { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Composter { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChiseledBookshelf { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Jukebox { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Crafter { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SmithingNew { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } impl<'mc> JNIInstantiatable<'mc> for InventoryType<'mc> { @@ -74,6 +350,96 @@ impl<'mc> JNIInstantiatable<'mc> for InventoryType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "CHEST" => Ok(InventoryType::Chest { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "DISPENSER" => Ok(InventoryType::Dispenser { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "DROPPER" => Ok(InventoryType::Dropper { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "FURNACE" => Ok(InventoryType::Furnace { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "WORKBENCH" => Ok(InventoryType::Workbench { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "CRAFTING" => Ok(InventoryType::Crafting { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "ENCHANTING" => Ok(InventoryType::Enchanting { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "BREWING" => Ok(InventoryType::Brewing { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "PLAYER" => Ok(InventoryType::Player { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "CREATIVE" => Ok(InventoryType::Creative { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "MERCHANT" => Ok(InventoryType::Merchant { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "ENDER_CHEST" => Ok(InventoryType::EnderChest { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "ANVIL" => Ok(InventoryType::Anvil { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "SMITHING" => Ok(InventoryType::Smithing { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "BEACON" => Ok(InventoryType::Beacon { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "HOPPER" => Ok(InventoryType::Hopper { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "SHULKER_BOX" => Ok(InventoryType::ShulkerBox { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "BARREL" => Ok(InventoryType::Barrel { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "BLAST_FURNACE" => Ok(InventoryType::BlastFurnace { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "LECTERN" => Ok(InventoryType::Lectern { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "SMOKER" => Ok(InventoryType::Smoker { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "LOOM" => Ok(InventoryType::Loom { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "CARTOGRAPHY" => Ok(InventoryType::Cartography { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "GRINDSTONE" => Ok(InventoryType::Grindstone { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "STONECUTTER" => Ok(InventoryType::Stonecutter { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "COMPOSTER" => Ok(InventoryType::Composter { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "CHISELED_BOOKSHELF" => Ok(InventoryType::ChiseledBookshelf { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "JUKEBOX" => Ok(InventoryType::Jukebox { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "CRAFTER" => Ok(InventoryType::Crafter { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), + "SMITHING_NEW" => Ok(InventoryType::SmithingNew { + inner: InventoryTypeStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -145,6 +511,35 @@ impl<'mc> InventoryTypeStruct<'mc> { .to_string_lossy() .to_string()) } + /// Gets the corresponding {@link MenuType} of this InventoryType. + /// + /// Not all InventoryType correspond to a {@link MenuType}. These + /// InventoryTypes are also not creatable. If this method returns null, + /// {@link #isCreatable()} will return false, with the exception of + /// {@link #MERCHANT}. + /// + /// As well as not necessarily corresponding to a {@link MenuType} some + /// InventoryType correspond to the same {@link MenuType}, including: + ///
    + ///
  • Dropper, Dispenser + ///
  • ShulkerBox, Barrel, Chest + ///
+ pub fn menu_type( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/MenuType;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMenuType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::MenuType::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } /// Denotes that this InventoryType can be created via the normal /// {@link org.bukkit.Bukkit#createInventory} methods. pub fn is_creatable(&self) -> Result> { @@ -161,10 +556,54 @@ impl<'mc> InventoryTypeStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum InventoryTypeSlotType<'mc> {} +pub enum InventoryTypeSlotType<'mc> { + Result { + inner: InventoryTypeSlotTypeStruct<'mc>, + }, + Crafting { + inner: InventoryTypeSlotTypeStruct<'mc>, + }, + Armor { + inner: InventoryTypeSlotTypeStruct<'mc>, + }, + Container { + inner: InventoryTypeSlotTypeStruct<'mc>, + }, + Quickbar { + inner: InventoryTypeSlotTypeStruct<'mc>, + }, + Outside { + inner: InventoryTypeSlotTypeStruct<'mc>, + }, + Fuel { + inner: InventoryTypeSlotTypeStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for InventoryTypeSlotType<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + InventoryTypeSlotType::Result { .. } => f.write_str("RESULT"), + InventoryTypeSlotType::Crafting { .. } => f.write_str("CRAFTING"), + InventoryTypeSlotType::Armor { .. } => f.write_str("ARMOR"), + InventoryTypeSlotType::Container { .. } => f.write_str("CONTAINER"), + InventoryTypeSlotType::Quickbar { .. } => f.write_str("QUICKBAR"), + InventoryTypeSlotType::Outside { .. } => f.write_str("OUTSIDE"), + InventoryTypeSlotType::Fuel { .. } => f.write_str("FUEL"), + } + } +} +impl<'mc> std::ops::Deref for InventoryTypeSlotType<'mc> { + type Target = InventoryTypeSlotTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + InventoryTypeSlotType::Result { inner } => inner, + InventoryTypeSlotType::Crafting { inner } => inner, + InventoryTypeSlotType::Armor { inner } => inner, + InventoryTypeSlotType::Container { inner } => inner, + InventoryTypeSlotType::Quickbar { inner } => inner, + InventoryTypeSlotType::Outside { inner } => inner, + InventoryTypeSlotType::Fuel { inner } => inner, + } } } @@ -191,6 +630,28 @@ impl<'mc> InventoryTypeSlotType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "RESULT" => Ok(InventoryTypeSlotType::Result { + inner: InventoryTypeSlotTypeStruct::from_raw(env, obj)?, + }), + "CRAFTING" => Ok(InventoryTypeSlotType::Crafting { + inner: InventoryTypeSlotTypeStruct::from_raw(env, obj)?, + }), + "ARMOR" => Ok(InventoryTypeSlotType::Armor { + inner: InventoryTypeSlotTypeStruct::from_raw(env, obj)?, + }), + "CONTAINER" => Ok(InventoryTypeSlotType::Container { + inner: InventoryTypeSlotTypeStruct::from_raw(env, obj)?, + }), + "QUICKBAR" => Ok(InventoryTypeSlotType::Quickbar { + inner: InventoryTypeSlotTypeStruct::from_raw(env, obj)?, + }), + "OUTSIDE" => Ok(InventoryTypeSlotType::Outside { + inner: InventoryTypeSlotTypeStruct::from_raw(env, obj)?, + }), + "FUEL" => Ok(InventoryTypeSlotType::Fuel { + inner: InventoryTypeSlotTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -204,10 +665,28 @@ pub struct InventoryTypeSlotTypeStruct<'mc>( impl<'mc> JNIRaw<'mc> for InventoryTypeSlotType<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Result { inner } => inner.0.clone(), + Self::Crafting { inner } => inner.0.clone(), + Self::Armor { inner } => inner.0.clone(), + Self::Container { inner } => inner.0.clone(), + Self::Quickbar { inner } => inner.0.clone(), + Self::Outside { inner } => inner.0.clone(), + Self::Fuel { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Result { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Crafting { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Armor { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Container { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Quickbar { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Outside { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Fuel { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for InventoryTypeSlotType<'mc> { @@ -237,6 +716,27 @@ impl<'mc> JNIInstantiatable<'mc> for InventoryTypeSlotType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "RESULT" => Ok(InventoryTypeSlotType::Result { + inner: InventoryTypeSlotTypeStruct::from_raw(env, obj)?, + }), + "CRAFTING" => Ok(InventoryTypeSlotType::Crafting { + inner: InventoryTypeSlotTypeStruct::from_raw(env, obj)?, + }), + "ARMOR" => Ok(InventoryTypeSlotType::Armor { + inner: InventoryTypeSlotTypeStruct::from_raw(env, obj)?, + }), + "CONTAINER" => Ok(InventoryTypeSlotType::Container { + inner: InventoryTypeSlotTypeStruct::from_raw(env, obj)?, + }), + "QUICKBAR" => Ok(InventoryTypeSlotType::Quickbar { + inner: InventoryTypeSlotTypeStruct::from_raw(env, obj)?, + }), + "OUTSIDE" => Ok(InventoryTypeSlotType::Outside { + inner: InventoryTypeSlotTypeStruct::from_raw(env, obj)?, + }), + "FUEL" => Ok(InventoryTypeSlotType::Fuel { + inner: InventoryTypeSlotTypeStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -296,12 +796,12 @@ impl<'mc> InventoryTypeSlotTypeStruct<'mc> { } } #[repr(C)] -pub struct FurnaceSmeltEvent<'mc>( +pub struct InventoryClickEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for FurnaceSmeltEvent<'mc> { +impl<'mc> JNIRaw<'mc> for InventoryClickEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -309,162 +809,21 @@ impl<'mc> JNIRaw<'mc> for FurnaceSmeltEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for FurnaceSmeltEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for InventoryClickEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate FurnaceSmeltEvent from null object.").into(), + eyre::eyre!("Tried to instantiate InventoryClickEvent from null object.").into(), ); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/inventory/FurnaceSmeltEvent")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a FurnaceSmeltEvent object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> FurnaceSmeltEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - furnace: impl Into>, - source: impl Into>, - result: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/inventory/ItemStack;Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(furnace.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(source.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(result.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/event/inventory/FurnaceSmeltEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = jni.translate_error_no_gen(res)?; - crate::event::inventory::FurnaceSmeltEvent::from_raw(&jni, res) - } - // SUPER CLASS: org.bukkit.event.block.BlockCookEvent ( []) - /// Gets the smelted ItemStack for this event - pub fn source(&self) -> Result, Box> { - let temp_clone = crate::event::block::BlockCookEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockCookEvent = temp_clone.into(); - real.source() - } - /// Gets the resultant ItemStack for this event - pub fn result(&self) -> Result, Box> { - let temp_clone = crate::event::block::BlockCookEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockCookEvent = temp_clone.into(); - real.result() - } - /// Sets the resultant ItemStack for this event - pub fn set_result( - &self, - result: impl Into>, - ) -> Result<(), Box> { - let temp_clone = crate::event::block::BlockCookEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockCookEvent = temp_clone.into(); - real.set_result(result) - } - - pub fn is_cancelled(&self) -> Result> { - let temp_clone = crate::event::block::BlockCookEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockCookEvent = temp_clone.into(); - real.is_cancelled() - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let temp_clone = crate::event::block::BlockCookEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockCookEvent = temp_clone.into(); - real.set_cancelled(cancel) - } - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn handler_list( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - crate::event::block::BlockCookEvent::handler_list(jni) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for FurnaceSmeltEvent<'mc> { - fn into(self) -> crate::event::block::BlockCookEvent<'mc> { - crate::event::block::BlockCookEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting FurnaceSmeltEvent into crate::event::block::BlockCookEvent") - } -} -#[repr(C)] -pub struct CraftItemEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for CraftItemEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for CraftItemEvent<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate CraftItemEvent from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/inventory/CraftItemEvent")?; + env.validate_name(&obj, "org/bukkit/event/inventory/InventoryClickEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a CraftItemEvent object, got {}", + "Invalid argument passed. Expected a InventoryClickEvent object, got {}", name ) .into()) @@ -474,201 +833,218 @@ impl<'mc> JNIInstantiatable<'mc> for CraftItemEvent<'mc> { } } -impl<'mc> CraftItemEvent<'mc> { +impl<'mc> InventoryClickEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - recipe: impl Into>, - what: impl Into>, + view: impl Into>, val_type: impl Into>, slot: i32, click: impl Into>, action: impl Into>, key: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/Recipe;"; + sig += "Lorg/bukkit/inventory/InventoryView;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) + jni::objects::JObject::from_raw(view.into().jni_object().clone()) }); args.push(val_1); - sig += "Lorg/bukkit/inventory/InventoryView;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(what.into().jni_object().clone()) - }); - args.push(val_2); sig += "Lorg/bukkit/event/inventory/InventoryType/SlotType;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { + let val_2 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); - args.push(val_3); + args.push(val_2); sig += "I"; - let val_4 = jni::objects::JValueGen::Int(slot); - args.push(val_4); + let val_3 = jni::objects::JValueGen::Int(slot); + args.push(val_3); sig += "Lorg/bukkit/event/inventory/ClickType;"; - let val_5 = jni::objects::JValueGen::Object(unsafe { + let val_4 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(click.into().jni_object().clone()) }); - args.push(val_5); + args.push(val_4); sig += "Lorg/bukkit/event/inventory/InventoryAction;"; - let val_6 = jni::objects::JValueGen::Object(unsafe { + let val_5 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(action.into().jni_object().clone()) }); - args.push(val_6); + args.push(val_5); if let Some(a) = key { sig += "I"; - let val_7 = jni::objects::JValueGen::Int(a); - args.push(val_7); + let val_6 = jni::objects::JValueGen::Int(a); + args.push(val_6); } sig += ")V"; - let cls = jni.find_class("org/bukkit/event/inventory/CraftItemEvent"); + let cls = jni.find_class("org/bukkit/event/inventory/InventoryClickEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::inventory::CraftItemEvent::from_raw(&jni, res) - } - - pub fn recipe(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Recipe;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getRecipe", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::Recipe::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + crate::event::inventory::InventoryClickEvent::from_raw(&jni, res) } - - pub fn inventory( + /// Gets the type of slot that was clicked. + pub fn slot_type( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/CraftingInventory;"); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType/SlotType;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSlotType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::CraftingInventory::from_raw(&self.jni_ref(), unsafe { + crate::event::inventory::InventoryTypeSlotType::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.event.inventory.InventoryClickEvent ( ['getRecipe', 'getInventory']) - /// Gets the type of slot that was clicked. - pub fn slot_type( - &self, - ) -> Result, Box> - { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.slot_type() - } - /// Gets the current ItemStack on the cursor. - pub fn cursor( + /// Gets the current ItemStack on the cursor. + pub fn cursor( &self, ) -> Result>, Box> { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.cursor() + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCursor", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } /// Gets the ItemStack currently in the clicked slot. pub fn current_item( &self, ) -> Result>, Box> { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.current_item() + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCurrentItem", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } /// Gets whether or not the ClickType for this event represents a right /// click. pub fn is_right_click(&self) -> Result> { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.is_right_click() + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isRightClick", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } /// Gets whether or not the ClickType for this event represents a left /// click. pub fn is_left_click(&self) -> Result> { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.is_left_click() + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isLeftClick", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } /// Gets whether the ClickType for this event indicates that the key was /// pressed down when the click was made. pub fn is_shift_click(&self) -> Result> { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.is_shift_click() + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isShiftClick", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } + #[deprecated] /// Sets the item on the cursor. pub fn set_cursor( &self, stack: impl Into>, ) -> Result<(), Box> { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.set_cursor(stack) + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(stack.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCursor", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } /// Sets the ItemStack currently in the clicked slot. pub fn set_current_item( &self, stack: impl Into>, ) -> Result<(), Box> { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.set_current_item(stack) + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(stack.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCurrentItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } /// Gets the inventory corresponding to the clicked slot. pub fn clicked_inventory( &self, ) -> Result>, Box> { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.clicked_inventory() + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getClickedInventory", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::Inventory::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } /// The slot number that was clicked, ready for passing to /// {@link Inventory#getItem(int)}. Note that there may be two slots with /// the same slot number, since a view links two different inventories. pub fn slot(&self) -> Result> { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.slot() + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSlot", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } /// The raw slot number clicked, ready for passing to {@link InventoryView /// #getItem(int)} This slot number is unique for the view. pub fn raw_slot(&self) -> Result> { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.raw_slot() + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRawSlot", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } /// If the ClickType is NUMBER_KEY, this method will return the index of /// the pressed key (0-8). pub fn hotbar_button(&self) -> Result> { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.hotbar_button() + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHotbarButton", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } /// Gets the InventoryAction that triggered this event. /// @@ -678,11 +1054,14 @@ impl<'mc> CraftItemEvent<'mc> { pub fn action( &self, ) -> Result, Box> { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.action() + let sig = String::from("()Lorg/bukkit/event/inventory/InventoryAction;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getAction", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryAction::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } /// Gets the ClickType for this event. /// @@ -690,11 +1069,14 @@ impl<'mc> CraftItemEvent<'mc> { pub fn click( &self, ) -> Result, Box> { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.click() + let sig = String::from("()Lorg/bukkit/event/inventory/ClickType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getClick", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::ClickType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn handlers(&self) -> Result, Box> { @@ -711,49 +1093,117 @@ impl<'mc> CraftItemEvent<'mc> { pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { - crate::event::inventory::InventoryClickEvent::handler_list(jni) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/inventory/InventoryClickEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) } -} -impl<'mc> Into> for CraftItemEvent<'mc> { - fn into(self) -> crate::event::inventory::InventoryClickEvent<'mc> { - crate::event::inventory::InventoryClickEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting CraftItemEvent into crate::event::inventory::InventoryClickEvent", - ) + // SUPER CLASS: org.bukkit.event.inventory.InventoryInteractEvent ( ['getSlotType', 'getCursor', 'getCurrentItem', 'isRightClick', 'isLeftClick', 'isShiftClick', 'setCursor', 'setCurrentItem', 'getClickedInventory', 'getSlot', 'getRawSlot', 'getHotbarButton', 'getAction', 'getClick', 'getHandlers', 'getHandlerList']) + /// Gets the player who performed the click. + pub fn who_clicked( + &self, + ) -> Result, Box> { + let temp_clone = + crate::event::inventory::InventoryInteractEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryInteractEvent = temp_clone.into(); + real.who_clicked() } -} -#[repr(C)] -pub struct InventoryEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for InventoryEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Sets the result of this event. This will change whether or not this + /// event is considered cancelled. + pub fn set_result( + &self, + new_result: impl Into>, + ) -> Result<(), Box> { + let temp_clone = + crate::event::inventory::InventoryInteractEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryInteractEvent = temp_clone.into(); + real.set_result(new_result) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets the {@link org.bukkit.event.Event.Result} of this event. The Result describes the + /// behavior that will be applied to the inventory in relation to this + /// event. + pub fn result(&self) -> Result, Box> { + let temp_clone = + crate::event::inventory::InventoryInteractEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryInteractEvent = temp_clone.into(); + real.result() } -} -impl<'mc> JNIInstantiatable<'mc> for InventoryEvent<'mc> { - fn from_raw( + /// Gets whether or not this event is cancelled. This is based off of the + /// Result value returned by {@link #getResult()}.Result.ALLOW and + /// Result.DEFAULT will result in a returned value of false, but + /// Result.DENY will result in a returned value of true. + /// + /// {@inheritDoc} + pub fn is_cancelled(&self) -> Result> { + let temp_clone = + crate::event::inventory::InventoryInteractEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryInteractEvent = temp_clone.into(); + real.is_cancelled() + } + /// Proxy method to {@link #setResult(org.bukkit.event.Event.Result)} for the Cancellable + /// interface. {@link #setResult(org.bukkit.event.Event.Result)} is preferred, as it allows + /// you to specify the Result beyond Result.DENY and Result.ALLOW. + /// + /// {@inheritDoc} + pub fn set_cancelled(&self, to_cancel: bool) -> Result<(), Box> { + let temp_clone = + crate::event::inventory::InventoryInteractEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryInteractEvent = temp_clone.into(); + real.set_cancelled(to_cancel) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for InventoryClickEvent<'mc> { + fn into(self) -> crate::event::inventory::InventoryInteractEvent<'mc> { + crate::event::inventory::InventoryInteractEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting InventoryClickEvent into crate::event::inventory::InventoryInteractEvent") + } +} +#[repr(C)] +pub struct FurnaceExtractEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for FurnaceExtractEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for FurnaceExtractEvent<'mc> { + fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate InventoryEvent from null object.").into(), + eyre::eyre!("Tried to instantiate FurnaceExtractEvent from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/inventory/InventoryEvent")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/inventory/FurnaceExtractEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a InventoryEvent object, got {}", + "Invalid argument passed. Expected a FurnaceExtractEvent object, got {}", name ) .into()) @@ -763,67 +1213,93 @@ impl<'mc> JNIInstantiatable<'mc> for InventoryEvent<'mc> { } } -impl<'mc> InventoryEvent<'mc> { +impl<'mc> FurnaceExtractEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - transaction: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/InventoryView;)V"); + player: impl Into>, + block: impl Into>, + item_type: impl Into>, + item_amount: i32, + exp: i32, + ) -> Result, Box> { + let sig = String::from( + "(Lorg/bukkit/entity/Player;Lorg/bukkit/block/Block;Lorg/bukkit/Material;II)V", + ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transaction.into().jni_object().clone()) + jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/inventory/InventoryEvent"); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(block.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_type.into().jni_object().clone()) + }); + let val_4 = jni::objects::JValueGen::Int(item_amount); + let val_5 = jni::objects::JValueGen::Int(exp); + let cls = jni.find_class("org/bukkit/event/inventory/FurnaceExtractEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + jni::objects::JValueGen::from(val_5), + ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::inventory::InventoryEvent::from_raw(&jni, res) + crate::event::inventory::FurnaceExtractEvent::from_raw(&jni, res) } - /// Gets the primary Inventory involved in this transaction - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + /// Get the player that triggered the event + pub fn player(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Player::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the Material of the item being retrieved + pub fn item_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItemType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + crate::Material::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the list of players viewing the primary (upper) inventory involved - /// in this event - pub fn viewers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + /// Get the item count being retrieved + pub fn item_amount(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getViewers", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItemAmount", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::HumanEntity::from_raw(&self.0, obj)?); - } - Ok(new_vec) + Ok(res.i()?) } - /// Gets the view object itself - pub fn view(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/InventoryView;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getView", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::InventoryView::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + // SUPER CLASS: org.bukkit.event.block.BlockExpEvent ( ['getPlayer', 'getItemType', 'getItemAmount']) + /// Get the experience dropped by the block after the event has processed + pub fn exp_to_drop(&self) -> Result> { + let temp_clone = crate::event::block::BlockExpEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockExpEvent = temp_clone.into(); + real.exp_to_drop() + } + /// Set the amount of experience dropped by the block after the event has + /// processed + pub fn set_exp_to_drop(&self, exp: i32) -> Result<(), Box> { + let temp_clone = crate::event::block::BlockExpEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockExpEvent = temp_clone.into(); + real.set_exp_to_drop(exp) } pub fn handlers(&self) -> Result, Box> { @@ -840,50 +1316,7 @@ impl<'mc> InventoryEvent<'mc> { pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/inventory/InventoryEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.Event ( ['getInventory', 'getViewers', 'getView', 'getHandlers', 'getHandlerList']) - /// Convenience method for providing a user-friendly identifier. By - /// default, it is the event's class's {@linkplain Class#getSimpleName() - /// simple name}. - pub fn event_name(&self) -> Result> { - let temp_clone = crate::event::Event::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::Event = temp_clone.into(); - real.event_name() - } - /// Any custom event that should not by synchronized with other events must - /// use the specific constructor. These are the caveats of using an - /// asynchronous event: - ///
    - ///
  • The event is never fired from inside code triggered by a - /// synchronous event. Attempting to do so results in an {@link - /// java.lang.IllegalStateException}. - ///
  • However, asynchronous event handlers may fire synchronous or - /// asynchronous events - ///
  • The event may be fired multiple times simultaneously and in any - /// order. - ///
  • Any newly registered or unregistered handler is ignored after an - /// event starts execution. - ///
  • The handlers for this event may block for any length of time. - ///
  • Some implementations may selectively declare a specific event use - /// as asynchronous. This behavior should be clearly defined. - ///
  • Asynchronous calls are not calculated in the plugin timing system. - ///
- pub fn is_asynchronous(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isAsynchronous", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::event::block::BlockExpEvent::handler_list(jni) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -891,19 +1324,19 @@ impl<'mc> InventoryEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for InventoryEvent<'mc> { - fn into(self) -> crate::event::Event<'mc> { - crate::event::Event::from_raw(&self.jni_ref(), self.1) - .expect("Error converting InventoryEvent into crate::event::Event") +impl<'mc> Into> for FurnaceExtractEvent<'mc> { + fn into(self) -> crate::event::block::BlockExpEvent<'mc> { + crate::event::block::BlockExpEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting FurnaceExtractEvent into crate::event::block::BlockExpEvent") } } #[repr(C)] -pub struct BrewEvent<'mc>( +pub struct FurnaceSmeltEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BrewEvent<'mc> { +impl<'mc> JNIRaw<'mc> for FurnaceSmeltEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -911,18 +1344,21 @@ impl<'mc> JNIRaw<'mc> for BrewEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BrewEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for FurnaceSmeltEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate BrewEvent from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate FurnaceSmeltEvent from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/inventory/BrewEvent")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/inventory/FurnaceSmeltEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BrewEvent object, got {}", + "Invalid argument passed. Expected a FurnaceSmeltEvent object, got {}", name ) .into()) @@ -932,36 +1368,24 @@ impl<'mc> JNIInstantiatable<'mc> for BrewEvent<'mc> { } } -impl<'mc> BrewEvent<'mc> { +impl<'mc> FurnaceSmeltEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - brewer: impl Into>, - contents: impl Into>, - results: Vec>, - fuel_level: i32, - ) -> Result, Box> { - let sig = String::from( - "(Lorg/bukkit/block/Block;Lorg/bukkit/inventory/BrewerInventory;Ljava/util/List;I)V", - ); + furnace: impl Into>, + source: impl Into>, + result: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/inventory/ItemStack;Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(brewer.into().jni_object().clone()) + jni::objects::JObject::from_raw(furnace.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(contents.into().jni_object().clone()) + jni::objects::JObject::from_raw(source.into().jni_object().clone()) }); - let raw_val_3 = jni.new_object("java/util/ArrayList", "()V", vec![])?; - for v in results { - let map_val_0 = jni::objects::JValueGen::Object(v); - jni.call_method( - &raw_val_3, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_3 = jni::objects::JValueGen::Object(raw_val_3); - let val_4 = jni::objects::JValueGen::Int(fuel_level); - let cls = jni.find_class("org/bukkit/event/inventory/BrewEvent"); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(result.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/inventory/FurnaceSmeltEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -970,79 +1394,54 @@ impl<'mc> BrewEvent<'mc> { jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::inventory::BrewEvent::from_raw(&jni, res) + crate::event::inventory::FurnaceSmeltEvent::from_raw(&jni, res) } - /// Gets the contents of the Brewing Stand. - /// Note: The brewer inventory still holds the items found prior to - /// the finalization of the brewing process, e.g. the plain water bottles. - pub fn contents( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/BrewerInventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getContents", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::BrewerInventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + // SUPER CLASS: org.bukkit.event.block.BlockCookEvent ( []) + /// Gets the smelted ItemStack for this event + pub fn source(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockCookEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockCookEvent = temp_clone.into(); + real.source() } - /// Gets the remaining fuel level. - pub fn fuel_level(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFuelLevel", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + /// Gets the resultant ItemStack for this event + pub fn result(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockCookEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockCookEvent = temp_clone.into(); + real.result() } - /// Gets the resulting items in the Brewing Stand. - /// The returned list, in case of a server-created event instance, is - /// mutable. Any changes in the returned list will reflect in the brewing - /// result if the event is not cancelled. If the size of the list is reduced, - /// remaining items will be set to air. - pub fn results( + /// Sets the resultant ItemStack for this event + pub fn set_result( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getResults", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::inventory::ItemStack::from_raw(&self.0, obj)?); - } - Ok(new_vec) + result: impl Into>, + ) -> Result<(), Box> { + let temp_clone = crate::event::block::BlockCookEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockCookEvent = temp_clone.into(); + real.set_result(result) } pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let temp_clone = crate::event::block::BlockCookEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockCookEvent = temp_clone.into(); + real.is_cancelled() } pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + let temp_clone = crate::event::block::BlockCookEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockCookEvent = temp_clone.into(); + real.set_cancelled(cancel) } pub fn handlers(&self) -> Result, Box> { @@ -1059,22 +1458,7 @@ impl<'mc> BrewEvent<'mc> { pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/inventory/BrewEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getContents', 'getFuelLevel', 'getResults', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) - /// Gets the block involved in this event. - pub fn block(&self) -> Result, Box> { - let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockEvent = temp_clone.into(); - real.block() + crate::event::block::BlockCookEvent::handler_list(jni) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1082,25 +1466,19 @@ impl<'mc> BrewEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BrewEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BrewEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for BrewEvent<'mc> { - fn into(self) -> crate::event::block::BlockEvent<'mc> { - crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BrewEvent into crate::event::block::BlockEvent") +impl<'mc> Into> for FurnaceSmeltEvent<'mc> { + fn into(self) -> crate::event::block::BlockCookEvent<'mc> { + crate::event::block::BlockCookEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting FurnaceSmeltEvent into crate::event::block::BlockCookEvent") } } #[repr(C)] -pub struct SmithItemEvent<'mc>( +pub struct CraftItemEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for SmithItemEvent<'mc> { +impl<'mc> JNIRaw<'mc> for CraftItemEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1108,20 +1486,20 @@ impl<'mc> JNIRaw<'mc> for SmithItemEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for SmithItemEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CraftItemEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate SmithItemEvent from null object.").into(), + eyre::eyre!("Tried to instantiate CraftItemEvent from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/inventory/SmithItemEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/inventory/CraftItemEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SmithItemEvent object, got {}", + "Invalid argument passed. Expected a CraftItemEvent object, got {}", name ) .into()) @@ -1131,67 +1509,84 @@ impl<'mc> JNIInstantiatable<'mc> for SmithItemEvent<'mc> { } } -impl<'mc> SmithItemEvent<'mc> { +impl<'mc> CraftItemEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - view: impl Into>, + recipe: impl Into>, + what: impl Into>, val_type: impl Into>, slot: i32, click: impl Into>, action: impl Into>, key: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/InventoryView;"; + sig += "Lorg/bukkit/inventory/Recipe;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(view.into().jni_object().clone()) + jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) }); args.push(val_1); - sig += "Lorg/bukkit/event/inventory/InventoryType/SlotType;"; + sig += "Lorg/bukkit/inventory/InventoryView;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(what.into().jni_object().clone()) }); args.push(val_2); - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(slot); + sig += "Lorg/bukkit/event/inventory/InventoryType/SlotType;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); args.push(val_3); + sig += "I"; + let val_4 = jni::objects::JValueGen::Int(slot); + args.push(val_4); sig += "Lorg/bukkit/event/inventory/ClickType;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { + let val_5 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(click.into().jni_object().clone()) }); - args.push(val_4); + args.push(val_5); sig += "Lorg/bukkit/event/inventory/InventoryAction;"; - let val_5 = jni::objects::JValueGen::Object(unsafe { + let val_6 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(action.into().jni_object().clone()) }); - args.push(val_5); + args.push(val_6); if let Some(a) = key { sig += "I"; - let val_6 = jni::objects::JValueGen::Int(a); - args.push(val_6); + let val_7 = jni::objects::JValueGen::Int(a); + args.push(val_7); } sig += ")V"; - let cls = jni.find_class("org/bukkit/event/inventory/SmithItemEvent"); + let cls = jni.find_class("org/bukkit/event/inventory/CraftItemEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::inventory::SmithItemEvent::from_raw(&jni, res) + crate::event::inventory::CraftItemEvent::from_raw(&jni, res) + } + + pub fn recipe(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Recipe;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRecipe", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Recipe::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn inventory( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/SmithingInventory;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/CraftingInventory;"); let res = self.jni_ref() .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::SmithingInventory::from_raw(&self.jni_ref(), unsafe { + crate::inventory::CraftingInventory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.event.inventory.InventoryClickEvent ( ['getInventory']) + // SUPER CLASS: org.bukkit.event.inventory.InventoryClickEvent ( ['getRecipe', 'getInventory']) /// Gets the type of slot that was clicked. pub fn slot_type( &self, @@ -1359,20 +1754,20 @@ impl<'mc> SmithItemEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for SmithItemEvent<'mc> { +impl<'mc> Into> for CraftItemEvent<'mc> { fn into(self) -> crate::event::inventory::InventoryClickEvent<'mc> { crate::event::inventory::InventoryClickEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting SmithItemEvent into crate::event::inventory::InventoryClickEvent", + "Error converting CraftItemEvent into crate::event::inventory::InventoryClickEvent", ) } } #[repr(C)] -pub struct BrewingStandFuelEvent<'mc>( +pub struct InventoryEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BrewingStandFuelEvent<'mc> { +impl<'mc> JNIRaw<'mc> for InventoryEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1380,22 +1775,20 @@ impl<'mc> JNIRaw<'mc> for BrewingStandFuelEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BrewingStandFuelEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for InventoryEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate BrewingStandFuelEvent from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate InventoryEvent from null object.").into(), + ); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/inventory/BrewingStandFuelEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/inventory/InventoryEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BrewingStandFuelEvent object, got {}", + "Invalid argument passed. Expected a InventoryEvent object, got {}", name ) .into()) @@ -1405,114 +1798,67 @@ impl<'mc> JNIInstantiatable<'mc> for BrewingStandFuelEvent<'mc> { } } -impl<'mc> BrewingStandFuelEvent<'mc> { +impl<'mc> InventoryEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - brewing_stand: impl Into>, - fuel: impl Into>, - fuel_power: i32, - ) -> Result, Box> - { - let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/inventory/ItemStack;I)V"); + transaction: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/InventoryView;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(brewing_stand.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(fuel.into().jni_object().clone()) + jni::objects::JObject::from_raw(transaction.into().jni_object().clone()) }); - let val_3 = jni::objects::JValueGen::Int(fuel_power); - let cls = jni.find_class("org/bukkit/event/inventory/BrewingStandFuelEvent"); + let cls = jni.find_class("org/bukkit/event/inventory/InventoryEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = jni.translate_error_no_gen(res)?; - crate::event::inventory::BrewingStandFuelEvent::from_raw(&jni, res) - } - /// Gets the ItemStack of the fuel before the amount was subtracted. - pub fn fuel(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFuel", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + crate::event::inventory::InventoryEvent::from_raw(&jni, res) } - /// Gets the fuel power for this fuel. Each unit of power can fuel one - /// brewing operation. - pub fn fuel_power(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the primary Inventory involved in this transaction + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFuelPower", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the fuel power for this fuel. Each unit of power can fuel one - /// brewing operation. - pub fn set_fuel_power(&self, fuel_power: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(fuel_power); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFuelPower", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets whether the brewing stand's fuel will be reduced / consumed or not. - pub fn is_consuming(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the list of players viewing the primary (upper) inventory involved + /// in this event + pub fn viewers( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isConsuming", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getViewers", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether the brewing stand's fuel will be reduced / consumed or not. - pub fn set_consuming(&self, consuming: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(consuming.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setConsuming", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::HumanEntity::from_raw(&self.0, obj)?); + } + Ok(new_vec) } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + /// Gets the view object itself + pub fn view(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/InventoryView;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getView", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::inventory::InventoryView::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn handlers(&self) -> Result, Box> { @@ -1530,21 +1876,49 @@ impl<'mc> BrewingStandFuelEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/inventory/BrewingStandFuelEvent"); + let cls = jni.find_class("org/bukkit/event/inventory/InventoryEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getFuel', 'getFuelPower', 'setFuelPower', 'isConsuming', 'setConsuming', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) - /// Gets the block involved in this event. - pub fn block(&self) -> Result, Box> { - let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { + // SUPER CLASS: org.bukkit.event.Event ( ['getInventory', 'getViewers', 'getView', 'getHandlers', 'getHandlerList']) + /// Convenience method for providing a user-friendly identifier. By + /// default, it is the event's class's {@linkplain Class#getSimpleName() + /// simple name}. + pub fn event_name(&self) -> Result> { + let temp_clone = crate::event::Event::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::block::BlockEvent = temp_clone.into(); - real.block() + let real: crate::event::Event = temp_clone.into(); + real.event_name() + } + /// Any custom event that should not by synchronized with other events must + /// use the specific constructor. These are the caveats of using an + /// asynchronous event: + ///
    + ///
  • The event is never fired from inside code triggered by a + /// synchronous event. Attempting to do so results in an {@link + /// java.lang.IllegalStateException}. + ///
  • However, asynchronous event handlers may fire synchronous or + /// asynchronous events + ///
  • The event may be fired multiple times simultaneously and in any + /// order. + ///
  • Any newly registered or unregistered handler is ignored after an + /// event starts execution. + ///
  • The handlers for this event may block for any length of time. + ///
  • Some implementations may selectively declare a specific event use + /// as asynchronous. This behavior should be clearly defined. + ///
  • Asynchronous calls are not calculated in the plugin timing system. + ///
+ pub fn is_asynchronous(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isAsynchronous", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1552,97 +1926,19 @@ impl<'mc> BrewingStandFuelEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BrewingStandFuelEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BrewingStandFuelEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for BrewingStandFuelEvent<'mc> { - fn into(self) -> crate::event::block::BlockEvent<'mc> { - crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BrewingStandFuelEvent into crate::event::block::BlockEvent") - } -} -pub enum DragType<'mc> {} -impl<'mc> std::fmt::Display for DragType<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> DragType<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/event/inventory/DragType"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/event/inventory/DragType;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } +impl<'mc> Into> for InventoryEvent<'mc> { + fn into(self) -> crate::event::Event<'mc> { + crate::event::Event::from_raw(&self.jni_ref(), self.1) + .expect("Error converting InventoryEvent into crate::event::Event") } } - #[repr(C)] -pub struct DragTypeStruct<'mc>( +pub struct BrewEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for DragType<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for DragType<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate DragType from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/inventory/DragType")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a DragType object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for DragTypeStruct<'mc> { +impl<'mc> JNIRaw<'mc> for BrewEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1650,20 +1946,18 @@ impl<'mc> JNIRaw<'mc> for DragTypeStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for DragTypeStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BrewEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate DragTypeStruct from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate BrewEvent from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/inventory/DragType")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/inventory/BrewEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a DragTypeStruct object, got {}", + "Invalid argument passed. Expected a BrewEvent object, got {}", name ) .into()) @@ -1673,81 +1967,36 @@ impl<'mc> JNIInstantiatable<'mc> for DragTypeStruct<'mc> { } } -impl<'mc> DragTypeStruct<'mc> { - pub fn values( +impl<'mc> BrewEvent<'mc> { + pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/inventory/DragType;"); - let cls = jni.find_class("org/bukkit/event/inventory/DragType"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::inventory::DragType::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct PrepareInventoryResultEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PrepareInventoryResultEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PrepareInventoryResultEvent<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PrepareInventoryResultEvent from null object." - ) - .into()); - } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/event/inventory/PrepareInventoryResultEvent", - )?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PrepareInventoryResultEvent object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> PrepareInventoryResultEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - inventory: impl Into>, - result: impl Into>, - ) -> Result, Box> - { - let sig = - String::from("(Lorg/bukkit/inventory/InventoryView;Lorg/bukkit/inventory/ItemStack;)V"); + brewer: impl Into>, + contents: impl Into>, + results: Vec>, + fuel_level: i32, + ) -> Result, Box> { + let sig = String::from( + "(Lorg/bukkit/block/Block;Lorg/bukkit/inventory/BrewerInventory;Ljava/util/List;I)V", + ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(inventory.into().jni_object().clone()) + jni::objects::JObject::from_raw(brewer.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(result.into().jni_object().clone()) + jni::objects::JObject::from_raw(contents.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/inventory/PrepareInventoryResultEvent"); + let raw_val_3 = jni.new_object("java/util/ArrayList", "()V", vec![])?; + for v in results { + let map_val_0 = jni::objects::JValueGen::Object(v); + jni.call_method( + &raw_val_3, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_3 = jni::objects::JValueGen::Object(raw_val_3); + let val_4 = jni::objects::JValueGen::Int(fuel_level); + let cls = jni.find_class("org/bukkit/event/inventory/BrewEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -1755,40 +2004,75 @@ impl<'mc> PrepareInventoryResultEvent<'mc> { vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::inventory::PrepareInventoryResultEvent::from_raw(&jni, res) + crate::event::inventory::BrewEvent::from_raw(&jni, res) } - /// Get result item, may be null. - pub fn result( + /// Gets the contents of the Brewing Stand. + /// Note: The brewer inventory still holds the items found prior to + /// the finalization of the brewing process, e.g. the plain water bottles. + pub fn contents( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getResult", sig.as_str(), vec![]); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/BrewerInventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getContents", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::inventory::BrewerInventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set result item, may be null. - pub fn set_result( + /// Gets the remaining fuel level. + pub fn fuel_level(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFuelLevel", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the resulting items in the Brewing Stand. + /// The returned list, in case of a server-created event instance, is + /// mutable. Any changes in the returned list will reflect in the brewing + /// result if the event is not cancelled. If the size of the list is reduced, + /// remaining items will be set to air. + pub fn results( &self, - result: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(result.into().jni_object().clone()) - }); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getResults", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::inventory::ItemStack::from_raw(&self.0, obj)?); + } + Ok(new_vec) + } + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setResult", + "setCancelled", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -1811,50 +2095,21 @@ impl<'mc> PrepareInventoryResultEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/inventory/PrepareInventoryResultEvent"); + let cls = jni.find_class("org/bukkit/event/inventory/BrewEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.inventory.InventoryEvent ( ['getResult', 'setResult', 'getHandlers', 'getHandlerList']) - /// Gets the primary Inventory involved in this transaction - pub fn inventory( - &self, - ) -> Result, Box> { - let temp_clone = crate::event::inventory::InventoryEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryEvent = temp_clone.into(); - real.inventory() - } - /// Gets the list of players viewing the primary (upper) inventory involved - /// in this event - pub fn viewers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getViewers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::HumanEntity::from_raw(&self.0, obj)?); - } - Ok(new_vec) - } - /// Gets the view object itself - pub fn view(&self) -> Result, Box> { - let temp_clone = crate::event::inventory::InventoryEvent::from_raw(&self.0, unsafe { + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getContents', 'getFuelLevel', 'getResults', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + /// Gets the block involved in this event. + pub fn block(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::inventory::InventoryEvent = temp_clone.into(); - real.view() + let real: crate::event::block::BlockEvent = temp_clone.into(); + real.block() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1862,18 +2117,25 @@ impl<'mc> PrepareInventoryResultEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PrepareInventoryResultEvent<'mc> { - fn into(self) -> crate::event::inventory::InventoryEvent<'mc> { - crate::event::inventory::InventoryEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting PrepareInventoryResultEvent into crate::event::inventory::InventoryEvent") +impl<'mc> Into> for BrewEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BrewEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for BrewEvent<'mc> { + fn into(self) -> crate::event::block::BlockEvent<'mc> { + crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BrewEvent into crate::event::block::BlockEvent") } } #[repr(C)] -pub struct InventoryDragEvent<'mc>( +pub struct SmithItemEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for InventoryDragEvent<'mc> { +impl<'mc> JNIRaw<'mc> for SmithItemEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1881,21 +2143,20 @@ impl<'mc> JNIRaw<'mc> for InventoryDragEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for InventoryDragEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for SmithItemEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate InventoryDragEvent from null object.").into(), + eyre::eyre!("Tried to instantiate SmithItemEvent from null object.").into(), ); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/inventory/InventoryDragEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/inventory/SmithItemEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a InventoryDragEvent object, got {}", + "Invalid argument passed. Expected a SmithItemEvent object, got {}", name ) .into()) @@ -1905,18 +2166,826 @@ impl<'mc> JNIInstantiatable<'mc> for InventoryDragEvent<'mc> { } } -impl<'mc> InventoryDragEvent<'mc> { +impl<'mc> SmithItemEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - what: impl Into>, - new_cursor: impl Into>, - old_cursor: impl Into>, - right: bool, - slots: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/InventoryView;Lorg/bukkit/inventory/ItemStack;Lorg/bukkit/inventory/ItemStack;ZLjava/util/Map;)V"); + view: impl Into>, + val_type: impl Into>, + slot: i32, + click: impl Into>, + action: impl Into>, + key: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/InventoryView;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(what.into().jni_object().clone()) + jni::objects::JObject::from_raw(view.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Lorg/bukkit/event/inventory/InventoryType/SlotType;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + args.push(val_2); + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(slot); + args.push(val_3); + sig += "Lorg/bukkit/event/inventory/ClickType;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(click.into().jni_object().clone()) + }); + args.push(val_4); + sig += "Lorg/bukkit/event/inventory/InventoryAction;"; + let val_5 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(action.into().jni_object().clone()) + }); + args.push(val_5); + if let Some(a) = key { + sig += "I"; + let val_6 = jni::objects::JValueGen::Int(a); + args.push(val_6); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/inventory/SmithItemEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::event::inventory::SmithItemEvent::from_raw(&jni, res) + } + + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/SmithingInventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::SmithingInventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + // SUPER CLASS: org.bukkit.event.inventory.InventoryClickEvent ( ['getInventory']) + /// Gets the type of slot that was clicked. + pub fn slot_type( + &self, + ) -> Result, Box> + { + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.slot_type() + } + /// Gets the current ItemStack on the cursor. + pub fn cursor( + &self, + ) -> Result>, Box> { + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.cursor() + } + /// Gets the ItemStack currently in the clicked slot. + pub fn current_item( + &self, + ) -> Result>, Box> { + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.current_item() + } + /// Gets whether or not the ClickType for this event represents a right + /// click. + pub fn is_right_click(&self) -> Result> { + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.is_right_click() + } + /// Gets whether or not the ClickType for this event represents a left + /// click. + pub fn is_left_click(&self) -> Result> { + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.is_left_click() + } + /// Gets whether the ClickType for this event indicates that the key was + /// pressed down when the click was made. + pub fn is_shift_click(&self) -> Result> { + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.is_shift_click() + } + /// Sets the item on the cursor. + pub fn set_cursor( + &self, + stack: impl Into>, + ) -> Result<(), Box> { + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.set_cursor(stack) + } + /// Sets the ItemStack currently in the clicked slot. + pub fn set_current_item( + &self, + stack: impl Into>, + ) -> Result<(), Box> { + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.set_current_item(stack) + } + /// Gets the inventory corresponding to the clicked slot. + pub fn clicked_inventory( + &self, + ) -> Result>, Box> { + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.clicked_inventory() + } + /// The slot number that was clicked, ready for passing to + /// {@link Inventory#getItem(int)}. Note that there may be two slots with + /// the same slot number, since a view links two different inventories. + pub fn slot(&self) -> Result> { + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.slot() + } + /// The raw slot number clicked, ready for passing to {@link InventoryView + /// #getItem(int)} This slot number is unique for the view. + pub fn raw_slot(&self) -> Result> { + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.raw_slot() + } + /// If the ClickType is NUMBER_KEY, this method will return the index of + /// the pressed key (0-8). + pub fn hotbar_button(&self) -> Result> { + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.hotbar_button() + } + /// Gets the InventoryAction that triggered this event. + /// + /// This action cannot be changed, and represents what the normal outcome + /// of the event will be. To change the behavior of this + /// InventoryClickEvent, changes must be manually applied. + pub fn action( + &self, + ) -> Result, Box> { + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.action() + } + /// Gets the ClickType for this event. + /// + /// This is insulated against changes to the inventory by other plugins. + pub fn click( + &self, + ) -> Result, Box> { + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.click() + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + crate::event::inventory::InventoryClickEvent::handler_list(jni) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for SmithItemEvent<'mc> { + fn into(self) -> crate::event::inventory::InventoryClickEvent<'mc> { + crate::event::inventory::InventoryClickEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting SmithItemEvent into crate::event::inventory::InventoryClickEvent", + ) + } +} +#[repr(C)] +pub struct BrewingStandFuelEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for BrewingStandFuelEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for BrewingStandFuelEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate BrewingStandFuelEvent from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/inventory/BrewingStandFuelEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BrewingStandFuelEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> BrewingStandFuelEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + brewing_stand: impl Into>, + fuel: impl Into>, + fuel_power: i32, + ) -> Result, Box> + { + let sig = String::from("(Lorg/bukkit/block/Block;Lorg/bukkit/inventory/ItemStack;I)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(brewing_stand.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(fuel.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Int(fuel_power); + let cls = jni.find_class("org/bukkit/event/inventory/BrewingStandFuelEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::event::inventory::BrewingStandFuelEvent::from_raw(&jni, res) + } + /// Gets the ItemStack of the fuel before the amount was subtracted. + pub fn fuel(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFuel", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the fuel power for this fuel. Each unit of power can fuel one + /// brewing operation. + pub fn fuel_power(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFuelPower", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the fuel power for this fuel. Each unit of power can fuel one + /// brewing operation. + pub fn set_fuel_power(&self, fuel_power: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(fuel_power); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFuelPower", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether the brewing stand's fuel will be reduced / consumed or not. + pub fn is_consuming(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isConsuming", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether the brewing stand's fuel will be reduced / consumed or not. + pub fn set_consuming(&self, consuming: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(consuming.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setConsuming", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/inventory/BrewingStandFuelEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.block.BlockEvent ( ['getFuel', 'getFuelPower', 'setFuelPower', 'isConsuming', 'setConsuming', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + /// Gets the block involved in this event. + pub fn block(&self) -> Result, Box> { + let temp_clone = crate::event::block::BlockEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::block::BlockEvent = temp_clone.into(); + real.block() + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for BrewingStandFuelEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BrewingStandFuelEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for BrewingStandFuelEvent<'mc> { + fn into(self) -> crate::event::block::BlockEvent<'mc> { + crate::event::block::BlockEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BrewingStandFuelEvent into crate::event::block::BlockEvent") + } +} +pub enum DragType<'mc> { + Single { inner: DragTypeStruct<'mc> }, + Even { inner: DragTypeStruct<'mc> }, +} +impl<'mc> std::fmt::Display for DragType<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + DragType::Single { .. } => f.write_str("SINGLE"), + DragType::Even { .. } => f.write_str("EVEN"), + } + } +} +impl<'mc> std::ops::Deref for DragType<'mc> { + type Target = DragTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + DragType::Single { inner } => inner, + DragType::Even { inner } => inner, + } + } +} + +impl<'mc> DragType<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/event/inventory/DragType"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/event/inventory/DragType;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "SINGLE" => Ok(DragType::Single { + inner: DragTypeStruct::from_raw(env, obj)?, + }), + "EVEN" => Ok(DragType::Even { + inner: DragTypeStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct DragTypeStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for DragType<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Single { inner } => inner.0.clone(), + Self::Even { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Single { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Even { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for DragType<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate DragType from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/inventory/DragType")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a DragType object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "SINGLE" => Ok(DragType::Single { + inner: DragTypeStruct::from_raw(env, obj)?, + }), + "EVEN" => Ok(DragType::Even { + inner: DragTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for DragTypeStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for DragTypeStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate DragTypeStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/inventory/DragType")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a DragTypeStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> DragTypeStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/inventory/DragType;"); + let cls = jni.find_class("org/bukkit/event/inventory/DragType"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::inventory::DragType::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct PrepareInventoryResultEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PrepareInventoryResultEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PrepareInventoryResultEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate PrepareInventoryResultEvent from null object." + ) + .into()); + } + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/event/inventory/PrepareInventoryResultEvent", + )?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PrepareInventoryResultEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> PrepareInventoryResultEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + inventory: impl Into>, + result: impl Into>, + ) -> Result, Box> + { + let sig = + String::from("(Lorg/bukkit/inventory/InventoryView;Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(inventory.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(result.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/inventory/PrepareInventoryResultEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::event::inventory::PrepareInventoryResultEvent::from_raw(&jni, res) + } + /// Get result item, may be null. + pub fn result( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getResult", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Set result item, may be null. + pub fn set_result( + &self, + result: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(result.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setResult", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/inventory/PrepareInventoryResultEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.inventory.InventoryEvent ( ['getResult', 'setResult', 'getHandlers', 'getHandlerList']) + /// Gets the primary Inventory involved in this transaction + pub fn inventory( + &self, + ) -> Result, Box> { + let temp_clone = crate::event::inventory::InventoryEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryEvent = temp_clone.into(); + real.inventory() + } + /// Gets the list of players viewing the primary (upper) inventory involved + /// in this event + pub fn viewers( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getViewers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::HumanEntity::from_raw(&self.0, obj)?); + } + Ok(new_vec) + } + /// Gets the view object itself + pub fn view(&self) -> Result, Box> { + let temp_clone = crate::event::inventory::InventoryEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryEvent = temp_clone.into(); + real.view() + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for PrepareInventoryResultEvent<'mc> { + fn into(self) -> crate::event::inventory::InventoryEvent<'mc> { + crate::event::inventory::InventoryEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting PrepareInventoryResultEvent into crate::event::inventory::InventoryEvent") + } +} +#[repr(C)] +pub struct InventoryDragEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for InventoryDragEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for InventoryDragEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate InventoryDragEvent from null object.").into(), + ); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/inventory/InventoryDragEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a InventoryDragEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> InventoryDragEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + what: impl Into>, + new_cursor: impl Into>, + old_cursor: impl Into>, + right: bool, + slots: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/InventoryView;Lorg/bukkit/inventory/ItemStack;Lorg/bukkit/inventory/ItemStack;ZLjava/util/Map;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(what.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(new_cursor.into().jni_object().clone()) @@ -2486,10 +3555,31 @@ impl<'mc> Into> for HopperInventorySearchEv ) } } -pub enum HopperInventorySearchEventContainerType<'mc> {} +pub enum HopperInventorySearchEventContainerType<'mc> { + Source { + inner: HopperInventorySearchEventContainerTypeStruct<'mc>, + }, + Destination { + inner: HopperInventorySearchEventContainerTypeStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for HopperInventorySearchEventContainerType<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + HopperInventorySearchEventContainerType::Source { .. } => f.write_str("SOURCE"), + HopperInventorySearchEventContainerType::Destination { .. } => { + f.write_str("DESTINATION") + } + } + } +} +impl<'mc> std::ops::Deref for HopperInventorySearchEventContainerType<'mc> { + type Target = HopperInventorySearchEventContainerTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + HopperInventorySearchEventContainerType::Source { inner } => inner, + HopperInventorySearchEventContainerType::Destination { inner } => inner, + } } } @@ -2517,6 +3607,13 @@ impl<'mc> HopperInventorySearchEventContainerType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "SOURCE" => Ok(HopperInventorySearchEventContainerType::Source { + inner: HopperInventorySearchEventContainerTypeStruct::from_raw(env, obj)?, + }), + "DESTINATION" => Ok(HopperInventorySearchEventContainerType::Destination { + inner: HopperInventorySearchEventContainerTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -2530,10 +3627,18 @@ pub struct HopperInventorySearchEventContainerTypeStruct<'mc>( impl<'mc> JNIRaw<'mc> for HopperInventorySearchEventContainerType<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Source { inner } => inner.0.clone(), + Self::Destination { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Source { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Destination { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } impl<'mc> JNIInstantiatable<'mc> for HopperInventorySearchEventContainerType<'mc> { @@ -2565,6 +3670,12 @@ impl<'mc> JNIInstantiatable<'mc> for HopperInventorySearchEventContainerType<'mc .to_string_lossy() .to_string(); match variant_str.as_str() { + "SOURCE" => Ok(HopperInventorySearchEventContainerType::Source { + inner: HopperInventorySearchEventContainerTypeStruct::from_raw(env, obj)?, + }), + "DESTINATION" => Ok(HopperInventorySearchEventContainerType::Destination { + inner: HopperInventorySearchEventContainerTypeStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -2916,194 +4027,20 @@ impl<'mc> PrepareItemCraftEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, what: impl Into>, view: impl Into>, - is_repair: bool, - ) -> Result, Box> - { - let sig = String::from( - "(Lorg/bukkit/inventory/CraftingInventory;Lorg/bukkit/inventory/InventoryView;Z)V", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(what.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(view.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Bool(is_repair.into()); - let cls = jni.find_class("org/bukkit/event/inventory/PrepareItemCraftEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = jni.translate_error_no_gen(res)?; - crate::event::inventory::PrepareItemCraftEvent::from_raw(&jni, res) - } - /// Get the recipe that has been formed. If this event was triggered by a - /// tool repair, this will be a temporary shapeless recipe representing the - /// repair. - pub fn recipe( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Recipe;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getRecipe", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::Recipe::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/CraftingInventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::CraftingInventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Check if this event was triggered by a tool repair operation rather - /// than a crafting recipe. - pub fn is_repair(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isRepair", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn handler_list( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/inventory/PrepareItemCraftEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.inventory.InventoryEvent ( ['getRecipe', 'getInventory', 'isRepair', 'getHandlers', 'getHandlerList']) - /// Gets the list of players viewing the primary (upper) inventory involved - /// in this event - pub fn viewers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getViewers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::HumanEntity::from_raw(&self.0, obj)?); - } - Ok(new_vec) - } - /// Gets the view object itself - pub fn view(&self) -> Result, Box> { - let temp_clone = crate::event::inventory::InventoryEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryEvent = temp_clone.into(); - real.view() - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for PrepareItemCraftEvent<'mc> { - fn into(self) -> crate::event::inventory::InventoryEvent<'mc> { - crate::event::inventory::InventoryEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting PrepareItemCraftEvent into crate::event::inventory::InventoryEvent", - ) - } -} -#[repr(C)] -pub struct PrepareGrindstoneEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PrepareGrindstoneEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PrepareGrindstoneEvent<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PrepareGrindstoneEvent from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/inventory/PrepareGrindstoneEvent")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PrepareGrindstoneEvent object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> PrepareGrindstoneEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - inventory: impl Into>, - result: impl Into>, - ) -> Result, Box> + is_repair: bool, + ) -> Result, Box> { - let sig = - String::from("(Lorg/bukkit/inventory/InventoryView;Lorg/bukkit/inventory/ItemStack;)V"); + let sig = String::from( + "(Lorg/bukkit/inventory/CraftingInventory;Lorg/bukkit/inventory/InventoryView;Z)V", + ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(inventory.into().jni_object().clone()) + jni::objects::JObject::from_raw(what.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(result.into().jni_object().clone()) + jni::objects::JObject::from_raw(view.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/inventory/PrepareGrindstoneEvent"); + let val_3 = jni::objects::JValueGen::Bool(is_repair.into()); + let cls = jni.find_class("org/bukkit/event/inventory/PrepareItemCraftEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -3111,24 +4048,54 @@ impl<'mc> PrepareGrindstoneEvent<'mc> { vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::inventory::PrepareGrindstoneEvent::from_raw(&jni, res) + crate::event::inventory::PrepareItemCraftEvent::from_raw(&jni, res) + } + /// Get the recipe that has been formed. If this event was triggered by a + /// tool repair, this will be a temporary shapeless recipe representing the + /// repair. + pub fn recipe( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Recipe;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRecipe", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::Recipe::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } pub fn inventory( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/GrindstoneInventory;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/CraftingInventory;"); let res = self.jni_ref() .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::GrindstoneInventory::from_raw(&self.jni_ref(), unsafe { + crate::inventory::CraftingInventory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } + /// Check if this event was triggered by a tool repair operation rather + /// than a crafting recipe. + pub fn is_repair(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isRepair", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -3145,36 +4112,40 @@ impl<'mc> PrepareGrindstoneEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/inventory/PrepareGrindstoneEvent"); + let cls = jni.find_class("org/bukkit/event/inventory/PrepareItemCraftEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.inventory.PrepareInventoryResultEvent ( ['getInventory', 'getHandlers', 'getHandlerList']) - /// Get result item, may be null. - pub fn result( + // SUPER CLASS: org.bukkit.event.inventory.InventoryEvent ( ['getRecipe', 'getInventory', 'isRepair', 'getHandlers', 'getHandlerList']) + /// Gets the list of players viewing the primary (upper) inventory involved + /// in this event + pub fn viewers( &self, - ) -> Result>, Box> { - let temp_clone = - crate::event::inventory::PrepareInventoryResultEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::PrepareInventoryResultEvent = temp_clone.into(); - real.result() + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getViewers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::HumanEntity::from_raw(&self.0, obj)?); + } + Ok(new_vec) } - /// Set result item, may be null. - pub fn set_result( - &self, - result: impl Into>, - ) -> Result<(), Box> { - let temp_clone = - crate::event::inventory::PrepareInventoryResultEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::PrepareInventoryResultEvent = temp_clone.into(); - real.set_result(result) + /// Gets the view object itself + pub fn view(&self) -> Result, Box> { + let temp_clone = crate::event::inventory::InventoryEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryEvent = temp_clone.into(); + real.view() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -3182,152 +4153,20 @@ impl<'mc> PrepareGrindstoneEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> - for PrepareGrindstoneEvent<'mc> -{ - fn into(self) -> crate::event::inventory::PrepareInventoryResultEvent<'mc> { - crate::event::inventory::PrepareInventoryResultEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting PrepareGrindstoneEvent into crate::event::inventory::PrepareInventoryResultEvent") - } -} -pub enum InventoryAction<'mc> {} -impl<'mc> std::fmt::Display for InventoryAction<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> InventoryAction<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/event/inventory/InventoryAction"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/event/inventory/InventoryAction;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct InventoryActionStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for InventoryAction<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for InventoryAction<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate InventoryAction from null object.").into(), - ); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/inventory/InventoryAction")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a InventoryAction object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for InventoryActionStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for InventoryActionStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate InventoryActionStruct from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/inventory/InventoryAction")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a InventoryActionStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> InventoryActionStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/inventory/InventoryAction;"); - let cls = jni.find_class("org/bukkit/event/inventory/InventoryAction"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::inventory::InventoryAction::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) +impl<'mc> Into> for PrepareItemCraftEvent<'mc> { + fn into(self) -> crate::event::inventory::InventoryEvent<'mc> { + crate::event::inventory::InventoryEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting PrepareItemCraftEvent into crate::event::inventory::InventoryEvent", + ) } } #[repr(C)] -pub struct InventoryPickupItemEvent<'mc>( +pub struct PrepareGrindstoneEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for InventoryPickupItemEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PrepareGrindstoneEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3335,22 +4174,22 @@ impl<'mc> JNIRaw<'mc> for InventoryPickupItemEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for InventoryPickupItemEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PrepareGrindstoneEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate InventoryPickupItemEvent from null object." + "Tried to instantiate PrepareGrindstoneEvent from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/inventory/InventoryPickupItemEvent")?; + env.validate_name(&obj, "org/bukkit/event/inventory/PrepareGrindstoneEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a InventoryPickupItemEvent object, got {}", + "Invalid argument passed. Expected a PrepareGrindstoneEvent object, got {}", name ) .into()) @@ -3360,21 +4199,22 @@ impl<'mc> JNIInstantiatable<'mc> for InventoryPickupItemEvent<'mc> { } } -impl<'mc> InventoryPickupItemEvent<'mc> { +impl<'mc> PrepareGrindstoneEvent<'mc> { pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - inventory: impl Into>, - item: impl Into>, - ) -> Result, Box> + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + inventory: impl Into>, + result: impl Into>, + ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/Inventory;Lorg/bukkit/entity/Item;)V"); + let sig = + String::from("(Lorg/bukkit/inventory/InventoryView;Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(inventory.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(result.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/inventory/InventoryPickupItemEvent"); + let cls = jni.find_class("org/bukkit/event/inventory/PrepareGrindstoneEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -3385,55 +4225,22 @@ impl<'mc> InventoryPickupItemEvent<'mc> { ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::inventory::InventoryPickupItemEvent::from_raw(&jni, res) + crate::event::inventory::PrepareGrindstoneEvent::from_raw(&jni, res) } - /// Gets the Inventory that picked up the item + pub fn inventory( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/GrindstoneInventory;"); let res = self.jni_ref() .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the Item entity that was picked up - pub fn item(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Item;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Item::from_raw(&self.jni_ref(), unsafe { + crate::inventory::GrindstoneInventory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); let res = @@ -3449,49 +4256,36 @@ impl<'mc> InventoryPickupItemEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/inventory/InventoryPickupItemEvent"); + let cls = jni.find_class("org/bukkit/event/inventory/PrepareGrindstoneEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.Event ( ['getInventory', 'getItem', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) - /// Convenience method for providing a user-friendly identifier. By - /// default, it is the event's class's {@linkplain Class#getSimpleName() - /// simple name}. - pub fn event_name(&self) -> Result> { - let temp_clone = crate::event::Event::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::Event = temp_clone.into(); - real.event_name() + // SUPER CLASS: org.bukkit.event.inventory.PrepareInventoryResultEvent ( ['getInventory', 'getHandlers', 'getHandlerList']) + /// Get result item, may be null. + pub fn result( + &self, + ) -> Result>, Box> { + let temp_clone = + crate::event::inventory::PrepareInventoryResultEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::PrepareInventoryResultEvent = temp_clone.into(); + real.result() } - /// Any custom event that should not by synchronized with other events must - /// use the specific constructor. These are the caveats of using an - /// asynchronous event: - ///
    - ///
  • The event is never fired from inside code triggered by a - /// synchronous event. Attempting to do so results in an {@link - /// java.lang.IllegalStateException}. - ///
  • However, asynchronous event handlers may fire synchronous or - /// asynchronous events - ///
  • The event may be fired multiple times simultaneously and in any - /// order. - ///
  • Any newly registered or unregistered handler is ignored after an - /// event starts execution. - ///
  • The handlers for this event may block for any length of time. - ///
  • Some implementations may selectively declare a specific event use - /// as asynchronous. This behavior should be clearly defined. - ///
  • Asynchronous calls are not calculated in the plugin timing system. - ///
- pub fn is_asynchronous(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isAsynchronous", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Set result item, may be null. + pub fn set_result( + &self, + result: impl Into>, + ) -> Result<(), Box> { + let temp_clone = + crate::event::inventory::PrepareInventoryResultEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::PrepareInventoryResultEvent = temp_clone.into(); + real.set_result(result) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -3499,146 +4293,389 @@ impl<'mc> InventoryPickupItemEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for InventoryPickupItemEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting InventoryPickupItemEvent into crate::event::Cancellable") +impl<'mc> Into> + for PrepareGrindstoneEvent<'mc> +{ + fn into(self) -> crate::event::inventory::PrepareInventoryResultEvent<'mc> { + crate::event::inventory::PrepareInventoryResultEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting PrepareGrindstoneEvent into crate::event::inventory::PrepareInventoryResultEvent") } } -impl<'mc> Into> for InventoryPickupItemEvent<'mc> { - fn into(self) -> crate::event::Event<'mc> { - crate::event::Event::from_raw(&self.jni_ref(), self.1) - .expect("Error converting InventoryPickupItemEvent into crate::event::Event") +pub enum InventoryAction<'mc> { + Nothing { inner: InventoryActionStruct<'mc> }, + PickupAll { inner: InventoryActionStruct<'mc> }, + PickupSome { inner: InventoryActionStruct<'mc> }, + PickupHalf { inner: InventoryActionStruct<'mc> }, + PickupOne { inner: InventoryActionStruct<'mc> }, + PlaceAll { inner: InventoryActionStruct<'mc> }, + PlaceSome { inner: InventoryActionStruct<'mc> }, + PlaceOne { inner: InventoryActionStruct<'mc> }, + SwapWithCursor { inner: InventoryActionStruct<'mc> }, + DropAllCursor { inner: InventoryActionStruct<'mc> }, + DropOneCursor { inner: InventoryActionStruct<'mc> }, + DropAllSlot { inner: InventoryActionStruct<'mc> }, + DropOneSlot { inner: InventoryActionStruct<'mc> }, + MoveToOtherInventory { inner: InventoryActionStruct<'mc> }, + HotbarMoveAndReadd { inner: InventoryActionStruct<'mc> }, + HotbarSwap { inner: InventoryActionStruct<'mc> }, + CloneStack { inner: InventoryActionStruct<'mc> }, + CollectToCursor { inner: InventoryActionStruct<'mc> }, + Unknown { inner: InventoryActionStruct<'mc> }, +} +impl<'mc> std::fmt::Display for InventoryAction<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + InventoryAction::Nothing { .. } => f.write_str("NOTHING"), + InventoryAction::PickupAll { .. } => f.write_str("PICKUP_ALL"), + InventoryAction::PickupSome { .. } => f.write_str("PICKUP_SOME"), + InventoryAction::PickupHalf { .. } => f.write_str("PICKUP_HALF"), + InventoryAction::PickupOne { .. } => f.write_str("PICKUP_ONE"), + InventoryAction::PlaceAll { .. } => f.write_str("PLACE_ALL"), + InventoryAction::PlaceSome { .. } => f.write_str("PLACE_SOME"), + InventoryAction::PlaceOne { .. } => f.write_str("PLACE_ONE"), + InventoryAction::SwapWithCursor { .. } => f.write_str("SWAP_WITH_CURSOR"), + InventoryAction::DropAllCursor { .. } => f.write_str("DROP_ALL_CURSOR"), + InventoryAction::DropOneCursor { .. } => f.write_str("DROP_ONE_CURSOR"), + InventoryAction::DropAllSlot { .. } => f.write_str("DROP_ALL_SLOT"), + InventoryAction::DropOneSlot { .. } => f.write_str("DROP_ONE_SLOT"), + InventoryAction::MoveToOtherInventory { .. } => f.write_str("MOVE_TO_OTHER_INVENTORY"), + InventoryAction::HotbarMoveAndReadd { .. } => f.write_str("HOTBAR_MOVE_AND_READD"), + InventoryAction::HotbarSwap { .. } => f.write_str("HOTBAR_SWAP"), + InventoryAction::CloneStack { .. } => f.write_str("CLONE_STACK"), + InventoryAction::CollectToCursor { .. } => f.write_str("COLLECT_TO_CURSOR"), + InventoryAction::Unknown { .. } => f.write_str("UNKNOWN"), + } + } +} +impl<'mc> std::ops::Deref for InventoryAction<'mc> { + type Target = InventoryActionStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + InventoryAction::Nothing { inner } => inner, + InventoryAction::PickupAll { inner } => inner, + InventoryAction::PickupSome { inner } => inner, + InventoryAction::PickupHalf { inner } => inner, + InventoryAction::PickupOne { inner } => inner, + InventoryAction::PlaceAll { inner } => inner, + InventoryAction::PlaceSome { inner } => inner, + InventoryAction::PlaceOne { inner } => inner, + InventoryAction::SwapWithCursor { inner } => inner, + InventoryAction::DropAllCursor { inner } => inner, + InventoryAction::DropOneCursor { inner } => inner, + InventoryAction::DropAllSlot { inner } => inner, + InventoryAction::DropOneSlot { inner } => inner, + InventoryAction::MoveToOtherInventory { inner } => inner, + InventoryAction::HotbarMoveAndReadd { inner } => inner, + InventoryAction::HotbarSwap { inner } => inner, + InventoryAction::CloneStack { inner } => inner, + InventoryAction::CollectToCursor { inner } => inner, + InventoryAction::Unknown { inner } => inner, + } + } +} + +impl<'mc> InventoryAction<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/event/inventory/InventoryAction"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/event/inventory/InventoryAction;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "NOTHING" => Ok(InventoryAction::Nothing { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "PICKUP_ALL" => Ok(InventoryAction::PickupAll { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "PICKUP_SOME" => Ok(InventoryAction::PickupSome { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "PICKUP_HALF" => Ok(InventoryAction::PickupHalf { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "PICKUP_ONE" => Ok(InventoryAction::PickupOne { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "PLACE_ALL" => Ok(InventoryAction::PlaceAll { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "PLACE_SOME" => Ok(InventoryAction::PlaceSome { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "PLACE_ONE" => Ok(InventoryAction::PlaceOne { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "SWAP_WITH_CURSOR" => Ok(InventoryAction::SwapWithCursor { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "DROP_ALL_CURSOR" => Ok(InventoryAction::DropAllCursor { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "DROP_ONE_CURSOR" => Ok(InventoryAction::DropOneCursor { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "DROP_ALL_SLOT" => Ok(InventoryAction::DropAllSlot { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "DROP_ONE_SLOT" => Ok(InventoryAction::DropOneSlot { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "MOVE_TO_OTHER_INVENTORY" => Ok(InventoryAction::MoveToOtherInventory { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "HOTBAR_MOVE_AND_READD" => Ok(InventoryAction::HotbarMoveAndReadd { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "HOTBAR_SWAP" => Ok(InventoryAction::HotbarSwap { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "CLONE_STACK" => Ok(InventoryAction::CloneStack { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "COLLECT_TO_CURSOR" => Ok(InventoryAction::CollectToCursor { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(InventoryAction::Unknown { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } + #[repr(C)] -pub struct InventoryCloseEvent<'mc>( +pub struct InventoryActionStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for InventoryCloseEvent<'mc> { +impl<'mc> JNIRaw<'mc> for InventoryAction<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + match self { + Self::Nothing { inner } => inner.0.clone(), + Self::PickupAll { inner } => inner.0.clone(), + Self::PickupSome { inner } => inner.0.clone(), + Self::PickupHalf { inner } => inner.0.clone(), + Self::PickupOne { inner } => inner.0.clone(), + Self::PlaceAll { inner } => inner.0.clone(), + Self::PlaceSome { inner } => inner.0.clone(), + Self::PlaceOne { inner } => inner.0.clone(), + Self::SwapWithCursor { inner } => inner.0.clone(), + Self::DropAllCursor { inner } => inner.0.clone(), + Self::DropOneCursor { inner } => inner.0.clone(), + Self::DropAllSlot { inner } => inner.0.clone(), + Self::DropOneSlot { inner } => inner.0.clone(), + Self::MoveToOtherInventory { inner } => inner.0.clone(), + Self::HotbarMoveAndReadd { inner } => inner.0.clone(), + Self::HotbarSwap { inner } => inner.0.clone(), + Self::CloneStack { inner } => inner.0.clone(), + Self::CollectToCursor { inner } => inner.0.clone(), + Self::Unknown { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + match self { + Self::Nothing { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PickupAll { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PickupSome { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PickupHalf { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PickupOne { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PlaceAll { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PlaceSome { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PlaceOne { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SwapWithCursor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DropAllCursor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DropOneCursor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DropAllSlot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DropOneSlot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MoveToOtherInventory { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HotbarMoveAndReadd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HotbarSwap { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CloneStack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CollectToCursor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Unknown { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for InventoryCloseEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for InventoryAction<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate InventoryCloseEvent from null object.").into(), + eyre::eyre!("Tried to instantiate InventoryAction from null object.").into(), ); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/inventory/InventoryCloseEvent")?; + env.validate_name(&obj, "org/bukkit/event/inventory/InventoryAction")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a InventoryCloseEvent object, got {}", + "Invalid argument passed. Expected a InventoryAction object, got {}", name ) .into()) } else { - Ok(Self(env.clone(), obj)) + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "NOTHING" => Ok(InventoryAction::Nothing { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "PICKUP_ALL" => Ok(InventoryAction::PickupAll { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "PICKUP_SOME" => Ok(InventoryAction::PickupSome { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "PICKUP_HALF" => Ok(InventoryAction::PickupHalf { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "PICKUP_ONE" => Ok(InventoryAction::PickupOne { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "PLACE_ALL" => Ok(InventoryAction::PlaceAll { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "PLACE_SOME" => Ok(InventoryAction::PlaceSome { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "PLACE_ONE" => Ok(InventoryAction::PlaceOne { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "SWAP_WITH_CURSOR" => Ok(InventoryAction::SwapWithCursor { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "DROP_ALL_CURSOR" => Ok(InventoryAction::DropAllCursor { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "DROP_ONE_CURSOR" => Ok(InventoryAction::DropOneCursor { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "DROP_ALL_SLOT" => Ok(InventoryAction::DropAllSlot { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "DROP_ONE_SLOT" => Ok(InventoryAction::DropOneSlot { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "MOVE_TO_OTHER_INVENTORY" => Ok(InventoryAction::MoveToOtherInventory { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "HOTBAR_MOVE_AND_READD" => Ok(InventoryAction::HotbarMoveAndReadd { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "HOTBAR_SWAP" => Ok(InventoryAction::HotbarSwap { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "CLONE_STACK" => Ok(InventoryAction::CloneStack { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "COLLECT_TO_CURSOR" => Ok(InventoryAction::CollectToCursor { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(InventoryAction::Unknown { + inner: InventoryActionStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } } -impl<'mc> InventoryCloseEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - transaction: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/InventoryView;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transaction.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/event/inventory/InventoryCloseEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error_no_gen(res)?; - crate::event::inventory::InventoryCloseEvent::from_raw(&jni, res) +impl<'mc> JNIRaw<'mc> for InventoryActionStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Returns the player involved in this event - pub fn player(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::HumanEntity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} +impl<'mc> JNIInstantiatable<'mc> for InventoryActionStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate InventoryActionStruct from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/inventory/InventoryAction")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a InventoryActionStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } +} - pub fn handler_list( +impl<'mc> InventoryActionStruct<'mc> { + pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/inventory/InventoryCloseEvent"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/inventory/InventoryAction;"); + let cls = jni.find_class("org/bukkit/event/inventory/InventoryAction"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.inventory.InventoryEvent ( ['getPlayer', 'getHandlers', 'getHandlerList']) - /// Gets the primary Inventory involved in this transaction - pub fn inventory( - &self, - ) -> Result, Box> { - let temp_clone = crate::event::inventory::InventoryEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryEvent = temp_clone.into(); - real.inventory() - } - /// Gets the list of players viewing the primary (upper) inventory involved - /// in this event - pub fn viewers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getViewers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::HumanEntity::from_raw(&self.0, obj)?); - } - Ok(new_vec) - } - /// Gets the view object itself - pub fn view(&self) -> Result, Box> { - let temp_clone = crate::event::inventory::InventoryEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryEvent = temp_clone.into(); - real.view() + crate::event::inventory::InventoryAction::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -3646,20 +4683,13 @@ impl<'mc> InventoryCloseEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for InventoryCloseEvent<'mc> { - fn into(self) -> crate::event::inventory::InventoryEvent<'mc> { - crate::event::inventory::InventoryEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting InventoryCloseEvent into crate::event::inventory::InventoryEvent", - ) - } -} #[repr(C)] -pub struct InventoryInteractEvent<'mc>( +pub struct InventoryPickupItemEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for InventoryInteractEvent<'mc> { +impl<'mc> JNIRaw<'mc> for InventoryPickupItemEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3667,22 +4697,22 @@ impl<'mc> JNIRaw<'mc> for InventoryInteractEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for InventoryInteractEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for InventoryPickupItemEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate InventoryInteractEvent from null object." + "Tried to instantiate InventoryPickupItemEvent from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/inventory/InventoryInteractEvent")?; + env.validate_name(&obj, "org/bukkit/event/inventory/InventoryPickupItemEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a InventoryInteractEvent object, got {}", + "Invalid argument passed. Expected a InventoryPickupItemEvent object, got {}", name ) .into()) @@ -3692,77 +4722,58 @@ impl<'mc> JNIInstantiatable<'mc> for InventoryInteractEvent<'mc> { } } -impl<'mc> InventoryInteractEvent<'mc> { +impl<'mc> InventoryPickupItemEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - transaction: impl Into>, - ) -> Result, Box> + inventory: impl Into>, + item: impl Into>, + ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/InventoryView;)V"); + let sig = String::from("(Lorg/bukkit/inventory/Inventory;Lorg/bukkit/entity/Item;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transaction.into().jni_object().clone()) + jni::objects::JObject::from_raw(inventory.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/inventory/InventoryInteractEvent"); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/inventory/InventoryPickupItemEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::inventory::InventoryInteractEvent::from_raw(&jni, res) + crate::event::inventory::InventoryPickupItemEvent::from_raw(&jni, res) } - /// Gets the player who performed the click. - pub fn who_clicked( + /// Gets the Inventory that picked up the item + pub fn inventory( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getWhoClicked", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::HumanEntity::from_raw(&self.jni_ref(), unsafe { + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the result of this event. This will change whether or not this - /// event is considered cancelled. - pub fn set_result( - &self, - new_result: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/Event/Result;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_result.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setResult", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the {@link org.bukkit.event.Event.Result} of this event. The Result describes the - /// behavior that will be applied to the inventory in relation to this - /// event. - pub fn result(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/Event/Result;"); + /// Gets the Item entity that was picked up + pub fn item(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Item;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getResult", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::event::EventResult::from_raw(&self.jni_ref(), unsafe { + crate::entity::Item::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets whether or not this event is cancelled. This is based off of the - /// Result value returned by {@link #getResult()}.Result.ALLOW and - /// Result.DEFAULT will result in a returned value of false, but - /// Result.DENY will result in a returned value of true. - /// - /// {@inheritDoc} + pub fn is_cancelled(&self) -> Result> { let sig = String::from("()Z"); let res = @@ -3771,14 +4782,10 @@ impl<'mc> InventoryInteractEvent<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Proxy method to {@link #setResult(org.bukkit.event.Event.Result)} for the Cancellable - /// interface. {@link #setResult(org.bukkit.event.Event.Result)} is preferred, as it allows - /// you to specify the Result beyond Result.DENY and Result.ALLOW. - /// - /// {@inheritDoc} - pub fn set_cancelled(&self, to_cancel: bool) -> Result<(), Box> { + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(to_cancel.into()); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); let res = self.jni_ref().call_method( &self.jni_object(), "setCancelled", @@ -3788,44 +4795,6 @@ impl<'mc> InventoryInteractEvent<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - // SUPER CLASS: org.bukkit.event.inventory.InventoryEvent ( ['getWhoClicked', 'setResult', 'getResult', 'isCancelled', 'setCancelled']) - /// Gets the primary Inventory involved in this transaction - pub fn inventory( - &self, - ) -> Result, Box> { - let temp_clone = crate::event::inventory::InventoryEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryEvent = temp_clone.into(); - real.inventory() - } - /// Gets the list of players viewing the primary (upper) inventory involved - /// in this event - pub fn viewers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getViewers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::HumanEntity::from_raw(&self.0, obj)?); - } - Ok(new_vec) - } - /// Gets the view object itself - pub fn view(&self) -> Result, Box> { - let temp_clone = crate::event::inventory::InventoryEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryEvent = temp_clone.into(); - real.view() - } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -3841,7 +4810,50 @@ impl<'mc> InventoryInteractEvent<'mc> { pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { - crate::event::inventory::InventoryEvent::handler_list(jni) + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/inventory/InventoryPickupItemEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.Event ( ['getInventory', 'getItem', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + /// Convenience method for providing a user-friendly identifier. By + /// default, it is the event's class's {@linkplain Class#getSimpleName() + /// simple name}. + pub fn event_name(&self) -> Result> { + let temp_clone = crate::event::Event::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::Event = temp_clone.into(); + real.event_name() + } + /// Any custom event that should not by synchronized with other events must + /// use the specific constructor. These are the caveats of using an + /// asynchronous event: + ///
    + ///
  • The event is never fired from inside code triggered by a + /// synchronous event. Attempting to do so results in an {@link + /// java.lang.IllegalStateException}. + ///
  • However, asynchronous event handlers may fire synchronous or + /// asynchronous events + ///
  • The event may be fired multiple times simultaneously and in any + /// order. + ///
  • Any newly registered or unregistered handler is ignored after an + /// event starts execution. + ///
  • The handlers for this event may block for any length of time. + ///
  • Some implementations may selectively declare a specific event use + /// as asynchronous. This behavior should be clearly defined. + ///
  • Asynchronous calls are not calculated in the plugin timing system. + ///
+ pub fn is_asynchronous(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isAsynchronous", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -3849,26 +4861,25 @@ impl<'mc> InventoryInteractEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for InventoryInteractEvent<'mc> { +impl<'mc> Into> for InventoryPickupItemEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting InventoryInteractEvent into crate::event::Cancellable") + .expect("Error converting InventoryPickupItemEvent into crate::event::Cancellable") } } -impl<'mc> Into> for InventoryInteractEvent<'mc> { - fn into(self) -> crate::event::inventory::InventoryEvent<'mc> { - crate::event::inventory::InventoryEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting InventoryInteractEvent into crate::event::inventory::InventoryEvent", - ) +impl<'mc> Into> for InventoryPickupItemEvent<'mc> { + fn into(self) -> crate::event::Event<'mc> { + crate::event::Event::from_raw(&self.jni_ref(), self.1) + .expect("Error converting InventoryPickupItemEvent into crate::event::Event") } } #[repr(C)] -pub struct PrepareAnvilEvent<'mc>( +pub struct InventoryCloseEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PrepareAnvilEvent<'mc> { +impl<'mc> JNIRaw<'mc> for InventoryCloseEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3876,21 +4887,21 @@ impl<'mc> JNIRaw<'mc> for PrepareAnvilEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PrepareAnvilEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for InventoryCloseEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate PrepareAnvilEvent from null object.").into(), + eyre::eyre!("Tried to instantiate InventoryCloseEvent from null object.").into(), ); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/inventory/PrepareAnvilEvent")?; + env.validate_name(&obj, "org/bukkit/event/inventory/InventoryCloseEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PrepareAnvilEvent object, got {}", + "Invalid argument passed. Expected a InventoryCloseEvent object, got {}", name ) .into()) @@ -3900,43 +4911,33 @@ impl<'mc> JNIInstantiatable<'mc> for PrepareAnvilEvent<'mc> { } } -impl<'mc> PrepareAnvilEvent<'mc> { +impl<'mc> InventoryCloseEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - inventory: impl Into>, - result: impl Into>, - ) -> Result, Box> { - let sig = - String::from("(Lorg/bukkit/inventory/InventoryView;Lorg/bukkit/inventory/ItemStack;)V"); + transaction: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/InventoryView;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(inventory.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(result.into().jni_object().clone()) + jni::objects::JObject::from_raw(transaction.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/inventory/PrepareAnvilEvent"); + let cls = jni.find_class("org/bukkit/event/inventory/InventoryCloseEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = jni.translate_error_no_gen(res)?; - crate::event::inventory::PrepareAnvilEvent::from_raw(&jni, res) + crate::event::inventory::InventoryCloseEvent::from_raw(&jni, res) } - - pub fn inventory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/AnvilInventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + /// Returns the player involved in this event + pub fn player(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::AnvilInventory::from_raw(&self.jni_ref(), unsafe { + crate::entity::HumanEntity::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -3956,36 +4957,50 @@ impl<'mc> PrepareAnvilEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/inventory/PrepareAnvilEvent"); + let cls = jni.find_class("org/bukkit/event/inventory/InventoryCloseEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.inventory.PrepareInventoryResultEvent ( ['getInventory', 'getHandlers', 'getHandlerList']) - /// Get result item, may be null. - pub fn result( + // SUPER CLASS: org.bukkit.event.inventory.InventoryEvent ( ['getPlayer', 'getHandlers', 'getHandlerList']) + /// Gets the primary Inventory involved in this transaction + pub fn inventory( &self, - ) -> Result>, Box> { - let temp_clone = - crate::event::inventory::PrepareInventoryResultEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::PrepareInventoryResultEvent = temp_clone.into(); - real.result() + ) -> Result, Box> { + let temp_clone = crate::event::inventory::InventoryEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryEvent = temp_clone.into(); + real.inventory() } - /// Set result item, may be null. - pub fn set_result( + /// Gets the list of players viewing the primary (upper) inventory involved + /// in this event + pub fn viewers( &self, - result: impl Into>, - ) -> Result<(), Box> { - let temp_clone = - crate::event::inventory::PrepareInventoryResultEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::PrepareInventoryResultEvent = temp_clone.into(); - real.set_result(result) + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getViewers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::HumanEntity::from_raw(&self.0, obj)?); + } + Ok(new_vec) + } + /// Gets the view object itself + pub fn view(&self) -> Result, Box> { + let temp_clone = crate::event::inventory::InventoryEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryEvent = temp_clone.into(); + real.view() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -3993,20 +5008,20 @@ impl<'mc> PrepareAnvilEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> - for PrepareAnvilEvent<'mc> -{ - fn into(self) -> crate::event::inventory::PrepareInventoryResultEvent<'mc> { - crate::event::inventory::PrepareInventoryResultEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting PrepareAnvilEvent into crate::event::inventory::PrepareInventoryResultEvent") +impl<'mc> Into> for InventoryCloseEvent<'mc> { + fn into(self) -> crate::event::inventory::InventoryEvent<'mc> { + crate::event::inventory::InventoryEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting InventoryCloseEvent into crate::event::inventory::InventoryEvent", + ) } } #[repr(C)] -pub struct InventoryCreativeEvent<'mc>( +pub struct InventoryInteractEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for InventoryCreativeEvent<'mc> { +impl<'mc> JNIRaw<'mc> for InventoryInteractEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -4014,22 +5029,22 @@ impl<'mc> JNIRaw<'mc> for InventoryCreativeEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for InventoryCreativeEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for InventoryInteractEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate InventoryCreativeEvent from null object." + "Tried to instantiate InventoryInteractEvent from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/inventory/InventoryCreativeEvent")?; + env.validate_name(&obj, "org/bukkit/event/inventory/InventoryInteractEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a InventoryCreativeEvent object, got {}", + "Invalid argument passed. Expected a InventoryInteractEvent object, got {}", name ) .into()) @@ -4039,193 +5054,139 @@ impl<'mc> JNIInstantiatable<'mc> for InventoryCreativeEvent<'mc> { } } -impl<'mc> InventoryCreativeEvent<'mc> { +impl<'mc> InventoryInteractEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - what: impl Into>, - val_type: impl Into>, - slot: i32, - new_item: impl Into>, - ) -> Result, Box> + transaction: impl Into>, + ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/InventoryView;Lorg/bukkit/event/inventory/InventoryType/SlotType;ILorg/bukkit/inventory/ItemStack;)V"); + let sig = String::from("(Lorg/bukkit/inventory/InventoryView;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(what.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Int(slot); - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_item.into().jni_object().clone()) + jni::objects::JObject::from_raw(transaction.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/inventory/InventoryCreativeEvent"); + let cls = jni.find_class("org/bukkit/event/inventory/InventoryInteractEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - ], - ); - let res = jni.translate_error_no_gen(res)?; - crate::event::inventory::InventoryCreativeEvent::from_raw(&jni, res) - } - - pub fn cursor(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getCursor", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn set_cursor( - &self, - item: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCursor", - sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - // SUPER CLASS: org.bukkit.event.inventory.InventoryClickEvent ( ['getCursor', 'setCursor']) - /// Gets the type of slot that was clicked. - pub fn slot_type( - &self, - ) -> Result, Box> - { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.slot_type() - } - /// Gets the ItemStack currently in the clicked slot. - pub fn current_item( - &self, - ) -> Result>, Box> { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.current_item() - } - /// Gets whether or not the ClickType for this event represents a right - /// click. - pub fn is_right_click(&self) -> Result> { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.is_right_click() - } - /// Gets whether or not the ClickType for this event represents a left - /// click. - pub fn is_left_click(&self) -> Result> { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.is_left_click() - } - /// Gets whether the ClickType for this event indicates that the key was - /// pressed down when the click was made. - pub fn is_shift_click(&self) -> Result> { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.is_shift_click() - } - /// Sets the ItemStack currently in the clicked slot. - pub fn set_current_item( - &self, - stack: impl Into>, - ) -> Result<(), Box> { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.set_current_item(stack) + let res = jni.translate_error_no_gen(res)?; + crate::event::inventory::InventoryInteractEvent::from_raw(&jni, res) } - /// Gets the inventory corresponding to the clicked slot. - pub fn clicked_inventory( + /// Gets the player who performed the click. + pub fn who_clicked( &self, - ) -> Result>, Box> { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.clicked_inventory() + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getWhoClicked", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::HumanEntity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// The slot number that was clicked, ready for passing to - /// {@link Inventory#getItem(int)}. Note that there may be two slots with - /// the same slot number, since a view links two different inventories. - pub fn slot(&self) -> Result> { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.slot() + /// Sets the result of this event. This will change whether or not this + /// event is considered cancelled. + pub fn set_result( + &self, + new_result: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/event/Event/Result;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(new_result.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setResult", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// The raw slot number clicked, ready for passing to {@link InventoryView - /// #getItem(int)} This slot number is unique for the view. - pub fn raw_slot(&self) -> Result> { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.raw_slot() + /// Gets the {@link org.bukkit.event.Event.Result} of this event. The Result describes the + /// behavior that will be applied to the inventory in relation to this + /// event. + pub fn result(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/Event/Result;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getResult", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::EventResult::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// If the ClickType is NUMBER_KEY, this method will return the index of - /// the pressed key (0-8). - pub fn hotbar_button(&self) -> Result> { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.hotbar_button() + /// Gets whether or not this event is cancelled. This is based off of the + /// Result value returned by {@link #getResult()}.Result.ALLOW and + /// Result.DEFAULT will result in a returned value of false, but + /// Result.DENY will result in a returned value of true. + /// + /// {@inheritDoc} + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the InventoryAction that triggered this event. + /// Proxy method to {@link #setResult(org.bukkit.event.Event.Result)} for the Cancellable + /// interface. {@link #setResult(org.bukkit.event.Event.Result)} is preferred, as it allows + /// you to specify the Result beyond Result.DENY and Result.ALLOW. /// - /// This action cannot be changed, and represents what the normal outcome - /// of the event will be. To change the behavior of this - /// InventoryClickEvent, changes must be manually applied. - pub fn action( + /// {@inheritDoc} + pub fn set_cancelled(&self, to_cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(to_cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + // SUPER CLASS: org.bukkit.event.inventory.InventoryEvent ( ['getWhoClicked', 'setResult', 'getResult', 'isCancelled', 'setCancelled']) + /// Gets the primary Inventory involved in this transaction + pub fn inventory( &self, - ) -> Result, Box> { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + ) -> Result, Box> { + let temp_clone = crate::event::inventory::InventoryEvent::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.action() + let real: crate::event::inventory::InventoryEvent = temp_clone.into(); + real.inventory() } - /// Gets the ClickType for this event. - /// - /// This is insulated against changes to the inventory by other plugins. - pub fn click( + /// Gets the list of players viewing the primary (upper) inventory involved + /// in this event + pub fn viewers( &self, - ) -> Result, Box> { - let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getViewers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::HumanEntity::from_raw(&self.0, obj)?); + } + Ok(new_vec) + } + /// Gets the view object itself + pub fn view(&self) -> Result, Box> { + let temp_clone = crate::event::inventory::InventoryEvent::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); - real.click() + let real: crate::event::inventory::InventoryEvent = temp_clone.into(); + real.view() } pub fn handlers(&self) -> Result, Box> { @@ -4242,7 +5203,7 @@ impl<'mc> InventoryCreativeEvent<'mc> { pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { - crate::event::inventory::InventoryClickEvent::handler_list(jni) + crate::event::inventory::InventoryEvent::handler_list(jni) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -4250,18 +5211,26 @@ impl<'mc> InventoryCreativeEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for InventoryCreativeEvent<'mc> { - fn into(self) -> crate::event::inventory::InventoryClickEvent<'mc> { - crate::event::inventory::InventoryClickEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting InventoryCreativeEvent into crate::event::inventory::InventoryClickEvent") +impl<'mc> Into> for InventoryInteractEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting InventoryInteractEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for InventoryInteractEvent<'mc> { + fn into(self) -> crate::event::inventory::InventoryEvent<'mc> { + crate::event::inventory::InventoryEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting InventoryInteractEvent into crate::event::inventory::InventoryEvent", + ) } } #[repr(C)] -pub struct InventoryOpenEvent<'mc>( +pub struct PrepareAnvilEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for InventoryOpenEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PrepareAnvilEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -4269,21 +5238,21 @@ impl<'mc> JNIRaw<'mc> for InventoryOpenEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for InventoryOpenEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PrepareAnvilEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate InventoryOpenEvent from null object.").into(), + eyre::eyre!("Tried to instantiate PrepareAnvilEvent from null object.").into(), ); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/inventory/InventoryOpenEvent")?; + env.validate_name(&obj, "org/bukkit/event/inventory/PrepareAnvilEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a InventoryOpenEvent object, got {}", + "Invalid argument passed. Expected a PrepareAnvilEvent object, got {}", name ) .into()) @@ -4293,65 +5262,59 @@ impl<'mc> JNIInstantiatable<'mc> for InventoryOpenEvent<'mc> { } } -impl<'mc> InventoryOpenEvent<'mc> { +impl<'mc> PrepareAnvilEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - transaction: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/InventoryView;)V"); + inventory: impl Into>, + result: impl Into>, + ) -> Result, Box> { + let sig = String::from( + "(Lorg/bukkit/inventory/view/AnvilView;Lorg/bukkit/inventory/ItemStack;)V", + ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(transaction.into().jni_object().clone()) + jni::objects::JObject::from_raw(inventory.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/inventory/InventoryOpenEvent"); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(result.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/inventory/PrepareAnvilEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::inventory::InventoryOpenEvent::from_raw(&jni, res) + crate::event::inventory::PrepareAnvilEvent::from_raw(&jni, res) } - /// Returns the player involved in this event - pub fn player(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); + + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/AnvilInventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::HumanEntity::from_raw(&self.jni_ref(), unsafe { + crate::inventory::AnvilInventory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the cancellation state of this event. A cancelled event will not - /// be executed in the server, but will still pass to other plugins. - /// - /// If an inventory open event is cancelled, the inventory screen will not - /// show. - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + + pub fn view( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/view/AnvilView;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getView", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets the cancellation state of this event. A cancelled event will not - /// be executed in the server, but will still pass to other plugins. - /// - /// If an inventory open event is cancelled, the inventory screen will not - /// show. - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::inventory::view::AnvilView::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn handlers(&self) -> Result, Box> { @@ -4369,50 +5332,36 @@ impl<'mc> InventoryOpenEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/inventory/InventoryOpenEvent"); + let cls = jni.find_class("org/bukkit/event/inventory/PrepareAnvilEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.inventory.InventoryEvent ( ['getPlayer', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) - /// Gets the primary Inventory involved in this transaction - pub fn inventory( - &self, - ) -> Result, Box> { - let temp_clone = crate::event::inventory::InventoryEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryEvent = temp_clone.into(); - real.inventory() - } - /// Gets the list of players viewing the primary (upper) inventory involved - /// in this event - pub fn viewers( + } + // SUPER CLASS: org.bukkit.event.inventory.PrepareInventoryResultEvent ( ['getInventory', 'getView', 'getHandlers', 'getHandlerList']) + /// Get result item, may be null. + pub fn result( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getViewers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::HumanEntity::from_raw(&self.0, obj)?); - } - Ok(new_vec) + ) -> Result>, Box> { + let temp_clone = + crate::event::inventory::PrepareInventoryResultEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::PrepareInventoryResultEvent = temp_clone.into(); + real.result() } - /// Gets the view object itself - pub fn view(&self) -> Result, Box> { - let temp_clone = crate::event::inventory::InventoryEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryEvent = temp_clone.into(); - real.view() + /// Set result item, may be null. + pub fn set_result( + &self, + result: impl Into>, + ) -> Result<(), Box> { + let temp_clone = + crate::event::inventory::PrepareInventoryResultEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::PrepareInventoryResultEvent = temp_clone.into(); + real.set_result(result) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -4420,26 +5369,20 @@ impl<'mc> InventoryOpenEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for InventoryOpenEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting InventoryOpenEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for InventoryOpenEvent<'mc> { - fn into(self) -> crate::event::inventory::InventoryEvent<'mc> { - crate::event::inventory::InventoryEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting InventoryOpenEvent into crate::event::inventory::InventoryEvent", - ) +impl<'mc> Into> + for PrepareAnvilEvent<'mc> +{ + fn into(self) -> crate::event::inventory::PrepareInventoryResultEvent<'mc> { + crate::event::inventory::PrepareInventoryResultEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting PrepareAnvilEvent into crate::event::inventory::PrepareInventoryResultEvent") } } #[repr(C)] -pub struct InventoryClickEvent<'mc>( +pub struct InventoryCreativeEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for InventoryClickEvent<'mc> { +impl<'mc> JNIRaw<'mc> for InventoryCreativeEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -4447,21 +5390,22 @@ impl<'mc> JNIRaw<'mc> for InventoryClickEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for InventoryClickEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for InventoryCreativeEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate InventoryClickEvent from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate InventoryCreativeEvent from null object." + ) + .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/inventory/InventoryClickEvent")?; + env.validate_name(&obj, "org/bukkit/event/inventory/InventoryCreativeEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a InventoryClickEvent object, got {}", + "Invalid argument passed. Expected a InventoryCreativeEvent object, got {}", name ) .into()) @@ -4471,218 +5415,167 @@ impl<'mc> JNIInstantiatable<'mc> for InventoryClickEvent<'mc> { } } -impl<'mc> InventoryClickEvent<'mc> { +impl<'mc> InventoryCreativeEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - view: impl Into>, + what: impl Into>, val_type: impl Into>, slot: i32, - click: impl Into>, - action: impl Into>, - key: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/InventoryView;"; + new_item: impl Into>, + ) -> Result, Box> + { + let sig = String::from("(Lorg/bukkit/inventory/InventoryView;Lorg/bukkit/event/inventory/InventoryType/SlotType;ILorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(view.into().jni_object().clone()) + jni::objects::JObject::from_raw(what.into().jni_object().clone()) }); - args.push(val_1); - sig += "Lorg/bukkit/event/inventory/InventoryType/SlotType;"; let val_2 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); - args.push(val_2); - sig += "I"; let val_3 = jni::objects::JValueGen::Int(slot); - args.push(val_3); - sig += "Lorg/bukkit/event/inventory/ClickType;"; let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(click.into().jni_object().clone()) - }); - args.push(val_4); - sig += "Lorg/bukkit/event/inventory/InventoryAction;"; - let val_5 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(action.into().jni_object().clone()) + jni::objects::JObject::from_raw(new_item.into().jni_object().clone()) }); - args.push(val_5); - if let Some(a) = key { - sig += "I"; - let val_6 = jni::objects::JValueGen::Int(a); - args.push(val_6); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/event/inventory/InventoryClickEvent"); + let cls = jni.find_class("org/bukkit/event/inventory/InventoryCreativeEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + ], + ); let res = jni.translate_error_no_gen(res)?; - crate::event::inventory::InventoryClickEvent::from_raw(&jni, res) - } - /// Gets the type of slot that was clicked. - pub fn slot_type( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType/SlotType;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSlotType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::inventory::InventoryTypeSlotType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + crate::event::inventory::InventoryCreativeEvent::from_raw(&jni, res) } - /// Gets the current ItemStack on the cursor. - pub fn cursor( - &self, - ) -> Result>, Box> { + + pub fn cursor(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self .jni_ref() .call_method(&self.jni_object(), "getCursor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn set_cursor( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCursor", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + // SUPER CLASS: org.bukkit.event.inventory.InventoryClickEvent ( ['getCursor', 'setCursor']) + /// Gets the type of slot that was clicked. + pub fn slot_type( + &self, + ) -> Result, Box> + { + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.slot_type() } /// Gets the ItemStack currently in the clicked slot. pub fn current_item( &self, ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCurrentItem", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.current_item() } /// Gets whether or not the ClickType for this event represents a right /// click. pub fn is_right_click(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isRightClick", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.is_right_click() } /// Gets whether or not the ClickType for this event represents a left /// click. pub fn is_left_click(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isLeftClick", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.is_left_click() } /// Gets whether the ClickType for this event indicates that the key was /// pressed down when the click was made. pub fn is_shift_click(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isShiftClick", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Sets the item on the cursor. - pub fn set_cursor( - &self, - stack: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(stack.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCursor", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.is_shift_click() } /// Sets the ItemStack currently in the clicked slot. pub fn set_current_item( &self, stack: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(stack.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCurrentItem", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.set_current_item(stack) } /// Gets the inventory corresponding to the clicked slot. pub fn clicked_inventory( &self, ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getClickedInventory", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::Inventory::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.clicked_inventory() } /// The slot number that was clicked, ready for passing to /// {@link Inventory#getItem(int)}. Note that there may be two slots with /// the same slot number, since a view links two different inventories. pub fn slot(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSlot", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.slot() } /// The raw slot number clicked, ready for passing to {@link InventoryView /// #getItem(int)} This slot number is unique for the view. pub fn raw_slot(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRawSlot", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.raw_slot() } /// If the ClickType is NUMBER_KEY, this method will return the index of /// the pressed key (0-8). pub fn hotbar_button(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHotbarButton", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.hotbar_button() } /// Gets the InventoryAction that triggered this event. /// @@ -4692,14 +5585,11 @@ impl<'mc> InventoryClickEvent<'mc> { pub fn action( &self, ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/inventory/InventoryAction;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getAction", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::inventory::InventoryAction::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.action() } /// Gets the ClickType for this event. /// @@ -4707,14 +5597,11 @@ impl<'mc> InventoryClickEvent<'mc> { pub fn click( &self, ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/inventory/ClickType;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getClick", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::inventory::ClickType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let temp_clone = crate::event::inventory::InventoryClickEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryClickEvent = temp_clone.into(); + real.click() } pub fn handlers(&self) -> Result, Box> { @@ -4731,76 +5618,177 @@ impl<'mc> InventoryClickEvent<'mc> { pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/inventory/InventoryClickEvent"); + crate::event::inventory::InventoryClickEvent::handler_list(jni) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for InventoryCreativeEvent<'mc> { + fn into(self) -> crate::event::inventory::InventoryClickEvent<'mc> { + crate::event::inventory::InventoryClickEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting InventoryCreativeEvent into crate::event::inventory::InventoryClickEvent") + } +} +#[repr(C)] +pub struct InventoryOpenEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for InventoryOpenEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for InventoryOpenEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate InventoryOpenEvent from null object.").into(), + ); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/inventory/InventoryOpenEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a InventoryOpenEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> InventoryOpenEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + transaction: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/InventoryView;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(transaction.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/inventory/InventoryOpenEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) + let res = jni.new_object( + cls, + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error_no_gen(res)?; + crate::event::inventory::InventoryOpenEvent::from_raw(&jni, res) } - // SUPER CLASS: org.bukkit.event.inventory.InventoryInteractEvent ( ['getSlotType', 'getCursor', 'getCurrentItem', 'isRightClick', 'isLeftClick', 'isShiftClick', 'setCursor', 'setCurrentItem', 'getClickedInventory', 'getSlot', 'getRawSlot', 'getHotbarButton', 'getAction', 'getClick', 'getHandlers', 'getHandlerList']) - /// Gets the player who performed the click. - pub fn who_clicked( - &self, - ) -> Result, Box> { - let temp_clone = - crate::event::inventory::InventoryInteractEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryInteractEvent = temp_clone.into(); - real.who_clicked() + /// Returns the player involved in this event + pub fn player(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::HumanEntity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the result of this event. This will change whether or not this - /// event is considered cancelled. - pub fn set_result( - &self, - new_result: impl Into>, - ) -> Result<(), Box> { - let temp_clone = - crate::event::inventory::InventoryInteractEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryInteractEvent = temp_clone.into(); - real.set_result(new_result) + /// Gets the cancellation state of this event. A cancelled event will not + /// be executed in the server, but will still pass to other plugins. + /// + /// If an inventory open event is cancelled, the inventory screen will not + /// show. + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the {@link org.bukkit.event.Event.Result} of this event. The Result describes the - /// behavior that will be applied to the inventory in relation to this - /// event. - pub fn result(&self) -> Result, Box> { - let temp_clone = - crate::event::inventory::InventoryInteractEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryInteractEvent = temp_clone.into(); - real.result() + /// Sets the cancellation state of this event. A cancelled event will not + /// be executed in the server, but will still pass to other plugins. + /// + /// If an inventory open event is cancelled, the inventory screen will not + /// show. + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/inventory/InventoryOpenEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) } - /// Gets whether or not this event is cancelled. This is based off of the - /// Result value returned by {@link #getResult()}.Result.ALLOW and - /// Result.DEFAULT will result in a returned value of false, but - /// Result.DENY will result in a returned value of true. - /// - /// {@inheritDoc} - pub fn is_cancelled(&self) -> Result> { - let temp_clone = - crate::event::inventory::InventoryInteractEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryInteractEvent = temp_clone.into(); - real.is_cancelled() + // SUPER CLASS: org.bukkit.event.inventory.InventoryEvent ( ['getPlayer', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + /// Gets the primary Inventory involved in this transaction + pub fn inventory( + &self, + ) -> Result, Box> { + let temp_clone = crate::event::inventory::InventoryEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryEvent = temp_clone.into(); + real.inventory() } - /// Proxy method to {@link #setResult(org.bukkit.event.Event.Result)} for the Cancellable - /// interface. {@link #setResult(org.bukkit.event.Event.Result)} is preferred, as it allows - /// you to specify the Result beyond Result.DENY and Result.ALLOW. - /// - /// {@inheritDoc} - pub fn set_cancelled(&self, to_cancel: bool) -> Result<(), Box> { - let temp_clone = - crate::event::inventory::InventoryInteractEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::inventory::InventoryInteractEvent = temp_clone.into(); - real.set_cancelled(to_cancel) + /// Gets the list of players viewing the primary (upper) inventory involved + /// in this event + pub fn viewers( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getViewers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::HumanEntity::from_raw(&self.0, obj)?); + } + Ok(new_vec) + } + /// Gets the view object itself + pub fn view(&self) -> Result, Box> { + let temp_clone = crate::event::inventory::InventoryEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::inventory::InventoryEvent = temp_clone.into(); + real.view() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -4808,15 +5796,74 @@ impl<'mc> InventoryClickEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for InventoryClickEvent<'mc> { - fn into(self) -> crate::event::inventory::InventoryInteractEvent<'mc> { - crate::event::inventory::InventoryInteractEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting InventoryClickEvent into crate::event::inventory::InventoryInteractEvent") +impl<'mc> Into> for InventoryOpenEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting InventoryOpenEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for InventoryOpenEvent<'mc> { + fn into(self) -> crate::event::inventory::InventoryEvent<'mc> { + crate::event::inventory::InventoryEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting InventoryOpenEvent into crate::event::inventory::InventoryEvent", + ) } } -pub enum ClickType<'mc> {} +pub enum ClickType<'mc> { + Left { inner: ClickTypeStruct<'mc> }, + ShiftLeft { inner: ClickTypeStruct<'mc> }, + Right { inner: ClickTypeStruct<'mc> }, + ShiftRight { inner: ClickTypeStruct<'mc> }, + WindowBorderLeft { inner: ClickTypeStruct<'mc> }, + WindowBorderRight { inner: ClickTypeStruct<'mc> }, + Middle { inner: ClickTypeStruct<'mc> }, + NumberKey { inner: ClickTypeStruct<'mc> }, + DoubleClick { inner: ClickTypeStruct<'mc> }, + Drop { inner: ClickTypeStruct<'mc> }, + ControlDrop { inner: ClickTypeStruct<'mc> }, + Creative { inner: ClickTypeStruct<'mc> }, + SwapOffhand { inner: ClickTypeStruct<'mc> }, + Unknown { inner: ClickTypeStruct<'mc> }, +} impl<'mc> std::fmt::Display for ClickType<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + ClickType::Left { .. } => f.write_str("LEFT"), + ClickType::ShiftLeft { .. } => f.write_str("SHIFT_LEFT"), + ClickType::Right { .. } => f.write_str("RIGHT"), + ClickType::ShiftRight { .. } => f.write_str("SHIFT_RIGHT"), + ClickType::WindowBorderLeft { .. } => f.write_str("WINDOW_BORDER_LEFT"), + ClickType::WindowBorderRight { .. } => f.write_str("WINDOW_BORDER_RIGHT"), + ClickType::Middle { .. } => f.write_str("MIDDLE"), + ClickType::NumberKey { .. } => f.write_str("NUMBER_KEY"), + ClickType::DoubleClick { .. } => f.write_str("DOUBLE_CLICK"), + ClickType::Drop { .. } => f.write_str("DROP"), + ClickType::ControlDrop { .. } => f.write_str("CONTROL_DROP"), + ClickType::Creative { .. } => f.write_str("CREATIVE"), + ClickType::SwapOffhand { .. } => f.write_str("SWAP_OFFHAND"), + ClickType::Unknown { .. } => f.write_str("UNKNOWN"), + } + } +} +impl<'mc> std::ops::Deref for ClickType<'mc> { + type Target = ClickTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + ClickType::Left { inner } => inner, + ClickType::ShiftLeft { inner } => inner, + ClickType::Right { inner } => inner, + ClickType::ShiftRight { inner } => inner, + ClickType::WindowBorderLeft { inner } => inner, + ClickType::WindowBorderRight { inner } => inner, + ClickType::Middle { inner } => inner, + ClickType::NumberKey { inner } => inner, + ClickType::DoubleClick { inner } => inner, + ClickType::Drop { inner } => inner, + ClickType::ControlDrop { inner } => inner, + ClickType::Creative { inner } => inner, + ClickType::SwapOffhand { inner } => inner, + ClickType::Unknown { inner } => inner, + } } } @@ -4843,6 +5890,49 @@ impl<'mc> ClickType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "LEFT" => Ok(ClickType::Left { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "SHIFT_LEFT" => Ok(ClickType::ShiftLeft { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "RIGHT" => Ok(ClickType::Right { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "SHIFT_RIGHT" => Ok(ClickType::ShiftRight { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "WINDOW_BORDER_LEFT" => Ok(ClickType::WindowBorderLeft { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "WINDOW_BORDER_RIGHT" => Ok(ClickType::WindowBorderRight { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "MIDDLE" => Ok(ClickType::Middle { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "NUMBER_KEY" => Ok(ClickType::NumberKey { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "DOUBLE_CLICK" => Ok(ClickType::DoubleClick { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "DROP" => Ok(ClickType::Drop { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "CONTROL_DROP" => Ok(ClickType::ControlDrop { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "CREATIVE" => Ok(ClickType::Creative { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "SWAP_OFFHAND" => Ok(ClickType::SwapOffhand { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(ClickType::Unknown { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -4856,10 +5946,56 @@ pub struct ClickTypeStruct<'mc>( impl<'mc> JNIRaw<'mc> for ClickType<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Left { inner } => inner.0.clone(), + Self::ShiftLeft { inner } => inner.0.clone(), + Self::Right { inner } => inner.0.clone(), + Self::ShiftRight { inner } => inner.0.clone(), + Self::WindowBorderLeft { inner } => inner.0.clone(), + Self::WindowBorderRight { inner } => inner.0.clone(), + Self::Middle { inner } => inner.0.clone(), + Self::NumberKey { inner } => inner.0.clone(), + Self::DoubleClick { inner } => inner.0.clone(), + Self::Drop { inner } => inner.0.clone(), + Self::ControlDrop { inner } => inner.0.clone(), + Self::Creative { inner } => inner.0.clone(), + Self::SwapOffhand { inner } => inner.0.clone(), + Self::Unknown { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Left { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ShiftLeft { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Right { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ShiftRight { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WindowBorderLeft { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WindowBorderRight { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Middle { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::NumberKey { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DoubleClick { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Drop { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ControlDrop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Creative { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SwapOffhand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Unknown { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for ClickType<'mc> { @@ -4885,6 +6021,48 @@ impl<'mc> JNIInstantiatable<'mc> for ClickType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "LEFT" => Ok(ClickType::Left { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "SHIFT_LEFT" => Ok(ClickType::ShiftLeft { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "RIGHT" => Ok(ClickType::Right { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "SHIFT_RIGHT" => Ok(ClickType::ShiftRight { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "WINDOW_BORDER_LEFT" => Ok(ClickType::WindowBorderLeft { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "WINDOW_BORDER_RIGHT" => Ok(ClickType::WindowBorderRight { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "MIDDLE" => Ok(ClickType::Middle { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "NUMBER_KEY" => Ok(ClickType::NumberKey { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "DOUBLE_CLICK" => Ok(ClickType::DoubleClick { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "DROP" => Ok(ClickType::Drop { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "CONTROL_DROP" => Ok(ClickType::ControlDrop { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "CREATIVE" => Ok(ClickType::Creative { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "SWAP_OFFHAND" => Ok(ClickType::SwapOffhand { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(ClickType::Unknown { + inner: ClickTypeStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -5374,10 +6552,10 @@ impl<'mc> JNIInstantiatable<'mc> for TradeSelectEvent<'mc> { impl<'mc> TradeSelectEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - transaction: impl Into>, + transaction: impl Into>, new_index: i32, ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/InventoryView;I)V"); + let sig = String::from("(Lorg/bukkit/inventory/view/MerchantView;I)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(transaction.into().jni_object().clone()) }); @@ -5429,6 +6607,19 @@ impl<'mc> TradeSelectEvent<'mc> { }) } + pub fn view( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/view/MerchantView;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getView", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::view::MerchantView::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); let res = @@ -5451,7 +6642,7 @@ impl<'mc> TradeSelectEvent<'mc> { let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.inventory.InventoryInteractEvent ( ['getIndex', 'getInventory', 'getMerchant', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.inventory.InventoryInteractEvent ( ['getIndex', 'getInventory', 'getMerchant', 'getView', 'getHandlers', 'getHandlerList']) /// Gets the player who performed the click. pub fn who_clicked( &self, @@ -5525,158 +6716,3 @@ impl<'mc> Into> for TradeSe crate::event::inventory::InventoryInteractEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting TradeSelectEvent into crate::event::inventory::InventoryInteractEvent") } } -#[repr(C)] -pub struct FurnaceExtractEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for FurnaceExtractEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for FurnaceExtractEvent<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate FurnaceExtractEvent from null object.").into(), - ); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/inventory/FurnaceExtractEvent")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a FurnaceExtractEvent object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> FurnaceExtractEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - player: impl Into>, - block: impl Into>, - item_type: impl Into>, - item_amount: i32, - exp: i32, - ) -> Result, Box> { - let sig = String::from( - "(Lorg/bukkit/entity/Player;Lorg/bukkit/block/Block;Lorg/bukkit/Material;II)V", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_type.into().jni_object().clone()) - }); - let val_4 = jni::objects::JValueGen::Int(item_amount); - let val_5 = jni::objects::JValueGen::Int(exp); - let cls = jni.find_class("org/bukkit/event/inventory/FurnaceExtractEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - jni::objects::JValueGen::from(val_5), - ], - ); - let res = jni.translate_error_no_gen(res)?; - crate::event::inventory::FurnaceExtractEvent::from_raw(&jni, res) - } - /// Get the player that triggered the event - pub fn player(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Player;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Player::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the Material of the item being retrieved - pub fn item_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the item count being retrieved - pub fn item_amount(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemAmount", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - // SUPER CLASS: org.bukkit.event.block.BlockExpEvent ( ['getPlayer', 'getItemType', 'getItemAmount']) - /// Get the experience dropped by the block after the event has processed - pub fn exp_to_drop(&self) -> Result> { - let temp_clone = crate::event::block::BlockExpEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockExpEvent = temp_clone.into(); - real.exp_to_drop() - } - /// Set the amount of experience dropped by the block after the event has - /// processed - pub fn set_exp_to_drop(&self, exp: i32) -> Result<(), Box> { - let temp_clone = crate::event::block::BlockExpEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::block::BlockExpEvent = temp_clone.into(); - real.set_exp_to_drop(exp) - } - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn handler_list( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - crate::event::block::BlockExpEvent::handler_list(jni) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for FurnaceExtractEvent<'mc> { - fn into(self) -> crate::event::block::BlockExpEvent<'mc> { - crate::event::block::BlockExpEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting FurnaceExtractEvent into crate::event::block::BlockExpEvent") - } -} diff --git a/blackboxmc-rs-bukkit/src/event/mod.rs b/blackboxmc-rs-bukkit/src/event/mod.rs index b0b997c..5e0186a 100644 --- a/blackboxmc-rs-bukkit/src/event/mod.rs +++ b/blackboxmc-rs-bukkit/src/event/mod.rs @@ -171,120 +171,40 @@ impl<'mc> HandlerList<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -#[repr(C)] -pub struct Cancellable<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Cancellable<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } +pub enum EventPriority<'mc> { + Lowest { inner: EventPriorityStruct<'mc> }, + Low { inner: EventPriorityStruct<'mc> }, + Normal { inner: EventPriorityStruct<'mc> }, + High { inner: EventPriorityStruct<'mc> }, + Highest { inner: EventPriorityStruct<'mc> }, + Monitor { inner: EventPriorityStruct<'mc> }, } -impl<'mc> JNIInstantiatable<'mc> for Cancellable<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Cancellable from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/Cancellable")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Cancellable object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) +impl<'mc> std::fmt::Display for EventPriority<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + EventPriority::Lowest { .. } => f.write_str("LOWEST"), + EventPriority::Low { .. } => f.write_str("LOW"), + EventPriority::Normal { .. } => f.write_str("NORMAL"), + EventPriority::High { .. } => f.write_str("HIGH"), + EventPriority::Highest { .. } => f.write_str("HIGHEST"), + EventPriority::Monitor { .. } => f.write_str("MONITOR"), } } } - -impl<'mc> Cancellable<'mc> { - /// Gets the cancellation state of this event. A cancelled event will not - /// be executed in the server, but will still pass to other plugins - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets the cancellation state of this event. A cancelled event will not - /// be executed in the server, but will still pass to other plugins. - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct Listener<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Listener<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Listener<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Listener from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/Listener")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Listener object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) +impl<'mc> std::ops::Deref for EventPriority<'mc> { + type Target = EventPriorityStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + EventPriority::Lowest { inner } => inner, + EventPriority::Low { inner } => inner, + EventPriority::Normal { inner } => inner, + EventPriority::High { inner } => inner, + EventPriority::Highest { inner } => inner, + EventPriority::Monitor { inner } => inner, } } } -impl<'mc> Listener<'mc> { - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -pub enum EventPriority<'mc> {} -impl<'mc> std::fmt::Display for EventPriority<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - impl<'mc> EventPriority<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, @@ -308,6 +228,25 @@ impl<'mc> EventPriority<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "LOWEST" => Ok(EventPriority::Lowest { + inner: EventPriorityStruct::from_raw(env, obj)?, + }), + "LOW" => Ok(EventPriority::Low { + inner: EventPriorityStruct::from_raw(env, obj)?, + }), + "NORMAL" => Ok(EventPriority::Normal { + inner: EventPriorityStruct::from_raw(env, obj)?, + }), + "HIGH" => Ok(EventPriority::High { + inner: EventPriorityStruct::from_raw(env, obj)?, + }), + "HIGHEST" => Ok(EventPriority::Highest { + inner: EventPriorityStruct::from_raw(env, obj)?, + }), + "MONITOR" => Ok(EventPriority::Monitor { + inner: EventPriorityStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -321,10 +260,24 @@ pub struct EventPriorityStruct<'mc>( impl<'mc> JNIRaw<'mc> for EventPriority<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Lowest { inner } => inner.0.clone(), + Self::Low { inner } => inner.0.clone(), + Self::Normal { inner } => inner.0.clone(), + Self::High { inner } => inner.0.clone(), + Self::Highest { inner } => inner.0.clone(), + Self::Monitor { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Lowest { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Low { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Normal { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::High { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Highest { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Monitor { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for EventPriority<'mc> { @@ -350,6 +303,24 @@ impl<'mc> JNIInstantiatable<'mc> for EventPriority<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "LOWEST" => Ok(EventPriority::Lowest { + inner: EventPriorityStruct::from_raw(env, obj)?, + }), + "LOW" => Ok(EventPriority::Low { + inner: EventPriorityStruct::from_raw(env, obj)?, + }), + "NORMAL" => Ok(EventPriority::Normal { + inner: EventPriorityStruct::from_raw(env, obj)?, + }), + "HIGH" => Ok(EventPriority::High { + inner: EventPriorityStruct::from_raw(env, obj)?, + }), + "HIGHEST" => Ok(EventPriority::Highest { + inner: EventPriorityStruct::from_raw(env, obj)?, + }), + "MONITOR" => Ok(EventPriority::Monitor { + inner: EventPriorityStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -415,90 +386,6 @@ impl<'mc> EventPriorityStruct<'mc> { } } #[repr(C)] -pub struct EventHandler<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for EventHandler<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for EventHandler<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate EventHandler from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/EventHandler")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EventHandler object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> EventHandler<'mc> { - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct EventException<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for EventException<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for EventException<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate EventException from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/EventException")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EventException object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> EventException<'mc> { - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] pub struct Event<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, @@ -601,10 +488,28 @@ impl<'mc> Event<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum EventResult<'mc> {} +pub enum EventResult<'mc> { + Deny { inner: EventResultStruct<'mc> }, + Default { inner: EventResultStruct<'mc> }, + Allow { inner: EventResultStruct<'mc> }, +} impl<'mc> std::fmt::Display for EventResult<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + EventResult::Deny { .. } => f.write_str("DENY"), + EventResult::Default { .. } => f.write_str("DEFAULT"), + EventResult::Allow { .. } => f.write_str("ALLOW"), + } + } +} +impl<'mc> std::ops::Deref for EventResult<'mc> { + type Target = EventResultStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + EventResult::Deny { inner } => inner, + EventResult::Default { inner } => inner, + EventResult::Allow { inner } => inner, + } } } @@ -631,6 +536,16 @@ impl<'mc> EventResult<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "DENY" => Ok(EventResult::Deny { + inner: EventResultStruct::from_raw(env, obj)?, + }), + "DEFAULT" => Ok(EventResult::Default { + inner: EventResultStruct::from_raw(env, obj)?, + }), + "ALLOW" => Ok(EventResult::Allow { + inner: EventResultStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -644,10 +559,18 @@ pub struct EventResultStruct<'mc>( impl<'mc> JNIRaw<'mc> for EventResult<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Deny { inner } => inner.0.clone(), + Self::Default { inner } => inner.0.clone(), + Self::Allow { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Deny { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Default { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Allow { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for EventResult<'mc> { @@ -673,6 +596,15 @@ impl<'mc> JNIInstantiatable<'mc> for EventResult<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "DENY" => Ok(EventResult::Deny { + inner: EventResultStruct::from_raw(env, obj)?, + }), + "DEFAULT" => Ok(EventResult::Default { + inner: EventResultStruct::from_raw(env, obj)?, + }), + "ALLOW" => Ok(EventResult::Allow { + inner: EventResultStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -728,6 +660,197 @@ impl<'mc> EventResultStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +#[repr(C)] +pub struct Cancellable<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Cancellable<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Cancellable<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Cancellable from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/Cancellable")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Cancellable object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Cancellable<'mc> { + /// Gets the cancellation state of this event. A cancelled event will not + /// be executed in the server, but will still pass to other plugins + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the cancellation state of this event. A cancelled event will not + /// be executed in the server, but will still pass to other plugins. + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct Listener<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Listener<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Listener<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Listener from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/Listener")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Listener object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Listener<'mc> { + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct EventHandler<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for EventHandler<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for EventHandler<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate EventHandler from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/EventHandler")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EventHandler object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> EventHandler<'mc> { + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct EventException<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for EventException<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for EventException<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate EventException from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/EventException")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EventException object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> EventException<'mc> { + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} pub mod block; pub mod enchantment; pub mod entity; diff --git a/blackboxmc-rs-bukkit/src/event/player/mod.rs b/blackboxmc-rs-bukkit/src/event/player/mod.rs index 405a318..1465b15 100644 --- a/blackboxmc-rs-bukkit/src/event/player/mod.rs +++ b/blackboxmc-rs-bukkit/src/event/player/mod.rs @@ -3,12 +3,12 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] -pub struct PlayerSignOpenEvent<'mc>( +pub struct PlayerStatisticIncrementEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerSignOpenEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerStatisticIncrementEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -16,21 +16,24 @@ impl<'mc> JNIRaw<'mc> for PlayerSignOpenEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerSignOpenEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerStatisticIncrementEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate PlayerSignOpenEvent from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate PlayerStatisticIncrementEvent from null object." + ) + .into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerSignOpenEvent")?; + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/event/player/PlayerStatisticIncrementEvent", + )?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerSignOpenEvent object, got {}", + "Invalid argument passed. Expected a PlayerStatisticIncrementEvent object, got {}", name ) .into()) @@ -40,77 +43,112 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerSignOpenEvent<'mc> { } } -impl<'mc> PlayerSignOpenEvent<'mc> { +impl<'mc> PlayerStatisticIncrementEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, player: impl Into>, - sign: impl Into>, - side: impl Into>, - cause: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/block/Sign;Lorg/bukkit/block/sign/Side;Lorg/bukkit/event/player/PlayerSignOpenEvent/Cause;)V"); + statistic: impl Into>, + initial_value: i32, + new_value: i32, + material: std::option::Option>>, + ) -> Result, Box> + { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Player;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); + args.push(val_1); + sig += "Lorg/bukkit/Statistic;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sign.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(side.into().jni_object().clone()) - }); - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(cause.into().jni_object().clone()) + jni::objects::JObject::from_raw(statistic.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/player/PlayerSignOpenEvent"); + args.push(val_2); + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(initial_value); + args.push(val_3); + sig += "I"; + let val_4 = jni::objects::JValueGen::Int(new_value); + args.push(val_4); + if let Some(a) = material { + sig += "Lorg/bukkit/Material;"; + let val_5 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_5); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/player/PlayerStatisticIncrementEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - ], - ); + let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerSignOpenEvent::from_raw(&jni, res) + crate::event::player::PlayerStatisticIncrementEvent::from_raw(&jni, res) } - /// Gets the sign that was opened. - pub fn sign(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/Sign;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSign", sig.as_str(), vec![]); + /// Gets the statistic that is being incremented. + pub fn statistic(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Statistic;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getStatistic", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::Sign::from_raw(&self.jni_ref(), unsafe { + crate::Statistic::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets side of the sign opened. - pub fn side(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/sign/Side;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSide", sig.as_str(), vec![]); + /// Gets the previous value of the statistic. + pub fn previous_value(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPreviousValue", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::block::sign::Side::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Gets the cause of the sign open. - pub fn cause( + /// Gets the new value of the statistic. + pub fn new_value(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getNewValue", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the EntityType if {@link #getStatistic() getStatistic()} is an + /// entity statistic otherwise returns null. + pub fn entity_type( &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/event/player/PlayerSignOpenEvent/Cause;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getCause", sig.as_str(), vec![]); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEntityType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::event::player::PlayerSignOpenEventCause::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntityType::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the Material if {@link #getStatistic() getStatistic()} is a block + /// or item statistic otherwise returns null. + pub fn material(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaterial", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Material::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) + })?)) } pub fn is_cancelled(&self) -> Result> { @@ -150,14 +188,14 @@ impl<'mc> PlayerSignOpenEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerSignOpenEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerStatisticIncrementEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getSign', 'getSide', 'getCause', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getStatistic', 'getPreviousValue', 'getNewValue', 'getEntityType', 'getMaterial', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -172,187 +210,54 @@ impl<'mc> PlayerSignOpenEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerSignOpenEvent<'mc> { +impl<'mc> Into> for PlayerStatisticIncrementEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerSignOpenEvent into crate::event::Cancellable") + .expect("Error converting PlayerStatisticIncrementEvent into crate::event::Cancellable") } } -impl<'mc> Into> for PlayerSignOpenEvent<'mc> { +impl<'mc> Into> for PlayerStatisticIncrementEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { - crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerSignOpenEvent into crate::event::player::PlayerEvent") - } -} -pub enum PlayerSignOpenEventCause<'mc> {} -impl<'mc> std::fmt::Display for PlayerSignOpenEventCause<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> PlayerSignOpenEventCause<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/event/player/PlayerSignOpenEvent/Cause"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/event/player/PlayerSignOpenEvent/Cause;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting PlayerStatisticIncrementEvent into crate::event::player::PlayerEvent", + ) } } - #[repr(C)] -pub struct PlayerSignOpenEventCauseStruct<'mc>( +pub struct PlayerSpawnChangeEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerSignOpenEventCause<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerSpawnChangeEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + self.0.clone() } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerSignOpenEventCause<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerSpawnChangeEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate PlayerSignOpenEventCause from null object." + "Tried to instantiate PlayerSpawnChangeEvent from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerSignOpenEvent/Cause")?; + env.validate_name(&obj, "org/bukkit/event/player/PlayerSpawnChangeEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerSignOpenEventCause object, got {}", + "Invalid argument passed. Expected a PlayerSpawnChangeEvent object, got {}", name ) .into()) } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for PlayerSignOpenEventCauseStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PlayerSignOpenEventCauseStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PlayerSignOpenEventCauseStruct from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerSignOpenEvent/Cause")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerSignOpenEventCauseStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> PlayerSignOpenEventCauseStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/event/player/PlayerSignOpenEvent/Cause;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerSignOpenEvent/Cause"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::player::PlayerSignOpenEventCause::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct PlayerSpawnChangeEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PlayerSpawnChangeEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PlayerSpawnChangeEvent<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PlayerSpawnChangeEvent from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerSpawnChangeEvent")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerSpawnChangeEvent object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + Ok(Self(env.clone(), obj)) } } } @@ -534,10 +439,49 @@ impl<'mc> Into> for PlayerSpawnChangeEven ) } } -pub enum PlayerSpawnChangeEventCause<'mc> {} +pub enum PlayerSpawnChangeEventCause<'mc> { + Command { + inner: PlayerSpawnChangeEventCauseStruct<'mc>, + }, + Bed { + inner: PlayerSpawnChangeEventCauseStruct<'mc>, + }, + RespawnAnchor { + inner: PlayerSpawnChangeEventCauseStruct<'mc>, + }, + Plugin { + inner: PlayerSpawnChangeEventCauseStruct<'mc>, + }, + Reset { + inner: PlayerSpawnChangeEventCauseStruct<'mc>, + }, + Unknown { + inner: PlayerSpawnChangeEventCauseStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for PlayerSpawnChangeEventCause<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + PlayerSpawnChangeEventCause::Command { .. } => f.write_str("COMMAND"), + PlayerSpawnChangeEventCause::Bed { .. } => f.write_str("BED"), + PlayerSpawnChangeEventCause::RespawnAnchor { .. } => f.write_str("RESPAWN_ANCHOR"), + PlayerSpawnChangeEventCause::Plugin { .. } => f.write_str("PLUGIN"), + PlayerSpawnChangeEventCause::Reset { .. } => f.write_str("RESET"), + PlayerSpawnChangeEventCause::Unknown { .. } => f.write_str("UNKNOWN"), + } + } +} +impl<'mc> std::ops::Deref for PlayerSpawnChangeEventCause<'mc> { + type Target = PlayerSpawnChangeEventCauseStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + PlayerSpawnChangeEventCause::Command { inner } => inner, + PlayerSpawnChangeEventCause::Bed { inner } => inner, + PlayerSpawnChangeEventCause::RespawnAnchor { inner } => inner, + PlayerSpawnChangeEventCause::Plugin { inner } => inner, + PlayerSpawnChangeEventCause::Reset { inner } => inner, + PlayerSpawnChangeEventCause::Unknown { inner } => inner, + } } } @@ -564,6 +508,25 @@ impl<'mc> PlayerSpawnChangeEventCause<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "COMMAND" => Ok(PlayerSpawnChangeEventCause::Command { + inner: PlayerSpawnChangeEventCauseStruct::from_raw(env, obj)?, + }), + "BED" => Ok(PlayerSpawnChangeEventCause::Bed { + inner: PlayerSpawnChangeEventCauseStruct::from_raw(env, obj)?, + }), + "RESPAWN_ANCHOR" => Ok(PlayerSpawnChangeEventCause::RespawnAnchor { + inner: PlayerSpawnChangeEventCauseStruct::from_raw(env, obj)?, + }), + "PLUGIN" => Ok(PlayerSpawnChangeEventCause::Plugin { + inner: PlayerSpawnChangeEventCauseStruct::from_raw(env, obj)?, + }), + "RESET" => Ok(PlayerSpawnChangeEventCause::Reset { + inner: PlayerSpawnChangeEventCauseStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(PlayerSpawnChangeEventCause::Unknown { + inner: PlayerSpawnChangeEventCauseStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -577,10 +540,26 @@ pub struct PlayerSpawnChangeEventCauseStruct<'mc>( impl<'mc> JNIRaw<'mc> for PlayerSpawnChangeEventCause<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Command { inner } => inner.0.clone(), + Self::Bed { inner } => inner.0.clone(), + Self::RespawnAnchor { inner } => inner.0.clone(), + Self::Plugin { inner } => inner.0.clone(), + Self::Reset { inner } => inner.0.clone(), + Self::Unknown { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Command { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Bed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::RespawnAnchor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Plugin { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Reset { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Unknown { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for PlayerSpawnChangeEventCause<'mc> { @@ -610,6 +589,24 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerSpawnChangeEventCause<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "COMMAND" => Ok(PlayerSpawnChangeEventCause::Command { + inner: PlayerSpawnChangeEventCauseStruct::from_raw(env, obj)?, + }), + "BED" => Ok(PlayerSpawnChangeEventCause::Bed { + inner: PlayerSpawnChangeEventCauseStruct::from_raw(env, obj)?, + }), + "RESPAWN_ANCHOR" => Ok(PlayerSpawnChangeEventCause::RespawnAnchor { + inner: PlayerSpawnChangeEventCauseStruct::from_raw(env, obj)?, + }), + "PLUGIN" => Ok(PlayerSpawnChangeEventCause::Plugin { + inner: PlayerSpawnChangeEventCauseStruct::from_raw(env, obj)?, + }), + "RESET" => Ok(PlayerSpawnChangeEventCause::Reset { + inner: PlayerSpawnChangeEventCauseStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(PlayerSpawnChangeEventCause::Unknown { + inner: PlayerSpawnChangeEventCauseStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -669,12 +666,12 @@ impl<'mc> PlayerSpawnChangeEventCauseStruct<'mc> { } } #[repr(C)] -pub struct PlayerExpCooldownChangeEvent<'mc>( +pub struct PlayerRecipeBookClickEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerExpCooldownChangeEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerRecipeBookClickEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -682,22 +679,22 @@ impl<'mc> JNIRaw<'mc> for PlayerExpCooldownChangeEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerExpCooldownChangeEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerRecipeBookClickEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate PlayerExpCooldownChangeEvent from null object." + "Tried to instantiate PlayerRecipeBookClickEvent from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerExpCooldownChangeEvent")?; + env.validate_name(&obj, "org/bukkit/event/player/PlayerRecipeBookClickEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerExpCooldownChangeEvent object, got {}", + "Invalid argument passed. Expected a PlayerRecipeBookClickEvent object, got {}", name ) .into()) @@ -707,23 +704,23 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerExpCooldownChangeEvent<'mc> { } } -impl<'mc> PlayerExpCooldownChangeEvent<'mc> { +impl<'mc> PlayerRecipeBookClickEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, player: impl Into>, - newcooldown: i32, - reason: impl Into>, - ) -> Result, Box> + recipe: impl Into>, + shift_click: bool, + ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Player;ILorg/bukkit/event/player/PlayerExpCooldownChangeEvent/ChangeReason;)V"); + let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/inventory/Recipe;Z)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(newcooldown); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(reason.into().jni_object().clone()) + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/player/PlayerExpCooldownChangeEvent"); + let val_3 = jni::objects::JValueGen::Bool(shift_click.into()); + let cls = jni.find_class("org/bukkit/event/player/PlayerRecipeBookClickEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -735,42 +732,83 @@ impl<'mc> PlayerExpCooldownChangeEvent<'mc> { ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerExpCooldownChangeEvent::from_raw(&jni, res) + crate::event::player::PlayerRecipeBookClickEvent::from_raw(&jni, res) } - /// Gets the reason for the change. - pub fn reason( + /// Gets the original recipe the player was trying to craft. + /// + /// This will not reflect any changes made with {@link setRecipe}. + pub fn original_recipe( &self, - ) -> Result< - crate::event::player::PlayerExpCooldownChangeEventChangeReason<'mc>, - Box, - > { - let sig = - String::from("()Lorg/bukkit/event/player/PlayerExpCooldownChangeEvent/ChangeReason;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Recipe;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getOriginalRecipe", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Recipe::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the recipe the player is trying to craft. + /// + /// This will reflect changes made with {@link setRecipe}. + pub fn recipe(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Recipe;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getReason", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getRecipe", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::event::player::PlayerExpCooldownChangeEventChangeReason::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - ) + crate::inventory::Recipe::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the new cooldown for the player. - pub fn new_cooldown(&self) -> Result> { - let sig = String::from("()I"); + /// Set the recipe that will be used. + /// + /// The game will attempt to move the ingredients for this recipe into the + /// appropriate slots. + /// + /// If the original recipe is a {@link CraftingRecipe} the provided recipe + /// must also be a {@link CraftingRecipe}, otherwise the provided recipe must + /// be of the same type as the original recipe. + pub fn set_recipe( + &self, + recipe: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/Recipe;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRecipe", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// If true the game will attempt to move the ingredients for as many copies + /// of this recipe as possible into the appropriate slots, otherwise only 1 + /// copy will be moved. + pub fn is_shift_click(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getNewCooldown", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isShiftClick", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the new cooldown for the player. - pub fn set_new_cooldown(&self, new_cooldown: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(new_cooldown); + /// Sets if the game will attempt to move the ingredients for as many copies + /// of this recipe as possible into the appropriate slots. + pub fn set_shift_click(&self, shift_click: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(shift_click.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setNewCooldown", + "setShiftClick", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -793,14 +831,14 @@ impl<'mc> PlayerExpCooldownChangeEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerExpCooldownChangeEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerRecipeBookClickEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getReason', 'getNewCooldown', 'setNewCooldown', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getOriginalRecipe', 'getRecipe', 'setRecipe', 'isShiftClick', 'setShiftClick', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -815,185 +853,43 @@ impl<'mc> PlayerExpCooldownChangeEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerExpCooldownChangeEvent<'mc> { +impl<'mc> Into> for PlayerRecipeBookClickEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting PlayerExpCooldownChangeEvent into crate::event::player::PlayerEvent", + "Error converting PlayerRecipeBookClickEvent into crate::event::player::PlayerEvent", ) } } -pub enum PlayerExpCooldownChangeEventChangeReason<'mc> {} -impl<'mc> std::fmt::Display for PlayerExpCooldownChangeEventChangeReason<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> PlayerExpCooldownChangeEventChangeReason<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = - env.find_class("org/bukkit/event/player/PlayerExpCooldownChangeEvent/ChangeReason"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/event/player/PlayerExpCooldownChangeEvent/ChangeReason;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - #[repr(C)] -pub struct PlayerExpCooldownChangeEventChangeReasonStruct<'mc>( +pub struct PlayerItemConsumeEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerExpCooldownChangeEventChangeReason<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerItemConsumeEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + self.0.clone() } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerExpCooldownChangeEventChangeReason<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerItemConsumeEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate PlayerExpCooldownChangeEventChangeReason from null object." + "Tried to instantiate PlayerItemConsumeEvent from null object." ) .into()); } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/event/player/PlayerExpCooldownChangeEvent/ChangeReason", - )?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/player/PlayerItemConsumeEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerExpCooldownChangeEventChangeReason object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for PlayerExpCooldownChangeEventChangeReasonStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PlayerExpCooldownChangeEventChangeReasonStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PlayerExpCooldownChangeEventChangeReasonStruct from null object.") - .into()); - } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/event/player/PlayerExpCooldownChangeEvent/ChangeReason", - )?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerExpCooldownChangeEventChangeReasonStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> PlayerExpCooldownChangeEventChangeReasonStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result< - crate::event::player::PlayerExpCooldownChangeEventChangeReason<'mc>, - Box, - > { - let sig = - String::from("()Lorg/bukkit/event/player/PlayerExpCooldownChangeEvent/ChangeReason;"); - let cls = - jni.find_class("org/bukkit/event/player/PlayerExpCooldownChangeEvent/ChangeReason"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::player::PlayerExpCooldownChangeEventChangeReason::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct PlayerChangedMainHandEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PlayerChangedMainHandEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PlayerChangedMainHandEvent<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PlayerChangedMainHandEvent from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerChangedMainHandEvent")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerChangedMainHandEvent object, got {}", + "Invalid argument passed. Expected a PlayerItemConsumeEvent object, got {}", name ) .into()) @@ -1003,46 +899,104 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerChangedMainHandEvent<'mc> { } } -impl<'mc> PlayerChangedMainHandEvent<'mc> { +impl<'mc> PlayerItemConsumeEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - who: impl Into>, - main_hand: impl Into>, - ) -> Result, Box> - { - let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/inventory/MainHand;)V"); + player: impl Into>, + item: impl Into>, + hand: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Player;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(who.into().jni_object().clone()) + jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); + args.push(val_1); + sig += "Lorg/bukkit/inventory/ItemStack;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(main_hand.into().jni_object().clone()) + jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/player/PlayerChangedMainHandEvent"); + args.push(val_2); + if let Some(a) = hand { + sig += "Lorg/bukkit/inventory/EquipmentSlot;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_3); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/player/PlayerItemConsumeEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::event::player::PlayerItemConsumeEvent::from_raw(&jni, res) + } + /// Gets the item that is being consumed. Modifying the returned item will + /// have no effect, you must use {@link + /// #setItem(org.bukkit.inventory.ItemStack)} instead. + pub fn item(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Set the item being consumed + pub fn set_item( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItem", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerChangedMainHandEvent::from_raw(&jni, res) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the new main hand of the player. The old hand is still momentarily - /// available via {@link Player#getMainHand()}. - pub fn main_hand(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/MainHand;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMainHand", sig.as_str(), vec![]); + /// Get the hand used to consume the item. + pub fn hand(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/EquipmentSlot;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHand", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::MainHand::from_raw(&self.jni_ref(), unsafe { + crate::inventory::EquipmentSlot::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); let res = @@ -1058,14 +1012,14 @@ impl<'mc> PlayerChangedMainHandEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerChangedMainHandEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerItemConsumeEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getMainHand', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getItem', 'setItem', 'getHand', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -1080,20 +1034,26 @@ impl<'mc> PlayerChangedMainHandEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerChangedMainHandEvent<'mc> { +impl<'mc> Into> for PlayerItemConsumeEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerItemConsumeEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for PlayerItemConsumeEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting PlayerChangedMainHandEvent into crate::event::player::PlayerEvent", + "Error converting PlayerItemConsumeEvent into crate::event::player::PlayerEvent", ) } } #[repr(C)] -pub struct PlayerMoveEvent<'mc>( +pub struct PlayerInteractEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerMoveEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerInteractEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1101,20 +1061,21 @@ impl<'mc> JNIRaw<'mc> for PlayerMoveEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerMoveEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerInteractEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate PlayerMoveEvent from null object.").into(), + eyre::eyre!("Tried to instantiate PlayerInteractEvent from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/player/PlayerMoveEvent")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/player/PlayerInteractEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerMoveEvent object, got {}", + "Invalid argument passed. Expected a PlayerInteractEvent object, got {}", name ) .into()) @@ -1124,44 +1085,78 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerMoveEvent<'mc> { } } -impl<'mc> PlayerMoveEvent<'mc> { +impl<'mc> PlayerInteractEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - player: impl Into>, - from: impl Into>, - to: impl Into>, - ) -> Result, Box> { - let sig = - String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/Location;Lorg/bukkit/Location;)V"); + who: impl Into>, + action: impl Into>, + item: impl Into>, + clicked_block: impl Into>, + clicked_face: impl Into>, + hand: std::option::Option>>, + clicked_position: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Player;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) + jni::objects::JObject::from_raw(who.into().jni_object().clone()) }); + args.push(val_1); + sig += "Lorg/bukkit/event/block/Action;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(from.into().jni_object().clone()) + jni::objects::JObject::from_raw(action.into().jni_object().clone()) }); + args.push(val_2); + sig += "Lorg/bukkit/inventory/ItemStack;"; let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(to.into().jni_object().clone()) + jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/player/PlayerMoveEvent"); + args.push(val_3); + sig += "Lorg/bukkit/block/Block;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(clicked_block.into().jni_object().clone()) + }); + args.push(val_4); + sig += "Lorg/bukkit/block/BlockFace;"; + let val_5 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(clicked_face.into().jni_object().clone()) + }); + args.push(val_5); + if let Some(a) = hand { + sig += "Lorg/bukkit/inventory/EquipmentSlot;"; + let val_6 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_6); + } + if let Some(a) = clicked_position { + sig += "Lorg/bukkit/util/Vector;"; + let val_7 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_7); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/player/PlayerInteractEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); + let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerMoveEvent::from_raw(&jni, res) + crate::event::player::PlayerInteractEvent::from_raw(&jni, res) } - /// Gets the cancellation state of this event. A cancelled event will not - /// be executed in the server, but will still pass to other plugins - /// - /// If a move or teleport event is cancelled, the player will be moved or - /// teleported back to the Location as defined by getFrom(). This will not - /// fire an event + /// Returns the action type + pub fn action(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/block/Action;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getAction", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::block::Action::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + #[deprecated] + /// Gets the cancellation state of this event. Set to true if you want to prevent buckets from placing water and so forth pub fn is_cancelled(&self) -> Result> { let sig = String::from("()Z"); let res = @@ -1170,12 +1165,12 @@ impl<'mc> PlayerMoveEvent<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the cancellation state of this event. A cancelled event will not - /// be executed in the server, but will still pass to other plugins + /// Sets the cancellation state of this event. A canceled event will not be + /// executed in the server, but will still pass to other plugins /// - /// If a move or teleport event is cancelled, the player will be moved or - /// teleported back to the Location as defined by getFrom(). This will not - /// fire an event + /// Canceling this event will prevent use of food (player won't lose the + /// food item), prevent bows/snowballs/eggs from firing, etc. (player won't + /// lose the ammo) pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); let val_1 = jni::objects::JValueGen::Bool(cancel.into()); @@ -1188,124 +1183,259 @@ impl<'mc> PlayerMoveEvent<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the location this player moved from - pub fn from(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); + /// Returns the item in hand represented by this event + pub fn item( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getFrom", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Convenience method. Returns the material of the item represented by + /// this event + pub fn material(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaterial", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the location to mark as where the player moved from - pub fn set_from( - &self, - from: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Location;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(from.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFrom", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Check if this event involved a block + pub fn has_block(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasBlock", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the location this player moved to - pub fn to(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); + /// Check if this event involved an item + pub fn has_item(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getTo", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasItem", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Convenience method to inform the user whether this was a block + /// placement event. + pub fn is_block_in_hand(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isBlockInHand", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the clicked block + pub fn clicked_block( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getClickedBlock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + Ok(Some(crate::block::Block::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Returns the face of the block that was clicked + pub fn block_face(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBlockFace", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + }) } - /// Sets the location that this player will move to - pub fn set_to( + /// This controls the action to take with the block (if any) that was + /// clicked on. This event gets processed for all blocks, but most don't + /// have a default action + pub fn use_interacted_block( &self, - to: impl Into>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/Event/Result;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "useInteractedBlock", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::event::EventResult::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn set_use_interacted_block( + &self, + use_interacted_block: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Location;)V"); + let sig = String::from("(Lorg/bukkit/event/Event/Result;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(to.into().jni_object().clone()) + jni::objects::JObject::from_raw(use_interacted_block.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setTo", + "setUseInteractedBlock", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + /// This controls the action to take with the item the player is holding. + /// This includes both blocks and items (such as flint and steel or + /// records). When this is set to default, it will be allowed if no action + /// is taken on the interacted block. + pub fn use_item_in_hand( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/Event/Result;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "useItemInHand", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + crate::event::EventResult::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - pub fn handler_list( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerMoveEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['isCancelled', 'setCancelled', 'getFrom', 'setFrom', 'getTo', 'setTo', 'getHandlers', 'getHandlerList']) - /// Returns the player involved in this event - pub fn player(&self) -> Result, Box> { - let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerEvent = temp_clone.into(); - real.player() + pub fn set_use_item_in_hand( + &self, + use_item_in_hand: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/event/Event/Result;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(use_item_in_hand.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setUseItemInHand", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - + /// The hand used to perform this interaction. May be null in the case of + /// {@link Action#PHYSICAL}. + pub fn hand( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/EquipmentSlot;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHand", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::EquipmentSlot::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the exact position on the block the player interacted with, this will + /// be null outside of {@link Action#RIGHT_CLICK_BLOCK}. + /// + /// All vector components are between 0.0 and 1.0 inclusive. + pub fn clicked_position( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getClickedPosition", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::util::Vector::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/player/PlayerInteractEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getAction', 'isCancelled', 'setCancelled', 'getItem', 'getMaterial', 'hasBlock', 'hasItem', 'isBlockInHand', 'getClickedBlock', 'getBlockFace', 'useInteractedBlock', 'setUseInteractedBlock', 'useItemInHand', 'setUseItemInHand', 'getHand', 'getClickedPosition', 'getHandlers', 'getHandlerList']) + /// Returns the player involved in this event + pub fn player(&self) -> Result, Box> { + let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerEvent = temp_clone.into(); + real.player() + } + pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerMoveEvent<'mc> { +impl<'mc> Into> for PlayerInteractEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerMoveEvent into crate::event::Cancellable") + .expect("Error converting PlayerInteractEvent into crate::event::Cancellable") } } -impl<'mc> Into> for PlayerMoveEvent<'mc> { +impl<'mc> Into> for PlayerInteractEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerMoveEvent into crate::event::player::PlayerEvent") + .expect("Error converting PlayerInteractEvent into crate::event::player::PlayerEvent") } } #[repr(C)] -pub struct AsyncPlayerPreLoginEvent<'mc>( +pub struct PlayerChatTabCompleteEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for AsyncPlayerPreLoginEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerChatTabCompleteEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1313,22 +1443,22 @@ impl<'mc> JNIRaw<'mc> for AsyncPlayerPreLoginEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for AsyncPlayerPreLoginEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerChatTabCompleteEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate AsyncPlayerPreLoginEvent from null object." + "Tried to instantiate PlayerChatTabCompleteEvent from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/AsyncPlayerPreLoginEvent")?; + env.validate_name(&obj, "org/bukkit/event/player/PlayerChatTabCompleteEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a AsyncPlayerPreLoginEvent object, got {}", + "Invalid argument passed. Expected a PlayerChatTabCompleteEvent object, got {}", name ) .into()) @@ -1338,117 +1468,29 @@ impl<'mc> JNIInstantiatable<'mc> for AsyncPlayerPreLoginEvent<'mc> { } } -impl<'mc> AsyncPlayerPreLoginEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - name: impl Into, - ip_address: jni::objects::JObject<'mc>, - unique_id: std::option::Option>>, - transferred: std::option::Option, - ) -> Result, Box> - { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(name.into())?, - )); - args.push(val_1); - sig += "Ljava/net/InetAddress;"; - let val_2 = jni::objects::JValueGen::Object(ip_address); - args.push(val_2); - if let Some(a) = unique_id { - sig += "Ljava/util/UUID;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_3); - } - if let Some(a) = transferred { - sig += "Z"; - let val_4 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_4); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/event/player/AsyncPlayerPreLoginEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::event::player::AsyncPlayerPreLoginEvent::from_raw(&jni, res) - } - /// Gets the current result of the login, as an enum - pub fn login_result( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/event/player/AsyncPlayerPreLoginEvent/Result;"); +impl<'mc> PlayerChatTabCompleteEvent<'mc> { + /// Gets the chat message being tab-completed. + pub fn chat_message(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLoginResult", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getChatMessage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::event::player::AsyncPlayerPreLoginEventResult::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - #[deprecated] - /// Gets the current result of the login, as an enum - pub fn result( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/event/player/PlayerPreLoginEvent/Result;"); - let res = self + Ok(self .jni_ref() - .call_method(&self.jni_object(), "getResult", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::player::PlayerPreLoginEventResult::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the new result of the login, as an enum - pub fn set_login_result( - &self, - result: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/player/AsyncPlayerPreLoginEvent/Result;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(result.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLoginResult", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Sets the new result of the login, as an enum - pub fn set_result( - &self, - result: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/player/PlayerPreLoginEvent/Result;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(result.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setResult", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Gets the current kick message that will be used if getResult() != - /// Result.ALLOWED - pub fn kick_message(&self) -> Result> { + /// Gets the last 'token' of the message being tab-completed. + /// + /// The token is the substring starting with the character after the last + /// space in the message. + pub fn last_token(&self) -> Result> { let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getKickMessage", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLastToken", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(self .jni_ref() @@ -1456,102 +1498,29 @@ impl<'mc> AsyncPlayerPreLoginEvent<'mc> { .to_string_lossy() .to_string()) } - /// Sets the kick message to display if getResult() != Result.ALLOWED - pub fn set_kick_message( - &self, - message: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(message.into())?, - )); + /// This is the collection of completions for this event. + pub fn tab_completions(&self) -> Result, Box> { + let sig = String::from("()Ljava/util/Collection;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setKickMessage", + "getTabCompletions", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Allows the player to log in - pub fn allow(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "allow", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Disallows the player from logging in, with the given reason - pub fn disallow( - &self, - result: impl Into>, - message: impl Into, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/event/player/PlayerPreLoginEvent/Result;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(result.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(message.into())?, - )); - args.push(val_2); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "disallow", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the player's name. - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Gets the player IP address. - pub fn address(&self) -> Result, Box> { - let sig = String::from("()Ljava/net/InetAddress;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAddress", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) - } - /// Gets the player's unique ID. - pub fn unique_id( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets if this connection has been transferred from another server. - pub fn is_transferred(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isTransferred", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); + } + Ok(new_vec) } pub fn handlers(&self) -> Result, Box> { @@ -1569,49 +1538,21 @@ impl<'mc> AsyncPlayerPreLoginEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/AsyncPlayerPreLoginEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerChatTabCompleteEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.Event ( ['getLoginResult', 'getResult', 'setLoginResult', 'setResult', 'getKickMessage', 'setKickMessage', 'allow', 'disallow', 'getName', 'getAddress', 'getUniqueId', 'isTransferred', 'getHandlers', 'getHandlerList']) - /// Convenience method for providing a user-friendly identifier. By - /// default, it is the event's class's {@linkplain Class#getSimpleName() - /// simple name}. - pub fn event_name(&self) -> Result> { - let temp_clone = crate::event::Event::from_raw(&self.0, unsafe { + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getChatMessage', 'getLastToken', 'getTabCompletions', 'getHandlers', 'getHandlerList']) + /// Returns the player involved in this event + pub fn player(&self) -> Result, Box> { + let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::Event = temp_clone.into(); - real.event_name() - } - /// Any custom event that should not by synchronized with other events must - /// use the specific constructor. These are the caveats of using an - /// asynchronous event: - ///
    - ///
  • The event is never fired from inside code triggered by a - /// synchronous event. Attempting to do so results in an {@link - /// java.lang.IllegalStateException}. - ///
  • However, asynchronous event handlers may fire synchronous or - /// asynchronous events - ///
  • The event may be fired multiple times simultaneously and in any - /// order. - ///
  • Any newly registered or unregistered handler is ignored after an - /// event starts execution. - ///
  • The handlers for this event may block for any length of time. - ///
  • Some implementations may selectively declare a specific event use - /// as asynchronous. This behavior should be clearly defined. - ///
  • Asynchronous calls are not calculated in the plugin timing system. - ///
- pub fn is_asynchronous(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isAsynchronous", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let real: crate::event::player::PlayerEvent = temp_clone.into(); + real.player() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1619,267 +1560,222 @@ impl<'mc> AsyncPlayerPreLoginEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for AsyncPlayerPreLoginEvent<'mc> { - fn into(self) -> crate::event::Event<'mc> { - crate::event::Event::from_raw(&self.jni_ref(), self.1) - .expect("Error converting AsyncPlayerPreLoginEvent into crate::event::Event") - } -} -pub enum AsyncPlayerPreLoginEventResult<'mc> {} -impl<'mc> std::fmt::Display for AsyncPlayerPreLoginEventResult<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> AsyncPlayerPreLoginEventResult<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/event/player/AsyncPlayerPreLoginEvent/Result"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/event/player/AsyncPlayerPreLoginEvent/Result;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } +impl<'mc> Into> for PlayerChatTabCompleteEvent<'mc> { + fn into(self) -> crate::event::player::PlayerEvent<'mc> { + crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting PlayerChatTabCompleteEvent into crate::event::player::PlayerEvent", + ) } } - #[repr(C)] -pub struct AsyncPlayerPreLoginEventResultStruct<'mc>( +pub struct PlayerBucketEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for AsyncPlayerPreLoginEventResult<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerBucketEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + self.0.clone() } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for AsyncPlayerPreLoginEventResult<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerBucketEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate AsyncPlayerPreLoginEventResult from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate PlayerBucketEvent from null object.").into(), + ); } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/event/player/AsyncPlayerPreLoginEvent/Result", - )?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/player/PlayerBucketEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a AsyncPlayerPreLoginEventResult object, got {}", + "Invalid argument passed. Expected a PlayerBucketEvent object, got {}", name ) .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for AsyncPlayerPreLoginEventResultStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for AsyncPlayerPreLoginEventResultStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate AsyncPlayerPreLoginEventResultStruct from null object." - ) - .into()); - } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/event/player/AsyncPlayerPreLoginEvent/Result", - )?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a AsyncPlayerPreLoginEventResultStruct object, got {}", - name - ) - .into()) } else { Ok(Self(env.clone(), obj)) } } } -impl<'mc> AsyncPlayerPreLoginEventResultStruct<'mc> { - pub fn values( +impl<'mc> PlayerBucketEvent<'mc> { + pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/event/player/AsyncPlayerPreLoginEvent/Result;"); - let cls = jni.find_class("org/bukkit/event/player/AsyncPlayerPreLoginEvent/Result"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::player::AsyncPlayerPreLoginEventResult::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct PlayerChatTabCompleteEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PlayerChatTabCompleteEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PlayerChatTabCompleteEvent<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PlayerChatTabCompleteEvent from null object." - ) - .into()); + who: impl Into>, + block: impl Into>, + block_clicked: impl Into>, + block_face: impl Into>, + bucket: impl Into>, + item_in_hand: std::option::Option>>, + hand: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Player;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(who.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Lorg/bukkit/block/Block;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(block.into().jni_object().clone()) + }); + args.push(val_2); + sig += "Lorg/bukkit/block/Block;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(block_clicked.into().jni_object().clone()) + }); + args.push(val_3); + sig += "Lorg/bukkit/block/BlockFace;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(block_face.into().jni_object().clone()) + }); + args.push(val_4); + sig += "Lorg/bukkit/Material;"; + let val_5 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(bucket.into().jni_object().clone()) + }); + args.push(val_5); + if let Some(a) = item_in_hand { + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_6 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_6); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerChatTabCompleteEvent")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerChatTabCompleteEvent object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + if let Some(a) = hand { + sig += "Lorg/bukkit/inventory/EquipmentSlot;"; + let val_7 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_7); } + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/player/PlayerBucketEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::event::player::PlayerBucketEvent::from_raw(&jni, res) } -} - -impl<'mc> PlayerChatTabCompleteEvent<'mc> { - /// Gets the chat message being tab-completed. - pub fn chat_message(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getChatMessage", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self + /// Returns the bucket used in this event + pub fn bucket(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = self .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + .call_method(&self.jni_object(), "getBucket", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the last 'token' of the message being tab-completed. - /// - /// The token is the substring starting with the character after the last - /// space in the message. - pub fn last_token(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Get the resulting item in hand after the bucket event + pub fn item_stack( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLastToken", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItemStack", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// This is the collection of completions for this event. - pub fn tab_completions(&self) -> Result, Box> { - let sig = String::from("()Ljava/util/Collection;"); + /// Set the item in hand after the event + pub fn set_item_stack( + &self, + item_stack: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getTabCompletions", + "setItemStack", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the block involved in this event. + pub fn block(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), - ); - } - Ok(new_vec) + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + /// Return the block clicked + pub fn block_clicked(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBlockClicked", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the face on the clicked block + pub fn block_face(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBlockFace", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the hand that was used in this event. + pub fn hand(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/EquipmentSlot;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHand", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::EquipmentSlot::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - pub fn handler_list( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerChatTabCompleteEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getChatMessage', 'getLastToken', 'getTabCompletions', 'getHandlers', 'getHandlerList']) + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getBucket', 'getItemStack', 'setItemStack', 'getBlock', 'getBlockClicked', 'getBlockFace', 'getHand', 'isCancelled', 'setCancelled']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -1894,20 +1790,25 @@ impl<'mc> PlayerChatTabCompleteEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerChatTabCompleteEvent<'mc> { +impl<'mc> Into> for PlayerBucketEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerBucketEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for PlayerBucketEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { - crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting PlayerChatTabCompleteEvent into crate::event::player::PlayerEvent", - ) + crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerBucketEvent into crate::event::player::PlayerEvent") } } #[repr(C)] -pub struct PlayerItemMendEvent<'mc>( +pub struct PlayerChangedMainHandEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerItemMendEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerChangedMainHandEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1915,21 +1816,22 @@ impl<'mc> JNIRaw<'mc> for PlayerItemMendEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerItemMendEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerChangedMainHandEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate PlayerItemMendEvent from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate PlayerChangedMainHandEvent from null object." + ) + .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerItemMendEvent")?; + env.validate_name(&obj, "org/bukkit/event/player/PlayerChangedMainHandEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerItemMendEvent object, got {}", + "Invalid argument passed. Expected a PlayerChangedMainHandEvent object, got {}", name ) .into()) @@ -1939,135 +1841,44 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerItemMendEvent<'mc> { } } -impl<'mc> PlayerItemMendEvent<'mc> { +impl<'mc> PlayerChangedMainHandEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, who: impl Into>, - item: impl Into>, - slot: impl Into>, - experience_orb: impl Into>, - repair_amount: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Player;"; + main_hand: impl Into>, + ) -> Result, Box> + { + let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/inventory/MainHand;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(who.into().jni_object().clone()) }); - args.push(val_1); - sig += "Lorg/bukkit/inventory/ItemStack;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - args.push(val_2); - sig += "Lorg/bukkit/inventory/EquipmentSlot;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(slot.into().jni_object().clone()) - }); - args.push(val_3); - sig += "Lorg/bukkit/entity/ExperienceOrb;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(experience_orb.into().jni_object().clone()) + jni::objects::JObject::from_raw(main_hand.into().jni_object().clone()) }); - args.push(val_4); - if let Some(a) = repair_amount { - sig += "I"; - let val_5 = jni::objects::JValueGen::Int(a); - args.push(val_5); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/event/player/PlayerItemMendEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerChangedMainHandEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerItemMendEvent::from_raw(&jni, res) - } - /// Get the {@link ItemStack} to be repaired. - /// This is not necessarily the item the player is holding. - pub fn item(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the {@link EquipmentSlot} in which the repaired {@link ItemStack} - /// may be found. - pub fn slot(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/EquipmentSlot;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSlot", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::EquipmentSlot::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the experience orb triggering the event. - pub fn experience_orb( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/ExperienceOrb;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getExperienceOrb", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::entity::ExperienceOrb::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the amount the item is to be repaired. - /// The default value is twice the value of the consumed experience orb - /// or the remaining damage left on the item, whichever is smaller. - pub fn repair_amount(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRepairAmount", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the amount the item will be repaired. - /// Half of this value will be subtracted from the experience orb which initiated this event. - pub fn set_repair_amount(&self, amount: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(amount); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRepairAmount", + let res = jni.new_object( + cls, sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = jni.translate_error_no_gen(res)?; + crate::event::player::PlayerChangedMainHandEvent::from_raw(&jni, res) } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the new main hand of the player. The old hand is still momentarily + /// available via {@link Player#getMainHand()}. + pub fn main_hand(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/MainHand;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMainHand", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_cancelled(&self, cancelled: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancelled.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::inventory::MainHand::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn handlers(&self) -> Result, Box> { @@ -2085,14 +1896,14 @@ impl<'mc> PlayerItemMendEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerItemMendEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerChangedMainHandEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getItem', 'getSlot', 'getExperienceOrb', 'getRepairAmount', 'setRepairAmount', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getMainHand', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -2107,25 +1918,20 @@ impl<'mc> PlayerItemMendEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerItemMendEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerItemMendEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for PlayerItemMendEvent<'mc> { +impl<'mc> Into> for PlayerChangedMainHandEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { - crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerItemMendEvent into crate::event::player::PlayerEvent") + crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting PlayerChangedMainHandEvent into crate::event::player::PlayerEvent", + ) } } #[repr(C)] -pub struct PlayerAnimationEvent<'mc>( +pub struct PlayerMoveEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerAnimationEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerMoveEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2133,21 +1939,20 @@ impl<'mc> JNIRaw<'mc> for PlayerAnimationEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerAnimationEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerMoveEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate PlayerAnimationEvent from null object.").into(), + eyre::eyre!("Tried to instantiate PlayerMoveEvent from null object.").into(), ); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerAnimationEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/player/PlayerMoveEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerAnimationEvent object, got {}", + "Invalid argument passed. Expected a PlayerMoveEvent object, got {}", name ) .into()) @@ -2157,53 +1962,44 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerAnimationEvent<'mc> { } } -impl<'mc> PlayerAnimationEvent<'mc> { - /// Construct a new PlayerAnimation event +impl<'mc> PlayerMoveEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, player: impl Into>, - player_animation_type: std::option::Option< - impl Into>, - >, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Player;"; + from: impl Into>, + to: impl Into>, + ) -> Result, Box> { + let sig = + String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/Location;Lorg/bukkit/Location;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); - args.push(val_1); - if let Some(a) = player_animation_type { - sig += "Lorg/bukkit/event/player/PlayerAnimationType;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/event/player/PlayerAnimationEvent"); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(from.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(to.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/player/PlayerMoveEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerAnimationEvent::from_raw(&jni, res) - } - /// Get the type of this animation event - pub fn animation_type( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/player/PlayerAnimationType;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAnimationType", + let res = jni.new_object( + cls, sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); - let res = self.jni_ref().translate_error(res)?; - crate::event::player::PlayerAnimationType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let res = jni.translate_error_no_gen(res)?; + crate::event::player::PlayerMoveEvent::from_raw(&jni, res) } - + /// Gets the cancellation state of this event. A cancelled event will not + /// be executed in the server, but will still pass to other plugins + /// + /// If a move or teleport event is cancelled, the player will be moved or + /// teleported back to the Location as defined by getFrom(). This will not + /// fire an event pub fn is_cancelled(&self) -> Result> { let sig = String::from("()Z"); let res = @@ -2212,7 +2008,12 @@ impl<'mc> PlayerAnimationEvent<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - + /// Sets the cancellation state of this event. A cancelled event will not + /// be executed in the server, but will still pass to other plugins + /// + /// If a move or teleport event is cancelled, the player will be moved or + /// teleported back to the Location as defined by getFrom(). This will not + /// fire an event pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); let val_1 = jni::objects::JValueGen::Bool(cancel.into()); @@ -2225,132 +2026,66 @@ impl<'mc> PlayerAnimationEvent<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + /// Gets the location this player moved from + pub fn from(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFrom", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn handler_list( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerAnimationEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getAnimationType', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) - /// Returns the player involved in this event - pub fn player(&self) -> Result, Box> { - let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerEvent = temp_clone.into(); - real.player() - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for PlayerAnimationEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerAnimationEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for PlayerAnimationEvent<'mc> { - fn into(self) -> crate::event::player::PlayerEvent<'mc> { - crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerAnimationEvent into crate::event::player::PlayerEvent") - } -} -#[repr(C)] -pub struct PlayerItemBreakEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PlayerItemBreakEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PlayerItemBreakEvent<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate PlayerItemBreakEvent from null object.").into(), - ); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerItemBreakEvent")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerItemBreakEvent object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> PlayerItemBreakEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - player: impl Into>, - broken_item: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/inventory/ItemStack;)V"); + /// Sets the location to mark as where the player moved from + pub fn set_from( + &self, + from: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Location;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(broken_item.into().jni_object().clone()) + jni::objects::JObject::from_raw(from.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/player/PlayerItemBreakEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFrom", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerItemBreakEvent::from_raw(&jni, res) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the item that broke - pub fn broken_item( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBrokenItem", sig.as_str(), vec![]); + /// Gets the location this player moved to + pub fn to(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTo", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) + })?)) + } + /// Sets the location that this player will move to + pub fn set_to( + &self, + to: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Location;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(to.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTo", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn handlers(&self) -> Result, Box> { @@ -2368,14 +2103,14 @@ impl<'mc> PlayerItemBreakEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerItemBreakEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerMoveEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getBrokenItem', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['isCancelled', 'setCancelled', 'getFrom', 'setFrom', 'getTo', 'setTo', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -2390,19 +2125,25 @@ impl<'mc> PlayerItemBreakEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerItemBreakEvent<'mc> { +impl<'mc> Into> for PlayerMoveEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerMoveEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for PlayerMoveEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerItemBreakEvent into crate::event::player::PlayerEvent") + .expect("Error converting PlayerMoveEvent into crate::event::player::PlayerEvent") } } #[repr(C)] -pub struct PlayerToggleSprintEvent<'mc>( +pub struct PlayerSignOpenEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerToggleSprintEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerSignOpenEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2410,22 +2151,21 @@ impl<'mc> JNIRaw<'mc> for PlayerToggleSprintEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerToggleSprintEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerSignOpenEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PlayerToggleSprintEvent from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate PlayerSignOpenEvent from null object.").into(), + ); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerToggleSprintEvent")?; + env.validate_name(&obj, "org/bukkit/event/player/PlayerSignOpenEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerToggleSprintEvent object, got {}", + "Invalid argument passed. Expected a PlayerSignOpenEvent object, got {}", name ) .into()) @@ -2435,19 +2175,28 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerToggleSprintEvent<'mc> { } } -impl<'mc> PlayerToggleSprintEvent<'mc> { +impl<'mc> PlayerSignOpenEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, player: impl Into>, - is_sprinting: bool, - ) -> Result, Box> - { - let sig = String::from("(Lorg/bukkit/entity/Player;Z)V"); + sign: impl Into>, + side: impl Into>, + cause: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/block/Sign;Lorg/bukkit/block/sign/Side;Lorg/bukkit/event/player/PlayerSignOpenEvent/Cause;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Bool(is_sprinting.into()); - let cls = jni.find_class("org/bukkit/event/player/PlayerToggleSprintEvent"); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sign.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(side.into().jni_object().clone()) + }); + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(cause.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/player/PlayerSignOpenEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -2455,19 +2204,48 @@ impl<'mc> PlayerToggleSprintEvent<'mc> { vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerToggleSprintEvent::from_raw(&jni, res) + crate::event::player::PlayerSignOpenEvent::from_raw(&jni, res) } - /// Gets whether the player is now sprinting or not. - pub fn is_sprinting(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isSprinting", sig.as_str(), vec![]); + /// Gets the sign that was opened. + pub fn sign(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/Sign;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSign", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::Sign::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets side of the sign opened. + pub fn side(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/sign/Side;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSide", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::sign::Side::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the cause of the sign open. + pub fn cause( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/event/player/PlayerSignOpenEvent/Cause;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCause", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::player::PlayerSignOpenEventCause::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn is_cancelled(&self) -> Result> { @@ -2507,14 +2285,14 @@ impl<'mc> PlayerToggleSprintEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerToggleSprintEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerSignOpenEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['isSprinting', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getSign', 'getSide', 'getCause', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -2529,129 +2307,209 @@ impl<'mc> PlayerToggleSprintEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerToggleSprintEvent<'mc> { +impl<'mc> Into> for PlayerSignOpenEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerToggleSprintEvent into crate::event::Cancellable") + .expect("Error converting PlayerSignOpenEvent into crate::event::Cancellable") } } -impl<'mc> Into> for PlayerToggleSprintEvent<'mc> { +impl<'mc> Into> for PlayerSignOpenEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { - crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting PlayerToggleSprintEvent into crate::event::player::PlayerEvent", - ) + crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerSignOpenEvent into crate::event::player::PlayerEvent") } } -#[repr(C)] -pub struct PlayerLocaleChangeEvent<'mc>( +pub enum PlayerSignOpenEventCause<'mc> { + Interact { + inner: PlayerSignOpenEventCauseStruct<'mc>, + }, + Place { + inner: PlayerSignOpenEventCauseStruct<'mc>, + }, + Plugin { + inner: PlayerSignOpenEventCauseStruct<'mc>, + }, + Unknown { + inner: PlayerSignOpenEventCauseStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for PlayerSignOpenEventCause<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PlayerSignOpenEventCause::Interact { .. } => f.write_str("INTERACT"), + PlayerSignOpenEventCause::Place { .. } => f.write_str("PLACE"), + PlayerSignOpenEventCause::Plugin { .. } => f.write_str("PLUGIN"), + PlayerSignOpenEventCause::Unknown { .. } => f.write_str("UNKNOWN"), + } + } +} +impl<'mc> std::ops::Deref for PlayerSignOpenEventCause<'mc> { + type Target = PlayerSignOpenEventCauseStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + PlayerSignOpenEventCause::Interact { inner } => inner, + PlayerSignOpenEventCause::Place { inner } => inner, + PlayerSignOpenEventCause::Plugin { inner } => inner, + PlayerSignOpenEventCause::Unknown { inner } => inner, + } + } +} + +impl<'mc> PlayerSignOpenEventCause<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/event/player/PlayerSignOpenEvent/Cause"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/event/player/PlayerSignOpenEvent/Cause;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "INTERACT" => Ok(PlayerSignOpenEventCause::Interact { + inner: PlayerSignOpenEventCauseStruct::from_raw(env, obj)?, + }), + "PLACE" => Ok(PlayerSignOpenEventCause::Place { + inner: PlayerSignOpenEventCauseStruct::from_raw(env, obj)?, + }), + "PLUGIN" => Ok(PlayerSignOpenEventCause::Plugin { + inner: PlayerSignOpenEventCauseStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(PlayerSignOpenEventCause::Unknown { + inner: PlayerSignOpenEventCauseStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct PlayerSignOpenEventCauseStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerLocaleChangeEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerSignOpenEventCause<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + match self { + Self::Interact { inner } => inner.0.clone(), + Self::Place { inner } => inner.0.clone(), + Self::Plugin { inner } => inner.0.clone(), + Self::Unknown { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + match self { + Self::Interact { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Place { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Plugin { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Unknown { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerLocaleChangeEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerSignOpenEventCause<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate PlayerLocaleChangeEvent from null object." + "Tried to instantiate PlayerSignOpenEventCause from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerLocaleChangeEvent")?; + env.validate_name(&obj, "org/bukkit/event/player/PlayerSignOpenEvent/Cause")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerLocaleChangeEvent object, got {}", + "Invalid argument passed. Expected a PlayerSignOpenEventCause object, got {}", name ) .into()) } else { - Ok(Self(env.clone(), obj)) + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "INTERACT" => Ok(PlayerSignOpenEventCause::Interact { + inner: PlayerSignOpenEventCauseStruct::from_raw(env, obj)?, + }), + "PLACE" => Ok(PlayerSignOpenEventCause::Place { + inner: PlayerSignOpenEventCauseStruct::from_raw(env, obj)?, + }), + "PLUGIN" => Ok(PlayerSignOpenEventCause::Plugin { + inner: PlayerSignOpenEventCauseStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(PlayerSignOpenEventCause::Unknown { + inner: PlayerSignOpenEventCauseStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } } -impl<'mc> PlayerLocaleChangeEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - who: impl Into>, - locale: impl Into, - ) -> Result, Box> - { - let sig = String::from("(Lorg/bukkit/entity/Player;Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(who.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(locale.into())?, - )); - let cls = jni.find_class("org/bukkit/event/player/PlayerLocaleChangeEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerLocaleChangeEvent::from_raw(&jni, res) +impl<'mc> JNIRaw<'mc> for PlayerSignOpenEventCauseStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - - pub fn locale(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getLocale", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} +impl<'mc> JNIInstantiatable<'mc> for PlayerSignOpenEventCauseStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate PlayerSignOpenEventCauseStruct from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/player/PlayerSignOpenEvent/Cause")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PlayerSignOpenEventCauseStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } +} - pub fn handler_list( +impl<'mc> PlayerSignOpenEventCauseStruct<'mc> { + pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerLocaleChangeEvent"); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/event/player/PlayerSignOpenEvent/Cause;"); + let cls = jni.find_class("org/bukkit/event/player/PlayerSignOpenEvent/Cause"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getLocale', 'getHandlers', 'getHandlerList']) - /// Returns the player involved in this event - pub fn player(&self) -> Result, Box> { - let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerEvent = temp_clone.into(); - real.player() + crate::event::player::PlayerSignOpenEventCause::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -2659,20 +2517,13 @@ impl<'mc> PlayerLocaleChangeEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerLocaleChangeEvent<'mc> { - fn into(self) -> crate::event::player::PlayerEvent<'mc> { - crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting PlayerLocaleChangeEvent into crate::event::player::PlayerEvent", - ) - } -} #[repr(C)] -pub struct PlayerItemDamageEvent<'mc>( +pub struct AsyncPlayerPreLoginEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerItemDamageEvent<'mc> { +impl<'mc> JNIRaw<'mc> for AsyncPlayerPreLoginEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2680,22 +2531,22 @@ impl<'mc> JNIRaw<'mc> for PlayerItemDamageEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerItemDamageEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for AsyncPlayerPreLoginEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate PlayerItemDamageEvent from null object." + "Tried to instantiate AsyncPlayerPreLoginEvent from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerItemDamageEvent")?; + env.validate_name(&obj, "org/bukkit/event/player/AsyncPlayerPreLoginEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerItemDamageEvent object, got {}", + "Invalid argument passed. Expected a AsyncPlayerPreLoginEvent object, got {}", name ) .into()) @@ -2705,90 +2556,221 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerItemDamageEvent<'mc> { } } -impl<'mc> PlayerItemDamageEvent<'mc> { +impl<'mc> AsyncPlayerPreLoginEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - player: impl Into>, - what: impl Into>, - damage: i32, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/inventory/ItemStack;I)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(what.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Int(damage); - let cls = jni.find_class("org/bukkit/event/player/PlayerItemDamageEvent"); + name: impl Into, + ip_address: jni::objects::JObject<'mc>, + unique_id: std::option::Option>>, + transferred: std::option::Option, + ) -> Result, Box> + { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(name.into())?, + )); + args.push(val_1); + sig += "Ljava/net/InetAddress;"; + let val_2 = jni::objects::JValueGen::Object(ip_address); + args.push(val_2); + if let Some(a) = unique_id { + sig += "Ljava/util/UUID;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_3); + } + if let Some(a) = transferred { + sig += "Z"; + let val_4 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_4); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/player/AsyncPlayerPreLoginEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); + let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerItemDamageEvent::from_raw(&jni, res) - } - /// Gets the item being damaged. - pub fn item(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + crate::event::player::AsyncPlayerPreLoginEvent::from_raw(&jni, res) } - /// Gets the amount of durability damage this item will be taking. - pub fn damage(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the current result of the login, as an enum + pub fn login_result( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/event/player/AsyncPlayerPreLoginEvent/Result;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLoginResult", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::player::AsyncPlayerPreLoginEventResult::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + #[deprecated] + /// Gets the current result of the login, as an enum + pub fn result( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/event/player/PlayerPreLoginEvent/Result;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getDamage", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getResult", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::event::player::PlayerPreLoginEventResult::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - - pub fn set_damage(&self, damage: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(damage); + /// Sets the new result of the login, as an enum + pub fn set_login_result( + &self, + result: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/event/player/AsyncPlayerPreLoginEvent/Result;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(result.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setDamage", + "setLoginResult", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); + #[deprecated] + /// Sets the new result of the login, as an enum + pub fn set_result( + &self, + result: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/event/player/PlayerPreLoginEvent/Result;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(result.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setResult", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the current kick message that will be used if getResult() != + /// Result.ALLOWED + pub fn kick_message(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getKickMessage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + /// Sets the kick message to display if getResult() != Result.ALLOWED + pub fn set_kick_message( + &self, + message: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(message.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setCancelled", + "setKickMessage", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } + /// Allows the player to log in + pub fn allow(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "allow", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Disallows the player from logging in, with the given reason + pub fn disallow( + &self, + result: impl Into>, + message: impl Into, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/event/player/PlayerPreLoginEvent/Result;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(result.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(message.into())?, + )); + args.push(val_2); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "disallow", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the player's name. + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gets the player IP address. + pub fn address(&self) -> Result, Box> { + let sig = String::from("()Ljava/net/InetAddress;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAddress", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) + } + /// Gets the player's unique ID. + pub fn unique_id( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets if this connection has been transferred from another server. + pub fn is_transferred(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isTransferred", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -2805,21 +2787,49 @@ impl<'mc> PlayerItemDamageEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerItemDamageEvent"); + let cls = jni.find_class("org/bukkit/event/player/AsyncPlayerPreLoginEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getItem', 'getDamage', 'setDamage', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) - /// Returns the player involved in this event - pub fn player(&self) -> Result, Box> { - let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { + // SUPER CLASS: org.bukkit.event.Event ( ['getLoginResult', 'getResult', 'setLoginResult', 'setResult', 'getKickMessage', 'setKickMessage', 'allow', 'disallow', 'getName', 'getAddress', 'getUniqueId', 'isTransferred', 'getHandlers', 'getHandlerList']) + /// Convenience method for providing a user-friendly identifier. By + /// default, it is the event's class's {@linkplain Class#getSimpleName() + /// simple name}. + pub fn event_name(&self) -> Result> { + let temp_clone = crate::event::Event::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::player::PlayerEvent = temp_clone.into(); - real.player() + let real: crate::event::Event = temp_clone.into(); + real.event_name() + } + /// Any custom event that should not by synchronized with other events must + /// use the specific constructor. These are the caveats of using an + /// asynchronous event: + ///
    + ///
  • The event is never fired from inside code triggered by a + /// synchronous event. Attempting to do so results in an {@link + /// java.lang.IllegalStateException}. + ///
  • However, asynchronous event handlers may fire synchronous or + /// asynchronous events + ///
  • The event may be fired multiple times simultaneously and in any + /// order. + ///
  • Any newly registered or unregistered handler is ignored after an + /// event starts execution. + ///
  • The handlers for this event may block for any length of time. + ///
  • Some implementations may selectively declare a specific event use + /// as asynchronous. This behavior should be clearly defined. + ///
  • Asynchronous calls are not calculated in the plugin timing system. + ///
+ pub fn is_asynchronous(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isAsynchronous", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -2827,197 +2837,226 @@ impl<'mc> PlayerItemDamageEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerItemDamageEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerItemDamageEvent into crate::event::Cancellable") +impl<'mc> Into> for AsyncPlayerPreLoginEvent<'mc> { + fn into(self) -> crate::event::Event<'mc> { + crate::event::Event::from_raw(&self.jni_ref(), self.1) + .expect("Error converting AsyncPlayerPreLoginEvent into crate::event::Event") } } -impl<'mc> Into> for PlayerItemDamageEvent<'mc> { - fn into(self) -> crate::event::player::PlayerEvent<'mc> { - crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerItemDamageEvent into crate::event::player::PlayerEvent") - } +pub enum AsyncPlayerPreLoginEventResult<'mc> { + Allowed { + inner: AsyncPlayerPreLoginEventResultStruct<'mc>, + }, + KickFull { + inner: AsyncPlayerPreLoginEventResultStruct<'mc>, + }, + KickBanned { + inner: AsyncPlayerPreLoginEventResultStruct<'mc>, + }, + KickWhitelist { + inner: AsyncPlayerPreLoginEventResultStruct<'mc>, + }, + KickOther { + inner: AsyncPlayerPreLoginEventResultStruct<'mc>, + }, } -#[repr(C)] -pub struct AsyncPlayerChatPreviewEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for AsyncPlayerChatPreviewEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() +impl<'mc> std::fmt::Display for AsyncPlayerPreLoginEventResult<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + AsyncPlayerPreLoginEventResult::Allowed { .. } => f.write_str("ALLOWED"), + AsyncPlayerPreLoginEventResult::KickFull { .. } => f.write_str("KICK_FULL"), + AsyncPlayerPreLoginEventResult::KickBanned { .. } => f.write_str("KICK_BANNED"), + AsyncPlayerPreLoginEventResult::KickWhitelist { .. } => f.write_str("KICK_WHITELIST"), + AsyncPlayerPreLoginEventResult::KickOther { .. } => f.write_str("KICK_OTHER"), + } } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } +} +impl<'mc> std::ops::Deref for AsyncPlayerPreLoginEventResult<'mc> { + type Target = AsyncPlayerPreLoginEventResultStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + AsyncPlayerPreLoginEventResult::Allowed { inner } => inner, + AsyncPlayerPreLoginEventResult::KickFull { inner } => inner, + AsyncPlayerPreLoginEventResult::KickBanned { inner } => inner, + AsyncPlayerPreLoginEventResult::KickWhitelist { inner } => inner, + AsyncPlayerPreLoginEventResult::KickOther { inner } => inner, + } } } -impl<'mc> JNIInstantiatable<'mc> for AsyncPlayerChatPreviewEvent<'mc> { - fn from_raw( + +impl<'mc> AsyncPlayerPreLoginEventResult<'mc> { + pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate AsyncPlayerChatPreviewEvent from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/AsyncPlayerChatPreviewEvent")?; + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/event/player/AsyncPlayerPreLoginEvent/Result"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/event/player/AsyncPlayerPreLoginEvent/Result;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "ALLOWED" => Ok(AsyncPlayerPreLoginEventResult::Allowed { + inner: AsyncPlayerPreLoginEventResultStruct::from_raw(env, obj)?, + }), + "KICK_FULL" => Ok(AsyncPlayerPreLoginEventResult::KickFull { + inner: AsyncPlayerPreLoginEventResultStruct::from_raw(env, obj)?, + }), + "KICK_BANNED" => Ok(AsyncPlayerPreLoginEventResult::KickBanned { + inner: AsyncPlayerPreLoginEventResultStruct::from_raw(env, obj)?, + }), + "KICK_WHITELIST" => Ok(AsyncPlayerPreLoginEventResult::KickWhitelist { + inner: AsyncPlayerPreLoginEventResultStruct::from_raw(env, obj)?, + }), + "KICK_OTHER" => Ok(AsyncPlayerPreLoginEventResult::KickOther { + inner: AsyncPlayerPreLoginEventResultStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct AsyncPlayerPreLoginEventResultStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for AsyncPlayerPreLoginEventResult<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Allowed { inner } => inner.0.clone(), + Self::KickFull { inner } => inner.0.clone(), + Self::KickBanned { inner } => inner.0.clone(), + Self::KickWhitelist { inner } => inner.0.clone(), + Self::KickOther { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Allowed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::KickFull { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::KickBanned { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::KickWhitelist { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::KickOther { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for AsyncPlayerPreLoginEventResult<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate AsyncPlayerPreLoginEventResult from null object." + ) + .into()); + } + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/event/player/AsyncPlayerPreLoginEvent/Result", + )?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a AsyncPlayerChatPreviewEvent object, got {}", + "Invalid argument passed. Expected a AsyncPlayerPreLoginEventResult object, got {}", name ) .into()) } else { - Ok(Self(env.clone(), obj)) + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "ALLOWED" => Ok(AsyncPlayerPreLoginEventResult::Allowed { + inner: AsyncPlayerPreLoginEventResultStruct::from_raw(env, obj)?, + }), + "KICK_FULL" => Ok(AsyncPlayerPreLoginEventResult::KickFull { + inner: AsyncPlayerPreLoginEventResultStruct::from_raw(env, obj)?, + }), + "KICK_BANNED" => Ok(AsyncPlayerPreLoginEventResult::KickBanned { + inner: AsyncPlayerPreLoginEventResultStruct::from_raw(env, obj)?, + }), + "KICK_WHITELIST" => Ok(AsyncPlayerPreLoginEventResult::KickWhitelist { + inner: AsyncPlayerPreLoginEventResultStruct::from_raw(env, obj)?, + }), + "KICK_OTHER" => Ok(AsyncPlayerPreLoginEventResult::KickOther { + inner: AsyncPlayerPreLoginEventResultStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } } -impl<'mc> AsyncPlayerChatPreviewEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_async: bool, - who: impl Into>, - message: impl Into, - players: impl Into>, - ) -> Result, Box> - { - let sig = String::from("(ZLorg/bukkit/entity/Player;Ljava/lang/String;Ljava/util/Set;)V"); - let val_1 = jni::objects::JValueGen::Bool(val_async.into()); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(who.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(message.into())?, - )); - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(players.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/event/player/AsyncPlayerChatPreviewEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - ], - ); - let res = jni.translate_error_no_gen(res)?; - crate::event::player::AsyncPlayerChatPreviewEvent::from_raw(&jni, res) +impl<'mc> JNIRaw<'mc> for AsyncPlayerPreLoginEventResultStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for AsyncPlayerPreLoginEventResultStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate AsyncPlayerPreLoginEventResultStruct from null object." + ) + .into()); + } + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/event/player/AsyncPlayerPreLoginEvent/Result", + )?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a AsyncPlayerPreLoginEventResultStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } +} - pub fn handler_list( +impl<'mc> AsyncPlayerPreLoginEventResultStruct<'mc> { + pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/AsyncPlayerChatPreviewEvent"); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/event/player/AsyncPlayerPreLoginEvent/Result;"); + let cls = jni.find_class("org/bukkit/event/player/AsyncPlayerPreLoginEvent/Result"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.player.AsyncPlayerChatEvent ( ['getHandlers', 'getHandlerList']) - /// Gets the message that the player is attempting to send. This message - /// will be used with {@link #getFormat()}. - pub fn message(&self) -> Result> { - let temp_clone = crate::event::player::AsyncPlayerChatEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::AsyncPlayerChatEvent = temp_clone.into(); - real.message() - } - /// Sets the message that the player will send. This message will be used - /// with {@link #getFormat()}. - pub fn set_message( - &self, - message: impl Into, - ) -> Result<(), Box> { - let temp_clone = crate::event::player::AsyncPlayerChatEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::AsyncPlayerChatEvent = temp_clone.into(); - real.set_message(message) - } - /// Gets the format to use to display this chat message. - /// - /// When this event finishes execution, the first format parameter is the - /// {@link Player#getDisplayName()} and the second parameter is {@link - /// #getMessage()} - pub fn format(&self) -> Result> { - let temp_clone = crate::event::player::AsyncPlayerChatEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::AsyncPlayerChatEvent = temp_clone.into(); - real.format() - } - /// Sets the format to use to display this chat message. - /// - /// When this event finishes execution, the first format parameter is the - /// {@link Player#getDisplayName()} and the second parameter is {@link - /// #getMessage()} - pub fn set_format(&self, format: impl Into) -> Result<(), Box> { - let temp_clone = crate::event::player::AsyncPlayerChatEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::AsyncPlayerChatEvent = temp_clone.into(); - real.set_format(format) - } - /// Gets a set of recipients that this chat message will be displayed to. - /// - /// The set returned is not guaranteed to be mutable and may auto-populate - /// on access. Any listener accessing the returned set should be aware that - /// it may reduce performance for a lazy set implementation. - /// - /// Listeners should be aware that modifying the list may throw {@link - /// UnsupportedOperationException} if the event caller provides an - /// unmodifiable set. - pub fn recipients( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRecipients", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn is_cancelled(&self) -> Result> { - let temp_clone = crate::event::player::AsyncPlayerChatEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::AsyncPlayerChatEvent = temp_clone.into(); - real.is_cancelled() - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let temp_clone = crate::event::player::AsyncPlayerChatEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::AsyncPlayerChatEvent = temp_clone.into(); - real.set_cancelled(cancel) + crate::event::player::AsyncPlayerPreLoginEventResult::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -3025,20 +3064,13 @@ impl<'mc> AsyncPlayerChatPreviewEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> - for AsyncPlayerChatPreviewEvent<'mc> -{ - fn into(self) -> crate::event::player::AsyncPlayerChatEvent<'mc> { - crate::event::player::AsyncPlayerChatEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting AsyncPlayerChatPreviewEvent into crate::event::player::AsyncPlayerChatEvent") - } -} #[repr(C)] -pub struct PlayerBucketEmptyEvent<'mc>( +pub struct PlayerItemMendEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerBucketEmptyEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerItemMendEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3046,22 +3078,21 @@ impl<'mc> JNIRaw<'mc> for PlayerBucketEmptyEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerBucketEmptyEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerItemMendEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PlayerBucketEmptyEvent from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate PlayerItemMendEvent from null object.").into(), + ); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerBucketEmptyEvent")?; + env.validate_name(&obj, "org/bukkit/event/player/PlayerItemMendEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerBucketEmptyEvent object, got {}", + "Invalid argument passed. Expected a PlayerItemMendEvent object, got {}", name ) .into()) @@ -3071,17 +3102,15 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerBucketEmptyEvent<'mc> { } } -impl<'mc> PlayerBucketEmptyEvent<'mc> { +impl<'mc> PlayerItemMendEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, who: impl Into>, - block: impl Into>, - block_clicked: impl Into>, - block_face: impl Into>, - bucket: impl Into>, - item_in_hand: std::option::Option>>, - hand: std::option::Option>>, - ) -> Result, Box> { + item: impl Into>, + slot: impl Into>, + experience_orb: impl Into>, + repair_amount: std::option::Option, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "Lorg/bukkit/entity/Player;"; @@ -3089,46 +3118,119 @@ impl<'mc> PlayerBucketEmptyEvent<'mc> { jni::objects::JObject::from_raw(who.into().jni_object().clone()) }); args.push(val_1); - sig += "Lorg/bukkit/block/Block;"; + sig += "Lorg/bukkit/inventory/ItemStack;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) + jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); args.push(val_2); - sig += "Lorg/bukkit/block/Block;"; + sig += "Lorg/bukkit/inventory/EquipmentSlot;"; let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block_clicked.into().jni_object().clone()) + jni::objects::JObject::from_raw(slot.into().jni_object().clone()) }); args.push(val_3); - sig += "Lorg/bukkit/block/BlockFace;"; + sig += "Lorg/bukkit/entity/ExperienceOrb;"; let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block_face.into().jni_object().clone()) + jni::objects::JObject::from_raw(experience_orb.into().jni_object().clone()) }); args.push(val_4); - sig += "Lorg/bukkit/Material;"; - let val_5 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(bucket.into().jni_object().clone()) - }); - args.push(val_5); - if let Some(a) = item_in_hand { - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_6 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_6); - } - if let Some(a) = hand { - sig += "Lorg/bukkit/inventory/EquipmentSlot;"; - let val_7 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_7); + if let Some(a) = repair_amount { + sig += "I"; + let val_5 = jni::objects::JValueGen::Int(a); + args.push(val_5); } sig += ")V"; - let cls = jni.find_class("org/bukkit/event/player/PlayerBucketEmptyEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerItemMendEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerBucketEmptyEvent::from_raw(&jni, res) + crate::event::player::PlayerItemMendEvent::from_raw(&jni, res) + } + /// Get the {@link ItemStack} to be repaired. + /// This is not necessarily the item the player is holding. + pub fn item(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the {@link EquipmentSlot} in which the repaired {@link ItemStack} + /// may be found. + pub fn slot(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/EquipmentSlot;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSlot", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::EquipmentSlot::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the experience orb triggering the event. + pub fn experience_orb( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/ExperienceOrb;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getExperienceOrb", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::entity::ExperienceOrb::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the amount the item is to be repaired. + /// The default value is twice the value of the consumed experience orb + /// or the remaining damage left on the item, whichever is smaller. + pub fn repair_amount(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRepairAmount", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the amount the item will be repaired. + /// Half of this value will be subtracted from the experience orb which initiated this event. + pub fn set_repair_amount(&self, amount: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(amount); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRepairAmount", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancelled: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancelled.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn handlers(&self) -> Result, Box> { @@ -3146,90 +3248,21 @@ impl<'mc> PlayerBucketEmptyEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerBucketEmptyEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerItemMendEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerBucketEvent ( ['getHandlers', 'getHandlerList']) - /// Returns the bucket used in this event - pub fn bucket(&self) -> Result, Box> { - let temp_clone = crate::event::player::PlayerBucketEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerBucketEvent = temp_clone.into(); - real.bucket() - } - /// Get the resulting item in hand after the bucket event - pub fn item_stack( - &self, - ) -> Result>, Box> { - let temp_clone = crate::event::player::PlayerBucketEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerBucketEvent = temp_clone.into(); - real.item_stack() - } - /// Set the item in hand after the event - pub fn set_item_stack( - &self, - item_stack: impl Into>, - ) -> Result<(), Box> { - let temp_clone = crate::event::player::PlayerBucketEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerBucketEvent = temp_clone.into(); - real.set_item_stack(item_stack) - } - /// Gets the block involved in this event. - pub fn block(&self) -> Result, Box> { - let temp_clone = crate::event::player::PlayerBucketEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerBucketEvent = temp_clone.into(); - real.block() - } - /// Return the block clicked - pub fn block_clicked(&self) -> Result, Box> { - let temp_clone = crate::event::player::PlayerBucketEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerBucketEvent = temp_clone.into(); - real.block_clicked() - } - /// Get the face on the clicked block - pub fn block_face(&self) -> Result, Box> { - let temp_clone = crate::event::player::PlayerBucketEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerBucketEvent = temp_clone.into(); - real.block_face() - } - /// Get the hand that was used in this event. - pub fn hand(&self) -> Result, Box> { - let temp_clone = crate::event::player::PlayerBucketEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerBucketEvent = temp_clone.into(); - real.hand() - } - - pub fn is_cancelled(&self) -> Result> { - let temp_clone = crate::event::player::PlayerBucketEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerBucketEvent = temp_clone.into(); - real.is_cancelled() - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let temp_clone = crate::event::player::PlayerBucketEvent::from_raw(&self.0, unsafe { + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getItem', 'getSlot', 'getExperienceOrb', 'getRepairAmount', 'setRepairAmount', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + /// Returns the player involved in this event + pub fn player(&self) -> Result, Box> { + let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::player::PlayerBucketEvent = temp_clone.into(); - real.set_cancelled(cancel) + let real: crate::event::player::PlayerEvent = temp_clone.into(); + real.player() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -3237,20 +3270,25 @@ impl<'mc> PlayerBucketEmptyEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerBucketEmptyEvent<'mc> { - fn into(self) -> crate::event::player::PlayerBucketEvent<'mc> { - crate::event::player::PlayerBucketEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting PlayerBucketEmptyEvent into crate::event::player::PlayerBucketEvent", - ) +impl<'mc> Into> for PlayerItemMendEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerItemMendEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for PlayerItemMendEvent<'mc> { + fn into(self) -> crate::event::player::PlayerEvent<'mc> { + crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerItemMendEvent into crate::event::player::PlayerEvent") } } #[repr(C)] -pub struct PlayerInteractEntityEvent<'mc>( +pub struct PlayerAnimationEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerInteractEntityEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerAnimationEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3258,22 +3296,21 @@ impl<'mc> JNIRaw<'mc> for PlayerInteractEntityEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerInteractEntityEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerAnimationEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PlayerInteractEntityEvent from null object." - ) - .into()); - } + return Err( + eyre::eyre!("Tried to instantiate PlayerAnimationEvent from null object.").into(), + ); + } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerInteractEntityEvent")?; + env.validate_name(&obj, "org/bukkit/event/player/PlayerAnimationEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerInteractEntityEvent object, got {}", + "Invalid argument passed. Expected a PlayerAnimationEvent object, got {}", name ) .into()) @@ -3283,39 +3320,51 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerInteractEntityEvent<'mc> { } } -impl<'mc> PlayerInteractEntityEvent<'mc> { +impl<'mc> PlayerAnimationEvent<'mc> { + /// Construct a new PlayerAnimation event pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - who: impl Into>, - clicked_entity: impl Into>, - hand: std::option::Option>>, - ) -> Result, Box> - { + player: impl Into>, + player_animation_type: std::option::Option< + impl Into>, + >, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "Lorg/bukkit/entity/Player;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(who.into().jni_object().clone()) + jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); args.push(val_1); - sig += "Lorg/bukkit/entity/Entity;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(clicked_entity.into().jni_object().clone()) - }); - args.push(val_2); - if let Some(a) = hand { - sig += "Lorg/bukkit/inventory/EquipmentSlot;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { + if let Some(a) = player_animation_type { + sig += "Lorg/bukkit/event/player/PlayerAnimationType;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); - args.push(val_3); + args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/event/player/PlayerInteractEntityEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerAnimationEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerInteractEntityEvent::from_raw(&jni, res) + crate::event::player::PlayerAnimationEvent::from_raw(&jni, res) + } + /// Get the type of this animation event + pub fn animation_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/player/PlayerAnimationType;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAnimationType", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::event::player::PlayerAnimationType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn is_cancelled(&self) -> Result> { @@ -3339,28 +3388,6 @@ impl<'mc> PlayerInteractEntityEvent<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the entity that was right-clicked by the player. - pub fn right_clicked(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRightClicked", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// The hand used to perform this interaction. - pub fn hand(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/EquipmentSlot;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHand", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::EquipmentSlot::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -3377,14 +3404,14 @@ impl<'mc> PlayerInteractEntityEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerInteractEntityEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerAnimationEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['isCancelled', 'setCancelled', 'getRightClicked', 'getHand', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getAnimationType', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -3399,26 +3426,25 @@ impl<'mc> PlayerInteractEntityEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerInteractEntityEvent<'mc> { +impl<'mc> Into> for PlayerAnimationEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerInteractEntityEvent into crate::event::Cancellable") + .expect("Error converting PlayerAnimationEvent into crate::event::Cancellable") } } -impl<'mc> Into> for PlayerInteractEntityEvent<'mc> { +impl<'mc> Into> for PlayerAnimationEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { - crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting PlayerInteractEntityEvent into crate::event::player::PlayerEvent", - ) + crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerAnimationEvent into crate::event::player::PlayerEvent") } } #[repr(C)] -pub struct PlayerFishEvent<'mc>( +pub struct PlayerItemBreakEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerFishEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerItemBreakEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3426,20 +3452,21 @@ impl<'mc> JNIRaw<'mc> for PlayerFishEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerFishEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerItemBreakEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate PlayerFishEvent from null object.").into(), + eyre::eyre!("Tried to instantiate PlayerItemBreakEvent from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/player/PlayerFishEvent")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/player/PlayerItemBreakEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerFishEvent object, got {}", + "Invalid argument passed. Expected a PlayerItemBreakEvent object, got {}", name ) .into()) @@ -3449,162 +3476,183 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerFishEvent<'mc> { } } -impl<'mc> PlayerFishEvent<'mc> { +impl<'mc> PlayerItemBreakEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, player: impl Into>, - entity: impl Into>, - hook_entity: impl Into>, - hand: impl Into>, - state: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Player;"; + broken_item: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); - args.push(val_1); - sig += "Lorg/bukkit/entity/Entity;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) - }); - args.push(val_2); - sig += "Lorg/bukkit/entity/FishHook;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(hook_entity.into().jni_object().clone()) - }); - args.push(val_3); - sig += "Lorg/bukkit/inventory/EquipmentSlot;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(hand.into().jni_object().clone()) + jni::objects::JObject::from_raw(broken_item.into().jni_object().clone()) }); - args.push(val_4); - if let Some(a) = state { - sig += "Lorg/bukkit/event/player/PlayerFishEvent/State;"; - let val_5 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_5); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/event/player/PlayerFishEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerItemBreakEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerFishEvent::from_raw(&jni, res) - } - /// Gets the entity caught by the player. - /// - /// If player has fished successfully, the result may be cast to {@link - /// org.bukkit.entity.Item}. - pub fn caught(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getCaught", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::event::player::PlayerItemBreakEvent::from_raw(&jni, res) } - /// Gets the fishing hook. - pub fn hook(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/FishHook;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHook", sig.as_str(), vec![]); + /// Gets the item that broke + pub fn broken_item( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBrokenItem", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::FishHook::from_raw(&self.jni_ref(), unsafe { + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the amount of experience received when fishing. - /// - /// Note: This value has no default effect unless the event state is {@link - /// State#CAUGHT_FISH}. - pub fn exp_to_drop(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getExpToDrop", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/player/PlayerItemBreakEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) } - /// Sets the amount of experience received when fishing. - /// - /// Note: This value has no default effect unless the event state is {@link - /// State#CAUGHT_FISH}. - pub fn set_exp_to_drop(&self, amount: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(amount); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setExpToDrop", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getBrokenItem', 'getHandlers', 'getHandlerList']) + /// Returns the player involved in this event + pub fn player(&self) -> Result, Box> { + let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerEvent = temp_clone.into(); + real.player() } - /// Get the hand that was used in this event. - /// - /// The hand used is only present when the event state is {@link State#FISHING}. - /// In all other states, the hand is null. - pub fn hand( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/EquipmentSlot;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHand", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for PlayerItemBreakEvent<'mc> { + fn into(self) -> crate::event::player::PlayerEvent<'mc> { + crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerItemBreakEvent into crate::event::player::PlayerEvent") + } +} +#[repr(C)] +pub struct PlayerToggleSprintEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PlayerToggleSprintEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PlayerToggleSprintEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate PlayerToggleSprintEvent from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/player/PlayerToggleSprintEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PlayerToggleSprintEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - Ok(Some(crate::inventory::EquipmentSlot::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) } - /// Gets the state of the fishing - pub fn state( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/player/PlayerFishEvent/State;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getState", sig.as_str(), vec![]); +} + +impl<'mc> PlayerToggleSprintEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + player: impl Into>, + is_sprinting: bool, + ) -> Result, Box> + { + let sig = String::from("(Lorg/bukkit/entity/Player;Z)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(player.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Bool(is_sprinting.into()); + let cls = jni.find_class("org/bukkit/event/player/PlayerToggleSprintEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::event::player::PlayerToggleSprintEvent::from_raw(&jni, res) + } + /// Gets whether the player is now sprinting or not. + pub fn is_sprinting(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isSprinting", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::event::player::PlayerFishEventState::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) + } + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn handlers(&self) -> Result, Box> { @@ -3622,14 +3670,14 @@ impl<'mc> PlayerFishEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerFishEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerToggleSprintEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getCaught', 'getHook', 'isCancelled', 'setCancelled', 'getExpToDrop', 'setExpToDrop', 'getHand', 'getState', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['isSprinting', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -3644,100 +3692,26 @@ impl<'mc> PlayerFishEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerFishEvent<'mc> { +impl<'mc> Into> for PlayerToggleSprintEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerFishEvent into crate::event::Cancellable") + .expect("Error converting PlayerToggleSprintEvent into crate::event::Cancellable") } } -impl<'mc> Into> for PlayerFishEvent<'mc> { +impl<'mc> Into> for PlayerToggleSprintEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { - crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerFishEvent into crate::event::player::PlayerEvent") - } -} -pub enum PlayerFishEventState<'mc> {} -impl<'mc> std::fmt::Display for PlayerFishEventState<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> PlayerFishEventState<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/event/player/PlayerFishEvent/State"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/event/player/PlayerFishEvent/State;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting PlayerToggleSprintEvent into crate::event::player::PlayerEvent", + ) } } - #[repr(C)] -pub struct PlayerFishEventStateStruct<'mc>( +pub struct PlayerLocaleChangeEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerFishEventState<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for PlayerFishEventState<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate PlayerFishEventState from null object.").into(), - ); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerFishEvent/State")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerFishEventState object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for PlayerFishEventStateStruct<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerLocaleChangeEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3745,22 +3719,22 @@ impl<'mc> JNIRaw<'mc> for PlayerFishEventStateStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerFishEventStateStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerLocaleChangeEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate PlayerFishEventStateStruct from null object." + "Tried to instantiate PlayerLocaleChangeEvent from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerFishEvent/State")?; + env.validate_name(&obj, "org/bukkit/event/player/PlayerLocaleChangeEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerFishEventStateStruct object, got {}", + "Invalid argument passed. Expected a PlayerLocaleChangeEvent object, got {}", name ) .into()) @@ -3770,31 +3744,98 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerFishEventStateStruct<'mc> { } } -impl<'mc> PlayerFishEventStateStruct<'mc> { - pub fn values( +impl<'mc> PlayerLocaleChangeEvent<'mc> { + pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/player/PlayerFishEvent/State;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerFishEvent/State"); + who: impl Into>, + locale: impl Into, + ) -> Result, Box> + { + let sig = String::from("(Lorg/bukkit/entity/Player;Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(who.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(locale.into())?, + )); + let cls = jni.find_class("org/bukkit/event/player/PlayerLocaleChangeEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::player::PlayerFishEventState::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::event::player::PlayerLocaleChangeEvent::from_raw(&jni, res) + } + + pub fn locale(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLocale", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/player/PlayerLocaleChangeEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getLocale', 'getHandlers', 'getHandlerList']) + /// Returns the player involved in this event + pub fn player(&self) -> Result, Box> { + let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerEvent = temp_clone.into(); + real.player() + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for PlayerLocaleChangeEvent<'mc> { + fn into(self) -> crate::event::player::PlayerEvent<'mc> { + crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting PlayerLocaleChangeEvent into crate::event::player::PlayerEvent", + ) + } +} #[repr(C)] -pub struct PlayerLoginEvent<'mc>( +pub struct PlayerItemDamageEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerLoginEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerItemDamageEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3802,20 +3843,22 @@ impl<'mc> JNIRaw<'mc> for PlayerLoginEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerLoginEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerItemDamageEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate PlayerLoginEvent from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate PlayerItemDamageEvent from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/player/PlayerLoginEvent")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/player/PlayerItemDamageEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerLoginEvent object, got {}", + "Invalid argument passed. Expected a PlayerItemDamageEvent object, got {}", name ) .into()) @@ -3825,215 +3868,114 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerLoginEvent<'mc> { } } -impl<'mc> PlayerLoginEvent<'mc> { - /// This constructor pre-configures the event with a result and message +impl<'mc> PlayerItemDamageEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, player: impl Into>, - hostname: impl Into, - address: jni::objects::JObject<'mc>, - result: std::option::Option>>, - message: std::option::Option>, - real_address: std::option::Option>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Player;"; + what: impl Into>, + damage: i32, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/inventory/ItemStack;I)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); - args.push(val_1); - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(hostname.into())?, - )); - args.push(val_2); - sig += "Ljava/net/InetAddress;"; - let val_3 = jni::objects::JValueGen::Object(address); - args.push(val_3); - if let Some(a) = result { - sig += "Lorg/bukkit/event/player/PlayerLoginEvent/Result;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_4); - } - if let Some(a) = message { - sig += "Ljava/lang/String;"; - let val_5 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(a.into())?, - )); - args.push(val_5); - } - if let Some(a) = real_address { - sig += "Ljava/net/InetAddress;"; - let val_6 = jni::objects::JValueGen::Object(a); - args.push(val_6); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/event/player/PlayerLoginEvent"); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(what.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Int(damage); + let cls = jni.find_class("org/bukkit/event/player/PlayerItemDamageEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerLoginEvent::from_raw(&jni, res) + crate::event::player::PlayerItemDamageEvent::from_raw(&jni, res) } - /// Gets the current result of the login, as an enum - pub fn result( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/player/PlayerLoginEvent/Result;"); + /// Gets the item being damaged. + pub fn item(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getResult", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::event::player::PlayerLoginEventResult::from_raw(&self.jni_ref(), unsafe { + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the new result of the login, as an enum - pub fn set_result( - &self, - result: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/player/PlayerLoginEvent/Result;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(result.into().jni_object().clone()) - }); + /// Gets the amount of durability damage this item will be taking. + pub fn damage(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getDamage", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + + pub fn set_damage(&self, damage: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(damage); let res = self.jni_ref().call_method( &self.jni_object(), - "setResult", + "setDamage", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the current kick message that will be used if getResult() != - /// Result.ALLOWED - pub fn kick_message(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getKickMessage", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - /// Sets the kick message to display if getResult() != Result.ALLOWED - pub fn set_kick_message( - &self, - message: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(message.into())?, - )); + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setKickMessage", + "setCancelled", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the hostname that the player used to connect to the server, or - /// blank if unknown - pub fn hostname(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getHostname", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Allows the player to log in - pub fn allow(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "allow", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/player/PlayerItemDamageEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) } - /// Disallows the player from logging in, with the given reason - pub fn disallow( - &self, - result: impl Into>, - message: impl Into, - ) -> Result<(), Box> { - let sig = - String::from("(Lorg/bukkit/event/player/PlayerLoginEvent/Result;Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(result.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(message.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "disallow", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the {@link InetAddress} for the Player associated with this event. - /// This method is provided as a workaround for player.getAddress() - /// returning null during PlayerLoginEvent. - pub fn address(&self) -> Result, Box> { - let sig = String::from("()Ljava/net/InetAddress;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAddress", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) - } - /// Gets the connection address of this player, regardless of whether it has - /// been spoofed or not. - pub fn real_address(&self) -> Result, Box> { - let sig = String::from("()Ljava/net/InetAddress;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRealAddress", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) - } - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn handler_list( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerLoginEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getResult', 'setResult', 'getKickMessage', 'setKickMessage', 'getHostname', 'allow', 'disallow', 'getAddress', 'getRealAddress', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getItem', 'getDamage', 'setDamage', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -4048,95 +3990,25 @@ impl<'mc> PlayerLoginEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerLoginEvent<'mc> { - fn into(self) -> crate::event::player::PlayerEvent<'mc> { - crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerLoginEvent into crate::event::player::PlayerEvent") - } -} -pub enum PlayerLoginEventResult<'mc> {} -impl<'mc> std::fmt::Display for PlayerLoginEventResult<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} +impl<'mc> Into> for PlayerItemDamageEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerItemDamageEvent into crate::event::Cancellable") } } - -impl<'mc> PlayerLoginEventResult<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/event/player/PlayerLoginEvent/Result"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/event/player/PlayerLoginEvent/Result;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } +impl<'mc> Into> for PlayerItemDamageEvent<'mc> { + fn into(self) -> crate::event::player::PlayerEvent<'mc> { + crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerItemDamageEvent into crate::event::player::PlayerEvent") } } - #[repr(C)] -pub struct PlayerLoginEventResultStruct<'mc>( +pub struct AsyncPlayerChatPreviewEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerLoginEventResult<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for PlayerLoginEventResult<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PlayerLoginEventResult from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerLoginEvent/Result")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerLoginEventResult object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for PlayerLoginEventResultStruct<'mc> { +impl<'mc> JNIRaw<'mc> for AsyncPlayerChatPreviewEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -4144,22 +4016,22 @@ impl<'mc> JNIRaw<'mc> for PlayerLoginEventResultStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerLoginEventResultStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for AsyncPlayerChatPreviewEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate PlayerLoginEventResultStruct from null object." + "Tried to instantiate AsyncPlayerChatPreviewEvent from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerLoginEvent/Result")?; + env.validate_name(&obj, "org/bukkit/event/player/AsyncPlayerChatPreviewEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerLoginEventResultStruct object, got {}", + "Invalid argument passed. Expected a AsyncPlayerChatPreviewEvent object, got {}", name ) .into()) @@ -4169,148 +4041,146 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerLoginEventResultStruct<'mc> { } } -impl<'mc> PlayerLoginEventResultStruct<'mc> { - pub fn values( +impl<'mc> AsyncPlayerChatPreviewEvent<'mc> { + pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/player/PlayerLoginEvent/Result;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerLoginEvent/Result"); + val_async: bool, + who: impl Into>, + message: impl Into, + players: impl Into>, + ) -> Result, Box> + { + let sig = String::from("(ZLorg/bukkit/entity/Player;Ljava/lang/String;Ljava/util/Set;)V"); + let val_1 = jni::objects::JValueGen::Bool(val_async.into()); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(who.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(message.into())?, + )); + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(players.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/player/AsyncPlayerChatPreviewEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::player::PlayerLoginEventResult::from_raw(&jni, obj) + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::event::player::AsyncPlayerChatPreviewEvent::from_raw(&jni, res) } - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -#[repr(C)] -pub struct PlayerRiptideEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); -impl<'mc> JNIRaw<'mc> for PlayerRiptideEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/player/AsyncPlayerChatPreviewEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + // SUPER CLASS: org.bukkit.event.player.AsyncPlayerChatEvent ( ['getHandlers', 'getHandlerList']) + /// Gets the message that the player is attempting to send. This message + /// will be used with {@link #getFormat()}. + pub fn message(&self) -> Result> { + let temp_clone = crate::event::player::AsyncPlayerChatEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::AsyncPlayerChatEvent = temp_clone.into(); + real.message() } -} -impl<'mc> JNIInstantiatable<'mc> for PlayerRiptideEvent<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate PlayerRiptideEvent from null object.").into(), - ); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerRiptideEvent")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerRiptideEvent object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Sets the message that the player will send. This message will be used + /// with {@link #getFormat()}. + pub fn set_message( + &self, + message: impl Into, + ) -> Result<(), Box> { + let temp_clone = crate::event::player::AsyncPlayerChatEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::AsyncPlayerChatEvent = temp_clone.into(); + real.set_message(message) } -} - -impl<'mc> PlayerRiptideEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - who: impl Into>, - item: impl Into>, - velocity: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Player;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(who.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - args.push(val_2); - if let Some(a) = velocity { - sig += "Lorg/bukkit/util/Vector;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_3); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/event/player/PlayerRiptideEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerRiptideEvent::from_raw(&jni, res) + /// Gets the format to use to display this chat message. + /// + /// When this event finishes execution, the first format parameter is the + /// {@link Player#getDisplayName()} and the second parameter is {@link + /// #getMessage()} + pub fn format(&self) -> Result> { + let temp_clone = crate::event::player::AsyncPlayerChatEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::AsyncPlayerChatEvent = temp_clone.into(); + real.format() } - /// Gets the item containing the used enchantment. - pub fn item(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Sets the format to use to display this chat message. + /// + /// When this event finishes execution, the first format parameter is the + /// {@link Player#getDisplayName()} and the second parameter is {@link + /// #getMessage()} + pub fn set_format(&self, format: impl Into) -> Result<(), Box> { + let temp_clone = crate::event::player::AsyncPlayerChatEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::AsyncPlayerChatEvent = temp_clone.into(); + real.set_format(format) } - /// Get the velocity applied to the player as a result of this riptide. - pub fn velocity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); + /// Gets a set of recipients that this chat message will be displayed to. + /// + /// The set returned is not guaranteed to be mutable and may auto-populate + /// on access. Any listener accessing the returned set should be aware that + /// it may reduce performance for a lazy set implementation. + /// + /// Listeners should be aware that modifying the list may throw {@link + /// UnsupportedOperationException} if the event caller provides an + /// unmodifiable set. + pub fn recipients( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getRecipients", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + pub fn is_cancelled(&self) -> Result> { + let temp_clone = crate::event::player::AsyncPlayerChatEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::AsyncPlayerChatEvent = temp_clone.into(); + real.is_cancelled() } - pub fn handler_list( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerRiptideEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getItem', 'getVelocity', 'getHandlers', 'getHandlerList']) - /// Returns the player involved in this event - pub fn player(&self) -> Result, Box> { - let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let temp_clone = crate::event::player::AsyncPlayerChatEvent::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::player::PlayerEvent = temp_clone.into(); - real.player() + let real: crate::event::player::AsyncPlayerChatEvent = temp_clone.into(); + real.set_cancelled(cancel) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -4318,19 +4188,20 @@ impl<'mc> PlayerRiptideEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerRiptideEvent<'mc> { - fn into(self) -> crate::event::player::PlayerEvent<'mc> { - crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerRiptideEvent into crate::event::player::PlayerEvent") +impl<'mc> Into> + for AsyncPlayerChatPreviewEvent<'mc> +{ + fn into(self) -> crate::event::player::AsyncPlayerChatEvent<'mc> { + crate::event::player::AsyncPlayerChatEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting AsyncPlayerChatPreviewEvent into crate::event::player::AsyncPlayerChatEvent") } } #[repr(C)] -pub struct PlayerChangedWorldEvent<'mc>( +pub struct PlayerBucketEmptyEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerChangedWorldEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerBucketEmptyEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -4338,22 +4209,22 @@ impl<'mc> JNIRaw<'mc> for PlayerChangedWorldEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerChangedWorldEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerBucketEmptyEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate PlayerChangedWorldEvent from null object." + "Tried to instantiate PlayerBucketEmptyEvent from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerChangedWorldEvent")?; + env.validate_name(&obj, "org/bukkit/event/player/PlayerBucketEmptyEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerChangedWorldEvent object, got {}", + "Invalid argument passed. Expected a PlayerBucketEmptyEvent object, got {}", name ) .into()) @@ -4363,43 +4234,64 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerChangedWorldEvent<'mc> { } } -impl<'mc> PlayerChangedWorldEvent<'mc> { +impl<'mc> PlayerBucketEmptyEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - player: impl Into>, - from: impl Into>, - ) -> Result, Box> - { - let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/World;)V"); + who: impl Into>, + block: impl Into>, + block_clicked: impl Into>, + block_face: impl Into>, + bucket: impl Into>, + item_in_hand: std::option::Option>>, + hand: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Player;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) + jni::objects::JObject::from_raw(who.into().jni_object().clone()) }); + args.push(val_1); + sig += "Lorg/bukkit/block/Block;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(from.into().jni_object().clone()) + jni::objects::JObject::from_raw(block.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/player/PlayerChangedWorldEvent"); + args.push(val_2); + sig += "Lorg/bukkit/block/Block;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(block_clicked.into().jni_object().clone()) + }); + args.push(val_3); + sig += "Lorg/bukkit/block/BlockFace;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(block_face.into().jni_object().clone()) + }); + args.push(val_4); + sig += "Lorg/bukkit/Material;"; + let val_5 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(bucket.into().jni_object().clone()) + }); + args.push(val_5); + if let Some(a) = item_in_hand { + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_6 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_6); + } + if let Some(a) = hand { + sig += "Lorg/bukkit/inventory/EquipmentSlot;"; + let val_7 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_7); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/player/PlayerBucketEmptyEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerChangedWorldEvent::from_raw(&jni, res) - } - /// Gets the world the player is switching from. - pub fn from(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFrom", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + crate::event::player::PlayerBucketEmptyEvent::from_raw(&jni, res) } pub fn handlers(&self) -> Result, Box> { @@ -4417,42 +4309,111 @@ impl<'mc> PlayerChangedWorldEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerChangedWorldEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerBucketEmptyEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getFrom', 'getHandlers', 'getHandlerList']) - /// Returns the player involved in this event - pub fn player(&self) -> Result, Box> { - let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { + // SUPER CLASS: org.bukkit.event.player.PlayerBucketEvent ( ['getHandlers', 'getHandlerList']) + /// Returns the bucket used in this event + pub fn bucket(&self) -> Result, Box> { + let temp_clone = crate::event::player::PlayerBucketEvent::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::player::PlayerEvent = temp_clone.into(); - real.player() + let real: crate::event::player::PlayerBucketEvent = temp_clone.into(); + real.bucket() } - + /// Get the resulting item in hand after the bucket event + pub fn item_stack( + &self, + ) -> Result>, Box> { + let temp_clone = crate::event::player::PlayerBucketEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerBucketEvent = temp_clone.into(); + real.item_stack() + } + /// Set the item in hand after the event + pub fn set_item_stack( + &self, + item_stack: impl Into>, + ) -> Result<(), Box> { + let temp_clone = crate::event::player::PlayerBucketEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerBucketEvent = temp_clone.into(); + real.set_item_stack(item_stack) + } + /// Gets the block involved in this event. + pub fn block(&self) -> Result, Box> { + let temp_clone = crate::event::player::PlayerBucketEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerBucketEvent = temp_clone.into(); + real.block() + } + /// Return the block clicked + pub fn block_clicked(&self) -> Result, Box> { + let temp_clone = crate::event::player::PlayerBucketEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerBucketEvent = temp_clone.into(); + real.block_clicked() + } + /// Get the face on the clicked block + pub fn block_face(&self) -> Result, Box> { + let temp_clone = crate::event::player::PlayerBucketEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerBucketEvent = temp_clone.into(); + real.block_face() + } + /// Get the hand that was used in this event. + pub fn hand(&self) -> Result, Box> { + let temp_clone = crate::event::player::PlayerBucketEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerBucketEvent = temp_clone.into(); + real.hand() + } + + pub fn is_cancelled(&self) -> Result> { + let temp_clone = crate::event::player::PlayerBucketEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerBucketEvent = temp_clone.into(); + real.is_cancelled() + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let temp_clone = crate::event::player::PlayerBucketEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerBucketEvent = temp_clone.into(); + real.set_cancelled(cancel) + } + pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerChangedWorldEvent<'mc> { - fn into(self) -> crate::event::player::PlayerEvent<'mc> { - crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting PlayerChangedWorldEvent into crate::event::player::PlayerEvent", +impl<'mc> Into> for PlayerBucketEmptyEvent<'mc> { + fn into(self) -> crate::event::player::PlayerBucketEvent<'mc> { + crate::event::player::PlayerBucketEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting PlayerBucketEmptyEvent into crate::event::player::PlayerBucketEvent", ) } } #[repr(C)] -pub struct PlayerStatisticIncrementEvent<'mc>( +pub struct PlayerInteractEntityEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerStatisticIncrementEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerInteractEntityEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -4460,24 +4421,22 @@ impl<'mc> JNIRaw<'mc> for PlayerStatisticIncrementEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerStatisticIncrementEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerInteractEntityEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate PlayerStatisticIncrementEvent from null object." + "Tried to instantiate PlayerInteractEntityEvent from null object." ) .into()); } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/event/player/PlayerStatisticIncrementEvent", - )?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/player/PlayerInteractEntityEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerStatisticIncrementEvent object, got {}", + "Invalid argument passed. Expected a PlayerInteractEntityEvent object, got {}", name ) .into()) @@ -4487,112 +4446,39 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerStatisticIncrementEvent<'mc> { } } -impl<'mc> PlayerStatisticIncrementEvent<'mc> { +impl<'mc> PlayerInteractEntityEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - player: impl Into>, - statistic: impl Into>, - initial_value: i32, - new_value: i32, - material: std::option::Option>>, - ) -> Result, Box> + who: impl Into>, + clicked_entity: impl Into>, + hand: std::option::Option>>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "Lorg/bukkit/entity/Player;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) + jni::objects::JObject::from_raw(who.into().jni_object().clone()) }); args.push(val_1); - sig += "Lorg/bukkit/Statistic;"; + sig += "Lorg/bukkit/entity/Entity;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(statistic.into().jni_object().clone()) + jni::objects::JObject::from_raw(clicked_entity.into().jni_object().clone()) }); args.push(val_2); - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(initial_value); - args.push(val_3); - sig += "I"; - let val_4 = jni::objects::JValueGen::Int(new_value); - args.push(val_4); - if let Some(a) = material { - sig += "Lorg/bukkit/Material;"; - let val_5 = jni::objects::JValueGen::Object(unsafe { + if let Some(a) = hand { + sig += "Lorg/bukkit/inventory/EquipmentSlot;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); - args.push(val_5); + args.push(val_3); } sig += ")V"; - let cls = jni.find_class("org/bukkit/event/player/PlayerStatisticIncrementEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerInteractEntityEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerStatisticIncrementEvent::from_raw(&jni, res) - } - /// Gets the statistic that is being incremented. - pub fn statistic(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Statistic;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getStatistic", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Statistic::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the previous value of the statistic. - pub fn previous_value(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPreviousValue", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the new value of the statistic. - pub fn new_value(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getNewValue", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the EntityType if {@link #getStatistic() getStatistic()} is an - /// entity statistic otherwise returns null. - pub fn entity_type( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEntityType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::EntityType::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Gets the Material if {@link #getStatistic() getStatistic()} is a block - /// or item statistic otherwise returns null. - pub fn material(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaterial", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + crate::event::player::PlayerInteractEntityEvent::from_raw(&jni, res) } pub fn is_cancelled(&self) -> Result> { @@ -4616,6 +4502,28 @@ impl<'mc> PlayerStatisticIncrementEvent<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } + /// Gets the entity that was right-clicked by the player. + pub fn right_clicked(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRightClicked", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// The hand used to perform this interaction. + pub fn hand(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/EquipmentSlot;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHand", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::EquipmentSlot::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -4632,14 +4540,14 @@ impl<'mc> PlayerStatisticIncrementEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerStatisticIncrementEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerInteractEntityEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getStatistic', 'getPreviousValue', 'getNewValue', 'getEntityType', 'getMaterial', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['isCancelled', 'setCancelled', 'getRightClicked', 'getHand', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -4654,26 +4562,26 @@ impl<'mc> PlayerStatisticIncrementEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerStatisticIncrementEvent<'mc> { +impl<'mc> Into> for PlayerInteractEntityEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerStatisticIncrementEvent into crate::event::Cancellable") + .expect("Error converting PlayerInteractEntityEvent into crate::event::Cancellable") } } -impl<'mc> Into> for PlayerStatisticIncrementEvent<'mc> { +impl<'mc> Into> for PlayerInteractEntityEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting PlayerStatisticIncrementEvent into crate::event::player::PlayerEvent", + "Error converting PlayerInteractEntityEvent into crate::event::player::PlayerEvent", ) } } #[repr(C)] -pub struct PlayerRespawnEvent<'mc>( +pub struct PlayerFishEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerRespawnEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerFishEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -4681,21 +4589,20 @@ impl<'mc> JNIRaw<'mc> for PlayerRespawnEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerRespawnEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerFishEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate PlayerRespawnEvent from null object.").into(), + eyre::eyre!("Tried to instantiate PlayerFishEvent from null object.").into(), ); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerRespawnEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/player/PlayerFishEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerRespawnEvent object, got {}", + "Invalid argument passed. Expected a PlayerFishEvent object, got {}", name ) .into()) @@ -4705,117 +4612,160 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerRespawnEvent<'mc> { } } -impl<'mc> PlayerRespawnEvent<'mc> { +impl<'mc> PlayerFishEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - respawn_player: impl Into>, - respawn_location: impl Into>, - is_bed_spawn: bool, - is_anchor_spawn: std::option::Option, - respawn_reason: std::option::Option< - impl Into>, - >, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Player;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(respawn_player.into().jni_object().clone()) + player: impl Into>, + entity: impl Into>, + hook_entity: impl Into>, + hand: impl Into>, + state: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Player;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); args.push(val_1); - sig += "Lorg/bukkit/Location;"; + sig += "Lorg/bukkit/entity/Entity;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(respawn_location.into().jni_object().clone()) + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) }); args.push(val_2); - sig += "Z"; - let val_3 = jni::objects::JValueGen::Bool(is_bed_spawn.into()); + sig += "Lorg/bukkit/entity/FishHook;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(hook_entity.into().jni_object().clone()) + }); args.push(val_3); - if let Some(a) = is_anchor_spawn { - sig += "Z"; - let val_4 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_4); - } - if let Some(a) = respawn_reason { - sig += "Lorg/bukkit/event/player/PlayerRespawnEvent/RespawnReason;"; + sig += "Lorg/bukkit/inventory/EquipmentSlot;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(hand.into().jni_object().clone()) + }); + args.push(val_4); + if let Some(a) = state { + sig += "Lorg/bukkit/event/player/PlayerFishEvent/State;"; let val_5 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); args.push(val_5); } sig += ")V"; - let cls = jni.find_class("org/bukkit/event/player/PlayerRespawnEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerFishEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerRespawnEvent::from_raw(&jni, res) + crate::event::player::PlayerFishEvent::from_raw(&jni, res) } - /// Gets the current respawn location - pub fn respawn_location(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getRespawnLocation", - sig.as_str(), - vec![], - ); + /// Gets the entity caught by the player. + /// + /// If player has fished successfully, the result may be cast to {@link + /// org.bukkit.entity.Item}. + pub fn caught(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCaught", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the fishing hook. + pub fn hook(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/FishHook;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHook", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::FishHook::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the new respawn location - pub fn set_respawn_location( - &self, - respawn_location: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Location;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(respawn_location.into().jni_object().clone()) - }); + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setRespawnLocation", + "setCancelled", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the respawn location is the player's bed. - pub fn is_bed_spawn(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isBedSpawn", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets whether the respawn location is the player's respawn anchor. - pub fn is_anchor_spawn(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the amount of experience received when fishing. + /// + /// Note: This value has no default effect unless the event state is {@link + /// State#CAUGHT_FISH}. + pub fn exp_to_drop(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isAnchorSpawn", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getExpToDrop", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Gets the reason this respawn event was called. - pub fn respawn_reason( - &self, - ) -> Result< - crate::event::player::PlayerRespawnEventRespawnReason<'mc>, - Box, - > { - let sig = String::from("()Lorg/bukkit/event/player/PlayerRespawnEvent/RespawnReason;"); + /// Sets the amount of experience received when fishing. + /// + /// Note: This value has no default effect unless the event state is {@link + /// State#CAUGHT_FISH}. + pub fn set_exp_to_drop(&self, amount: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "getRespawnReason", + "setExpToDrop", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the hand that was used in this event. + /// + /// The hand used is only present when the event state is {@link State#FISHING}. + /// In all other states, the hand is null. + pub fn hand( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/EquipmentSlot;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHand", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::event::player::PlayerRespawnEventRespawnReason::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::EquipmentSlot::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the state of the fishing + pub fn state( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/player/PlayerFishEvent/State;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getState", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::player::PlayerFishEventState::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -4835,14 +4785,14 @@ impl<'mc> PlayerRespawnEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerRespawnEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerFishEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getRespawnLocation', 'setRespawnLocation', 'isBedSpawn', 'isAnchorSpawn', 'getRespawnReason', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getCaught', 'getHook', 'isCancelled', 'setCancelled', 'getExpToDrop', 'setExpToDrop', 'getHand', 'getState', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -4857,31 +4807,81 @@ impl<'mc> PlayerRespawnEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerRespawnEvent<'mc> { +impl<'mc> Into> for PlayerFishEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerFishEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for PlayerFishEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerRespawnEvent into crate::event::player::PlayerEvent") + .expect("Error converting PlayerFishEvent into crate::event::player::PlayerEvent") } } -pub enum PlayerRespawnEventRespawnReason<'mc> {} -impl<'mc> std::fmt::Display for PlayerRespawnEventRespawnReason<'mc> { +pub enum PlayerFishEventState<'mc> { + Fishing { + inner: PlayerFishEventStateStruct<'mc>, + }, + CaughtFish { + inner: PlayerFishEventStateStruct<'mc>, + }, + CaughtEntity { + inner: PlayerFishEventStateStruct<'mc>, + }, + InGround { + inner: PlayerFishEventStateStruct<'mc>, + }, + FailedAttempt { + inner: PlayerFishEventStateStruct<'mc>, + }, + ReelIn { + inner: PlayerFishEventStateStruct<'mc>, + }, + Bite { + inner: PlayerFishEventStateStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for PlayerFishEventState<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + PlayerFishEventState::Fishing { .. } => f.write_str("FISHING"), + PlayerFishEventState::CaughtFish { .. } => f.write_str("CAUGHT_FISH"), + PlayerFishEventState::CaughtEntity { .. } => f.write_str("CAUGHT_ENTITY"), + PlayerFishEventState::InGround { .. } => f.write_str("IN_GROUND"), + PlayerFishEventState::FailedAttempt { .. } => f.write_str("FAILED_ATTEMPT"), + PlayerFishEventState::ReelIn { .. } => f.write_str("REEL_IN"), + PlayerFishEventState::Bite { .. } => f.write_str("BITE"), + } + } +} +impl<'mc> std::ops::Deref for PlayerFishEventState<'mc> { + type Target = PlayerFishEventStateStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + PlayerFishEventState::Fishing { inner } => inner, + PlayerFishEventState::CaughtFish { inner } => inner, + PlayerFishEventState::CaughtEntity { inner } => inner, + PlayerFishEventState::InGround { inner } => inner, + PlayerFishEventState::FailedAttempt { inner } => inner, + PlayerFishEventState::ReelIn { inner } => inner, + PlayerFishEventState::Bite { inner } => inner, + } } } -impl<'mc> PlayerRespawnEventRespawnReason<'mc> { +impl<'mc> PlayerFishEventState<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/event/player/PlayerRespawnEvent/RespawnReason"); + let cls = env.find_class("org/bukkit/event/player/PlayerFishEvent/State"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/event/player/PlayerRespawnEvent/RespawnReason;", + "(Ljava/lang/String;)Lorg/bukkit/event/player/PlayerFishEvent/State;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -4893,46 +4893,87 @@ impl<'mc> PlayerRespawnEventRespawnReason<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "FISHING" => Ok(PlayerFishEventState::Fishing { + inner: PlayerFishEventStateStruct::from_raw(env, obj)?, + }), + "CAUGHT_FISH" => Ok(PlayerFishEventState::CaughtFish { + inner: PlayerFishEventStateStruct::from_raw(env, obj)?, + }), + "CAUGHT_ENTITY" => Ok(PlayerFishEventState::CaughtEntity { + inner: PlayerFishEventStateStruct::from_raw(env, obj)?, + }), + "IN_GROUND" => Ok(PlayerFishEventState::InGround { + inner: PlayerFishEventStateStruct::from_raw(env, obj)?, + }), + "FAILED_ATTEMPT" => Ok(PlayerFishEventState::FailedAttempt { + inner: PlayerFishEventStateStruct::from_raw(env, obj)?, + }), + "REEL_IN" => Ok(PlayerFishEventState::ReelIn { + inner: PlayerFishEventStateStruct::from_raw(env, obj)?, + }), + "BITE" => Ok(PlayerFishEventState::Bite { + inner: PlayerFishEventStateStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct PlayerRespawnEventRespawnReasonStruct<'mc>( +pub struct PlayerFishEventStateStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerRespawnEventRespawnReason<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerFishEventState<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Fishing { inner } => inner.0.clone(), + Self::CaughtFish { inner } => inner.0.clone(), + Self::CaughtEntity { inner } => inner.0.clone(), + Self::InGround { inner } => inner.0.clone(), + Self::FailedAttempt { inner } => inner.0.clone(), + Self::ReelIn { inner } => inner.0.clone(), + Self::Bite { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Fishing { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CaughtFish { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CaughtEntity { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::InGround { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::FailedAttempt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ReelIn { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Bite { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerRespawnEventRespawnReason<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerFishEventState<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PlayerRespawnEventRespawnReason from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate PlayerFishEventState from null object.").into(), + ); } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/event/player/PlayerRespawnEvent/RespawnReason", - )?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/player/PlayerFishEvent/State")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerRespawnEventRespawnReason object, got {}", - name - ) - .into()) + "Invalid argument passed. Expected a PlayerFishEventState object, got {}", + name + ) + .into()) } else { let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); let variant = env.translate_error(variant)?; @@ -4941,13 +4982,34 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerRespawnEventRespawnReason<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "FISHING" => Ok(PlayerFishEventState::Fishing { + inner: PlayerFishEventStateStruct::from_raw(env, obj)?, + }), + "CAUGHT_FISH" => Ok(PlayerFishEventState::CaughtFish { + inner: PlayerFishEventStateStruct::from_raw(env, obj)?, + }), + "CAUGHT_ENTITY" => Ok(PlayerFishEventState::CaughtEntity { + inner: PlayerFishEventStateStruct::from_raw(env, obj)?, + }), + "IN_GROUND" => Ok(PlayerFishEventState::InGround { + inner: PlayerFishEventStateStruct::from_raw(env, obj)?, + }), + "FAILED_ATTEMPT" => Ok(PlayerFishEventState::FailedAttempt { + inner: PlayerFishEventStateStruct::from_raw(env, obj)?, + }), + "REEL_IN" => Ok(PlayerFishEventState::ReelIn { + inner: PlayerFishEventStateStruct::from_raw(env, obj)?, + }), + "BITE" => Ok(PlayerFishEventState::Bite { + inner: PlayerFishEventStateStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for PlayerRespawnEventRespawnReasonStruct<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerFishEventStateStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -4955,47 +5017,42 @@ impl<'mc> JNIRaw<'mc> for PlayerRespawnEventRespawnReasonStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerRespawnEventRespawnReasonStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerFishEventStateStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate PlayerRespawnEventRespawnReasonStruct from null object." + "Tried to instantiate PlayerFishEventStateStruct from null object." ) .into()); } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/event/player/PlayerRespawnEvent/RespawnReason", - )?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/player/PlayerFishEvent/State")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerRespawnEventRespawnReasonStruct object, got {}", - name - ) - .into()) + "Invalid argument passed. Expected a PlayerFishEventStateStruct object, got {}", + name + ) + .into()) } else { Ok(Self(env.clone(), obj)) } } } -impl<'mc> PlayerRespawnEventRespawnReasonStruct<'mc> { +impl<'mc> PlayerFishEventStateStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result< - crate::event::player::PlayerRespawnEventRespawnReason<'mc>, - Box, - > { - let sig = String::from("()Lorg/bukkit/event/player/PlayerRespawnEvent/RespawnReason;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerRespawnEvent/RespawnReason"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/player/PlayerFishEvent/State;"); + let cls = jni.find_class("org/bukkit/event/player/PlayerFishEvent/State"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::event::player::PlayerRespawnEventRespawnReason::from_raw(&jni, obj) + crate::event::player::PlayerFishEventState::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -5004,12 +5061,12 @@ impl<'mc> PlayerRespawnEventRespawnReasonStruct<'mc> { } } #[repr(C)] -pub struct PlayerEggThrowEvent<'mc>( +pub struct PlayerLoginEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerEggThrowEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerLoginEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -5017,21 +5074,20 @@ impl<'mc> JNIRaw<'mc> for PlayerEggThrowEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerEggThrowEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerLoginEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate PlayerEggThrowEvent from null object.").into(), + eyre::eyre!("Tried to instantiate PlayerLoginEvent from null object.").into(), ); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerEggThrowEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/player/PlayerLoginEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerEggThrowEvent object, got {}", + "Invalid argument passed. Expected a PlayerLoginEvent object, got {}", name ) .into()) @@ -5041,141 +5097,191 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerEggThrowEvent<'mc> { } } -impl<'mc> PlayerEggThrowEvent<'mc> { +impl<'mc> PlayerLoginEvent<'mc> { + /// This constructor pre-configures the event with a result and message pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, player: impl Into>, - egg: impl Into>, - hatching: bool, - num_hatches: i8, - hatching_type: impl Into>, - ) -> Result, Box> { - let sig = String::from( - "(Lorg/bukkit/entity/Player;Lorg/bukkit/entity/Egg;ZBLorg/bukkit/entity/EntityType;)V", - ); + hostname: impl Into, + address: jni::objects::JObject<'mc>, + result: std::option::Option>>, + message: std::option::Option>, + real_address: std::option::Option>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Player;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(egg.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Bool(hatching.into()); - let val_4 = jni::objects::JValueGen::Byte(num_hatches); - let val_5 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(hatching_type.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/event/player/PlayerEggThrowEvent"); + args.push(val_1); + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(hostname.into())?, + )); + args.push(val_2); + sig += "Ljava/net/InetAddress;"; + let val_3 = jni::objects::JValueGen::Object(address); + args.push(val_3); + if let Some(a) = result { + sig += "Lorg/bukkit/event/player/PlayerLoginEvent/Result;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_4); + } + if let Some(a) = message { + sig += "Ljava/lang/String;"; + let val_5 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(a.into())?, + )); + args.push(val_5); + } + if let Some(a) = real_address { + sig += "Ljava/net/InetAddress;"; + let val_6 = jni::objects::JValueGen::Object(a); + args.push(val_6); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/player/PlayerLoginEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - jni::objects::JValueGen::from(val_5), - ], - ); + let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerEggThrowEvent::from_raw(&jni, res) + crate::event::player::PlayerLoginEvent::from_raw(&jni, res) } - /// Gets the egg involved in this event. - pub fn egg(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Egg;"); + /// Gets the current result of the login, as an enum + pub fn result( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/player/PlayerLoginEvent/Result;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getEgg", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getResult", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Egg::from_raw(&self.jni_ref(), unsafe { + crate::event::player::PlayerLoginEventResult::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets whether the egg is hatching or not. Will be what the server - /// would've done without interaction. - pub fn is_hatching(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isHatching", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether the egg will hatch or not. - pub fn set_hatching(&self, hatching: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(hatching.into()); + /// Sets the new result of the login, as an enum + pub fn set_result( + &self, + result: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/event/player/PlayerLoginEvent/Result;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(result.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setHatching", + "setResult", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the type of the mob being hatched (EntityType.CHICKEN by default) - pub fn hatching_type( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + /// Gets the current kick message that will be used if getResult() != + /// Result.ALLOWED + pub fn kick_message(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getHatchingType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getKickMessage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Change the type of mob being hatched by the egg - pub fn set_hatching_type( + /// Sets the kick message to display if getResult() != Result.ALLOWED + pub fn set_kick_message( &self, - hatch_type: impl Into>, + message: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/EntityType;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(hatch_type.into().jni_object().clone()) - }); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(message.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setHatchingType", + "setKickMessage", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the number of mob hatches from the egg. By default the number will - /// be the number the server would've done - ///
    - ///
  • 7/8 chance of being 0 - ///
  • 31/256 ~= 1/8 chance to be 1 - ///
  • 1/256 chance to be 4 - ///
- pub fn num_hatches(&self) -> Result> { - let sig = String::from("()B"); + /// Gets the hostname that the player used to connect to the server, or + /// blank if unknown + pub fn hostname(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getNumHatches", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getHostname", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Change the number of mobs coming out of the hatched egg - /// - /// The boolean hatching will override this number. Ie. If hatching = - /// false, this number will not matter - pub fn set_num_hatches(&self, num_hatches: i8) -> Result<(), Box> { - let sig = String::from("(B)V"); - let val_1 = jni::objects::JValueGen::Byte(num_hatches); + /// Allows the player to log in + pub fn allow(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "allow", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Disallows the player from logging in, with the given reason + pub fn disallow( + &self, + result: impl Into>, + message: impl Into, + ) -> Result<(), Box> { + let sig = + String::from("(Lorg/bukkit/event/player/PlayerLoginEvent/Result;Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(result.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(message.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setNumHatches", + "disallow", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } + /// Gets the {@link InetAddress} for the Player associated with this event. + /// This method is provided as a workaround for player.getAddress() + /// returning null during PlayerLoginEvent. + pub fn address(&self) -> Result, Box> { + let sig = String::from("()Ljava/net/InetAddress;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAddress", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) + } + /// Gets the connection address of this player, regardless of whether it has + /// been spoofed or not. + pub fn real_address(&self) -> Result, Box> { + let sig = String::from("()Ljava/net/InetAddress;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRealAddress", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) + } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -5192,14 +5298,14 @@ impl<'mc> PlayerEggThrowEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerEggThrowEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerLoginEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getEgg', 'isHatching', 'setHatching', 'getHatchingType', 'setHatchingType', 'getNumHatches', 'setNumHatches', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getResult', 'setResult', 'getKickMessage', 'setKickMessage', 'getHostname', 'allow', 'disallow', 'getAddress', 'getRealAddress', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -5214,19 +5320,178 @@ impl<'mc> PlayerEggThrowEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerEggThrowEvent<'mc> { +impl<'mc> Into> for PlayerLoginEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerEggThrowEvent into crate::event::player::PlayerEvent") + .expect("Error converting PlayerLoginEvent into crate::event::player::PlayerEvent") } } -#[repr(C)] -pub struct PlayerInteractAtEntityEvent<'mc>( +pub enum PlayerLoginEventResult<'mc> { + Allowed { + inner: PlayerLoginEventResultStruct<'mc>, + }, + KickFull { + inner: PlayerLoginEventResultStruct<'mc>, + }, + KickBanned { + inner: PlayerLoginEventResultStruct<'mc>, + }, + KickWhitelist { + inner: PlayerLoginEventResultStruct<'mc>, + }, + KickOther { + inner: PlayerLoginEventResultStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for PlayerLoginEventResult<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PlayerLoginEventResult::Allowed { .. } => f.write_str("ALLOWED"), + PlayerLoginEventResult::KickFull { .. } => f.write_str("KICK_FULL"), + PlayerLoginEventResult::KickBanned { .. } => f.write_str("KICK_BANNED"), + PlayerLoginEventResult::KickWhitelist { .. } => f.write_str("KICK_WHITELIST"), + PlayerLoginEventResult::KickOther { .. } => f.write_str("KICK_OTHER"), + } + } +} +impl<'mc> std::ops::Deref for PlayerLoginEventResult<'mc> { + type Target = PlayerLoginEventResultStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + PlayerLoginEventResult::Allowed { inner } => inner, + PlayerLoginEventResult::KickFull { inner } => inner, + PlayerLoginEventResult::KickBanned { inner } => inner, + PlayerLoginEventResult::KickWhitelist { inner } => inner, + PlayerLoginEventResult::KickOther { inner } => inner, + } + } +} + +impl<'mc> PlayerLoginEventResult<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/event/player/PlayerLoginEvent/Result"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/event/player/PlayerLoginEvent/Result;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "ALLOWED" => Ok(PlayerLoginEventResult::Allowed { + inner: PlayerLoginEventResultStruct::from_raw(env, obj)?, + }), + "KICK_FULL" => Ok(PlayerLoginEventResult::KickFull { + inner: PlayerLoginEventResultStruct::from_raw(env, obj)?, + }), + "KICK_BANNED" => Ok(PlayerLoginEventResult::KickBanned { + inner: PlayerLoginEventResultStruct::from_raw(env, obj)?, + }), + "KICK_WHITELIST" => Ok(PlayerLoginEventResult::KickWhitelist { + inner: PlayerLoginEventResultStruct::from_raw(env, obj)?, + }), + "KICK_OTHER" => Ok(PlayerLoginEventResult::KickOther { + inner: PlayerLoginEventResultStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct PlayerLoginEventResultStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerInteractAtEntityEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerLoginEventResult<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Allowed { inner } => inner.0.clone(), + Self::KickFull { inner } => inner.0.clone(), + Self::KickBanned { inner } => inner.0.clone(), + Self::KickWhitelist { inner } => inner.0.clone(), + Self::KickOther { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Allowed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::KickFull { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::KickBanned { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::KickWhitelist { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::KickOther { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for PlayerLoginEventResult<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate PlayerLoginEventResult from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/player/PlayerLoginEvent/Result")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PlayerLoginEventResult object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "ALLOWED" => Ok(PlayerLoginEventResult::Allowed { + inner: PlayerLoginEventResultStruct::from_raw(env, obj)?, + }), + "KICK_FULL" => Ok(PlayerLoginEventResult::KickFull { + inner: PlayerLoginEventResultStruct::from_raw(env, obj)?, + }), + "KICK_BANNED" => Ok(PlayerLoginEventResult::KickBanned { + inner: PlayerLoginEventResultStruct::from_raw(env, obj)?, + }), + "KICK_WHITELIST" => Ok(PlayerLoginEventResult::KickWhitelist { + inner: PlayerLoginEventResultStruct::from_raw(env, obj)?, + }), + "KICK_OTHER" => Ok(PlayerLoginEventResult::KickOther { + inner: PlayerLoginEventResultStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for PlayerLoginEventResultStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -5234,22 +5499,22 @@ impl<'mc> JNIRaw<'mc> for PlayerInteractAtEntityEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerInteractAtEntityEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerLoginEventResultStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate PlayerInteractAtEntityEvent from null object." + "Tried to instantiate PlayerLoginEventResultStruct from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerInteractAtEntityEvent")?; + env.validate_name(&obj, "org/bukkit/event/player/PlayerLoginEvent/Result")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerInteractAtEntityEvent object, got {}", + "Invalid argument passed. Expected a PlayerLoginEventResultStruct object, got {}", name ) .into()) @@ -5259,15 +5524,69 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerInteractAtEntityEvent<'mc> { } } -impl<'mc> PlayerInteractAtEntityEvent<'mc> { +impl<'mc> PlayerLoginEventResultStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/player/PlayerLoginEvent/Result;"); + let cls = jni.find_class("org/bukkit/event/player/PlayerLoginEvent/Result"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::player::PlayerLoginEventResult::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct PlayerRiptideEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PlayerRiptideEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PlayerRiptideEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate PlayerRiptideEvent from null object.").into(), + ); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/player/PlayerRiptideEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PlayerRiptideEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> PlayerRiptideEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, who: impl Into>, - clicked_entity: impl Into>, - position: impl Into>, - hand: std::option::Option>>, - ) -> Result, Box> - { + item: impl Into>, + velocity: std::option::Option>>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "Lorg/bukkit/entity/Player;"; @@ -5275,39 +5594,42 @@ impl<'mc> PlayerInteractAtEntityEvent<'mc> { jni::objects::JObject::from_raw(who.into().jni_object().clone()) }); args.push(val_1); - sig += "Lorg/bukkit/entity/Entity;"; + sig += "Lorg/bukkit/inventory/ItemStack;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(clicked_entity.into().jni_object().clone()) + jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); args.push(val_2); - sig += "Lorg/bukkit/util/Vector;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(position.into().jni_object().clone()) - }); - args.push(val_3); - if let Some(a) = hand { - sig += "Lorg/bukkit/inventory/EquipmentSlot;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { + if let Some(a) = velocity { + sig += "Lorg/bukkit/util/Vector;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); - args.push(val_4); + args.push(val_3); } sig += ")V"; - let cls = jni.find_class("org/bukkit/event/player/PlayerInteractAtEntityEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerRiptideEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerInteractAtEntityEvent::from_raw(&jni, res) + crate::event::player::PlayerRiptideEvent::from_raw(&jni, res) } - - pub fn clicked_position(&self) -> Result, Box> { + /// Gets the item containing the used enchantment. + pub fn item(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the velocity applied to the player as a result of this riptide. + pub fn velocity(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getClickedPosition", - sig.as_str(), - vec![], - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVelocity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) @@ -5329,49 +5651,21 @@ impl<'mc> PlayerInteractAtEntityEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerInteractAtEntityEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerRiptideEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerInteractEntityEvent ( ['getClickedPosition', 'getHandlers', 'getHandlerList']) - - pub fn is_cancelled(&self) -> Result> { - let temp_clone = - crate::event::player::PlayerInteractEntityEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerInteractEntityEvent = temp_clone.into(); - real.is_cancelled() - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let temp_clone = - crate::event::player::PlayerInteractEntityEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerInteractEntityEvent = temp_clone.into(); - real.set_cancelled(cancel) - } - /// Gets the entity that was right-clicked by the player. - pub fn right_clicked(&self) -> Result, Box> { - let temp_clone = - crate::event::player::PlayerInteractEntityEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerInteractEntityEvent = temp_clone.into(); - real.right_clicked() - } - /// The hand used to perform this interaction. - pub fn hand(&self) -> Result, Box> { - let temp_clone = - crate::event::player::PlayerInteractEntityEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerInteractEntityEvent = temp_clone.into(); - real.hand() + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getItem', 'getVelocity', 'getHandlers', 'getHandlerList']) + /// Returns the player involved in this event + pub fn player(&self) -> Result, Box> { + let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerEvent = temp_clone.into(); + real.player() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -5379,20 +5673,19 @@ impl<'mc> PlayerInteractAtEntityEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> - for PlayerInteractAtEntityEvent<'mc> -{ - fn into(self) -> crate::event::player::PlayerInteractEntityEvent<'mc> { - crate::event::player::PlayerInteractEntityEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting PlayerInteractAtEntityEvent into crate::event::player::PlayerInteractEntityEvent") - } -} +impl<'mc> Into> for PlayerRiptideEvent<'mc> { + fn into(self) -> crate::event::player::PlayerEvent<'mc> { + crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerRiptideEvent into crate::event::player::PlayerEvent") + } +} #[repr(C)] -pub struct PlayerEditBookEvent<'mc>( +pub struct PlayerChangedWorldEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerEditBookEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerChangedWorldEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -5400,21 +5693,22 @@ impl<'mc> JNIRaw<'mc> for PlayerEditBookEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerEditBookEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerChangedWorldEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate PlayerEditBookEvent from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate PlayerChangedWorldEvent from null object." + ) + .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerEditBookEvent")?; + env.validate_name(&obj, "org/bukkit/event/player/PlayerChangedWorldEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerEditBookEvent object, got {}", + "Invalid argument passed. Expected a PlayerChangedWorldEvent object, got {}", name ) .into()) @@ -5424,28 +5718,21 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerEditBookEvent<'mc> { } } -impl<'mc> PlayerEditBookEvent<'mc> { +impl<'mc> PlayerChangedWorldEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - who: impl Into>, - slot: i32, - previous_book_meta: impl Into>, - new_book_meta: impl Into>, - is_signing: bool, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Player;ILorg/bukkit/inventory/meta/BookMeta;Lorg/bukkit/inventory/meta/BookMeta;Z)V"); + player: impl Into>, + from: impl Into>, + ) -> Result, Box> + { + let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/World;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(who.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(slot); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(previous_book_meta.into().jni_object().clone()) + jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_book_meta.into().jni_object().clone()) + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(from.into().jni_object().clone()) }); - let val_5 = jni::objects::JValueGen::Bool(is_signing.into()); - let cls = jni.find_class("org/bukkit/event/player/PlayerEditBookEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerChangedWorldEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -5453,101 +5740,21 @@ impl<'mc> PlayerEditBookEvent<'mc> { vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - jni::objects::JValueGen::from(val_5), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerEditBookEvent::from_raw(&jni, res) - } - /// Gets the book meta currently on the book. - /// - /// Note: this is a copy of the book meta. You cannot use this object to - /// change the existing book meta. - pub fn previous_book_meta( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/BookMeta;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPreviousBookMeta", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::BookMeta::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the book meta that the player is attempting to add to the book. - /// - /// Note: this is a copy of the proposed new book meta. Use {@link - /// #setNewBookMeta(BookMeta)} to change what will actually be added to the - /// book. - pub fn new_book_meta( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/BookMeta;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getNewBookMeta", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::BookMeta::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - #[deprecated] - /// Gets the inventory slot number for the book item that triggered this event.This is a slot number on the player's hotbar in the range 0-8, or -1 for off hand. - pub fn slot(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSlot", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the book meta that will actually be added to the book. - pub fn set_new_book_meta( - &self, - new_book_meta: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/BookMeta;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_book_meta.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setNewBookMeta", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::event::player::PlayerChangedWorldEvent::from_raw(&jni, res) } - /// Gets whether or not the book is being signed. If a book is signed the - /// Material changes from BOOK_AND_QUILL to WRITTEN_BOOK. - pub fn is_signing(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the world the player is switching from. + pub fn from(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isSigning", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFrom", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether or not the book is being signed. If a book is signed the - /// Material changes from BOOK_AND_QUILL to WRITTEN_BOOK. - pub fn set_signing(&self, signing: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(signing.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSigning", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn handlers(&self) -> Result, Box> { @@ -5565,36 +5772,14 @@ impl<'mc> PlayerEditBookEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerEditBookEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerChangedWorldEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getPreviousBookMeta', 'getNewBookMeta', 'getSlot', 'setNewBookMeta', 'isSigning', 'setSigning', 'getHandlers', 'getHandlerList', 'isCancelled', 'setCancelled']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getFrom', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -5609,25 +5794,20 @@ impl<'mc> PlayerEditBookEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerEditBookEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerEditBookEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for PlayerEditBookEvent<'mc> { +impl<'mc> Into> for PlayerChangedWorldEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { - crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerEditBookEvent into crate::event::player::PlayerEvent") + crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting PlayerChangedWorldEvent into crate::event::player::PlayerEvent", + ) } } #[repr(C)] -pub struct PlayerChatEvent<'mc>( +pub struct PlayerRespawnEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerChatEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerRespawnEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -5635,20 +5815,21 @@ impl<'mc> JNIRaw<'mc> for PlayerChatEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerChatEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerRespawnEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate PlayerChatEvent from null object.").into(), + eyre::eyre!("Tried to instantiate PlayerRespawnEvent from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/player/PlayerChatEvent")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/player/PlayerRespawnEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerChatEvent object, got {}", + "Invalid argument passed. Expected a PlayerRespawnEvent object, got {}", name ) .into()) @@ -5658,157 +5839,117 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerChatEvent<'mc> { } } -impl<'mc> PlayerChatEvent<'mc> { +impl<'mc> PlayerRespawnEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - player: impl Into>, - message: impl Into, - format: std::option::Option>, - recipients: std::option::Option>>, - ) -> Result, Box> { + respawn_player: impl Into>, + respawn_location: impl Into>, + is_bed_spawn: bool, + is_anchor_spawn: std::option::Option, + respawn_reason: std::option::Option< + impl Into>, + >, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "Lorg/bukkit/entity/Player;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) + jni::objects::JObject::from_raw(respawn_player.into().jni_object().clone()) }); args.push(val_1); - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(message.into())?, - )); + sig += "Lorg/bukkit/Location;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(respawn_location.into().jni_object().clone()) + }); args.push(val_2); - if let Some(a) = format { - sig += "Ljava/lang/String;"; - let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(a.into())?, - )); - args.push(val_3); + sig += "Z"; + let val_3 = jni::objects::JValueGen::Bool(is_bed_spawn.into()); + args.push(val_3); + if let Some(a) = is_anchor_spawn { + sig += "Z"; + let val_4 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_4); } - if let Some(a) = recipients { - sig += "Ljava/util/Set;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { + if let Some(a) = respawn_reason { + sig += "Lorg/bukkit/event/player/PlayerRespawnEvent/RespawnReason;"; + let val_5 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); - args.push(val_4); + args.push(val_5); } sig += ")V"; - let cls = jni.find_class("org/bukkit/event/player/PlayerChatEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerRespawnEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerChatEvent::from_raw(&jni, res) + crate::event::player::PlayerRespawnEvent::from_raw(&jni, res) } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + /// Gets the current respawn location + pub fn respawn_location(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setCancelled", + "getRespawnLocation", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the message that the player is attempting to send - pub fn message(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMessage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Sets the message that the player will send - pub fn set_message( - &self, - message: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(message.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMessage", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the player that this message will display as, or command will be - /// executed as - pub fn set_player( + /// Sets the new respawn location + pub fn set_respawn_location( &self, - player: impl Into>, + respawn_location: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Player;)V"); + let sig = String::from("(Lorg/bukkit/Location;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) + jni::objects::JObject::from_raw(respawn_location.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPlayer", + "setRespawnLocation", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the format to use to display this chat message - pub fn format(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFormat", sig.as_str(), vec![]); + /// Gets whether the respawn location is the player's bed. + pub fn is_bed_spawn(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isBedSpawn", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - /// Sets the format to use to display this chat message - pub fn set_format(&self, format: impl Into) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(format.into())?, - )); + /// Gets whether the respawn location is the player's respawn anchor. + pub fn is_anchor_spawn(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isAnchorSpawn", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the reason this respawn event was called. + pub fn respawn_reason( + &self, + ) -> Result< + crate::event::player::PlayerRespawnEventRespawnReason<'mc>, + Box, + > { + let sig = String::from("()Lorg/bukkit/event/player/PlayerRespawnEvent/RespawnReason;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setFormat", + "getRespawnReason", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets a set of recipients that this chat message will be displayed to - pub fn recipients( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRecipients", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + crate::event::player::PlayerRespawnEventRespawnReason::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -5828,14 +5969,14 @@ impl<'mc> PlayerChatEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerChatEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerRespawnEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['isCancelled', 'setCancelled', 'getMessage', 'setMessage', 'setPlayer', 'getFormat', 'setFormat', 'getRecipients', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getRespawnLocation', 'setRespawnLocation', 'isBedSpawn', 'isAnchorSpawn', 'getRespawnReason', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -5850,25 +5991,150 @@ impl<'mc> PlayerChatEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerChatEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerChatEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for PlayerChatEvent<'mc> { +impl<'mc> Into> for PlayerRespawnEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerChatEvent into crate::event::player::PlayerEvent") + .expect("Error converting PlayerRespawnEvent into crate::event::player::PlayerEvent") + } +} +pub enum PlayerRespawnEventRespawnReason<'mc> { + Death { + inner: PlayerRespawnEventRespawnReasonStruct<'mc>, + }, + EndPortal { + inner: PlayerRespawnEventRespawnReasonStruct<'mc>, + }, + Plugin { + inner: PlayerRespawnEventRespawnReasonStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for PlayerRespawnEventRespawnReason<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PlayerRespawnEventRespawnReason::Death { .. } => f.write_str("DEATH"), + PlayerRespawnEventRespawnReason::EndPortal { .. } => f.write_str("END_PORTAL"), + PlayerRespawnEventRespawnReason::Plugin { .. } => f.write_str("PLUGIN"), + } + } +} +impl<'mc> std::ops::Deref for PlayerRespawnEventRespawnReason<'mc> { + type Target = PlayerRespawnEventRespawnReasonStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + PlayerRespawnEventRespawnReason::Death { inner } => inner, + PlayerRespawnEventRespawnReason::EndPortal { inner } => inner, + PlayerRespawnEventRespawnReason::Plugin { inner } => inner, + } + } +} + +impl<'mc> PlayerRespawnEventRespawnReason<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/event/player/PlayerRespawnEvent/RespawnReason"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/event/player/PlayerRespawnEvent/RespawnReason;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "DEATH" => Ok(PlayerRespawnEventRespawnReason::Death { + inner: PlayerRespawnEventRespawnReasonStruct::from_raw(env, obj)?, + }), + "END_PORTAL" => Ok(PlayerRespawnEventRespawnReason::EndPortal { + inner: PlayerRespawnEventRespawnReasonStruct::from_raw(env, obj)?, + }), + "PLUGIN" => Ok(PlayerRespawnEventRespawnReason::Plugin { + inner: PlayerRespawnEventRespawnReasonStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } + #[repr(C)] -pub struct PlayerRecipeDiscoverEvent<'mc>( +pub struct PlayerRespawnEventRespawnReasonStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerRecipeDiscoverEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerRespawnEventRespawnReason<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Death { inner } => inner.0.clone(), + Self::EndPortal { inner } => inner.0.clone(), + Self::Plugin { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Death { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::EndPortal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Plugin { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for PlayerRespawnEventRespawnReason<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate PlayerRespawnEventRespawnReason from null object." + ) + .into()); + } + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/event/player/PlayerRespawnEvent/RespawnReason", + )?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PlayerRespawnEventRespawnReason object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "DEATH" => Ok(PlayerRespawnEventRespawnReason::Death { + inner: PlayerRespawnEventRespawnReasonStruct::from_raw(env, obj)?, + }), + "END_PORTAL" => Ok(PlayerRespawnEventRespawnReason::EndPortal { + inner: PlayerRespawnEventRespawnReasonStruct::from_raw(env, obj)?, + }), + "PLUGIN" => Ok(PlayerRespawnEventRespawnReason::Plugin { + inner: PlayerRespawnEventRespawnReasonStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for PlayerRespawnEventRespawnReasonStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -5876,85 +6142,221 @@ impl<'mc> JNIRaw<'mc> for PlayerRecipeDiscoverEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerRecipeDiscoverEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerRespawnEventRespawnReasonStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate PlayerRecipeDiscoverEvent from null object." + "Tried to instantiate PlayerRespawnEventRespawnReasonStruct from null object." ) .into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerRecipeDiscoverEvent")?; + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/event/player/PlayerRespawnEvent/RespawnReason", + )?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerRecipeDiscoverEvent object, got {}", - name - ) - .into()) + "Invalid argument passed. Expected a PlayerRespawnEventRespawnReasonStruct object, got {}", + name + ) + .into()) } else { Ok(Self(env.clone(), obj)) } } } -impl<'mc> PlayerRecipeDiscoverEvent<'mc> { - pub fn new( +impl<'mc> PlayerRespawnEventRespawnReasonStruct<'mc> { + pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - who: impl Into>, - recipe: impl Into>, - ) -> Result, Box> - { - let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/NamespacedKey;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(who.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/event/player/PlayerRecipeDiscoverEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), + ) -> Result< + crate::event::player::PlayerRespawnEventRespawnReason<'mc>, + Box, + > { + let sig = String::from("()Lorg/bukkit/event/player/PlayerRespawnEvent/RespawnReason;"); + let cls = jni.find_class("org/bukkit/event/player/PlayerRespawnEvent/RespawnReason"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::player::PlayerRespawnEventRespawnReason::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct PlayerEggThrowEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PlayerEggThrowEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PlayerEggThrowEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate PlayerEggThrowEvent from null object.").into(), + ); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/player/PlayerEggThrowEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PlayerEggThrowEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> PlayerEggThrowEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + player: impl Into>, + egg: impl Into>, + hatching: bool, + num_hatches: i8, + hatching_type: impl Into>, + ) -> Result, Box> { + let sig = String::from( + "(Lorg/bukkit/entity/Player;Lorg/bukkit/entity/Egg;ZBLorg/bukkit/entity/EntityType;)V", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(player.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(egg.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Bool(hatching.into()); + let val_4 = jni::objects::JValueGen::Byte(num_hatches); + let val_5 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(hatching_type.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/player/PlayerEggThrowEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + jni::objects::JValueGen::from(val_5), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerRecipeDiscoverEvent::from_raw(&jni, res) + crate::event::player::PlayerEggThrowEvent::from_raw(&jni, res) } - /// Get the namespaced key of the discovered recipe. - pub fn recipe(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + /// Gets the egg involved in this event. + pub fn egg(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Egg;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getRecipe", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEgg", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + crate::entity::Egg::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn is_cancelled(&self) -> Result> { + /// Gets whether the egg is hatching or not. Will be what the server + /// would've done without interaction. + pub fn is_hatching(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isHatching", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + /// Sets whether the egg will hatch or not. + pub fn set_hatching(&self, hatching: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let val_1 = jni::objects::JValueGen::Bool(hatching.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCancelled", + "setHatching", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the type of the mob being hatched (EntityType.CHICKEN by default) + pub fn hatching_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHatchingType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Change the type of mob being hatched by the egg + pub fn set_hatching_type( + &self, + hatch_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/EntityType;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(hatch_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setHatchingType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the number of mob hatches from the egg. By default the number will + /// be the number the server would've done + ///
    + ///
  • 7/8 chance of being 0 + ///
  • 31/256 ~= 1/8 chance to be 1 + ///
  • 1/256 chance to be 4 + ///
+ pub fn num_hatches(&self) -> Result> { + let sig = String::from("()B"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getNumHatches", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.b()?) + } + /// Change the number of mobs coming out of the hatched egg + /// + /// The boolean hatching will override this number. Ie. If hatching = + /// false, this number will not matter + pub fn set_num_hatches(&self, num_hatches: i8) -> Result<(), Box> { + let sig = String::from("(B)V"); + let val_1 = jni::objects::JValueGen::Byte(num_hatches); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setNumHatches", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -5977,14 +6379,14 @@ impl<'mc> PlayerRecipeDiscoverEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerRecipeDiscoverEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerEggThrowEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getRecipe', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getEgg', 'isHatching', 'setHatching', 'getHatchingType', 'setHatchingType', 'getNumHatches', 'setNumHatches', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -5999,26 +6401,19 @@ impl<'mc> PlayerRecipeDiscoverEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerRecipeDiscoverEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerRecipeDiscoverEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for PlayerRecipeDiscoverEvent<'mc> { +impl<'mc> Into> for PlayerEggThrowEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { - crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting PlayerRecipeDiscoverEvent into crate::event::player::PlayerEvent", - ) + crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerEggThrowEvent into crate::event::player::PlayerEvent") } } #[repr(C)] -pub struct PlayerJoinEvent<'mc>( +pub struct PlayerLinksSendEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerJoinEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerLinksSendEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6026,20 +6421,21 @@ impl<'mc> JNIRaw<'mc> for PlayerJoinEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerJoinEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerLinksSendEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate PlayerJoinEvent from null object.").into(), + eyre::eyre!("Tried to instantiate PlayerLinksSendEvent from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/player/PlayerJoinEvent")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/player/PlayerLinksSendEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerJoinEvent object, got {}", + "Invalid argument passed. Expected a PlayerLinksSendEvent object, got {}", name ) .into()) @@ -6049,20 +6445,20 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerJoinEvent<'mc> { } } -impl<'mc> PlayerJoinEvent<'mc> { +impl<'mc> PlayerLinksSendEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - player_joined: impl Into>, - join_message: impl Into, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Player;Ljava/lang/String;)V"); + player: impl Into>, + links: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/ServerLinks;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player_joined.into().jni_object().clone()) + jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(join_message.into())?, - )); - let cls = jni.find_class("org/bukkit/event/player/PlayerJoinEvent"); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(links.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/player/PlayerLinksSendEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -6073,42 +6469,18 @@ impl<'mc> PlayerJoinEvent<'mc> { ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerJoinEvent::from_raw(&jni, res) + crate::event::player::PlayerLinksSendEvent::from_raw(&jni, res) } - /// Gets the join message to send to all online players - pub fn join_message(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getJoinMessage", sig.as_str(), vec![]); + /// Gets the links to be sent, for modification. + pub fn links(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/ServerLinks;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLinks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// Sets the join message to send to all online players - pub fn set_join_message( - &self, - join_message: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(join_message.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setJoinMessage", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::ServerLinks::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn handlers(&self) -> Result, Box> { @@ -6126,14 +6498,14 @@ impl<'mc> PlayerJoinEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerJoinEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerLinksSendEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getJoinMessage', 'setJoinMessage', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getLinks', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -6148,19 +6520,19 @@ impl<'mc> PlayerJoinEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerJoinEvent<'mc> { +impl<'mc> Into> for PlayerLinksSendEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerJoinEvent into crate::event::player::PlayerEvent") + .expect("Error converting PlayerLinksSendEvent into crate::event::player::PlayerEvent") } } #[repr(C)] -pub struct PlayerTakeLecternBookEvent<'mc>( +pub struct PlayerExpCooldownChangeEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerTakeLecternBookEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerExpCooldownChangeEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6168,22 +6540,22 @@ impl<'mc> JNIRaw<'mc> for PlayerTakeLecternBookEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerTakeLecternBookEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerExpCooldownChangeEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate PlayerTakeLecternBookEvent from null object." + "Tried to instantiate PlayerExpCooldownChangeEvent from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerTakeLecternBookEvent")?; + env.validate_name(&obj, "org/bukkit/event/player/PlayerExpCooldownChangeEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerTakeLecternBookEvent object, got {}", + "Invalid argument passed. Expected a PlayerExpCooldownChangeEvent object, got {}", name ) .into()) @@ -6193,21 +6565,23 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerTakeLecternBookEvent<'mc> { } } -impl<'mc> PlayerTakeLecternBookEvent<'mc> { +impl<'mc> PlayerExpCooldownChangeEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - who: impl Into>, - lectern: impl Into>, - ) -> Result, Box> + player: impl Into>, + newcooldown: i32, + reason: impl Into>, + ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/block/Lectern;)V"); + let sig = String::from("(Lorg/bukkit/entity/Player;ILorg/bukkit/event/player/PlayerExpCooldownChangeEvent/ChangeReason;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(who.into().jni_object().clone()) + jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(lectern.into().jni_object().clone()) + let val_2 = jni::objects::JValueGen::Int(newcooldown); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(reason.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/player/PlayerTakeLecternBookEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerExpCooldownChangeEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -6215,55 +6589,46 @@ impl<'mc> PlayerTakeLecternBookEvent<'mc> { vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerTakeLecternBookEvent::from_raw(&jni, res) - } - /// Gets the lectern involved. - pub fn lectern(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/Lectern;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLectern", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::Lectern::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + crate::event::player::PlayerExpCooldownChangeEvent::from_raw(&jni, res) } - /// Gets the current ItemStack on the lectern. - pub fn book( + /// Gets the reason for the change. + pub fn reason( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + ) -> Result< + crate::event::player::PlayerExpCooldownChangeEventChangeReason<'mc>, + Box, + > { + let sig = + String::from("()Lorg/bukkit/event/player/PlayerExpCooldownChangeEvent/ChangeReason;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getBook", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getReason", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( + crate::event::player::PlayerExpCooldownChangeEventChangeReason::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + ) } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the new cooldown for the player. + pub fn new_cooldown(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getNewCooldown", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + /// Sets the new cooldown for the player. + pub fn set_new_cooldown(&self, new_cooldown: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(new_cooldown); let res = self.jni_ref().call_method( &self.jni_object(), - "setCancelled", + "setNewCooldown", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -6286,14 +6651,14 @@ impl<'mc> PlayerTakeLecternBookEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerTakeLecternBookEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerExpCooldownChangeEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getLectern', 'getBook', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getReason', 'getNewCooldown', 'setNewCooldown', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -6308,126 +6673,188 @@ impl<'mc> PlayerTakeLecternBookEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerTakeLecternBookEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerTakeLecternBookEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for PlayerTakeLecternBookEvent<'mc> { +impl<'mc> Into> for PlayerExpCooldownChangeEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting PlayerTakeLecternBookEvent into crate::event::player::PlayerEvent", + "Error converting PlayerExpCooldownChangeEvent into crate::event::player::PlayerEvent", ) } } +pub enum PlayerExpCooldownChangeEventChangeReason<'mc> { + PickupOrb { + inner: PlayerExpCooldownChangeEventChangeReasonStruct<'mc>, + }, + Plugin { + inner: PlayerExpCooldownChangeEventChangeReasonStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for PlayerExpCooldownChangeEventChangeReason<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PlayerExpCooldownChangeEventChangeReason::PickupOrb { .. } => f.write_str("PICKUP_ORB"), + PlayerExpCooldownChangeEventChangeReason::Plugin { .. } => f.write_str("PLUGIN"), + } + } +} +impl<'mc> std::ops::Deref for PlayerExpCooldownChangeEventChangeReason<'mc> { + type Target = PlayerExpCooldownChangeEventChangeReasonStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + PlayerExpCooldownChangeEventChangeReason::PickupOrb { inner } => inner, + PlayerExpCooldownChangeEventChangeReason::Plugin { inner } => inner, + } + } +} + +impl<'mc> PlayerExpCooldownChangeEventChangeReason<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = + env.find_class("org/bukkit/event/player/PlayerExpCooldownChangeEvent/ChangeReason"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/event/player/PlayerExpCooldownChangeEvent/ChangeReason;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "PICKUP_ORB" => Ok(PlayerExpCooldownChangeEventChangeReason::PickupOrb { + inner: PlayerExpCooldownChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + "PLUGIN" => Ok(PlayerExpCooldownChangeEventChangeReason::Plugin { + inner: PlayerExpCooldownChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + #[repr(C)] -pub struct PlayerShowEntityEvent<'mc>( +pub struct PlayerExpCooldownChangeEventChangeReasonStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerShowEntityEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerExpCooldownChangeEventChangeReason<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + match self { + Self::PickupOrb { inner } => inner.0.clone(), + Self::Plugin { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + match self { + Self::PickupOrb { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Plugin { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerShowEntityEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerExpCooldownChangeEventChangeReason<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate PlayerShowEntityEvent from null object." + "Tried to instantiate PlayerExpCooldownChangeEventChangeReason from null object." ) .into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerShowEntityEvent")?; + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/event/player/PlayerExpCooldownChangeEvent/ChangeReason", + )?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerShowEntityEvent object, got {}", - name - ) - .into()) + "Invalid argument passed. Expected a PlayerExpCooldownChangeEventChangeReason object, got {}", + name + ) + .into()) } else { - Ok(Self(env.clone(), obj)) + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "PICKUP_ORB" => Ok(PlayerExpCooldownChangeEventChangeReason::PickupOrb { + inner: PlayerExpCooldownChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + "PLUGIN" => Ok(PlayerExpCooldownChangeEventChangeReason::Plugin { + inner: PlayerExpCooldownChangeEventChangeReasonStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } } -impl<'mc> PlayerShowEntityEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - who: impl Into>, - entity: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/entity/Entity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(who.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/event/player/PlayerShowEntityEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerShowEntityEvent::from_raw(&jni, res) +impl<'mc> JNIRaw<'mc> for PlayerExpCooldownChangeEventChangeReasonStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Gets the entity which has been shown to the player. - pub fn entity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} +impl<'mc> JNIInstantiatable<'mc> for PlayerExpCooldownChangeEventChangeReasonStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate PlayerExpCooldownChangeEventChangeReasonStruct from null object.") + .into()); + } + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/event/player/PlayerExpCooldownChangeEvent/ChangeReason", + )?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PlayerExpCooldownChangeEventChangeReasonStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } +} - pub fn handler_list( +impl<'mc> PlayerExpCooldownChangeEventChangeReasonStruct<'mc> { + pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerShowEntityEvent"); + ) -> Result< + crate::event::player::PlayerExpCooldownChangeEventChangeReason<'mc>, + Box, + > { + let sig = + String::from("()Lorg/bukkit/event/player/PlayerExpCooldownChangeEvent/ChangeReason;"); + let cls = + jni.find_class("org/bukkit/event/player/PlayerExpCooldownChangeEvent/ChangeReason"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getEntity', 'getHandlers', 'getHandlerList']) - /// Returns the player involved in this event - pub fn player(&self) -> Result, Box> { - let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerEvent = temp_clone.into(); - real.player() + crate::event::player::PlayerExpCooldownChangeEventChangeReason::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -6435,19 +6862,13 @@ impl<'mc> PlayerShowEntityEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerShowEntityEvent<'mc> { - fn into(self) -> crate::event::player::PlayerEvent<'mc> { - crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerShowEntityEvent into crate::event::player::PlayerEvent") - } -} #[repr(C)] -pub struct PlayerRegisterChannelEvent<'mc>( +pub struct PlayerInteractAtEntityEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerRegisterChannelEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerInteractAtEntityEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6455,22 +6876,22 @@ impl<'mc> JNIRaw<'mc> for PlayerRegisterChannelEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerRegisterChannelEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerInteractAtEntityEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate PlayerRegisterChannelEvent from null object." + "Tried to instantiate PlayerInteractAtEntityEvent from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerRegisterChannelEvent")?; + env.validate_name(&obj, "org/bukkit/event/player/PlayerInteractAtEntityEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerRegisterChannelEvent object, got {}", + "Invalid argument passed. Expected a PlayerInteractAtEntityEvent object, got {}", name ) .into()) @@ -6480,41 +6901,59 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerRegisterChannelEvent<'mc> { } } -impl<'mc> PlayerRegisterChannelEvent<'mc> { +impl<'mc> PlayerInteractAtEntityEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - player: impl Into>, - channel: impl Into, - ) -> Result, Box> + who: impl Into>, + clicked_entity: impl Into>, + position: impl Into>, + hand: std::option::Option>>, + ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Player;Ljava/lang/String;)V"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Player;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) + jni::objects::JObject::from_raw(who.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(channel.into())?, - )); - let cls = jni.find_class("org/bukkit/event/player/PlayerRegisterChannelEvent"); + args.push(val_1); + sig += "Lorg/bukkit/entity/Entity;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(clicked_entity.into().jni_object().clone()) + }); + args.push(val_2); + sig += "Lorg/bukkit/util/Vector;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(position.into().jni_object().clone()) + }); + args.push(val_3); + if let Some(a) = hand { + sig += "Lorg/bukkit/inventory/EquipmentSlot;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_4); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/player/PlayerInteractAtEntityEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerRegisterChannelEvent::from_raw(&jni, res) + crate::event::player::PlayerInteractAtEntityEvent::from_raw(&jni, res) } - // SUPER CLASS: org.bukkit.event.player.PlayerChannelEvent ( []) - pub fn channel(&self) -> Result> { - let temp_clone = crate::event::player::PlayerChannelEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerChannelEvent = temp_clone.into(); - real.channel() + pub fn clicked_position(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getClickedPosition", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn handlers(&self) -> Result, Box> { @@ -6531,7 +6970,50 @@ impl<'mc> PlayerRegisterChannelEvent<'mc> { pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { - crate::event::player::PlayerChannelEvent::handler_list(jni) + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/player/PlayerInteractAtEntityEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.player.PlayerInteractEntityEvent ( ['getClickedPosition', 'getHandlers', 'getHandlerList']) + + pub fn is_cancelled(&self) -> Result> { + let temp_clone = + crate::event::player::PlayerInteractEntityEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerInteractEntityEvent = temp_clone.into(); + real.is_cancelled() + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let temp_clone = + crate::event::player::PlayerInteractEntityEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerInteractEntityEvent = temp_clone.into(); + real.set_cancelled(cancel) + } + /// Gets the entity that was right-clicked by the player. + pub fn right_clicked(&self) -> Result, Box> { + let temp_clone = + crate::event::player::PlayerInteractEntityEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerInteractEntityEvent = temp_clone.into(); + real.right_clicked() + } + /// The hand used to perform this interaction. + pub fn hand(&self) -> Result, Box> { + let temp_clone = + crate::event::player::PlayerInteractEntityEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerInteractEntityEvent = temp_clone.into(); + real.hand() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -6539,18 +7021,20 @@ impl<'mc> PlayerRegisterChannelEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerRegisterChannelEvent<'mc> { - fn into(self) -> crate::event::player::PlayerChannelEvent<'mc> { - crate::event::player::PlayerChannelEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting PlayerRegisterChannelEvent into crate::event::player::PlayerChannelEvent") +impl<'mc> Into> + for PlayerInteractAtEntityEvent<'mc> +{ + fn into(self) -> crate::event::player::PlayerInteractEntityEvent<'mc> { + crate::event::player::PlayerInteractEntityEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting PlayerInteractAtEntityEvent into crate::event::player::PlayerInteractEntityEvent") } } #[repr(C)] -pub struct PlayerBedEnterEvent<'mc>( +pub struct PlayerEditBookEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerBedEnterEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerEditBookEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6558,21 +7042,21 @@ impl<'mc> JNIRaw<'mc> for PlayerBedEnterEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerBedEnterEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerEditBookEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate PlayerBedEnterEvent from null object.").into(), + eyre::eyre!("Tried to instantiate PlayerEditBookEvent from null object.").into(), ); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerBedEnterEvent")?; + env.validate_name(&obj, "org/bukkit/event/player/PlayerEditBookEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerBedEnterEvent object, got {}", + "Invalid argument passed. Expected a PlayerEditBookEvent object, got {}", name ) .into()) @@ -6582,145 +7066,131 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerBedEnterEvent<'mc> { } } -impl<'mc> PlayerBedEnterEvent<'mc> { +impl<'mc> PlayerEditBookEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, who: impl Into>, - bed: impl Into>, - bed_enter_result: std::option::Option< - impl Into>, - >, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Player;"; + slot: i32, + previous_book_meta: impl Into>, + new_book_meta: impl Into>, + is_signing: bool, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/Player;ILorg/bukkit/inventory/meta/BookMeta;Lorg/bukkit/inventory/meta/BookMeta;Z)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(who.into().jni_object().clone()) }); - args.push(val_1); - sig += "Lorg/bukkit/block/Block;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(bed.into().jni_object().clone()) + let val_2 = jni::objects::JValueGen::Int(slot); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(previous_book_meta.into().jni_object().clone()) }); - args.push(val_2); - if let Some(a) = bed_enter_result { - sig += "Lorg/bukkit/event/player/PlayerBedEnterEvent/BedEnterResult;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_3); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/event/player/PlayerBedEnterEvent"); + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(new_book_meta.into().jni_object().clone()) + }); + let val_5 = jni::objects::JValueGen::Bool(is_signing.into()); + let cls = jni.find_class("org/bukkit/event/player/PlayerEditBookEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + jni::objects::JValueGen::from(val_5), + ], + ); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerBedEnterEvent::from_raw(&jni, res) + crate::event::player::PlayerEditBookEvent::from_raw(&jni, res) } - /// This describes the default outcome of this event. - pub fn bed_enter_result( + /// Gets the book meta currently on the book. + /// + /// Note: this is a copy of the book meta. You cannot use this object to + /// change the existing book meta. + pub fn previous_book_meta( &self, - ) -> Result< - crate::event::player::PlayerBedEnterEventBedEnterResult<'mc>, - Box, - > { - let sig = String::from("()Lorg/bukkit/event/player/PlayerBedEnterEvent/BedEnterResult;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/BookMeta;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getBedEnterResult", + "getPreviousBookMeta", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::event::player::PlayerBedEnterEventBedEnterResult::from_raw(&self.jni_ref(), unsafe { + crate::inventory::meta::BookMeta::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// This controls the action to take with the bed that was clicked on. + /// Gets the book meta that the player is attempting to add to the book. /// - /// In case of {@link org.bukkit.event.Event.Result#DEFAULT}, the default outcome is described by - /// {@link #getBedEnterResult()}. - pub fn use_bed(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/Event/Result;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "useBed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::EventResult::from_raw(&self.jni_ref(), unsafe { + /// Note: this is a copy of the proposed new book meta. Use {@link + /// #setNewBookMeta(BookMeta)} to change what will actually be added to the + /// book. + pub fn new_book_meta( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/BookMeta;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getNewBookMeta", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::BookMeta::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the action to take with the interacted bed. - /// - /// {@link org.bukkit.event.Event.Result#ALLOW} will result in the player sleeping, regardless of - /// the default outcome described by {@link #getBedEnterResult()}. - /// - /// {@link org.bukkit.event.Event.Result#DENY} will prevent the player from sleeping. This has the - /// same effect as canceling the event via {@link #setCancelled(boolean)}. - /// - /// {@link org.bukkit.event.Event.Result#DEFAULT} will result in the outcome described by - /// {@link #getBedEnterResult()}. - pub fn set_use_bed( + #[deprecated] + /// Gets the inventory slot number for the book item that triggered this event.This is a slot number on the player's hotbar in the range 0-8, or -1 for off hand. + pub fn slot(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSlot", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the book meta that will actually be added to the book. + pub fn set_new_book_meta( &self, - use_bed: impl Into>, + new_book_meta: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/Event/Result;)V"); + let sig = String::from("(Lorg/bukkit/inventory/meta/BookMeta;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(use_bed.into().jni_object().clone()) + jni::objects::JObject::from_raw(new_book_meta.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setUseBed", + "setNewBookMeta", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the cancellation state of this event. Set to true if you want to - /// prevent the player from sleeping. - /// - /// Canceling the event has the same effect as setting {@link #useBed()} to - /// {@link org.bukkit.event.Event.Result#DENY}. - /// - /// For backwards compatibility reasons this also returns true if - /// {@link #useBed()} is {@link org.bukkit.event.Event.Result#DEFAULT} and the - /// {@link #getBedEnterResult() default action} is to prevent bed entering. - pub fn is_cancelled(&self) -> Result> { + /// Gets whether or not the book is being signed. If a book is signed the + /// Material changes from BOOK_AND_QUILL to WRITTEN_BOOK. + pub fn is_signing(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSigning", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the cancellation state of this event. A canceled event will not be - /// executed in the server, but will still pass to other plugins. - /// - /// Canceling this event will prevent use of the bed. - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + /// Sets whether or not the book is being signed. If a book is signed the + /// Material changes from BOOK_AND_QUILL to WRITTEN_BOOK. + pub fn set_signing(&self, signing: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let val_1 = jni::objects::JValueGen::Bool(signing.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCancelled", + "setSigning", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the bed block involved in this event. - pub fn bed(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -6737,14 +7207,36 @@ impl<'mc> PlayerBedEnterEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerBedEnterEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerEditBookEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getBedEnterResult', 'useBed', 'setUseBed', 'isCancelled', 'setCancelled', 'getBed', 'getHandlers', 'getHandlerList']) + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getPreviousBookMeta', 'getNewBookMeta', 'getSlot', 'setNewBookMeta', 'isSigning', 'setSigning', 'getHandlers', 'getHandlerList', 'isCancelled', 'setCancelled']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -6759,103 +7251,25 @@ impl<'mc> PlayerBedEnterEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerBedEnterEvent<'mc> { +impl<'mc> Into> for PlayerEditBookEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerBedEnterEvent into crate::event::Cancellable") + .expect("Error converting PlayerEditBookEvent into crate::event::Cancellable") } } -impl<'mc> Into> for PlayerBedEnterEvent<'mc> { +impl<'mc> Into> for PlayerEditBookEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerBedEnterEvent into crate::event::player::PlayerEvent") - } -} -pub enum PlayerBedEnterEventBedEnterResult<'mc> {} -impl<'mc> std::fmt::Display for PlayerBedEnterEventBedEnterResult<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> PlayerBedEnterEventBedEnterResult<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/event/player/PlayerBedEnterEvent/BedEnterResult"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/event/player/PlayerBedEnterEvent/BedEnterResult;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + .expect("Error converting PlayerEditBookEvent into crate::event::player::PlayerEvent") } } - #[repr(C)] -pub struct PlayerBedEnterEventBedEnterResultStruct<'mc>( +pub struct PlayerChatEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerBedEnterEventBedEnterResult<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for PlayerBedEnterEventBedEnterResult<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PlayerBedEnterEventBedEnterResult from null object." - ) - .into()); - } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/event/player/PlayerBedEnterEvent/BedEnterResult", - )?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerBedEnterEventBedEnterResult object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for PlayerBedEnterEventBedEnterResultStruct<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerChatEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6863,204 +7277,183 @@ impl<'mc> JNIRaw<'mc> for PlayerBedEnterEventBedEnterResultStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerBedEnterEventBedEnterResultStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerChatEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PlayerBedEnterEventBedEnterResultStruct from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate PlayerChatEvent from null object.").into(), + ); } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/event/player/PlayerBedEnterEvent/BedEnterResult", - )?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/player/PlayerChatEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerBedEnterEventBedEnterResultStruct object, got {}", - name - ) - .into()) + "Invalid argument passed. Expected a PlayerChatEvent object, got {}", + name + ) + .into()) } else { Ok(Self(env.clone(), obj)) } } } -impl<'mc> PlayerBedEnterEventBedEnterResultStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result< - crate::event::player::PlayerBedEnterEventBedEnterResult<'mc>, - Box, - > { - let sig = String::from("()Lorg/bukkit/event/player/PlayerBedEnterEvent/BedEnterResult;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerBedEnterEvent/BedEnterResult"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::player::PlayerBedEnterEventBedEnterResult::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct PlayerRecipeBookClickEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PlayerRecipeBookClickEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PlayerRecipeBookClickEvent<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PlayerRecipeBookClickEvent from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerRecipeBookClickEvent")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerRecipeBookClickEvent object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> PlayerRecipeBookClickEvent<'mc> { - pub fn new( +impl<'mc> PlayerChatEvent<'mc> { + pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, player: impl Into>, - recipe: impl Into>, - shift_click: bool, - ) -> Result, Box> - { - let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/inventory/Recipe;Z)V"); + message: impl Into, + format: std::option::Option>, + recipients: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Player;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Bool(shift_click.into()); - let cls = jni.find_class("org/bukkit/event/player/PlayerRecipeBookClickEvent"); + args.push(val_1); + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(message.into())?, + )); + args.push(val_2); + if let Some(a) = format { + sig += "Ljava/lang/String;"; + let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(a.into())?, + )); + args.push(val_3); + } + if let Some(a) = recipients { + sig += "Ljava/util/Set;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_4); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/player/PlayerChatEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); + let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerRecipeBookClickEvent::from_raw(&jni, res) + crate::event::player::PlayerChatEvent::from_raw(&jni, res) } - /// Gets the original recipe the player was trying to craft. - /// - /// This will not reflect any changes made with {@link setRecipe}. - pub fn original_recipe( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Recipe;"); + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getOriginalRecipe", + "setCancelled", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::Recipe::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the recipe the player is trying to craft. - /// - /// This will reflect changes made with {@link setRecipe}. - pub fn recipe(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Recipe;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getRecipe", sig.as_str(), vec![]); + /// Gets the message that the player is attempting to send + pub fn message(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMessage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Recipe::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Set the recipe that will be used. - /// - /// The game will attempt to move the ingredients for this recipe into the - /// appropriate slots. - /// - /// If the original recipe is a {@link CraftingRecipe} the provided recipe - /// must also be a {@link CraftingRecipe}, otherwise the provided recipe must - /// be of the same type as the original recipe. - pub fn set_recipe( + /// Sets the message that the player will send + pub fn set_message( &self, - recipe: impl Into>, + message: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/Recipe;)V"); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(message.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMessage", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets the player that this message will display as, or command will be + /// executed as + pub fn set_player( + &self, + player: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/Player;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) + jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setRecipe", + "setPlayer", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// If true the game will attempt to move the ingredients for as many copies - /// of this recipe as possible into the appropriate slots, otherwise only 1 - /// copy will be moved. - pub fn is_shift_click(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isShiftClick", sig.as_str(), vec![]); + /// Gets the format to use to display this chat message + pub fn format(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFormat", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets if the game will attempt to move the ingredients for as many copies - /// of this recipe as possible into the appropriate slots. - pub fn set_shift_click(&self, shift_click: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(shift_click.into()); + /// Sets the format to use to display this chat message + pub fn set_format(&self, format: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(format.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setShiftClick", + "setFormat", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } + /// Gets a set of recipients that this chat message will be displayed to + pub fn recipients( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRecipients", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -7077,14 +7470,14 @@ impl<'mc> PlayerRecipeBookClickEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerRecipeBookClickEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerChatEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getOriginalRecipe', 'getRecipe', 'setRecipe', 'isShiftClick', 'setShiftClick', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['isCancelled', 'setCancelled', 'getMessage', 'setMessage', 'setPlayer', 'getFormat', 'setFormat', 'getRecipients', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -7099,20 +7492,25 @@ impl<'mc> PlayerRecipeBookClickEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerRecipeBookClickEvent<'mc> { +impl<'mc> Into> for PlayerChatEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerChatEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for PlayerChatEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { - crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting PlayerRecipeBookClickEvent into crate::event::player::PlayerEvent", - ) + crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerChatEvent into crate::event::player::PlayerEvent") } } #[repr(C)] -pub struct PlayerPreLoginEvent<'mc>( +pub struct PlayerRecipeDiscoverEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerPreLoginEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerRecipeDiscoverEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -7120,21 +7518,22 @@ impl<'mc> JNIRaw<'mc> for PlayerPreLoginEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerPreLoginEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerRecipeDiscoverEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate PlayerPreLoginEvent from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate PlayerRecipeDiscoverEvent from null object." + ) + .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerPreLoginEvent")?; + env.validate_name(&obj, "org/bukkit/event/player/PlayerRecipeDiscoverEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerPreLoginEvent object, got {}", + "Invalid argument passed. Expected a PlayerRecipeDiscoverEvent object, got {}", name ) .into()) @@ -7144,159 +7543,66 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerPreLoginEvent<'mc> { } } -impl<'mc> PlayerPreLoginEvent<'mc> { +impl<'mc> PlayerRecipeDiscoverEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - name: impl Into, - ip_address: jni::objects::JObject<'mc>, - unique_id: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(name.into())?, - )); - args.push(val_1); - sig += "Ljava/net/InetAddress;"; - let val_2 = jni::objects::JValueGen::Object(ip_address); - args.push(val_2); - if let Some(a) = unique_id { - sig += "Ljava/util/UUID;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_3); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/event/player/PlayerPreLoginEvent"); + who: impl Into>, + recipe: impl Into>, + ) -> Result, Box> + { + let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/NamespacedKey;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(who.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/player/PlayerRecipeDiscoverEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerPreLoginEvent::from_raw(&jni, res) + crate::event::player::PlayerRecipeDiscoverEvent::from_raw(&jni, res) } - /// Gets the current result of the login, as an enum - pub fn result( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/event/player/PlayerPreLoginEvent/Result;"); + /// Get the namespaced key of the discovered recipe. + pub fn recipe(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getResult", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getRecipe", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::event::player::PlayerPreLoginEventResult::from_raw(&self.jni_ref(), unsafe { + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the new result of the login, as an enum - pub fn set_result( - &self, - result: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/player/PlayerPreLoginEvent/Result;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(result.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setResult", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the current kick message that will be used if getResult() != - /// Result.ALLOWED - pub fn kick_message(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getKickMessage", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - /// Sets the kick message to display if getResult() != Result.ALLOWED - pub fn set_kick_message( - &self, - message: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(message.into())?, - )); + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setKickMessage", + "setCancelled", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Allows the player to log in - pub fn allow(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "allow", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Disallows the player from logging in, with the given reason - pub fn disallow( - &self, - result: impl Into>, - message: impl Into, - ) -> Result<(), Box> { - let sig = String::from( - "(Lorg/bukkit/event/player/PlayerPreLoginEvent/Result;Ljava/lang/String;)V", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(result.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(message.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "disallow", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the player's name. - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Gets the player IP address. - pub fn address(&self) -> Result, Box> { - let sig = String::from("()Ljava/net/InetAddress;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAddress", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) - } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -7308,67 +7614,26 @@ impl<'mc> PlayerPreLoginEvent<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the player's unique ID. - pub fn unique_id( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerPreLoginEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerRecipeDiscoverEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.Event ( ['getResult', 'setResult', 'getKickMessage', 'setKickMessage', 'allow', 'disallow', 'getName', 'getAddress', 'getHandlers', 'getUniqueId', 'getHandlerList']) - /// Convenience method for providing a user-friendly identifier. By - /// default, it is the event's class's {@linkplain Class#getSimpleName() - /// simple name}. - pub fn event_name(&self) -> Result> { - let temp_clone = crate::event::Event::from_raw(&self.0, unsafe { + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getRecipe', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + /// Returns the player involved in this event + pub fn player(&self) -> Result, Box> { + let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::Event = temp_clone.into(); - real.event_name() - } - /// Any custom event that should not by synchronized with other events must - /// use the specific constructor. These are the caveats of using an - /// asynchronous event: - ///
    - ///
  • The event is never fired from inside code triggered by a - /// synchronous event. Attempting to do so results in an {@link - /// java.lang.IllegalStateException}. - ///
  • However, asynchronous event handlers may fire synchronous or - /// asynchronous events - ///
  • The event may be fired multiple times simultaneously and in any - /// order. - ///
  • Any newly registered or unregistered handler is ignored after an - /// event starts execution. - ///
  • The handlers for this event may block for any length of time. - ///
  • Some implementations may selectively declare a specific event use - /// as asynchronous. This behavior should be clearly defined. - ///
  • Asynchronous calls are not calculated in the plugin timing system. - ///
- pub fn is_asynchronous(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isAsynchronous", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let real: crate::event::player::PlayerEvent = temp_clone.into(); + real.player() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -7376,176 +7641,47 @@ impl<'mc> PlayerPreLoginEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerPreLoginEvent<'mc> { - fn into(self) -> crate::event::Event<'mc> { - crate::event::Event::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerPreLoginEvent into crate::event::Event") +impl<'mc> Into> for PlayerRecipeDiscoverEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerRecipeDiscoverEvent into crate::event::Cancellable") } } -pub enum PlayerPreLoginEventResult<'mc> {} -impl<'mc> std::fmt::Display for PlayerPreLoginEventResult<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} +impl<'mc> Into> for PlayerRecipeDiscoverEvent<'mc> { + fn into(self) -> crate::event::player::PlayerEvent<'mc> { + crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting PlayerRecipeDiscoverEvent into crate::event::player::PlayerEvent", + ) } } +#[repr(C)] +pub struct PlayerJoinEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); -impl<'mc> PlayerPreLoginEventResult<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/event/player/PlayerPreLoginEvent/Result"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/event/player/PlayerPreLoginEvent/Result;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct PlayerPreLoginEventResultStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PlayerPreLoginEventResult<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for PlayerPreLoginEventResult<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PlayerPreLoginEventResult from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerPreLoginEvent/Result")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerPreLoginEventResult object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for PlayerPreLoginEventResultStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PlayerPreLoginEventResultStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PlayerPreLoginEventResultStruct from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerPreLoginEvent/Result")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerPreLoginEventResultStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> PlayerPreLoginEventResultStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/event/player/PlayerPreLoginEvent/Result;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerPreLoginEvent/Result"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::player::PlayerPreLoginEventResult::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct PlayerAdvancementDoneEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PlayerAdvancementDoneEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PlayerAdvancementDoneEvent<'mc> { - fn from_raw( +impl<'mc> JNIRaw<'mc> for PlayerJoinEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PlayerJoinEvent<'mc> { + fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PlayerAdvancementDoneEvent from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate PlayerJoinEvent from null object.").into(), + ); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerAdvancementDoneEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/player/PlayerJoinEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerAdvancementDoneEvent object, got {}", + "Invalid argument passed. Expected a PlayerJoinEvent object, got {}", name ) .into()) @@ -7555,21 +7691,20 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerAdvancementDoneEvent<'mc> { } } -impl<'mc> PlayerAdvancementDoneEvent<'mc> { +impl<'mc> PlayerJoinEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - who: impl Into>, - advancement: impl Into>, - ) -> Result, Box> - { - let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/advancement/Advancement;)V"); + player_joined: impl Into>, + join_message: impl Into, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/Player;Ljava/lang/String;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(who.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(advancement.into().jni_object().clone()) + jni::objects::JObject::from_raw(player_joined.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/player/PlayerAdvancementDoneEvent"); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(join_message.into())?, + )); + let cls = jni.find_class("org/bukkit/event/player/PlayerJoinEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -7580,20 +7715,42 @@ impl<'mc> PlayerAdvancementDoneEvent<'mc> { ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerAdvancementDoneEvent::from_raw(&jni, res) + crate::event::player::PlayerJoinEvent::from_raw(&jni, res) } - /// Get the advancement which has been completed. - pub fn advancement( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/advancement/Advancement;"); + /// Gets the join message to send to all online players + pub fn join_message(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAdvancement", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getJoinMessage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::advancement::Advancement::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Sets the join message to send to all online players + pub fn set_join_message( + &self, + join_message: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(join_message.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setJoinMessage", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn handlers(&self) -> Result, Box> { @@ -7611,14 +7768,14 @@ impl<'mc> PlayerAdvancementDoneEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerAdvancementDoneEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerJoinEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getAdvancement', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getJoinMessage', 'setJoinMessage', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -7633,20 +7790,19 @@ impl<'mc> PlayerAdvancementDoneEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerAdvancementDoneEvent<'mc> { +impl<'mc> Into> for PlayerJoinEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { - crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting PlayerAdvancementDoneEvent into crate::event::player::PlayerEvent", - ) + crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerJoinEvent into crate::event::player::PlayerEvent") } } #[repr(C)] -pub struct PlayerGameModeChangeEvent<'mc>( +pub struct PlayerTakeLecternBookEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerGameModeChangeEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerTakeLecternBookEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -7654,22 +7810,22 @@ impl<'mc> JNIRaw<'mc> for PlayerGameModeChangeEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerGameModeChangeEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerTakeLecternBookEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate PlayerGameModeChangeEvent from null object." + "Tried to instantiate PlayerTakeLecternBookEvent from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerGameModeChangeEvent")?; + env.validate_name(&obj, "org/bukkit/event/player/PlayerTakeLecternBookEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerGameModeChangeEvent object, got {}", + "Invalid argument passed. Expected a PlayerTakeLecternBookEvent object, got {}", name ) .into()) @@ -7679,21 +7835,21 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerGameModeChangeEvent<'mc> { } } -impl<'mc> PlayerGameModeChangeEvent<'mc> { +impl<'mc> PlayerTakeLecternBookEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - player: impl Into>, - new_game_mode: impl Into>, - ) -> Result, Box> + who: impl Into>, + lectern: impl Into>, + ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/GameMode;)V"); + let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/block/Lectern;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) + jni::objects::JObject::from_raw(who.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_game_mode.into().jni_object().clone()) + jni::objects::JObject::from_raw(lectern.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/event/player/PlayerGameModeChangeEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerTakeLecternBookEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -7704,17 +7860,45 @@ impl<'mc> PlayerGameModeChangeEvent<'mc> { ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerGameModeChangeEvent::from_raw(&jni, res) + crate::event::player::PlayerTakeLecternBookEvent::from_raw(&jni, res) } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the lectern involved. + pub fn lectern(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/Lectern;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLectern", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } + crate::block::Lectern::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the current ItemStack on the lectern. + pub fn book( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBook", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); @@ -7728,17 +7912,6 @@ impl<'mc> PlayerGameModeChangeEvent<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the GameMode the player is switched to. - pub fn new_game_mode(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/GameMode;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getNewGameMode", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::GameMode::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -7755,14 +7928,14 @@ impl<'mc> PlayerGameModeChangeEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerGameModeChangeEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerTakeLecternBookEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['isCancelled', 'setCancelled', 'getNewGameMode', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getLectern', 'getBook', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -7777,26 +7950,26 @@ impl<'mc> PlayerGameModeChangeEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerGameModeChangeEvent<'mc> { +impl<'mc> Into> for PlayerTakeLecternBookEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerGameModeChangeEvent into crate::event::Cancellable") + .expect("Error converting PlayerTakeLecternBookEvent into crate::event::Cancellable") } } -impl<'mc> Into> for PlayerGameModeChangeEvent<'mc> { +impl<'mc> Into> for PlayerTakeLecternBookEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting PlayerGameModeChangeEvent into crate::event::player::PlayerEvent", + "Error converting PlayerTakeLecternBookEvent into crate::event::player::PlayerEvent", ) } } #[repr(C)] -pub struct PlayerToggleSneakEvent<'mc>( +pub struct PlayerShowEntityEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerToggleSneakEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerShowEntityEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -7804,22 +7977,22 @@ impl<'mc> JNIRaw<'mc> for PlayerToggleSneakEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerToggleSneakEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerShowEntityEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate PlayerToggleSneakEvent from null object." + "Tried to instantiate PlayerShowEntityEvent from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerToggleSneakEvent")?; + env.validate_name(&obj, "org/bukkit/event/player/PlayerShowEntityEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerToggleSneakEvent object, got {}", + "Invalid argument passed. Expected a PlayerShowEntityEvent object, got {}", name ) .into()) @@ -7829,18 +8002,20 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerToggleSneakEvent<'mc> { } } -impl<'mc> PlayerToggleSneakEvent<'mc> { +impl<'mc> PlayerShowEntityEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - player: impl Into>, - is_sneaking: bool, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Player;Z)V"); + who: impl Into>, + entity: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/entity/Entity;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) + jni::objects::JObject::from_raw(who.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Bool(is_sneaking.into()); - let cls = jni.find_class("org/bukkit/event/player/PlayerToggleSneakEvent"); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/player/PlayerShowEntityEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -7851,38 +8026,18 @@ impl<'mc> PlayerToggleSneakEvent<'mc> { ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerToggleSneakEvent::from_raw(&jni, res) - } - /// Returns whether the player is now sneaking or not. - pub fn is_sneaking(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isSneaking", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::event::player::PlayerShowEntityEvent::from_raw(&jni, res) } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + /// Gets the entity which has been shown to the player. + pub fn entity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn handlers(&self) -> Result, Box> { @@ -7900,14 +8055,14 @@ impl<'mc> PlayerToggleSneakEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerToggleSneakEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerShowEntityEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['isSneaking', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getEntity', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -7922,26 +8077,19 @@ impl<'mc> PlayerToggleSneakEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerToggleSneakEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerToggleSneakEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for PlayerToggleSneakEvent<'mc> { +impl<'mc> Into> for PlayerShowEntityEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { - crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting PlayerToggleSneakEvent into crate::event::player::PlayerEvent", - ) + crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerShowEntityEvent into crate::event::player::PlayerEvent") } } #[repr(C)] -pub struct PlayerPickupArrowEvent<'mc>( +pub struct PlayerRegisterChannelEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerPickupArrowEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerRegisterChannelEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -7949,22 +8097,22 @@ impl<'mc> JNIRaw<'mc> for PlayerPickupArrowEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerPickupArrowEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerRegisterChannelEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate PlayerPickupArrowEvent from null object." + "Tried to instantiate PlayerRegisterChannelEvent from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerPickupArrowEvent")?; + env.validate_name(&obj, "org/bukkit/event/player/PlayerRegisterChannelEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerPickupArrowEvent object, got {}", + "Invalid argument passed. Expected a PlayerRegisterChannelEvent object, got {}", name ) .into()) @@ -7974,24 +8122,21 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerPickupArrowEvent<'mc> { } } -impl<'mc> PlayerPickupArrowEvent<'mc> { +impl<'mc> PlayerRegisterChannelEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, player: impl Into>, - item: impl Into>, - arrow: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/entity/Item;Lorg/bukkit/entity/AbstractArrow;)V"); + channel: impl Into, + ) -> Result, Box> + { + let sig = String::from("(Lorg/bukkit/entity/Player;Ljava/lang/String;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(arrow.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/event/player/PlayerPickupArrowEvent"); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(channel.into())?, + )); + let cls = jni.find_class("org/bukkit/event/player/PlayerRegisterChannelEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -7999,55 +8144,19 @@ impl<'mc> PlayerPickupArrowEvent<'mc> { vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerPickupArrowEvent::from_raw(&jni, res) - } - /// Get the arrow being picked up by the player - pub fn arrow(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/AbstractArrow;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getArrow", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::AbstractArrow::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - // SUPER CLASS: org.bukkit.event.player.PlayerPickupItemEvent ( ['getArrow']) - /// Gets the Item picked up by the player. - pub fn item(&self) -> Result, Box> { - let temp_clone = crate::event::player::PlayerPickupItemEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerPickupItemEvent = temp_clone.into(); - real.item() - } - /// Gets the amount remaining on the ground, if any - pub fn remaining(&self) -> Result> { - let temp_clone = crate::event::player::PlayerPickupItemEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerPickupItemEvent = temp_clone.into(); - real.remaining() - } - - pub fn is_cancelled(&self) -> Result> { - let temp_clone = crate::event::player::PlayerPickupItemEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerPickupItemEvent = temp_clone.into(); - real.is_cancelled() + crate::event::player::PlayerRegisterChannelEvent::from_raw(&jni, res) } + // SUPER CLASS: org.bukkit.event.player.PlayerChannelEvent ( []) - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let temp_clone = crate::event::player::PlayerPickupItemEvent::from_raw(&self.0, unsafe { + pub fn channel(&self) -> Result> { + let temp_clone = crate::event::player::PlayerChannelEvent::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::player::PlayerPickupItemEvent = temp_clone.into(); - real.set_cancelled(cancel) + let real: crate::event::player::PlayerChannelEvent = temp_clone.into(); + real.channel() } pub fn handlers(&self) -> Result, Box> { @@ -8064,7 +8173,7 @@ impl<'mc> PlayerPickupArrowEvent<'mc> { pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { - crate::event::player::PlayerPickupItemEvent::handler_list(jni) + crate::event::player::PlayerChannelEvent::handler_list(jni) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -8072,18 +8181,18 @@ impl<'mc> PlayerPickupArrowEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerPickupArrowEvent<'mc> { - fn into(self) -> crate::event::player::PlayerPickupItemEvent<'mc> { - crate::event::player::PlayerPickupItemEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting PlayerPickupArrowEvent into crate::event::player::PlayerPickupItemEvent") +impl<'mc> Into> for PlayerRegisterChannelEvent<'mc> { + fn into(self) -> crate::event::player::PlayerChannelEvent<'mc> { + crate::event::player::PlayerChannelEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting PlayerRegisterChannelEvent into crate::event::player::PlayerChannelEvent") } } #[repr(C)] -pub struct PlayerArmorStandManipulateEvent<'mc>( +pub struct PlayerBedEnterEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerArmorStandManipulateEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerBedEnterEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -8091,46 +8200,39 @@ impl<'mc> JNIRaw<'mc> for PlayerArmorStandManipulateEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerArmorStandManipulateEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerBedEnterEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PlayerArmorStandManipulateEvent from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate PlayerBedEnterEvent from null object.").into(), + ); } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/event/player/PlayerArmorStandManipulateEvent", - )?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/player/PlayerBedEnterEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerArmorStandManipulateEvent object, got {}", - name - ) - .into()) + "Invalid argument passed. Expected a PlayerBedEnterEvent object, got {}", + name + ) + .into()) } else { Ok(Self(env.clone(), obj)) } } } -impl<'mc> PlayerArmorStandManipulateEvent<'mc> { +impl<'mc> PlayerBedEnterEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, who: impl Into>, - clicked_entity: impl Into>, - player_item: impl Into>, - armor_stand_item: impl Into>, - slot: impl Into>, - hand: std::option::Option>>, - ) -> Result< - crate::event::player::PlayerArmorStandManipulateEvent<'mc>, - Box, - > { + bed: impl Into>, + bed_enter_result: std::option::Option< + impl Into>, + >, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "Lorg/bukkit/entity/Player;"; @@ -8138,120 +8240,126 @@ impl<'mc> PlayerArmorStandManipulateEvent<'mc> { jni::objects::JObject::from_raw(who.into().jni_object().clone()) }); args.push(val_1); - sig += "Lorg/bukkit/entity/ArmorStand;"; + sig += "Lorg/bukkit/block/Block;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(clicked_entity.into().jni_object().clone()) + jni::objects::JObject::from_raw(bed.into().jni_object().clone()) }); args.push(val_2); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player_item.into().jni_object().clone()) - }); - args.push(val_3); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(armor_stand_item.into().jni_object().clone()) - }); - args.push(val_4); - sig += "Lorg/bukkit/inventory/EquipmentSlot;"; - let val_5 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(slot.into().jni_object().clone()) - }); - args.push(val_5); - if let Some(a) = hand { - sig += "Lorg/bukkit/inventory/EquipmentSlot;"; - let val_6 = jni::objects::JValueGen::Object(unsafe { + if let Some(a) = bed_enter_result { + sig += "Lorg/bukkit/event/player/PlayerBedEnterEvent/BedEnterResult;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); - args.push(val_6); + args.push(val_3); } sig += ")V"; - let cls = jni.find_class("org/bukkit/event/player/PlayerArmorStandManipulateEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerBedEnterEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerArmorStandManipulateEvent::from_raw(&jni, res) - } - /// Returns the item held by the player. - /// - /// If this item is empty and the armor stand item is also empty, there will be no - /// transaction between the player and the armor stand. If the player's item is empty - /// but the armor stand item is not, the player's item will be placed on the armor - /// stand. If both items are not empty, the items will be swapped. - /// - /// In the case that this event is cancelled, the original items will remain the same. - pub fn player_item( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPlayerItem", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + crate::event::player::PlayerBedEnterEvent::from_raw(&jni, res) } - /// Returns the item held by the armor stand. - /// - /// If this item is empty and the player's item is also empty, there will be no - /// transaction between the player and the armor stand. If the player's item is empty - /// but the armor stand item is not, then the player will obtain the armor stand item. - /// In the case that the player's item is not empty but the armor stand item is empty, - /// the player's item will be placed on the armor stand. If both items are not empty, - /// the items will be swapped. - /// - /// In the case that the event is cancelled the original items will remain the same. - pub fn armor_stand_item( + /// This describes the default outcome of this event. + pub fn bed_enter_result( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + ) -> Result< + crate::event::player::PlayerBedEnterEventBedEnterResult<'mc>, + Box, + > { + let sig = String::from("()Lorg/bukkit/event/player/PlayerBedEnterEvent/BedEnterResult;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getArmorStandItem", + "getBedEnterResult", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns the raw item slot of the armor stand in this event. - pub fn slot(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/EquipmentSlot;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSlot", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::EquipmentSlot::from_raw(&self.jni_ref(), unsafe { + crate::event::player::PlayerBedEnterEventBedEnterResult::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// {@inheritDoc} + /// This controls the action to take with the bed that was clicked on. /// - /// Note that this is not the hand of the armor stand that was changed, but rather - /// the hand used by the player to swap items with the armor stand. - pub fn hand(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/EquipmentSlot;"); + /// In case of {@link org.bukkit.event.Event.Result#DEFAULT}, the default outcome is described by + /// {@link #getBedEnterResult()}. + pub fn use_bed(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/Event/Result;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getHand", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "useBed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::EquipmentSlot::from_raw(&self.jni_ref(), unsafe { + crate::event::EventResult::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn right_clicked( + /// Sets the action to take with the interacted bed. + /// + /// {@link org.bukkit.event.Event.Result#ALLOW} will result in the player sleeping, regardless of + /// the default outcome described by {@link #getBedEnterResult()}. + /// + /// {@link org.bukkit.event.Event.Result#DENY} will prevent the player from sleeping. This has the + /// same effect as canceling the event via {@link #setCancelled(boolean)}. + /// + /// {@link org.bukkit.event.Event.Result#DEFAULT} will result in the outcome described by + /// {@link #getBedEnterResult()}. + pub fn set_use_bed( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/ArmorStand;"); + use_bed: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/event/Event/Result;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(use_bed.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setUseBed", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the cancellation state of this event. Set to true if you want to + /// prevent the player from sleeping. + /// + /// Canceling the event has the same effect as setting {@link #useBed()} to + /// {@link org.bukkit.event.Event.Result#DENY}. + /// + /// For backwards compatibility reasons this also returns true if + /// {@link #useBed()} is {@link org.bukkit.event.Event.Result#DEFAULT} and the + /// {@link #getBedEnterResult() default action} is to prevent bed entering. + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getRightClicked", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::ArmorStand::from_raw(&self.jni_ref(), unsafe { + Ok(res.z()?) + } + /// Sets the cancellation state of this event. A canceled event will not be + /// executed in the server, but will still pass to other plugins. + /// + /// Canceling this event will prevent use of the bed. + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the bed block involved in this event. + pub fn bed(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::Block::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -8271,31 +8379,21 @@ impl<'mc> PlayerArmorStandManipulateEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerArmorStandManipulateEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerBedEnterEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerInteractEntityEvent ( ['getPlayerItem', 'getArmorStandItem', 'getSlot', 'getHand', 'getRightClicked', 'getHandlers', 'getHandlerList']) - - pub fn is_cancelled(&self) -> Result> { - let temp_clone = - crate::event::player::PlayerInteractEntityEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerInteractEntityEvent = temp_clone.into(); - real.is_cancelled() - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let temp_clone = - crate::event::player::PlayerInteractEntityEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerInteractEntityEvent = temp_clone.into(); - real.set_cancelled(cancel) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getBedEnterResult', 'useBed', 'setUseBed', 'isCancelled', 'setCancelled', 'getBed', 'getHandlers', 'getHandlerList']) + /// Returns the player involved in this event + pub fn player(&self) -> Result, Box> { + let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerEvent = temp_clone.into(); + real.player() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -8303,141 +8401,253 @@ impl<'mc> PlayerArmorStandManipulateEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> - for PlayerArmorStandManipulateEvent<'mc> -{ - fn into(self) -> crate::event::player::PlayerInteractEntityEvent<'mc> { - crate::event::player::PlayerInteractEntityEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting PlayerArmorStandManipulateEvent into crate::event::player::PlayerInteractEntityEvent") +impl<'mc> Into> for PlayerBedEnterEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerBedEnterEvent into crate::event::Cancellable") } } -#[repr(C)] -pub struct PlayerDropItemEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PlayerDropItemEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() +impl<'mc> Into> for PlayerBedEnterEvent<'mc> { + fn into(self) -> crate::event::player::PlayerEvent<'mc> { + crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerBedEnterEvent into crate::event::player::PlayerEvent") } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } +} +pub enum PlayerBedEnterEventBedEnterResult<'mc> { + Ok { + inner: PlayerBedEnterEventBedEnterResultStruct<'mc>, + }, + NotPossibleHere { + inner: PlayerBedEnterEventBedEnterResultStruct<'mc>, + }, + NotPossibleNow { + inner: PlayerBedEnterEventBedEnterResultStruct<'mc>, + }, + TooFarAway { + inner: PlayerBedEnterEventBedEnterResultStruct<'mc>, + }, + NotSafe { + inner: PlayerBedEnterEventBedEnterResultStruct<'mc>, + }, + OtherProblem { + inner: PlayerBedEnterEventBedEnterResultStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for PlayerBedEnterEventBedEnterResult<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PlayerBedEnterEventBedEnterResult::Ok { .. } => f.write_str("OK"), + PlayerBedEnterEventBedEnterResult::NotPossibleHere { .. } => { + f.write_str("NOT_POSSIBLE_HERE") + } + PlayerBedEnterEventBedEnterResult::NotPossibleNow { .. } => { + f.write_str("NOT_POSSIBLE_NOW") + } + PlayerBedEnterEventBedEnterResult::TooFarAway { .. } => f.write_str("TOO_FAR_AWAY"), + PlayerBedEnterEventBedEnterResult::NotSafe { .. } => f.write_str("NOT_SAFE"), + PlayerBedEnterEventBedEnterResult::OtherProblem { .. } => f.write_str("OTHER_PROBLEM"), + } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerDropItemEvent<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate PlayerDropItemEvent from null object.").into(), - ); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerDropItemEvent")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerDropItemEvent object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) +impl<'mc> std::ops::Deref for PlayerBedEnterEventBedEnterResult<'mc> { + type Target = PlayerBedEnterEventBedEnterResultStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + PlayerBedEnterEventBedEnterResult::Ok { inner } => inner, + PlayerBedEnterEventBedEnterResult::NotPossibleHere { inner } => inner, + PlayerBedEnterEventBedEnterResult::NotPossibleNow { inner } => inner, + PlayerBedEnterEventBedEnterResult::TooFarAway { inner } => inner, + PlayerBedEnterEventBedEnterResult::NotSafe { inner } => inner, + PlayerBedEnterEventBedEnterResult::OtherProblem { inner } => inner, } } } -impl<'mc> PlayerDropItemEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - player: impl Into>, - drop: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/entity/Item;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(drop.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/event/player/PlayerDropItemEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( +impl<'mc> PlayerBedEnterEventBedEnterResult<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/event/player/PlayerBedEnterEvent/BedEnterResult"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/event/player/PlayerBedEnterEvent/BedEnterResult;", + vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerDropItemEvent::from_raw(&jni, res) - } - /// Gets the ItemDrop created by the player - pub fn item_drop(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Item;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemDrop", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Item::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "OK" => Ok(PlayerBedEnterEventBedEnterResult::Ok { + inner: PlayerBedEnterEventBedEnterResultStruct::from_raw(env, obj)?, + }), + "NOT_POSSIBLE_HERE" => Ok(PlayerBedEnterEventBedEnterResult::NotPossibleHere { + inner: PlayerBedEnterEventBedEnterResultStruct::from_raw(env, obj)?, + }), + "NOT_POSSIBLE_NOW" => Ok(PlayerBedEnterEventBedEnterResult::NotPossibleNow { + inner: PlayerBedEnterEventBedEnterResultStruct::from_raw(env, obj)?, + }), + "TOO_FAR_AWAY" => Ok(PlayerBedEnterEventBedEnterResult::TooFarAway { + inner: PlayerBedEnterEventBedEnterResultStruct::from_raw(env, obj)?, + }), + "NOT_SAFE" => Ok(PlayerBedEnterEventBedEnterResult::NotSafe { + inner: PlayerBedEnterEventBedEnterResultStruct::from_raw(env, obj)?, + }), + "OTHER_PROBLEM" => Ok(PlayerBedEnterEventBedEnterResult::OtherProblem { + inner: PlayerBedEnterEventBedEnterResultStruct::from_raw(env, obj)?, + }), - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } +} - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +#[repr(C)] +pub struct PlayerBedEnterEventBedEnterResultStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PlayerBedEnterEventBedEnterResult<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Ok { inner } => inner.0.clone(), + Self::NotPossibleHere { inner } => inner.0.clone(), + Self::NotPossibleNow { inner } => inner.0.clone(), + Self::TooFarAway { inner } => inner.0.clone(), + Self::NotSafe { inner } => inner.0.clone(), + Self::OtherProblem { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Ok { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::NotPossibleHere { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NotPossibleNow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TooFarAway { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NotSafe { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::OtherProblem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for PlayerBedEnterEventBedEnterResult<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate PlayerBedEnterEventBedEnterResult from null object." + ) + .into()); + } + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/event/player/PlayerBedEnterEvent/BedEnterResult", + )?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PlayerBedEnterEventBedEnterResult object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "OK" => Ok(PlayerBedEnterEventBedEnterResult::Ok { + inner: PlayerBedEnterEventBedEnterResultStruct::from_raw(env, obj)?, + }), + "NOT_POSSIBLE_HERE" => Ok(PlayerBedEnterEventBedEnterResult::NotPossibleHere { + inner: PlayerBedEnterEventBedEnterResultStruct::from_raw(env, obj)?, + }), + "NOT_POSSIBLE_NOW" => Ok(PlayerBedEnterEventBedEnterResult::NotPossibleNow { + inner: PlayerBedEnterEventBedEnterResultStruct::from_raw(env, obj)?, + }), + "TOO_FAR_AWAY" => Ok(PlayerBedEnterEventBedEnterResult::TooFarAway { + inner: PlayerBedEnterEventBedEnterResultStruct::from_raw(env, obj)?, + }), + "NOT_SAFE" => Ok(PlayerBedEnterEventBedEnterResult::NotSafe { + inner: PlayerBedEnterEventBedEnterResultStruct::from_raw(env, obj)?, + }), + "OTHER_PROBLEM" => Ok(PlayerBedEnterEventBedEnterResult::OtherProblem { + inner: PlayerBedEnterEventBedEnterResultStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } } +} - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +impl<'mc> JNIRaw<'mc> for PlayerBedEnterEventBedEnterResultStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PlayerBedEnterEventBedEnterResultStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate PlayerBedEnterEventBedEnterResultStruct from null object." + ) + .into()); + } + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/event/player/PlayerBedEnterEvent/BedEnterResult", + )?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PlayerBedEnterEventBedEnterResultStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } +} - pub fn handler_list( +impl<'mc> PlayerBedEnterEventBedEnterResultStruct<'mc> { + pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerDropItemEvent"); + ) -> Result< + crate::event::player::PlayerBedEnterEventBedEnterResult<'mc>, + Box, + > { + let sig = String::from("()Lorg/bukkit/event/player/PlayerBedEnterEvent/BedEnterResult;"); + let cls = jni.find_class("org/bukkit/event/player/PlayerBedEnterEvent/BedEnterResult"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getItemDrop', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) - /// Returns the player involved in this event - pub fn player(&self) -> Result, Box> { - let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerEvent = temp_clone.into(); - real.player() + crate::event::player::PlayerBedEnterEventBedEnterResult::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -8445,25 +8655,13 @@ impl<'mc> PlayerDropItemEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerDropItemEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerDropItemEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for PlayerDropItemEvent<'mc> { - fn into(self) -> crate::event::player::PlayerEvent<'mc> { - crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerDropItemEvent into crate::event::player::PlayerEvent") - } -} #[repr(C)] -pub struct PlayerQuitEvent<'mc>( +pub struct PlayerPreLoginEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerQuitEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerPreLoginEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -8471,20 +8669,21 @@ impl<'mc> JNIRaw<'mc> for PlayerQuitEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerQuitEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerPreLoginEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate PlayerQuitEvent from null object.").into(), + eyre::eyre!("Tried to instantiate PlayerPreLoginEvent from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/player/PlayerQuitEvent")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/player/PlayerPreLoginEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerQuitEvent object, got {}", + "Invalid argument passed. Expected a PlayerPreLoginEvent object, got {}", name ) .into()) @@ -8494,67 +8693,159 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerQuitEvent<'mc> { } } -impl<'mc> PlayerQuitEvent<'mc> { +impl<'mc> PlayerPreLoginEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - who: impl Into>, - quit_message: impl Into, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Player;Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(who.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(quit_message.into())?, + name: impl Into, + ip_address: jni::objects::JObject<'mc>, + unique_id: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(name.into())?, )); - let cls = jni.find_class("org/bukkit/event/player/PlayerQuitEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerQuitEvent::from_raw(&jni, res) + args.push(val_1); + sig += "Ljava/net/InetAddress;"; + let val_2 = jni::objects::JValueGen::Object(ip_address); + args.push(val_2); + if let Some(a) = unique_id { + sig += "Ljava/util/UUID;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_3); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/player/PlayerPreLoginEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::event::player::PlayerPreLoginEvent::from_raw(&jni, res) } - /// Gets the quit message to send to all online players - pub fn quit_message(&self) -> Result, Box> { + /// Gets the current result of the login, as an enum + pub fn result( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/event/player/PlayerPreLoginEvent/Result;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getResult", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::player::PlayerPreLoginEventResult::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the new result of the login, as an enum + pub fn set_result( + &self, + result: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/event/player/PlayerPreLoginEvent/Result;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(result.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setResult", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the current kick message that will be used if getResult() != + /// Result.ALLOWED + pub fn kick_message(&self) -> Result> { let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getQuitMessage", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getKickMessage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets the quit message to send to all online players - pub fn set_quit_message( + /// Sets the kick message to display if getResult() != Result.ALLOWED + pub fn set_kick_message( &self, - quit_message: impl Into, + message: impl Into, ) -> Result<(), Box> { let sig = String::from("(Ljava/lang/String;)V"); let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(quit_message.into())?, + self.jni_ref().new_string(message.into())?, )); let res = self.jni_ref().call_method( &self.jni_object(), - "setQuitMessage", + "setKickMessage", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } + /// Allows the player to log in + pub fn allow(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "allow", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Disallows the player from logging in, with the given reason + pub fn disallow( + &self, + result: impl Into>, + message: impl Into, + ) -> Result<(), Box> { + let sig = String::from( + "(Lorg/bukkit/event/player/PlayerPreLoginEvent/Result;Ljava/lang/String;)V", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(result.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(message.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "disallow", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the player's name. + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gets the player IP address. + pub fn address(&self) -> Result, Box> { + let sig = String::from("()Ljava/net/InetAddress;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAddress", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) + } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -8566,26 +8857,67 @@ impl<'mc> PlayerQuitEvent<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } + /// Gets the player's unique ID. + pub fn unique_id( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerQuitEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerPreLoginEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getQuitMessage', 'setQuitMessage', 'getHandlers', 'getHandlerList']) - /// Returns the player involved in this event - pub fn player(&self) -> Result, Box> { - let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { + // SUPER CLASS: org.bukkit.event.Event ( ['getResult', 'setResult', 'getKickMessage', 'setKickMessage', 'allow', 'disallow', 'getName', 'getAddress', 'getHandlers', 'getUniqueId', 'getHandlerList']) + /// Convenience method for providing a user-friendly identifier. By + /// default, it is the event's class's {@linkplain Class#getSimpleName() + /// simple name}. + pub fn event_name(&self) -> Result> { + let temp_clone = crate::event::Event::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::event::player::PlayerEvent = temp_clone.into(); - real.player() + let real: crate::event::Event = temp_clone.into(); + real.event_name() + } + /// Any custom event that should not by synchronized with other events must + /// use the specific constructor. These are the caveats of using an + /// asynchronous event: + ///
    + ///
  • The event is never fired from inside code triggered by a + /// synchronous event. Attempting to do so results in an {@link + /// java.lang.IllegalStateException}. + ///
  • However, asynchronous event handlers may fire synchronous or + /// asynchronous events + ///
  • The event may be fired multiple times simultaneously and in any + /// order. + ///
  • Any newly registered or unregistered handler is ignored after an + /// event starts execution. + ///
  • The handlers for this event may block for any length of time. + ///
  • Some implementations may selectively declare a specific event use + /// as asynchronous. This behavior should be clearly defined. + ///
  • Asynchronous calls are not calculated in the plugin timing system. + ///
+ pub fn is_asynchronous(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isAsynchronous", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -8593,65 +8925,283 @@ impl<'mc> PlayerQuitEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerQuitEvent<'mc> { - fn into(self) -> crate::event::player::PlayerEvent<'mc> { - crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerQuitEvent into crate::event::player::PlayerEvent") +impl<'mc> Into> for PlayerPreLoginEvent<'mc> { + fn into(self) -> crate::event::Event<'mc> { + crate::event::Event::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerPreLoginEvent into crate::event::Event") + } +} +pub enum PlayerPreLoginEventResult<'mc> { + Allowed { + inner: PlayerPreLoginEventResultStruct<'mc>, + }, + KickFull { + inner: PlayerPreLoginEventResultStruct<'mc>, + }, + KickBanned { + inner: PlayerPreLoginEventResultStruct<'mc>, + }, + KickWhitelist { + inner: PlayerPreLoginEventResultStruct<'mc>, + }, + KickOther { + inner: PlayerPreLoginEventResultStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for PlayerPreLoginEventResult<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PlayerPreLoginEventResult::Allowed { .. } => f.write_str("ALLOWED"), + PlayerPreLoginEventResult::KickFull { .. } => f.write_str("KICK_FULL"), + PlayerPreLoginEventResult::KickBanned { .. } => f.write_str("KICK_BANNED"), + PlayerPreLoginEventResult::KickWhitelist { .. } => f.write_str("KICK_WHITELIST"), + PlayerPreLoginEventResult::KickOther { .. } => f.write_str("KICK_OTHER"), + } + } +} +impl<'mc> std::ops::Deref for PlayerPreLoginEventResult<'mc> { + type Target = PlayerPreLoginEventResultStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + PlayerPreLoginEventResult::Allowed { inner } => inner, + PlayerPreLoginEventResult::KickFull { inner } => inner, + PlayerPreLoginEventResult::KickBanned { inner } => inner, + PlayerPreLoginEventResult::KickWhitelist { inner } => inner, + PlayerPreLoginEventResult::KickOther { inner } => inner, + } + } +} + +impl<'mc> PlayerPreLoginEventResult<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/event/player/PlayerPreLoginEvent/Result"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/event/player/PlayerPreLoginEvent/Result;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "ALLOWED" => Ok(PlayerPreLoginEventResult::Allowed { + inner: PlayerPreLoginEventResultStruct::from_raw(env, obj)?, + }), + "KICK_FULL" => Ok(PlayerPreLoginEventResult::KickFull { + inner: PlayerPreLoginEventResultStruct::from_raw(env, obj)?, + }), + "KICK_BANNED" => Ok(PlayerPreLoginEventResult::KickBanned { + inner: PlayerPreLoginEventResultStruct::from_raw(env, obj)?, + }), + "KICK_WHITELIST" => Ok(PlayerPreLoginEventResult::KickWhitelist { + inner: PlayerPreLoginEventResultStruct::from_raw(env, obj)?, + }), + "KICK_OTHER" => Ok(PlayerPreLoginEventResult::KickOther { + inner: PlayerPreLoginEventResultStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } + #[repr(C)] -pub struct PlayerLevelChangeEvent<'mc>( +pub struct PlayerPreLoginEventResultStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerLevelChangeEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerPreLoginEventResult<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + match self { + Self::Allowed { inner } => inner.0.clone(), + Self::KickFull { inner } => inner.0.clone(), + Self::KickBanned { inner } => inner.0.clone(), + Self::KickWhitelist { inner } => inner.0.clone(), + Self::KickOther { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + match self { + Self::Allowed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::KickFull { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::KickBanned { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::KickWhitelist { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::KickOther { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerLevelChangeEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerPreLoginEventResult<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate PlayerLevelChangeEvent from null object." + "Tried to instantiate PlayerPreLoginEventResult from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerLevelChangeEvent")?; + env.validate_name(&obj, "org/bukkit/event/player/PlayerPreLoginEvent/Result")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerLevelChangeEvent object, got {}", + "Invalid argument passed. Expected a PlayerPreLoginEventResult object, got {}", name ) .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "ALLOWED" => Ok(PlayerPreLoginEventResult::Allowed { + inner: PlayerPreLoginEventResultStruct::from_raw(env, obj)?, + }), + "KICK_FULL" => Ok(PlayerPreLoginEventResult::KickFull { + inner: PlayerPreLoginEventResultStruct::from_raw(env, obj)?, + }), + "KICK_BANNED" => Ok(PlayerPreLoginEventResult::KickBanned { + inner: PlayerPreLoginEventResultStruct::from_raw(env, obj)?, + }), + "KICK_WHITELIST" => Ok(PlayerPreLoginEventResult::KickWhitelist { + inner: PlayerPreLoginEventResultStruct::from_raw(env, obj)?, + }), + "KICK_OTHER" => Ok(PlayerPreLoginEventResult::KickOther { + inner: PlayerPreLoginEventResultStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for PlayerPreLoginEventResultStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PlayerPreLoginEventResultStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate PlayerPreLoginEventResultStruct from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/player/PlayerPreLoginEvent/Result")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PlayerPreLoginEventResultStruct object, got {}", + name + ) + .into()) } else { Ok(Self(env.clone(), obj)) } } } -impl<'mc> PlayerLevelChangeEvent<'mc> { +impl<'mc> PlayerPreLoginEventResultStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/event/player/PlayerPreLoginEvent/Result;"); + let cls = jni.find_class("org/bukkit/event/player/PlayerPreLoginEvent/Result"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::player::PlayerPreLoginEventResult::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct PlayerAdvancementDoneEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PlayerAdvancementDoneEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PlayerAdvancementDoneEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate PlayerAdvancementDoneEvent from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/player/PlayerAdvancementDoneEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PlayerAdvancementDoneEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> PlayerAdvancementDoneEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - player: impl Into>, - old_level: i32, - new_level: i32, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Player;II)V"); + who: impl Into>, + advancement: impl Into>, + ) -> Result, Box> + { + let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/advancement/Advancement;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) + jni::objects::JObject::from_raw(who.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(old_level); - let val_3 = jni::objects::JValueGen::Int(new_level); - let cls = jni.find_class("org/bukkit/event/player/PlayerLevelChangeEvent"); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(advancement.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/player/PlayerAdvancementDoneEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -8659,29 +9209,23 @@ impl<'mc> PlayerLevelChangeEvent<'mc> { vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerLevelChangeEvent::from_raw(&jni, res) - } - /// Gets the old level of the player - pub fn old_level(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getOldLevel", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::event::player::PlayerAdvancementDoneEvent::from_raw(&jni, res) } - /// Gets the new level of the player - pub fn new_level(&self) -> Result> { - let sig = String::from("()I"); + /// Get the advancement which has been completed. + pub fn advancement( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/advancement/Advancement;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getNewLevel", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAdvancement", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::advancement::Advancement::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn handlers(&self) -> Result, Box> { @@ -8699,14 +9243,14 @@ impl<'mc> PlayerLevelChangeEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerLevelChangeEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerAdvancementDoneEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getOldLevel', 'getNewLevel', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getAdvancement', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -8721,20 +9265,20 @@ impl<'mc> PlayerLevelChangeEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerLevelChangeEvent<'mc> { +impl<'mc> Into> for PlayerAdvancementDoneEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting PlayerLevelChangeEvent into crate::event::player::PlayerEvent", + "Error converting PlayerAdvancementDoneEvent into crate::event::player::PlayerEvent", ) } } #[repr(C)] -pub struct PlayerRecipeBookSettingsChangeEvent<'mc>( +pub struct PlayerGameModeChangeEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerRecipeBookSettingsChangeEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerGameModeChangeEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -8742,56 +9286,46 @@ impl<'mc> JNIRaw<'mc> for PlayerRecipeBookSettingsChangeEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerRecipeBookSettingsChangeEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerGameModeChangeEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate PlayerRecipeBookSettingsChangeEvent from null object." + "Tried to instantiate PlayerGameModeChangeEvent from null object." ) .into()); } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/event/player/PlayerRecipeBookSettingsChangeEvent", - )?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/player/PlayerGameModeChangeEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerRecipeBookSettingsChangeEvent object, got {}", - name - ) - .into()) + "Invalid argument passed. Expected a PlayerGameModeChangeEvent object, got {}", + name + ) + .into()) } else { Ok(Self(env.clone(), obj)) } } } -impl<'mc> PlayerRecipeBookSettingsChangeEvent<'mc> { +impl<'mc> PlayerGameModeChangeEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, player: impl Into>, - recipe_book_type: impl Into< - crate::event::player::PlayerRecipeBookSettingsChangeEventRecipeBookType<'mc>, - >, - open: bool, - filtering: bool, - ) -> Result< - crate::event::player::PlayerRecipeBookSettingsChangeEvent<'mc>, - Box, - > { - let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/event/player/PlayerRecipeBookSettingsChangeEvent/RecipeBookType;ZZ)V"); + new_game_mode: impl Into>, + ) -> Result, Box> + { + let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/GameMode;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(recipe_book_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(new_game_mode.into().jni_object().clone()) }); - let val_3 = jni::objects::JValueGen::Bool(open.into()); - let val_4 = jni::objects::JValueGen::Bool(filtering.into()); - let cls = jni.find_class("org/bukkit/event/player/PlayerRecipeBookSettingsChangeEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerGameModeChangeEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -8799,53 +9333,44 @@ impl<'mc> PlayerRecipeBookSettingsChangeEvent<'mc> { vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerRecipeBookSettingsChangeEvent::from_raw(&jni, res) + crate::event::player::PlayerGameModeChangeEvent::from_raw(&jni, res) } - /// Gets the type of recipe book the player is changing the settings for. - pub fn recipe_book_type( - &self, - ) -> Result< - crate::event::player::PlayerRecipeBookSettingsChangeEventRecipeBookType<'mc>, - Box, - > { - let sig = String::from( - "()Lorg/bukkit/event/player/PlayerRecipeBookSettingsChangeEvent/RecipeBookType;", - ); + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getRecipeBookType", + "setCancelled", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::event::player::PlayerRecipeBookSettingsChangeEventRecipeBookType::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - ) - } - /// Checks if the recipe book is being opened or closed. - pub fn is_open(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isOpen", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Checks if the recipe book filter is being enabled or disabled. - pub fn is_filtering(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the GameMode the player is switched to. + pub fn new_game_mode(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/GameMode;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isFiltering", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getNewGameMode", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } + crate::GameMode::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -8862,14 +9387,14 @@ impl<'mc> PlayerRecipeBookSettingsChangeEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerRecipeBookSettingsChangeEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerGameModeChangeEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getRecipeBookType', 'isOpen', 'isFiltering', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['isCancelled', 'setCancelled', 'getNewGameMode', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -8884,100 +9409,26 @@ impl<'mc> PlayerRecipeBookSettingsChangeEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> - for PlayerRecipeBookSettingsChangeEvent<'mc> -{ - fn into(self) -> crate::event::player::PlayerEvent<'mc> { - crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting PlayerRecipeBookSettingsChangeEvent into crate::event::player::PlayerEvent") - } -} -pub enum PlayerRecipeBookSettingsChangeEventRecipeBookType<'mc> {} -impl<'mc> std::fmt::Display for PlayerRecipeBookSettingsChangeEventRecipeBookType<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} +impl<'mc> Into> for PlayerGameModeChangeEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerGameModeChangeEvent into crate::event::Cancellable") } } - -impl<'mc> PlayerRecipeBookSettingsChangeEventRecipeBookType<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> - { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class( - "org/bukkit/event/player/PlayerRecipeBookSettingsChangeEvent/RecipeBookType", - ); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/event/player/PlayerRecipeBookSettingsChangeEvent/RecipeBookType;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } +impl<'mc> Into> for PlayerGameModeChangeEvent<'mc> { + fn into(self) -> crate::event::player::PlayerEvent<'mc> { + crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting PlayerGameModeChangeEvent into crate::event::player::PlayerEvent", + ) } } - #[repr(C)] -pub struct PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct<'mc>( +pub struct PlayerToggleSneakEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerRecipeBookSettingsChangeEventRecipeBookType<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for PlayerRecipeBookSettingsChangeEventRecipeBookType<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PlayerRecipeBookSettingsChangeEventRecipeBookType from null object.") - .into()); - } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/event/player/PlayerRecipeBookSettingsChangeEvent/RecipeBookType", - )?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerRecipeBookSettingsChangeEventRecipeBookType object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerToggleSneakEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -8985,50 +9436,117 @@ impl<'mc> JNIRaw<'mc> for PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruc unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerToggleSneakEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct from null object.") - .into()); + "Tried to instantiate PlayerToggleSneakEvent from null object." + ) + .into()); } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/event/player/PlayerRecipeBookSettingsChangeEvent/RecipeBookType", - )?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/player/PlayerToggleSneakEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct object, got {}", - name - ) - .into()) + "Invalid argument passed. Expected a PlayerToggleSneakEvent object, got {}", + name + ) + .into()) } else { Ok(Self(env.clone(), obj)) } } } -impl<'mc> PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct<'mc> { - pub fn values( +impl<'mc> PlayerToggleSneakEvent<'mc> { + pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result< - crate::event::player::PlayerRecipeBookSettingsChangeEventRecipeBookType<'mc>, - Box, - > { - let sig = String::from( - "()Lorg/bukkit/event/player/PlayerRecipeBookSettingsChangeEvent/RecipeBookType;", + player: impl Into>, + is_sneaking: bool, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/Player;Z)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(player.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Bool(is_sneaking.into()); + let cls = jni.find_class("org/bukkit/event/player/PlayerToggleSneakEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - let cls = jni.find_class( - "org/bukkit/event/player/PlayerRecipeBookSettingsChangeEvent/RecipeBookType", + let res = jni.translate_error_no_gen(res)?; + crate::event::player::PlayerToggleSneakEvent::from_raw(&jni, res) + } + /// Returns whether the player is now sneaking or not. + pub fn is_sneaking(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isSneaking", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/player/PlayerToggleSneakEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::event::player::PlayerRecipeBookSettingsChangeEventRecipeBookType::from_raw(&jni, obj) + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['isSneaking', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + /// Returns the player involved in this event + pub fn player(&self) -> Result, Box> { + let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerEvent = temp_clone.into(); + real.player() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -9036,13 +9554,26 @@ impl<'mc> PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for PlayerToggleSneakEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerToggleSneakEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for PlayerToggleSneakEvent<'mc> { + fn into(self) -> crate::event::player::PlayerEvent<'mc> { + crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting PlayerToggleSneakEvent into crate::event::player::PlayerEvent", + ) + } +} #[repr(C)] -pub struct PlayerBucketFishEvent<'mc>( +pub struct PlayerPickupArrowEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerBucketFishEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerPickupArrowEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -9050,22 +9581,22 @@ impl<'mc> JNIRaw<'mc> for PlayerBucketFishEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerBucketFishEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerPickupArrowEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate PlayerBucketFishEvent from null object." + "Tried to instantiate PlayerPickupArrowEvent from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerBucketFishEvent")?; + env.validate_name(&obj, "org/bukkit/event/player/PlayerPickupArrowEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerBucketFishEvent object, got {}", + "Invalid argument passed. Expected a PlayerPickupArrowEvent object, got {}", name ) .into()) @@ -9075,32 +9606,24 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerBucketFishEvent<'mc> { } } -impl<'mc> PlayerBucketFishEvent<'mc> { +impl<'mc> PlayerPickupArrowEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, player: impl Into>, - fish: impl Into>, - water_bucket: impl Into>, - fish_bucket: impl Into>, - hand: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/entity/Fish;Lorg/bukkit/inventory/ItemStack;Lorg/bukkit/inventory/ItemStack;Lorg/bukkit/inventory/EquipmentSlot;)V"); + item: impl Into>, + arrow: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/entity/Item;Lorg/bukkit/entity/AbstractArrow;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(fish.into().jni_object().clone()) + jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(water_bucket.into().jni_object().clone()) + jni::objects::JObject::from_raw(arrow.into().jni_object().clone()) }); - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(fish_bucket.into().jni_object().clone()) - }); - let val_5 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(hand.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/event/player/PlayerBucketFishEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerPickupArrowEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -9109,103 +9632,53 @@ impl<'mc> PlayerBucketFishEvent<'mc> { jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - jni::objects::JValueGen::from(val_5), ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerBucketFishEvent::from_raw(&jni, res) + crate::event::player::PlayerPickupArrowEvent::from_raw(&jni, res) } - /// Gets the fish involved with this event. - pub fn entity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Fish;"); + /// Get the arrow being picked up by the player + pub fn arrow(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/AbstractArrow;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Fish::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - #[deprecated] - /// Gets the bucket used. This refers to the bucket clicked with, ie {@link Material#WATER_BUCKET}. - pub fn water_bucket( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getWaterBucket", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - #[deprecated] - /// Gets the bucket that the fish will be put into. This refers to the bucket with the fish, ie {@link Material#PUFFERFISH_BUCKET}. - pub fn fish_bucket( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFishBucket", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getArrow", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + crate::entity::AbstractArrow::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.event.player.PlayerBucketEntityEvent ( ['getEntity', 'getWaterBucket', 'getFishBucket']) - /// Gets the bucket used to capture the {@link Entity}. - /// This refers to the bucket clicked with, eg {@link Material#WATER_BUCKET}. - pub fn original_bucket( - &self, - ) -> Result, Box> { - let temp_clone = - crate::event::player::PlayerBucketEntityEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerBucketEntityEvent = temp_clone.into(); - real.original_bucket() - } - /// Gets the bucket that the {@link Entity} will be put into. - /// This refers to the bucket with the entity, eg - /// {@link Material#PUFFERFISH_BUCKET}. - pub fn entity_bucket( - &self, - ) -> Result, Box> { - let temp_clone = - crate::event::player::PlayerBucketEntityEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerBucketEntityEvent = temp_clone.into(); - real.entity_bucket() + // SUPER CLASS: org.bukkit.event.player.PlayerPickupItemEvent ( ['getArrow']) + /// Gets the Item picked up by the player. + pub fn item(&self) -> Result, Box> { + let temp_clone = crate::event::player::PlayerPickupItemEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerPickupItemEvent = temp_clone.into(); + real.item() } - /// Get the hand that was used to bucket the entity. - pub fn hand(&self) -> Result, Box> { - let temp_clone = - crate::event::player::PlayerBucketEntityEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerBucketEntityEvent = temp_clone.into(); - real.hand() + /// Gets the amount remaining on the ground, if any + pub fn remaining(&self) -> Result> { + let temp_clone = crate::event::player::PlayerPickupItemEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerPickupItemEvent = temp_clone.into(); + real.remaining() } pub fn is_cancelled(&self) -> Result> { - let temp_clone = - crate::event::player::PlayerBucketEntityEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerBucketEntityEvent = temp_clone.into(); + let temp_clone = crate::event::player::PlayerPickupItemEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerPickupItemEvent = temp_clone.into(); real.is_cancelled() } pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let temp_clone = - crate::event::player::PlayerBucketEntityEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerBucketEntityEvent = temp_clone.into(); + let temp_clone = crate::event::player::PlayerPickupItemEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerPickupItemEvent = temp_clone.into(); real.set_cancelled(cancel) } @@ -9223,7 +9696,7 @@ impl<'mc> PlayerBucketFishEvent<'mc> { pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { - crate::event::player::PlayerBucketEntityEvent::handler_list(jni) + crate::event::player::PlayerPickupItemEvent::handler_list(jni) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -9231,18 +9704,18 @@ impl<'mc> PlayerBucketFishEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerBucketFishEvent<'mc> { - fn into(self) -> crate::event::player::PlayerBucketEntityEvent<'mc> { - crate::event::player::PlayerBucketEntityEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting PlayerBucketFishEvent into crate::event::player::PlayerBucketEntityEvent") +impl<'mc> Into> for PlayerPickupArrowEvent<'mc> { + fn into(self) -> crate::event::player::PlayerPickupItemEvent<'mc> { + crate::event::player::PlayerPickupItemEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting PlayerPickupArrowEvent into crate::event::player::PlayerPickupItemEvent") } } #[repr(C)] -pub struct PlayerTeleportEvent<'mc>( +pub struct PlayerArmorStandManipulateEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerTeleportEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerArmorStandManipulateEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -9250,273 +9723,232 @@ impl<'mc> JNIRaw<'mc> for PlayerTeleportEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerTeleportEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerArmorStandManipulateEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate PlayerTeleportEvent from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate PlayerArmorStandManipulateEvent from null object." + ) + .into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerTeleportEvent")?; + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/event/player/PlayerArmorStandManipulateEvent", + )?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerTeleportEvent object, got {}", - name - ) - .into()) + "Invalid argument passed. Expected a PlayerArmorStandManipulateEvent object, got {}", + name + ) + .into()) } else { Ok(Self(env.clone(), obj)) } } } -impl<'mc> PlayerTeleportEvent<'mc> { +impl<'mc> PlayerArmorStandManipulateEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - player: impl Into>, - from: impl Into>, - to: impl Into>, - cause: std::option::Option< - impl Into>, - >, - ) -> Result, Box> { + who: impl Into>, + clicked_entity: impl Into>, + player_item: impl Into>, + armor_stand_item: impl Into>, + slot: impl Into>, + hand: std::option::Option>>, + ) -> Result< + crate::event::player::PlayerArmorStandManipulateEvent<'mc>, + Box, + > { let mut args = Vec::new(); let mut sig = String::from("("); sig += "Lorg/bukkit/entity/Player;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(player.into().jni_object().clone()) + jni::objects::JObject::from_raw(who.into().jni_object().clone()) }); args.push(val_1); - sig += "Lorg/bukkit/Location;"; + sig += "Lorg/bukkit/entity/ArmorStand;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(from.into().jni_object().clone()) + jni::objects::JObject::from_raw(clicked_entity.into().jni_object().clone()) }); args.push(val_2); - sig += "Lorg/bukkit/Location;"; + sig += "Lorg/bukkit/inventory/ItemStack;"; let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(to.into().jni_object().clone()) + jni::objects::JObject::from_raw(player_item.into().jni_object().clone()) }); args.push(val_3); - if let Some(a) = cause { - sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(armor_stand_item.into().jni_object().clone()) + }); + args.push(val_4); + sig += "Lorg/bukkit/inventory/EquipmentSlot;"; + let val_5 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(slot.into().jni_object().clone()) + }); + args.push(val_5); + if let Some(a) = hand { + sig += "Lorg/bukkit/inventory/EquipmentSlot;"; + let val_6 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); - args.push(val_4); + args.push(val_6); } sig += ")V"; - let cls = jni.find_class("org/bukkit/event/player/PlayerTeleportEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerArmorStandManipulateEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerTeleportEvent::from_raw(&jni, res) + crate::event::player::PlayerArmorStandManipulateEvent::from_raw(&jni, res) } - /// Gets the cause of this teleportation event - pub fn cause( + /// Returns the item held by the player. + /// + /// If this item is empty and the armor stand item is also empty, there will be no + /// transaction between the player and the armor stand. If the player's item is empty + /// but the armor stand item is not, the player's item will be placed on the armor + /// stand. If both items are not empty, the items will be swapped. + /// + /// In the case that this event is cancelled, the original items will remain the same. + pub fn player_item( &self, - ) -> Result< - crate::event::player::PlayerTeleportEventTeleportCause<'mc>, - Box, - > { - let sig = String::from("()Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getCause", sig.as_str(), vec![]); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPlayerItem", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::event::player::PlayerTeleportEventTeleportCause::from_raw(&self.jni_ref(), unsafe { + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + /// Returns the item held by the armor stand. + /// + /// If this item is empty and the player's item is also empty, there will be no + /// transaction between the player and the armor stand. If the player's item is empty + /// but the armor stand item is not, then the player will obtain the armor stand item. + /// In the case that the player's item is not empty but the armor stand item is empty, + /// the player's item will be placed on the armor stand. If both items are not empty, + /// the items will be swapped. + /// + /// In the case that the event is cancelled the original items will remain the same. + pub fn armor_stand_item( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getArmorStandItem", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn handler_list( + /// Returns the raw item slot of the armor stand in this event. + pub fn slot(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/EquipmentSlot;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSlot", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::EquipmentSlot::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// {@inheritDoc} + /// + /// Note that this is not the hand of the armor stand that was changed, but rather + /// the hand used by the player to swap items with the armor stand. + pub fn hand(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/EquipmentSlot;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHand", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::EquipmentSlot::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn right_clicked( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/ArmorStand;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRightClicked", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::ArmorStand::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerTeleportEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerArmorStandManipulateEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerMoveEvent ( ['getCause', 'getHandlers', 'getHandlerList']) - /// Gets the cancellation state of this event. A cancelled event will not - /// be executed in the server, but will still pass to other plugins - /// - /// If a move or teleport event is cancelled, the player will be moved or - /// teleported back to the Location as defined by getFrom(). This will not - /// fire an event + // SUPER CLASS: org.bukkit.event.player.PlayerInteractEntityEvent ( ['getPlayerItem', 'getArmorStandItem', 'getSlot', 'getHand', 'getRightClicked', 'getHandlers', 'getHandlerList']) + pub fn is_cancelled(&self) -> Result> { - let temp_clone = crate::event::player::PlayerMoveEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerMoveEvent = temp_clone.into(); + let temp_clone = + crate::event::player::PlayerInteractEntityEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerInteractEntityEvent = temp_clone.into(); real.is_cancelled() } - /// Sets the cancellation state of this event. A cancelled event will not - /// be executed in the server, but will still pass to other plugins - /// - /// If a move or teleport event is cancelled, the player will be moved or - /// teleported back to the Location as defined by getFrom(). This will not - /// fire an event + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let temp_clone = crate::event::player::PlayerMoveEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerMoveEvent = temp_clone.into(); + let temp_clone = + crate::event::player::PlayerInteractEntityEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerInteractEntityEvent = temp_clone.into(); real.set_cancelled(cancel) } - /// Gets the location this player moved from - pub fn from(&self) -> Result, Box> { - let temp_clone = crate::event::player::PlayerMoveEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerMoveEvent = temp_clone.into(); - real.from() - } - /// Sets the location to mark as where the player moved from - pub fn set_from( - &self, - from: impl Into>, - ) -> Result<(), Box> { - let temp_clone = crate::event::player::PlayerMoveEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerMoveEvent = temp_clone.into(); - real.set_from(from) - } - /// Gets the location this player moved to - pub fn to(&self) -> Result>, Box> { - let temp_clone = crate::event::player::PlayerMoveEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerMoveEvent = temp_clone.into(); - real.to() - } - /// Sets the location that this player will move to - pub fn set_to( - &self, - to: impl Into>, - ) -> Result<(), Box> { - let temp_clone = crate::event::player::PlayerMoveEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerMoveEvent = temp_clone.into(); - real.set_to(to) - } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerTeleportEvent<'mc> { - fn into(self) -> crate::event::player::PlayerMoveEvent<'mc> { - crate::event::player::PlayerMoveEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting PlayerTeleportEvent into crate::event::player::PlayerMoveEvent", - ) - } -} -pub enum PlayerTeleportEventTeleportCause<'mc> {} -impl<'mc> std::fmt::Display for PlayerTeleportEventTeleportCause<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> PlayerTeleportEventTeleportCause<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/event/player/PlayerTeleportEvent/TeleportCause"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } +impl<'mc> Into> + for PlayerArmorStandManipulateEvent<'mc> +{ + fn into(self) -> crate::event::player::PlayerInteractEntityEvent<'mc> { + crate::event::player::PlayerInteractEntityEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting PlayerArmorStandManipulateEvent into crate::event::player::PlayerInteractEntityEvent") } } - #[repr(C)] -pub struct PlayerTeleportEventTeleportCauseStruct<'mc>( +pub struct PlayerDropItemEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerTeleportEventTeleportCause<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for PlayerTeleportEventTeleportCause<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PlayerTeleportEventTeleportCause from null object." - ) - .into()); - } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/event/player/PlayerTeleportEvent/TeleportCause", - )?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerTeleportEventTeleportCause object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for PlayerTeleportEventTeleportCauseStruct<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerDropItemEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -9524,165 +9956,64 @@ impl<'mc> JNIRaw<'mc> for PlayerTeleportEventTeleportCauseStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerTeleportEventTeleportCauseStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerDropItemEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PlayerTeleportEventTeleportCauseStruct from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate PlayerDropItemEvent from null object.").into(), + ); } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/event/player/PlayerTeleportEvent/TeleportCause", - )?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/player/PlayerDropItemEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerTeleportEventTeleportCauseStruct object, got {}", - name - ) - .into()) + "Invalid argument passed. Expected a PlayerDropItemEvent object, got {}", + name + ) + .into()) } else { Ok(Self(env.clone(), obj)) } } } -impl<'mc> PlayerTeleportEventTeleportCauseStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result< - crate::event::player::PlayerTeleportEventTeleportCause<'mc>, - Box, - > { - let sig = String::from("()Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerTeleportEvent/TeleportCause"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::player::PlayerTeleportEventTeleportCause::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct PlayerItemConsumeEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PlayerItemConsumeEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PlayerItemConsumeEvent<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PlayerItemConsumeEvent from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerItemConsumeEvent")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerItemConsumeEvent object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> PlayerItemConsumeEvent<'mc> { - pub fn new( +impl<'mc> PlayerDropItemEvent<'mc> { + pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, player: impl Into>, - item: impl Into>, - hand: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Player;"; + drop: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/entity/Item;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); - args.push(val_1); - sig += "Lorg/bukkit/inventory/ItemStack;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(drop.into().jni_object().clone()) }); - args.push(val_2); - if let Some(a) = hand { - sig += "Lorg/bukkit/inventory/EquipmentSlot;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_3); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/event/player/PlayerItemConsumeEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerDropItemEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerItemConsumeEvent::from_raw(&jni, res) - } - /// Gets the item that is being consumed. Modifying the returned item will - /// have no effect, you must use {@link - /// #setItem(org.bukkit.inventory.ItemStack)} instead. - pub fn item(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Set the item being consumed - pub fn set_item( - &self, - item: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setItem", + let res = jni.new_object( + cls, sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = jni.translate_error_no_gen(res)?; + crate::event::player::PlayerDropItemEvent::from_raw(&jni, res) } - /// Get the hand used to consume the item. - pub fn hand(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/EquipmentSlot;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHand", sig.as_str(), vec![]); + /// Gets the ItemDrop created by the player + pub fn item_drop(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Item;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemDrop", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::EquipmentSlot::from_raw(&self.jni_ref(), unsafe { + crate::entity::Item::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -9724,14 +10055,14 @@ impl<'mc> PlayerItemConsumeEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerItemConsumeEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerDropItemEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getItem', 'setItem', 'getHand', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getItemDrop', 'isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -9746,26 +10077,25 @@ impl<'mc> PlayerItemConsumeEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerItemConsumeEvent<'mc> { +impl<'mc> Into> for PlayerDropItemEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerItemConsumeEvent into crate::event::Cancellable") + .expect("Error converting PlayerDropItemEvent into crate::event::Cancellable") } } -impl<'mc> Into> for PlayerItemConsumeEvent<'mc> { +impl<'mc> Into> for PlayerDropItemEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { - crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting PlayerItemConsumeEvent into crate::event::player::PlayerEvent", - ) + crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerDropItemEvent into crate::event::player::PlayerEvent") } } #[repr(C)] -pub struct PlayerInteractEvent<'mc>( +pub struct PlayerQuitEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerInteractEvent<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerQuitEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -9773,21 +10103,20 @@ impl<'mc> JNIRaw<'mc> for PlayerInteractEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerInteractEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerQuitEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate PlayerInteractEvent from null object.").into(), + eyre::eyre!("Tried to instantiate PlayerQuitEvent from null object.").into(), ); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/player/PlayerInteractEvent")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/player/PlayerQuitEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerInteractEvent object, got {}", + "Invalid argument passed. Expected a PlayerQuitEvent object, got {}", name ) .into()) @@ -9797,300 +10126,67 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerInteractEvent<'mc> { } } -impl<'mc> PlayerInteractEvent<'mc> { +impl<'mc> PlayerQuitEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, who: impl Into>, - action: impl Into>, - item: impl Into>, - clicked_block: impl Into>, - clicked_face: impl Into>, - hand: std::option::Option>>, - clicked_position: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Player;"; + quit_message: impl Into, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/Player;Ljava/lang/String;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(who.into().jni_object().clone()) }); - args.push(val_1); - sig += "Lorg/bukkit/event/block/Action;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(action.into().jni_object().clone()) - }); - args.push(val_2); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - args.push(val_3); - sig += "Lorg/bukkit/block/Block;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(clicked_block.into().jni_object().clone()) - }); - args.push(val_4); - sig += "Lorg/bukkit/block/BlockFace;"; - let val_5 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(clicked_face.into().jni_object().clone()) - }); - args.push(val_5); - if let Some(a) = hand { - sig += "Lorg/bukkit/inventory/EquipmentSlot;"; - let val_6 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_6); - } - if let Some(a) = clicked_position { - sig += "Lorg/bukkit/util/Vector;"; - let val_7 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_7); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/event/player/PlayerInteractEvent"); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(quit_message.into())?, + )); + let cls = jni.find_class("org/bukkit/event/player/PlayerQuitEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerInteractEvent::from_raw(&jni, res) - } - /// Returns the action type - pub fn action(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/block/Action;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getAction", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::block::Action::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + crate::event::player::PlayerQuitEvent::from_raw(&jni, res) } - #[deprecated] - /// Gets the cancellation state of this event. Set to true if you want to prevent buckets from placing water and so forth - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the quit message to send to all online players + pub fn quit_message(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getQuitMessage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Sets the cancellation state of this event. A canceled event will not be - /// executed in the server, but will still pass to other plugins - /// - /// Canceling this event will prevent use of food (player won't lose the - /// food item), prevent bows/snowballs/eggs from firing, etc. (player won't - /// lose the ammo) - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns the item in hand represented by this event - pub fn item( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Convenience method. Returns the material of the item represented by - /// this event - pub fn material(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaterial", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Check if this event involved a block - pub fn has_block(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasBlock", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Check if this event involved an item - pub fn has_item(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasItem", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Convenience method to inform the user whether this was a block - /// placement event. - pub fn is_block_in_hand(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isBlockInHand", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the clicked block - pub fn clicked_block( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getClickedBlock", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::block::Block::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Returns the face of the block that was clicked - pub fn block_face(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBlockFace", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// This controls the action to take with the block (if any) that was - /// clicked on. This event gets processed for all blocks, but most don't - /// have a default action - pub fn use_interacted_block( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/Event/Result;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "useInteractedBlock", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::event::EventResult::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn set_use_interacted_block( - &self, - use_interacted_block: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/Event/Result;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(use_interacted_block.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setUseInteractedBlock", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// This controls the action to take with the item the player is holding. - /// This includes both blocks and items (such as flint and steel or - /// records). When this is set to default, it will be allowed if no action - /// is taken on the interacted block. - pub fn use_item_in_hand( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/Event/Result;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "useItemInHand", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::EventResult::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn set_use_item_in_hand( + /// Sets the quit message to send to all online players + pub fn set_quit_message( &self, - use_item_in_hand: impl Into>, + quit_message: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/Event/Result;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(use_item_in_hand.into().jni_object().clone()) - }); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(quit_message.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setUseItemInHand", + "setQuitMessage", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// The hand used to perform this interaction. May be null in the case of - /// {@link Action#PHYSICAL}. - pub fn hand( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/EquipmentSlot;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHand", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::EquipmentSlot::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Gets the exact position on the block the player interacted with, this will - /// be null outside of {@link Action#RIGHT_CLICK_BLOCK}. - /// - /// All vector components are between 0.0 and 1.0 inclusive. - pub fn clicked_position( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getClickedPosition", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::util::Vector::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } pub fn handlers(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); @@ -10107,14 +10203,14 @@ impl<'mc> PlayerInteractEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/player/PlayerInteractEvent"); + let cls = jni.find_class("org/bukkit/event/player/PlayerQuitEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getAction', 'isCancelled', 'setCancelled', 'getItem', 'getMaterial', 'hasBlock', 'hasItem', 'isBlockInHand', 'getClickedBlock', 'getBlockFace', 'useInteractedBlock', 'setUseInteractedBlock', 'useItemInHand', 'setUseItemInHand', 'getHand', 'getClickedPosition', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getQuitMessage', 'setQuitMessage', 'getHandlers', 'getHandlerList']) /// Returns the player involved in this event pub fn player(&self) -> Result, Box> { let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { @@ -10129,16 +10225,1244 @@ impl<'mc> PlayerInteractEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerInteractEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerInteractEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for PlayerInteractEvent<'mc> { +impl<'mc> Into> for PlayerQuitEvent<'mc> { fn into(self) -> crate::event::player::PlayerEvent<'mc> { crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerInteractEvent into crate::event::player::PlayerEvent") + .expect("Error converting PlayerQuitEvent into crate::event::player::PlayerEvent") + } +} +#[repr(C)] +pub struct PlayerLevelChangeEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PlayerLevelChangeEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PlayerLevelChangeEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate PlayerLevelChangeEvent from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/player/PlayerLevelChangeEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PlayerLevelChangeEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> PlayerLevelChangeEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + player: impl Into>, + old_level: i32, + new_level: i32, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/Player;II)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(player.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(old_level); + let val_3 = jni::objects::JValueGen::Int(new_level); + let cls = jni.find_class("org/bukkit/event/player/PlayerLevelChangeEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::event::player::PlayerLevelChangeEvent::from_raw(&jni, res) + } + /// Gets the old level of the player + pub fn old_level(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getOldLevel", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the new level of the player + pub fn new_level(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getNewLevel", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/player/PlayerLevelChangeEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getOldLevel', 'getNewLevel', 'getHandlers', 'getHandlerList']) + /// Returns the player involved in this event + pub fn player(&self) -> Result, Box> { + let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerEvent = temp_clone.into(); + real.player() + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for PlayerLevelChangeEvent<'mc> { + fn into(self) -> crate::event::player::PlayerEvent<'mc> { + crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting PlayerLevelChangeEvent into crate::event::player::PlayerEvent", + ) + } +} +#[repr(C)] +pub struct PlayerRecipeBookSettingsChangeEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PlayerRecipeBookSettingsChangeEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PlayerRecipeBookSettingsChangeEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate PlayerRecipeBookSettingsChangeEvent from null object." + ) + .into()); + } + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/event/player/PlayerRecipeBookSettingsChangeEvent", + )?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PlayerRecipeBookSettingsChangeEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> PlayerRecipeBookSettingsChangeEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + player: impl Into>, + recipe_book_type: impl Into< + crate::event::player::PlayerRecipeBookSettingsChangeEventRecipeBookType<'mc>, + >, + open: bool, + filtering: bool, + ) -> Result< + crate::event::player::PlayerRecipeBookSettingsChangeEvent<'mc>, + Box, + > { + let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/event/player/PlayerRecipeBookSettingsChangeEvent/RecipeBookType;ZZ)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(player.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(recipe_book_type.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Bool(open.into()); + let val_4 = jni::objects::JValueGen::Bool(filtering.into()); + let cls = jni.find_class("org/bukkit/event/player/PlayerRecipeBookSettingsChangeEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::event::player::PlayerRecipeBookSettingsChangeEvent::from_raw(&jni, res) + } + /// Gets the type of recipe book the player is changing the settings for. + pub fn recipe_book_type( + &self, + ) -> Result< + crate::event::player::PlayerRecipeBookSettingsChangeEventRecipeBookType<'mc>, + Box, + > { + let sig = String::from( + "()Lorg/bukkit/event/player/PlayerRecipeBookSettingsChangeEvent/RecipeBookType;", + ); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getRecipeBookType", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::event::player::PlayerRecipeBookSettingsChangeEventRecipeBookType::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + ) + } + /// Checks if the recipe book is being opened or closed. + pub fn is_open(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isOpen", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks if the recipe book filter is being enabled or disabled. + pub fn is_filtering(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isFiltering", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/player/PlayerRecipeBookSettingsChangeEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getRecipeBookType', 'isOpen', 'isFiltering', 'getHandlers', 'getHandlerList']) + /// Returns the player involved in this event + pub fn player(&self) -> Result, Box> { + let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerEvent = temp_clone.into(); + real.player() + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> + for PlayerRecipeBookSettingsChangeEvent<'mc> +{ + fn into(self) -> crate::event::player::PlayerEvent<'mc> { + crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting PlayerRecipeBookSettingsChangeEvent into crate::event::player::PlayerEvent") + } +} +pub enum PlayerRecipeBookSettingsChangeEventRecipeBookType<'mc> { + Crafting { + inner: PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct<'mc>, + }, + Furnace { + inner: PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct<'mc>, + }, + BlastFurnace { + inner: PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct<'mc>, + }, + Smoker { + inner: PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for PlayerRecipeBookSettingsChangeEventRecipeBookType<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PlayerRecipeBookSettingsChangeEventRecipeBookType::Crafting { .. } => { + f.write_str("CRAFTING") + } + PlayerRecipeBookSettingsChangeEventRecipeBookType::Furnace { .. } => { + f.write_str("FURNACE") + } + PlayerRecipeBookSettingsChangeEventRecipeBookType::BlastFurnace { .. } => { + f.write_str("BLAST_FURNACE") + } + PlayerRecipeBookSettingsChangeEventRecipeBookType::Smoker { .. } => { + f.write_str("SMOKER") + } + } + } +} +impl<'mc> std::ops::Deref for PlayerRecipeBookSettingsChangeEventRecipeBookType<'mc> { + type Target = PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct<'mc>; + fn deref( + &self, + ) -> & as std::ops::Deref>::Target { + match self { + PlayerRecipeBookSettingsChangeEventRecipeBookType::Crafting { inner } => inner, + PlayerRecipeBookSettingsChangeEventRecipeBookType::Furnace { inner } => inner, + PlayerRecipeBookSettingsChangeEventRecipeBookType::BlastFurnace { inner } => inner, + PlayerRecipeBookSettingsChangeEventRecipeBookType::Smoker { inner } => inner, + } + } +} + +impl<'mc> PlayerRecipeBookSettingsChangeEventRecipeBookType<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> + { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class( + "org/bukkit/event/player/PlayerRecipeBookSettingsChangeEvent/RecipeBookType", + ); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/event/player/PlayerRecipeBookSettingsChangeEvent/RecipeBookType;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "CRAFTING" => Ok( + PlayerRecipeBookSettingsChangeEventRecipeBookType::Crafting { + inner: PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct::from_raw( + env, obj, + )?, + }, + ), + "FURNACE" => Ok(PlayerRecipeBookSettingsChangeEventRecipeBookType::Furnace { + inner: PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct::from_raw(env, obj)?, + }), + "BLAST_FURNACE" => Ok( + PlayerRecipeBookSettingsChangeEventRecipeBookType::BlastFurnace { + inner: PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct::from_raw( + env, obj, + )?, + }, + ), + "SMOKER" => Ok(PlayerRecipeBookSettingsChangeEventRecipeBookType::Smoker { + inner: PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PlayerRecipeBookSettingsChangeEventRecipeBookType<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Crafting { inner } => inner.0.clone(), + Self::Furnace { inner } => inner.0.clone(), + Self::BlastFurnace { inner } => inner.0.clone(), + Self::Smoker { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Crafting { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Furnace { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BlastFurnace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Smoker { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for PlayerRecipeBookSettingsChangeEventRecipeBookType<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate PlayerRecipeBookSettingsChangeEventRecipeBookType from null object.") + .into()); + } + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/event/player/PlayerRecipeBookSettingsChangeEvent/RecipeBookType", + )?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PlayerRecipeBookSettingsChangeEventRecipeBookType object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "CRAFTING" => Ok( + PlayerRecipeBookSettingsChangeEventRecipeBookType::Crafting { + inner: PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct::from_raw( + env, obj, + )?, + }, + ), + "FURNACE" => Ok(PlayerRecipeBookSettingsChangeEventRecipeBookType::Furnace { + inner: PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct::from_raw( + env, obj, + )?, + }), + "BLAST_FURNACE" => Ok( + PlayerRecipeBookSettingsChangeEventRecipeBookType::BlastFurnace { + inner: PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct::from_raw( + env, obj, + )?, + }, + ), + "SMOKER" => Ok(PlayerRecipeBookSettingsChangeEventRecipeBookType::Smoker { + inner: PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct::from_raw( + env, obj, + )?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct from null object.") + .into()); + } + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/event/player/PlayerRecipeBookSettingsChangeEvent/RecipeBookType", + )?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> PlayerRecipeBookSettingsChangeEventRecipeBookTypeStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result< + crate::event::player::PlayerRecipeBookSettingsChangeEventRecipeBookType<'mc>, + Box, + > { + let sig = String::from( + "()Lorg/bukkit/event/player/PlayerRecipeBookSettingsChangeEvent/RecipeBookType;", + ); + let cls = jni.find_class( + "org/bukkit/event/player/PlayerRecipeBookSettingsChangeEvent/RecipeBookType", + ); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::player::PlayerRecipeBookSettingsChangeEventRecipeBookType::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct PlayerBucketFishEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PlayerBucketFishEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PlayerBucketFishEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate PlayerBucketFishEvent from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/player/PlayerBucketFishEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PlayerBucketFishEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> PlayerBucketFishEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + player: impl Into>, + fish: impl Into>, + water_bucket: impl Into>, + fish_bucket: impl Into>, + hand: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/Player;Lorg/bukkit/entity/Fish;Lorg/bukkit/inventory/ItemStack;Lorg/bukkit/inventory/ItemStack;Lorg/bukkit/inventory/EquipmentSlot;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(player.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(fish.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(water_bucket.into().jni_object().clone()) + }); + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(fish_bucket.into().jni_object().clone()) + }); + let val_5 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(hand.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/player/PlayerBucketFishEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + jni::objects::JValueGen::from(val_5), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::event::player::PlayerBucketFishEvent::from_raw(&jni, res) + } + /// Gets the fish involved with this event. + pub fn entity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Fish;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Fish::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + #[deprecated] + /// Gets the bucket used. This refers to the bucket clicked with, ie {@link Material#WATER_BUCKET}. + pub fn water_bucket( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getWaterBucket", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + #[deprecated] + /// Gets the bucket that the fish will be put into. This refers to the bucket with the fish, ie {@link Material#PUFFERFISH_BUCKET}. + pub fn fish_bucket( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFishBucket", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + // SUPER CLASS: org.bukkit.event.player.PlayerBucketEntityEvent ( ['getEntity', 'getWaterBucket', 'getFishBucket']) + /// Gets the bucket used to capture the {@link Entity}. + /// This refers to the bucket clicked with, eg {@link Material#WATER_BUCKET}. + pub fn original_bucket( + &self, + ) -> Result, Box> { + let temp_clone = + crate::event::player::PlayerBucketEntityEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerBucketEntityEvent = temp_clone.into(); + real.original_bucket() + } + /// Gets the bucket that the {@link Entity} will be put into. + /// This refers to the bucket with the entity, eg + /// {@link Material#PUFFERFISH_BUCKET}. + pub fn entity_bucket( + &self, + ) -> Result, Box> { + let temp_clone = + crate::event::player::PlayerBucketEntityEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerBucketEntityEvent = temp_clone.into(); + real.entity_bucket() + } + /// Get the hand that was used to bucket the entity. + pub fn hand(&self) -> Result, Box> { + let temp_clone = + crate::event::player::PlayerBucketEntityEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerBucketEntityEvent = temp_clone.into(); + real.hand() + } + + pub fn is_cancelled(&self) -> Result> { + let temp_clone = + crate::event::player::PlayerBucketEntityEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerBucketEntityEvent = temp_clone.into(); + real.is_cancelled() + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let temp_clone = + crate::event::player::PlayerBucketEntityEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerBucketEntityEvent = temp_clone.into(); + real.set_cancelled(cancel) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + crate::event::player::PlayerBucketEntityEvent::handler_list(jni) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for PlayerBucketFishEvent<'mc> { + fn into(self) -> crate::event::player::PlayerBucketEntityEvent<'mc> { + crate::event::player::PlayerBucketEntityEvent::from_raw(&self.jni_ref(), self.1).expect("Error converting PlayerBucketFishEvent into crate::event::player::PlayerBucketEntityEvent") + } +} +#[repr(C)] +pub struct PlayerTeleportEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PlayerTeleportEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PlayerTeleportEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate PlayerTeleportEvent from null object.").into(), + ); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/player/PlayerTeleportEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PlayerTeleportEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> PlayerTeleportEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + player: impl Into>, + from: impl Into>, + to: impl Into>, + cause: std::option::Option< + impl Into>, + >, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/Player;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(player.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Lorg/bukkit/Location;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(from.into().jni_object().clone()) + }); + args.push(val_2); + sig += "Lorg/bukkit/Location;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(to.into().jni_object().clone()) + }); + args.push(val_3); + if let Some(a) = cause { + sig += "Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_4); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/player/PlayerTeleportEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::event::player::PlayerTeleportEvent::from_raw(&jni, res) + } + /// Gets the cause of this teleportation event + pub fn cause( + &self, + ) -> Result< + crate::event::player::PlayerTeleportEventTeleportCause<'mc>, + Box, + > { + let sig = String::from("()Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCause", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::player::PlayerTeleportEventTeleportCause::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/player/PlayerTeleportEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.player.PlayerMoveEvent ( ['getCause', 'getHandlers', 'getHandlerList']) + /// Gets the cancellation state of this event. A cancelled event will not + /// be executed in the server, but will still pass to other plugins + /// + /// If a move or teleport event is cancelled, the player will be moved or + /// teleported back to the Location as defined by getFrom(). This will not + /// fire an event + pub fn is_cancelled(&self) -> Result> { + let temp_clone = crate::event::player::PlayerMoveEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerMoveEvent = temp_clone.into(); + real.is_cancelled() + } + /// Sets the cancellation state of this event. A cancelled event will not + /// be executed in the server, but will still pass to other plugins + /// + /// If a move or teleport event is cancelled, the player will be moved or + /// teleported back to the Location as defined by getFrom(). This will not + /// fire an event + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let temp_clone = crate::event::player::PlayerMoveEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerMoveEvent = temp_clone.into(); + real.set_cancelled(cancel) + } + /// Gets the location this player moved from + pub fn from(&self) -> Result, Box> { + let temp_clone = crate::event::player::PlayerMoveEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerMoveEvent = temp_clone.into(); + real.from() + } + /// Sets the location to mark as where the player moved from + pub fn set_from( + &self, + from: impl Into>, + ) -> Result<(), Box> { + let temp_clone = crate::event::player::PlayerMoveEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerMoveEvent = temp_clone.into(); + real.set_from(from) + } + /// Gets the location this player moved to + pub fn to(&self) -> Result>, Box> { + let temp_clone = crate::event::player::PlayerMoveEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerMoveEvent = temp_clone.into(); + real.to() + } + /// Sets the location that this player will move to + pub fn set_to( + &self, + to: impl Into>, + ) -> Result<(), Box> { + let temp_clone = crate::event::player::PlayerMoveEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::player::PlayerMoveEvent = temp_clone.into(); + real.set_to(to) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for PlayerTeleportEvent<'mc> { + fn into(self) -> crate::event::player::PlayerMoveEvent<'mc> { + crate::event::player::PlayerMoveEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting PlayerTeleportEvent into crate::event::player::PlayerMoveEvent", + ) + } +} +pub enum PlayerTeleportEventTeleportCause<'mc> { + EnderPearl { + inner: PlayerTeleportEventTeleportCauseStruct<'mc>, + }, + Command { + inner: PlayerTeleportEventTeleportCauseStruct<'mc>, + }, + Plugin { + inner: PlayerTeleportEventTeleportCauseStruct<'mc>, + }, + NetherPortal { + inner: PlayerTeleportEventTeleportCauseStruct<'mc>, + }, + EndPortal { + inner: PlayerTeleportEventTeleportCauseStruct<'mc>, + }, + Spectate { + inner: PlayerTeleportEventTeleportCauseStruct<'mc>, + }, + EndGateway { + inner: PlayerTeleportEventTeleportCauseStruct<'mc>, + }, + ChorusFruit { + inner: PlayerTeleportEventTeleportCauseStruct<'mc>, + }, + Dismount { + inner: PlayerTeleportEventTeleportCauseStruct<'mc>, + }, + ExitBed { + inner: PlayerTeleportEventTeleportCauseStruct<'mc>, + }, + Unknown { + inner: PlayerTeleportEventTeleportCauseStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for PlayerTeleportEventTeleportCause<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PlayerTeleportEventTeleportCause::EnderPearl { .. } => f.write_str("ENDER_PEARL"), + PlayerTeleportEventTeleportCause::Command { .. } => f.write_str("COMMAND"), + PlayerTeleportEventTeleportCause::Plugin { .. } => f.write_str("PLUGIN"), + PlayerTeleportEventTeleportCause::NetherPortal { .. } => f.write_str("NETHER_PORTAL"), + PlayerTeleportEventTeleportCause::EndPortal { .. } => f.write_str("END_PORTAL"), + PlayerTeleportEventTeleportCause::Spectate { .. } => f.write_str("SPECTATE"), + PlayerTeleportEventTeleportCause::EndGateway { .. } => f.write_str("END_GATEWAY"), + PlayerTeleportEventTeleportCause::ChorusFruit { .. } => f.write_str("CHORUS_FRUIT"), + PlayerTeleportEventTeleportCause::Dismount { .. } => f.write_str("DISMOUNT"), + PlayerTeleportEventTeleportCause::ExitBed { .. } => f.write_str("EXIT_BED"), + PlayerTeleportEventTeleportCause::Unknown { .. } => f.write_str("UNKNOWN"), + } + } +} +impl<'mc> std::ops::Deref for PlayerTeleportEventTeleportCause<'mc> { + type Target = PlayerTeleportEventTeleportCauseStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + PlayerTeleportEventTeleportCause::EnderPearl { inner } => inner, + PlayerTeleportEventTeleportCause::Command { inner } => inner, + PlayerTeleportEventTeleportCause::Plugin { inner } => inner, + PlayerTeleportEventTeleportCause::NetherPortal { inner } => inner, + PlayerTeleportEventTeleportCause::EndPortal { inner } => inner, + PlayerTeleportEventTeleportCause::Spectate { inner } => inner, + PlayerTeleportEventTeleportCause::EndGateway { inner } => inner, + PlayerTeleportEventTeleportCause::ChorusFruit { inner } => inner, + PlayerTeleportEventTeleportCause::Dismount { inner } => inner, + PlayerTeleportEventTeleportCause::ExitBed { inner } => inner, + PlayerTeleportEventTeleportCause::Unknown { inner } => inner, + } + } +} + +impl<'mc> PlayerTeleportEventTeleportCause<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/event/player/PlayerTeleportEvent/TeleportCause"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "ENDER_PEARL" => Ok(PlayerTeleportEventTeleportCause::EnderPearl { + inner: PlayerTeleportEventTeleportCauseStruct::from_raw(env, obj)?, + }), + "COMMAND" => Ok(PlayerTeleportEventTeleportCause::Command { + inner: PlayerTeleportEventTeleportCauseStruct::from_raw(env, obj)?, + }), + "PLUGIN" => Ok(PlayerTeleportEventTeleportCause::Plugin { + inner: PlayerTeleportEventTeleportCauseStruct::from_raw(env, obj)?, + }), + "NETHER_PORTAL" => Ok(PlayerTeleportEventTeleportCause::NetherPortal { + inner: PlayerTeleportEventTeleportCauseStruct::from_raw(env, obj)?, + }), + "END_PORTAL" => Ok(PlayerTeleportEventTeleportCause::EndPortal { + inner: PlayerTeleportEventTeleportCauseStruct::from_raw(env, obj)?, + }), + "SPECTATE" => Ok(PlayerTeleportEventTeleportCause::Spectate { + inner: PlayerTeleportEventTeleportCauseStruct::from_raw(env, obj)?, + }), + "END_GATEWAY" => Ok(PlayerTeleportEventTeleportCause::EndGateway { + inner: PlayerTeleportEventTeleportCauseStruct::from_raw(env, obj)?, + }), + "CHORUS_FRUIT" => Ok(PlayerTeleportEventTeleportCause::ChorusFruit { + inner: PlayerTeleportEventTeleportCauseStruct::from_raw(env, obj)?, + }), + "DISMOUNT" => Ok(PlayerTeleportEventTeleportCause::Dismount { + inner: PlayerTeleportEventTeleportCauseStruct::from_raw(env, obj)?, + }), + "EXIT_BED" => Ok(PlayerTeleportEventTeleportCause::ExitBed { + inner: PlayerTeleportEventTeleportCauseStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(PlayerTeleportEventTeleportCause::Unknown { + inner: PlayerTeleportEventTeleportCauseStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct PlayerTeleportEventTeleportCauseStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PlayerTeleportEventTeleportCause<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::EnderPearl { inner } => inner.0.clone(), + Self::Command { inner } => inner.0.clone(), + Self::Plugin { inner } => inner.0.clone(), + Self::NetherPortal { inner } => inner.0.clone(), + Self::EndPortal { inner } => inner.0.clone(), + Self::Spectate { inner } => inner.0.clone(), + Self::EndGateway { inner } => inner.0.clone(), + Self::ChorusFruit { inner } => inner.0.clone(), + Self::Dismount { inner } => inner.0.clone(), + Self::ExitBed { inner } => inner.0.clone(), + Self::Unknown { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::EnderPearl { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Command { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Plugin { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::NetherPortal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EndPortal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Spectate { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::EndGateway { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChorusFruit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Dismount { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ExitBed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Unknown { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for PlayerTeleportEventTeleportCause<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate PlayerTeleportEventTeleportCause from null object." + ) + .into()); + } + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/event/player/PlayerTeleportEvent/TeleportCause", + )?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PlayerTeleportEventTeleportCause object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "ENDER_PEARL" => Ok(PlayerTeleportEventTeleportCause::EnderPearl { + inner: PlayerTeleportEventTeleportCauseStruct::from_raw(env, obj)?, + }), + "COMMAND" => Ok(PlayerTeleportEventTeleportCause::Command { + inner: PlayerTeleportEventTeleportCauseStruct::from_raw(env, obj)?, + }), + "PLUGIN" => Ok(PlayerTeleportEventTeleportCause::Plugin { + inner: PlayerTeleportEventTeleportCauseStruct::from_raw(env, obj)?, + }), + "NETHER_PORTAL" => Ok(PlayerTeleportEventTeleportCause::NetherPortal { + inner: PlayerTeleportEventTeleportCauseStruct::from_raw(env, obj)?, + }), + "END_PORTAL" => Ok(PlayerTeleportEventTeleportCause::EndPortal { + inner: PlayerTeleportEventTeleportCauseStruct::from_raw(env, obj)?, + }), + "SPECTATE" => Ok(PlayerTeleportEventTeleportCause::Spectate { + inner: PlayerTeleportEventTeleportCauseStruct::from_raw(env, obj)?, + }), + "END_GATEWAY" => Ok(PlayerTeleportEventTeleportCause::EndGateway { + inner: PlayerTeleportEventTeleportCauseStruct::from_raw(env, obj)?, + }), + "CHORUS_FRUIT" => Ok(PlayerTeleportEventTeleportCause::ChorusFruit { + inner: PlayerTeleportEventTeleportCauseStruct::from_raw(env, obj)?, + }), + "DISMOUNT" => Ok(PlayerTeleportEventTeleportCause::Dismount { + inner: PlayerTeleportEventTeleportCauseStruct::from_raw(env, obj)?, + }), + "EXIT_BED" => Ok(PlayerTeleportEventTeleportCause::ExitBed { + inner: PlayerTeleportEventTeleportCauseStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(PlayerTeleportEventTeleportCause::Unknown { + inner: PlayerTeleportEventTeleportCauseStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for PlayerTeleportEventTeleportCauseStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PlayerTeleportEventTeleportCauseStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate PlayerTeleportEventTeleportCauseStruct from null object." + ) + .into()); + } + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/event/player/PlayerTeleportEvent/TeleportCause", + )?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PlayerTeleportEventTeleportCauseStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> PlayerTeleportEventTeleportCauseStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result< + crate::event::player::PlayerTeleportEventTeleportCause<'mc>, + Box, + > { + let sig = String::from("()Lorg/bukkit/event/player/PlayerTeleportEvent/TeleportCause;"); + let cls = jni.find_class("org/bukkit/event/player/PlayerTeleportEvent/TeleportCause"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::player::PlayerTeleportEventTeleportCause::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } } #[repr(C)] @@ -11707,10 +13031,65 @@ impl<'mc> Into> for PlayerResourcePackSta ) } } -pub enum PlayerResourcePackStatusEventStatus<'mc> {} +pub enum PlayerResourcePackStatusEventStatus<'mc> { + SuccessfullyLoaded { + inner: PlayerResourcePackStatusEventStatusStruct<'mc>, + }, + Declined { + inner: PlayerResourcePackStatusEventStatusStruct<'mc>, + }, + FailedDownload { + inner: PlayerResourcePackStatusEventStatusStruct<'mc>, + }, + Accepted { + inner: PlayerResourcePackStatusEventStatusStruct<'mc>, + }, + Downloaded { + inner: PlayerResourcePackStatusEventStatusStruct<'mc>, + }, + InvalidUrl { + inner: PlayerResourcePackStatusEventStatusStruct<'mc>, + }, + FailedReload { + inner: PlayerResourcePackStatusEventStatusStruct<'mc>, + }, + Discarded { + inner: PlayerResourcePackStatusEventStatusStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for PlayerResourcePackStatusEventStatus<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + PlayerResourcePackStatusEventStatus::SuccessfullyLoaded { .. } => { + f.write_str("SUCCESSFULLY_LOADED") + } + PlayerResourcePackStatusEventStatus::Declined { .. } => f.write_str("DECLINED"), + PlayerResourcePackStatusEventStatus::FailedDownload { .. } => { + f.write_str("FAILED_DOWNLOAD") + } + PlayerResourcePackStatusEventStatus::Accepted { .. } => f.write_str("ACCEPTED"), + PlayerResourcePackStatusEventStatus::Downloaded { .. } => f.write_str("DOWNLOADED"), + PlayerResourcePackStatusEventStatus::InvalidUrl { .. } => f.write_str("INVALID_URL"), + PlayerResourcePackStatusEventStatus::FailedReload { .. } => { + f.write_str("FAILED_RELOAD") + } + PlayerResourcePackStatusEventStatus::Discarded { .. } => f.write_str("DISCARDED"), + } + } +} +impl<'mc> std::ops::Deref for PlayerResourcePackStatusEventStatus<'mc> { + type Target = PlayerResourcePackStatusEventStatusStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + PlayerResourcePackStatusEventStatus::SuccessfullyLoaded { inner } => inner, + PlayerResourcePackStatusEventStatus::Declined { inner } => inner, + PlayerResourcePackStatusEventStatus::FailedDownload { inner } => inner, + PlayerResourcePackStatusEventStatus::Accepted { inner } => inner, + PlayerResourcePackStatusEventStatus::Downloaded { inner } => inner, + PlayerResourcePackStatusEventStatus::InvalidUrl { inner } => inner, + PlayerResourcePackStatusEventStatus::FailedReload { inner } => inner, + PlayerResourcePackStatusEventStatus::Discarded { inner } => inner, + } } } @@ -11737,6 +13116,31 @@ impl<'mc> PlayerResourcePackStatusEventStatus<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "SUCCESSFULLY_LOADED" => Ok(PlayerResourcePackStatusEventStatus::SuccessfullyLoaded { + inner: PlayerResourcePackStatusEventStatusStruct::from_raw(env, obj)?, + }), + "DECLINED" => Ok(PlayerResourcePackStatusEventStatus::Declined { + inner: PlayerResourcePackStatusEventStatusStruct::from_raw(env, obj)?, + }), + "FAILED_DOWNLOAD" => Ok(PlayerResourcePackStatusEventStatus::FailedDownload { + inner: PlayerResourcePackStatusEventStatusStruct::from_raw(env, obj)?, + }), + "ACCEPTED" => Ok(PlayerResourcePackStatusEventStatus::Accepted { + inner: PlayerResourcePackStatusEventStatusStruct::from_raw(env, obj)?, + }), + "DOWNLOADED" => Ok(PlayerResourcePackStatusEventStatus::Downloaded { + inner: PlayerResourcePackStatusEventStatusStruct::from_raw(env, obj)?, + }), + "INVALID_URL" => Ok(PlayerResourcePackStatusEventStatus::InvalidUrl { + inner: PlayerResourcePackStatusEventStatusStruct::from_raw(env, obj)?, + }), + "FAILED_RELOAD" => Ok(PlayerResourcePackStatusEventStatus::FailedReload { + inner: PlayerResourcePackStatusEventStatusStruct::from_raw(env, obj)?, + }), + "DISCARDED" => Ok(PlayerResourcePackStatusEventStatus::Discarded { + inner: PlayerResourcePackStatusEventStatusStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -11750,10 +13154,40 @@ pub struct PlayerResourcePackStatusEventStatusStruct<'mc>( impl<'mc> JNIRaw<'mc> for PlayerResourcePackStatusEventStatus<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::SuccessfullyLoaded { inner } => inner.0.clone(), + Self::Declined { inner } => inner.0.clone(), + Self::FailedDownload { inner } => inner.0.clone(), + Self::Accepted { inner } => inner.0.clone(), + Self::Downloaded { inner } => inner.0.clone(), + Self::InvalidUrl { inner } => inner.0.clone(), + Self::FailedReload { inner } => inner.0.clone(), + Self::Discarded { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::SuccessfullyLoaded { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Declined { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::FailedDownload { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Accepted { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Downloaded { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::InvalidUrl { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FailedReload { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Discarded { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } impl<'mc> JNIInstantiatable<'mc> for PlayerResourcePackStatusEventStatus<'mc> { @@ -11785,6 +13219,32 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerResourcePackStatusEventStatus<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "SUCCESSFULLY_LOADED" => { + Ok(PlayerResourcePackStatusEventStatus::SuccessfullyLoaded { + inner: PlayerResourcePackStatusEventStatusStruct::from_raw(env, obj)?, + }) + } + "DECLINED" => Ok(PlayerResourcePackStatusEventStatus::Declined { + inner: PlayerResourcePackStatusEventStatusStruct::from_raw(env, obj)?, + }), + "FAILED_DOWNLOAD" => Ok(PlayerResourcePackStatusEventStatus::FailedDownload { + inner: PlayerResourcePackStatusEventStatusStruct::from_raw(env, obj)?, + }), + "ACCEPTED" => Ok(PlayerResourcePackStatusEventStatus::Accepted { + inner: PlayerResourcePackStatusEventStatusStruct::from_raw(env, obj)?, + }), + "DOWNLOADED" => Ok(PlayerResourcePackStatusEventStatus::Downloaded { + inner: PlayerResourcePackStatusEventStatusStruct::from_raw(env, obj)?, + }), + "INVALID_URL" => Ok(PlayerResourcePackStatusEventStatus::InvalidUrl { + inner: PlayerResourcePackStatusEventStatusStruct::from_raw(env, obj)?, + }), + "FAILED_RELOAD" => Ok(PlayerResourcePackStatusEventStatus::FailedReload { + inner: PlayerResourcePackStatusEventStatusStruct::from_raw(env, obj)?, + }), + "DISCARDED" => Ok(PlayerResourcePackStatusEventStatus::Discarded { + inner: PlayerResourcePackStatusEventStatusStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -13291,241 +14751,6 @@ impl<'mc> Into> for PlayerToggleFlightEve } } #[repr(C)] -pub struct PlayerBucketEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PlayerBucketEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PlayerBucketEvent<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate PlayerBucketEvent from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/player/PlayerBucketEvent")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerBucketEvent object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> PlayerBucketEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - who: impl Into>, - block: impl Into>, - block_clicked: impl Into>, - block_face: impl Into>, - bucket: impl Into>, - item_in_hand: std::option::Option>>, - hand: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/Player;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(who.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/block/Block;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) - }); - args.push(val_2); - sig += "Lorg/bukkit/block/Block;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block_clicked.into().jni_object().clone()) - }); - args.push(val_3); - sig += "Lorg/bukkit/block/BlockFace;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block_face.into().jni_object().clone()) - }); - args.push(val_4); - sig += "Lorg/bukkit/Material;"; - let val_5 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(bucket.into().jni_object().clone()) - }); - args.push(val_5); - if let Some(a) = item_in_hand { - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_6 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_6); - } - if let Some(a) = hand { - sig += "Lorg/bukkit/inventory/EquipmentSlot;"; - let val_7 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_7); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/event/player/PlayerBucketEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::event::player::PlayerBucketEvent::from_raw(&jni, res) - } - /// Returns the bucket used in this event - pub fn bucket(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBucket", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the resulting item in hand after the bucket event - pub fn item_stack( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemStack", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Set the item in hand after the event - pub fn set_item_stack( - &self, - item_stack: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setItemStack", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the block involved in this event. - pub fn block(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Return the block clicked - pub fn block_clicked(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBlockClicked", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the face on the clicked block - pub fn block_face(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBlockFace", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the hand that was used in this event. - pub fn hand(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/EquipmentSlot;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHand", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::EquipmentSlot::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - // SUPER CLASS: org.bukkit.event.player.PlayerEvent ( ['getBucket', 'getItemStack', 'setItemStack', 'getBlock', 'getBlockClicked', 'getBlockFace', 'getHand', 'isCancelled', 'setCancelled']) - /// Returns the player involved in this event - pub fn player(&self) -> Result, Box> { - let temp_clone = crate::event::player::PlayerEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::player::PlayerEvent = temp_clone.into(); - real.player() - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for PlayerBucketEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerBucketEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for PlayerBucketEvent<'mc> { - fn into(self) -> crate::event::player::PlayerEvent<'mc> { - crate::event::player::PlayerEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerBucketEvent into crate::event::player::PlayerEvent") - } -} -#[repr(C)] pub struct AsyncPlayerChatEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, @@ -14256,10 +15481,29 @@ impl<'mc> Into> for PlayerSwapHandItemsEv ) } } -pub enum PlayerAnimationType<'mc> {} +pub enum PlayerAnimationType<'mc> { + ArmSwing { + inner: PlayerAnimationTypeStruct<'mc>, + }, + OffArmSwing { + inner: PlayerAnimationTypeStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for PlayerAnimationType<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + PlayerAnimationType::ArmSwing { .. } => f.write_str("ARM_SWING"), + PlayerAnimationType::OffArmSwing { .. } => f.write_str("OFF_ARM_SWING"), + } + } +} +impl<'mc> std::ops::Deref for PlayerAnimationType<'mc> { + type Target = PlayerAnimationTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + PlayerAnimationType::ArmSwing { inner } => inner, + PlayerAnimationType::OffArmSwing { inner } => inner, + } } } @@ -14286,6 +15530,13 @@ impl<'mc> PlayerAnimationType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "ARM_SWING" => Ok(PlayerAnimationType::ArmSwing { + inner: PlayerAnimationTypeStruct::from_raw(env, obj)?, + }), + "OFF_ARM_SWING" => Ok(PlayerAnimationType::OffArmSwing { + inner: PlayerAnimationTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -14299,10 +15550,18 @@ pub struct PlayerAnimationTypeStruct<'mc>( impl<'mc> JNIRaw<'mc> for PlayerAnimationType<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::ArmSwing { inner } => inner.0.clone(), + Self::OffArmSwing { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::ArmSwing { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::OffArmSwing { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } impl<'mc> JNIInstantiatable<'mc> for PlayerAnimationType<'mc> { @@ -14331,6 +15590,12 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerAnimationType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "ARM_SWING" => Ok(PlayerAnimationType::ArmSwing { + inner: PlayerAnimationTypeStruct::from_raw(env, obj)?, + }), + "OFF_ARM_SWING" => Ok(PlayerAnimationType::OffArmSwing { + inner: PlayerAnimationTypeStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } diff --git a/blackboxmc-rs-bukkit/src/event/raid/mod.rs b/blackboxmc-rs-bukkit/src/event/raid/mod.rs index 70a511e..ccc0d5d 100644 --- a/blackboxmc-rs-bukkit/src/event/raid/mod.rs +++ b/blackboxmc-rs-bukkit/src/event/raid/mod.rs @@ -127,10 +127,44 @@ impl<'mc> Into> for RaidStopEvent<'mc> { .expect("Error converting RaidStopEvent into crate::event::raid::RaidEvent") } } -pub enum RaidStopEventReason<'mc> {} +pub enum RaidStopEventReason<'mc> { + Peace { + inner: RaidStopEventReasonStruct<'mc>, + }, + Timeout { + inner: RaidStopEventReasonStruct<'mc>, + }, + Finished { + inner: RaidStopEventReasonStruct<'mc>, + }, + Unspawnable { + inner: RaidStopEventReasonStruct<'mc>, + }, + NotInVillage { + inner: RaidStopEventReasonStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for RaidStopEventReason<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + RaidStopEventReason::Peace { .. } => f.write_str("PEACE"), + RaidStopEventReason::Timeout { .. } => f.write_str("TIMEOUT"), + RaidStopEventReason::Finished { .. } => f.write_str("FINISHED"), + RaidStopEventReason::Unspawnable { .. } => f.write_str("UNSPAWNABLE"), + RaidStopEventReason::NotInVillage { .. } => f.write_str("NOT_IN_VILLAGE"), + } + } +} +impl<'mc> std::ops::Deref for RaidStopEventReason<'mc> { + type Target = RaidStopEventReasonStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + RaidStopEventReason::Peace { inner } => inner, + RaidStopEventReason::Timeout { inner } => inner, + RaidStopEventReason::Finished { inner } => inner, + RaidStopEventReason::Unspawnable { inner } => inner, + RaidStopEventReason::NotInVillage { inner } => inner, + } } } @@ -157,6 +191,22 @@ impl<'mc> RaidStopEventReason<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "PEACE" => Ok(RaidStopEventReason::Peace { + inner: RaidStopEventReasonStruct::from_raw(env, obj)?, + }), + "TIMEOUT" => Ok(RaidStopEventReason::Timeout { + inner: RaidStopEventReasonStruct::from_raw(env, obj)?, + }), + "FINISHED" => Ok(RaidStopEventReason::Finished { + inner: RaidStopEventReasonStruct::from_raw(env, obj)?, + }), + "UNSPAWNABLE" => Ok(RaidStopEventReason::Unspawnable { + inner: RaidStopEventReasonStruct::from_raw(env, obj)?, + }), + "NOT_IN_VILLAGE" => Ok(RaidStopEventReason::NotInVillage { + inner: RaidStopEventReasonStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -170,10 +220,26 @@ pub struct RaidStopEventReasonStruct<'mc>( impl<'mc> JNIRaw<'mc> for RaidStopEventReason<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Peace { inner } => inner.0.clone(), + Self::Timeout { inner } => inner.0.clone(), + Self::Finished { inner } => inner.0.clone(), + Self::Unspawnable { inner } => inner.0.clone(), + Self::NotInVillage { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Peace { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Timeout { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Finished { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Unspawnable { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NotInVillage { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } impl<'mc> JNIInstantiatable<'mc> for RaidStopEventReason<'mc> { @@ -202,6 +268,21 @@ impl<'mc> JNIInstantiatable<'mc> for RaidStopEventReason<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "PEACE" => Ok(RaidStopEventReason::Peace { + inner: RaidStopEventReasonStruct::from_raw(env, obj)?, + }), + "TIMEOUT" => Ok(RaidStopEventReason::Timeout { + inner: RaidStopEventReasonStruct::from_raw(env, obj)?, + }), + "FINISHED" => Ok(RaidStopEventReason::Finished { + inner: RaidStopEventReasonStruct::from_raw(env, obj)?, + }), + "UNSPAWNABLE" => Ok(RaidStopEventReason::Unspawnable { + inner: RaidStopEventReasonStruct::from_raw(env, obj)?, + }), + "NOT_IN_VILLAGE" => Ok(RaidStopEventReason::NotInVillage { + inner: RaidStopEventReasonStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } diff --git a/blackboxmc-rs-bukkit/src/event/server/mod.rs b/blackboxmc-rs-bukkit/src/event/server/mod.rs index 40754e4..d5294e9 100644 --- a/blackboxmc-rs-bukkit/src/event/server/mod.rs +++ b/blackboxmc-rs-bukkit/src/event/server/mod.rs @@ -3,6 +3,249 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] +pub struct ServerListPingEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ServerListPingEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for ServerListPingEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate ServerListPingEvent from null object.").into(), + ); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/server/ServerListPingEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ServerListPingEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> ServerListPingEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + hostname: impl Into, + address: jni::objects::JObject<'mc>, + motd: impl Into, + num_players: i32, + max_players: i32, + ) -> Result, Box> { + let sig = String::from("(Ljava/lang/String;Ljava/net/InetAddress;Ljava/lang/String;II)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(hostname.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(address); + let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(motd.into())?, + )); + let val_4 = jni::objects::JValueGen::Int(num_players); + let val_5 = jni::objects::JValueGen::Int(max_players); + let cls = jni.find_class("org/bukkit/event/server/ServerListPingEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + jni::objects::JValueGen::from(val_5), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::event::server::ServerListPingEvent::from_raw(&jni, res) + } + /// Gets the hostname that the player used to connect to the server, or + /// blank if unknown + pub fn hostname(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHostname", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Get the address the ping is coming from. + pub fn address(&self) -> Result, Box> { + let sig = String::from("()Ljava/net/InetAddress;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAddress", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) + } + /// Get the message of the day message. + pub fn motd(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getMotd", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Change the message of the day message. + pub fn set_motd(&self, motd: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(motd.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMotd", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the number of players sent. + pub fn num_players(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getNumPlayers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Get the maximum number of players sent. + pub fn max_players(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxPlayers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + #[deprecated] + /// Gets whether the server needs to send a preview of the chat to the client. + pub fn should_send_chat_previews(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "shouldSendChatPreviews", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set the maximum number of players sent. + pub fn set_max_players(&self, max_players: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(max_players); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaxPlayers", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets the server-icon sent to the client. + pub fn set_server_icon( + &self, + icon: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/util/CachedServerIcon;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(icon.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setServerIcon", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/server/ServerListPingEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + /// {@inheritDoc} + /// + /// Calling the {@link Iterator#remove()} method will force that particular + /// player to not be displayed on the player list, decrease the size + /// returned by {@link #getNumPlayers()}, and will not be returned again by + /// any new iterator. + /// + /// Note: The players here will not be shown in the server info if + /// {@link Bukkit#getHideOnlinePlayers()} is true. + pub fn iterator( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Iterator;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "iterator", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaIterator::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + // SUPER CLASS: org.bukkit.event.server.ServerEvent ( ['getHostname', 'getAddress', 'getMotd', 'setMotd', 'getNumPlayers', 'getMaxPlayers', 'shouldSendChatPreviews', 'setMaxPlayers', 'setServerIcon', 'getHandlers', 'getHandlerList', 'iterator']) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for ServerListPingEvent<'mc> { + fn into(self) -> crate::event::server::ServerEvent<'mc> { + crate::event::server::ServerEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ServerListPingEvent into crate::event::server::ServerEvent") + } +} +#[repr(C)] pub struct PluginEnableEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, @@ -1080,10 +1323,29 @@ impl<'mc> Into> for ServerLoadEvent<'mc> .expect("Error converting ServerLoadEvent into crate::event::server::ServerEvent") } } -pub enum ServerLoadEventLoadType<'mc> {} +pub enum ServerLoadEventLoadType<'mc> { + Startup { + inner: ServerLoadEventLoadTypeStruct<'mc>, + }, + Reload { + inner: ServerLoadEventLoadTypeStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for ServerLoadEventLoadType<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + ServerLoadEventLoadType::Startup { .. } => f.write_str("STARTUP"), + ServerLoadEventLoadType::Reload { .. } => f.write_str("RELOAD"), + } + } +} +impl<'mc> std::ops::Deref for ServerLoadEventLoadType<'mc> { + type Target = ServerLoadEventLoadTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + ServerLoadEventLoadType::Startup { inner } => inner, + ServerLoadEventLoadType::Reload { inner } => inner, + } } } @@ -1110,6 +1372,13 @@ impl<'mc> ServerLoadEventLoadType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "STARTUP" => Ok(ServerLoadEventLoadType::Startup { + inner: ServerLoadEventLoadTypeStruct::from_raw(env, obj)?, + }), + "RELOAD" => Ok(ServerLoadEventLoadType::Reload { + inner: ServerLoadEventLoadTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -1123,10 +1392,16 @@ pub struct ServerLoadEventLoadTypeStruct<'mc>( impl<'mc> JNIRaw<'mc> for ServerLoadEventLoadType<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Startup { inner } => inner.0.clone(), + Self::Reload { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Startup { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Reload { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for ServerLoadEventLoadType<'mc> { @@ -1156,6 +1431,12 @@ impl<'mc> JNIInstantiatable<'mc> for ServerLoadEventLoadType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "STARTUP" => Ok(ServerLoadEventLoadType::Startup { + inner: ServerLoadEventLoadTypeStruct::from_raw(env, obj)?, + }), + "RELOAD" => Ok(ServerLoadEventLoadType::Reload { + inner: ServerLoadEventLoadTypeStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -1318,249 +1599,6 @@ impl<'mc> Into> for ServerEvent<'mc> { } } #[repr(C)] -pub struct ServerListPingEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for ServerListPingEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for ServerListPingEvent<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate ServerListPingEvent from null object.").into(), - ); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/server/ServerListPingEvent")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ServerListPingEvent object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> ServerListPingEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - hostname: impl Into, - address: jni::objects::JObject<'mc>, - motd: impl Into, - num_players: i32, - max_players: i32, - ) -> Result, Box> { - let sig = String::from("(Ljava/lang/String;Ljava/net/InetAddress;Ljava/lang/String;II)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(hostname.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(address); - let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(motd.into())?, - )); - let val_4 = jni::objects::JValueGen::Int(num_players); - let val_5 = jni::objects::JValueGen::Int(max_players); - let cls = jni.find_class("org/bukkit/event/server/ServerListPingEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - jni::objects::JValueGen::from(val_5), - ], - ); - let res = jni.translate_error_no_gen(res)?; - crate::event::server::ServerListPingEvent::from_raw(&jni, res) - } - /// Gets the hostname that the player used to connect to the server, or - /// blank if unknown - pub fn hostname(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHostname", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Get the address the ping is coming from. - pub fn address(&self) -> Result, Box> { - let sig = String::from("()Ljava/net/InetAddress;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAddress", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) - } - /// Get the message of the day message. - pub fn motd(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getMotd", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Change the message of the day message. - pub fn set_motd(&self, motd: impl Into) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(motd.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMotd", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the number of players sent. - pub fn num_players(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getNumPlayers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Get the maximum number of players sent. - pub fn max_players(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaxPlayers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - #[deprecated] - /// Gets whether the server needs to send a preview of the chat to the client. - pub fn should_send_chat_previews(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "shouldSendChatPreviews", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Set the maximum number of players sent. - pub fn set_max_players(&self, max_players: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(max_players); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaxPlayers", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Sets the server-icon sent to the client. - pub fn set_server_icon( - &self, - icon: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/util/CachedServerIcon;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(icon.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setServerIcon", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn handler_list( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/server/ServerListPingEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - /// {@inheritDoc} - /// - /// Calling the {@link Iterator#remove()} method will force that particular - /// player to not be displayed on the player list, decrease the size - /// returned by {@link #getNumPlayers()}, and will not be returned again by - /// any new iterator. - /// - /// Note: The players here will not be shown in the server info if - /// {@link Bukkit#getHideOnlinePlayers()} is true. - pub fn iterator( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Iterator;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "iterator", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaIterator::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - // SUPER CLASS: org.bukkit.event.server.ServerEvent ( ['getHostname', 'getAddress', 'getMotd', 'setMotd', 'getNumPlayers', 'getMaxPlayers', 'shouldSendChatPreviews', 'setMaxPlayers', 'setServerIcon', 'getHandlers', 'getHandlerList', 'iterator']) - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for ServerListPingEvent<'mc> { - fn into(self) -> crate::event::server::ServerEvent<'mc> { - crate::event::server::ServerEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ServerListPingEvent into crate::event::server::ServerEvent") - } -} -#[repr(C)] pub struct RemoteServerCommandEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, diff --git a/blackboxmc-rs-bukkit/src/event/weather/mod.rs b/blackboxmc-rs-bukkit/src/event/weather/mod.rs index 8607bc7..9dac45d 100644 --- a/blackboxmc-rs-bukkit/src/event/weather/mod.rs +++ b/blackboxmc-rs-bukkit/src/event/weather/mod.rs @@ -3,313 +3,6 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] -pub struct LightningStrikeEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for LightningStrikeEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for LightningStrikeEvent<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate LightningStrikeEvent from null object.").into(), - ); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/weather/LightningStrikeEvent")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a LightningStrikeEvent object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> LightningStrikeEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - world: impl Into>, - bolt: impl Into>, - cause: std::option::Option< - impl Into>, - >, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/World;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/entity/LightningStrike;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(bolt.into().jni_object().clone()) - }); - args.push(val_2); - if let Some(a) = cause { - sig += "Lorg/bukkit/event/weather/LightningStrikeEvent/Cause;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_3); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/event/weather/LightningStrikeEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::event::weather::LightningStrikeEvent::from_raw(&jni, res) - } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the bolt which is striking the earth. - pub fn lightning( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/LightningStrike;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLightning", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::LightningStrike::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the cause of this lightning strike. - pub fn cause( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/event/weather/LightningStrikeEvent/Cause;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getCause", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::weather::LightningStrikeEventCause::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn handler_list( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/weather/LightningStrikeEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.weather.WeatherEvent ( ['isCancelled', 'setCancelled', 'getLightning', 'getCause', 'getHandlers', 'getHandlerList']) - /// Returns the World where this event is occurring - pub fn world(&self) -> Result, Box> { - let temp_clone = crate::event::weather::WeatherEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::weather::WeatherEvent = temp_clone.into(); - real.world() - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for LightningStrikeEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting LightningStrikeEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for LightningStrikeEvent<'mc> { - fn into(self) -> crate::event::weather::WeatherEvent<'mc> { - crate::event::weather::WeatherEvent::from_raw(&self.jni_ref(), self.1).expect( - "Error converting LightningStrikeEvent into crate::event::weather::WeatherEvent", - ) - } -} -pub enum LightningStrikeEventCause<'mc> {} -impl<'mc> std::fmt::Display for LightningStrikeEventCause<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> LightningStrikeEventCause<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/event/weather/LightningStrikeEvent/Cause"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/event/weather/LightningStrikeEvent/Cause;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct LightningStrikeEventCauseStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for LightningStrikeEventCause<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for LightningStrikeEventCause<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate LightningStrikeEventCause from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/weather/LightningStrikeEvent/Cause")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a LightningStrikeEventCause object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for LightningStrikeEventCauseStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for LightningStrikeEventCauseStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate LightningStrikeEventCauseStruct from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/weather/LightningStrikeEvent/Cause")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a LightningStrikeEventCauseStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> LightningStrikeEventCauseStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/event/weather/LightningStrikeEvent/Cause;"); - let cls = jni.find_class("org/bukkit/event/weather/LightningStrikeEvent/Cause"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::weather::LightningStrikeEventCause::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] pub struct WeatherEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, @@ -472,7 +165,150 @@ impl<'mc> WeatherChangeEvent<'mc> { jni::objects::JObject::from_raw(world.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Bool(to.into()); - let cls = jni.find_class("org/bukkit/event/weather/WeatherChangeEvent"); + let cls = jni.find_class("org/bukkit/event/weather/WeatherChangeEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::event::weather::WeatherChangeEvent::from_raw(&jni, res) + } + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the state of weather that the world is being set to + pub fn to_weather_state(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "toWeatherState", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/weather/WeatherChangeEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.weather.WeatherEvent ( ['isCancelled', 'setCancelled', 'toWeatherState', 'getHandlers', 'getHandlerList']) + /// Returns the World where this event is occurring + pub fn world(&self) -> Result, Box> { + let temp_clone = crate::event::weather::WeatherEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::weather::WeatherEvent = temp_clone.into(); + real.world() + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for WeatherChangeEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting WeatherChangeEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for WeatherChangeEvent<'mc> { + fn into(self) -> crate::event::weather::WeatherEvent<'mc> { + crate::event::weather::WeatherEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting WeatherChangeEvent into crate::event::weather::WeatherEvent") + } +} +#[repr(C)] +pub struct ThunderChangeEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ThunderChangeEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for ThunderChangeEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate ThunderChangeEvent from null object.").into(), + ); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/weather/ThunderChangeEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ThunderChangeEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> ThunderChangeEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + world: impl Into>, + to: bool, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/World;Z)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(world.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Bool(to.into()); + let cls = jni.find_class("org/bukkit/event/weather/ThunderChangeEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, @@ -483,7 +319,7 @@ impl<'mc> WeatherChangeEvent<'mc> { ], ); let res = jni.translate_error_no_gen(res)?; - crate::event::weather::WeatherChangeEvent::from_raw(&jni, res) + crate::event::weather::ThunderChangeEvent::from_raw(&jni, res) } pub fn is_cancelled(&self) -> Result> { @@ -507,12 +343,12 @@ impl<'mc> WeatherChangeEvent<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the state of weather that the world is being set to - pub fn to_weather_state(&self) -> Result> { + /// Gets the state of thunder that the world is being set to + pub fn to_thunder_state(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "toWeatherState", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "toThunderState", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } @@ -532,14 +368,14 @@ impl<'mc> WeatherChangeEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/weather/WeatherChangeEvent"); + let cls = jni.find_class("org/bukkit/event/weather/ThunderChangeEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.weather.WeatherEvent ( ['isCancelled', 'setCancelled', 'toWeatherState', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.weather.WeatherEvent ( ['isCancelled', 'setCancelled', 'toThunderState', 'getHandlers', 'getHandlerList']) /// Returns the World where this event is occurring pub fn world(&self) -> Result, Box> { let temp_clone = crate::event::weather::WeatherEvent::from_raw(&self.0, unsafe { @@ -554,25 +390,25 @@ impl<'mc> WeatherChangeEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for WeatherChangeEvent<'mc> { +impl<'mc> Into> for ThunderChangeEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting WeatherChangeEvent into crate::event::Cancellable") + .expect("Error converting ThunderChangeEvent into crate::event::Cancellable") } } -impl<'mc> Into> for WeatherChangeEvent<'mc> { +impl<'mc> Into> for ThunderChangeEvent<'mc> { fn into(self) -> crate::event::weather::WeatherEvent<'mc> { crate::event::weather::WeatherEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting WeatherChangeEvent into crate::event::weather::WeatherEvent") + .expect("Error converting ThunderChangeEvent into crate::event::weather::WeatherEvent") } } #[repr(C)] -pub struct ThunderChangeEvent<'mc>( +pub struct LightningStrikeEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ThunderChangeEvent<'mc> { +impl<'mc> JNIRaw<'mc> for LightningStrikeEvent<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -580,21 +416,21 @@ impl<'mc> JNIRaw<'mc> for ThunderChangeEvent<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ThunderChangeEvent<'mc> { +impl<'mc> JNIInstantiatable<'mc> for LightningStrikeEvent<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate ThunderChangeEvent from null object.").into(), + eyre::eyre!("Tried to instantiate LightningStrikeEvent from null object.").into(), ); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/event/weather/ThunderChangeEvent")?; + env.validate_name(&obj, "org/bukkit/event/weather/LightningStrikeEvent")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ThunderChangeEvent object, got {}", + "Invalid argument passed. Expected a LightningStrikeEvent object, got {}", name ) .into()) @@ -604,29 +440,40 @@ impl<'mc> JNIInstantiatable<'mc> for ThunderChangeEvent<'mc> { } } -impl<'mc> ThunderChangeEvent<'mc> { +impl<'mc> LightningStrikeEvent<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, world: impl Into>, - to: bool, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/World;Z)V"); + bolt: impl Into>, + cause: std::option::Option< + impl Into>, + >, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/World;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(world.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Bool(to.into()); - let cls = jni.find_class("org/bukkit/event/weather/ThunderChangeEvent"); + args.push(val_1); + sig += "Lorg/bukkit/entity/LightningStrike;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(bolt.into().jni_object().clone()) + }); + args.push(val_2); + if let Some(a) = cause { + sig += "Lorg/bukkit/event/weather/LightningStrikeEvent/Cause;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_3); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/event/weather/LightningStrikeEvent"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::event::weather::ThunderChangeEvent::from_raw(&jni, res) + crate::event::weather::LightningStrikeEvent::from_raw(&jni, res) } pub fn is_cancelled(&self) -> Result> { @@ -650,14 +497,32 @@ impl<'mc> ThunderChangeEvent<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the state of thunder that the world is being set to - pub fn to_thunder_state(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the bolt which is striking the earth. + pub fn lightning( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/LightningStrike;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "toThunderState", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLightning", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::LightningStrike::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the cause of this lightning strike. + pub fn cause( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/event/weather/LightningStrikeEvent/Cause;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCause", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::weather::LightningStrikeEventCause::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn handlers(&self) -> Result, Box> { @@ -675,14 +540,14 @@ impl<'mc> ThunderChangeEvent<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/weather/ThunderChangeEvent"); + let cls = jni.find_class("org/bukkit/event/weather/LightningStrikeEvent"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; crate::event::HandlerList::from_raw(&jni, obj) } - // SUPER CLASS: org.bukkit.event.weather.WeatherEvent ( ['isCancelled', 'setCancelled', 'toThunderState', 'getHandlers', 'getHandlerList']) + // SUPER CLASS: org.bukkit.event.weather.WeatherEvent ( ['isCancelled', 'setCancelled', 'getLightning', 'getCause', 'getHandlers', 'getHandlerList']) /// Returns the World where this event is occurring pub fn world(&self) -> Result, Box> { let temp_clone = crate::event::weather::WeatherEvent::from_raw(&self.0, unsafe { @@ -697,15 +562,268 @@ impl<'mc> ThunderChangeEvent<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for ThunderChangeEvent<'mc> { +impl<'mc> Into> for LightningStrikeEvent<'mc> { fn into(self) -> crate::event::Cancellable<'mc> { crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ThunderChangeEvent into crate::event::Cancellable") + .expect("Error converting LightningStrikeEvent into crate::event::Cancellable") } } -impl<'mc> Into> for ThunderChangeEvent<'mc> { +impl<'mc> Into> for LightningStrikeEvent<'mc> { fn into(self) -> crate::event::weather::WeatherEvent<'mc> { - crate::event::weather::WeatherEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ThunderChangeEvent into crate::event::weather::WeatherEvent") + crate::event::weather::WeatherEvent::from_raw(&self.jni_ref(), self.1).expect( + "Error converting LightningStrikeEvent into crate::event::weather::WeatherEvent", + ) + } +} +pub enum LightningStrikeEventCause<'mc> { + Command { + inner: LightningStrikeEventCauseStruct<'mc>, + }, + Custom { + inner: LightningStrikeEventCauseStruct<'mc>, + }, + Spawner { + inner: LightningStrikeEventCauseStruct<'mc>, + }, + Trident { + inner: LightningStrikeEventCauseStruct<'mc>, + }, + Trap { + inner: LightningStrikeEventCauseStruct<'mc>, + }, + Weather { + inner: LightningStrikeEventCauseStruct<'mc>, + }, + Enchantment { + inner: LightningStrikeEventCauseStruct<'mc>, + }, + Unknown { + inner: LightningStrikeEventCauseStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for LightningStrikeEventCause<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + LightningStrikeEventCause::Command { .. } => f.write_str("COMMAND"), + LightningStrikeEventCause::Custom { .. } => f.write_str("CUSTOM"), + LightningStrikeEventCause::Spawner { .. } => f.write_str("SPAWNER"), + LightningStrikeEventCause::Trident { .. } => f.write_str("TRIDENT"), + LightningStrikeEventCause::Trap { .. } => f.write_str("TRAP"), + LightningStrikeEventCause::Weather { .. } => f.write_str("WEATHER"), + LightningStrikeEventCause::Enchantment { .. } => f.write_str("ENCHANTMENT"), + LightningStrikeEventCause::Unknown { .. } => f.write_str("UNKNOWN"), + } + } +} +impl<'mc> std::ops::Deref for LightningStrikeEventCause<'mc> { + type Target = LightningStrikeEventCauseStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + LightningStrikeEventCause::Command { inner } => inner, + LightningStrikeEventCause::Custom { inner } => inner, + LightningStrikeEventCause::Spawner { inner } => inner, + LightningStrikeEventCause::Trident { inner } => inner, + LightningStrikeEventCause::Trap { inner } => inner, + LightningStrikeEventCause::Weather { inner } => inner, + LightningStrikeEventCause::Enchantment { inner } => inner, + LightningStrikeEventCause::Unknown { inner } => inner, + } + } +} + +impl<'mc> LightningStrikeEventCause<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/event/weather/LightningStrikeEvent/Cause"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/event/weather/LightningStrikeEvent/Cause;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "COMMAND" => Ok(LightningStrikeEventCause::Command { + inner: LightningStrikeEventCauseStruct::from_raw(env, obj)?, + }), + "CUSTOM" => Ok(LightningStrikeEventCause::Custom { + inner: LightningStrikeEventCauseStruct::from_raw(env, obj)?, + }), + "SPAWNER" => Ok(LightningStrikeEventCause::Spawner { + inner: LightningStrikeEventCauseStruct::from_raw(env, obj)?, + }), + "TRIDENT" => Ok(LightningStrikeEventCause::Trident { + inner: LightningStrikeEventCauseStruct::from_raw(env, obj)?, + }), + "TRAP" => Ok(LightningStrikeEventCause::Trap { + inner: LightningStrikeEventCauseStruct::from_raw(env, obj)?, + }), + "WEATHER" => Ok(LightningStrikeEventCause::Weather { + inner: LightningStrikeEventCauseStruct::from_raw(env, obj)?, + }), + "ENCHANTMENT" => Ok(LightningStrikeEventCause::Enchantment { + inner: LightningStrikeEventCauseStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(LightningStrikeEventCause::Unknown { + inner: LightningStrikeEventCauseStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct LightningStrikeEventCauseStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for LightningStrikeEventCause<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Command { inner } => inner.0.clone(), + Self::Custom { inner } => inner.0.clone(), + Self::Spawner { inner } => inner.0.clone(), + Self::Trident { inner } => inner.0.clone(), + Self::Trap { inner } => inner.0.clone(), + Self::Weather { inner } => inner.0.clone(), + Self::Enchantment { inner } => inner.0.clone(), + Self::Unknown { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Command { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Custom { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Spawner { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Trident { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Trap { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Weather { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Enchantment { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Unknown { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for LightningStrikeEventCause<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate LightningStrikeEventCause from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/weather/LightningStrikeEvent/Cause")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a LightningStrikeEventCause object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "COMMAND" => Ok(LightningStrikeEventCause::Command { + inner: LightningStrikeEventCauseStruct::from_raw(env, obj)?, + }), + "CUSTOM" => Ok(LightningStrikeEventCause::Custom { + inner: LightningStrikeEventCauseStruct::from_raw(env, obj)?, + }), + "SPAWNER" => Ok(LightningStrikeEventCause::Spawner { + inner: LightningStrikeEventCauseStruct::from_raw(env, obj)?, + }), + "TRIDENT" => Ok(LightningStrikeEventCause::Trident { + inner: LightningStrikeEventCauseStruct::from_raw(env, obj)?, + }), + "TRAP" => Ok(LightningStrikeEventCause::Trap { + inner: LightningStrikeEventCauseStruct::from_raw(env, obj)?, + }), + "WEATHER" => Ok(LightningStrikeEventCause::Weather { + inner: LightningStrikeEventCauseStruct::from_raw(env, obj)?, + }), + "ENCHANTMENT" => Ok(LightningStrikeEventCause::Enchantment { + inner: LightningStrikeEventCauseStruct::from_raw(env, obj)?, + }), + "UNKNOWN" => Ok(LightningStrikeEventCause::Unknown { + inner: LightningStrikeEventCauseStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for LightningStrikeEventCauseStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for LightningStrikeEventCauseStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate LightningStrikeEventCauseStruct from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/event/weather/LightningStrikeEvent/Cause")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a LightningStrikeEventCauseStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> LightningStrikeEventCauseStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/event/weather/LightningStrikeEvent/Cause;"); + let cls = jni.find_class("org/bukkit/event/weather/LightningStrikeEvent/Cause"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::weather::LightningStrikeEventCause::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } } diff --git a/blackboxmc-rs-bukkit/src/event/world/mod.rs b/blackboxmc-rs-bukkit/src/event/world/mod.rs index 28e8ca8..05f9160 100644 --- a/blackboxmc-rs-bukkit/src/event/world/mod.rs +++ b/blackboxmc-rs-bukkit/src/event/world/mod.rs @@ -3,134 +3,6 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] -pub struct WorldUnloadEvent<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for WorldUnloadEvent<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for WorldUnloadEvent<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate WorldUnloadEvent from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/event/world/WorldUnloadEvent")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a WorldUnloadEvent object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> WorldUnloadEvent<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - world: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/World;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/event/world/WorldUnloadEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error_no_gen(res)?; - crate::event::world::WorldUnloadEvent::from_raw(&jni, res) - } - - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(cancel.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCancelled", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn handlers(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn handler_list( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/HandlerList;"); - let cls = jni.find_class("org/bukkit/event/world/WorldUnloadEvent"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::event::HandlerList::from_raw(&jni, obj) - } - // SUPER CLASS: org.bukkit.event.world.WorldEvent ( ['isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) - /// Gets the world primarily involved with this event - pub fn world(&self) -> Result, Box> { - let temp_clone = crate::event::world::WorldEvent::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::event::world::WorldEvent = temp_clone.into(); - real.world() - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for WorldUnloadEvent<'mc> { - fn into(self) -> crate::event::Cancellable<'mc> { - crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting WorldUnloadEvent into crate::event::Cancellable") - } -} -impl<'mc> Into> for WorldUnloadEvent<'mc> { - fn into(self) -> crate::event::world::WorldEvent<'mc> { - crate::event::world::WorldEvent::from_raw(&self.jni_ref(), self.1) - .expect("Error converting WorldUnloadEvent into crate::event::world::WorldEvent") - } -} -#[repr(C)] pub struct LootGenerateEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, @@ -394,6 +266,134 @@ impl<'mc> Into> for LootGenerateEvent<'mc> } } #[repr(C)] +pub struct WorldUnloadEvent<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for WorldUnloadEvent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for WorldUnloadEvent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate WorldUnloadEvent from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/event/world/WorldUnloadEvent")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a WorldUnloadEvent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> WorldUnloadEvent<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + world: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/World;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(world.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/event/world/WorldUnloadEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error_no_gen(res)?; + crate::event::world::WorldUnloadEvent::from_raw(&jni, res) + } + + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_cancelled(&self, cancel: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(cancel.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCancelled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn handlers(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHandlers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::HandlerList::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn handler_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/HandlerList;"); + let cls = jni.find_class("org/bukkit/event/world/WorldUnloadEvent"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHandlerList", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::event::HandlerList::from_raw(&jni, obj) + } + // SUPER CLASS: org.bukkit.event.world.WorldEvent ( ['isCancelled', 'setCancelled', 'getHandlers', 'getHandlerList']) + /// Gets the world primarily involved with this event + pub fn world(&self) -> Result, Box> { + let temp_clone = crate::event::world::WorldEvent::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::event::world::WorldEvent = temp_clone.into(); + real.world() + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for WorldUnloadEvent<'mc> { + fn into(self) -> crate::event::Cancellable<'mc> { + crate::event::Cancellable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting WorldUnloadEvent into crate::event::Cancellable") + } +} +impl<'mc> Into> for WorldUnloadEvent<'mc> { + fn into(self) -> crate::event::world::WorldEvent<'mc> { + crate::event::world::WorldEvent::from_raw(&self.jni_ref(), self.1) + .expect("Error converting WorldUnloadEvent into crate::event::world::WorldEvent") + } +} +#[repr(C)] pub struct SpawnChangeEvent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, @@ -1354,10 +1354,34 @@ impl<'mc> Into> for PortalCreateEvent<'mc> .expect("Error converting PortalCreateEvent into crate::event::world::WorldEvent") } } -pub enum PortalCreateEventCreateReason<'mc> {} +pub enum PortalCreateEventCreateReason<'mc> { + Fire { + inner: PortalCreateEventCreateReasonStruct<'mc>, + }, + NetherPair { + inner: PortalCreateEventCreateReasonStruct<'mc>, + }, + EndPlatform { + inner: PortalCreateEventCreateReasonStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for PortalCreateEventCreateReason<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + PortalCreateEventCreateReason::Fire { .. } => f.write_str("FIRE"), + PortalCreateEventCreateReason::NetherPair { .. } => f.write_str("NETHER_PAIR"), + PortalCreateEventCreateReason::EndPlatform { .. } => f.write_str("END_PLATFORM"), + } + } +} +impl<'mc> std::ops::Deref for PortalCreateEventCreateReason<'mc> { + type Target = PortalCreateEventCreateReasonStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + PortalCreateEventCreateReason::Fire { inner } => inner, + PortalCreateEventCreateReason::NetherPair { inner } => inner, + PortalCreateEventCreateReason::EndPlatform { inner } => inner, + } } } @@ -1384,6 +1408,16 @@ impl<'mc> PortalCreateEventCreateReason<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "FIRE" => Ok(PortalCreateEventCreateReason::Fire { + inner: PortalCreateEventCreateReasonStruct::from_raw(env, obj)?, + }), + "NETHER_PAIR" => Ok(PortalCreateEventCreateReason::NetherPair { + inner: PortalCreateEventCreateReasonStruct::from_raw(env, obj)?, + }), + "END_PLATFORM" => Ok(PortalCreateEventCreateReason::EndPlatform { + inner: PortalCreateEventCreateReasonStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -1397,10 +1431,22 @@ pub struct PortalCreateEventCreateReasonStruct<'mc>( impl<'mc> JNIRaw<'mc> for PortalCreateEventCreateReason<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Fire { inner } => inner.0.clone(), + Self::NetherPair { inner } => inner.0.clone(), + Self::EndPlatform { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Fire { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::NetherPair { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EndPlatform { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } impl<'mc> JNIInstantiatable<'mc> for PortalCreateEventCreateReason<'mc> { @@ -1432,6 +1478,15 @@ impl<'mc> JNIInstantiatable<'mc> for PortalCreateEventCreateReason<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "FIRE" => Ok(PortalCreateEventCreateReason::Fire { + inner: PortalCreateEventCreateReasonStruct::from_raw(env, obj)?, + }), + "NETHER_PAIR" => Ok(PortalCreateEventCreateReason::NetherPair { + inner: PortalCreateEventCreateReasonStruct::from_raw(env, obj)?, + }), + "END_PLATFORM" => Ok(PortalCreateEventCreateReason::EndPlatform { + inner: PortalCreateEventCreateReasonStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -2300,10 +2355,36 @@ impl<'mc> Into> for AsyncStructureGenerateE ) } } -pub enum AsyncStructureGenerateEventCause<'mc> {} +pub enum AsyncStructureGenerateEventCause<'mc> { + Command { + inner: AsyncStructureGenerateEventCauseStruct<'mc>, + }, + WorldGeneration { + inner: AsyncStructureGenerateEventCauseStruct<'mc>, + }, + Custom { + inner: AsyncStructureGenerateEventCauseStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for AsyncStructureGenerateEventCause<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + AsyncStructureGenerateEventCause::Command { .. } => f.write_str("COMMAND"), + AsyncStructureGenerateEventCause::WorldGeneration { .. } => { + f.write_str("WORLD_GENERATION") + } + AsyncStructureGenerateEventCause::Custom { .. } => f.write_str("CUSTOM"), + } + } +} +impl<'mc> std::ops::Deref for AsyncStructureGenerateEventCause<'mc> { + type Target = AsyncStructureGenerateEventCauseStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + AsyncStructureGenerateEventCause::Command { inner } => inner, + AsyncStructureGenerateEventCause::WorldGeneration { inner } => inner, + AsyncStructureGenerateEventCause::Custom { inner } => inner, + } } } @@ -2330,6 +2411,16 @@ impl<'mc> AsyncStructureGenerateEventCause<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "COMMAND" => Ok(AsyncStructureGenerateEventCause::Command { + inner: AsyncStructureGenerateEventCauseStruct::from_raw(env, obj)?, + }), + "WORLD_GENERATION" => Ok(AsyncStructureGenerateEventCause::WorldGeneration { + inner: AsyncStructureGenerateEventCauseStruct::from_raw(env, obj)?, + }), + "CUSTOM" => Ok(AsyncStructureGenerateEventCause::Custom { + inner: AsyncStructureGenerateEventCauseStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -2343,10 +2434,20 @@ pub struct AsyncStructureGenerateEventCauseStruct<'mc>( impl<'mc> JNIRaw<'mc> for AsyncStructureGenerateEventCause<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Command { inner } => inner.0.clone(), + Self::WorldGeneration { inner } => inner.0.clone(), + Self::Custom { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Command { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::WorldGeneration { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Custom { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for AsyncStructureGenerateEventCause<'mc> { @@ -2378,6 +2479,15 @@ impl<'mc> JNIInstantiatable<'mc> for AsyncStructureGenerateEventCause<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "COMMAND" => Ok(AsyncStructureGenerateEventCause::Command { + inner: AsyncStructureGenerateEventCauseStruct::from_raw(env, obj)?, + }), + "WORLD_GENERATION" => Ok(AsyncStructureGenerateEventCause::WorldGeneration { + inner: AsyncStructureGenerateEventCauseStruct::from_raw(env, obj)?, + }), + "CUSTOM" => Ok(AsyncStructureGenerateEventCause::Custom { + inner: AsyncStructureGenerateEventCauseStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -3268,10 +3378,34 @@ impl<'mc> Into> for TimeSkipEvent<'mc> { .expect("Error converting TimeSkipEvent into crate::event::world::WorldEvent") } } -pub enum TimeSkipEventSkipReason<'mc> {} +pub enum TimeSkipEventSkipReason<'mc> { + Command { + inner: TimeSkipEventSkipReasonStruct<'mc>, + }, + Custom { + inner: TimeSkipEventSkipReasonStruct<'mc>, + }, + NightSkip { + inner: TimeSkipEventSkipReasonStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for TimeSkipEventSkipReason<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + TimeSkipEventSkipReason::Command { .. } => f.write_str("COMMAND"), + TimeSkipEventSkipReason::Custom { .. } => f.write_str("CUSTOM"), + TimeSkipEventSkipReason::NightSkip { .. } => f.write_str("NIGHT_SKIP"), + } + } +} +impl<'mc> std::ops::Deref for TimeSkipEventSkipReason<'mc> { + type Target = TimeSkipEventSkipReasonStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + TimeSkipEventSkipReason::Command { inner } => inner, + TimeSkipEventSkipReason::Custom { inner } => inner, + TimeSkipEventSkipReason::NightSkip { inner } => inner, + } } } @@ -3298,6 +3432,16 @@ impl<'mc> TimeSkipEventSkipReason<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "COMMAND" => Ok(TimeSkipEventSkipReason::Command { + inner: TimeSkipEventSkipReasonStruct::from_raw(env, obj)?, + }), + "CUSTOM" => Ok(TimeSkipEventSkipReason::Custom { + inner: TimeSkipEventSkipReasonStruct::from_raw(env, obj)?, + }), + "NIGHT_SKIP" => Ok(TimeSkipEventSkipReason::NightSkip { + inner: TimeSkipEventSkipReasonStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -3311,10 +3455,20 @@ pub struct TimeSkipEventSkipReasonStruct<'mc>( impl<'mc> JNIRaw<'mc> for TimeSkipEventSkipReason<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Command { inner } => inner.0.clone(), + Self::Custom { inner } => inner.0.clone(), + Self::NightSkip { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Command { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Custom { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::NightSkip { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } impl<'mc> JNIInstantiatable<'mc> for TimeSkipEventSkipReason<'mc> { @@ -3344,6 +3498,15 @@ impl<'mc> JNIInstantiatable<'mc> for TimeSkipEventSkipReason<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "COMMAND" => Ok(TimeSkipEventSkipReason::Command { + inner: TimeSkipEventSkipReasonStruct::from_raw(env, obj)?, + }), + "CUSTOM" => Ok(TimeSkipEventSkipReason::Custom { + inner: TimeSkipEventSkipReasonStruct::from_raw(env, obj)?, + }), + "NIGHT_SKIP" => Ok(TimeSkipEventSkipReason::NightSkip { + inner: TimeSkipEventSkipReasonStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } diff --git a/blackboxmc-rs-bukkit/src/help/mod.rs b/blackboxmc-rs-bukkit/src/help/mod.rs index 6a1db2f..d93e58e 100644 --- a/blackboxmc-rs-bukkit/src/help/mod.rs +++ b/blackboxmc-rs-bukkit/src/help/mod.rs @@ -3,12 +3,12 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] -pub struct HelpTopicFactory<'mc>( +pub struct IndexHelpTopic<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for HelpTopicFactory<'mc> { +impl<'mc> JNIRaw<'mc> for IndexHelpTopic<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -16,20 +16,20 @@ impl<'mc> JNIRaw<'mc> for HelpTopicFactory<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for HelpTopicFactory<'mc> { +impl<'mc> JNIInstantiatable<'mc> for IndexHelpTopic<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate HelpTopicFactory from null object.").into(), + eyre::eyre!("Tried to instantiate IndexHelpTopic from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/help/HelpTopicFactory")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/help/IndexHelpTopic")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a HelpTopicFactory object, got {}", + "Invalid argument passed. Expected a IndexHelpTopic object, got {}", name ) .into()) @@ -39,39 +39,98 @@ impl<'mc> JNIInstantiatable<'mc> for HelpTopicFactory<'mc> { } } -impl<'mc> HelpTopicFactory<'mc> { - pub fn from_extendable( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - plugin: &'mc crate::plugin::Plugin, - address: i32, - lib_name: String, - name: String, - ) -> Result> { - let obj = unsafe { plugin.new_extendable(address, "HelpTopicFactory", name, lib_name) }?; - Self::from_raw(env, obj) +impl<'mc> IndexHelpTopic<'mc> { + pub fn can_see( + &self, + sender: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/command/CommandSender;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "canSee", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// This method accepts a command deriving from a custom command base class - /// and constructs a custom HelpTopic for it. - pub fn create_topic( + + pub fn amend_can_see( &self, - command: jni::objects::JObject<'mc>, - ) -> Result>, Box> { - let sig = String::from("(LTCommand;)Lorg/bukkit/help/HelpTopic;"); - let val_1 = jni::objects::JValueGen::Object(command); + amended_permission: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(amended_permission.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "createTopic", + "amendCanSee", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn get_full_text( + &self, + sender: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/command/CommandSender;)Ljava/lang/String;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getFullText", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::help::HelpTopic::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + // SUPER CLASS: org.bukkit.help.HelpTopic ( ['canSee', 'amendCanSee', 'getFullText']) + /// Returns the name of this help topic. + pub fn name(&self) -> Result> { + let temp_clone = crate::help::HelpTopic::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::help::HelpTopic = temp_clone.into(); + real.name() + } + /// Returns a brief description that will be displayed in the topic index. + pub fn short_text(&self) -> Result> { + let temp_clone = crate::help::HelpTopic::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::help::HelpTopic = temp_clone.into(); + real.short_text() + } + /// Allows the server admin (or another plugin) to add or replace the + /// contents of a help topic. + /// + /// A null in either parameter will leave that part of the topic unchanged. + /// In either amending parameter, the string {@literal } is replaced + /// with the existing contents in the help topic. Use this to append or + /// prepend additional content into an automatically generated help topic. + pub fn amend_topic( + &self, + amended_short_text: impl Into, + amended_full_text: impl Into, + ) -> Result<(), Box> { + let temp_clone = crate::help::HelpTopic::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::help::HelpTopic = temp_clone.into(); + real.amend_topic(amended_short_text, amended_full_text) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -79,6 +138,12 @@ impl<'mc> HelpTopicFactory<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for IndexHelpTopic<'mc> { + fn into(self) -> crate::help::HelpTopic<'mc> { + crate::help::HelpTopic::from_raw(&self.jni_ref(), self.1) + .expect("Error converting IndexHelpTopic into crate::help::HelpTopic") + } +} #[repr(C)] pub struct HelpTopicComparator<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, @@ -427,148 +492,6 @@ impl<'mc> HelpTopic<'mc> { } } #[repr(C)] -pub struct IndexHelpTopic<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for IndexHelpTopic<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for IndexHelpTopic<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate IndexHelpTopic from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/help/IndexHelpTopic")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a IndexHelpTopic object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> IndexHelpTopic<'mc> { - pub fn can_see( - &self, - sender: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/command/CommandSender;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "canSee", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn amend_can_see( - &self, - amended_permission: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(amended_permission.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "amendCanSee", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn get_full_text( - &self, - sender: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/command/CommandSender;)Ljava/lang/String;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFullText", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - // SUPER CLASS: org.bukkit.help.HelpTopic ( ['canSee', 'amendCanSee', 'getFullText']) - /// Returns the name of this help topic. - pub fn name(&self) -> Result> { - let temp_clone = crate::help::HelpTopic::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::help::HelpTopic = temp_clone.into(); - real.name() - } - /// Returns a brief description that will be displayed in the topic index. - pub fn short_text(&self) -> Result> { - let temp_clone = crate::help::HelpTopic::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::help::HelpTopic = temp_clone.into(); - real.short_text() - } - /// Allows the server admin (or another plugin) to add or replace the - /// contents of a help topic. - /// - /// A null in either parameter will leave that part of the topic unchanged. - /// In either amending parameter, the string {@literal } is replaced - /// with the existing contents in the help topic. Use this to append or - /// prepend additional content into an automatically generated help topic. - pub fn amend_topic( - &self, - amended_short_text: impl Into, - amended_full_text: impl Into, - ) -> Result<(), Box> { - let temp_clone = crate::help::HelpTopic::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::help::HelpTopic = temp_clone.into(); - real.amend_topic(amended_short_text, amended_full_text) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for IndexHelpTopic<'mc> { - fn into(self) -> crate::help::HelpTopic<'mc> { - crate::help::HelpTopic::from_raw(&self.jni_ref(), self.1) - .expect("Error converting IndexHelpTopic into crate::help::HelpTopic") - } -} -#[repr(C)] pub struct GenericCommandHelpTopic<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, @@ -721,6 +644,83 @@ impl<'mc> Into> for GenericCommandHelpTopic<'mc> { } } #[repr(C)] +pub struct HelpTopicFactory<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for HelpTopicFactory<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for HelpTopicFactory<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate HelpTopicFactory from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/help/HelpTopicFactory")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a HelpTopicFactory object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> HelpTopicFactory<'mc> { + pub fn from_extendable( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + plugin: &'mc crate::plugin::Plugin, + address: i32, + lib_name: String, + name: String, + ) -> Result> { + let obj = unsafe { plugin.new_extendable(address, "HelpTopicFactory", name, lib_name) }?; + Self::from_raw(env, obj) + } + /// This method accepts a command deriving from a custom command base class + /// and constructs a custom HelpTopic for it. + pub fn create_topic( + &self, + command: jni::objects::JObject<'mc>, + ) -> Result>, Box> { + let sig = String::from("(LTCommand;)Lorg/bukkit/help/HelpTopic;"); + let val_1 = jni::objects::JValueGen::Object(command); + let res = self.jni_ref().call_method( + &self.jni_object(), + "createTopic", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::help::HelpTopic::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] pub struct HelpMap<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, diff --git a/blackboxmc-rs-bukkit/src/inventory/meta/components/mod.rs b/blackboxmc-rs-bukkit/src/inventory/meta/components/mod.rs index 97a804c..18f76af 100644 --- a/blackboxmc-rs-bukkit/src/inventory/meta/components/mod.rs +++ b/blackboxmc-rs-bukkit/src/inventory/meta/components/mod.rs @@ -130,6 +130,44 @@ impl<'mc> FoodComponent<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } + /// Gets the item this food will convert to once eaten. + pub fn using_converts_to( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getUsingConvertsTo", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets the item this food will convert to once eaten. + pub fn set_using_converts_to( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setUsingConvertsTo", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } /// Gets the effects which may be applied by this item when eaten. pub fn effects( &self, @@ -220,12 +258,10 @@ impl<'mc> FoodComponent<'mc> { pub fn serialize( &self, ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/Map;"; + let sig = String::from("()Ljava/util/Map;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), args); + .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) @@ -344,12 +380,10 @@ impl<'mc> FoodComponentFoodEffect<'mc> { pub fn serialize( &self, ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/Map;"; + let sig = String::from("()Ljava/util/Map;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), args); + .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) @@ -369,6 +403,161 @@ impl<'mc> Into( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for JukeboxPlayableComponent<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for JukeboxPlayableComponent<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate JukeboxPlayableComponent from null object." + ) + .into()); + } + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/inventory/meta/components/JukeboxPlayableComponent", + )?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a JukeboxPlayableComponent object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> JukeboxPlayableComponent<'mc> { + /// Gets the song assigned to this component. + pub fn song(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/JukeboxSong;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSong", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::JukeboxSong::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the key of the song assigned to this component. + pub fn song_key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSongKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the song assigned to this component. + pub fn set_song( + &self, + song: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/JukeboxSong;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(song.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSong", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets the key of the song assigned to this component. + pub fn set_song_key( + &self, + song: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(song.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSongKey", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the song will show in the item tooltip. + pub fn is_show_in_tooltip(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isShowInTooltip", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets if the song will show in the item tooltip. + pub fn set_show_in_tooltip(&self, show: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(show.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setShowInTooltip", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Creates a Map representation of this class. + /// + /// This class must provide a method to restore this class, as defined in + /// the {@link ConfigurationSerializable} interface javadocs. + pub fn serialize( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Map;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> + for JukeboxPlayableComponent<'mc> +{ + fn into(self) -> crate::configuration::serialization::ConfigurationSerializable<'mc> { + crate::configuration::serialization::ConfigurationSerializable::from_raw(&self.jni_ref(), self.1).expect("Error converting JukeboxPlayableComponent into crate::configuration::serialization::ConfigurationSerializable") + } +} +#[repr(C)] pub struct ToolComponent<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, @@ -581,12 +770,10 @@ impl<'mc> ToolComponent<'mc> { pub fn serialize( &self, ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/Map;"; + let sig = String::from("()Ljava/util/Map;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), args); + .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) @@ -751,12 +938,10 @@ impl<'mc> ToolComponentToolRule<'mc> { pub fn serialize( &self, ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/Map;"; + let sig = String::from("()Ljava/util/Map;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), args); + .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) diff --git a/blackboxmc-rs-bukkit/src/inventory/meta/mod.rs b/blackboxmc-rs-bukkit/src/inventory/meta/mod.rs index 5d061a1..7a16f9f 100644 --- a/blackboxmc-rs-bukkit/src/inventory/meta/mod.rs +++ b/blackboxmc-rs-bukkit/src/inventory/meta/mod.rs @@ -3,12 +3,12 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] -pub struct ItemMeta<'mc>( +pub struct KnowledgeBookMeta<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ItemMeta<'mc> { +impl<'mc> JNIRaw<'mc> for KnowledgeBookMeta<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -16,18 +16,21 @@ impl<'mc> JNIRaw<'mc> for ItemMeta<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ItemMeta<'mc> { +impl<'mc> JNIInstantiatable<'mc> for KnowledgeBookMeta<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ItemMeta from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate KnowledgeBookMeta from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/ItemMeta")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/inventory/meta/KnowledgeBookMeta")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ItemMeta object, got {}", + "Invalid argument passed. Expected a KnowledgeBookMeta object, got {}", name ) .into()) @@ -37,7 +40,92 @@ impl<'mc> JNIInstantiatable<'mc> for ItemMeta<'mc> { } } -impl<'mc> ItemMeta<'mc> { +impl<'mc> KnowledgeBookMeta<'mc> { + /// Checks for the existence of recipes in the book. + pub fn has_recipes(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasRecipes", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets all the recipes in the book. + pub fn recipes(&self) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRecipes", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::NamespacedKey::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Clears the existing book recipes, and sets the book to use the provided + /// recipes. + pub fn set_recipes( + &self, + recipes: Vec>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/List;)V"); + let raw_val_1 = self + .jni_ref() + .new_object("java/util/ArrayList", "()V", vec![])?; + for v in recipes { + let map_val_0 = jni::objects::JValueGen::Object(v); + self.jni_ref().call_method( + &raw_val_1, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_1 = jni::objects::JValueGen::Object(raw_val_1); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRecipes", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Adds new recipe to the end of the book. + pub fn add_recipe( + &self, + recipes: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(recipes.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addRecipe", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn clone( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/KnowledgeBookMeta;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::KnowledgeBookMeta::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } /// Checks for existence of a display name. pub fn has_display_name(&self) -> Result> { let sig = String::from("()Z"); @@ -791,6 +879,68 @@ impl<'mc> ItemMeta<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( + &self, + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) + } + /// Sets the item tool. + pub fn set_jukebox_playable( + &self, + jukebox_playable: impl Into>, + ) -> Result<(), Box> { + let sig = + String::from("(Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setJukeboxPlayable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } /// Checks for the existence of any AttributeModifiers. pub fn has_attribute_modifiers(&self) -> Result> { let sig = String::from("()Z"); @@ -1017,81 +1167,24 @@ impl<'mc> ItemMeta<'mc> { Ok(()) } - pub fn clone( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/ItemMeta;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Creates a Map representation of this class. - /// - /// This class must provide a method to restore this class, as defined in - /// the {@link ConfigurationSerializable} interface javadocs. - pub fn serialize( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPersistentDataContainer", - sig.as_str(), - args, - ); - let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> - for ItemMeta<'mc> -{ - fn into(self) -> crate::configuration::serialization::ConfigurationSerializable<'mc> { - crate::configuration::serialization::ConfigurationSerializable::from_raw(&self.jni_ref(), self.1).expect("Error converting ItemMeta into crate::configuration::serialization::ConfigurationSerializable") - } -} -impl<'mc> Into> for ItemMeta<'mc> { - fn into(self) -> crate::persistence::PersistentDataHolder<'mc> { - crate::persistence::PersistentDataHolder::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ItemMeta into crate::persistence::PersistentDataHolder") +impl<'mc> Into> for KnowledgeBookMeta<'mc> { + fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { + crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) + .expect("Error converting KnowledgeBookMeta into crate::inventory::meta::ItemMeta") } } #[repr(C)] -pub struct KnowledgeBookMeta<'mc>( +pub struct FireworkEffectMeta<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for KnowledgeBookMeta<'mc> { +impl<'mc> JNIRaw<'mc> for FireworkEffectMeta<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1099,21 +1192,21 @@ impl<'mc> JNIRaw<'mc> for KnowledgeBookMeta<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for KnowledgeBookMeta<'mc> { +impl<'mc> JNIInstantiatable<'mc> for FireworkEffectMeta<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate KnowledgeBookMeta from null object.").into(), + eyre::eyre!("Tried to instantiate FireworkEffectMeta from null object.").into(), ); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/inventory/meta/KnowledgeBookMeta")?; + env.validate_name(&obj, "org/bukkit/inventory/meta/FireworkEffectMeta")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a KnowledgeBookMeta object, got {}", + "Invalid argument passed. Expected a FireworkEffectMeta object, got {}", name ) .into()) @@ -1123,89 +1216,59 @@ impl<'mc> JNIInstantiatable<'mc> for KnowledgeBookMeta<'mc> { } } -impl<'mc> KnowledgeBookMeta<'mc> { - /// Checks for the existence of recipes in the book. - pub fn has_recipes(&self) -> Result> { +impl<'mc> FireworkEffectMeta<'mc> { + /// Sets the firework effect for this meta. + pub fn set_effect( + &self, + effect: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/FireworkEffect;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setEffect", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if this meta has an effect. + pub fn has_effect(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasRecipes", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasEffect", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets all the recipes in the book. - pub fn recipes(&self) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRecipes", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::NamespacedKey::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Clears the existing book recipes, and sets the book to use the provided - /// recipes. - pub fn set_recipes( - &self, - recipes: Vec>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/List;)V"); - let raw_val_1 = self + /// Gets the firework effect for this meta. + pub fn effect(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/FireworkEffect;"); + let res = self .jni_ref() - .new_object("java/util/ArrayList", "()V", vec![])?; - for v in recipes { - let map_val_0 = jni::objects::JValueGen::Object(v); - self.jni_ref().call_method( - &raw_val_1, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; + .call_method(&self.jni_object(), "getEffect", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - let val_1 = jni::objects::JValueGen::Object(raw_val_1); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRecipes", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Adds new recipe to the end of the book. - pub fn add_recipe( - &self, - recipes: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(recipes.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addRecipe", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(Some(crate::FireworkEffect::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } pub fn clone( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/KnowledgeBookMeta;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/FireworkEffectMeta;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::KnowledgeBookMeta::from_raw(&self.jni_ref(), unsafe { + crate::inventory::meta::FireworkEffectMeta::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -1962,6 +2025,68 @@ impl<'mc> KnowledgeBookMeta<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( + &self, + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) + } + /// Sets the item tool. + pub fn set_jukebox_playable( + &self, + jukebox_playable: impl Into>, + ) -> Result<(), Box> { + let sig = + String::from("(Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setJukeboxPlayable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } /// Checks for the existence of any AttributeModifiers. pub fn has_attribute_modifiers(&self) -> Result> { let sig = String::from("()Z"); @@ -2187,62 +2312,25 @@ impl<'mc> KnowledgeBookMeta<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Creates a Map representation of this class. - /// - /// This class must provide a method to restore this class, as defined in - /// the {@link ConfigurationSerializable} interface javadocs. - pub fn serialize( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPersistentDataContainer", - sig.as_str(), - args, - ); - let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for KnowledgeBookMeta<'mc> { +impl<'mc> Into> for FireworkEffectMeta<'mc> { fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) - .expect("Error converting KnowledgeBookMeta into crate::inventory::meta::ItemMeta") + .expect("Error converting FireworkEffectMeta into crate::inventory::meta::ItemMeta") } } #[repr(C)] -pub struct FireworkEffectMeta<'mc>( +pub struct BookMeta<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for FireworkEffectMeta<'mc> { +impl<'mc> JNIRaw<'mc> for BookMeta<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2250,21 +2338,18 @@ impl<'mc> JNIRaw<'mc> for FireworkEffectMeta<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for FireworkEffectMeta<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BookMeta<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate FireworkEffectMeta from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate BookMeta from null object.").into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/inventory/meta/FireworkEffectMeta")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/BookMeta")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a FireworkEffectMeta object, got {}", + "Invalid argument passed. Expected a BookMeta object, got {}", name ) .into()) @@ -2274,176 +2359,165 @@ impl<'mc> JNIInstantiatable<'mc> for FireworkEffectMeta<'mc> { } } -impl<'mc> FireworkEffectMeta<'mc> { - /// Sets the firework effect for this meta. - pub fn set_effect( - &self, - effect: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/FireworkEffect;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(effect.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setEffect", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks if this meta has an effect. - pub fn has_effect(&self) -> Result> { +impl<'mc> BookMeta<'mc> { + /// Checks for the existence of a title in the book. + pub fn has_title(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "hasEffect", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasTitle", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the firework effect for this meta. - pub fn effect(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/FireworkEffect;"); + /// Gets the title of the book. + /// + /// Plugins should check that hasTitle() returns true before calling this + /// method. + pub fn title(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getEffect", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTitle", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::FireworkEffect::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - - pub fn clone( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/FireworkEffectMeta;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + /// Sets the title of the book. + /// + /// Limited to 32 characters. Removes title when given null. + pub fn set_title(&self, title: impl Into) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(title.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTitle", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::FireworkEffectMeta::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Checks for existence of a display name. - pub fn has_display_name(&self) -> Result> { + /// Checks for the existence of an author in the book. + pub fn has_author(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasDisplayName", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasAuthor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the display name that is set. + /// Gets the author of the book. /// - /// Plugins should check that hasDisplayName() returns true - /// before calling this method. - pub fn display_name(&self) -> Result> { + /// Plugins should check that hasAuthor() returns true before calling this + /// method. + pub fn author(&self) -> Result, Box> { let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDisplayName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self + let res = self .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + .call_method(&self.jni_object(), "getAuthor", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Sets the display name. - pub fn set_display_name( - &self, - name: impl Into, - ) -> Result<(), Box> { + /// Sets the author of the book. Removes author when given null. + pub fn set_author(&self, author: impl Into) -> Result<(), Box> { let sig = String::from("(Ljava/lang/String;)V"); let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, + self.jni_ref().new_string(author.into())?, )); let res = self.jni_ref().call_method( &self.jni_object(), - "setDisplayName", + "setAuthor", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of an item name. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - pub fn has_item_name(&self) -> Result> { + /// Checks for the existence of generation level in the book. + pub fn has_generation(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasItemName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasGeneration", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the item name that is set. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. + /// Gets the generation of the book. /// - /// Plugins should check that hasItemName() returns true before - /// calling this method. - pub fn item_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Plugins should check that hasGeneration() returns true before calling + /// this method. + pub fn generation( + &self, + ) -> Result>, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/BookMeta/Generation;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getGeneration", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::meta::BookMetaGeneration::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the item name. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - pub fn set_item_name(&self, name: impl Into) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + /// Sets the generation of the book. Removes generation when given null. + pub fn set_generation( + &self, + generation: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/BookMeta/Generation;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(generation.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemName", + "setGeneration", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Checks for existence of a localized name. - pub fn has_localized_name(&self) -> Result> { + /// Checks for the existence of pages in the book. + pub fn has_pages(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasLocalizedName", - sig.as_str(), - vec![], - ); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasPages", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Gets the localized display name that is set.Plugins should check that hasLocalizedName() returns true before calling this method. - pub fn localized_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Gets the specified page in the book. The given page must exist. + /// + /// Pages are 1-indexed. + pub fn get_page(&self, page: i32) -> Result> { + let sig = String::from("(I)Ljava/lang/String;"); + let val_1 = jni::objects::JValueGen::Int(page); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocalizedName", + "getPage", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(self @@ -2452,47 +2526,42 @@ impl<'mc> FireworkEffectMeta<'mc> { .to_string_lossy() .to_string()) } - #[deprecated] - /// Sets the localized name. - pub fn set_localized_name( + /// Sets the specified page in the book. Pages of the book must be + /// contiguous. + /// + /// The data can be up to 1024 characters in length, additional characters + /// are truncated. + /// + /// Pages are 1-indexed. + pub fn set_page( &self, - name: impl Into, + page: i32, + data: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, + let sig = String::from("(ILjava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Int(page); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(data.into())?, )); let res = self.jni_ref().call_method( &self.jni_object(), - "setLocalizedName", + "setPage", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of lore. - pub fn has_lore(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasLore", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the lore that is set. - /// - /// Plugins should check if hasLore() returns true before - /// calling this method. - pub fn lore(&self) -> Result>, Box> { + /// Gets all the pages in the book. + pub fn pages(&self) -> Result, Box> { let sig = String::from("()Ljava/util/List;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getLore", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPages", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; let iter = list.iterator()?; @@ -2505,79 +2574,1895 @@ impl<'mc> FireworkEffectMeta<'mc> { .to_string(), ); } - Ok(Some(new_vec)) + Ok(new_vec) } - /// Sets the lore for this item. - /// Removes lore when given null. - pub fn set_lore( - &self, - lore: Vec>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/List;)V"); - let raw_val_1 = self + /// Clears the existing book pages, and sets the book to use the provided + /// pages. Maximum 100 pages with 1024 characters per page. + pub fn set_pages(&self, pages: impl Into) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(pages.into())?, + )); + args.push(val_1); + sig += ")V"; + let res = self .jni_ref() - .new_object("java/util/ArrayList", "()V", vec![])?; - for v in lore { - let map_val_0 = jni::objects::JValueGen::Object(v); - self.jni_ref().call_method( - &raw_val_1, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_1 = jni::objects::JValueGen::Object(raw_val_1); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLore", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "setPages", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of custom model data. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - pub fn has_custom_model_data(&self) -> Result> { - let sig = String::from("()Z"); + /// Adds new pages to the end of the book. Up to a maximum of 100 pages with + /// 1024 characters per page. + pub fn add_page(&self, pages: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(pages.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "hasCustomModelData", + "addPage", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the custom model data that is set. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - /// - /// Plugins should check that hasCustomModelData() returns true - /// before calling this method. - pub fn custom_model_data(&self) -> Result> { + /// Gets the number of pages in the book. + pub fn page_count(&self) -> Result> { let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCustomModelData", - sig.as_str(), - vec![], - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPageCount", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the custom model data. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - pub fn set_custom_model_data(&self, data: i32) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/Integer;)V"); - let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( - "java/lang/Integer", - "(Ljava/Lang/Object;)V", + + pub fn clone( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/WritableBookMeta;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::WritableBookMeta::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for BookMeta<'mc> { + fn into(self) -> crate::inventory::meta::WritableBookMeta<'mc> { + crate::inventory::meta::WritableBookMeta::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BookMeta into crate::inventory::meta::WritableBookMeta") + } +} +pub enum BookMetaGeneration<'mc> { + Original { + inner: BookMetaGenerationStruct<'mc>, + }, + CopyOfOriginal { + inner: BookMetaGenerationStruct<'mc>, + }, + CopyOfCopy { + inner: BookMetaGenerationStruct<'mc>, + }, + Tattered { + inner: BookMetaGenerationStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for BookMetaGeneration<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + BookMetaGeneration::Original { .. } => f.write_str("ORIGINAL"), + BookMetaGeneration::CopyOfOriginal { .. } => f.write_str("COPY_OF_ORIGINAL"), + BookMetaGeneration::CopyOfCopy { .. } => f.write_str("COPY_OF_COPY"), + BookMetaGeneration::Tattered { .. } => f.write_str("TATTERED"), + } + } +} +impl<'mc> std::ops::Deref for BookMetaGeneration<'mc> { + type Target = BookMetaGenerationStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + BookMetaGeneration::Original { inner } => inner, + BookMetaGeneration::CopyOfOriginal { inner } => inner, + BookMetaGeneration::CopyOfCopy { inner } => inner, + BookMetaGeneration::Tattered { inner } => inner, + } + } +} + +impl<'mc> BookMetaGeneration<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/inventory/meta/BookMeta/Generation"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/inventory/meta/BookMeta/Generation;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "ORIGINAL" => Ok(BookMetaGeneration::Original { + inner: BookMetaGenerationStruct::from_raw(env, obj)?, + }), + "COPY_OF_ORIGINAL" => Ok(BookMetaGeneration::CopyOfOriginal { + inner: BookMetaGenerationStruct::from_raw(env, obj)?, + }), + "COPY_OF_COPY" => Ok(BookMetaGeneration::CopyOfCopy { + inner: BookMetaGenerationStruct::from_raw(env, obj)?, + }), + "TATTERED" => Ok(BookMetaGeneration::Tattered { + inner: BookMetaGenerationStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct BookMetaGenerationStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for BookMetaGeneration<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Original { inner } => inner.0.clone(), + Self::CopyOfOriginal { inner } => inner.0.clone(), + Self::CopyOfCopy { inner } => inner.0.clone(), + Self::Tattered { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Original { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CopyOfOriginal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CopyOfCopy { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Tattered { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for BookMetaGeneration<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate BookMetaGeneration from null object.").into(), + ); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/inventory/meta/BookMeta/Generation")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BookMetaGeneration object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "ORIGINAL" => Ok(BookMetaGeneration::Original { + inner: BookMetaGenerationStruct::from_raw(env, obj)?, + }), + "COPY_OF_ORIGINAL" => Ok(BookMetaGeneration::CopyOfOriginal { + inner: BookMetaGenerationStruct::from_raw(env, obj)?, + }), + "COPY_OF_COPY" => Ok(BookMetaGeneration::CopyOfCopy { + inner: BookMetaGenerationStruct::from_raw(env, obj)?, + }), + "TATTERED" => Ok(BookMetaGeneration::Tattered { + inner: BookMetaGenerationStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for BookMetaGenerationStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for BookMetaGenerationStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate BookMetaGenerationStruct from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/inventory/meta/BookMeta/Generation")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BookMetaGenerationStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> BookMetaGenerationStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/BookMeta/Generation;"); + let cls = jni.find_class("org/bukkit/inventory/meta/BookMeta/Generation"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::inventory::meta::BookMetaGeneration::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct BannerMeta<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for BannerMeta<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for BannerMeta<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate BannerMeta from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/BannerMeta")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BannerMeta object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> BannerMeta<'mc> { + /// Returns a list of patterns on this banner + pub fn patterns( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPatterns", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::banner::Pattern::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(new_vec) + } + /// Sets the patterns used on this banner + pub fn set_patterns( + &self, + patterns: Vec>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/List;)V"); + let raw_val_1 = self + .jni_ref() + .new_object("java/util/ArrayList", "()V", vec![])?; + for v in patterns { + let map_val_0 = jni::objects::JValueGen::Object(v); + self.jni_ref().call_method( + &raw_val_1, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_1 = jni::objects::JValueGen::Object(raw_val_1); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPatterns", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Adds a new pattern on top of the existing + /// patterns + pub fn add_pattern( + &self, + pattern: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/banner/Pattern;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(pattern.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addPattern", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the pattern at the specified index + pub fn get_pattern( + &self, + i: i32, + ) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/block/banner/Pattern;"); + let val_1 = jni::objects::JValueGen::Int(i); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPattern", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::block::banner::Pattern::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Removes the pattern at the specified index + pub fn remove_pattern( + &self, + i: i32, + ) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/block/banner/Pattern;"); + let val_1 = jni::objects::JValueGen::Int(i); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removePattern", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::block::banner::Pattern::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the pattern at the specified index + pub fn set_pattern( + &self, + i: i32, + pattern: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(ILorg/bukkit/block/banner/Pattern;)V"); + let val_1 = jni::objects::JValueGen::Int(i); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(pattern.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPattern", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the number of patterns on this + /// banner + pub fn number_of_patterns(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "numberOfPatterns", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Checks for existence of a display name. + pub fn has_display_name(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasDisplayName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the display name that is set. + /// + /// Plugins should check that hasDisplayName() returns true + /// before calling this method. + pub fn display_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDisplayName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the display name. + pub fn set_display_name( + &self, + name: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDisplayName", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks for existence of an item name. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + pub fn has_item_name(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasItemName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the item name that is set. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + /// + /// Plugins should check that hasItemName() returns true before + /// calling this method. + pub fn item_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the item name. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + pub fn set_item_name(&self, name: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItemName", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Checks for existence of a localized name. + pub fn has_localized_name(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasLocalizedName", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Gets the localized display name that is set.Plugins should check that hasLocalizedName() returns true before calling this method. + pub fn localized_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLocalizedName", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + #[deprecated] + /// Sets the localized name. + pub fn set_localized_name( + &self, + name: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLocalizedName", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks for existence of lore. + pub fn has_lore(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasLore", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the lore that is set. + /// + /// Plugins should check if hasLore() returns true before + /// calling this method. + pub fn lore(&self) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLore", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); + } + Ok(Some(new_vec)) + } + /// Sets the lore for this item. + /// Removes lore when given null. + pub fn set_lore( + &self, + lore: Vec>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/List;)V"); + let raw_val_1 = self + .jni_ref() + .new_object("java/util/ArrayList", "()V", vec![])?; + for v in lore { + let map_val_0 = jni::objects::JValueGen::Object(v); + self.jni_ref().call_method( + &raw_val_1, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_1 = jni::objects::JValueGen::Object(raw_val_1); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLore", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks for existence of custom model data. + /// + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + pub fn has_custom_model_data(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasCustomModelData", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the custom model data that is set. + /// + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + /// + /// Plugins should check that hasCustomModelData() returns true + /// before calling this method. + pub fn custom_model_data(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCustomModelData", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the custom model data. + /// + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + pub fn set_custom_model_data(&self, data: i32) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/Integer;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Integer", + "(Ljava/Lang/Object;)V", + vec![data.into()], + )?); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCustomModelData", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks for the existence of any enchantments. + pub fn has_enchants(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasEnchants", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks for existence of the specified enchantment. + pub fn has_enchant( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasEnchant", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks for the level of the specified enchantment. + pub fn get_enchant_level( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)I"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getEnchantLevel", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns a copy the enchantments in this ItemMeta. + /// + /// Returns an empty map if none. + pub fn enchants( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Map;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEnchants", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Adds the specified enchantment to this item meta. + pub fn add_enchant( + &self, + ench: impl Into>, + level: i32, + ignore_level_restriction: bool, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;IZ)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(level); + let val_3 = jni::objects::JValueGen::Bool(ignore_level_restriction.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addEnchant", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Removes the specified enchantment from this item meta. + pub fn remove_enchant( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeEnchant", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Removes all enchantments from this item meta. + pub fn remove_enchantments(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeEnchantments", + sig.as_str(), + vec![], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the specified enchantment conflicts with any enchantments in + /// this ItemMeta. + pub fn has_conflicting_enchant( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasConflictingEnchant", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set itemflags which should be ignored when rendering a ItemStack in the Client. This Method does silently ignore double set itemFlags. + pub fn add_item_flags( + &self, + item_flags: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addItemFlags", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Remove specific set of itemFlags. This tells the Client it should render it again. This Method does silently ignore double removed itemFlags. + pub fn remove_item_flags( + &self, + item_flags: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeItemFlags", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get current set itemFlags. The collection returned is unmodifiable. + pub fn item_flags( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemFlags", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Check if the specified flag is present on this item. + pub fn has_item_flag( + &self, + flag: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(flag.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasItemFlag", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets if this item has hide_tooltip set. An item with this set will not + /// show any tooltip whatsoever. + pub fn is_hide_tooltip(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isHideTooltip", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets if this item has hide_tooltip set. An item with this set will not + /// show any tooltip whatsoever. + pub fn set_hide_tooltip(&self, hide_tooltip: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(hide_tooltip.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setHideTooltip", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Return if the unbreakable tag is true. An unbreakable item will not lose + /// durability. + pub fn is_unbreakable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isUnbreakable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the unbreakable tag. An unbreakable item will not lose durability. + pub fn set_unbreakable(&self, unbreakable: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(unbreakable.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setUnbreakable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if an enchantment_glint_override is set. + pub fn has_enchantment_glint_override(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasEnchantmentGlintOverride", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the enchantment_glint_override. If true, the item will glint, even + /// without enchantments; if false, the item will not glint, even with + /// enchantments. + /// Plugins should check {@link #hasEnchantmentGlintOverride()} before + /// calling this method. + pub fn enchantment_glint_override(&self) -> Result> { + let sig = String::from("()Ljava/lang/Boolean;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getEnchantmentGlintOverride", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the enchantment_glint_override. If true, the item will glint, even + /// without enchantments; if false, the item will not glint, even with + /// enchantments. If null, the override will be cleared. + pub fn set_enchantment_glint_override( + &self, + val_override: bool, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/Boolean;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Boolean", + "(Ljava/Lang/Object;)V", + vec![val_override.into()], + )?); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setEnchantmentGlintOverride", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if this item is fire_resistant. If true, it will not burn in fire + /// or lava. + pub fn is_fire_resistant(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isFireResistant", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets if this item is fire_resistant. If true, it will not burn in fire + /// or lava. + pub fn set_fire_resistant( + &self, + fire_resistant: bool, + ) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire_resistant.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFireResistant", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the max_stack_size is set. + pub fn has_max_stack_size(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasMaxStackSize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the max_stack_size. This is the maximum amount which an item will + /// stack. + pub fn max_stack_size(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the max_stack_size. This is the maximum amount which an item will + /// stack. + pub fn set_max_stack_size(&self, max: i32) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/Integer;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Integer", + "(Ljava/Lang/Object;)V", + vec![max.into()], + )?); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaxStackSize", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the rarity is set. + pub fn has_rarity(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasRarity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the item rarity. + /// Plugins should check {@link #hasRarity()} before calling this method. + pub fn rarity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemRarity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRarity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemRarity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the item rarity. + pub fn set_rarity( + &self, + rarity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemRarity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(rarity.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRarity", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the food is set. + pub fn has_food(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasFood", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the food set on this item, or creates an empty food instance. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with {@link #setFood(FoodComponent)} to + /// apply the changes. + pub fn food( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/FoodComponent;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFood", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::components::FoodComponent::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the item food. + pub fn set_food( + &self, + food: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/FoodComponent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(food.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFood", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the tool is set. + pub fn has_tool(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasTool", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the tool set on this item, or creates an empty tool instance. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with {@link #setTool(ToolComponent)} to + /// apply the changes. + pub fn tool( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/ToolComponent;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::components::ToolComponent::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the item tool. + pub fn set_tool( + &self, + tool: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(tool.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTool", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( + &self, + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) + } + /// Sets the item tool. + pub fn set_jukebox_playable( + &self, + jukebox_playable: impl Into>, + ) -> Result<(), Box> { + let sig = + String::from("(Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setJukeboxPlayable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks for the existence of any AttributeModifiers. + pub fn has_attribute_modifiers(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasAttributeModifiers", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Return an immutable copy of all {@link AttributeModifier}s + /// for a given {@link Attribute} + pub fn get_attribute_modifiers( + &self, + attribute: impl Into>, + ) -> Result>>, Box> + { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/attribute/Attribute;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Ljava/util/Collection;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAttributeModifiers", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::attribute::AttributeModifier::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(Some(new_vec)) + } + /// Add an Attribute and it's Modifier. + /// AttributeModifiers can now support {@link EquipmentSlot}s. + /// If not set, the {@link AttributeModifier} will be active in ALL slots. + /// + /// Two {@link AttributeModifier}s that have the same {@link java.util.UUID} + /// cannot exist on the same Attribute. + pub fn add_attribute_modifier( + &self, + attribute: impl Into>, + modifier: impl Into>, + ) -> Result> { + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;Lorg/bukkit/attribute/AttributeModifier;)Z", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(modifier.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addAttributeModifier", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set all {@link Attribute}s and their {@link AttributeModifier}s. + /// To clear all currently set Attributes and AttributeModifiers use + /// null or an empty Multimap. + /// If not null nor empty, this will filter all entries that are not-null + /// and add them to the ItemStack. + pub fn set_attribute_modifiers( + &self, + attribute_modifiers: jni::objects::JObject<'mc>, + ) -> Result<(), Box> { + let sig = String::from("(Lcom/google/common/collect/Multimap;)V"); + let val_1 = jni::objects::JValueGen::Object(attribute_modifiers); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAttributeModifiers", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Remove a specific {@link Attribute} and {@link AttributeModifier}. + /// AttributeModifiers are matched according to their {@link java.util.UUID}. + pub fn remove_attribute_modifier( + &self, + attribute: impl Into>, + modifier: std::option::Option>>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/attribute/Attribute;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = modifier { + sig += "Lorg/bukkit/attribute/AttributeModifier;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeAttributeModifier", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get this ItemMeta as an NBT string. If this ItemMeta does not have any + /// NBT, then {@code "{}"} will be returned. + /// + /// This string should NEVER be relied upon as a serializable value. If + /// serialization is desired, the {@link ConfigurationSerializable} API should be used + /// instead. + pub fn as_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Get this ItemMeta as a component-compliant string. If this ItemMeta does + /// not contain any components, then {@code "[]"} will be returned. + /// + /// The result of this method should yield a string representing the components + /// altered by this ItemMeta instance. When passed to {@link ItemFactory#createItemStack(String)} + /// with a prepended item type, it will create an ItemStack that has an ItemMeta + /// matching this ItemMeta instance exactly. Note that this method returns + /// ONLY the components and cannot be passed to createItemStack() alone. + /// An example may look something like this: + ///
+    /// ItemStack itemStack = // ... an item stack obtained from somewhere
+    /// ItemMeta itemMeta = itemStack.getItemMeta();
+    /// String components = itemMeta.getAsComponentString(); // example: "[minecraft:damage=53]"
+    /// String itemTypeKey = itemStack.getType().getKey().toString(); // example: "minecraft:diamond_sword"
+    /// String itemAsString = itemTypeKey + components; // results in: "minecraft:diamond_sword[minecraft:damage=53]"
+    /// ItemStack recreatedItemStack = Bukkit.getItemFactory().createItemStack(itemAsString);
+    /// assert itemStack.isSimilar(recreatedItemStack); // Should be true*
+    /// 
+ /// + /// *Components not represented or explicitly overridden by this ItemMeta instance + /// will not be included in the resulting string and therefore may result in ItemStacks + /// that do not match exactly. For example, if {@link #setDisplayName(String)} + /// is not set, then the custom name component will not be included. Or if this ItemMeta + /// is a PotionMeta, it will not include any components related to lodestone compasses, + /// banners, or books, etc., only components modifiable by a PotionMeta instance. + /// + /// This string should NEVER be relied upon as a serializable value. If + /// serialization is desired, the {@link ConfigurationSerializable} API should be used + /// instead. + pub fn as_component_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAsComponentString", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + #[deprecated] + /// Returns a public custom tag container capable of storing tags on the item. Those tags will be sent to the client with all of their content, so the client is capable of reading them. This will result in the player seeing a NBT Tag notification on the item. These tags can also be modified by the client once in creative mode + pub fn custom_tag_container( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/tags/CustomItemTagContainer;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCustomTagContainer", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::tags::CustomItemTagContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Internal use only! Do not use under any circumstances! + pub fn set_version(&self, version: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(version); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVersion", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn clone( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/ItemMeta;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for BannerMeta<'mc> { + fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { + crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BannerMeta into crate::inventory::meta::ItemMeta") + } +} +#[repr(C)] +pub struct SpawnEggMeta<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for SpawnEggMeta<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for SpawnEggMeta<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate SpawnEggMeta from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/SpawnEggMeta")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a SpawnEggMeta object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> SpawnEggMeta<'mc> { + #[deprecated] + /// Get the type of entity this egg will spawn. + pub fn spawned_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSpawnedType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + #[deprecated] + /// Set the type of entity this egg will spawn. + pub fn set_spawned_type( + &self, + val_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/EntityType;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSpawnedType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the {@link EntitySnapshot} that will be spawned by this spawn egg or null if no entity + /// has been set. + /// + /// + /// All applicable data from the egg will be copied, such as custom name, health, + /// and velocity. + /// + pub fn spawned_entity( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSpawnedEntity", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntitySnapshot::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets the {@link EntitySnapshot} that will be spawned by this spawn egg. + /// + /// + /// All applicable data from the entity will be copied, such as custom name, + /// health, and velocity. + /// + pub fn set_spawned_entity( + &self, + snapshot: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/EntitySnapshot;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(snapshot.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSpawnedEntity", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn clone( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/SpawnEggMeta;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::SpawnEggMeta::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Checks for existence of a display name. + pub fn has_display_name(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasDisplayName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the display name that is set. + /// + /// Plugins should check that hasDisplayName() returns true + /// before calling this method. + pub fn display_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDisplayName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the display name. + pub fn set_display_name( + &self, + name: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDisplayName", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks for existence of an item name. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + pub fn has_item_name(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasItemName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the item name that is set. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + /// + /// Plugins should check that hasItemName() returns true before + /// calling this method. + pub fn item_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the item name. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + pub fn set_item_name(&self, name: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItemName", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Checks for existence of a localized name. + pub fn has_localized_name(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasLocalizedName", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Gets the localized display name that is set.Plugins should check that hasLocalizedName() returns true before calling this method. + pub fn localized_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLocalizedName", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + #[deprecated] + /// Sets the localized name. + pub fn set_localized_name( + &self, + name: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLocalizedName", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks for existence of lore. + pub fn has_lore(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasLore", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the lore that is set. + /// + /// Plugins should check if hasLore() returns true before + /// calling this method. + pub fn lore(&self) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLore", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); + } + Ok(Some(new_vec)) + } + /// Sets the lore for this item. + /// Removes lore when given null. + pub fn set_lore( + &self, + lore: Vec>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/List;)V"); + let raw_val_1 = self + .jni_ref() + .new_object("java/util/ArrayList", "()V", vec![])?; + for v in lore { + let map_val_0 = jni::objects::JValueGen::Object(v); + self.jni_ref().call_method( + &raw_val_1, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_1 = jni::objects::JValueGen::Object(raw_val_1); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLore", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks for existence of custom model data. + /// + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + pub fn has_custom_model_data(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasCustomModelData", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the custom model data that is set. + /// + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + /// + /// Plugins should check that hasCustomModelData() returns true + /// before calling this method. + pub fn custom_model_data(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCustomModelData", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the custom model data. + /// + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + pub fn set_custom_model_data(&self, data: i32) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/Integer;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Integer", + "(Ljava/Lang/Object;)V", vec![data.into()], )?); let res = self.jni_ref().call_method( @@ -2808,956 +4693,587 @@ impl<'mc> FireworkEffectMeta<'mc> { let val_1 = jni::objects::JValueGen::Bool(hide_tooltip.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setHideTooltip", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Return if the unbreakable tag is true. An unbreakable item will not lose - /// durability. - pub fn is_unbreakable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isUnbreakable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets the unbreakable tag. An unbreakable item will not lose durability. - pub fn set_unbreakable(&self, unbreakable: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(unbreakable.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setUnbreakable", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets if an enchantment_glint_override is set. - pub fn has_enchantment_glint_override(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasEnchantmentGlintOverride", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets the enchantment_glint_override. If true, the item will glint, even - /// without enchantments; if false, the item will not glint, even with - /// enchantments. - /// Plugins should check {@link #hasEnchantmentGlintOverride()} before - /// calling this method. - pub fn enchantment_glint_override(&self) -> Result> { - let sig = String::from("()Ljava/lang/Boolean;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getEnchantmentGlintOverride", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets the enchantment_glint_override. If true, the item will glint, even - /// without enchantments; if false, the item will not glint, even with - /// enchantments. If null, the override will be cleared. - pub fn set_enchantment_glint_override( - &self, - val_override: bool, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/Boolean;)V"); - let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( - "java/lang/Boolean", - "(Ljava/Lang/Object;)V", - vec![val_override.into()], - )?); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setEnchantmentGlintOverride", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks if this item is fire_resistant. If true, it will not burn in fire - /// or lava. - pub fn is_fire_resistant(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isFireResistant", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets if this item is fire_resistant. If true, it will not burn in fire - /// or lava. - pub fn set_fire_resistant( - &self, - fire_resistant: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire_resistant.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFireResistant", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets if the max_stack_size is set. - pub fn has_max_stack_size(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasMaxStackSize", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the max_stack_size. This is the maximum amount which an item will - /// stack. - pub fn max_stack_size(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the max_stack_size. This is the maximum amount which an item will - /// stack. - pub fn set_max_stack_size(&self, max: i32) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/Integer;)V"); - let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( - "java/lang/Integer", - "(Ljava/Lang/Object;)V", - vec![max.into()], - )?); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaxStackSize", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets if the rarity is set. - pub fn has_rarity(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasRarity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the item rarity. - /// Plugins should check {@link #hasRarity()} before calling this method. - pub fn rarity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemRarity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getRarity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemRarity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the item rarity. - pub fn set_rarity( - &self, - rarity: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemRarity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(rarity.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRarity", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks if the food is set. - pub fn has_food(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasFood", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the food set on this item, or creates an empty food instance. - /// - /// The returned component is a snapshot of its current state and does not - /// reflect a live view of what is on an item. After changing any value on - /// this component, it must be set with {@link #setFood(FoodComponent)} to - /// apply the changes. - pub fn food( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/components/FoodComponent;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFood", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::components::FoodComponent::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the item food. - pub fn set_food( - &self, - food: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/components/FoodComponent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(food.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFood", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks if the tool is set. - pub fn has_tool(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasTool", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the tool set on this item, or creates an empty tool instance. - /// - /// The returned component is a snapshot of its current state and does not - /// reflect a live view of what is on an item. After changing any value on - /// this component, it must be set with {@link #setTool(ToolComponent)} to - /// apply the changes. - pub fn tool( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/components/ToolComponent;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); + "setHideTooltip", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Return if the unbreakable tag is true. An unbreakable item will not lose + /// durability. + pub fn is_unbreakable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isUnbreakable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::components::ToolComponent::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets the item tool. - pub fn set_tool( - &self, - tool: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tool.into().jni_object().clone()) - }); + /// Sets the unbreakable tag. An unbreakable item will not lose durability. + pub fn set_unbreakable(&self, unbreakable: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(unbreakable.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setTool", + "setUnbreakable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for the existence of any AttributeModifiers. - pub fn has_attribute_modifiers(&self) -> Result> { + /// Gets if an enchantment_glint_override is set. + pub fn has_enchantment_glint_override(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasAttributeModifiers", + "hasEnchantmentGlintOverride", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Return an immutable copy of all {@link AttributeModifier}s - /// for a given {@link Attribute} - pub fn get_attribute_modifiers( - &self, - attribute: impl Into>, - ) -> Result>>, Box> - { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/attribute/Attribute;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Ljava/util/Collection;"; + /// Sets the enchantment_glint_override. If true, the item will glint, even + /// without enchantments; if false, the item will not glint, even with + /// enchantments. + /// Plugins should check {@link #hasEnchantmentGlintOverride()} before + /// calling this method. + pub fn enchantment_glint_override(&self) -> Result> { + let sig = String::from("()Ljava/lang/Boolean;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getAttributeModifiers", + "getEnchantmentGlintOverride", sig.as_str(), - args, + vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::attribute::AttributeModifier::from_raw( - &self.jni_ref(), - obj, - )?); - } - Ok(Some(new_vec)) + Ok(res.z()?) } - /// Add an Attribute and it's Modifier. - /// AttributeModifiers can now support {@link EquipmentSlot}s. - /// If not set, the {@link AttributeModifier} will be active in ALL slots. - /// - /// Two {@link AttributeModifier}s that have the same {@link java.util.UUID} - /// cannot exist on the same Attribute. - pub fn add_attribute_modifier( + /// Sets the enchantment_glint_override. If true, the item will glint, even + /// without enchantments; if false, the item will not glint, even with + /// enchantments. If null, the override will be cleared. + pub fn set_enchantment_glint_override( &self, - attribute: impl Into>, - modifier: impl Into>, - ) -> Result> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;Lorg/bukkit/attribute/AttributeModifier;)Z", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(modifier.into().jni_object().clone()) - }); + val_override: bool, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/Boolean;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Boolean", + "(Ljava/Lang/Object;)V", + vec![val_override.into()], + )?); let res = self.jni_ref().call_method( &self.jni_object(), - "addAttributeModifier", + "setEnchantmentGlintOverride", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if this item is fire_resistant. If true, it will not burn in fire + /// or lava. + pub fn is_fire_resistant(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isFireResistant", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set all {@link Attribute}s and their {@link AttributeModifier}s. - /// To clear all currently set Attributes and AttributeModifiers use - /// null or an empty Multimap. - /// If not null nor empty, this will filter all entries that are not-null - /// and add them to the ItemStack. - pub fn set_attribute_modifiers( + /// Sets if this item is fire_resistant. If true, it will not burn in fire + /// or lava. + pub fn set_fire_resistant( &self, - attribute_modifiers: jni::objects::JObject<'mc>, + fire_resistant: bool, ) -> Result<(), Box> { - let sig = String::from("(Lcom/google/common/collect/Multimap;)V"); - let val_1 = jni::objects::JValueGen::Object(attribute_modifiers); + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire_resistant.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setAttributeModifiers", + "setFireResistant", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Remove a specific {@link Attribute} and {@link AttributeModifier}. - /// AttributeModifiers are matched according to their {@link java.util.UUID}. - pub fn remove_attribute_modifier( - &self, - attribute: impl Into>, - modifier: std::option::Option>>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/attribute/Attribute;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = modifier { - sig += "Lorg/bukkit/attribute/AttributeModifier;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Z"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "removeAttributeModifier", - sig.as_str(), - args, - ); + /// Gets if the max_stack_size is set. + pub fn has_max_stack_size(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasMaxStackSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get this ItemMeta as an NBT string. If this ItemMeta does not have any - /// NBT, then {@code "{}"} will be returned. - /// - /// This string should NEVER be relied upon as a serializable value. If - /// serialization is desired, the {@link ConfigurationSerializable} API should be used - /// instead. - pub fn as_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Gets the max_stack_size. This is the maximum amount which an item will + /// stack. + pub fn max_stack_size(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Get this ItemMeta as a component-compliant string. If this ItemMeta does - /// not contain any components, then {@code "[]"} will be returned. - /// - /// The result of this method should yield a string representing the components - /// altered by this ItemMeta instance. When passed to {@link ItemFactory#createItemStack(String)} - /// with a prepended item type, it will create an ItemStack that has an ItemMeta - /// matching this ItemMeta instance exactly. Note that this method returns - /// ONLY the components and cannot be passed to createItemStack() alone. - /// An example may look something like this: - ///
-    /// ItemStack itemStack = // ... an item stack obtained from somewhere
-    /// ItemMeta itemMeta = itemStack.getItemMeta();
-    /// String components = itemMeta.getAsComponentString(); // example: "[minecraft:damage=53]"
-    /// String itemTypeKey = itemStack.getType().getKey().toString(); // example: "minecraft:diamond_sword"
-    /// String itemAsString = itemTypeKey + components; // results in: "minecraft:diamond_sword[minecraft:damage=53]"
-    /// ItemStack recreatedItemStack = Bukkit.getItemFactory().createItemStack(itemAsString);
-    /// assert itemStack.isSimilar(recreatedItemStack); // Should be true*
-    /// 
- /// - /// *Components not represented or explicitly overridden by this ItemMeta instance - /// will not be included in the resulting string and therefore may result in ItemStacks - /// that do not match exactly. For example, if {@link #setDisplayName(String)} - /// is not set, then the custom name component will not be included. Or if this ItemMeta - /// is a PotionMeta, it will not include any components related to lodestone compasses, - /// banners, or books, etc., only components modifiable by a PotionMeta instance. - /// - /// This string should NEVER be relied upon as a serializable value. If - /// serialization is desired, the {@link ConfigurationSerializable} API should be used - /// instead. - pub fn as_component_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAsComponentString", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - #[deprecated] - /// Returns a public custom tag container capable of storing tags on the item. Those tags will be sent to the client with all of their content, so the client is capable of reading them. This will result in the player seeing a NBT Tag notification on the item. These tags can also be modified by the client once in creative mode - pub fn custom_tag_container( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/tags/CustomItemTagContainer;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCustomTagContainer", - sig.as_str(), - vec![], - ); + .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::tags::CustomItemTagContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Internal use only! Do not use under any circumstances! - pub fn set_version(&self, version: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(version); + /// Sets the max_stack_size. This is the maximum amount which an item will + /// stack. + pub fn set_max_stack_size(&self, max: i32) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/Integer;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Integer", + "(Ljava/Lang/Object;)V", + vec![max.into()], + )?); let res = self.jni_ref().call_method( &self.jni_object(), - "setVersion", + "setMaxStackSize", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Creates a Map representation of this class. - /// - /// This class must provide a method to restore this class, as defined in - /// the {@link ConfigurationSerializable} interface javadocs. - pub fn serialize( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); + /// Gets if the rarity is set. + pub fn has_rarity(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasRarity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + Ok(res.z()?) + } + /// Gets the item rarity. + /// Plugins should check {@link #hasRarity()} before calling this method. + pub fn rarity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemRarity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRarity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemRarity::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( + /// Sets the item rarity. + pub fn set_rarity( &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; + rarity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemRarity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(rarity.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "setRarity", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for FireworkEffectMeta<'mc> { - fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { - crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) - .expect("Error converting FireworkEffectMeta into crate::inventory::meta::ItemMeta") - } -} -#[repr(C)] -pub struct BookMeta<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for BookMeta<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for BookMeta<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate BookMeta from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/BookMeta")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a BookMeta object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> BookMeta<'mc> { - /// Checks for the existence of a title in the book. - pub fn has_title(&self) -> Result> { + /// Checks if the food is set. + pub fn has_food(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "hasTitle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasFood", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the title of the book. + /// Gets the food set on this item, or creates an empty food instance. /// - /// Plugins should check that hasTitle() returns true before calling this - /// method. - pub fn title(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with {@link #setFood(FoodComponent)} to + /// apply the changes. + pub fn food( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/FoodComponent;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getTitle", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFood", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + crate::inventory::meta::components::FoodComponent::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the title of the book. - /// - /// Limited to 32 characters. Removes title when given null. - pub fn set_title(&self, title: impl Into) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(title.into())?, - )); + /// Sets the item food. + pub fn set_food( + &self, + food: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/FoodComponent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(food.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setTitle", + "setFood", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Checks for the existence of an author in the book. - pub fn has_author(&self) -> Result> { + /// Checks if the tool is set. + pub fn has_tool(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "hasAuthor", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasTool", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the author of the book. + /// Gets the tool set on this item, or creates an empty tool instance. /// - /// Plugins should check that hasAuthor() returns true before calling this - /// method. - pub fn author(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with {@link #setTool(ToolComponent)} to + /// apply the changes. + pub fn tool( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/ToolComponent;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getAuthor", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + crate::inventory::meta::components::ToolComponent::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the author of the book. Removes author when given null. - pub fn set_author(&self, author: impl Into) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(author.into())?, - )); + /// Sets the item tool. + pub fn set_tool( + &self, + tool: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(tool.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setAuthor", + "setTool", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for the existence of generation level in the book. - pub fn has_generation(&self) -> Result> { + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasGeneration", sig.as_str(), vec![]); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the generation of the book. + /// Gets the jukebox playable component set on this item. /// - /// Plugins should check that hasGeneration() returns true before calling - /// this method. - pub fn generation( + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( &self, - ) -> Result>, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/BookMeta/Generation;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getGeneration", sig.as_str(), vec![]); + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::meta::BookMetaGeneration::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) } - /// Sets the generation of the book. Removes generation when given null. - pub fn set_generation( + /// Sets the item tool. + pub fn set_jukebox_playable( &self, - generation: impl Into>, + jukebox_playable: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/BookMeta/Generation;)V"); + let sig = + String::from("(Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(generation.into().jni_object().clone()) + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setGeneration", + "setJukeboxPlayable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for the existence of pages in the book. - pub fn has_pages(&self) -> Result> { + /// Checks for the existence of any AttributeModifiers. + pub fn has_attribute_modifiers(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasPages", sig.as_str(), vec![]); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasAttributeModifiers", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the specified page in the book. The given page must exist. - /// - /// Pages are 1-indexed. - pub fn get_page(&self, page: i32) -> Result> { - let sig = String::from("(I)Ljava/lang/String;"); - let val_1 = jni::objects::JValueGen::Int(page); + /// Return an immutable copy of all {@link AttributeModifier}s + /// for a given {@link Attribute} + pub fn get_attribute_modifiers( + &self, + attribute: impl Into>, + ) -> Result>>, Box> + { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/attribute/Attribute;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Ljava/util/Collection;"; let res = self.jni_ref().call_method( &self.jni_object(), - "getPage", + "getAttributeModifiers", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::attribute::AttributeModifier::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(Some(new_vec)) } - /// Sets the specified page in the book. Pages of the book must be - /// contiguous. - /// - /// The data can be up to 1024 characters in length, additional characters - /// are truncated. + /// Add an Attribute and it's Modifier. + /// AttributeModifiers can now support {@link EquipmentSlot}s. + /// If not set, the {@link AttributeModifier} will be active in ALL slots. /// - /// Pages are 1-indexed. - pub fn set_page( + /// Two {@link AttributeModifier}s that have the same {@link java.util.UUID} + /// cannot exist on the same Attribute. + pub fn add_attribute_modifier( &self, - page: i32, - data: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(ILjava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Int(page); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(data.into())?, - )); + attribute: impl Into>, + modifier: impl Into>, + ) -> Result> { + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;Lorg/bukkit/attribute/AttributeModifier;)Z", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(modifier.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPage", + "addAttributeModifier", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), ], ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set all {@link Attribute}s and their {@link AttributeModifier}s. + /// To clear all currently set Attributes and AttributeModifiers use + /// null or an empty Multimap. + /// If not null nor empty, this will filter all entries that are not-null + /// and add them to the ItemStack. + pub fn set_attribute_modifiers( + &self, + attribute_modifiers: jni::objects::JObject<'mc>, + ) -> Result<(), Box> { + let sig = String::from("(Lcom/google/common/collect/Multimap;)V"); + let val_1 = jni::objects::JValueGen::Object(attribute_modifiers); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAttributeModifiers", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets all the pages in the book. - pub fn pages(&self) -> Result, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPages", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), - ); - } - Ok(new_vec) - } - /// Clears the existing book pages, and sets the book to use the provided - /// pages. Maximum 100 pages with 1024 characters per page. - pub fn set_pages(&self, pages: impl Into) -> Result<(), Box> { + /// Remove a specific {@link Attribute} and {@link AttributeModifier}. + /// AttributeModifiers are matched according to their {@link java.util.UUID}. + pub fn remove_attribute_modifier( + &self, + attribute: impl Into>, + modifier: std::option::Option>>, + ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(pages.into())?, - )); + sig += "Lorg/bukkit/attribute/Attribute;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); args.push(val_1); - sig += ")V"; - let res = self + if let Some(a) = modifier { + sig += "Lorg/bukkit/attribute/AttributeModifier;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeAttributeModifier", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get this ItemMeta as an NBT string. If this ItemMeta does not have any + /// NBT, then {@code "{}"} will be returned. + /// + /// This string should NEVER be relied upon as a serializable value. If + /// serialization is desired, the {@link ConfigurationSerializable} API should be used + /// instead. + pub fn as_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self .jni_ref() - .call_method(&self.jni_object(), "setPages", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Get this ItemMeta as a component-compliant string. If this ItemMeta does + /// not contain any components, then {@code "[]"} will be returned. + /// + /// The result of this method should yield a string representing the components + /// altered by this ItemMeta instance. When passed to {@link ItemFactory#createItemStack(String)} + /// with a prepended item type, it will create an ItemStack that has an ItemMeta + /// matching this ItemMeta instance exactly. Note that this method returns + /// ONLY the components and cannot be passed to createItemStack() alone. + /// An example may look something like this: + ///
+    /// ItemStack itemStack = // ... an item stack obtained from somewhere
+    /// ItemMeta itemMeta = itemStack.getItemMeta();
+    /// String components = itemMeta.getAsComponentString(); // example: "[minecraft:damage=53]"
+    /// String itemTypeKey = itemStack.getType().getKey().toString(); // example: "minecraft:diamond_sword"
+    /// String itemAsString = itemTypeKey + components; // results in: "minecraft:diamond_sword[minecraft:damage=53]"
+    /// ItemStack recreatedItemStack = Bukkit.getItemFactory().createItemStack(itemAsString);
+    /// assert itemStack.isSimilar(recreatedItemStack); // Should be true*
+    /// 
+ /// + /// *Components not represented or explicitly overridden by this ItemMeta instance + /// will not be included in the resulting string and therefore may result in ItemStacks + /// that do not match exactly. For example, if {@link #setDisplayName(String)} + /// is not set, then the custom name component will not be included. Or if this ItemMeta + /// is a PotionMeta, it will not include any components related to lodestone compasses, + /// banners, or books, etc., only components modifiable by a PotionMeta instance. + /// + /// This string should NEVER be relied upon as a serializable value. If + /// serialization is desired, the {@link ConfigurationSerializable} API should be used + /// instead. + pub fn as_component_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAsComponentString", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + #[deprecated] + /// Returns a public custom tag container capable of storing tags on the item. Those tags will be sent to the client with all of their content, so the client is capable of reading them. This will result in the player seeing a NBT Tag notification on the item. These tags can also be modified by the client once in creative mode + pub fn custom_tag_container( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/tags/CustomItemTagContainer;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCustomTagContainer", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::tags::CustomItemTagContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Adds new pages to the end of the book. Up to a maximum of 100 pages with - /// 1024 characters per page. - pub fn add_page(&self, pages: impl Into) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(pages.into())?, - )); + /// Internal use only! Do not use under any circumstances! + pub fn set_version(&self, version: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(version); let res = self.jni_ref().call_method( &self.jni_object(), - "addPage", + "setVersion", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the number of pages in the book. - pub fn page_count(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPageCount", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - - pub fn clone( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/WritableBookMeta;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::WritableBookMeta::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BookMeta<'mc> { - fn into(self) -> crate::inventory::meta::WritableBookMeta<'mc> { - crate::inventory::meta::WritableBookMeta::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BookMeta into crate::inventory::meta::WritableBookMeta") - } -} -pub enum BookMetaGeneration<'mc> {} -impl<'mc> std::fmt::Display for BookMetaGeneration<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> BookMetaGeneration<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/inventory/meta/BookMeta/Generation"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/inventory/meta/BookMeta/Generation;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } +impl<'mc> Into> for SpawnEggMeta<'mc> { + fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { + crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) + .expect("Error converting SpawnEggMeta into crate::inventory::meta::ItemMeta") } } - #[repr(C)] -pub struct BookMetaGenerationStruct<'mc>( +pub struct AxolotlBucketMeta<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BookMetaGeneration<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for BookMetaGeneration<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate BookMetaGeneration from null object.").into(), - ); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/inventory/meta/BookMeta/Generation")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a BookMetaGeneration object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for BookMetaGenerationStruct<'mc> { +impl<'mc> JNIRaw<'mc> for AxolotlBucketMeta<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3765,75 +5281,21 @@ impl<'mc> JNIRaw<'mc> for BookMetaGenerationStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BookMetaGenerationStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for AxolotlBucketMeta<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate BookMetaGenerationStruct from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate AxolotlBucketMeta from null object.").into(), + ); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/inventory/meta/BookMeta/Generation")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a BookMetaGenerationStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> BookMetaGenerationStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/BookMeta/Generation;"); - let cls = jni.find_class("org/bukkit/inventory/meta/BookMeta/Generation"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::inventory::meta::BookMetaGeneration::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct BannerMeta<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for BannerMeta<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for BannerMeta<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate BannerMeta from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/BannerMeta")?; + env.validate_name(&obj, "org/bukkit/inventory/meta/AxolotlBucketMeta")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BannerMeta object, got {}", + "Invalid argument passed. Expected a AxolotlBucketMeta object, got {}", name ) .into()) @@ -3843,147 +5305,64 @@ impl<'mc> JNIInstantiatable<'mc> for BannerMeta<'mc> { } } -impl<'mc> BannerMeta<'mc> { - /// Returns a list of patterns on this banner - pub fn patterns( +impl<'mc> AxolotlBucketMeta<'mc> { + /// Get the variant of the axolotl in the bucket. + /// + /// Plugins should check that hasVariant() returns true before + /// calling this method. + pub fn variant( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Axolotl/Variant;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPatterns", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::block::banner::Pattern::from_raw( - &self.jni_ref(), - obj, - )?); - } - Ok(new_vec) - } - /// Sets the patterns used on this banner - pub fn set_patterns( - &self, - patterns: Vec>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/List;)V"); - let raw_val_1 = self - .jni_ref() - .new_object("java/util/ArrayList", "()V", vec![])?; - for v in patterns { - let map_val_0 = jni::objects::JValueGen::Object(v); - self.jni_ref().call_method( - &raw_val_1, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_1 = jni::objects::JValueGen::Object(raw_val_1); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPatterns", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::entity::AxolotlVariant::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Adds a new pattern on top of the existing - /// patterns - pub fn add_pattern( + /// Set the variant of this axolotl in the bucket. + pub fn set_variant( &self, - pattern: impl Into>, + variant: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/banner/Pattern;)V"); + let sig = String::from("(Lorg/bukkit/entity/Axolotl/Variant;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(pattern.into().jni_object().clone()) + jni::objects::JObject::from_raw(variant.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "addPattern", + "setVariant", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the pattern at the specified index - pub fn get_pattern( - &self, - i: i32, - ) -> Result, Box> { - let sig = String::from("(I)Lorg/bukkit/block/banner/Pattern;"); - let val_1 = jni::objects::JValueGen::Int(i); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPattern", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Checks for existence of a variant tag indicating a specific axolotl will be + /// spawned. + pub fn has_variant(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasVariant", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::banner::Pattern::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Removes the pattern at the specified index - pub fn remove_pattern( + + pub fn clone( &self, - i: i32, - ) -> Result, Box> { - let sig = String::from("(I)Lorg/bukkit/block/banner/Pattern;"); - let val_1 = jni::objects::JValueGen::Int(i); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removePattern", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/AxolotlBucketMeta;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::banner::Pattern::from_raw(&self.jni_ref(), unsafe { + crate::inventory::meta::AxolotlBucketMeta::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the pattern at the specified index - pub fn set_pattern( - &self, - i: i32, - pattern: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(ILorg/bukkit/block/banner/Pattern;)V"); - let val_1 = jni::objects::JValueGen::Int(i); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(pattern.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPattern", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns the number of patterns on this - /// banner - pub fn number_of_patterns(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "numberOfPatterns", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } /// Checks for existence of a display name. pub fn has_display_name(&self) -> Result> { let sig = String::from("()Z"); @@ -4737,6 +6116,68 @@ impl<'mc> BannerMeta<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( + &self, + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) + } + /// Sets the item tool. + pub fn set_jukebox_playable( + &self, + jukebox_playable: impl Into>, + ) -> Result<(), Box> { + let sig = + String::from("(Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setJukeboxPlayable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } /// Checks for the existence of any AttributeModifiers. pub fn has_attribute_modifiers(&self) -> Result> { let sig = String::from("()Z"); @@ -4963,74 +6404,24 @@ impl<'mc> BannerMeta<'mc> { Ok(()) } - pub fn clone( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/ItemMeta;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Creates a Map representation of this class. - /// - /// This class must provide a method to restore this class, as defined in - /// the {@link ConfigurationSerializable} interface javadocs. - pub fn serialize( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPersistentDataContainer", - sig.as_str(), - args, - ); - let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BannerMeta<'mc> { +impl<'mc> Into> for AxolotlBucketMeta<'mc> { fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BannerMeta into crate::inventory::meta::ItemMeta") + .expect("Error converting AxolotlBucketMeta into crate::inventory::meta::ItemMeta") } } #[repr(C)] -pub struct SpawnEggMeta<'mc>( +pub struct EnchantmentStorageMeta<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for SpawnEggMeta<'mc> { +impl<'mc> JNIRaw<'mc> for EnchantmentStorageMeta<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -5038,18 +6429,22 @@ impl<'mc> JNIRaw<'mc> for SpawnEggMeta<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for SpawnEggMeta<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EnchantmentStorageMeta<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate SpawnEggMeta from null object.").into()); + return Err(eyre::eyre!( + "Tried to instantiate EnchantmentStorageMeta from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/SpawnEggMeta")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/inventory/meta/EnchantmentStorageMeta")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SpawnEggMeta object, got {}", + "Invalid argument passed. Expected a EnchantmentStorageMeta object, got {}", name ) .into()) @@ -5059,99 +6454,145 @@ impl<'mc> JNIInstantiatable<'mc> for SpawnEggMeta<'mc> { } } -impl<'mc> SpawnEggMeta<'mc> { - #[deprecated] - /// Get the type of entity this egg will spawn. - pub fn spawned_type( +impl<'mc> EnchantmentStorageMeta<'mc> { + /// Checks for the existence of any stored enchantments. + pub fn has_stored_enchants(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasStoredEnchants", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks for storage of the specified enchantment. + pub fn has_stored_enchant( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSpawnedType", sig.as_str(), vec![]); + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasStoredEnchant", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks for the level of the stored enchantment. + pub fn get_stored_enchant_level( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)I"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getStoredEnchantLevel", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets a copy the stored enchantments in this ItemMeta. + pub fn stored_enchants( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Map;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getStoredEnchants", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - #[deprecated] - /// Set the type of entity this egg will spawn. - pub fn set_spawned_type( + /// Stores the specified enchantment in this item meta. + pub fn add_stored_enchant( &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/EntityType;)V"); + ench: impl Into>, + level: i32, + ignore_level_restriction: bool, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;IZ)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Int(level); + let val_3 = jni::objects::JValueGen::Bool(ignore_level_restriction.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setSpawnedType", + "addStoredEnchant", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the {@link EntitySnapshot} that will be spawned by this spawn egg or null if no entity - /// has been set. - /// - /// - /// All applicable data from the egg will be copied, such as custom name, health, - /// and velocity. - /// - pub fn spawned_entity( + /// Remove the specified stored enchantment from this item meta. + pub fn remove_stored_enchant( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getSpawnedEntity", + "removeStoredEnchant", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::EntitySnapshot::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Sets the {@link EntitySnapshot} that will be spawned by this spawn egg. - /// - /// - /// All applicable data from the entity will be copied, such as custom name, - /// health, and velocity. - /// - pub fn set_spawned_entity( + /// Checks if the specified enchantment conflicts with any enchantments in + /// this ItemMeta. + pub fn has_conflicting_stored_enchant( &self, - snapshot: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/EntitySnapshot;)V"); + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(snapshot.into().jni_object().clone()) + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setSpawnedEntity", + "hasConflictingStoredEnchant", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } pub fn clone( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/SpawnEggMeta;"); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/EnchantmentStorageMeta;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::SpawnEggMeta::from_raw(&self.jni_ref(), unsafe { + crate::inventory::meta::EnchantmentStorageMeta::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -5908,6 +7349,68 @@ impl<'mc> SpawnEggMeta<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( + &self, + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) + } + /// Sets the item tool. + pub fn set_jukebox_playable( + &self, + jukebox_playable: impl Into>, + ) -> Result<(), Box> { + let sig = + String::from("(Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setJukeboxPlayable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } /// Checks for the existence of any AttributeModifiers. pub fn has_attribute_modifiers(&self) -> Result> { let sig = String::from("()Z"); @@ -6133,62 +7636,25 @@ impl<'mc> SpawnEggMeta<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Creates a Map representation of this class. - /// - /// This class must provide a method to restore this class, as defined in - /// the {@link ConfigurationSerializable} interface javadocs. - pub fn serialize( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPersistentDataContainer", - sig.as_str(), - args, - ); - let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for SpawnEggMeta<'mc> { +impl<'mc> Into> for EnchantmentStorageMeta<'mc> { fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SpawnEggMeta into crate::inventory::meta::ItemMeta") + .expect("Error converting EnchantmentStorageMeta into crate::inventory::meta::ItemMeta") } } #[repr(C)] -pub struct AxolotlBucketMeta<'mc>( +pub struct SuspiciousStewMeta<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for AxolotlBucketMeta<'mc> { +impl<'mc> JNIRaw<'mc> for SuspiciousStewMeta<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6196,21 +7662,21 @@ impl<'mc> JNIRaw<'mc> for AxolotlBucketMeta<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for AxolotlBucketMeta<'mc> { +impl<'mc> JNIInstantiatable<'mc> for SuspiciousStewMeta<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate AxolotlBucketMeta from null object.").into(), + eyre::eyre!("Tried to instantiate SuspiciousStewMeta from null object.").into(), ); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/inventory/meta/AxolotlBucketMeta")?; + env.validate_name(&obj, "org/bukkit/inventory/meta/SuspiciousStewMeta")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a AxolotlBucketMeta object, got {}", + "Invalid argument passed. Expected a SuspiciousStewMeta object, got {}", name ) .into()) @@ -6218,63 +7684,127 @@ impl<'mc> JNIInstantiatable<'mc> for AxolotlBucketMeta<'mc> { Ok(Self(env.clone(), obj)) } } -} - -impl<'mc> AxolotlBucketMeta<'mc> { - /// Get the variant of the axolotl in the bucket. - /// - /// Plugins should check that hasVariant() returns true before - /// calling this method. - pub fn variant( +} + +impl<'mc> SuspiciousStewMeta<'mc> { + /// Checks for the presence of custom potion effects. + pub fn has_custom_effects(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasCustomEffects", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets an immutable list containing all custom potion effects applied to + /// this suspicious stew. + /// + /// Plugins should check that hasCustomEffects() returns true before calling + /// this method. + pub fn custom_effects( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCustomEffects", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Adds a custom potion effect to this suspicious stew. + pub fn add_custom_effect( + &self, + effect: impl Into>, + overwrite: bool, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffect;Z)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Bool(overwrite.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addCustomEffect", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Removes a custom potion effect from this suspicious stew. + pub fn remove_custom_effect( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Axolotl/Variant;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVariant", sig.as_str(), vec![]); + val_type: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeCustomEffect", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - crate::entity::AxolotlVariant::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Set the variant of this axolotl in the bucket. - pub fn set_variant( + /// Checks for a specific custom potion effect type on this suspicious stew. + pub fn has_custom_effect( &self, - variant: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/Axolotl/Variant;)V"); + val_type: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(variant.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVariant", + "hasCustomEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Checks for existence of a variant tag indicating a specific axolotl will be - /// spawned. - pub fn has_variant(&self) -> Result> { + /// Removes all custom potion effects from this suspicious stew. + pub fn clear_custom_effects(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasVariant", sig.as_str(), vec![]); + let res = self.jni_ref().call_method( + &self.jni_object(), + "clearCustomEffects", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } pub fn clone( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/AxolotlBucketMeta;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/SuspiciousStewMeta;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::AxolotlBucketMeta::from_raw(&self.jni_ref(), unsafe { + crate::inventory::meta::SuspiciousStewMeta::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -7031,6 +8561,68 @@ impl<'mc> AxolotlBucketMeta<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( + &self, + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) + } + /// Sets the item tool. + pub fn set_jukebox_playable( + &self, + jukebox_playable: impl Into>, + ) -> Result<(), Box> { + let sig = + String::from("(Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setJukeboxPlayable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } /// Checks for the existence of any AttributeModifiers. pub fn has_attribute_modifiers(&self) -> Result> { let sig = String::from("()Z"); @@ -7256,62 +8848,25 @@ impl<'mc> AxolotlBucketMeta<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Creates a Map representation of this class. - /// - /// This class must provide a method to restore this class, as defined in - /// the {@link ConfigurationSerializable} interface javadocs. - pub fn serialize( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPersistentDataContainer", - sig.as_str(), - args, - ); - let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for AxolotlBucketMeta<'mc> { +impl<'mc> Into> for SuspiciousStewMeta<'mc> { fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) - .expect("Error converting AxolotlBucketMeta into crate::inventory::meta::ItemMeta") + .expect("Error converting SuspiciousStewMeta into crate::inventory::meta::ItemMeta") } } #[repr(C)] -pub struct EnchantmentStorageMeta<'mc>( +pub struct CrossbowMeta<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EnchantmentStorageMeta<'mc> { +impl<'mc> JNIRaw<'mc> for CrossbowMeta<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -7319,22 +8874,18 @@ impl<'mc> JNIRaw<'mc> for EnchantmentStorageMeta<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EnchantmentStorageMeta<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CrossbowMeta<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate EnchantmentStorageMeta from null object." - ) - .into()); + return Err(eyre::eyre!("Tried to instantiate CrossbowMeta from null object.").into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/inventory/meta/EnchantmentStorageMeta")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/CrossbowMeta")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EnchantmentStorageMeta object, got {}", + "Invalid argument passed. Expected a CrossbowMeta object, got {}", name ) .into()) @@ -7344,147 +8895,86 @@ impl<'mc> JNIInstantiatable<'mc> for EnchantmentStorageMeta<'mc> { } } -impl<'mc> EnchantmentStorageMeta<'mc> { - /// Checks for the existence of any stored enchantments. - pub fn has_stored_enchants(&self) -> Result> { +impl<'mc> CrossbowMeta<'mc> { + /// Returns whether the item has any charged projectiles. + pub fn has_charged_projectiles(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasStoredEnchants", + "hasChargedProjectiles", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Checks for storage of the specified enchantment. - pub fn has_stored_enchant( - &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasStoredEnchant", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Checks for the level of the stored enchantment. - pub fn get_stored_enchant_level( - &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)I"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getStoredEnchantLevel", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets a copy the stored enchantments in this ItemMeta. - pub fn stored_enchants( + /// Returns an immutable list of the projectiles charged on this item. + pub fn charged_projectiles( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getStoredEnchants", + "getChargedProjectiles", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Stores the specified enchantment in this item meta. - pub fn add_stored_enchant( - &self, - ench: impl Into>, - level: i32, - ignore_level_restriction: bool, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;IZ)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(level); - let val_3 = jni::objects::JValueGen::Bool(ignore_level_restriction.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addStoredEnchant", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::inventory::ItemStack::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Remove the specified stored enchantment from this item meta. - pub fn remove_stored_enchant( + /// Sets the projectiles charged on this item. + /// Removes all projectiles when given null. + pub fn set_charged_projectiles( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) - }); + projectiles: Vec>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/List;)V"); + let raw_val_1 = self + .jni_ref() + .new_object("java/util/ArrayList", "()V", vec![])?; + for v in projectiles { + let map_val_0 = jni::objects::JValueGen::Object(v); + self.jni_ref().call_method( + &raw_val_1, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_1 = jni::objects::JValueGen::Object(raw_val_1); let res = self.jni_ref().call_method( &self.jni_object(), - "removeStoredEnchant", + "setChargedProjectiles", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Checks if the specified enchantment conflicts with any enchantments in - /// this ItemMeta. - pub fn has_conflicting_stored_enchant( + /// Adds a charged projectile to this item. + pub fn add_charged_projectile( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasConflictingStoredEnchant", + "addChargedProjectile", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn clone( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/EnchantmentStorageMeta;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::EnchantmentStorageMeta::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } /// Checks for existence of a display name. pub fn has_display_name(&self) -> Result> { @@ -7805,9696 +9295,10321 @@ impl<'mc> EnchantmentStorageMeta<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Adds the specified enchantment to this item meta. - pub fn add_enchant( - &self, - ench: impl Into>, - level: i32, - ignore_level_restriction: bool, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;IZ)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(level); - let val_3 = jni::objects::JValueGen::Bool(ignore_level_restriction.into()); + /// Adds the specified enchantment to this item meta. + pub fn add_enchant( + &self, + ench: impl Into>, + level: i32, + ignore_level_restriction: bool, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;IZ)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(level); + let val_3 = jni::objects::JValueGen::Bool(ignore_level_restriction.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addEnchant", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Removes the specified enchantment from this item meta. + pub fn remove_enchant( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeEnchant", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Removes all enchantments from this item meta. + pub fn remove_enchantments(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeEnchantments", + sig.as_str(), + vec![], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the specified enchantment conflicts with any enchantments in + /// this ItemMeta. + pub fn has_conflicting_enchant( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasConflictingEnchant", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set itemflags which should be ignored when rendering a ItemStack in the Client. This Method does silently ignore double set itemFlags. + pub fn add_item_flags( + &self, + item_flags: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addItemFlags", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Remove specific set of itemFlags. This tells the Client it should render it again. This Method does silently ignore double removed itemFlags. + pub fn remove_item_flags( + &self, + item_flags: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeItemFlags", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get current set itemFlags. The collection returned is unmodifiable. + pub fn item_flags( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemFlags", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Check if the specified flag is present on this item. + pub fn has_item_flag( + &self, + flag: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(flag.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasItemFlag", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets if this item has hide_tooltip set. An item with this set will not + /// show any tooltip whatsoever. + pub fn is_hide_tooltip(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isHideTooltip", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets if this item has hide_tooltip set. An item with this set will not + /// show any tooltip whatsoever. + pub fn set_hide_tooltip(&self, hide_tooltip: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(hide_tooltip.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setHideTooltip", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Return if the unbreakable tag is true. An unbreakable item will not lose + /// durability. + pub fn is_unbreakable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isUnbreakable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the unbreakable tag. An unbreakable item will not lose durability. + pub fn set_unbreakable(&self, unbreakable: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(unbreakable.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setUnbreakable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if an enchantment_glint_override is set. + pub fn has_enchantment_glint_override(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "addEnchant", + "hasEnchantmentGlintOverride", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes the specified enchantment from this item meta. - pub fn remove_enchant( - &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) - }); + /// Sets the enchantment_glint_override. If true, the item will glint, even + /// without enchantments; if false, the item will not glint, even with + /// enchantments. + /// Plugins should check {@link #hasEnchantmentGlintOverride()} before + /// calling this method. + pub fn enchantment_glint_override(&self) -> Result> { + let sig = String::from("()Ljava/lang/Boolean;"); let res = self.jni_ref().call_method( &self.jni_object(), - "removeEnchant", + "getEnchantmentGlintOverride", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes all enchantments from this item meta. - pub fn remove_enchantments(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Sets the enchantment_glint_override. If true, the item will glint, even + /// without enchantments; if false, the item will not glint, even with + /// enchantments. If null, the override will be cleared. + pub fn set_enchantment_glint_override( + &self, + val_override: bool, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/Boolean;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Boolean", + "(Ljava/Lang/Object;)V", + vec![val_override.into()], + )?); let res = self.jni_ref().call_method( &self.jni_object(), - "removeEnchantments", + "setEnchantmentGlintOverride", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if the specified enchantment conflicts with any enchantments in - /// this ItemMeta. - pub fn has_conflicting_enchant( + /// Checks if this item is fire_resistant. If true, it will not burn in fire + /// or lava. + pub fn is_fire_resistant(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isFireResistant", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets if this item is fire_resistant. If true, it will not burn in fire + /// or lava. + pub fn set_fire_resistant( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) - }); + fire_resistant: bool, + ) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire_resistant.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "hasConflictingEnchant", + "setFireResistant", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the max_stack_size is set. + pub fn has_max_stack_size(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasMaxStackSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set itemflags which should be ignored when rendering a ItemStack in the Client. This Method does silently ignore double set itemFlags. - pub fn add_item_flags( - &self, - item_flags: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) - }); + /// Gets the max_stack_size. This is the maximum amount which an item will + /// stack. + pub fn max_stack_size(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the max_stack_size. This is the maximum amount which an item will + /// stack. + pub fn set_max_stack_size(&self, max: i32) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/Integer;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Integer", + "(Ljava/Lang/Object;)V", + vec![max.into()], + )?); let res = self.jni_ref().call_method( &self.jni_object(), - "addItemFlags", + "setMaxStackSize", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Remove specific set of itemFlags. This tells the Client it should render it again. This Method does silently ignore double removed itemFlags. - pub fn remove_item_flags( + /// Gets if the rarity is set. + pub fn has_rarity(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasRarity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the item rarity. + /// Plugins should check {@link #hasRarity()} before calling this method. + pub fn rarity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemRarity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRarity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemRarity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the item rarity. + pub fn set_rarity( &self, - item_flags: impl Into>, + rarity: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); + let sig = String::from("(Lorg/bukkit/inventory/ItemRarity;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) + jni::objects::JObject::from_raw(rarity.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeItemFlags", + "setRarity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get current set itemFlags. The collection returned is unmodifiable. - pub fn item_flags( + /// Checks if the food is set. + pub fn has_food(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasFood", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the food set on this item, or creates an empty food instance. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with {@link #setFood(FoodComponent)} to + /// apply the changes. + pub fn food( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemFlags", sig.as_str(), vec![]); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/FoodComponent;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFood", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + crate::inventory::meta::components::FoodComponent::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Check if the specified flag is present on this item. - pub fn has_item_flag( + /// Sets the item food. + pub fn set_food( &self, - flag: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)Z"); + food: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/FoodComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(flag.into().jni_object().clone()) + jni::objects::JObject::from_raw(food.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasItemFlag", + "setFood", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets if this item has hide_tooltip set. An item with this set will not - /// show any tooltip whatsoever. - pub fn is_hide_tooltip(&self) -> Result> { + /// Checks if the tool is set. + pub fn has_tool(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isHideTooltip", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasTool", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets if this item has hide_tooltip set. An item with this set will not - /// show any tooltip whatsoever. - pub fn set_hide_tooltip(&self, hide_tooltip: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(hide_tooltip.into()); + /// Gets the tool set on this item, or creates an empty tool instance. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with {@link #setTool(ToolComponent)} to + /// apply the changes. + pub fn tool( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/ToolComponent;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::components::ToolComponent::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the item tool. + pub fn set_tool( + &self, + tool: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(tool.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setHideTooltip", + "setTool", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Return if the unbreakable tag is true. An unbreakable item will not lose - /// durability. - pub fn is_unbreakable(&self) -> Result> { + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isUnbreakable", sig.as_str(), vec![]); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the unbreakable tag. An unbreakable item will not lose durability. - pub fn set_unbreakable(&self, unbreakable: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(unbreakable.into()); + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( + &self, + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setUnbreakable", + "getJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) + } + /// Sets the item tool. + pub fn set_jukebox_playable( + &self, + jukebox_playable: impl Into>, + ) -> Result<(), Box> { + let sig = + String::from("(Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setJukeboxPlayable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if an enchantment_glint_override is set. - pub fn has_enchantment_glint_override(&self) -> Result> { + /// Checks for the existence of any AttributeModifiers. + pub fn has_attribute_modifiers(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasEnchantmentGlintOverride", + "hasAttributeModifiers", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the enchantment_glint_override. If true, the item will glint, even - /// without enchantments; if false, the item will not glint, even with - /// enchantments. - /// Plugins should check {@link #hasEnchantmentGlintOverride()} before - /// calling this method. - pub fn enchantment_glint_override(&self) -> Result> { - let sig = String::from("()Ljava/lang/Boolean;"); + /// Return an immutable copy of all {@link AttributeModifier}s + /// for a given {@link Attribute} + pub fn get_attribute_modifiers( + &self, + attribute: impl Into>, + ) -> Result>>, Box> + { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/attribute/Attribute;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Ljava/util/Collection;"; let res = self.jni_ref().call_method( &self.jni_object(), - "getEnchantmentGlintOverride", + "getAttributeModifiers", sig.as_str(), - vec![], + args, + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::attribute::AttributeModifier::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(Some(new_vec)) + } + /// Add an Attribute and it's Modifier. + /// AttributeModifiers can now support {@link EquipmentSlot}s. + /// If not set, the {@link AttributeModifier} will be active in ALL slots. + /// + /// Two {@link AttributeModifier}s that have the same {@link java.util.UUID} + /// cannot exist on the same Attribute. + pub fn add_attribute_modifier( + &self, + attribute: impl Into>, + modifier: impl Into>, + ) -> Result> { + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;Lorg/bukkit/attribute/AttributeModifier;)Z", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(modifier.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addAttributeModifier", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the enchantment_glint_override. If true, the item will glint, even - /// without enchantments; if false, the item will not glint, even with - /// enchantments. If null, the override will be cleared. - pub fn set_enchantment_glint_override( + /// Set all {@link Attribute}s and their {@link AttributeModifier}s. + /// To clear all currently set Attributes and AttributeModifiers use + /// null or an empty Multimap. + /// If not null nor empty, this will filter all entries that are not-null + /// and add them to the ItemStack. + pub fn set_attribute_modifiers( &self, - val_override: bool, + attribute_modifiers: jni::objects::JObject<'mc>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/Boolean;)V"); - let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( - "java/lang/Boolean", - "(Ljava/Lang/Object;)V", - vec![val_override.into()], - )?); + let sig = String::from("(Lcom/google/common/collect/Multimap;)V"); + let val_1 = jni::objects::JValueGen::Object(attribute_modifiers); let res = self.jni_ref().call_method( &self.jni_object(), - "setEnchantmentGlintOverride", + "setAttributeModifiers", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if this item is fire_resistant. If true, it will not burn in fire - /// or lava. - pub fn is_fire_resistant(&self) -> Result> { - let sig = String::from("()Z"); + /// Remove a specific {@link Attribute} and {@link AttributeModifier}. + /// AttributeModifiers are matched according to their {@link java.util.UUID}. + pub fn remove_attribute_modifier( + &self, + attribute: impl Into>, + modifier: std::option::Option>>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/attribute/Attribute;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = modifier { + sig += "Lorg/bukkit/attribute/AttributeModifier;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeAttributeModifier", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get this ItemMeta as an NBT string. If this ItemMeta does not have any + /// NBT, then {@code "{}"} will be returned. + /// + /// This string should NEVER be relied upon as a serializable value. If + /// serialization is desired, the {@link ConfigurationSerializable} API should be used + /// instead. + pub fn as_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isFireResistant", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets if this item is fire_resistant. If true, it will not burn in fire - /// or lava. - pub fn set_fire_resistant( + /// Get this ItemMeta as a component-compliant string. If this ItemMeta does + /// not contain any components, then {@code "[]"} will be returned. + /// + /// The result of this method should yield a string representing the components + /// altered by this ItemMeta instance. When passed to {@link ItemFactory#createItemStack(String)} + /// with a prepended item type, it will create an ItemStack that has an ItemMeta + /// matching this ItemMeta instance exactly. Note that this method returns + /// ONLY the components and cannot be passed to createItemStack() alone. + /// An example may look something like this: + ///
+    /// ItemStack itemStack = // ... an item stack obtained from somewhere
+    /// ItemMeta itemMeta = itemStack.getItemMeta();
+    /// String components = itemMeta.getAsComponentString(); // example: "[minecraft:damage=53]"
+    /// String itemTypeKey = itemStack.getType().getKey().toString(); // example: "minecraft:diamond_sword"
+    /// String itemAsString = itemTypeKey + components; // results in: "minecraft:diamond_sword[minecraft:damage=53]"
+    /// ItemStack recreatedItemStack = Bukkit.getItemFactory().createItemStack(itemAsString);
+    /// assert itemStack.isSimilar(recreatedItemStack); // Should be true*
+    /// 
+ /// + /// *Components not represented or explicitly overridden by this ItemMeta instance + /// will not be included in the resulting string and therefore may result in ItemStacks + /// that do not match exactly. For example, if {@link #setDisplayName(String)} + /// is not set, then the custom name component will not be included. Or if this ItemMeta + /// is a PotionMeta, it will not include any components related to lodestone compasses, + /// banners, or books, etc., only components modifiable by a PotionMeta instance. + /// + /// This string should NEVER be relied upon as a serializable value. If + /// serialization is desired, the {@link ConfigurationSerializable} API should be used + /// instead. + pub fn as_component_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAsComponentString", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + #[deprecated] + /// Returns a public custom tag container capable of storing tags on the item. Those tags will be sent to the client with all of their content, so the client is capable of reading them. This will result in the player seeing a NBT Tag notification on the item. These tags can also be modified by the client once in creative mode + pub fn custom_tag_container( &self, - fire_resistant: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire_resistant.into()); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/tags/CustomItemTagContainer;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCustomTagContainer", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::tags::CustomItemTagContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Internal use only! Do not use under any circumstances! + pub fn set_version(&self, version: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(version); let res = self.jni_ref().call_method( &self.jni_object(), - "setFireResistant", + "setVersion", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the max_stack_size is set. - pub fn has_max_stack_size(&self) -> Result> { + + pub fn clone( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/ItemMeta;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for CrossbowMeta<'mc> { + fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { + crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) + .expect("Error converting CrossbowMeta into crate::inventory::meta::ItemMeta") + } +} +#[repr(C)] +pub struct CompassMeta<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for CompassMeta<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for CompassMeta<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate CompassMeta from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/CompassMeta")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a CompassMeta object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> CompassMeta<'mc> { + /// Checks if this compass has been paired to a lodestone. + pub fn has_lodestone(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasMaxStackSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasLodestone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the max_stack_size. This is the maximum amount which an item will - /// stack. - pub fn max_stack_size(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the location that this compass will point to. + /// Check {@link #hasLodestone()} first! + pub fn lodestone(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLodestone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Sets the max_stack_size. This is the maximum amount which an item will - /// stack. - pub fn set_max_stack_size(&self, max: i32) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/Integer;)V"); - let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( - "java/lang/Integer", - "(Ljava/Lang/Object;)V", - vec![max.into()], - )?); + /// Sets the location this lodestone compass will point to. + pub fn set_lodestone( + &self, + lodestone: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Location;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(lodestone.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxStackSize", + "setLodestone", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the rarity is set. - pub fn has_rarity(&self) -> Result> { + /// Gets if this compass is tracking a specific lodestone. + /// If true the compass will only work if there is a lodestone at the tracked + /// location. + pub fn is_lodestone_tracked(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasRarity", sig.as_str(), vec![]); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isLodestoneTracked", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the item rarity. - /// Plugins should check {@link #hasRarity()} before calling this method. - pub fn rarity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemRarity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getRarity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemRarity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the item rarity. - pub fn set_rarity( - &self, - rarity: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemRarity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(rarity.into().jni_object().clone()) - }); + /// Sets if this compass is tracking a specific lodestone. + /// If true the compass will only work if there is a lodestone at the tracked + /// location. + pub fn set_lodestone_tracked(&self, tracked: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(tracked.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setRarity", + "setLodestoneTracked", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if the food is set. - pub fn has_food(&self) -> Result> { - let sig = String::from("()Z"); + + pub fn clone( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/CompassMeta;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "hasFood", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::CompassMeta::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Checks for existence of a display name. + pub fn has_display_name(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasDisplayName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the food set on this item, or creates an empty food instance. + /// Gets the display name that is set. /// - /// The returned component is a snapshot of its current state and does not - /// reflect a live view of what is on an item. After changing any value on - /// this component, it must be set with {@link #setFood(FoodComponent)} to - /// apply the changes. - pub fn food( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/components/FoodComponent;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFood", sig.as_str(), vec![]); + /// Plugins should check that hasDisplayName() returns true + /// before calling this method. + pub fn display_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDisplayName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::components::FoodComponent::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets the item food. - pub fn set_food( + /// Sets the display name. + pub fn set_display_name( &self, - food: impl Into>, + name: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/components/FoodComponent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(food.into().jni_object().clone()) - }); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setFood", + "setDisplayName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if the tool is set. - pub fn has_tool(&self) -> Result> { + /// Checks for existence of an item name. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + pub fn has_item_name(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasTool", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasItemName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the tool set on this item, or creates an empty tool instance. + /// Gets the item name that is set. /// - /// The returned component is a snapshot of its current state and does not - /// reflect a live view of what is on an item. After changing any value on - /// this component, it must be set with {@link #setTool(ToolComponent)} to - /// apply the changes. - pub fn tool( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/components/ToolComponent;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + /// + /// Plugins should check that hasItemName() returns true before + /// calling this method. + pub fn item_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::components::ToolComponent::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets the item tool. - pub fn set_tool( - &self, - tool: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tool.into().jni_object().clone()) - }); + /// Sets the item name. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + pub fn set_item_name(&self, name: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setTool", + "setItemName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for the existence of any AttributeModifiers. - pub fn has_attribute_modifiers(&self) -> Result> { + #[deprecated] + /// Checks for existence of a localized name. + pub fn has_localized_name(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasAttributeModifiers", + "hasLocalizedName", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Return an immutable copy of all {@link AttributeModifier}s - /// for a given {@link Attribute} - pub fn get_attribute_modifiers( + #[deprecated] + /// Gets the localized display name that is set.Plugins should check that hasLocalizedName() returns true before calling this method. + pub fn localized_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLocalizedName", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + #[deprecated] + /// Sets the localized name. + pub fn set_localized_name( &self, - attribute: impl Into>, - ) -> Result>>, Box> - { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/attribute/Attribute;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Ljava/util/Collection;"; + name: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "getAttributeModifiers", + "setLocalizedName", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks for existence of lore. + pub fn has_lore(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasLore", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the lore that is set. + /// + /// Plugins should check if hasLore() returns true before + /// calling this method. + pub fn lore(&self) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLore", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::attribute::AttributeModifier::from_raw( - &self.jni_ref(), - obj, - )?); + new_vec.push( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); } Ok(Some(new_vec)) } - /// Add an Attribute and it's Modifier. - /// AttributeModifiers can now support {@link EquipmentSlot}s. - /// If not set, the {@link AttributeModifier} will be active in ALL slots. - /// - /// Two {@link AttributeModifier}s that have the same {@link java.util.UUID} - /// cannot exist on the same Attribute. - pub fn add_attribute_modifier( - &self, - attribute: impl Into>, - modifier: impl Into>, - ) -> Result> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;Lorg/bukkit/attribute/AttributeModifier;)Z", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(modifier.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addAttributeModifier", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Set all {@link Attribute}s and their {@link AttributeModifier}s. - /// To clear all currently set Attributes and AttributeModifiers use - /// null or an empty Multimap. - /// If not null nor empty, this will filter all entries that are not-null - /// and add them to the ItemStack. - pub fn set_attribute_modifiers( + /// Sets the lore for this item. + /// Removes lore when given null. + pub fn set_lore( &self, - attribute_modifiers: jni::objects::JObject<'mc>, + lore: Vec>, ) -> Result<(), Box> { - let sig = String::from("(Lcom/google/common/collect/Multimap;)V"); - let val_1 = jni::objects::JValueGen::Object(attribute_modifiers); + let sig = String::from("(Ljava/util/List;)V"); + let raw_val_1 = self + .jni_ref() + .new_object("java/util/ArrayList", "()V", vec![])?; + for v in lore { + let map_val_0 = jni::objects::JValueGen::Object(v); + self.jni_ref().call_method( + &raw_val_1, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_1 = jni::objects::JValueGen::Object(raw_val_1); let res = self.jni_ref().call_method( &self.jni_object(), - "setAttributeModifiers", + "setLore", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Remove a specific {@link Attribute} and {@link AttributeModifier}. - /// AttributeModifiers are matched according to their {@link java.util.UUID}. - pub fn remove_attribute_modifier( - &self, - attribute: impl Into>, - modifier: std::option::Option>>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/attribute/Attribute;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = modifier { - sig += "Lorg/bukkit/attribute/AttributeModifier;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Z"; + /// Checks for existence of custom model data. + /// + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + pub fn has_custom_model_data(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "removeAttributeModifier", + "hasCustomModelData", sig.as_str(), - args, + vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get this ItemMeta as an NBT string. If this ItemMeta does not have any - /// NBT, then {@code "{}"} will be returned. - /// - /// This string should NEVER be relied upon as a serializable value. If - /// serialization is desired, the {@link ConfigurationSerializable} API should be used - /// instead. - pub fn as_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Get this ItemMeta as a component-compliant string. If this ItemMeta does - /// not contain any components, then {@code "[]"} will be returned. - /// - /// The result of this method should yield a string representing the components - /// altered by this ItemMeta instance. When passed to {@link ItemFactory#createItemStack(String)} - /// with a prepended item type, it will create an ItemStack that has an ItemMeta - /// matching this ItemMeta instance exactly. Note that this method returns - /// ONLY the components and cannot be passed to createItemStack() alone. - /// An example may look something like this: - ///
-    /// ItemStack itemStack = // ... an item stack obtained from somewhere
-    /// ItemMeta itemMeta = itemStack.getItemMeta();
-    /// String components = itemMeta.getAsComponentString(); // example: "[minecraft:damage=53]"
-    /// String itemTypeKey = itemStack.getType().getKey().toString(); // example: "minecraft:diamond_sword"
-    /// String itemAsString = itemTypeKey + components; // results in: "minecraft:diamond_sword[minecraft:damage=53]"
-    /// ItemStack recreatedItemStack = Bukkit.getItemFactory().createItemStack(itemAsString);
-    /// assert itemStack.isSimilar(recreatedItemStack); // Should be true*
-    /// 
+ /// Gets the custom model data that is set. /// - /// *Components not represented or explicitly overridden by this ItemMeta instance - /// will not be included in the resulting string and therefore may result in ItemStacks - /// that do not match exactly. For example, if {@link #setDisplayName(String)} - /// is not set, then the custom name component will not be included. Or if this ItemMeta - /// is a PotionMeta, it will not include any components related to lodestone compasses, - /// banners, or books, etc., only components modifiable by a PotionMeta instance. + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. /// - /// This string should NEVER be relied upon as a serializable value. If - /// serialization is desired, the {@link ConfigurationSerializable} API should be used - /// instead. - pub fn as_component_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Plugins should check that hasCustomModelData() returns true + /// before calling this method. + pub fn custom_model_data(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getAsComponentString", + "getCustomModelData", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.i()?) } - #[deprecated] - /// Returns a public custom tag container capable of storing tags on the item. Those tags will be sent to the client with all of their content, so the client is capable of reading them. This will result in the player seeing a NBT Tag notification on the item. These tags can also be modified by the client once in creative mode - pub fn custom_tag_container( + /// Sets the custom model data. + /// + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + pub fn set_custom_model_data(&self, data: i32) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/Integer;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Integer", + "(Ljava/Lang/Object;)V", + vec![data.into()], + )?); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCustomModelData", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks for the existence of any enchantments. + pub fn has_enchants(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasEnchants", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks for existence of the specified enchantment. + pub fn has_enchant( &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/tags/CustomItemTagContainer;"); + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getCustomTagContainer", + "hasEnchant", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::tags::CustomItemTagContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Internal use only! Do not use under any circumstances! - pub fn set_version(&self, version: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(version); + /// Checks for the level of the specified enchantment. + pub fn get_enchant_level( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)I"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVersion", + "getEnchantLevel", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Creates a Map representation of this class. + /// Returns a copy the enchantments in this ItemMeta. /// - /// This class must provide a method to restore this class, as defined in - /// the {@link ConfigurationSerializable} interface javadocs. - pub fn serialize( + /// Returns an empty map if none. + pub fn enchants( &self, ) -> Result, Box> { let sig = String::from("()Ljava/util/Map;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEnchants", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( + /// Adds the specified enchantment to this item meta. + pub fn add_enchant( &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; + ench: impl Into>, + level: i32, + ignore_level_restriction: bool, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;IZ)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(level); + let val_3 = jni::objects::JValueGen::Bool(ignore_level_restriction.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "addEnchant", sig.as_str(), - args, + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for EnchantmentStorageMeta<'mc> { - fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { - crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EnchantmentStorageMeta into crate::inventory::meta::ItemMeta") - } -} -#[repr(C)] -pub struct SuspiciousStewMeta<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for SuspiciousStewMeta<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for SuspiciousStewMeta<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate SuspiciousStewMeta from null object.").into(), - ); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/inventory/meta/SuspiciousStewMeta")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a SuspiciousStewMeta object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + Ok(res.z()?) } -} - -impl<'mc> SuspiciousStewMeta<'mc> { - /// Checks for the presence of custom potion effects. - pub fn has_custom_effects(&self) -> Result> { - let sig = String::from("()Z"); + /// Removes the specified enchantment from this item meta. + pub fn remove_enchant( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasCustomEffects", + "removeEnchant", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets an immutable list containing all custom potion effects applied to - /// this suspicious stew. - /// - /// Plugins should check that hasCustomEffects() returns true before calling - /// this method. - pub fn custom_effects( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + /// Removes all enchantments from this item meta. + pub fn remove_enchantments(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCustomEffects", + "removeEnchantments", sig.as_str(), vec![], ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Adds a custom potion effect to this suspicious stew. - pub fn add_custom_effect( + /// Checks if the specified enchantment conflicts with any enchantments in + /// this ItemMeta. + pub fn has_conflicting_enchant( &self, - effect: impl Into>, - overwrite: bool, + ench: impl Into>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffect;Z)Z"); + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(effect.into().jni_object().clone()) + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Bool(overwrite.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "addCustomEffect", + "hasConflictingEnchant", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes a custom potion effect from this suspicious stew. - pub fn remove_custom_effect( + /// Set itemflags which should be ignored when rendering a ItemStack in the Client. This Method does silently ignore double set itemFlags. + pub fn add_item_flags( &self, - val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); + item_flags: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeCustomEffect", + "addItemFlags", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Checks for a specific custom potion effect type on this suspicious stew. - pub fn has_custom_effect( + /// Remove specific set of itemFlags. This tells the Client it should render it again. This Method does silently ignore double removed itemFlags. + pub fn remove_item_flags( &self, - val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); + item_flags: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasCustomEffect", + "removeItemFlags", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get current set itemFlags. The collection returned is unmodifiable. + pub fn item_flags( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemFlags", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Removes all custom potion effects from this suspicious stew. - pub fn clear_custom_effects(&self) -> Result> { - let sig = String::from("()Z"); + /// Check if the specified flag is present on this item. + pub fn has_item_flag( + &self, + flag: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(flag.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "clearCustomEffects", + "hasItemFlag", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - - pub fn clone( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/SuspiciousStewMeta;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::SuspiciousStewMeta::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Checks for existence of a display name. - pub fn has_display_name(&self) -> Result> { + /// Gets if this item has hide_tooltip set. An item with this set will not + /// show any tooltip whatsoever. + pub fn is_hide_tooltip(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasDisplayName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isHideTooltip", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the display name that is set. - /// - /// Plugins should check that hasDisplayName() returns true - /// before calling this method. - pub fn display_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDisplayName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Sets the display name. - pub fn set_display_name( - &self, - name: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + /// Sets if this item has hide_tooltip set. An item with this set will not + /// show any tooltip whatsoever. + pub fn set_hide_tooltip(&self, hide_tooltip: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(hide_tooltip.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setDisplayName", + "setHideTooltip", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of an item name. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - pub fn has_item_name(&self) -> Result> { + /// Return if the unbreakable tag is true. An unbreakable item will not lose + /// durability. + pub fn is_unbreakable(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasItemName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isUnbreakable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the item name that is set. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - /// - /// Plugins should check that hasItemName() returns true before - /// calling this method. - pub fn item_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Sets the item name. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - pub fn set_item_name(&self, name: impl Into) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + /// Sets the unbreakable tag. An unbreakable item will not lose durability. + pub fn set_unbreakable(&self, unbreakable: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(unbreakable.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemName", + "setUnbreakable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Checks for existence of a localized name. - pub fn has_localized_name(&self) -> Result> { + /// Gets if an enchantment_glint_override is set. + pub fn has_enchantment_glint_override(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasLocalizedName", + "hasEnchantmentGlintOverride", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Gets the localized display name that is set.Plugins should check that hasLocalizedName() returns true before calling this method. - pub fn localized_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Sets the enchantment_glint_override. If true, the item will glint, even + /// without enchantments; if false, the item will not glint, even with + /// enchantments. + /// Plugins should check {@link #hasEnchantmentGlintOverride()} before + /// calling this method. + pub fn enchantment_glint_override(&self) -> Result> { + let sig = String::from("()Ljava/lang/Boolean;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocalizedName", + "getEnchantmentGlintOverride", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - #[deprecated] - /// Sets the localized name. - pub fn set_localized_name( + /// Sets the enchantment_glint_override. If true, the item will glint, even + /// without enchantments; if false, the item will not glint, even with + /// enchantments. If null, the override will be cleared. + pub fn set_enchantment_glint_override( &self, - name: impl Into, + val_override: bool, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + let sig = String::from("(Ljava/lang/Boolean;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Boolean", + "(Ljava/Lang/Object;)V", + vec![val_override.into()], + )?); let res = self.jni_ref().call_method( &self.jni_object(), - "setLocalizedName", + "setEnchantmentGlintOverride", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of lore. - pub fn has_lore(&self) -> Result> { + /// Checks if this item is fire_resistant. If true, it will not burn in fire + /// or lava. + pub fn is_fire_resistant(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasLore", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the lore that is set. - /// - /// Plugins should check if hasLore() returns true before - /// calling this method. - pub fn lore(&self) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getLore", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), - ); - } - Ok(Some(new_vec)) - } - /// Sets the lore for this item. - /// Removes lore when given null. - pub fn set_lore( - &self, - lore: Vec>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/List;)V"); - let raw_val_1 = self - .jni_ref() - .new_object("java/util/ArrayList", "()V", vec![])?; - for v in lore { - let map_val_0 = jni::objects::JValueGen::Object(v); - self.jni_ref().call_method( - &raw_val_1, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_1 = jni::objects::JValueGen::Object(raw_val_1); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isFireResistant", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets if this item is fire_resistant. If true, it will not burn in fire + /// or lava. + pub fn set_fire_resistant( + &self, + fire_resistant: bool, + ) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire_resistant.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLore", + "setFireResistant", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of custom model data. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - pub fn has_custom_model_data(&self) -> Result> { + /// Gets if the max_stack_size is set. + pub fn has_max_stack_size(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasCustomModelData", - sig.as_str(), - vec![], - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasMaxStackSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the custom model data that is set. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - /// - /// Plugins should check that hasCustomModelData() returns true - /// before calling this method. - pub fn custom_model_data(&self) -> Result> { + /// Gets the max_stack_size. This is the maximum amount which an item will + /// stack. + pub fn max_stack_size(&self) -> Result> { let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCustomModelData", - sig.as_str(), - vec![], - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the custom model data. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - pub fn set_custom_model_data(&self, data: i32) -> Result<(), Box> { + /// Sets the max_stack_size. This is the maximum amount which an item will + /// stack. + pub fn set_max_stack_size(&self, max: i32) -> Result<(), Box> { let sig = String::from("(Ljava/lang/Integer;)V"); let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( "java/lang/Integer", "(Ljava/Lang/Object;)V", - vec![data.into()], + vec![max.into()], )?); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomModelData", + "setMaxStackSize", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for the existence of any enchantments. - pub fn has_enchants(&self) -> Result> { + /// Gets if the rarity is set. + pub fn has_rarity(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasEnchants", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasRarity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Checks for existence of the specified enchantment. - pub fn has_enchant( + /// Gets the item rarity. + /// Plugins should check {@link #hasRarity()} before calling this method. + pub fn rarity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemRarity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRarity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemRarity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the item rarity. + pub fn set_rarity( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + rarity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemRarity;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(rarity.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasEnchant", + "setRarity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the food is set. + pub fn has_food(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasFood", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Checks for the level of the specified enchantment. - pub fn get_enchant_level( + /// Gets the food set on this item, or creates an empty food instance. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with {@link #setFood(FoodComponent)} to + /// apply the changes. + pub fn food( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)I"); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/FoodComponent;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFood", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::components::FoodComponent::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the item food. + pub fn set_food( + &self, + food: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/FoodComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(food.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getEnchantLevel", + "setFood", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the tool is set. + pub fn has_tool(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasTool", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Returns a copy the enchantments in this ItemMeta. + /// Gets the tool set on this item, or creates an empty tool instance. /// - /// Returns an empty map if none. - pub fn enchants( + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with {@link #setTool(ToolComponent)} to + /// apply the changes. + pub fn tool( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEnchants", sig.as_str(), vec![]); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/ToolComponent;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + crate::inventory::meta::components::ToolComponent::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Adds the specified enchantment to this item meta. - pub fn add_enchant( + /// Sets the item tool. + pub fn set_tool( &self, - ench: impl Into>, - level: i32, - ignore_level_restriction: bool, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;IZ)Z"); + tool: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(tool.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(level); - let val_3 = jni::objects::JValueGen::Bool(ignore_level_restriction.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "addEnchant", + "setTool", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes the specified enchantment from this item meta. - pub fn remove_enchant( + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) + } + /// Sets the item tool. + pub fn set_jukebox_playable( + &self, + jukebox_playable: impl Into>, + ) -> Result<(), Box> { + let sig = + String::from("(Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeEnchant", + "setJukeboxPlayable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Removes all enchantments from this item meta. - pub fn remove_enchantments(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Checks for the existence of any AttributeModifiers. + pub fn has_attribute_modifiers(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "removeEnchantments", + "hasAttributeModifiers", sig.as_str(), vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Checks if the specified enchantment conflicts with any enchantments in - /// this ItemMeta. - pub fn has_conflicting_enchant( - &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + /// Return an immutable copy of all {@link AttributeModifier}s + /// for a given {@link Attribute} + pub fn get_attribute_modifiers( + &self, + attribute: impl Into>, + ) -> Result>>, Box> + { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/attribute/Attribute;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) }); + args.push(val_1); + sig += ")Ljava/util/Collection;"; let res = self.jni_ref().call_method( &self.jni_object(), - "hasConflictingEnchant", + "getAttributeModifiers", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::attribute::AttributeModifier::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(Some(new_vec)) } - /// Set itemflags which should be ignored when rendering a ItemStack in the Client. This Method does silently ignore double set itemFlags. - pub fn add_item_flags( + /// Add an Attribute and it's Modifier. + /// AttributeModifiers can now support {@link EquipmentSlot}s. + /// If not set, the {@link AttributeModifier} will be active in ALL slots. + /// + /// Two {@link AttributeModifier}s that have the same {@link java.util.UUID} + /// cannot exist on the same Attribute. + pub fn add_attribute_modifier( &self, - item_flags: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); + attribute: impl Into>, + modifier: impl Into>, + ) -> Result> { + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;Lorg/bukkit/attribute/AttributeModifier;)Z", + ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(modifier.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "addItemFlags", + "addAttributeModifier", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Remove specific set of itemFlags. This tells the Client it should render it again. This Method does silently ignore double removed itemFlags. - pub fn remove_item_flags( + /// Set all {@link Attribute}s and their {@link AttributeModifier}s. + /// To clear all currently set Attributes and AttributeModifiers use + /// null or an empty Multimap. + /// If not null nor empty, this will filter all entries that are not-null + /// and add them to the ItemStack. + pub fn set_attribute_modifiers( &self, - item_flags: impl Into>, + attribute_modifiers: jni::objects::JObject<'mc>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) - }); + let sig = String::from("(Lcom/google/common/collect/Multimap;)V"); + let val_1 = jni::objects::JValueGen::Object(attribute_modifiers); let res = self.jni_ref().call_method( &self.jni_object(), - "removeItemFlags", + "setAttributeModifiers", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get current set itemFlags. The collection returned is unmodifiable. - pub fn item_flags( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemFlags", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Check if the specified flag is present on this item. - pub fn has_item_flag( + /// Remove a specific {@link Attribute} and {@link AttributeModifier}. + /// AttributeModifiers are matched according to their {@link java.util.UUID}. + pub fn remove_attribute_modifier( &self, - flag: impl Into>, + attribute: impl Into>, + modifier: std::option::Option>>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)Z"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/attribute/Attribute;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(flag.into().jni_object().clone()) + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) }); + args.push(val_1); + if let Some(a) = modifier { + sig += "Lorg/bukkit/attribute/AttributeModifier;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; let res = self.jni_ref().call_method( &self.jni_object(), - "hasItemFlag", + "removeAttributeModifier", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets if this item has hide_tooltip set. An item with this set will not - /// show any tooltip whatsoever. - pub fn is_hide_tooltip(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isHideTooltip", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets if this item has hide_tooltip set. An item with this set will not - /// show any tooltip whatsoever. - pub fn set_hide_tooltip(&self, hide_tooltip: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(hide_tooltip.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setHideTooltip", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Return if the unbreakable tag is true. An unbreakable item will not lose - /// durability. - pub fn is_unbreakable(&self) -> Result> { - let sig = String::from("()Z"); + /// Get this ItemMeta as an NBT string. If this ItemMeta does not have any + /// NBT, then {@code "{}"} will be returned. + /// + /// This string should NEVER be relied upon as a serializable value. If + /// serialization is desired, the {@link ConfigurationSerializable} API should be used + /// instead. + pub fn as_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isUnbreakable", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets the unbreakable tag. An unbreakable item will not lose durability. - pub fn set_unbreakable(&self, unbreakable: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(unbreakable.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setUnbreakable", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Gets if an enchantment_glint_override is set. - pub fn has_enchantment_glint_override(&self) -> Result> { - let sig = String::from("()Z"); + /// Get this ItemMeta as a component-compliant string. If this ItemMeta does + /// not contain any components, then {@code "[]"} will be returned. + /// + /// The result of this method should yield a string representing the components + /// altered by this ItemMeta instance. When passed to {@link ItemFactory#createItemStack(String)} + /// with a prepended item type, it will create an ItemStack that has an ItemMeta + /// matching this ItemMeta instance exactly. Note that this method returns + /// ONLY the components and cannot be passed to createItemStack() alone. + /// An example may look something like this: + ///
+    /// ItemStack itemStack = // ... an item stack obtained from somewhere
+    /// ItemMeta itemMeta = itemStack.getItemMeta();
+    /// String components = itemMeta.getAsComponentString(); // example: "[minecraft:damage=53]"
+    /// String itemTypeKey = itemStack.getType().getKey().toString(); // example: "minecraft:diamond_sword"
+    /// String itemAsString = itemTypeKey + components; // results in: "minecraft:diamond_sword[minecraft:damage=53]"
+    /// ItemStack recreatedItemStack = Bukkit.getItemFactory().createItemStack(itemAsString);
+    /// assert itemStack.isSimilar(recreatedItemStack); // Should be true*
+    /// 
+ /// + /// *Components not represented or explicitly overridden by this ItemMeta instance + /// will not be included in the resulting string and therefore may result in ItemStacks + /// that do not match exactly. For example, if {@link #setDisplayName(String)} + /// is not set, then the custom name component will not be included. Or if this ItemMeta + /// is a PotionMeta, it will not include any components related to lodestone compasses, + /// banners, or books, etc., only components modifiable by a PotionMeta instance. + /// + /// This string should NEVER be relied upon as a serializable value. If + /// serialization is desired, the {@link ConfigurationSerializable} API should be used + /// instead. + pub fn as_component_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasEnchantmentGlintOverride", + "getAsComponentString", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets the enchantment_glint_override. If true, the item will glint, even - /// without enchantments; if false, the item will not glint, even with - /// enchantments. - /// Plugins should check {@link #hasEnchantmentGlintOverride()} before - /// calling this method. - pub fn enchantment_glint_override(&self) -> Result> { - let sig = String::from("()Ljava/lang/Boolean;"); + #[deprecated] + /// Returns a public custom tag container capable of storing tags on the item. Those tags will be sent to the client with all of their content, so the client is capable of reading them. This will result in the player seeing a NBT Tag notification on the item. These tags can also be modified by the client once in creative mode + pub fn custom_tag_container( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/tags/CustomItemTagContainer;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getEnchantmentGlintOverride", + "getCustomTagContainer", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::meta::tags::CustomItemTagContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the enchantment_glint_override. If true, the item will glint, even - /// without enchantments; if false, the item will not glint, even with - /// enchantments. If null, the override will be cleared. - pub fn set_enchantment_glint_override( - &self, - val_override: bool, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/Boolean;)V"); - let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( - "java/lang/Boolean", - "(Ljava/Lang/Object;)V", - vec![val_override.into()], - )?); + /// Internal use only! Do not use under any circumstances! + pub fn set_version(&self, version: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(version); let res = self.jni_ref().call_method( &self.jni_object(), - "setEnchantmentGlintOverride", + "setVersion", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if this item is fire_resistant. If true, it will not burn in fire - /// or lava. - pub fn is_fire_resistant(&self) -> Result> { + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for CompassMeta<'mc> { + fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { + crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) + .expect("Error converting CompassMeta into crate::inventory::meta::ItemMeta") + } +} +#[repr(C)] +pub struct Damageable<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Damageable<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Damageable<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Damageable from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/Damageable")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Damageable object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Damageable<'mc> { + /// Checks to see if this item has damage + pub fn has_damage(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isFireResistant", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasDamage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets if this item is fire_resistant. If true, it will not burn in fire - /// or lava. - pub fn set_fire_resistant( - &self, - fire_resistant: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire_resistant.into()); + /// Gets the damage + pub fn damage(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getDamage", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the damage + pub fn set_damage(&self, damage: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(damage); let res = self.jni_ref().call_method( &self.jni_object(), - "setFireResistant", + "setDamage", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the max_stack_size is set. - pub fn has_max_stack_size(&self) -> Result> { + /// Checks to see if this item has a maximum amount of damage. + pub fn has_max_damage(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasMaxStackSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasMaxDamage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the max_stack_size. This is the maximum amount which an item will - /// stack. - pub fn max_stack_size(&self) -> Result> { + /// Gets the maximum amount of damage. + /// Plugins should check {@link #hasMaxDamage()} before calling this method. + pub fn max_damage(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxDamage", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the max_stack_size. This is the maximum amount which an item will - /// stack. - pub fn set_max_stack_size(&self, max: i32) -> Result<(), Box> { + /// Sets the maximum amount of damage. + pub fn set_max_damage(&self, max_damage: i32) -> Result<(), Box> { let sig = String::from("(Ljava/lang/Integer;)V"); let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( "java/lang/Integer", "(Ljava/Lang/Object;)V", - vec![max.into()], + vec![max_damage.into()], )?); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxStackSize", + "setMaxDamage", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the rarity is set. - pub fn has_rarity(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasRarity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the item rarity. - /// Plugins should check {@link #hasRarity()} before calling this method. - pub fn rarity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemRarity;"); + + pub fn clone( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/Damageable;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getRarity", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemRarity::from_raw(&self.jni_ref(), unsafe { + crate::inventory::meta::Damageable::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the item rarity. - pub fn set_rarity( - &self, - rarity: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemRarity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(rarity.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRarity", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks if the food is set. - pub fn has_food(&self) -> Result> { + /// Checks for existence of a display name. + pub fn has_display_name(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasFood", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasDisplayName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the food set on this item, or creates an empty food instance. + /// Gets the display name that is set. /// - /// The returned component is a snapshot of its current state and does not - /// reflect a live view of what is on an item. After changing any value on - /// this component, it must be set with {@link #setFood(FoodComponent)} to - /// apply the changes. - pub fn food( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/components/FoodComponent;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFood", sig.as_str(), vec![]); + /// Plugins should check that hasDisplayName() returns true + /// before calling this method. + pub fn display_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDisplayName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::components::FoodComponent::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets the item food. - pub fn set_food( + /// Sets the display name. + pub fn set_display_name( &self, - food: impl Into>, + name: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/components/FoodComponent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(food.into().jni_object().clone()) - }); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setFood", + "setDisplayName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if the tool is set. - pub fn has_tool(&self) -> Result> { + /// Checks for existence of an item name. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + pub fn has_item_name(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasTool", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasItemName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the tool set on this item, or creates an empty tool instance. + /// Gets the item name that is set. /// - /// The returned component is a snapshot of its current state and does not - /// reflect a live view of what is on an item. After changing any value on - /// this component, it must be set with {@link #setTool(ToolComponent)} to - /// apply the changes. - pub fn tool( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/components/ToolComponent;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + /// + /// Plugins should check that hasItemName() returns true before + /// calling this method. + pub fn item_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::components::ToolComponent::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the item tool. - pub fn set_tool( - &self, - tool: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tool.into().jni_object().clone()) - }); + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the item name. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + pub fn set_item_name(&self, name: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setTool", + "setItemName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for the existence of any AttributeModifiers. - pub fn has_attribute_modifiers(&self) -> Result> { + #[deprecated] + /// Checks for existence of a localized name. + pub fn has_localized_name(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasAttributeModifiers", + "hasLocalizedName", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Return an immutable copy of all {@link AttributeModifier}s - /// for a given {@link Attribute} - pub fn get_attribute_modifiers( + #[deprecated] + /// Gets the localized display name that is set.Plugins should check that hasLocalizedName() returns true before calling this method. + pub fn localized_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLocalizedName", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + #[deprecated] + /// Sets the localized name. + pub fn set_localized_name( &self, - attribute: impl Into>, - ) -> Result>>, Box> - { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/attribute/Attribute;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Ljava/util/Collection;"; + name: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "getAttributeModifiers", + "setLocalizedName", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks for existence of lore. + pub fn has_lore(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasLore", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the lore that is set. + /// + /// Plugins should check if hasLore() returns true before + /// calling this method. + pub fn lore(&self) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLore", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::attribute::AttributeModifier::from_raw( - &self.jni_ref(), - obj, - )?); + new_vec.push( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); } Ok(Some(new_vec)) } - /// Add an Attribute and it's Modifier. - /// AttributeModifiers can now support {@link EquipmentSlot}s. - /// If not set, the {@link AttributeModifier} will be active in ALL slots. - /// - /// Two {@link AttributeModifier}s that have the same {@link java.util.UUID} - /// cannot exist on the same Attribute. - pub fn add_attribute_modifier( - &self, - attribute: impl Into>, - modifier: impl Into>, - ) -> Result> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;Lorg/bukkit/attribute/AttributeModifier;)Z", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(modifier.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addAttributeModifier", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Set all {@link Attribute}s and their {@link AttributeModifier}s. - /// To clear all currently set Attributes and AttributeModifiers use - /// null or an empty Multimap. - /// If not null nor empty, this will filter all entries that are not-null - /// and add them to the ItemStack. - pub fn set_attribute_modifiers( + /// Sets the lore for this item. + /// Removes lore when given null. + pub fn set_lore( &self, - attribute_modifiers: jni::objects::JObject<'mc>, + lore: Vec>, ) -> Result<(), Box> { - let sig = String::from("(Lcom/google/common/collect/Multimap;)V"); - let val_1 = jni::objects::JValueGen::Object(attribute_modifiers); + let sig = String::from("(Ljava/util/List;)V"); + let raw_val_1 = self + .jni_ref() + .new_object("java/util/ArrayList", "()V", vec![])?; + for v in lore { + let map_val_0 = jni::objects::JValueGen::Object(v); + self.jni_ref().call_method( + &raw_val_1, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_1 = jni::objects::JValueGen::Object(raw_val_1); let res = self.jni_ref().call_method( &self.jni_object(), - "setAttributeModifiers", + "setLore", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Remove a specific {@link Attribute} and {@link AttributeModifier}. - /// AttributeModifiers are matched according to their {@link java.util.UUID}. - pub fn remove_attribute_modifier( - &self, - attribute: impl Into>, - modifier: std::option::Option>>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/attribute/Attribute;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = modifier { - sig += "Lorg/bukkit/attribute/AttributeModifier;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Z"; + /// Checks for existence of custom model data. + /// + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + pub fn has_custom_model_data(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "removeAttributeModifier", + "hasCustomModelData", sig.as_str(), - args, + vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get this ItemMeta as an NBT string. If this ItemMeta does not have any - /// NBT, then {@code "{}"} will be returned. + /// Gets the custom model data that is set. /// - /// This string should NEVER be relied upon as a serializable value. If - /// serialization is desired, the {@link ConfigurationSerializable} API should be used - /// instead. - pub fn as_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + /// + /// Plugins should check that hasCustomModelData() returns true + /// before calling this method. + pub fn custom_model_data(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCustomModelData", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.i()?) } - /// Get this ItemMeta as a component-compliant string. If this ItemMeta does - /// not contain any components, then {@code "[]"} will be returned. - /// - /// The result of this method should yield a string representing the components - /// altered by this ItemMeta instance. When passed to {@link ItemFactory#createItemStack(String)} - /// with a prepended item type, it will create an ItemStack that has an ItemMeta - /// matching this ItemMeta instance exactly. Note that this method returns - /// ONLY the components and cannot be passed to createItemStack() alone. - /// An example may look something like this: - ///
-    /// ItemStack itemStack = // ... an item stack obtained from somewhere
-    /// ItemMeta itemMeta = itemStack.getItemMeta();
-    /// String components = itemMeta.getAsComponentString(); // example: "[minecraft:damage=53]"
-    /// String itemTypeKey = itemStack.getType().getKey().toString(); // example: "minecraft:diamond_sword"
-    /// String itemAsString = itemTypeKey + components; // results in: "minecraft:diamond_sword[minecraft:damage=53]"
-    /// ItemStack recreatedItemStack = Bukkit.getItemFactory().createItemStack(itemAsString);
-    /// assert itemStack.isSimilar(recreatedItemStack); // Should be true*
-    /// 
- /// - /// *Components not represented or explicitly overridden by this ItemMeta instance - /// will not be included in the resulting string and therefore may result in ItemStacks - /// that do not match exactly. For example, if {@link #setDisplayName(String)} - /// is not set, then the custom name component will not be included. Or if this ItemMeta - /// is a PotionMeta, it will not include any components related to lodestone compasses, - /// banners, or books, etc., only components modifiable by a PotionMeta instance. + /// Sets the custom model data. /// - /// This string should NEVER be relied upon as a serializable value. If - /// serialization is desired, the {@link ConfigurationSerializable} API should be used - /// instead. - pub fn as_component_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + pub fn set_custom_model_data(&self, data: i32) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/Integer;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Integer", + "(Ljava/Lang/Object;)V", + vec![data.into()], + )?); let res = self.jni_ref().call_method( &self.jni_object(), - "getAsComponentString", + "setCustomModelData", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks for the existence of any enchantments. + pub fn has_enchants(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasEnchants", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - #[deprecated] - /// Returns a public custom tag container capable of storing tags on the item. Those tags will be sent to the client with all of their content, so the client is capable of reading them. This will result in the player seeing a NBT Tag notification on the item. These tags can also be modified by the client once in creative mode - pub fn custom_tag_container( + /// Checks for existence of the specified enchantment. + pub fn has_enchant( &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/tags/CustomItemTagContainer;"); + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getCustomTagContainer", + "hasEnchant", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::tags::CustomItemTagContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Internal use only! Do not use under any circumstances! - pub fn set_version(&self, version: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(version); + /// Checks for the level of the specified enchantment. + pub fn get_enchant_level( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)I"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVersion", + "getEnchantLevel", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Creates a Map representation of this class. + /// Returns a copy the enchantments in this ItemMeta. /// - /// This class must provide a method to restore this class, as defined in - /// the {@link ConfigurationSerializable} interface javadocs. - pub fn serialize( + /// Returns an empty map if none. + pub fn enchants( &self, ) -> Result, Box> { let sig = String::from("()Ljava/util/Map;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEnchants", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( + /// Adds the specified enchantment to this item meta. + pub fn add_enchant( &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; + ench: impl Into>, + level: i32, + ignore_level_restriction: bool, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;IZ)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(level); + let val_3 = jni::objects::JValueGen::Bool(ignore_level_restriction.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "addEnchant", sig.as_str(), - args, + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for SuspiciousStewMeta<'mc> { - fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { - crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SuspiciousStewMeta into crate::inventory::meta::ItemMeta") - } -} -#[repr(C)] -pub struct CrossbowMeta<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for CrossbowMeta<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for CrossbowMeta<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate CrossbowMeta from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/CrossbowMeta")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a CrossbowMeta object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Removes the specified enchantment from this item meta. + pub fn remove_enchant( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeEnchant", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} - -impl<'mc> CrossbowMeta<'mc> { - /// Returns whether the item has any charged projectiles. - pub fn has_charged_projectiles(&self) -> Result> { - let sig = String::from("()Z"); + /// Removes all enchantments from this item meta. + pub fn remove_enchantments(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasChargedProjectiles", + "removeEnchantments", sig.as_str(), vec![], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the specified enchantment conflicts with any enchantments in + /// this ItemMeta. + pub fn has_conflicting_enchant( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasConflictingEnchant", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns an immutable list of the projectiles charged on this item. - pub fn charged_projectiles( + /// Set itemflags which should be ignored when rendering a ItemStack in the Client. This Method does silently ignore double set itemFlags. + pub fn add_item_flags( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + item_flags: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getChargedProjectiles", + "addItemFlags", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::inventory::ItemStack::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the projectiles charged on this item. - /// Removes all projectiles when given null. - pub fn set_charged_projectiles( + /// Remove specific set of itemFlags. This tells the Client it should render it again. This Method does silently ignore double removed itemFlags. + pub fn remove_item_flags( &self, - projectiles: Vec>, + item_flags: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/List;)V"); - let raw_val_1 = self - .jni_ref() - .new_object("java/util/ArrayList", "()V", vec![])?; - for v in projectiles { - let map_val_0 = jni::objects::JValueGen::Object(v); - self.jni_ref().call_method( - &raw_val_1, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_1 = jni::objects::JValueGen::Object(raw_val_1); + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setChargedProjectiles", + "removeItemFlags", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Adds a charged projectile to this item. - pub fn add_charged_projectile( + /// Get current set itemFlags. The collection returned is unmodifiable. + pub fn item_flags( &self, - item: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemFlags", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Check if the specified flag is present on this item. + pub fn has_item_flag( + &self, + flag: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(flag.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "addChargedProjectile", + "hasItemFlag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks for existence of a display name. - pub fn has_display_name(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasDisplayName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the display name that is set. - /// - /// Plugins should check that hasDisplayName() returns true - /// before calling this method. - pub fn display_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Gets if this item has hide_tooltip set. An item with this set will not + /// show any tooltip whatsoever. + pub fn is_hide_tooltip(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDisplayName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isHideTooltip", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - /// Sets the display name. - pub fn set_display_name( - &self, - name: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + /// Sets if this item has hide_tooltip set. An item with this set will not + /// show any tooltip whatsoever. + pub fn set_hide_tooltip(&self, hide_tooltip: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(hide_tooltip.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setDisplayName", + "setHideTooltip", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of an item name. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - pub fn has_item_name(&self) -> Result> { + /// Return if the unbreakable tag is true. An unbreakable item will not lose + /// durability. + pub fn is_unbreakable(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasItemName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isUnbreakable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the item name that is set. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - /// - /// Plugins should check that hasItemName() returns true before - /// calling this method. - pub fn item_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Sets the item name. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - pub fn set_item_name(&self, name: impl Into) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + /// Sets the unbreakable tag. An unbreakable item will not lose durability. + pub fn set_unbreakable(&self, unbreakable: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(unbreakable.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemName", + "setUnbreakable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Checks for existence of a localized name. - pub fn has_localized_name(&self) -> Result> { + /// Gets if an enchantment_glint_override is set. + pub fn has_enchantment_glint_override(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasLocalizedName", + "hasEnchantmentGlintOverride", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Gets the localized display name that is set.Plugins should check that hasLocalizedName() returns true before calling this method. - pub fn localized_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Sets the enchantment_glint_override. If true, the item will glint, even + /// without enchantments; if false, the item will not glint, even with + /// enchantments. + /// Plugins should check {@link #hasEnchantmentGlintOverride()} before + /// calling this method. + pub fn enchantment_glint_override(&self) -> Result> { + let sig = String::from("()Ljava/lang/Boolean;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocalizedName", + "getEnchantmentGlintOverride", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - #[deprecated] - /// Sets the localized name. - pub fn set_localized_name( + /// Sets the enchantment_glint_override. If true, the item will glint, even + /// without enchantments; if false, the item will not glint, even with + /// enchantments. If null, the override will be cleared. + pub fn set_enchantment_glint_override( &self, - name: impl Into, + val_override: bool, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + let sig = String::from("(Ljava/lang/Boolean;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Boolean", + "(Ljava/Lang/Object;)V", + vec![val_override.into()], + )?); let res = self.jni_ref().call_method( &self.jni_object(), - "setLocalizedName", + "setEnchantmentGlintOverride", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of lore. - pub fn has_lore(&self) -> Result> { + /// Checks if this item is fire_resistant. If true, it will not burn in fire + /// or lava. + pub fn is_fire_resistant(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasLore", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isFireResistant", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the lore that is set. - /// - /// Plugins should check if hasLore() returns true before - /// calling this method. - pub fn lore(&self) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getLore", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), - ); - } - Ok(Some(new_vec)) - } - /// Sets the lore for this item. - /// Removes lore when given null. - pub fn set_lore( + /// Sets if this item is fire_resistant. If true, it will not burn in fire + /// or lava. + pub fn set_fire_resistant( &self, - lore: Vec>, + fire_resistant: bool, ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/List;)V"); - let raw_val_1 = self - .jni_ref() - .new_object("java/util/ArrayList", "()V", vec![])?; - for v in lore { - let map_val_0 = jni::objects::JValueGen::Object(v); - self.jni_ref().call_method( - &raw_val_1, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_1 = jni::objects::JValueGen::Object(raw_val_1); + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire_resistant.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLore", + "setFireResistant", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of custom model data. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - pub fn has_custom_model_data(&self) -> Result> { + /// Gets if the max_stack_size is set. + pub fn has_max_stack_size(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasCustomModelData", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the custom model data that is set. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - /// - /// Plugins should check that hasCustomModelData() returns true - /// before calling this method. - pub fn custom_model_data(&self) -> Result> { + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasMaxStackSize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the max_stack_size. This is the maximum amount which an item will + /// stack. + pub fn max_stack_size(&self) -> Result> { let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCustomModelData", - sig.as_str(), - vec![], - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the custom model data. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - pub fn set_custom_model_data(&self, data: i32) -> Result<(), Box> { + /// Sets the max_stack_size. This is the maximum amount which an item will + /// stack. + pub fn set_max_stack_size(&self, max: i32) -> Result<(), Box> { let sig = String::from("(Ljava/lang/Integer;)V"); let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( "java/lang/Integer", "(Ljava/Lang/Object;)V", - vec![data.into()], + vec![max.into()], )?); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomModelData", + "setMaxStackSize", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for the existence of any enchantments. - pub fn has_enchants(&self) -> Result> { + /// Gets if the rarity is set. + pub fn has_rarity(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasEnchants", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasRarity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Checks for existence of the specified enchantment. - pub fn has_enchant( + /// Gets the item rarity. + /// Plugins should check {@link #hasRarity()} before calling this method. + pub fn rarity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemRarity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRarity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemRarity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the item rarity. + pub fn set_rarity( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + rarity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemRarity;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(rarity.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasEnchant", + "setRarity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the food is set. + pub fn has_food(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasFood", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Checks for the level of the specified enchantment. - pub fn get_enchant_level( + /// Gets the food set on this item, or creates an empty food instance. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with {@link #setFood(FoodComponent)} to + /// apply the changes. + pub fn food( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)I"); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/FoodComponent;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFood", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::components::FoodComponent::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the item food. + pub fn set_food( + &self, + food: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/FoodComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(food.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getEnchantLevel", + "setFood", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the tool is set. + pub fn has_tool(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasTool", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Returns a copy the enchantments in this ItemMeta. + /// Gets the tool set on this item, or creates an empty tool instance. /// - /// Returns an empty map if none. - pub fn enchants( + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with {@link #setTool(ToolComponent)} to + /// apply the changes. + pub fn tool( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEnchants", sig.as_str(), vec![]); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/ToolComponent;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + crate::inventory::meta::components::ToolComponent::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Adds the specified enchantment to this item meta. - pub fn add_enchant( + /// Sets the item tool. + pub fn set_tool( &self, - ench: impl Into>, - level: i32, - ignore_level_restriction: bool, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;IZ)Z"); + tool: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(tool.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(level); - let val_3 = jni::objects::JValueGen::Bool(ignore_level_restriction.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "addEnchant", + "setTool", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes the specified enchantment from this item meta. - pub fn remove_enchant( + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) + } + /// Sets the item tool. + pub fn set_jukebox_playable( + &self, + jukebox_playable: impl Into>, + ) -> Result<(), Box> { + let sig = + String::from("(Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeEnchant", + "setJukeboxPlayable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks for the existence of any AttributeModifiers. + pub fn has_attribute_modifiers(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasAttributeModifiers", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes all enchantments from this item meta. - pub fn remove_enchantments(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Return an immutable copy of all {@link AttributeModifier}s + /// for a given {@link Attribute} + pub fn get_attribute_modifiers( + &self, + attribute: impl Into>, + ) -> Result>>, Box> + { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/attribute/Attribute;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Ljava/util/Collection;"; let res = self.jni_ref().call_method( &self.jni_object(), - "removeEnchantments", + "getAttributeModifiers", sig.as_str(), - vec![], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::attribute::AttributeModifier::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(Some(new_vec)) } - /// Checks if the specified enchantment conflicts with any enchantments in - /// this ItemMeta. - pub fn has_conflicting_enchant( + /// Add an Attribute and it's Modifier. + /// AttributeModifiers can now support {@link EquipmentSlot}s. + /// If not set, the {@link AttributeModifier} will be active in ALL slots. + /// + /// Two {@link AttributeModifier}s that have the same {@link java.util.UUID} + /// cannot exist on the same Attribute. + pub fn add_attribute_modifier( &self, - ench: impl Into>, + attribute: impl Into>, + modifier: impl Into>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;Lorg/bukkit/attribute/AttributeModifier;)Z", + ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(modifier.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasConflictingEnchant", + "addAttributeModifier", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set itemflags which should be ignored when rendering a ItemStack in the Client. This Method does silently ignore double set itemFlags. - pub fn add_item_flags( + /// Set all {@link Attribute}s and their {@link AttributeModifier}s. + /// To clear all currently set Attributes and AttributeModifiers use + /// null or an empty Multimap. + /// If not null nor empty, this will filter all entries that are not-null + /// and add them to the ItemStack. + pub fn set_attribute_modifiers( &self, - item_flags: impl Into>, + attribute_modifiers: jni::objects::JObject<'mc>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) - }); + let sig = String::from("(Lcom/google/common/collect/Multimap;)V"); + let val_1 = jni::objects::JValueGen::Object(attribute_modifiers); let res = self.jni_ref().call_method( &self.jni_object(), - "addItemFlags", + "setAttributeModifiers", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Remove specific set of itemFlags. This tells the Client it should render it again. This Method does silently ignore double removed itemFlags. - pub fn remove_item_flags( + /// Remove a specific {@link Attribute} and {@link AttributeModifier}. + /// AttributeModifiers are matched according to their {@link java.util.UUID}. + pub fn remove_attribute_modifier( &self, - item_flags: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); + attribute: impl Into>, + modifier: std::option::Option>>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/attribute/Attribute;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) }); + args.push(val_1); + if let Some(a) = modifier { + sig += "Lorg/bukkit/attribute/AttributeModifier;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; let res = self.jni_ref().call_method( &self.jni_object(), - "removeItemFlags", + "removeAttributeModifier", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Get current set itemFlags. The collection returned is unmodifiable. - pub fn item_flags( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Get this ItemMeta as an NBT string. If this ItemMeta does not have any + /// NBT, then {@code "{}"} will be returned. + /// + /// This string should NEVER be relied upon as a serializable value. If + /// serialization is desired, the {@link ConfigurationSerializable} API should be used + /// instead. + pub fn as_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemFlags", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Check if the specified flag is present on this item. - pub fn has_item_flag( - &self, - flag: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(flag.into().jni_object().clone()) - }); + /// Get this ItemMeta as a component-compliant string. If this ItemMeta does + /// not contain any components, then {@code "[]"} will be returned. + /// + /// The result of this method should yield a string representing the components + /// altered by this ItemMeta instance. When passed to {@link ItemFactory#createItemStack(String)} + /// with a prepended item type, it will create an ItemStack that has an ItemMeta + /// matching this ItemMeta instance exactly. Note that this method returns + /// ONLY the components and cannot be passed to createItemStack() alone. + /// An example may look something like this: + ///
+    /// ItemStack itemStack = // ... an item stack obtained from somewhere
+    /// ItemMeta itemMeta = itemStack.getItemMeta();
+    /// String components = itemMeta.getAsComponentString(); // example: "[minecraft:damage=53]"
+    /// String itemTypeKey = itemStack.getType().getKey().toString(); // example: "minecraft:diamond_sword"
+    /// String itemAsString = itemTypeKey + components; // results in: "minecraft:diamond_sword[minecraft:damage=53]"
+    /// ItemStack recreatedItemStack = Bukkit.getItemFactory().createItemStack(itemAsString);
+    /// assert itemStack.isSimilar(recreatedItemStack); // Should be true*
+    /// 
+ /// + /// *Components not represented or explicitly overridden by this ItemMeta instance + /// will not be included in the resulting string and therefore may result in ItemStacks + /// that do not match exactly. For example, if {@link #setDisplayName(String)} + /// is not set, then the custom name component will not be included. Or if this ItemMeta + /// is a PotionMeta, it will not include any components related to lodestone compasses, + /// banners, or books, etc., only components modifiable by a PotionMeta instance. + /// + /// This string should NEVER be relied upon as a serializable value. If + /// serialization is desired, the {@link ConfigurationSerializable} API should be used + /// instead. + pub fn as_component_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasItemFlag", + "getAsComponentString", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets if this item has hide_tooltip set. An item with this set will not - /// show any tooltip whatsoever. - pub fn is_hide_tooltip(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isHideTooltip", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets if this item has hide_tooltip set. An item with this set will not - /// show any tooltip whatsoever. - pub fn set_hide_tooltip(&self, hide_tooltip: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(hide_tooltip.into()); + #[deprecated] + /// Returns a public custom tag container capable of storing tags on the item. Those tags will be sent to the client with all of their content, so the client is capable of reading them. This will result in the player seeing a NBT Tag notification on the item. These tags can also be modified by the client once in creative mode + pub fn custom_tag_container( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/tags/CustomItemTagContainer;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setHideTooltip", + "getCustomTagContainer", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Return if the unbreakable tag is true. An unbreakable item will not lose - /// durability. - pub fn is_unbreakable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isUnbreakable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::meta::tags::CustomItemTagContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the unbreakable tag. An unbreakable item will not lose durability. - pub fn set_unbreakable(&self, unbreakable: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(unbreakable.into()); + /// Internal use only! Do not use under any circumstances! + pub fn set_version(&self, version: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(version); let res = self.jni_ref().call_method( &self.jni_object(), - "setUnbreakable", + "setVersion", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if an enchantment_glint_override is set. - pub fn has_enchantment_glint_override(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasEnchantmentGlintOverride", - sig.as_str(), - vec![], - ); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Damageable<'mc> { + fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { + crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Damageable into crate::inventory::meta::ItemMeta") + } +} +#[repr(C)] +pub struct BlockStateMeta<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for BlockStateMeta<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for BlockStateMeta<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate BlockStateMeta from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/BlockStateMeta")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BlockStateMeta object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> BlockStateMeta<'mc> { + /// Returns whether the item has a block state currently + /// attached to it. + pub fn has_block_state(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasBlockState", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the enchantment_glint_override. If true, the item will glint, even - /// without enchantments; if false, the item will not glint, even with - /// enchantments. - /// Plugins should check {@link #hasEnchantmentGlintOverride()} before - /// calling this method. - pub fn enchantment_glint_override(&self) -> Result> { - let sig = String::from("()Ljava/lang/Boolean;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getEnchantmentGlintOverride", - sig.as_str(), - vec![], - ); + /// Returns the currently attached block state for this + /// item or creates a new one if one doesn't exist. + /// The state is a copy, it must be set back (or to another + /// item) with {@link #setBlockState(org.bukkit.block.BlockState)} + pub fn block_state(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockState;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBlockState", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the enchantment_glint_override. If true, the item will glint, even - /// without enchantments; if false, the item will not glint, even with - /// enchantments. If null, the override will be cleared. - pub fn set_enchantment_glint_override( + /// Attaches a copy of the passed block state to the item. + pub fn set_block_state( &self, - val_override: bool, + block_state: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/Boolean;)V"); - let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( - "java/lang/Boolean", - "(Ljava/Lang/Object;)V", - vec![val_override.into()], - )?); + let sig = String::from("(Lorg/bukkit/block/BlockState;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(block_state.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setEnchantmentGlintOverride", + "setBlockState", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if this item is fire_resistant. If true, it will not burn in fire - /// or lava. - pub fn is_fire_resistant(&self) -> Result> { + /// Checks for existence of a display name. + pub fn has_display_name(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isFireResistant", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasDisplayName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets if this item is fire_resistant. If true, it will not burn in fire - /// or lava. - pub fn set_fire_resistant( + /// Gets the display name that is set. + /// + /// Plugins should check that hasDisplayName() returns true + /// before calling this method. + pub fn display_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDisplayName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the display name. + pub fn set_display_name( &self, - fire_resistant: bool, + name: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire_resistant.into()); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setFireResistant", + "setDisplayName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the max_stack_size is set. - pub fn has_max_stack_size(&self) -> Result> { + /// Checks for existence of an item name. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + pub fn has_item_name(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasMaxStackSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasItemName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the max_stack_size. This is the maximum amount which an item will - /// stack. - pub fn max_stack_size(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the item name that is set. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + /// + /// Plugins should check that hasItemName() returns true before + /// calling this method. + pub fn item_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItemName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets the max_stack_size. This is the maximum amount which an item will - /// stack. - pub fn set_max_stack_size(&self, max: i32) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/Integer;)V"); - let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( - "java/lang/Integer", - "(Ljava/Lang/Object;)V", - vec![max.into()], - )?); + /// Sets the item name. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + pub fn set_item_name(&self, name: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxStackSize", + "setItemName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the rarity is set. - pub fn has_rarity(&self) -> Result> { + #[deprecated] + /// Checks for existence of a localized name. + pub fn has_localized_name(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasRarity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the item rarity. - /// Plugins should check {@link #hasRarity()} before calling this method. - pub fn rarity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemRarity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getRarity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemRarity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the item rarity. - pub fn set_rarity( - &self, - rarity: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemRarity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(rarity.into().jni_object().clone()) - }); let res = self.jni_ref().call_method( &self.jni_object(), - "setRarity", + "hasLocalizedName", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks if the food is set. - pub fn has_food(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasFood", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the food set on this item, or creates an empty food instance. - /// - /// The returned component is a snapshot of its current state and does not - /// reflect a live view of what is on an item. After changing any value on - /// this component, it must be set with {@link #setFood(FoodComponent)} to - /// apply the changes. - pub fn food( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/components/FoodComponent;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFood", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::components::FoodComponent::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the item food. - pub fn set_food( - &self, - food: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/components/FoodComponent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(food.into().jni_object().clone()) - }); + #[deprecated] + /// Gets the localized display name that is set.Plugins should check that hasLocalizedName() returns true before calling this method. + pub fn localized_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setFood", + "getLocalizedName", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks if the tool is set. - pub fn has_tool(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasTool", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the tool set on this item, or creates an empty tool instance. - /// - /// The returned component is a snapshot of its current state and does not - /// reflect a live view of what is on an item. After changing any value on - /// this component, it must be set with {@link #setTool(ToolComponent)} to - /// apply the changes. - pub fn tool( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/components/ToolComponent;"); - let res = self + Ok(self .jni_ref() - .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::components::ToolComponent::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets the item tool. - pub fn set_tool( + #[deprecated] + /// Sets the localized name. + pub fn set_localized_name( &self, - tool: impl Into>, + name: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tool.into().jni_object().clone()) - }); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setTool", + "setLocalizedName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for the existence of any AttributeModifiers. - pub fn has_attribute_modifiers(&self) -> Result> { + /// Checks for existence of lore. + pub fn has_lore(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasAttributeModifiers", - sig.as_str(), - vec![], - ); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasLore", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Return an immutable copy of all {@link AttributeModifier}s - /// for a given {@link Attribute} - pub fn get_attribute_modifiers( - &self, - attribute: impl Into>, - ) -> Result>>, Box> - { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/attribute/Attribute;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Ljava/util/Collection;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAttributeModifiers", - sig.as_str(), - args, - ); + /// Gets the lore that is set. + /// + /// Plugins should check if hasLore() returns true before + /// calling this method. + pub fn lore(&self) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLore", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::attribute::AttributeModifier::from_raw( - &self.jni_ref(), - obj, - )?); + new_vec.push( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); } Ok(Some(new_vec)) } - /// Add an Attribute and it's Modifier. - /// AttributeModifiers can now support {@link EquipmentSlot}s. - /// If not set, the {@link AttributeModifier} will be active in ALL slots. - /// - /// Two {@link AttributeModifier}s that have the same {@link java.util.UUID} - /// cannot exist on the same Attribute. - pub fn add_attribute_modifier( - &self, - attribute: impl Into>, - modifier: impl Into>, - ) -> Result> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;Lorg/bukkit/attribute/AttributeModifier;)Z", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(modifier.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addAttributeModifier", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Set all {@link Attribute}s and their {@link AttributeModifier}s. - /// To clear all currently set Attributes and AttributeModifiers use - /// null or an empty Multimap. - /// If not null nor empty, this will filter all entries that are not-null - /// and add them to the ItemStack. - pub fn set_attribute_modifiers( + /// Sets the lore for this item. + /// Removes lore when given null. + pub fn set_lore( &self, - attribute_modifiers: jni::objects::JObject<'mc>, + lore: Vec>, ) -> Result<(), Box> { - let sig = String::from("(Lcom/google/common/collect/Multimap;)V"); - let val_1 = jni::objects::JValueGen::Object(attribute_modifiers); + let sig = String::from("(Ljava/util/List;)V"); + let raw_val_1 = self + .jni_ref() + .new_object("java/util/ArrayList", "()V", vec![])?; + for v in lore { + let map_val_0 = jni::objects::JValueGen::Object(v); + self.jni_ref().call_method( + &raw_val_1, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_1 = jni::objects::JValueGen::Object(raw_val_1); let res = self.jni_ref().call_method( &self.jni_object(), - "setAttributeModifiers", + "setLore", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Remove a specific {@link Attribute} and {@link AttributeModifier}. - /// AttributeModifiers are matched according to their {@link java.util.UUID}. - pub fn remove_attribute_modifier( - &self, - attribute: impl Into>, - modifier: std::option::Option>>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/attribute/Attribute;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = modifier { - sig += "Lorg/bukkit/attribute/AttributeModifier;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Z"; + /// Checks for existence of custom model data. + /// + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + pub fn has_custom_model_data(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "removeAttributeModifier", + "hasCustomModelData", sig.as_str(), - args, + vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get this ItemMeta as an NBT string. If this ItemMeta does not have any - /// NBT, then {@code "{}"} will be returned. + /// Gets the custom model data that is set. /// - /// This string should NEVER be relied upon as a serializable value. If - /// serialization is desired, the {@link ConfigurationSerializable} API should be used - /// instead. - pub fn as_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + /// + /// Plugins should check that hasCustomModelData() returns true + /// before calling this method. + pub fn custom_model_data(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCustomModelData", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.i()?) } - /// Get this ItemMeta as a component-compliant string. If this ItemMeta does - /// not contain any components, then {@code "[]"} will be returned. - /// - /// The result of this method should yield a string representing the components - /// altered by this ItemMeta instance. When passed to {@link ItemFactory#createItemStack(String)} - /// with a prepended item type, it will create an ItemStack that has an ItemMeta - /// matching this ItemMeta instance exactly. Note that this method returns - /// ONLY the components and cannot be passed to createItemStack() alone. - /// An example may look something like this: - ///
-    /// ItemStack itemStack = // ... an item stack obtained from somewhere
-    /// ItemMeta itemMeta = itemStack.getItemMeta();
-    /// String components = itemMeta.getAsComponentString(); // example: "[minecraft:damage=53]"
-    /// String itemTypeKey = itemStack.getType().getKey().toString(); // example: "minecraft:diamond_sword"
-    /// String itemAsString = itemTypeKey + components; // results in: "minecraft:diamond_sword[minecraft:damage=53]"
-    /// ItemStack recreatedItemStack = Bukkit.getItemFactory().createItemStack(itemAsString);
-    /// assert itemStack.isSimilar(recreatedItemStack); // Should be true*
-    /// 
- /// - /// *Components not represented or explicitly overridden by this ItemMeta instance - /// will not be included in the resulting string and therefore may result in ItemStacks - /// that do not match exactly. For example, if {@link #setDisplayName(String)} - /// is not set, then the custom name component will not be included. Or if this ItemMeta - /// is a PotionMeta, it will not include any components related to lodestone compasses, - /// banners, or books, etc., only components modifiable by a PotionMeta instance. + /// Sets the custom model data. /// - /// This string should NEVER be relied upon as a serializable value. If - /// serialization is desired, the {@link ConfigurationSerializable} API should be used - /// instead. - pub fn as_component_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + pub fn set_custom_model_data(&self, data: i32) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/Integer;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Integer", + "(Ljava/Lang/Object;)V", + vec![data.into()], + )?); let res = self.jni_ref().call_method( &self.jni_object(), - "getAsComponentString", + "setCustomModelData", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks for the existence of any enchantments. + pub fn has_enchants(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasEnchants", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - #[deprecated] - /// Returns a public custom tag container capable of storing tags on the item. Those tags will be sent to the client with all of their content, so the client is capable of reading them. This will result in the player seeing a NBT Tag notification on the item. These tags can also be modified by the client once in creative mode - pub fn custom_tag_container( + /// Checks for existence of the specified enchantment. + pub fn has_enchant( &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/tags/CustomItemTagContainer;"); + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getCustomTagContainer", + "hasEnchant", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::tags::CustomItemTagContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Internal use only! Do not use under any circumstances! - pub fn set_version(&self, version: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(version); + /// Checks for the level of the specified enchantment. + pub fn get_enchant_level( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)I"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVersion", + "getEnchantLevel", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn clone( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/ItemMeta;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Creates a Map representation of this class. + /// Returns a copy the enchantments in this ItemMeta. /// - /// This class must provide a method to restore this class, as defined in - /// the {@link ConfigurationSerializable} interface javadocs. - pub fn serialize( + /// Returns an empty map if none. + pub fn enchants( &self, ) -> Result, Box> { let sig = String::from("()Ljava/util/Map;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEnchants", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( + /// Adds the specified enchantment to this item meta. + pub fn add_enchant( &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; + ench: impl Into>, + level: i32, + ignore_level_restriction: bool, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;IZ)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(level); + let val_3 = jni::objects::JValueGen::Bool(ignore_level_restriction.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "addEnchant", sig.as_str(), - args, + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for CrossbowMeta<'mc> { - fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { - crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) - .expect("Error converting CrossbowMeta into crate::inventory::meta::ItemMeta") - } -} -#[repr(C)] -pub struct CompassMeta<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for CompassMeta<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for CompassMeta<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate CompassMeta from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/CompassMeta")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a CompassMeta object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + Ok(res.z()?) } -} - -impl<'mc> CompassMeta<'mc> { - /// Checks if this compass has been paired to a lodestone. - pub fn has_lodestone(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasLodestone", sig.as_str(), vec![]); + /// Removes the specified enchantment from this item meta. + pub fn remove_enchant( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeEnchant", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the location that this compass will point to. - /// Check {@link #hasLodestone()} first! - pub fn lodestone(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLodestone", sig.as_str(), vec![]); + /// Removes all enchantments from this item meta. + pub fn remove_enchantments(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeEnchantments", + sig.as_str(), + vec![], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the specified enchantment conflicts with any enchantments in + /// this ItemMeta. + pub fn has_conflicting_enchant( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasConflictingEnchant", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.z()?) } - /// Sets the location this lodestone compass will point to. - pub fn set_lodestone( + /// Set itemflags which should be ignored when rendering a ItemStack in the Client. This Method does silently ignore double set itemFlags. + pub fn add_item_flags( &self, - lodestone: impl Into>, + item_flags: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Location;)V"); + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(lodestone.into().jni_object().clone()) + jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLodestone", + "addItemFlags", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if this compass is tracking a specific lodestone. - /// If true the compass will only work if there is a lodestone at the tracked - /// location. - pub fn is_lodestone_tracked(&self) -> Result> { - let sig = String::from("()Z"); + /// Remove specific set of itemFlags. This tells the Client it should render it again. This Method does silently ignore double removed itemFlags. + pub fn remove_item_flags( + &self, + item_flags: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "isLodestoneTracked", + "removeItemFlags", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets if this compass is tracking a specific lodestone. - /// If true the compass will only work if there is a lodestone at the tracked - /// location. - pub fn set_lodestone_tracked(&self, tracked: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(tracked.into()); + /// Get current set itemFlags. The collection returned is unmodifiable. + pub fn item_flags( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemFlags", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Check if the specified flag is present on this item. + pub fn has_item_flag( + &self, + flag: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(flag.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLodestoneTracked", + "hasItemFlag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn clone( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/CompassMeta;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::CompassMeta::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Checks for existence of a display name. - pub fn has_display_name(&self) -> Result> { + /// Gets if this item has hide_tooltip set. An item with this set will not + /// show any tooltip whatsoever. + pub fn is_hide_tooltip(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasDisplayName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isHideTooltip", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the display name that is set. - /// - /// Plugins should check that hasDisplayName() returns true - /// before calling this method. - pub fn display_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDisplayName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Sets the display name. - pub fn set_display_name( - &self, - name: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + /// Sets if this item has hide_tooltip set. An item with this set will not + /// show any tooltip whatsoever. + pub fn set_hide_tooltip(&self, hide_tooltip: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(hide_tooltip.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setDisplayName", + "setHideTooltip", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of an item name. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - pub fn has_item_name(&self) -> Result> { + /// Return if the unbreakable tag is true. An unbreakable item will not lose + /// durability. + pub fn is_unbreakable(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasItemName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isUnbreakable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the item name that is set. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - /// - /// Plugins should check that hasItemName() returns true before - /// calling this method. - pub fn item_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Sets the item name. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - pub fn set_item_name(&self, name: impl Into) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + /// Sets the unbreakable tag. An unbreakable item will not lose durability. + pub fn set_unbreakable(&self, unbreakable: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(unbreakable.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemName", + "setUnbreakable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Checks for existence of a localized name. - pub fn has_localized_name(&self) -> Result> { + /// Gets if an enchantment_glint_override is set. + pub fn has_enchantment_glint_override(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasLocalizedName", + "hasEnchantmentGlintOverride", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Gets the localized display name that is set.Plugins should check that hasLocalizedName() returns true before calling this method. - pub fn localized_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Sets the enchantment_glint_override. If true, the item will glint, even + /// without enchantments; if false, the item will not glint, even with + /// enchantments. + /// Plugins should check {@link #hasEnchantmentGlintOverride()} before + /// calling this method. + pub fn enchantment_glint_override(&self) -> Result> { + let sig = String::from("()Ljava/lang/Boolean;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocalizedName", + "getEnchantmentGlintOverride", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - #[deprecated] - /// Sets the localized name. - pub fn set_localized_name( + /// Sets the enchantment_glint_override. If true, the item will glint, even + /// without enchantments; if false, the item will not glint, even with + /// enchantments. If null, the override will be cleared. + pub fn set_enchantment_glint_override( &self, - name: impl Into, + val_override: bool, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + let sig = String::from("(Ljava/lang/Boolean;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Boolean", + "(Ljava/Lang/Object;)V", + vec![val_override.into()], + )?); let res = self.jni_ref().call_method( &self.jni_object(), - "setLocalizedName", + "setEnchantmentGlintOverride", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of lore. - pub fn has_lore(&self) -> Result> { + /// Checks if this item is fire_resistant. If true, it will not burn in fire + /// or lava. + pub fn is_fire_resistant(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasLore", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isFireResistant", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the lore that is set. - /// - /// Plugins should check if hasLore() returns true before - /// calling this method. - pub fn lore(&self) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getLore", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), - ); - } - Ok(Some(new_vec)) - } - /// Sets the lore for this item. - /// Removes lore when given null. - pub fn set_lore( + /// Sets if this item is fire_resistant. If true, it will not burn in fire + /// or lava. + pub fn set_fire_resistant( &self, - lore: Vec>, + fire_resistant: bool, ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/List;)V"); - let raw_val_1 = self - .jni_ref() - .new_object("java/util/ArrayList", "()V", vec![])?; - for v in lore { - let map_val_0 = jni::objects::JValueGen::Object(v); - self.jni_ref().call_method( - &raw_val_1, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_1 = jni::objects::JValueGen::Object(raw_val_1); + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire_resistant.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLore", + "setFireResistant", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of custom model data. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - pub fn has_custom_model_data(&self) -> Result> { + /// Gets if the max_stack_size is set. + pub fn has_max_stack_size(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasCustomModelData", - sig.as_str(), - vec![], - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasMaxStackSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the custom model data that is set. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - /// - /// Plugins should check that hasCustomModelData() returns true - /// before calling this method. - pub fn custom_model_data(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCustomModelData", - sig.as_str(), - vec![], - ); + /// Gets the max_stack_size. This is the maximum amount which an item will + /// stack. + pub fn max_stack_size(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the custom model data. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - pub fn set_custom_model_data(&self, data: i32) -> Result<(), Box> { + /// Sets the max_stack_size. This is the maximum amount which an item will + /// stack. + pub fn set_max_stack_size(&self, max: i32) -> Result<(), Box> { let sig = String::from("(Ljava/lang/Integer;)V"); let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( "java/lang/Integer", "(Ljava/Lang/Object;)V", - vec![data.into()], + vec![max.into()], )?); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomModelData", + "setMaxStackSize", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for the existence of any enchantments. - pub fn has_enchants(&self) -> Result> { + /// Gets if the rarity is set. + pub fn has_rarity(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasEnchants", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasRarity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Checks for existence of the specified enchantment. - pub fn has_enchant( + /// Gets the item rarity. + /// Plugins should check {@link #hasRarity()} before calling this method. + pub fn rarity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemRarity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRarity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemRarity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the item rarity. + pub fn set_rarity( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + rarity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemRarity;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(rarity.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasEnchant", + "setRarity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the food is set. + pub fn has_food(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasFood", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Checks for the level of the specified enchantment. - pub fn get_enchant_level( + /// Gets the food set on this item, or creates an empty food instance. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with {@link #setFood(FoodComponent)} to + /// apply the changes. + pub fn food( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)I"); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/FoodComponent;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFood", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::components::FoodComponent::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the item food. + pub fn set_food( + &self, + food: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/FoodComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(food.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getEnchantLevel", + "setFood", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the tool is set. + pub fn has_tool(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasTool", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Returns a copy the enchantments in this ItemMeta. + /// Gets the tool set on this item, or creates an empty tool instance. /// - /// Returns an empty map if none. - pub fn enchants( + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with {@link #setTool(ToolComponent)} to + /// apply the changes. + pub fn tool( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEnchants", sig.as_str(), vec![]); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/ToolComponent;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + crate::inventory::meta::components::ToolComponent::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Adds the specified enchantment to this item meta. - pub fn add_enchant( + /// Sets the item tool. + pub fn set_tool( &self, - ench: impl Into>, - level: i32, - ignore_level_restriction: bool, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;IZ)Z"); + tool: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(tool.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(level); - let val_3 = jni::objects::JValueGen::Bool(ignore_level_restriction.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "addEnchant", + "setTool", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes the specified enchantment from this item meta. - pub fn remove_enchant( + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) + } + /// Sets the item tool. + pub fn set_jukebox_playable( + &self, + jukebox_playable: impl Into>, + ) -> Result<(), Box> { + let sig = + String::from("(Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeEnchant", + "setJukeboxPlayable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks for the existence of any AttributeModifiers. + pub fn has_attribute_modifiers(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasAttributeModifiers", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes all enchantments from this item meta. - pub fn remove_enchantments(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Return an immutable copy of all {@link AttributeModifier}s + /// for a given {@link Attribute} + pub fn get_attribute_modifiers( + &self, + attribute: impl Into>, + ) -> Result>>, Box> + { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/attribute/Attribute;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Ljava/util/Collection;"; let res = self.jni_ref().call_method( &self.jni_object(), - "removeEnchantments", + "getAttributeModifiers", sig.as_str(), - vec![], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::attribute::AttributeModifier::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(Some(new_vec)) } - /// Checks if the specified enchantment conflicts with any enchantments in - /// this ItemMeta. - pub fn has_conflicting_enchant( + /// Add an Attribute and it's Modifier. + /// AttributeModifiers can now support {@link EquipmentSlot}s. + /// If not set, the {@link AttributeModifier} will be active in ALL slots. + /// + /// Two {@link AttributeModifier}s that have the same {@link java.util.UUID} + /// cannot exist on the same Attribute. + pub fn add_attribute_modifier( &self, - ench: impl Into>, + attribute: impl Into>, + modifier: impl Into>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;Lorg/bukkit/attribute/AttributeModifier;)Z", + ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(modifier.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasConflictingEnchant", + "addAttributeModifier", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set itemflags which should be ignored when rendering a ItemStack in the Client. This Method does silently ignore double set itemFlags. - pub fn add_item_flags( + /// Set all {@link Attribute}s and their {@link AttributeModifier}s. + /// To clear all currently set Attributes and AttributeModifiers use + /// null or an empty Multimap. + /// If not null nor empty, this will filter all entries that are not-null + /// and add them to the ItemStack. + pub fn set_attribute_modifiers( &self, - item_flags: impl Into>, + attribute_modifiers: jni::objects::JObject<'mc>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) - }); + let sig = String::from("(Lcom/google/common/collect/Multimap;)V"); + let val_1 = jni::objects::JValueGen::Object(attribute_modifiers); let res = self.jni_ref().call_method( &self.jni_object(), - "addItemFlags", + "setAttributeModifiers", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Remove specific set of itemFlags. This tells the Client it should render it again. This Method does silently ignore double removed itemFlags. - pub fn remove_item_flags( + /// Remove a specific {@link Attribute} and {@link AttributeModifier}. + /// AttributeModifiers are matched according to their {@link java.util.UUID}. + pub fn remove_attribute_modifier( &self, - item_flags: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); + attribute: impl Into>, + modifier: std::option::Option>>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/attribute/Attribute;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) }); + args.push(val_1); + if let Some(a) = modifier { + sig += "Lorg/bukkit/attribute/AttributeModifier;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; let res = self.jni_ref().call_method( &self.jni_object(), - "removeItemFlags", + "removeAttributeModifier", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Get current set itemFlags. The collection returned is unmodifiable. - pub fn item_flags( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Get this ItemMeta as an NBT string. If this ItemMeta does not have any + /// NBT, then {@code "{}"} will be returned. + /// + /// This string should NEVER be relied upon as a serializable value. If + /// serialization is desired, the {@link ConfigurationSerializable} API should be used + /// instead. + pub fn as_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemFlags", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Check if the specified flag is present on this item. - pub fn has_item_flag( - &self, - flag: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(flag.into().jni_object().clone()) - }); + /// Get this ItemMeta as a component-compliant string. If this ItemMeta does + /// not contain any components, then {@code "[]"} will be returned. + /// + /// The result of this method should yield a string representing the components + /// altered by this ItemMeta instance. When passed to {@link ItemFactory#createItemStack(String)} + /// with a prepended item type, it will create an ItemStack that has an ItemMeta + /// matching this ItemMeta instance exactly. Note that this method returns + /// ONLY the components and cannot be passed to createItemStack() alone. + /// An example may look something like this: + ///
+    /// ItemStack itemStack = // ... an item stack obtained from somewhere
+    /// ItemMeta itemMeta = itemStack.getItemMeta();
+    /// String components = itemMeta.getAsComponentString(); // example: "[minecraft:damage=53]"
+    /// String itemTypeKey = itemStack.getType().getKey().toString(); // example: "minecraft:diamond_sword"
+    /// String itemAsString = itemTypeKey + components; // results in: "minecraft:diamond_sword[minecraft:damage=53]"
+    /// ItemStack recreatedItemStack = Bukkit.getItemFactory().createItemStack(itemAsString);
+    /// assert itemStack.isSimilar(recreatedItemStack); // Should be true*
+    /// 
+ /// + /// *Components not represented or explicitly overridden by this ItemMeta instance + /// will not be included in the resulting string and therefore may result in ItemStacks + /// that do not match exactly. For example, if {@link #setDisplayName(String)} + /// is not set, then the custom name component will not be included. Or if this ItemMeta + /// is a PotionMeta, it will not include any components related to lodestone compasses, + /// banners, or books, etc., only components modifiable by a PotionMeta instance. + /// + /// This string should NEVER be relied upon as a serializable value. If + /// serialization is desired, the {@link ConfigurationSerializable} API should be used + /// instead. + pub fn as_component_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasItemFlag", + "getAsComponentString", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets if this item has hide_tooltip set. An item with this set will not - /// show any tooltip whatsoever. - pub fn is_hide_tooltip(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isHideTooltip", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets if this item has hide_tooltip set. An item with this set will not - /// show any tooltip whatsoever. - pub fn set_hide_tooltip(&self, hide_tooltip: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(hide_tooltip.into()); + #[deprecated] + /// Returns a public custom tag container capable of storing tags on the item. Those tags will be sent to the client with all of their content, so the client is capable of reading them. This will result in the player seeing a NBT Tag notification on the item. These tags can also be modified by the client once in creative mode + pub fn custom_tag_container( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/tags/CustomItemTagContainer;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setHideTooltip", + "getCustomTagContainer", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Return if the unbreakable tag is true. An unbreakable item will not lose - /// durability. - pub fn is_unbreakable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isUnbreakable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::meta::tags::CustomItemTagContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the unbreakable tag. An unbreakable item will not lose durability. - pub fn set_unbreakable(&self, unbreakable: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(unbreakable.into()); + /// Internal use only! Do not use under any circumstances! + pub fn set_version(&self, version: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(version); let res = self.jni_ref().call_method( &self.jni_object(), - "setUnbreakable", + "setVersion", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if an enchantment_glint_override is set. - pub fn has_enchantment_glint_override(&self) -> Result> { + + pub fn clone( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/ItemMeta;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for BlockStateMeta<'mc> { + fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { + crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockStateMeta into crate::inventory::meta::ItemMeta") + } +} +#[repr(C)] +pub struct Repairable<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Repairable<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Repairable<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Repairable from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/Repairable")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Repairable object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Repairable<'mc> { + /// Checks to see if this has a repair penalty + pub fn has_repair_cost(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasEnchantmentGlintOverride", - sig.as_str(), - vec![], - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasRepairCost", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the enchantment_glint_override. If true, the item will glint, even - /// without enchantments; if false, the item will not glint, even with - /// enchantments. - /// Plugins should check {@link #hasEnchantmentGlintOverride()} before - /// calling this method. - pub fn enchantment_glint_override(&self) -> Result> { - let sig = String::from("()Ljava/lang/Boolean;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getEnchantmentGlintOverride", - sig.as_str(), - vec![], - ); + /// Gets the repair penalty + pub fn repair_cost(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRepairCost", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Sets the enchantment_glint_override. If true, the item will glint, even - /// without enchantments; if false, the item will not glint, even with - /// enchantments. If null, the override will be cleared. - pub fn set_enchantment_glint_override( - &self, - val_override: bool, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/Boolean;)V"); - let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( - "java/lang/Boolean", - "(Ljava/Lang/Object;)V", - vec![val_override.into()], - )?); + /// Sets the repair penalty + pub fn set_repair_cost(&self, cost: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(cost); let res = self.jni_ref().call_method( &self.jni_object(), - "setEnchantmentGlintOverride", + "setRepairCost", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if this item is fire_resistant. If true, it will not burn in fire - /// or lava. - pub fn is_fire_resistant(&self) -> Result> { + + pub fn clone( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/Repairable;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::Repairable::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Checks for existence of a display name. + pub fn has_display_name(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isFireResistant", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasDisplayName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets if this item is fire_resistant. If true, it will not burn in fire - /// or lava. - pub fn set_fire_resistant( + /// Gets the display name that is set. + /// + /// Plugins should check that hasDisplayName() returns true + /// before calling this method. + pub fn display_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDisplayName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the display name. + pub fn set_display_name( &self, - fire_resistant: bool, + name: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire_resistant.into()); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setFireResistant", + "setDisplayName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the max_stack_size is set. - pub fn has_max_stack_size(&self) -> Result> { + /// Checks for existence of an item name. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + pub fn has_item_name(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasMaxStackSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasItemName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the max_stack_size. This is the maximum amount which an item will - /// stack. - pub fn max_stack_size(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the item name that is set. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + /// + /// Plugins should check that hasItemName() returns true before + /// calling this method. + pub fn item_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItemName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets the max_stack_size. This is the maximum amount which an item will - /// stack. - pub fn set_max_stack_size(&self, max: i32) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/Integer;)V"); - let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( - "java/lang/Integer", - "(Ljava/Lang/Object;)V", - vec![max.into()], - )?); + /// Sets the item name. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + pub fn set_item_name(&self, name: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxStackSize", + "setItemName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the rarity is set. - pub fn has_rarity(&self) -> Result> { + #[deprecated] + /// Checks for existence of a localized name. + pub fn has_localized_name(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasRarity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the item rarity. - /// Plugins should check {@link #hasRarity()} before calling this method. - pub fn rarity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemRarity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getRarity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemRarity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the item rarity. - pub fn set_rarity( - &self, - rarity: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemRarity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(rarity.into().jni_object().clone()) - }); let res = self.jni_ref().call_method( &self.jni_object(), - "setRarity", + "hasLocalizedName", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks if the food is set. - pub fn has_food(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasFood", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the food set on this item, or creates an empty food instance. - /// - /// The returned component is a snapshot of its current state and does not - /// reflect a live view of what is on an item. After changing any value on - /// this component, it must be set with {@link #setFood(FoodComponent)} to - /// apply the changes. - pub fn food( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/components/FoodComponent;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFood", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::components::FoodComponent::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the item food. - pub fn set_food( - &self, - food: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/components/FoodComponent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(food.into().jni_object().clone()) - }); + #[deprecated] + /// Gets the localized display name that is set.Plugins should check that hasLocalizedName() returns true before calling this method. + pub fn localized_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setFood", + "getLocalizedName", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks if the tool is set. - pub fn has_tool(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasTool", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the tool set on this item, or creates an empty tool instance. - /// - /// The returned component is a snapshot of its current state and does not - /// reflect a live view of what is on an item. After changing any value on - /// this component, it must be set with {@link #setTool(ToolComponent)} to - /// apply the changes. - pub fn tool( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/components/ToolComponent;"); - let res = self + Ok(self .jni_ref() - .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::components::ToolComponent::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets the item tool. - pub fn set_tool( + #[deprecated] + /// Sets the localized name. + pub fn set_localized_name( &self, - tool: impl Into>, + name: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tool.into().jni_object().clone()) - }); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setTool", + "setLocalizedName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for the existence of any AttributeModifiers. - pub fn has_attribute_modifiers(&self) -> Result> { + /// Checks for existence of lore. + pub fn has_lore(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasAttributeModifiers", - sig.as_str(), - vec![], - ); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasLore", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Return an immutable copy of all {@link AttributeModifier}s - /// for a given {@link Attribute} - pub fn get_attribute_modifiers( - &self, - attribute: impl Into>, - ) -> Result>>, Box> - { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/attribute/Attribute;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Ljava/util/Collection;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAttributeModifiers", - sig.as_str(), - args, - ); + /// Gets the lore that is set. + /// + /// Plugins should check if hasLore() returns true before + /// calling this method. + pub fn lore(&self) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLore", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::attribute::AttributeModifier::from_raw( - &self.jni_ref(), - obj, - )?); + new_vec.push( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); } Ok(Some(new_vec)) } - /// Add an Attribute and it's Modifier. - /// AttributeModifiers can now support {@link EquipmentSlot}s. - /// If not set, the {@link AttributeModifier} will be active in ALL slots. - /// - /// Two {@link AttributeModifier}s that have the same {@link java.util.UUID} - /// cannot exist on the same Attribute. - pub fn add_attribute_modifier( - &self, - attribute: impl Into>, - modifier: impl Into>, - ) -> Result> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;Lorg/bukkit/attribute/AttributeModifier;)Z", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(modifier.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addAttributeModifier", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Set all {@link Attribute}s and their {@link AttributeModifier}s. - /// To clear all currently set Attributes and AttributeModifiers use - /// null or an empty Multimap. - /// If not null nor empty, this will filter all entries that are not-null - /// and add them to the ItemStack. - pub fn set_attribute_modifiers( + /// Sets the lore for this item. + /// Removes lore when given null. + pub fn set_lore( &self, - attribute_modifiers: jni::objects::JObject<'mc>, + lore: Vec>, ) -> Result<(), Box> { - let sig = String::from("(Lcom/google/common/collect/Multimap;)V"); - let val_1 = jni::objects::JValueGen::Object(attribute_modifiers); + let sig = String::from("(Ljava/util/List;)V"); + let raw_val_1 = self + .jni_ref() + .new_object("java/util/ArrayList", "()V", vec![])?; + for v in lore { + let map_val_0 = jni::objects::JValueGen::Object(v); + self.jni_ref().call_method( + &raw_val_1, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_1 = jni::objects::JValueGen::Object(raw_val_1); let res = self.jni_ref().call_method( &self.jni_object(), - "setAttributeModifiers", + "setLore", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Remove a specific {@link Attribute} and {@link AttributeModifier}. - /// AttributeModifiers are matched according to their {@link java.util.UUID}. - pub fn remove_attribute_modifier( - &self, - attribute: impl Into>, - modifier: std::option::Option>>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/attribute/Attribute;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = modifier { - sig += "Lorg/bukkit/attribute/AttributeModifier;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Z"; + /// Checks for existence of custom model data. + /// + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + pub fn has_custom_model_data(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "removeAttributeModifier", + "hasCustomModelData", sig.as_str(), - args, + vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get this ItemMeta as an NBT string. If this ItemMeta does not have any - /// NBT, then {@code "{}"} will be returned. - /// - /// This string should NEVER be relied upon as a serializable value. If - /// serialization is desired, the {@link ConfigurationSerializable} API should be used - /// instead. - pub fn as_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Get this ItemMeta as a component-compliant string. If this ItemMeta does - /// not contain any components, then {@code "[]"} will be returned. - /// - /// The result of this method should yield a string representing the components - /// altered by this ItemMeta instance. When passed to {@link ItemFactory#createItemStack(String)} - /// with a prepended item type, it will create an ItemStack that has an ItemMeta - /// matching this ItemMeta instance exactly. Note that this method returns - /// ONLY the components and cannot be passed to createItemStack() alone. - /// An example may look something like this: - ///
-    /// ItemStack itemStack = // ... an item stack obtained from somewhere
-    /// ItemMeta itemMeta = itemStack.getItemMeta();
-    /// String components = itemMeta.getAsComponentString(); // example: "[minecraft:damage=53]"
-    /// String itemTypeKey = itemStack.getType().getKey().toString(); // example: "minecraft:diamond_sword"
-    /// String itemAsString = itemTypeKey + components; // results in: "minecraft:diamond_sword[minecraft:damage=53]"
-    /// ItemStack recreatedItemStack = Bukkit.getItemFactory().createItemStack(itemAsString);
-    /// assert itemStack.isSimilar(recreatedItemStack); // Should be true*
-    /// 
+ /// Gets the custom model data that is set. /// - /// *Components not represented or explicitly overridden by this ItemMeta instance - /// will not be included in the resulting string and therefore may result in ItemStacks - /// that do not match exactly. For example, if {@link #setDisplayName(String)} - /// is not set, then the custom name component will not be included. Or if this ItemMeta - /// is a PotionMeta, it will not include any components related to lodestone compasses, - /// banners, or books, etc., only components modifiable by a PotionMeta instance. + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. /// - /// This string should NEVER be relied upon as a serializable value. If - /// serialization is desired, the {@link ConfigurationSerializable} API should be used - /// instead. - pub fn as_component_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Plugins should check that hasCustomModelData() returns true + /// before calling this method. + pub fn custom_model_data(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getAsComponentString", + "getCustomModelData", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.i()?) + } + /// Sets the custom model data. + /// + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + pub fn set_custom_model_data(&self, data: i32) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/Integer;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Integer", + "(Ljava/Lang/Object;)V", + vec![data.into()], + )?); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCustomModelData", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks for the existence of any enchantments. + pub fn has_enchants(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasEnchants", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - #[deprecated] - /// Returns a public custom tag container capable of storing tags on the item. Those tags will be sent to the client with all of their content, so the client is capable of reading them. This will result in the player seeing a NBT Tag notification on the item. These tags can also be modified by the client once in creative mode - pub fn custom_tag_container( + /// Checks for existence of the specified enchantment. + pub fn has_enchant( &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/tags/CustomItemTagContainer;"); + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getCustomTagContainer", + "hasEnchant", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::tags::CustomItemTagContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Internal use only! Do not use under any circumstances! - pub fn set_version(&self, version: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(version); + /// Checks for the level of the specified enchantment. + pub fn get_enchant_level( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)I"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVersion", + "getEnchantLevel", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Creates a Map representation of this class. + /// Returns a copy the enchantments in this ItemMeta. /// - /// This class must provide a method to restore this class, as defined in - /// the {@link ConfigurationSerializable} interface javadocs. - pub fn serialize( + /// Returns an empty map if none. + pub fn enchants( &self, ) -> Result, Box> { let sig = String::from("()Ljava/util/Map;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEnchants", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( + /// Adds the specified enchantment to this item meta. + pub fn add_enchant( &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; + ench: impl Into>, + level: i32, + ignore_level_restriction: bool, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;IZ)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(level); + let val_3 = jni::objects::JValueGen::Bool(ignore_level_restriction.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "addEnchant", sig.as_str(), - args, + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for CompassMeta<'mc> { - fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { - crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) - .expect("Error converting CompassMeta into crate::inventory::meta::ItemMeta") - } -} -#[repr(C)] -pub struct Damageable<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Damageable<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Damageable<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Damageable from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/Damageable")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Damageable object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + Ok(res.z()?) } -} - -impl<'mc> Damageable<'mc> { - /// Checks to see if this item has damage - pub fn has_damage(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasDamage", sig.as_str(), vec![]); + /// Removes the specified enchantment from this item meta. + pub fn remove_enchant( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeEnchant", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the damage - pub fn damage(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getDamage", sig.as_str(), vec![]); + /// Removes all enchantments from this item meta. + pub fn remove_enchantments(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeEnchantments", + sig.as_str(), + vec![], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the specified enchantment conflicts with any enchantments in + /// this ItemMeta. + pub fn has_conflicting_enchant( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasConflictingEnchant", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the damage - pub fn set_damage(&self, damage: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(damage); + /// Set itemflags which should be ignored when rendering a ItemStack in the Client. This Method does silently ignore double set itemFlags. + pub fn add_item_flags( + &self, + item_flags: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setDamage", + "addItemFlags", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks to see if this item has a maximum amount of damage. - pub fn has_max_damage(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasMaxDamage", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Remove specific set of itemFlags. This tells the Client it should render it again. This Method does silently ignore double removed itemFlags. + pub fn remove_item_flags( + &self, + item_flags: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeItemFlags", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the maximum amount of damage. - /// Plugins should check {@link #hasMaxDamage()} before calling this method. - pub fn max_damage(&self) -> Result> { - let sig = String::from("()I"); + /// Get current set itemFlags. The collection returned is unmodifiable. + pub fn item_flags( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxDamage", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItemFlags", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the maximum amount of damage. - pub fn set_max_damage(&self, max_damage: i32) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/Integer;)V"); - let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( - "java/lang/Integer", - "(Ljava/Lang/Object;)V", - vec![max_damage.into()], - )?); + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Check if the specified flag is present on this item. + pub fn has_item_flag( + &self, + flag: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(flag.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxDamage", + "hasItemFlag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn clone( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/Damageable;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::Damageable::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Checks for existence of a display name. - pub fn has_display_name(&self) -> Result> { + /// Gets if this item has hide_tooltip set. An item with this set will not + /// show any tooltip whatsoever. + pub fn is_hide_tooltip(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasDisplayName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isHideTooltip", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the display name that is set. - /// - /// Plugins should check that hasDisplayName() returns true - /// before calling this method. - pub fn display_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDisplayName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Sets the display name. - pub fn set_display_name( - &self, - name: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + /// Sets if this item has hide_tooltip set. An item with this set will not + /// show any tooltip whatsoever. + pub fn set_hide_tooltip(&self, hide_tooltip: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(hide_tooltip.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setDisplayName", + "setHideTooltip", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of an item name. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - pub fn has_item_name(&self) -> Result> { + /// Return if the unbreakable tag is true. An unbreakable item will not lose + /// durability. + pub fn is_unbreakable(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasItemName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isUnbreakable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the item name that is set. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - /// - /// Plugins should check that hasItemName() returns true before - /// calling this method. - pub fn item_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Sets the item name. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - pub fn set_item_name(&self, name: impl Into) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + /// Sets the unbreakable tag. An unbreakable item will not lose durability. + pub fn set_unbreakable(&self, unbreakable: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(unbreakable.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemName", + "setUnbreakable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Checks for existence of a localized name. - pub fn has_localized_name(&self) -> Result> { + /// Gets if an enchantment_glint_override is set. + pub fn has_enchantment_glint_override(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasLocalizedName", + "hasEnchantmentGlintOverride", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Gets the localized display name that is set.Plugins should check that hasLocalizedName() returns true before calling this method. - pub fn localized_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Sets the enchantment_glint_override. If true, the item will glint, even + /// without enchantments; if false, the item will not glint, even with + /// enchantments. + /// Plugins should check {@link #hasEnchantmentGlintOverride()} before + /// calling this method. + pub fn enchantment_glint_override(&self) -> Result> { + let sig = String::from("()Ljava/lang/Boolean;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocalizedName", + "getEnchantmentGlintOverride", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - #[deprecated] - /// Sets the localized name. - pub fn set_localized_name( + /// Sets the enchantment_glint_override. If true, the item will glint, even + /// without enchantments; if false, the item will not glint, even with + /// enchantments. If null, the override will be cleared. + pub fn set_enchantment_glint_override( &self, - name: impl Into, + val_override: bool, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + let sig = String::from("(Ljava/lang/Boolean;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Boolean", + "(Ljava/Lang/Object;)V", + vec![val_override.into()], + )?); let res = self.jni_ref().call_method( &self.jni_object(), - "setLocalizedName", + "setEnchantmentGlintOverride", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of lore. - pub fn has_lore(&self) -> Result> { + /// Checks if this item is fire_resistant. If true, it will not burn in fire + /// or lava. + pub fn is_fire_resistant(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasLore", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isFireResistant", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the lore that is set. - /// - /// Plugins should check if hasLore() returns true before - /// calling this method. - pub fn lore(&self) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getLore", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), - ); - } - Ok(Some(new_vec)) - } - /// Sets the lore for this item. - /// Removes lore when given null. - pub fn set_lore( + /// Sets if this item is fire_resistant. If true, it will not burn in fire + /// or lava. + pub fn set_fire_resistant( &self, - lore: Vec>, + fire_resistant: bool, ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/List;)V"); - let raw_val_1 = self - .jni_ref() - .new_object("java/util/ArrayList", "()V", vec![])?; - for v in lore { - let map_val_0 = jni::objects::JValueGen::Object(v); - self.jni_ref().call_method( - &raw_val_1, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_1 = jni::objects::JValueGen::Object(raw_val_1); + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire_resistant.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLore", + "setFireResistant", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of custom model data. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - pub fn has_custom_model_data(&self) -> Result> { + /// Gets if the max_stack_size is set. + pub fn has_max_stack_size(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasCustomModelData", - sig.as_str(), - vec![], - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasMaxStackSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the custom model data that is set. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - /// - /// Plugins should check that hasCustomModelData() returns true - /// before calling this method. - pub fn custom_model_data(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCustomModelData", - sig.as_str(), - vec![], - ); + /// Gets the max_stack_size. This is the maximum amount which an item will + /// stack. + pub fn max_stack_size(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the custom model data. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - pub fn set_custom_model_data(&self, data: i32) -> Result<(), Box> { + /// Sets the max_stack_size. This is the maximum amount which an item will + /// stack. + pub fn set_max_stack_size(&self, max: i32) -> Result<(), Box> { let sig = String::from("(Ljava/lang/Integer;)V"); let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( "java/lang/Integer", "(Ljava/Lang/Object;)V", - vec![data.into()], + vec![max.into()], )?); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomModelData", + "setMaxStackSize", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for the existence of any enchantments. - pub fn has_enchants(&self) -> Result> { + /// Gets if the rarity is set. + pub fn has_rarity(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasEnchants", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasRarity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Checks for existence of the specified enchantment. - pub fn has_enchant( + /// Gets the item rarity. + /// Plugins should check {@link #hasRarity()} before calling this method. + pub fn rarity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemRarity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRarity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemRarity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the item rarity. + pub fn set_rarity( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + rarity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemRarity;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(rarity.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasEnchant", + "setRarity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the food is set. + pub fn has_food(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasFood", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Checks for the level of the specified enchantment. - pub fn get_enchant_level( + /// Gets the food set on this item, or creates an empty food instance. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with {@link #setFood(FoodComponent)} to + /// apply the changes. + pub fn food( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)I"); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/FoodComponent;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFood", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::components::FoodComponent::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the item food. + pub fn set_food( + &self, + food: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/FoodComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(food.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getEnchantLevel", + "setFood", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the tool is set. + pub fn has_tool(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasTool", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Returns a copy the enchantments in this ItemMeta. + /// Gets the tool set on this item, or creates an empty tool instance. /// - /// Returns an empty map if none. - pub fn enchants( + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with {@link #setTool(ToolComponent)} to + /// apply the changes. + pub fn tool( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEnchants", sig.as_str(), vec![]); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/ToolComponent;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + crate::inventory::meta::components::ToolComponent::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Adds the specified enchantment to this item meta. - pub fn add_enchant( + /// Sets the item tool. + pub fn set_tool( &self, - ench: impl Into>, - level: i32, - ignore_level_restriction: bool, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;IZ)Z"); + tool: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(tool.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(level); - let val_3 = jni::objects::JValueGen::Bool(ignore_level_restriction.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "addEnchant", + "setTool", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes the specified enchantment from this item meta. - pub fn remove_enchant( + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) + } + /// Sets the item tool. + pub fn set_jukebox_playable( + &self, + jukebox_playable: impl Into>, + ) -> Result<(), Box> { + let sig = + String::from("(Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeEnchant", + "setJukeboxPlayable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks for the existence of any AttributeModifiers. + pub fn has_attribute_modifiers(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasAttributeModifiers", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes all enchantments from this item meta. - pub fn remove_enchantments(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Return an immutable copy of all {@link AttributeModifier}s + /// for a given {@link Attribute} + pub fn get_attribute_modifiers( + &self, + attribute: impl Into>, + ) -> Result>>, Box> + { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/attribute/Attribute;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Ljava/util/Collection;"; let res = self.jni_ref().call_method( &self.jni_object(), - "removeEnchantments", + "getAttributeModifiers", sig.as_str(), - vec![], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::attribute::AttributeModifier::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(Some(new_vec)) } - /// Checks if the specified enchantment conflicts with any enchantments in - /// this ItemMeta. - pub fn has_conflicting_enchant( + /// Add an Attribute and it's Modifier. + /// AttributeModifiers can now support {@link EquipmentSlot}s. + /// If not set, the {@link AttributeModifier} will be active in ALL slots. + /// + /// Two {@link AttributeModifier}s that have the same {@link java.util.UUID} + /// cannot exist on the same Attribute. + pub fn add_attribute_modifier( &self, - ench: impl Into>, + attribute: impl Into>, + modifier: impl Into>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;Lorg/bukkit/attribute/AttributeModifier;)Z", + ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(modifier.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasConflictingEnchant", + "addAttributeModifier", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set itemflags which should be ignored when rendering a ItemStack in the Client. This Method does silently ignore double set itemFlags. - pub fn add_item_flags( + /// Set all {@link Attribute}s and their {@link AttributeModifier}s. + /// To clear all currently set Attributes and AttributeModifiers use + /// null or an empty Multimap. + /// If not null nor empty, this will filter all entries that are not-null + /// and add them to the ItemStack. + pub fn set_attribute_modifiers( &self, - item_flags: impl Into>, + attribute_modifiers: jni::objects::JObject<'mc>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) - }); + let sig = String::from("(Lcom/google/common/collect/Multimap;)V"); + let val_1 = jni::objects::JValueGen::Object(attribute_modifiers); let res = self.jni_ref().call_method( &self.jni_object(), - "addItemFlags", + "setAttributeModifiers", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Remove specific set of itemFlags. This tells the Client it should render it again. This Method does silently ignore double removed itemFlags. - pub fn remove_item_flags( + /// Remove a specific {@link Attribute} and {@link AttributeModifier}. + /// AttributeModifiers are matched according to their {@link java.util.UUID}. + pub fn remove_attribute_modifier( &self, - item_flags: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); + attribute: impl Into>, + modifier: std::option::Option>>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/attribute/Attribute;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) }); + args.push(val_1); + if let Some(a) = modifier { + sig += "Lorg/bukkit/attribute/AttributeModifier;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; let res = self.jni_ref().call_method( &self.jni_object(), - "removeItemFlags", + "removeAttributeModifier", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Get current set itemFlags. The collection returned is unmodifiable. - pub fn item_flags( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Get this ItemMeta as an NBT string. If this ItemMeta does not have any + /// NBT, then {@code "{}"} will be returned. + /// + /// This string should NEVER be relied upon as a serializable value. If + /// serialization is desired, the {@link ConfigurationSerializable} API should be used + /// instead. + pub fn as_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemFlags", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Check if the specified flag is present on this item. - pub fn has_item_flag( - &self, - flag: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(flag.into().jni_object().clone()) - }); + /// Get this ItemMeta as a component-compliant string. If this ItemMeta does + /// not contain any components, then {@code "[]"} will be returned. + /// + /// The result of this method should yield a string representing the components + /// altered by this ItemMeta instance. When passed to {@link ItemFactory#createItemStack(String)} + /// with a prepended item type, it will create an ItemStack that has an ItemMeta + /// matching this ItemMeta instance exactly. Note that this method returns + /// ONLY the components and cannot be passed to createItemStack() alone. + /// An example may look something like this: + ///
+    /// ItemStack itemStack = // ... an item stack obtained from somewhere
+    /// ItemMeta itemMeta = itemStack.getItemMeta();
+    /// String components = itemMeta.getAsComponentString(); // example: "[minecraft:damage=53]"
+    /// String itemTypeKey = itemStack.getType().getKey().toString(); // example: "minecraft:diamond_sword"
+    /// String itemAsString = itemTypeKey + components; // results in: "minecraft:diamond_sword[minecraft:damage=53]"
+    /// ItemStack recreatedItemStack = Bukkit.getItemFactory().createItemStack(itemAsString);
+    /// assert itemStack.isSimilar(recreatedItemStack); // Should be true*
+    /// 
+ /// + /// *Components not represented or explicitly overridden by this ItemMeta instance + /// will not be included in the resulting string and therefore may result in ItemStacks + /// that do not match exactly. For example, if {@link #setDisplayName(String)} + /// is not set, then the custom name component will not be included. Or if this ItemMeta + /// is a PotionMeta, it will not include any components related to lodestone compasses, + /// banners, or books, etc., only components modifiable by a PotionMeta instance. + /// + /// This string should NEVER be relied upon as a serializable value. If + /// serialization is desired, the {@link ConfigurationSerializable} API should be used + /// instead. + pub fn as_component_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasItemFlag", + "getAsComponentString", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets if this item has hide_tooltip set. An item with this set will not - /// show any tooltip whatsoever. - pub fn is_hide_tooltip(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isHideTooltip", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets if this item has hide_tooltip set. An item with this set will not - /// show any tooltip whatsoever. - pub fn set_hide_tooltip(&self, hide_tooltip: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(hide_tooltip.into()); + #[deprecated] + /// Returns a public custom tag container capable of storing tags on the item. Those tags will be sent to the client with all of their content, so the client is capable of reading them. This will result in the player seeing a NBT Tag notification on the item. These tags can also be modified by the client once in creative mode + pub fn custom_tag_container( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/tags/CustomItemTagContainer;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setHideTooltip", + "getCustomTagContainer", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Return if the unbreakable tag is true. An unbreakable item will not lose - /// durability. - pub fn is_unbreakable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isUnbreakable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::meta::tags::CustomItemTagContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the unbreakable tag. An unbreakable item will not lose durability. - pub fn set_unbreakable(&self, unbreakable: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(unbreakable.into()); + /// Internal use only! Do not use under any circumstances! + pub fn set_version(&self, version: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(version); let res = self.jni_ref().call_method( &self.jni_object(), - "setUnbreakable", + "setVersion", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if an enchantment_glint_override is set. - pub fn has_enchantment_glint_override(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasEnchantmentGlintOverride", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Sets the enchantment_glint_override. If true, the item will glint, even - /// without enchantments; if false, the item will not glint, even with - /// enchantments. - /// Plugins should check {@link #hasEnchantmentGlintOverride()} before - /// calling this method. - pub fn enchantment_glint_override(&self) -> Result> { - let sig = String::from("()Ljava/lang/Boolean;"); +} +impl<'mc> Into> for Repairable<'mc> { + fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { + crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Repairable into crate::inventory::meta::ItemMeta") + } +} +#[repr(C)] +pub struct BlockDataMeta<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for BlockDataMeta<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for BlockDataMeta<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate BlockDataMeta from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/BlockDataMeta")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BlockDataMeta object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> BlockDataMeta<'mc> { + /// Returns whether the item has block data currently attached to it. + pub fn has_block_data(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasBlockData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the currently attached block data for this item or creates a new + /// one if one doesn't exist. + /// The state is a copy, it must be set back (or to another item) with + /// {@link #setBlockData(org.bukkit.block.data.BlockData)} + pub fn get_block_data( + &self, + material: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/Material;)Lorg/bukkit/block/data/BlockData;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getEnchantmentGlintOverride", + "getBlockData", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the enchantment_glint_override. If true, the item will glint, even - /// without enchantments; if false, the item will not glint, even with - /// enchantments. If null, the override will be cleared. - pub fn set_enchantment_glint_override( + /// Attaches a copy of the passed block data to the item. + pub fn set_block_data( &self, - val_override: bool, + block_data: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/Boolean;)V"); - let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( - "java/lang/Boolean", - "(Ljava/Lang/Object;)V", - vec![val_override.into()], - )?); + let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(block_data.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setEnchantmentGlintOverride", + "setBlockData", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if this item is fire_resistant. If true, it will not burn in fire - /// or lava. - pub fn is_fire_resistant(&self) -> Result> { + /// Checks for existence of a display name. + pub fn has_display_name(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isFireResistant", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasDisplayName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets if this item is fire_resistant. If true, it will not burn in fire - /// or lava. - pub fn set_fire_resistant( + /// Gets the display name that is set. + /// + /// Plugins should check that hasDisplayName() returns true + /// before calling this method. + pub fn display_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDisplayName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the display name. + pub fn set_display_name( &self, - fire_resistant: bool, + name: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire_resistant.into()); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setFireResistant", + "setDisplayName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the max_stack_size is set. - pub fn has_max_stack_size(&self) -> Result> { + /// Checks for existence of an item name. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + pub fn has_item_name(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasMaxStackSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasItemName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the max_stack_size. This is the maximum amount which an item will - /// stack. - pub fn max_stack_size(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the item name that is set. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + /// + /// Plugins should check that hasItemName() returns true before + /// calling this method. + pub fn item_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItemName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets the max_stack_size. This is the maximum amount which an item will - /// stack. - pub fn set_max_stack_size(&self, max: i32) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/Integer;)V"); - let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( - "java/lang/Integer", - "(Ljava/Lang/Object;)V", - vec![max.into()], - )?); + /// Sets the item name. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + pub fn set_item_name(&self, name: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxStackSize", + "setItemName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the rarity is set. - pub fn has_rarity(&self) -> Result> { + #[deprecated] + /// Checks for existence of a localized name. + pub fn has_localized_name(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasRarity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the item rarity. - /// Plugins should check {@link #hasRarity()} before calling this method. - pub fn rarity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemRarity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getRarity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemRarity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the item rarity. - pub fn set_rarity( - &self, - rarity: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemRarity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(rarity.into().jni_object().clone()) - }); let res = self.jni_ref().call_method( &self.jni_object(), - "setRarity", + "hasLocalizedName", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks if the food is set. - pub fn has_food(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasFood", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the food set on this item, or creates an empty food instance. - /// - /// The returned component is a snapshot of its current state and does not - /// reflect a live view of what is on an item. After changing any value on - /// this component, it must be set with {@link #setFood(FoodComponent)} to - /// apply the changes. - pub fn food( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/components/FoodComponent;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFood", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::components::FoodComponent::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the item food. - pub fn set_food( - &self, - food: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/components/FoodComponent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(food.into().jni_object().clone()) - }); + #[deprecated] + /// Gets the localized display name that is set.Plugins should check that hasLocalizedName() returns true before calling this method. + pub fn localized_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setFood", + "getLocalizedName", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks if the tool is set. - pub fn has_tool(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasTool", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the tool set on this item, or creates an empty tool instance. - /// - /// The returned component is a snapshot of its current state and does not - /// reflect a live view of what is on an item. After changing any value on - /// this component, it must be set with {@link #setTool(ToolComponent)} to - /// apply the changes. - pub fn tool( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/components/ToolComponent;"); - let res = self + Ok(self .jni_ref() - .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::components::ToolComponent::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets the item tool. - pub fn set_tool( - &self, - tool: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tool.into().jni_object().clone()) - }); + #[deprecated] + /// Sets the localized name. + pub fn set_localized_name( + &self, + name: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setTool", + "setLocalizedName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for the existence of any AttributeModifiers. - pub fn has_attribute_modifiers(&self) -> Result> { + /// Checks for existence of lore. + pub fn has_lore(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasAttributeModifiers", - sig.as_str(), - vec![], - ); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasLore", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Return an immutable copy of all {@link AttributeModifier}s - /// for a given {@link Attribute} - pub fn get_attribute_modifiers( - &self, - attribute: impl Into>, - ) -> Result>>, Box> - { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/attribute/Attribute;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Ljava/util/Collection;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAttributeModifiers", - sig.as_str(), - args, - ); + /// Gets the lore that is set. + /// + /// Plugins should check if hasLore() returns true before + /// calling this method. + pub fn lore(&self) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLore", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::attribute::AttributeModifier::from_raw( - &self.jni_ref(), - obj, - )?); + new_vec.push( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); } Ok(Some(new_vec)) } - /// Add an Attribute and it's Modifier. - /// AttributeModifiers can now support {@link EquipmentSlot}s. - /// If not set, the {@link AttributeModifier} will be active in ALL slots. - /// - /// Two {@link AttributeModifier}s that have the same {@link java.util.UUID} - /// cannot exist on the same Attribute. - pub fn add_attribute_modifier( - &self, - attribute: impl Into>, - modifier: impl Into>, - ) -> Result> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;Lorg/bukkit/attribute/AttributeModifier;)Z", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(modifier.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addAttributeModifier", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Set all {@link Attribute}s and their {@link AttributeModifier}s. - /// To clear all currently set Attributes and AttributeModifiers use - /// null or an empty Multimap. - /// If not null nor empty, this will filter all entries that are not-null - /// and add them to the ItemStack. - pub fn set_attribute_modifiers( + /// Sets the lore for this item. + /// Removes lore when given null. + pub fn set_lore( &self, - attribute_modifiers: jni::objects::JObject<'mc>, + lore: Vec>, ) -> Result<(), Box> { - let sig = String::from("(Lcom/google/common/collect/Multimap;)V"); - let val_1 = jni::objects::JValueGen::Object(attribute_modifiers); + let sig = String::from("(Ljava/util/List;)V"); + let raw_val_1 = self + .jni_ref() + .new_object("java/util/ArrayList", "()V", vec![])?; + for v in lore { + let map_val_0 = jni::objects::JValueGen::Object(v); + self.jni_ref().call_method( + &raw_val_1, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_1 = jni::objects::JValueGen::Object(raw_val_1); let res = self.jni_ref().call_method( &self.jni_object(), - "setAttributeModifiers", + "setLore", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Remove a specific {@link Attribute} and {@link AttributeModifier}. - /// AttributeModifiers are matched according to their {@link java.util.UUID}. - pub fn remove_attribute_modifier( - &self, - attribute: impl Into>, - modifier: std::option::Option>>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/attribute/Attribute;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = modifier { - sig += "Lorg/bukkit/attribute/AttributeModifier;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Z"; + /// Checks for existence of custom model data. + /// + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + pub fn has_custom_model_data(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "removeAttributeModifier", + "hasCustomModelData", sig.as_str(), - args, + vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get this ItemMeta as an NBT string. If this ItemMeta does not have any - /// NBT, then {@code "{}"} will be returned. + /// Gets the custom model data that is set. /// - /// This string should NEVER be relied upon as a serializable value. If - /// serialization is desired, the {@link ConfigurationSerializable} API should be used - /// instead. - pub fn as_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + /// + /// Plugins should check that hasCustomModelData() returns true + /// before calling this method. + pub fn custom_model_data(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCustomModelData", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.i()?) } - /// Get this ItemMeta as a component-compliant string. If this ItemMeta does - /// not contain any components, then {@code "[]"} will be returned. - /// - /// The result of this method should yield a string representing the components - /// altered by this ItemMeta instance. When passed to {@link ItemFactory#createItemStack(String)} - /// with a prepended item type, it will create an ItemStack that has an ItemMeta - /// matching this ItemMeta instance exactly. Note that this method returns - /// ONLY the components and cannot be passed to createItemStack() alone. - /// An example may look something like this: - ///
-    /// ItemStack itemStack = // ... an item stack obtained from somewhere
-    /// ItemMeta itemMeta = itemStack.getItemMeta();
-    /// String components = itemMeta.getAsComponentString(); // example: "[minecraft:damage=53]"
-    /// String itemTypeKey = itemStack.getType().getKey().toString(); // example: "minecraft:diamond_sword"
-    /// String itemAsString = itemTypeKey + components; // results in: "minecraft:diamond_sword[minecraft:damage=53]"
-    /// ItemStack recreatedItemStack = Bukkit.getItemFactory().createItemStack(itemAsString);
-    /// assert itemStack.isSimilar(recreatedItemStack); // Should be true*
-    /// 
- /// - /// *Components not represented or explicitly overridden by this ItemMeta instance - /// will not be included in the resulting string and therefore may result in ItemStacks - /// that do not match exactly. For example, if {@link #setDisplayName(String)} - /// is not set, then the custom name component will not be included. Or if this ItemMeta - /// is a PotionMeta, it will not include any components related to lodestone compasses, - /// banners, or books, etc., only components modifiable by a PotionMeta instance. + /// Sets the custom model data. /// - /// This string should NEVER be relied upon as a serializable value. If - /// serialization is desired, the {@link ConfigurationSerializable} API should be used - /// instead. - pub fn as_component_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + pub fn set_custom_model_data(&self, data: i32) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/Integer;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Integer", + "(Ljava/Lang/Object;)V", + vec![data.into()], + )?); let res = self.jni_ref().call_method( &self.jni_object(), - "getAsComponentString", + "setCustomModelData", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks for the existence of any enchantments. + pub fn has_enchants(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasEnchants", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - #[deprecated] - /// Returns a public custom tag container capable of storing tags on the item. Those tags will be sent to the client with all of their content, so the client is capable of reading them. This will result in the player seeing a NBT Tag notification on the item. These tags can also be modified by the client once in creative mode - pub fn custom_tag_container( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/tags/CustomItemTagContainer;"); + /// Checks for existence of the specified enchantment. + pub fn has_enchant( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getCustomTagContainer", + "hasEnchant", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::tags::CustomItemTagContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Internal use only! Do not use under any circumstances! - pub fn set_version(&self, version: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(version); + /// Checks for the level of the specified enchantment. + pub fn get_enchant_level( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)I"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVersion", + "getEnchantLevel", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Creates a Map representation of this class. + /// Returns a copy the enchantments in this ItemMeta. /// - /// This class must provide a method to restore this class, as defined in - /// the {@link ConfigurationSerializable} interface javadocs. - pub fn serialize( + /// Returns an empty map if none. + pub fn enchants( &self, ) -> Result, Box> { let sig = String::from("()Ljava/util/Map;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEnchants", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( + /// Adds the specified enchantment to this item meta. + pub fn add_enchant( &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; + ench: impl Into>, + level: i32, + ignore_level_restriction: bool, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;IZ)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(level); + let val_3 = jni::objects::JValueGen::Bool(ignore_level_restriction.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "addEnchant", sig.as_str(), - args, + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Damageable<'mc> { - fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { - crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Damageable into crate::inventory::meta::ItemMeta") - } -} -#[repr(C)] -pub struct BlockStateMeta<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for BlockStateMeta<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + Ok(res.z()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Removes the specified enchantment from this item meta. + pub fn remove_enchant( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeEnchant", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for BlockStateMeta<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate BlockStateMeta from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/BlockStateMeta")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockStateMeta object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Removes all enchantments from this item meta. + pub fn remove_enchantments(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeEnchantments", + sig.as_str(), + vec![], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> BlockStateMeta<'mc> { - /// Returns whether the item has a block state currently - /// attached to it. - pub fn has_block_state(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasBlockState", sig.as_str(), vec![]); + /// Checks if the specified enchantment conflicts with any enchantments in + /// this ItemMeta. + pub fn has_conflicting_enchant( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasConflictingEnchant", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns the currently attached block state for this - /// item or creates a new one if one doesn't exist. - /// The state is a copy, it must be set back (or to another - /// item) with {@link #setBlockState(org.bukkit.block.BlockState)} - pub fn block_state(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockState;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBlockState", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Set itemflags which should be ignored when rendering a ItemStack in the Client. This Method does silently ignore double set itemFlags. + pub fn add_item_flags( + &self, + item_flags: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addItemFlags", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Attaches a copy of the passed block state to the item. - pub fn set_block_state( + /// Remove specific set of itemFlags. This tells the Client it should render it again. This Method does silently ignore double removed itemFlags. + pub fn remove_item_flags( &self, - block_state: impl Into>, + item_flags: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockState;)V"); + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block_state.into().jni_object().clone()) + jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBlockState", + "removeItemFlags", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of a display name. - pub fn has_display_name(&self) -> Result> { - let sig = String::from("()Z"); + /// Get current set itemFlags. The collection returned is unmodifiable. + pub fn item_flags( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasDisplayName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItemFlags", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the display name that is set. - /// - /// Plugins should check that hasDisplayName() returns true - /// before calling this method. - pub fn display_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Check if the specified flag is present on this item. + pub fn has_item_flag( + &self, + flag: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(flag.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasItemFlag", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets if this item has hide_tooltip set. An item with this set will not + /// show any tooltip whatsoever. + pub fn is_hide_tooltip(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDisplayName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isHideTooltip", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - /// Sets the display name. - pub fn set_display_name( - &self, - name: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + /// Sets if this item has hide_tooltip set. An item with this set will not + /// show any tooltip whatsoever. + pub fn set_hide_tooltip(&self, hide_tooltip: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(hide_tooltip.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setDisplayName", + "setHideTooltip", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of an item name. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - pub fn has_item_name(&self) -> Result> { + /// Return if the unbreakable tag is true. An unbreakable item will not lose + /// durability. + pub fn is_unbreakable(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasItemName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isUnbreakable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the item name that is set. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - /// - /// Plugins should check that hasItemName() returns true before - /// calling this method. - pub fn item_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Sets the item name. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - pub fn set_item_name(&self, name: impl Into) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + /// Sets the unbreakable tag. An unbreakable item will not lose durability. + pub fn set_unbreakable(&self, unbreakable: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(unbreakable.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemName", + "setUnbreakable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Checks for existence of a localized name. - pub fn has_localized_name(&self) -> Result> { + /// Gets if an enchantment_glint_override is set. + pub fn has_enchantment_glint_override(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasLocalizedName", + "hasEnchantmentGlintOverride", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Gets the localized display name that is set.Plugins should check that hasLocalizedName() returns true before calling this method. - pub fn localized_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Sets the enchantment_glint_override. If true, the item will glint, even + /// without enchantments; if false, the item will not glint, even with + /// enchantments. + /// Plugins should check {@link #hasEnchantmentGlintOverride()} before + /// calling this method. + pub fn enchantment_glint_override(&self) -> Result> { + let sig = String::from("()Ljava/lang/Boolean;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocalizedName", + "getEnchantmentGlintOverride", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - #[deprecated] - /// Sets the localized name. - pub fn set_localized_name( + /// Sets the enchantment_glint_override. If true, the item will glint, even + /// without enchantments; if false, the item will not glint, even with + /// enchantments. If null, the override will be cleared. + pub fn set_enchantment_glint_override( &self, - name: impl Into, + val_override: bool, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + let sig = String::from("(Ljava/lang/Boolean;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Boolean", + "(Ljava/Lang/Object;)V", + vec![val_override.into()], + )?); let res = self.jni_ref().call_method( &self.jni_object(), - "setLocalizedName", + "setEnchantmentGlintOverride", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of lore. - pub fn has_lore(&self) -> Result> { + /// Checks if this item is fire_resistant. If true, it will not burn in fire + /// or lava. + pub fn is_fire_resistant(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasLore", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isFireResistant", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the lore that is set. - /// - /// Plugins should check if hasLore() returns true before - /// calling this method. - pub fn lore(&self) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getLore", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), - ); - } - Ok(Some(new_vec)) - } - /// Sets the lore for this item. - /// Removes lore when given null. - pub fn set_lore( + /// Sets if this item is fire_resistant. If true, it will not burn in fire + /// or lava. + pub fn set_fire_resistant( &self, - lore: Vec>, + fire_resistant: bool, ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/List;)V"); - let raw_val_1 = self - .jni_ref() - .new_object("java/util/ArrayList", "()V", vec![])?; - for v in lore { - let map_val_0 = jni::objects::JValueGen::Object(v); - self.jni_ref().call_method( - &raw_val_1, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_1 = jni::objects::JValueGen::Object(raw_val_1); + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire_resistant.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLore", + "setFireResistant", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of custom model data. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - pub fn has_custom_model_data(&self) -> Result> { + /// Gets if the max_stack_size is set. + pub fn has_max_stack_size(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasCustomModelData", - sig.as_str(), - vec![], - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasMaxStackSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the custom model data that is set. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - /// - /// Plugins should check that hasCustomModelData() returns true - /// before calling this method. - pub fn custom_model_data(&self) -> Result> { + /// Gets the max_stack_size. This is the maximum amount which an item will + /// stack. + pub fn max_stack_size(&self) -> Result> { let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the max_stack_size. This is the maximum amount which an item will + /// stack. + pub fn set_max_stack_size(&self, max: i32) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/Integer;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Integer", + "(Ljava/Lang/Object;)V", + vec![max.into()], + )?); let res = self.jni_ref().call_method( &self.jni_object(), - "getCustomModelData", + "setMaxStackSize", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the rarity is set. + pub fn has_rarity(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasRarity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) + } + /// Gets the item rarity. + /// Plugins should check {@link #hasRarity()} before calling this method. + pub fn rarity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemRarity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRarity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemRarity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the custom model data. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - pub fn set_custom_model_data(&self, data: i32) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/Integer;)V"); - let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( - "java/lang/Integer", - "(Ljava/Lang/Object;)V", - vec![data.into()], - )?); + /// Sets the item rarity. + pub fn set_rarity( + &self, + rarity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemRarity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(rarity.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomModelData", + "setRarity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for the existence of any enchantments. - pub fn has_enchants(&self) -> Result> { + /// Checks if the food is set. + pub fn has_food(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasEnchants", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasFood", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Checks for existence of the specified enchantment. - pub fn has_enchant( + /// Gets the food set on this item, or creates an empty food instance. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with {@link #setFood(FoodComponent)} to + /// apply the changes. + pub fn food( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasEnchant", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/FoodComponent;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFood", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::meta::components::FoodComponent::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Checks for the level of the specified enchantment. - pub fn get_enchant_level( + /// Sets the item food. + pub fn set_food( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)I"); + food: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/FoodComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(food.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getEnchantLevel", + "setFood", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the tool is set. + pub fn has_tool(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasTool", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Returns a copy the enchantments in this ItemMeta. + /// Gets the tool set on this item, or creates an empty tool instance. /// - /// Returns an empty map if none. - pub fn enchants( + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with {@link #setTool(ToolComponent)} to + /// apply the changes. + pub fn tool( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEnchants", sig.as_str(), vec![]); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/ToolComponent;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + crate::inventory::meta::components::ToolComponent::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Adds the specified enchantment to this item meta. - pub fn add_enchant( + /// Sets the item tool. + pub fn set_tool( &self, - ench: impl Into>, - level: i32, - ignore_level_restriction: bool, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;IZ)Z"); + tool: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(tool.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(level); - let val_3 = jni::objects::JValueGen::Bool(ignore_level_restriction.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "addEnchant", + "setTool", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes the specified enchantment from this item meta. - pub fn remove_enchant( + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) + } + /// Sets the item tool. + pub fn set_jukebox_playable( + &self, + jukebox_playable: impl Into>, + ) -> Result<(), Box> { + let sig = + String::from("(Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeEnchant", + "setJukeboxPlayable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Removes all enchantments from this item meta. - pub fn remove_enchantments(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Checks for the existence of any AttributeModifiers. + pub fn has_attribute_modifiers(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "removeEnchantments", + "hasAttributeModifiers", sig.as_str(), vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Checks if the specified enchantment conflicts with any enchantments in - /// this ItemMeta. - pub fn has_conflicting_enchant( + /// Return an immutable copy of all {@link AttributeModifier}s + /// for a given {@link Attribute} + pub fn get_attribute_modifiers( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + attribute: impl Into>, + ) -> Result>>, Box> + { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/attribute/Attribute;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) }); + args.push(val_1); + sig += ")Ljava/util/Collection;"; let res = self.jni_ref().call_method( &self.jni_object(), - "hasConflictingEnchant", + "getAttributeModifiers", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::attribute::AttributeModifier::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(Some(new_vec)) } - /// Set itemflags which should be ignored when rendering a ItemStack in the Client. This Method does silently ignore double set itemFlags. - pub fn add_item_flags( + /// Add an Attribute and it's Modifier. + /// AttributeModifiers can now support {@link EquipmentSlot}s. + /// If not set, the {@link AttributeModifier} will be active in ALL slots. + /// + /// Two {@link AttributeModifier}s that have the same {@link java.util.UUID} + /// cannot exist on the same Attribute. + pub fn add_attribute_modifier( &self, - item_flags: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); + attribute: impl Into>, + modifier: impl Into>, + ) -> Result> { + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;Lorg/bukkit/attribute/AttributeModifier;)Z", + ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(modifier.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "addItemFlags", + "addAttributeModifier", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Remove specific set of itemFlags. This tells the Client it should render it again. This Method does silently ignore double removed itemFlags. - pub fn remove_item_flags( + /// Set all {@link Attribute}s and their {@link AttributeModifier}s. + /// To clear all currently set Attributes and AttributeModifiers use + /// null or an empty Multimap. + /// If not null nor empty, this will filter all entries that are not-null + /// and add them to the ItemStack. + pub fn set_attribute_modifiers( &self, - item_flags: impl Into>, + attribute_modifiers: jni::objects::JObject<'mc>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) - }); + let sig = String::from("(Lcom/google/common/collect/Multimap;)V"); + let val_1 = jni::objects::JValueGen::Object(attribute_modifiers); let res = self.jni_ref().call_method( &self.jni_object(), - "removeItemFlags", + "setAttributeModifiers", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get current set itemFlags. The collection returned is unmodifiable. - pub fn item_flags( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemFlags", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Check if the specified flag is present on this item. - pub fn has_item_flag( + /// Remove a specific {@link Attribute} and {@link AttributeModifier}. + /// AttributeModifiers are matched according to their {@link java.util.UUID}. + pub fn remove_attribute_modifier( &self, - flag: impl Into>, + attribute: impl Into>, + modifier: std::option::Option>>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)Z"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/attribute/Attribute;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(flag.into().jni_object().clone()) + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) }); + args.push(val_1); + if let Some(a) = modifier { + sig += "Lorg/bukkit/attribute/AttributeModifier;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; let res = self.jni_ref().call_method( &self.jni_object(), - "hasItemFlag", + "removeAttributeModifier", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets if this item has hide_tooltip set. An item with this set will not - /// show any tooltip whatsoever. - pub fn is_hide_tooltip(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isHideTooltip", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets if this item has hide_tooltip set. An item with this set will not - /// show any tooltip whatsoever. - pub fn set_hide_tooltip(&self, hide_tooltip: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(hide_tooltip.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setHideTooltip", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Return if the unbreakable tag is true. An unbreakable item will not lose - /// durability. - pub fn is_unbreakable(&self) -> Result> { - let sig = String::from("()Z"); + /// Get this ItemMeta as an NBT string. If this ItemMeta does not have any + /// NBT, then {@code "{}"} will be returned. + /// + /// This string should NEVER be relied upon as a serializable value. If + /// serialization is desired, the {@link ConfigurationSerializable} API should be used + /// instead. + pub fn as_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isUnbreakable", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets the unbreakable tag. An unbreakable item will not lose durability. - pub fn set_unbreakable(&self, unbreakable: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(unbreakable.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setUnbreakable", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Gets if an enchantment_glint_override is set. - pub fn has_enchantment_glint_override(&self) -> Result> { - let sig = String::from("()Z"); + /// Get this ItemMeta as a component-compliant string. If this ItemMeta does + /// not contain any components, then {@code "[]"} will be returned. + /// + /// The result of this method should yield a string representing the components + /// altered by this ItemMeta instance. When passed to {@link ItemFactory#createItemStack(String)} + /// with a prepended item type, it will create an ItemStack that has an ItemMeta + /// matching this ItemMeta instance exactly. Note that this method returns + /// ONLY the components and cannot be passed to createItemStack() alone. + /// An example may look something like this: + ///
+    /// ItemStack itemStack = // ... an item stack obtained from somewhere
+    /// ItemMeta itemMeta = itemStack.getItemMeta();
+    /// String components = itemMeta.getAsComponentString(); // example: "[minecraft:damage=53]"
+    /// String itemTypeKey = itemStack.getType().getKey().toString(); // example: "minecraft:diamond_sword"
+    /// String itemAsString = itemTypeKey + components; // results in: "minecraft:diamond_sword[minecraft:damage=53]"
+    /// ItemStack recreatedItemStack = Bukkit.getItemFactory().createItemStack(itemAsString);
+    /// assert itemStack.isSimilar(recreatedItemStack); // Should be true*
+    /// 
+ /// + /// *Components not represented or explicitly overridden by this ItemMeta instance + /// will not be included in the resulting string and therefore may result in ItemStacks + /// that do not match exactly. For example, if {@link #setDisplayName(String)} + /// is not set, then the custom name component will not be included. Or if this ItemMeta + /// is a PotionMeta, it will not include any components related to lodestone compasses, + /// banners, or books, etc., only components modifiable by a PotionMeta instance. + /// + /// This string should NEVER be relied upon as a serializable value. If + /// serialization is desired, the {@link ConfigurationSerializable} API should be used + /// instead. + pub fn as_component_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasEnchantmentGlintOverride", + "getAsComponentString", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets the enchantment_glint_override. If true, the item will glint, even - /// without enchantments; if false, the item will not glint, even with - /// enchantments. - /// Plugins should check {@link #hasEnchantmentGlintOverride()} before - /// calling this method. - pub fn enchantment_glint_override(&self) -> Result> { - let sig = String::from("()Ljava/lang/Boolean;"); + #[deprecated] + /// Returns a public custom tag container capable of storing tags on the item. Those tags will be sent to the client with all of their content, so the client is capable of reading them. This will result in the player seeing a NBT Tag notification on the item. These tags can also be modified by the client once in creative mode + pub fn custom_tag_container( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/tags/CustomItemTagContainer;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getEnchantmentGlintOverride", + "getCustomTagContainer", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::meta::tags::CustomItemTagContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the enchantment_glint_override. If true, the item will glint, even - /// without enchantments; if false, the item will not glint, even with - /// enchantments. If null, the override will be cleared. - pub fn set_enchantment_glint_override( - &self, - val_override: bool, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/Boolean;)V"); - let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( - "java/lang/Boolean", - "(Ljava/Lang/Object;)V", - vec![val_override.into()], - )?); + /// Internal use only! Do not use under any circumstances! + pub fn set_version(&self, version: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(version); let res = self.jni_ref().call_method( &self.jni_object(), - "setEnchantmentGlintOverride", + "setVersion", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if this item is fire_resistant. If true, it will not burn in fire - /// or lava. - pub fn is_fire_resistant(&self) -> Result> { - let sig = String::from("()Z"); + + pub fn clone( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/ItemMeta;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for BlockDataMeta<'mc> { + fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { + crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockDataMeta into crate::inventory::meta::ItemMeta") + } +} +#[repr(C)] +pub struct TropicalFishBucketMeta<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for TropicalFishBucketMeta<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for TropicalFishBucketMeta<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate TropicalFishBucketMeta from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/inventory/meta/TropicalFishBucketMeta")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a TropicalFishBucketMeta object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> TropicalFishBucketMeta<'mc> { + /// Gets the color of the fish's pattern. + /// + /// Plugins should check that hasVariant() returns true before + /// calling this method. + pub fn pattern_color(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/DyeColor;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isFireResistant", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPatternColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::DyeColor::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets if this item is fire_resistant. If true, it will not burn in fire - /// or lava. - pub fn set_fire_resistant( + /// Sets the color of the fish's pattern. + /// + /// Setting this when hasVariant() returns false will initialize + /// all other values to unspecified defaults. + pub fn set_pattern_color( &self, - fire_resistant: bool, + color: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire_resistant.into()); + let sig = String::from("(Lorg/bukkit/DyeColor;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(color.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setFireResistant", + "setPatternColor", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the max_stack_size is set. - pub fn has_max_stack_size(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasMaxStackSize", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the max_stack_size. This is the maximum amount which an item will - /// stack. - pub fn max_stack_size(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the color of the fish's body. + /// + /// Plugins should check that hasVariant() returns true before + /// calling this method. + pub fn body_color(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/DyeColor;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBodyColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::DyeColor::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the max_stack_size. This is the maximum amount which an item will - /// stack. - pub fn set_max_stack_size(&self, max: i32) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/Integer;)V"); - let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( - "java/lang/Integer", - "(Ljava/Lang/Object;)V", - vec![max.into()], - )?); + /// Sets the color of the fish's body. + /// + /// Setting this when hasVariant() returns false will initialize + /// all other values to unspecified defaults. + pub fn set_body_color( + &self, + color: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/DyeColor;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(color.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxStackSize", + "setBodyColor", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the rarity is set. - pub fn has_rarity(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasRarity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the item rarity. - /// Plugins should check {@link #hasRarity()} before calling this method. - pub fn rarity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemRarity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getRarity", sig.as_str(), vec![]); + /// Gets the fish's pattern. + /// + /// Plugins should check that hasVariant() returns true before + /// calling this method. + pub fn pattern( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/TropicalFish/Pattern;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPattern", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemRarity::from_raw(&self.jni_ref(), unsafe { + crate::entity::TropicalFishPattern::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the item rarity. - pub fn set_rarity( + /// Sets the fish's pattern. + /// + /// Setting this when hasVariant() returns false will initialize + /// all other values to unspecified defaults. + pub fn set_pattern( &self, - rarity: impl Into>, + pattern: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemRarity;)V"); + let sig = String::from("(Lorg/bukkit/entity/TropicalFish/Pattern;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(rarity.into().jni_object().clone()) + jni::objects::JObject::from_raw(pattern.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setRarity", + "setPattern", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if the food is set. - pub fn has_food(&self) -> Result> { + /// Checks for existence of a variant tag indicating a specific fish will be + /// spawned. + pub fn has_variant(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasFood", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasVariant", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the food set on this item, or creates an empty food instance. - /// - /// The returned component is a snapshot of its current state and does not - /// reflect a live view of what is on an item. After changing any value on - /// this component, it must be set with {@link #setFood(FoodComponent)} to - /// apply the changes. - pub fn food( + + pub fn clone( &self, - ) -> Result, Box> + ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/components/FoodComponent;"); + let sig = String::from("()Lorg/bukkit/inventory/meta/TropicalFishBucketMeta;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getFood", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::components::FoodComponent::from_raw(&self.jni_ref(), unsafe { + crate::inventory::meta::TropicalFishBucketMeta::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the item food. - pub fn set_food( + /// Checks for existence of a display name. + pub fn has_display_name(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasDisplayName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the display name that is set. + /// + /// Plugins should check that hasDisplayName() returns true + /// before calling this method. + pub fn display_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDisplayName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the display name. + pub fn set_display_name( &self, - food: impl Into>, + name: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/components/FoodComponent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(food.into().jni_object().clone()) - }); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setFood", + "setDisplayName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if the tool is set. - pub fn has_tool(&self) -> Result> { + /// Checks for existence of an item name. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + pub fn has_item_name(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasTool", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasItemName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the tool set on this item, or creates an empty tool instance. + /// Gets the item name that is set. /// - /// The returned component is a snapshot of its current state and does not - /// reflect a live view of what is on an item. After changing any value on - /// this component, it must be set with {@link #setTool(ToolComponent)} to - /// apply the changes. - pub fn tool( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/components/ToolComponent;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + /// + /// Plugins should check that hasItemName() returns true before + /// calling this method. + pub fn item_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::components::ToolComponent::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the item tool. - pub fn set_tool( - &self, - tool: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tool.into().jni_object().clone()) - }); + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the item name. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + pub fn set_item_name(&self, name: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setTool", + "setItemName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for the existence of any AttributeModifiers. - pub fn has_attribute_modifiers(&self) -> Result> { + #[deprecated] + /// Checks for existence of a localized name. + pub fn has_localized_name(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasAttributeModifiers", + "hasLocalizedName", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Return an immutable copy of all {@link AttributeModifier}s - /// for a given {@link Attribute} - pub fn get_attribute_modifiers( + #[deprecated] + /// Gets the localized display name that is set.Plugins should check that hasLocalizedName() returns true before calling this method. + pub fn localized_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLocalizedName", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + #[deprecated] + /// Sets the localized name. + pub fn set_localized_name( &self, - attribute: impl Into>, - ) -> Result>>, Box> - { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/attribute/Attribute;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Ljava/util/Collection;"; + name: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "getAttributeModifiers", + "setLocalizedName", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks for existence of lore. + pub fn has_lore(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasLore", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the lore that is set. + /// + /// Plugins should check if hasLore() returns true before + /// calling this method. + pub fn lore(&self) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLore", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::attribute::AttributeModifier::from_raw( - &self.jni_ref(), - obj, - )?); + new_vec.push( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); } Ok(Some(new_vec)) } - /// Add an Attribute and it's Modifier. - /// AttributeModifiers can now support {@link EquipmentSlot}s. - /// If not set, the {@link AttributeModifier} will be active in ALL slots. - /// - /// Two {@link AttributeModifier}s that have the same {@link java.util.UUID} - /// cannot exist on the same Attribute. - pub fn add_attribute_modifier( - &self, - attribute: impl Into>, - modifier: impl Into>, - ) -> Result> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;Lorg/bukkit/attribute/AttributeModifier;)Z", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(modifier.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addAttributeModifier", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Set all {@link Attribute}s and their {@link AttributeModifier}s. - /// To clear all currently set Attributes and AttributeModifiers use - /// null or an empty Multimap. - /// If not null nor empty, this will filter all entries that are not-null - /// and add them to the ItemStack. - pub fn set_attribute_modifiers( + /// Sets the lore for this item. + /// Removes lore when given null. + pub fn set_lore( &self, - attribute_modifiers: jni::objects::JObject<'mc>, + lore: Vec>, ) -> Result<(), Box> { - let sig = String::from("(Lcom/google/common/collect/Multimap;)V"); - let val_1 = jni::objects::JValueGen::Object(attribute_modifiers); + let sig = String::from("(Ljava/util/List;)V"); + let raw_val_1 = self + .jni_ref() + .new_object("java/util/ArrayList", "()V", vec![])?; + for v in lore { + let map_val_0 = jni::objects::JValueGen::Object(v); + self.jni_ref().call_method( + &raw_val_1, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_1 = jni::objects::JValueGen::Object(raw_val_1); let res = self.jni_ref().call_method( &self.jni_object(), - "setAttributeModifiers", + "setLore", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Remove a specific {@link Attribute} and {@link AttributeModifier}. - /// AttributeModifiers are matched according to their {@link java.util.UUID}. - pub fn remove_attribute_modifier( - &self, - attribute: impl Into>, - modifier: std::option::Option>>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/attribute/Attribute;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = modifier { - sig += "Lorg/bukkit/attribute/AttributeModifier;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Z"; + /// Checks for existence of custom model data. + /// + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + pub fn has_custom_model_data(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "removeAttributeModifier", + "hasCustomModelData", sig.as_str(), - args, + vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get this ItemMeta as an NBT string. If this ItemMeta does not have any - /// NBT, then {@code "{}"} will be returned. + /// Gets the custom model data that is set. /// - /// This string should NEVER be relied upon as a serializable value. If - /// serialization is desired, the {@link ConfigurationSerializable} API should be used - /// instead. - pub fn as_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + /// + /// Plugins should check that hasCustomModelData() returns true + /// before calling this method. + pub fn custom_model_data(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCustomModelData", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.i()?) } - /// Get this ItemMeta as a component-compliant string. If this ItemMeta does - /// not contain any components, then {@code "[]"} will be returned. - /// - /// The result of this method should yield a string representing the components - /// altered by this ItemMeta instance. When passed to {@link ItemFactory#createItemStack(String)} - /// with a prepended item type, it will create an ItemStack that has an ItemMeta - /// matching this ItemMeta instance exactly. Note that this method returns - /// ONLY the components and cannot be passed to createItemStack() alone. - /// An example may look something like this: - ///
-    /// ItemStack itemStack = // ... an item stack obtained from somewhere
-    /// ItemMeta itemMeta = itemStack.getItemMeta();
-    /// String components = itemMeta.getAsComponentString(); // example: "[minecraft:damage=53]"
-    /// String itemTypeKey = itemStack.getType().getKey().toString(); // example: "minecraft:diamond_sword"
-    /// String itemAsString = itemTypeKey + components; // results in: "minecraft:diamond_sword[minecraft:damage=53]"
-    /// ItemStack recreatedItemStack = Bukkit.getItemFactory().createItemStack(itemAsString);
-    /// assert itemStack.isSimilar(recreatedItemStack); // Should be true*
-    /// 
- /// - /// *Components not represented or explicitly overridden by this ItemMeta instance - /// will not be included in the resulting string and therefore may result in ItemStacks - /// that do not match exactly. For example, if {@link #setDisplayName(String)} - /// is not set, then the custom name component will not be included. Or if this ItemMeta - /// is a PotionMeta, it will not include any components related to lodestone compasses, - /// banners, or books, etc., only components modifiable by a PotionMeta instance. + /// Sets the custom model data. /// - /// This string should NEVER be relied upon as a serializable value. If - /// serialization is desired, the {@link ConfigurationSerializable} API should be used - /// instead. - pub fn as_component_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + pub fn set_custom_model_data(&self, data: i32) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/Integer;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Integer", + "(Ljava/Lang/Object;)V", + vec![data.into()], + )?); let res = self.jni_ref().call_method( &self.jni_object(), - "getAsComponentString", + "setCustomModelData", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks for the existence of any enchantments. + pub fn has_enchants(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasEnchants", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - #[deprecated] - /// Returns a public custom tag container capable of storing tags on the item. Those tags will be sent to the client with all of their content, so the client is capable of reading them. This will result in the player seeing a NBT Tag notification on the item. These tags can also be modified by the client once in creative mode - pub fn custom_tag_container( + /// Checks for existence of the specified enchantment. + pub fn has_enchant( &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/tags/CustomItemTagContainer;"); + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getCustomTagContainer", + "hasEnchant", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::tags::CustomItemTagContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Internal use only! Do not use under any circumstances! - pub fn set_version(&self, version: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(version); + /// Checks for the level of the specified enchantment. + pub fn get_enchant_level( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)I"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVersion", + "getEnchantLevel", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn clone( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/ItemMeta;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Creates a Map representation of this class. + /// Returns a copy the enchantments in this ItemMeta. /// - /// This class must provide a method to restore this class, as defined in - /// the {@link ConfigurationSerializable} interface javadocs. - pub fn serialize( + /// Returns an empty map if none. + pub fn enchants( &self, ) -> Result, Box> { let sig = String::from("()Ljava/util/Map;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEnchants", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( + /// Adds the specified enchantment to this item meta. + pub fn add_enchant( &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; + ench: impl Into>, + level: i32, + ignore_level_restriction: bool, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;IZ)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(level); + let val_3 = jni::objects::JValueGen::Bool(ignore_level_restriction.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "addEnchant", sig.as_str(), - args, + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for BlockStateMeta<'mc> { - fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { - crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockStateMeta into crate::inventory::meta::ItemMeta") - } -} -#[repr(C)] -pub struct Repairable<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Repairable<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + Ok(res.z()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Removes the specified enchantment from this item meta. + pub fn remove_enchant( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeEnchant", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for Repairable<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Repairable from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/Repairable")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Repairable object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Removes all enchantments from this item meta. + pub fn remove_enchantments(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeEnchantments", + sig.as_str(), + vec![], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> Repairable<'mc> { - /// Checks to see if this has a repair penalty - pub fn has_repair_cost(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasRepairCost", sig.as_str(), vec![]); + /// Checks if the specified enchantment conflicts with any enchantments in + /// this ItemMeta. + pub fn has_conflicting_enchant( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasConflictingEnchant", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the repair penalty - pub fn repair_cost(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRepairCost", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + /// Set itemflags which should be ignored when rendering a ItemStack in the Client. This Method does silently ignore double set itemFlags. + pub fn add_item_flags( + &self, + item_flags: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addItemFlags", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the repair penalty - pub fn set_repair_cost(&self, cost: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(cost); + /// Remove specific set of itemFlags. This tells the Client it should render it again. This Method does silently ignore double removed itemFlags. + pub fn remove_item_flags( + &self, + item_flags: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setRepairCost", + "removeItemFlags", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn clone( + /// Get current set itemFlags. The collection returned is unmodifiable. + pub fn item_flags( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/Repairable;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemFlags", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::Repairable::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Checks for existence of a display name. - pub fn has_display_name(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasDisplayName", sig.as_str(), vec![]); + /// Check if the specified flag is present on this item. + pub fn has_item_flag( + &self, + flag: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(flag.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasItemFlag", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the display name that is set. - /// - /// Plugins should check that hasDisplayName() returns true - /// before calling this method. - pub fn display_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Gets if this item has hide_tooltip set. An item with this set will not + /// show any tooltip whatsoever. + pub fn is_hide_tooltip(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDisplayName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isHideTooltip", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - /// Sets the display name. - pub fn set_display_name( - &self, - name: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + /// Sets if this item has hide_tooltip set. An item with this set will not + /// show any tooltip whatsoever. + pub fn set_hide_tooltip(&self, hide_tooltip: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(hide_tooltip.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setDisplayName", + "setHideTooltip", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of an item name. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - pub fn has_item_name(&self) -> Result> { + /// Return if the unbreakable tag is true. An unbreakable item will not lose + /// durability. + pub fn is_unbreakable(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasItemName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isUnbreakable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the item name that is set. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - /// - /// Plugins should check that hasItemName() returns true before - /// calling this method. - pub fn item_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Sets the item name. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - pub fn set_item_name(&self, name: impl Into) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + /// Sets the unbreakable tag. An unbreakable item will not lose durability. + pub fn set_unbreakable(&self, unbreakable: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(unbreakable.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemName", + "setUnbreakable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Checks for existence of a localized name. - pub fn has_localized_name(&self) -> Result> { + /// Gets if an enchantment_glint_override is set. + pub fn has_enchantment_glint_override(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasLocalizedName", + "hasEnchantmentGlintOverride", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Gets the localized display name that is set.Plugins should check that hasLocalizedName() returns true before calling this method. - pub fn localized_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Sets the enchantment_glint_override. If true, the item will glint, even + /// without enchantments; if false, the item will not glint, even with + /// enchantments. + /// Plugins should check {@link #hasEnchantmentGlintOverride()} before + /// calling this method. + pub fn enchantment_glint_override(&self) -> Result> { + let sig = String::from("()Ljava/lang/Boolean;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocalizedName", + "getEnchantmentGlintOverride", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - #[deprecated] - /// Sets the localized name. - pub fn set_localized_name( + /// Sets the enchantment_glint_override. If true, the item will glint, even + /// without enchantments; if false, the item will not glint, even with + /// enchantments. If null, the override will be cleared. + pub fn set_enchantment_glint_override( &self, - name: impl Into, + val_override: bool, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + let sig = String::from("(Ljava/lang/Boolean;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Boolean", + "(Ljava/Lang/Object;)V", + vec![val_override.into()], + )?); let res = self.jni_ref().call_method( &self.jni_object(), - "setLocalizedName", + "setEnchantmentGlintOverride", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of lore. - pub fn has_lore(&self) -> Result> { + /// Checks if this item is fire_resistant. If true, it will not burn in fire + /// or lava. + pub fn is_fire_resistant(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasLore", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isFireResistant", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the lore that is set. - /// - /// Plugins should check if hasLore() returns true before - /// calling this method. - pub fn lore(&self) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getLore", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), - ); - } - Ok(Some(new_vec)) - } - /// Sets the lore for this item. - /// Removes lore when given null. - pub fn set_lore( + /// Sets if this item is fire_resistant. If true, it will not burn in fire + /// or lava. + pub fn set_fire_resistant( &self, - lore: Vec>, + fire_resistant: bool, ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/List;)V"); - let raw_val_1 = self - .jni_ref() - .new_object("java/util/ArrayList", "()V", vec![])?; - for v in lore { - let map_val_0 = jni::objects::JValueGen::Object(v); - self.jni_ref().call_method( - &raw_val_1, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_1 = jni::objects::JValueGen::Object(raw_val_1); + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire_resistant.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLore", + "setFireResistant", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of custom model data. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - pub fn has_custom_model_data(&self) -> Result> { + /// Gets if the max_stack_size is set. + pub fn has_max_stack_size(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasCustomModelData", - sig.as_str(), - vec![], - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasMaxStackSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the custom model data that is set. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - /// - /// Plugins should check that hasCustomModelData() returns true - /// before calling this method. - pub fn custom_model_data(&self) -> Result> { + Ok(res.z()?) + } + /// Gets the max_stack_size. This is the maximum amount which an item will + /// stack. + pub fn max_stack_size(&self) -> Result> { let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCustomModelData", - sig.as_str(), - vec![], - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the custom model data. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - pub fn set_custom_model_data(&self, data: i32) -> Result<(), Box> { + /// Sets the max_stack_size. This is the maximum amount which an item will + /// stack. + pub fn set_max_stack_size(&self, max: i32) -> Result<(), Box> { let sig = String::from("(Ljava/lang/Integer;)V"); let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( "java/lang/Integer", "(Ljava/Lang/Object;)V", - vec![data.into()], + vec![max.into()], )?); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomModelData", + "setMaxStackSize", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for the existence of any enchantments. - pub fn has_enchants(&self) -> Result> { + /// Gets if the rarity is set. + pub fn has_rarity(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasEnchants", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasRarity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Checks for existence of the specified enchantment. - pub fn has_enchant( + /// Gets the item rarity. + /// Plugins should check {@link #hasRarity()} before calling this method. + pub fn rarity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemRarity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRarity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemRarity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the item rarity. + pub fn set_rarity( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + rarity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemRarity;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(rarity.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasEnchant", + "setRarity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the food is set. + pub fn has_food(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasFood", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Checks for the level of the specified enchantment. - pub fn get_enchant_level( + /// Gets the food set on this item, or creates an empty food instance. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with {@link #setFood(FoodComponent)} to + /// apply the changes. + pub fn food( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)I"); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/FoodComponent;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFood", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::components::FoodComponent::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the item food. + pub fn set_food( + &self, + food: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/FoodComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(food.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getEnchantLevel", + "setFood", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the tool is set. + pub fn has_tool(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasTool", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Returns a copy the enchantments in this ItemMeta. + /// Gets the tool set on this item, or creates an empty tool instance. /// - /// Returns an empty map if none. - pub fn enchants( + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with {@link #setTool(ToolComponent)} to + /// apply the changes. + pub fn tool( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEnchants", sig.as_str(), vec![]); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/ToolComponent;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + crate::inventory::meta::components::ToolComponent::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Adds the specified enchantment to this item meta. - pub fn add_enchant( + /// Sets the item tool. + pub fn set_tool( &self, - ench: impl Into>, - level: i32, - ignore_level_restriction: bool, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;IZ)Z"); + tool: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(tool.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(level); - let val_3 = jni::objects::JValueGen::Bool(ignore_level_restriction.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "addEnchant", + "setTool", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes the specified enchantment from this item meta. - pub fn remove_enchant( + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) + } + /// Sets the item tool. + pub fn set_jukebox_playable( + &self, + jukebox_playable: impl Into>, + ) -> Result<(), Box> { + let sig = + String::from("(Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeEnchant", + "setJukeboxPlayable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks for the existence of any AttributeModifiers. + pub fn has_attribute_modifiers(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasAttributeModifiers", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes all enchantments from this item meta. - pub fn remove_enchantments(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Return an immutable copy of all {@link AttributeModifier}s + /// for a given {@link Attribute} + pub fn get_attribute_modifiers( + &self, + attribute: impl Into>, + ) -> Result>>, Box> + { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/attribute/Attribute;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Ljava/util/Collection;"; let res = self.jni_ref().call_method( &self.jni_object(), - "removeEnchantments", + "getAttributeModifiers", sig.as_str(), - vec![], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::attribute::AttributeModifier::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(Some(new_vec)) } - /// Checks if the specified enchantment conflicts with any enchantments in - /// this ItemMeta. - pub fn has_conflicting_enchant( + /// Add an Attribute and it's Modifier. + /// AttributeModifiers can now support {@link EquipmentSlot}s. + /// If not set, the {@link AttributeModifier} will be active in ALL slots. + /// + /// Two {@link AttributeModifier}s that have the same {@link java.util.UUID} + /// cannot exist on the same Attribute. + pub fn add_attribute_modifier( &self, - ench: impl Into>, + attribute: impl Into>, + modifier: impl Into>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;Lorg/bukkit/attribute/AttributeModifier;)Z", + ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(modifier.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "hasConflictingEnchant", + "addAttributeModifier", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set itemflags which should be ignored when rendering a ItemStack in the Client. This Method does silently ignore double set itemFlags. - pub fn add_item_flags( + /// Set all {@link Attribute}s and their {@link AttributeModifier}s. + /// To clear all currently set Attributes and AttributeModifiers use + /// null or an empty Multimap. + /// If not null nor empty, this will filter all entries that are not-null + /// and add them to the ItemStack. + pub fn set_attribute_modifiers( &self, - item_flags: impl Into>, + attribute_modifiers: jni::objects::JObject<'mc>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) - }); + let sig = String::from("(Lcom/google/common/collect/Multimap;)V"); + let val_1 = jni::objects::JValueGen::Object(attribute_modifiers); let res = self.jni_ref().call_method( &self.jni_object(), - "addItemFlags", + "setAttributeModifiers", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Remove specific set of itemFlags. This tells the Client it should render it again. This Method does silently ignore double removed itemFlags. - pub fn remove_item_flags( + /// Remove a specific {@link Attribute} and {@link AttributeModifier}. + /// AttributeModifiers are matched according to their {@link java.util.UUID}. + pub fn remove_attribute_modifier( &self, - item_flags: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); + attribute: impl Into>, + modifier: std::option::Option>>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/attribute/Attribute;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) }); + args.push(val_1); + if let Some(a) = modifier { + sig += "Lorg/bukkit/attribute/AttributeModifier;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; let res = self.jni_ref().call_method( &self.jni_object(), - "removeItemFlags", + "removeAttributeModifier", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Get current set itemFlags. The collection returned is unmodifiable. - pub fn item_flags( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Get this ItemMeta as an NBT string. If this ItemMeta does not have any + /// NBT, then {@code "{}"} will be returned. + /// + /// This string should NEVER be relied upon as a serializable value. If + /// serialization is desired, the {@link ConfigurationSerializable} API should be used + /// instead. + pub fn as_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemFlags", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Check if the specified flag is present on this item. - pub fn has_item_flag( - &self, - flag: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(flag.into().jni_object().clone()) - }); + /// Get this ItemMeta as a component-compliant string. If this ItemMeta does + /// not contain any components, then {@code "[]"} will be returned. + /// + /// The result of this method should yield a string representing the components + /// altered by this ItemMeta instance. When passed to {@link ItemFactory#createItemStack(String)} + /// with a prepended item type, it will create an ItemStack that has an ItemMeta + /// matching this ItemMeta instance exactly. Note that this method returns + /// ONLY the components and cannot be passed to createItemStack() alone. + /// An example may look something like this: + ///
+    /// ItemStack itemStack = // ... an item stack obtained from somewhere
+    /// ItemMeta itemMeta = itemStack.getItemMeta();
+    /// String components = itemMeta.getAsComponentString(); // example: "[minecraft:damage=53]"
+    /// String itemTypeKey = itemStack.getType().getKey().toString(); // example: "minecraft:diamond_sword"
+    /// String itemAsString = itemTypeKey + components; // results in: "minecraft:diamond_sword[minecraft:damage=53]"
+    /// ItemStack recreatedItemStack = Bukkit.getItemFactory().createItemStack(itemAsString);
+    /// assert itemStack.isSimilar(recreatedItemStack); // Should be true*
+    /// 
+ /// + /// *Components not represented or explicitly overridden by this ItemMeta instance + /// will not be included in the resulting string and therefore may result in ItemStacks + /// that do not match exactly. For example, if {@link #setDisplayName(String)} + /// is not set, then the custom name component will not be included. Or if this ItemMeta + /// is a PotionMeta, it will not include any components related to lodestone compasses, + /// banners, or books, etc., only components modifiable by a PotionMeta instance. + /// + /// This string should NEVER be relied upon as a serializable value. If + /// serialization is desired, the {@link ConfigurationSerializable} API should be used + /// instead. + pub fn as_component_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasItemFlag", + "getAsComponentString", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets if this item has hide_tooltip set. An item with this set will not - /// show any tooltip whatsoever. - pub fn is_hide_tooltip(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isHideTooltip", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets if this item has hide_tooltip set. An item with this set will not - /// show any tooltip whatsoever. - pub fn set_hide_tooltip(&self, hide_tooltip: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(hide_tooltip.into()); + #[deprecated] + /// Returns a public custom tag container capable of storing tags on the item. Those tags will be sent to the client with all of their content, so the client is capable of reading them. This will result in the player seeing a NBT Tag notification on the item. These tags can also be modified by the client once in creative mode + pub fn custom_tag_container( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/tags/CustomItemTagContainer;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setHideTooltip", + "getCustomTagContainer", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Return if the unbreakable tag is true. An unbreakable item will not lose - /// durability. - pub fn is_unbreakable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isUnbreakable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::meta::tags::CustomItemTagContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the unbreakable tag. An unbreakable item will not lose durability. - pub fn set_unbreakable(&self, unbreakable: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(unbreakable.into()); + /// Internal use only! Do not use under any circumstances! + pub fn set_version(&self, version: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(version); let res = self.jni_ref().call_method( &self.jni_object(), - "setUnbreakable", + "setVersion", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if an enchantment_glint_override is set. - pub fn has_enchantment_glint_override(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasEnchantmentGlintOverride", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Sets the enchantment_glint_override. If true, the item will glint, even - /// without enchantments; if false, the item will not glint, even with - /// enchantments. - /// Plugins should check {@link #hasEnchantmentGlintOverride()} before - /// calling this method. - pub fn enchantment_glint_override(&self) -> Result> { - let sig = String::from("()Ljava/lang/Boolean;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getEnchantmentGlintOverride", - sig.as_str(), - vec![], - ); +} +impl<'mc> Into> for TropicalFishBucketMeta<'mc> { + fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { + crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) + .expect("Error converting TropicalFishBucketMeta into crate::inventory::meta::ItemMeta") + } +} +#[repr(C)] +pub struct LeatherArmorMeta<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for LeatherArmorMeta<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for LeatherArmorMeta<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate LeatherArmorMeta from null object.").into(), + ); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/inventory/meta/LeatherArmorMeta")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a LeatherArmorMeta object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> LeatherArmorMeta<'mc> { + /// Gets the color of the armor. If it has not been set otherwise, it will + /// be {@link ItemFactory#getDefaultLeatherColor()}. + pub fn color(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Color;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Color::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the enchantment_glint_override. If true, the item will glint, even - /// without enchantments; if false, the item will not glint, even with - /// enchantments. If null, the override will be cleared. - pub fn set_enchantment_glint_override( + /// Sets the color of the armor. + pub fn set_color( &self, - val_override: bool, + color: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/Boolean;)V"); - let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( - "java/lang/Boolean", - "(Ljava/Lang/Object;)V", - vec![val_override.into()], - )?); + let sig = String::from("(Lorg/bukkit/Color;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(color.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setEnchantmentGlintOverride", + "setColor", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if this item is fire_resistant. If true, it will not burn in fire - /// or lava. - pub fn is_fire_resistant(&self) -> Result> { + + pub fn clone( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/LeatherArmorMeta;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::LeatherArmorMeta::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Checks for existence of a display name. + pub fn has_display_name(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isFireResistant", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasDisplayName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets if this item is fire_resistant. If true, it will not burn in fire - /// or lava. - pub fn set_fire_resistant( + /// Gets the display name that is set. + /// + /// Plugins should check that hasDisplayName() returns true + /// before calling this method. + pub fn display_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDisplayName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the display name. + pub fn set_display_name( &self, - fire_resistant: bool, + name: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire_resistant.into()); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setFireResistant", + "setDisplayName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the max_stack_size is set. - pub fn has_max_stack_size(&self) -> Result> { + /// Checks for existence of an item name. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + pub fn has_item_name(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasMaxStackSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasItemName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the max_stack_size. This is the maximum amount which an item will - /// stack. - pub fn max_stack_size(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the item name that is set. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + /// + /// Plugins should check that hasItemName() returns true before + /// calling this method. + pub fn item_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItemName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets the max_stack_size. This is the maximum amount which an item will - /// stack. - pub fn set_max_stack_size(&self, max: i32) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/Integer;)V"); - let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( - "java/lang/Integer", - "(Ljava/Lang/Object;)V", - vec![max.into()], - )?); + /// Sets the item name. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + pub fn set_item_name(&self, name: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxStackSize", + "setItemName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the rarity is set. - pub fn has_rarity(&self) -> Result> { + #[deprecated] + /// Checks for existence of a localized name. + pub fn has_localized_name(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasRarity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the item rarity. - /// Plugins should check {@link #hasRarity()} before calling this method. - pub fn rarity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemRarity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getRarity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemRarity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the item rarity. - pub fn set_rarity( - &self, - rarity: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemRarity;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(rarity.into().jni_object().clone()) - }); let res = self.jni_ref().call_method( &self.jni_object(), - "setRarity", + "hasLocalizedName", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks if the food is set. - pub fn has_food(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasFood", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the food set on this item, or creates an empty food instance. - /// - /// The returned component is a snapshot of its current state and does not - /// reflect a live view of what is on an item. After changing any value on - /// this component, it must be set with {@link #setFood(FoodComponent)} to - /// apply the changes. - pub fn food( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/components/FoodComponent;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFood", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::components::FoodComponent::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the item food. - pub fn set_food( - &self, - food: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/components/FoodComponent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(food.into().jni_object().clone()) - }); + #[deprecated] + /// Gets the localized display name that is set.Plugins should check that hasLocalizedName() returns true before calling this method. + pub fn localized_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setFood", + "getLocalizedName", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks if the tool is set. - pub fn has_tool(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasTool", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the tool set on this item, or creates an empty tool instance. - /// - /// The returned component is a snapshot of its current state and does not - /// reflect a live view of what is on an item. After changing any value on - /// this component, it must be set with {@link #setTool(ToolComponent)} to - /// apply the changes. - pub fn tool( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/components/ToolComponent;"); - let res = self + Ok(self .jni_ref() - .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::components::ToolComponent::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets the item tool. - pub fn set_tool( + #[deprecated] + /// Sets the localized name. + pub fn set_localized_name( &self, - tool: impl Into>, + name: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tool.into().jni_object().clone()) - }); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setTool", + "setLocalizedName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for the existence of any AttributeModifiers. - pub fn has_attribute_modifiers(&self) -> Result> { + /// Checks for existence of lore. + pub fn has_lore(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasAttributeModifiers", - sig.as_str(), - vec![], - ); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasLore", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Return an immutable copy of all {@link AttributeModifier}s - /// for a given {@link Attribute} - pub fn get_attribute_modifiers( - &self, - attribute: impl Into>, - ) -> Result>>, Box> - { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/attribute/Attribute;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Ljava/util/Collection;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAttributeModifiers", - sig.as_str(), - args, - ); + /// Gets the lore that is set. + /// + /// Plugins should check if hasLore() returns true before + /// calling this method. + pub fn lore(&self) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLore", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::attribute::AttributeModifier::from_raw( - &self.jni_ref(), - obj, - )?); + new_vec.push( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); } Ok(Some(new_vec)) } - /// Add an Attribute and it's Modifier. - /// AttributeModifiers can now support {@link EquipmentSlot}s. - /// If not set, the {@link AttributeModifier} will be active in ALL slots. - /// - /// Two {@link AttributeModifier}s that have the same {@link java.util.UUID} - /// cannot exist on the same Attribute. - pub fn add_attribute_modifier( - &self, - attribute: impl Into>, - modifier: impl Into>, - ) -> Result> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;Lorg/bukkit/attribute/AttributeModifier;)Z", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(modifier.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addAttributeModifier", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Set all {@link Attribute}s and their {@link AttributeModifier}s. - /// To clear all currently set Attributes and AttributeModifiers use - /// null or an empty Multimap. - /// If not null nor empty, this will filter all entries that are not-null - /// and add them to the ItemStack. - pub fn set_attribute_modifiers( + /// Sets the lore for this item. + /// Removes lore when given null. + pub fn set_lore( &self, - attribute_modifiers: jni::objects::JObject<'mc>, + lore: Vec>, ) -> Result<(), Box> { - let sig = String::from("(Lcom/google/common/collect/Multimap;)V"); - let val_1 = jni::objects::JValueGen::Object(attribute_modifiers); + let sig = String::from("(Ljava/util/List;)V"); + let raw_val_1 = self + .jni_ref() + .new_object("java/util/ArrayList", "()V", vec![])?; + for v in lore { + let map_val_0 = jni::objects::JValueGen::Object(v); + self.jni_ref().call_method( + &raw_val_1, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_1 = jni::objects::JValueGen::Object(raw_val_1); let res = self.jni_ref().call_method( &self.jni_object(), - "setAttributeModifiers", + "setLore", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Remove a specific {@link Attribute} and {@link AttributeModifier}. - /// AttributeModifiers are matched according to their {@link java.util.UUID}. - pub fn remove_attribute_modifier( - &self, - attribute: impl Into>, - modifier: std::option::Option>>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/attribute/Attribute;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = modifier { - sig += "Lorg/bukkit/attribute/AttributeModifier;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Z"; + /// Checks for existence of custom model data. + /// + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + pub fn has_custom_model_data(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "removeAttributeModifier", + "hasCustomModelData", sig.as_str(), - args, + vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get this ItemMeta as an NBT string. If this ItemMeta does not have any - /// NBT, then {@code "{}"} will be returned. + /// Gets the custom model data that is set. /// - /// This string should NEVER be relied upon as a serializable value. If - /// serialization is desired, the {@link ConfigurationSerializable} API should be used - /// instead. - pub fn as_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + /// + /// Plugins should check that hasCustomModelData() returns true + /// before calling this method. + pub fn custom_model_data(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCustomModelData", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.i()?) } - /// Get this ItemMeta as a component-compliant string. If this ItemMeta does - /// not contain any components, then {@code "[]"} will be returned. - /// - /// The result of this method should yield a string representing the components - /// altered by this ItemMeta instance. When passed to {@link ItemFactory#createItemStack(String)} - /// with a prepended item type, it will create an ItemStack that has an ItemMeta - /// matching this ItemMeta instance exactly. Note that this method returns - /// ONLY the components and cannot be passed to createItemStack() alone. - /// An example may look something like this: - ///
-    /// ItemStack itemStack = // ... an item stack obtained from somewhere
-    /// ItemMeta itemMeta = itemStack.getItemMeta();
-    /// String components = itemMeta.getAsComponentString(); // example: "[minecraft:damage=53]"
-    /// String itemTypeKey = itemStack.getType().getKey().toString(); // example: "minecraft:diamond_sword"
-    /// String itemAsString = itemTypeKey + components; // results in: "minecraft:diamond_sword[minecraft:damage=53]"
-    /// ItemStack recreatedItemStack = Bukkit.getItemFactory().createItemStack(itemAsString);
-    /// assert itemStack.isSimilar(recreatedItemStack); // Should be true*
-    /// 
- /// - /// *Components not represented or explicitly overridden by this ItemMeta instance - /// will not be included in the resulting string and therefore may result in ItemStacks - /// that do not match exactly. For example, if {@link #setDisplayName(String)} - /// is not set, then the custom name component will not be included. Or if this ItemMeta - /// is a PotionMeta, it will not include any components related to lodestone compasses, - /// banners, or books, etc., only components modifiable by a PotionMeta instance. + /// Sets the custom model data. /// - /// This string should NEVER be relied upon as a serializable value. If - /// serialization is desired, the {@link ConfigurationSerializable} API should be used - /// instead. - pub fn as_component_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + pub fn set_custom_model_data(&self, data: i32) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/Integer;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Integer", + "(Ljava/Lang/Object;)V", + vec![data.into()], + )?); let res = self.jni_ref().call_method( &self.jni_object(), - "getAsComponentString", + "setCustomModelData", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks for the existence of any enchantments. + pub fn has_enchants(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasEnchants", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - #[deprecated] - /// Returns a public custom tag container capable of storing tags on the item. Those tags will be sent to the client with all of their content, so the client is capable of reading them. This will result in the player seeing a NBT Tag notification on the item. These tags can also be modified by the client once in creative mode - pub fn custom_tag_container( + /// Checks for existence of the specified enchantment. + pub fn has_enchant( &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/tags/CustomItemTagContainer;"); + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getCustomTagContainer", + "hasEnchant", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::tags::CustomItemTagContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Internal use only! Do not use under any circumstances! - pub fn set_version(&self, version: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(version); + /// Checks for the level of the specified enchantment. + pub fn get_enchant_level( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)I"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setVersion", + "getEnchantLevel", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Creates a Map representation of this class. + /// Returns a copy the enchantments in this ItemMeta. /// - /// This class must provide a method to restore this class, as defined in - /// the {@link ConfigurationSerializable} interface javadocs. - pub fn serialize( + /// Returns an empty map if none. + pub fn enchants( &self, ) -> Result, Box> { let sig = String::from("()Ljava/util/Map;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEnchants", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( + /// Adds the specified enchantment to this item meta. + pub fn add_enchant( &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; + ench: impl Into>, + level: i32, + ignore_level_restriction: bool, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;IZ)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(level); + let val_3 = jni::objects::JValueGen::Bool(ignore_level_restriction.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "addEnchant", sig.as_str(), - args, + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Repairable<'mc> { - fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { - crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Repairable into crate::inventory::meta::ItemMeta") - } -} -#[repr(C)] -pub struct BlockDataMeta<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for BlockDataMeta<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + Ok(res.z()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Removes the specified enchantment from this item meta. + pub fn remove_enchant( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeEnchant", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for BlockDataMeta<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate BlockDataMeta from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/BlockDataMeta")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockDataMeta object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Removes all enchantments from this item meta. + pub fn remove_enchantments(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeEnchantments", + sig.as_str(), + vec![], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> BlockDataMeta<'mc> { - /// Returns whether the item has block data currently attached to it. - pub fn has_block_data(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasBlockData", sig.as_str(), vec![]); + /// Checks if the specified enchantment conflicts with any enchantments in + /// this ItemMeta. + pub fn has_conflicting_enchant( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasConflictingEnchant", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns the currently attached block data for this item or creates a new - /// one if one doesn't exist. - /// The state is a copy, it must be set back (or to another item) with - /// {@link #setBlockData(org.bukkit.block.data.BlockData)} - pub fn get_block_data( + /// Set itemflags which should be ignored when rendering a ItemStack in the Client. This Method does silently ignore double set itemFlags. + pub fn add_item_flags( &self, - material: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/Material;)Lorg/bukkit/block/data/BlockData;"); + item_flags: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) + jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getBlockData", + "addItemFlags", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Attaches a copy of the passed block data to the item. - pub fn set_block_data( + /// Remove specific set of itemFlags. This tells the Client it should render it again. This Method does silently ignore double removed itemFlags. + pub fn remove_item_flags( &self, - block_data: impl Into>, + item_flags: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/data/BlockData;)V"); + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block_data.into().jni_object().clone()) + jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBlockData", + "removeItemFlags", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of a display name. - pub fn has_display_name(&self) -> Result> { - let sig = String::from("()Z"); + /// Get current set itemFlags. The collection returned is unmodifiable. + pub fn item_flags( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasDisplayName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItemFlags", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the display name that is set. - /// - /// Plugins should check that hasDisplayName() returns true - /// before calling this method. - pub fn display_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Check if the specified flag is present on this item. + pub fn has_item_flag( + &self, + flag: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(flag.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasItemFlag", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets if this item has hide_tooltip set. An item with this set will not + /// show any tooltip whatsoever. + pub fn is_hide_tooltip(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDisplayName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isHideTooltip", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - /// Sets the display name. - pub fn set_display_name( - &self, - name: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + /// Sets if this item has hide_tooltip set. An item with this set will not + /// show any tooltip whatsoever. + pub fn set_hide_tooltip(&self, hide_tooltip: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(hide_tooltip.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setDisplayName", + "setHideTooltip", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of an item name. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - pub fn has_item_name(&self) -> Result> { + /// Return if the unbreakable tag is true. An unbreakable item will not lose + /// durability. + pub fn is_unbreakable(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasItemName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isUnbreakable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the item name that is set. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - /// - /// Plugins should check that hasItemName() returns true before - /// calling this method. - pub fn item_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Sets the item name. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - pub fn set_item_name(&self, name: impl Into) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + /// Sets the unbreakable tag. An unbreakable item will not lose durability. + pub fn set_unbreakable(&self, unbreakable: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(unbreakable.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemName", + "setUnbreakable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Checks for existence of a localized name. - pub fn has_localized_name(&self) -> Result> { + /// Gets if an enchantment_glint_override is set. + pub fn has_enchantment_glint_override(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasLocalizedName", + "hasEnchantmentGlintOverride", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Gets the localized display name that is set.Plugins should check that hasLocalizedName() returns true before calling this method. - pub fn localized_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Sets the enchantment_glint_override. If true, the item will glint, even + /// without enchantments; if false, the item will not glint, even with + /// enchantments. + /// Plugins should check {@link #hasEnchantmentGlintOverride()} before + /// calling this method. + pub fn enchantment_glint_override(&self) -> Result> { + let sig = String::from("()Ljava/lang/Boolean;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLocalizedName", + "getEnchantmentGlintOverride", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - #[deprecated] - /// Sets the localized name. - pub fn set_localized_name( + /// Sets the enchantment_glint_override. If true, the item will glint, even + /// without enchantments; if false, the item will not glint, even with + /// enchantments. If null, the override will be cleared. + pub fn set_enchantment_glint_override( &self, - name: impl Into, + val_override: bool, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + let sig = String::from("(Ljava/lang/Boolean;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Boolean", + "(Ljava/Lang/Object;)V", + vec![val_override.into()], + )?); let res = self.jni_ref().call_method( &self.jni_object(), - "setLocalizedName", + "setEnchantmentGlintOverride", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of lore. - pub fn has_lore(&self) -> Result> { + /// Checks if this item is fire_resistant. If true, it will not burn in fire + /// or lava. + pub fn is_fire_resistant(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasLore", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isFireResistant", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the lore that is set. - /// - /// Plugins should check if hasLore() returns true before - /// calling this method. - pub fn lore(&self) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getLore", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), - ); - } - Ok(Some(new_vec)) - } - /// Sets the lore for this item. - /// Removes lore when given null. - pub fn set_lore( + /// Sets if this item is fire_resistant. If true, it will not burn in fire + /// or lava. + pub fn set_fire_resistant( &self, - lore: Vec>, + fire_resistant: bool, ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/List;)V"); - let raw_val_1 = self - .jni_ref() - .new_object("java/util/ArrayList", "()V", vec![])?; - for v in lore { - let map_val_0 = jni::objects::JValueGen::Object(v); - self.jni_ref().call_method( - &raw_val_1, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_1 = jni::objects::JValueGen::Object(raw_val_1); + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire_resistant.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLore", + "setFireResistant", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of custom model data. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - pub fn has_custom_model_data(&self) -> Result> { + /// Gets if the max_stack_size is set. + pub fn has_max_stack_size(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasCustomModelData", - sig.as_str(), - vec![], - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasMaxStackSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the custom model data that is set. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - /// - /// Plugins should check that hasCustomModelData() returns true - /// before calling this method. - pub fn custom_model_data(&self) -> Result> { + /// Gets the max_stack_size. This is the maximum amount which an item will + /// stack. + pub fn max_stack_size(&self) -> Result> { let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCustomModelData", - sig.as_str(), - vec![], - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the custom model data. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - pub fn set_custom_model_data(&self, data: i32) -> Result<(), Box> { + /// Sets the max_stack_size. This is the maximum amount which an item will + /// stack. + pub fn set_max_stack_size(&self, max: i32) -> Result<(), Box> { let sig = String::from("(Ljava/lang/Integer;)V"); let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( "java/lang/Integer", "(Ljava/Lang/Object;)V", - vec![data.into()], + vec![max.into()], )?); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomModelData", + "setMaxStackSize", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the rarity is set. + pub fn has_rarity(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasRarity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the item rarity. + /// Plugins should check {@link #hasRarity()} before calling this method. + pub fn rarity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemRarity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRarity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemRarity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the item rarity. + pub fn set_rarity( + &self, + rarity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemRarity;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(rarity.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRarity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for the existence of any enchantments. - pub fn has_enchants(&self) -> Result> { + /// Checks if the food is set. + pub fn has_food(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasEnchants", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasFood", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Checks for existence of the specified enchantment. - pub fn has_enchant( + /// Gets the food set on this item, or creates an empty food instance. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with {@link #setFood(FoodComponent)} to + /// apply the changes. + pub fn food( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasEnchant", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/FoodComponent;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFood", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::meta::components::FoodComponent::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Checks for the level of the specified enchantment. - pub fn get_enchant_level( + /// Sets the item food. + pub fn set_food( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)I"); + food: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/FoodComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(food.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getEnchantLevel", + "setFood", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the tool is set. + pub fn has_tool(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasTool", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Returns a copy the enchantments in this ItemMeta. + /// Gets the tool set on this item, or creates an empty tool instance. /// - /// Returns an empty map if none. - pub fn enchants( + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with {@link #setTool(ToolComponent)} to + /// apply the changes. + pub fn tool( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEnchants", sig.as_str(), vec![]); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/ToolComponent;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + crate::inventory::meta::components::ToolComponent::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Adds the specified enchantment to this item meta. - pub fn add_enchant( + /// Sets the item tool. + pub fn set_tool( &self, - ench: impl Into>, - level: i32, - ignore_level_restriction: bool, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;IZ)Z"); + tool: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(tool.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(level); - let val_3 = jni::objects::JValueGen::Bool(ignore_level_restriction.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "addEnchant", + "setTool", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes the specified enchantment from this item meta. - pub fn remove_enchant( + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) + } + /// Sets the item tool. + pub fn set_jukebox_playable( + &self, + jukebox_playable: impl Into>, + ) -> Result<(), Box> { + let sig = + String::from("(Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeEnchant", + "setJukeboxPlayable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Removes all enchantments from this item meta. - pub fn remove_enchantments(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Checks for the existence of any AttributeModifiers. + pub fn has_attribute_modifiers(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "removeEnchantments", + "hasAttributeModifiers", sig.as_str(), vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Checks if the specified enchantment conflicts with any enchantments in - /// this ItemMeta. - pub fn has_conflicting_enchant( + /// Return an immutable copy of all {@link AttributeModifier}s + /// for a given {@link Attribute} + pub fn get_attribute_modifiers( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + attribute: impl Into>, + ) -> Result>>, Box> + { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/attribute/Attribute;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) }); + args.push(val_1); + sig += ")Ljava/util/Collection;"; let res = self.jni_ref().call_method( &self.jni_object(), - "hasConflictingEnchant", + "getAttributeModifiers", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::attribute::AttributeModifier::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(Some(new_vec)) } - /// Set itemflags which should be ignored when rendering a ItemStack in the Client. This Method does silently ignore double set itemFlags. - pub fn add_item_flags( + /// Add an Attribute and it's Modifier. + /// AttributeModifiers can now support {@link EquipmentSlot}s. + /// If not set, the {@link AttributeModifier} will be active in ALL slots. + /// + /// Two {@link AttributeModifier}s that have the same {@link java.util.UUID} + /// cannot exist on the same Attribute. + pub fn add_attribute_modifier( &self, - item_flags: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); + attribute: impl Into>, + modifier: impl Into>, + ) -> Result> { + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;Lorg/bukkit/attribute/AttributeModifier;)Z", + ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(modifier.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "addItemFlags", + "addAttributeModifier", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Remove specific set of itemFlags. This tells the Client it should render it again. This Method does silently ignore double removed itemFlags. - pub fn remove_item_flags( + /// Set all {@link Attribute}s and their {@link AttributeModifier}s. + /// To clear all currently set Attributes and AttributeModifiers use + /// null or an empty Multimap. + /// If not null nor empty, this will filter all entries that are not-null + /// and add them to the ItemStack. + pub fn set_attribute_modifiers( &self, - item_flags: impl Into>, + attribute_modifiers: jni::objects::JObject<'mc>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) - }); + let sig = String::from("(Lcom/google/common/collect/Multimap;)V"); + let val_1 = jni::objects::JValueGen::Object(attribute_modifiers); let res = self.jni_ref().call_method( &self.jni_object(), - "removeItemFlags", + "setAttributeModifiers", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get current set itemFlags. The collection returned is unmodifiable. - pub fn item_flags( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemFlags", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Check if the specified flag is present on this item. - pub fn has_item_flag( + /// Remove a specific {@link Attribute} and {@link AttributeModifier}. + /// AttributeModifiers are matched according to their {@link java.util.UUID}. + pub fn remove_attribute_modifier( &self, - flag: impl Into>, + attribute: impl Into>, + modifier: std::option::Option>>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)Z"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/attribute/Attribute;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(flag.into().jni_object().clone()) + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) }); + args.push(val_1); + if let Some(a) = modifier { + sig += "Lorg/bukkit/attribute/AttributeModifier;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; let res = self.jni_ref().call_method( &self.jni_object(), - "hasItemFlag", + "removeAttributeModifier", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets if this item has hide_tooltip set. An item with this set will not - /// show any tooltip whatsoever. - pub fn is_hide_tooltip(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isHideTooltip", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets if this item has hide_tooltip set. An item with this set will not - /// show any tooltip whatsoever. - pub fn set_hide_tooltip(&self, hide_tooltip: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(hide_tooltip.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setHideTooltip", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Return if the unbreakable tag is true. An unbreakable item will not lose - /// durability. - pub fn is_unbreakable(&self) -> Result> { - let sig = String::from("()Z"); + /// Get this ItemMeta as an NBT string. If this ItemMeta does not have any + /// NBT, then {@code "{}"} will be returned. + /// + /// This string should NEVER be relied upon as a serializable value. If + /// serialization is desired, the {@link ConfigurationSerializable} API should be used + /// instead. + pub fn as_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isUnbreakable", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets the unbreakable tag. An unbreakable item will not lose durability. - pub fn set_unbreakable(&self, unbreakable: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(unbreakable.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setUnbreakable", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Gets if an enchantment_glint_override is set. - pub fn has_enchantment_glint_override(&self) -> Result> { - let sig = String::from("()Z"); + /// Get this ItemMeta as a component-compliant string. If this ItemMeta does + /// not contain any components, then {@code "[]"} will be returned. + /// + /// The result of this method should yield a string representing the components + /// altered by this ItemMeta instance. When passed to {@link ItemFactory#createItemStack(String)} + /// with a prepended item type, it will create an ItemStack that has an ItemMeta + /// matching this ItemMeta instance exactly. Note that this method returns + /// ONLY the components and cannot be passed to createItemStack() alone. + /// An example may look something like this: + ///
+    /// ItemStack itemStack = // ... an item stack obtained from somewhere
+    /// ItemMeta itemMeta = itemStack.getItemMeta();
+    /// String components = itemMeta.getAsComponentString(); // example: "[minecraft:damage=53]"
+    /// String itemTypeKey = itemStack.getType().getKey().toString(); // example: "minecraft:diamond_sword"
+    /// String itemAsString = itemTypeKey + components; // results in: "minecraft:diamond_sword[minecraft:damage=53]"
+    /// ItemStack recreatedItemStack = Bukkit.getItemFactory().createItemStack(itemAsString);
+    /// assert itemStack.isSimilar(recreatedItemStack); // Should be true*
+    /// 
+ /// + /// *Components not represented or explicitly overridden by this ItemMeta instance + /// will not be included in the resulting string and therefore may result in ItemStacks + /// that do not match exactly. For example, if {@link #setDisplayName(String)} + /// is not set, then the custom name component will not be included. Or if this ItemMeta + /// is a PotionMeta, it will not include any components related to lodestone compasses, + /// banners, or books, etc., only components modifiable by a PotionMeta instance. + /// + /// This string should NEVER be relied upon as a serializable value. If + /// serialization is desired, the {@link ConfigurationSerializable} API should be used + /// instead. + pub fn as_component_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasEnchantmentGlintOverride", + "getAsComponentString", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets the enchantment_glint_override. If true, the item will glint, even - /// without enchantments; if false, the item will not glint, even with - /// enchantments. - /// Plugins should check {@link #hasEnchantmentGlintOverride()} before - /// calling this method. - pub fn enchantment_glint_override(&self) -> Result> { - let sig = String::from("()Ljava/lang/Boolean;"); + #[deprecated] + /// Returns a public custom tag container capable of storing tags on the item. Those tags will be sent to the client with all of their content, so the client is capable of reading them. This will result in the player seeing a NBT Tag notification on the item. These tags can also be modified by the client once in creative mode + pub fn custom_tag_container( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/tags/CustomItemTagContainer;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getEnchantmentGlintOverride", + "getCustomTagContainer", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::meta::tags::CustomItemTagContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the enchantment_glint_override. If true, the item will glint, even - /// without enchantments; if false, the item will not glint, even with - /// enchantments. If null, the override will be cleared. - pub fn set_enchantment_glint_override( - &self, - val_override: bool, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/Boolean;)V"); - let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( - "java/lang/Boolean", - "(Ljava/Lang/Object;)V", - vec![val_override.into()], - )?); + /// Internal use only! Do not use under any circumstances! + pub fn set_version(&self, version: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(version); let res = self.jni_ref().call_method( &self.jni_object(), - "setEnchantmentGlintOverride", + "setVersion", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if this item is fire_resistant. If true, it will not burn in fire - /// or lava. - pub fn is_fire_resistant(&self) -> Result> { + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for LeatherArmorMeta<'mc> { + fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { + crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) + .expect("Error converting LeatherArmorMeta into crate::inventory::meta::ItemMeta") + } +} +#[repr(C)] +pub struct SkullMeta<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for SkullMeta<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for SkullMeta<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate SkullMeta from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/SkullMeta")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a SkullMeta object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> SkullMeta<'mc> { + #[deprecated] + /// Gets the owner of the skull. + pub fn owner(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Checks to see if the skull has an owner. + pub fn has_owner(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isFireResistant", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasOwner", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets if this item is fire_resistant. If true, it will not burn in fire - /// or lava. - pub fn set_fire_resistant( - &self, - fire_resistant: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire_resistant.into()); + #[deprecated] + /// Sets the owner of the skull. + pub fn set_owner(&self, owner: impl Into) -> Result> { + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(owner.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setFireResistant", + "setOwner", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets if the max_stack_size is set. - pub fn has_max_stack_size(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasMaxStackSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the max_stack_size. This is the maximum amount which an item will - /// stack. - pub fn max_stack_size(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the owner of the skull. + pub fn owning_player( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/OfflinePlayer;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getOwningPlayer", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::OfflinePlayer::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the max_stack_size. This is the maximum amount which an item will - /// stack. - pub fn set_max_stack_size(&self, max: i32) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/Integer;)V"); - let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( - "java/lang/Integer", - "(Ljava/Lang/Object;)V", - vec![max.into()], - )?); + /// Sets the owner of the skull. + /// + /// Plugins should check that hasOwner() returns true before calling this + /// plugin. + pub fn set_owning_player( + &self, + owner: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/OfflinePlayer;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owner.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxStackSize", + "setOwningPlayer", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets if the rarity is set. - pub fn has_rarity(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasRarity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the item rarity. - /// Plugins should check {@link #hasRarity()} before calling this method. - pub fn rarity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemRarity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getRarity", sig.as_str(), vec![]); + /// Gets the profile of the player who owns the skull. This player profile + /// may appear as the texture depending on skull type. + pub fn owner_profile( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/profile/PlayerProfile;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getOwnerProfile", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemRarity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::profile::PlayerProfile::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the item rarity. - pub fn set_rarity( + /// Sets the profile of the player who owns the skull. This player profile + /// may appear as the texture depending on skull type. + /// + /// The profile must contain both a unique id and a skin texture. If either + /// of these is missing, the profile must contain a name by which the server + /// will then attempt to look up the unique id and skin texture. + pub fn set_owner_profile( &self, - rarity: impl Into>, + profile: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemRarity;)V"); + let sig = String::from("(Lorg/bukkit/profile/PlayerProfile;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(rarity.into().jni_object().clone()) + jni::objects::JObject::from_raw(profile.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setRarity", + "setOwnerProfile", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if the food is set. - pub fn has_food(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasFood", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the food set on this item, or creates an empty food instance. + /// Sets the sound to play if the skull is placed on a note block. /// - /// The returned component is a snapshot of its current state and does not - /// reflect a live view of what is on an item. After changing any value on - /// this component, it must be set with {@link #setFood(FoodComponent)} to - /// apply the changes. - pub fn food( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/components/FoodComponent;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFood", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::components::FoodComponent::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the item food. - pub fn set_food( + /// Note: This only works for player heads. For other heads, + /// see {@link org.bukkit.Instrument}. + pub fn set_note_block_sound( &self, - food: impl Into>, + note_block_sound: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/components/FoodComponent;)V"); + let sig = String::from("(Lorg/bukkit/NamespacedKey;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(food.into().jni_object().clone()) + jni::objects::JObject::from_raw(note_block_sound.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setFood", + "setNoteBlockSound", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if the tool is set. - pub fn has_tool(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasTool", sig.as_str(), vec![]); + /// Gets the sound to play if the skull is placed on a note block. + /// + /// Note: This only works for player heads. For other heads, + /// see {@link org.bukkit.Instrument}. + pub fn note_block_sound( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNoteBlockSound", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::NamespacedKey::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets the tool set on this item, or creates an empty tool instance. - /// - /// The returned component is a snapshot of its current state and does not - /// reflect a live view of what is on an item. After changing any value on - /// this component, it must be set with {@link #setTool(ToolComponent)} to - /// apply the changes. - pub fn tool( + + pub fn clone( &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/components/ToolComponent;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/SkullMeta;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::components::ToolComponent::from_raw(&self.jni_ref(), unsafe { + crate::inventory::meta::SkullMeta::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the item tool. - pub fn set_tool( + /// Checks for existence of a display name. + pub fn has_display_name(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasDisplayName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the display name that is set. + /// + /// Plugins should check that hasDisplayName() returns true + /// before calling this method. + pub fn display_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDisplayName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the display name. + pub fn set_display_name( &self, - tool: impl Into>, + name: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tool.into().jni_object().clone()) - }); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setTool", + "setDisplayName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for the existence of any AttributeModifiers. - pub fn has_attribute_modifiers(&self) -> Result> { + /// Checks for existence of an item name. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + pub fn has_item_name(&self) -> Result> { let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasItemName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the item name that is set. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + /// + /// Plugins should check that hasItemName() returns true before + /// calling this method. + pub fn item_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the item name. + /// + /// Item name differs from display name in that it is cannot be edited by an + /// anvil, is not styled with italics, and does not show labels. + pub fn set_item_name(&self, name: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "hasAttributeModifiers", + "setItemName", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Return an immutable copy of all {@link AttributeModifier}s - /// for a given {@link Attribute} - pub fn get_attribute_modifiers( - &self, - attribute: impl Into>, - ) -> Result>>, Box> - { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/attribute/Attribute;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Ljava/util/Collection;"; + #[deprecated] + /// Checks for existence of a localized name. + pub fn has_localized_name(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getAttributeModifiers", + "hasLocalizedName", sig.as_str(), - args, + vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::attribute::AttributeModifier::from_raw( - &self.jni_ref(), - obj, - )?); - } - Ok(Some(new_vec)) + Ok(res.z()?) } - /// Add an Attribute and it's Modifier. - /// AttributeModifiers can now support {@link EquipmentSlot}s. - /// If not set, the {@link AttributeModifier} will be active in ALL slots. - /// - /// Two {@link AttributeModifier}s that have the same {@link java.util.UUID} - /// cannot exist on the same Attribute. - pub fn add_attribute_modifier( - &self, - attribute: impl Into>, - modifier: impl Into>, - ) -> Result> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;Lorg/bukkit/attribute/AttributeModifier;)Z", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(modifier.into().jni_object().clone()) - }); + #[deprecated] + /// Gets the localized display name that is set.Plugins should check that hasLocalizedName() returns true before calling this method. + pub fn localized_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref().call_method( &self.jni_object(), - "addAttributeModifier", + "getLocalizedName", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Set all {@link Attribute}s and their {@link AttributeModifier}s. - /// To clear all currently set Attributes and AttributeModifiers use - /// null or an empty Multimap. - /// If not null nor empty, this will filter all entries that are not-null - /// and add them to the ItemStack. - pub fn set_attribute_modifiers( + #[deprecated] + /// Sets the localized name. + pub fn set_localized_name( &self, - attribute_modifiers: jni::objects::JObject<'mc>, + name: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Lcom/google/common/collect/Multimap;)V"); - let val_1 = jni::objects::JValueGen::Object(attribute_modifiers); + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setAttributeModifiers", + "setLocalizedName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Remove a specific {@link Attribute} and {@link AttributeModifier}. - /// AttributeModifiers are matched according to their {@link java.util.UUID}. - pub fn remove_attribute_modifier( - &self, - attribute: impl Into>, - modifier: std::option::Option>>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/attribute/Attribute;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = modifier { - sig += "Lorg/bukkit/attribute/AttributeModifier;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Z"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "removeAttributeModifier", - sig.as_str(), - args, - ); + /// Checks for existence of lore. + pub fn has_lore(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasLore", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get this ItemMeta as an NBT string. If this ItemMeta does not have any - /// NBT, then {@code "{}"} will be returned. + /// Gets the lore that is set. /// - /// This string should NEVER be relied upon as a serializable value. If - /// serialization is desired, the {@link ConfigurationSerializable} API should be used - /// instead. - pub fn as_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self + /// Plugins should check if hasLore() returns true before + /// calling this method. + pub fn lore(&self) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + .call_method(&self.jni_object(), "getLore", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); + } + Ok(Some(new_vec)) } - /// Get this ItemMeta as a component-compliant string. If this ItemMeta does - /// not contain any components, then {@code "[]"} will be returned. - /// - /// The result of this method should yield a string representing the components - /// altered by this ItemMeta instance. When passed to {@link ItemFactory#createItemStack(String)} - /// with a prepended item type, it will create an ItemStack that has an ItemMeta - /// matching this ItemMeta instance exactly. Note that this method returns - /// ONLY the components and cannot be passed to createItemStack() alone. - /// An example may look something like this: - ///
-    /// ItemStack itemStack = // ... an item stack obtained from somewhere
-    /// ItemMeta itemMeta = itemStack.getItemMeta();
-    /// String components = itemMeta.getAsComponentString(); // example: "[minecraft:damage=53]"
-    /// String itemTypeKey = itemStack.getType().getKey().toString(); // example: "minecraft:diamond_sword"
-    /// String itemAsString = itemTypeKey + components; // results in: "minecraft:diamond_sword[minecraft:damage=53]"
-    /// ItemStack recreatedItemStack = Bukkit.getItemFactory().createItemStack(itemAsString);
-    /// assert itemStack.isSimilar(recreatedItemStack); // Should be true*
-    /// 
- /// - /// *Components not represented or explicitly overridden by this ItemMeta instance - /// will not be included in the resulting string and therefore may result in ItemStacks - /// that do not match exactly. For example, if {@link #setDisplayName(String)} - /// is not set, then the custom name component will not be included. Or if this ItemMeta - /// is a PotionMeta, it will not include any components related to lodestone compasses, - /// banners, or books, etc., only components modifiable by a PotionMeta instance. + /// Sets the lore for this item. + /// Removes lore when given null. + pub fn set_lore( + &self, + lore: Vec>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/List;)V"); + let raw_val_1 = self + .jni_ref() + .new_object("java/util/ArrayList", "()V", vec![])?; + for v in lore { + let map_val_0 = jni::objects::JValueGen::Object(v); + self.jni_ref().call_method( + &raw_val_1, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_1 = jni::objects::JValueGen::Object(raw_val_1); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLore", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks for existence of custom model data. /// - /// This string should NEVER be relied upon as a serializable value. If - /// serialization is desired, the {@link ConfigurationSerializable} API should be used - /// instead. - pub fn as_component_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + pub fn has_custom_model_data(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getAsComponentString", + "hasCustomModelData", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - #[deprecated] - /// Returns a public custom tag container capable of storing tags on the item. Those tags will be sent to the client with all of their content, so the client is capable of reading them. This will result in the player seeing a NBT Tag notification on the item. These tags can also be modified by the client once in creative mode - pub fn custom_tag_container( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/tags/CustomItemTagContainer;"); + /// Gets the custom model data that is set. + /// + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + /// + /// Plugins should check that hasCustomModelData() returns true + /// before calling this method. + pub fn custom_model_data(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCustomTagContainer", + "getCustomModelData", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::tags::CustomItemTagContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Internal use only! Do not use under any circumstances! - pub fn set_version(&self, version: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(version); + /// Sets the custom model data. + /// + /// CustomModelData is an integer that may be associated client side with a + /// custom item model. + pub fn set_custom_model_data(&self, data: i32) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/Integer;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Integer", + "(Ljava/Lang/Object;)V", + vec![data.into()], + )?); let res = self.jni_ref().call_method( &self.jni_object(), - "setVersion", + "setCustomModelData", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn clone( + /// Checks for the existence of any enchantments. + pub fn has_enchants(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasEnchants", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks for existence of the specified enchantment. + pub fn has_enchant( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/ItemMeta;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasEnchant", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Creates a Map representation of this class. + /// Checks for the level of the specified enchantment. + pub fn get_enchant_level( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)I"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getEnchantLevel", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns a copy the enchantments in this ItemMeta. /// - /// This class must provide a method to restore this class, as defined in - /// the {@link ConfigurationSerializable} interface javadocs. - pub fn serialize( + /// Returns an empty map if none. + pub fn enchants( &self, ) -> Result, Box> { let sig = String::from("()Ljava/util/Map;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEnchants", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( + /// Adds the specified enchantment to this item meta. + pub fn add_enchant( &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; + ench: impl Into>, + level: i32, + ignore_level_restriction: bool, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;IZ)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(level); + let val_3 = jni::objects::JValueGen::Bool(ignore_level_restriction.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "addEnchant", sig.as_str(), - args, + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for BlockDataMeta<'mc> { - fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { - crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockDataMeta into crate::inventory::meta::ItemMeta") - } -} -#[repr(C)] -pub struct TropicalFishBucketMeta<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for TropicalFishBucketMeta<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for TropicalFishBucketMeta<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate TropicalFishBucketMeta from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/inventory/meta/TropicalFishBucketMeta")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a TropicalFishBucketMeta object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + Ok(res.z()?) } -} - -impl<'mc> TropicalFishBucketMeta<'mc> { - /// Gets the color of the fish's pattern. - /// - /// Plugins should check that hasVariant() returns true before - /// calling this method. - pub fn pattern_color(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/DyeColor;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPatternColor", sig.as_str(), vec![]); + /// Removes the specified enchantment from this item meta. + pub fn remove_enchant( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeEnchant", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - crate::DyeColor::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) + } + /// Removes all enchantments from this item meta. + pub fn remove_enchantments(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeEnchantments", + sig.as_str(), + vec![], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Sets the color of the fish's pattern. - /// - /// Setting this when hasVariant() returns false will initialize - /// all other values to unspecified defaults. - pub fn set_pattern_color( + /// Checks if the specified enchantment conflicts with any enchantments in + /// this ItemMeta. + pub fn has_conflicting_enchant( &self, - color: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/DyeColor;)V"); + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPatternColor", + "hasConflictingEnchant", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the color of the fish's body. - /// - /// Plugins should check that hasVariant() returns true before - /// calling this method. - pub fn body_color(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/DyeColor;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBodyColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::DyeColor::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets the color of the fish's body. - /// - /// Setting this when hasVariant() returns false will initialize - /// all other values to unspecified defaults. - pub fn set_body_color( + /// Set itemflags which should be ignored when rendering a ItemStack in the Client. This Method does silently ignore double set itemFlags. + pub fn add_item_flags( &self, - color: impl Into>, + item_flags: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/DyeColor;)V"); + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) + jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBodyColor", + "addItemFlags", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the fish's pattern. - /// - /// Plugins should check that hasVariant() returns true before - /// calling this method. - pub fn pattern( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/TropicalFish/Pattern;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPattern", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::TropicalFishPattern::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the fish's pattern. - /// - /// Setting this when hasVariant() returns false will initialize - /// all other values to unspecified defaults. - pub fn set_pattern( + /// Remove specific set of itemFlags. This tells the Client it should render it again. This Method does silently ignore double removed itemFlags. + pub fn remove_item_flags( &self, - pattern: impl Into>, + item_flags: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/TropicalFish/Pattern;)V"); + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(pattern.into().jni_object().clone()) + jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPattern", + "removeItemFlags", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of a variant tag indicating a specific fish will be - /// spawned. - pub fn has_variant(&self) -> Result> { - let sig = String::from("()Z"); + /// Get current set itemFlags. The collection returned is unmodifiable. + pub fn item_flags( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasVariant", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn clone( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/TropicalFishBucketMeta;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItemFlags", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::TropicalFishBucketMeta::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Checks for existence of a display name. - pub fn has_display_name(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasDisplayName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the display name that is set. - /// - /// Plugins should check that hasDisplayName() returns true - /// before calling this method. - pub fn display_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDisplayName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Sets the display name. - pub fn set_display_name( + /// Check if the specified flag is present on this item. + pub fn has_item_flag( &self, - name: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + flag: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(flag.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setDisplayName", + "hasItemFlag", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks for existence of an item name. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - pub fn has_item_name(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasItemName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the item name that is set. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - /// - /// Plugins should check that hasItemName() returns true before - /// calling this method. - pub fn item_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Gets if this item has hide_tooltip set. An item with this set will not + /// show any tooltip whatsoever. + pub fn is_hide_tooltip(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Sets the item name. - /// - /// Item name differs from display name in that it is cannot be edited by an - /// anvil, is not styled with italics, and does not show labels. - pub fn set_item_name(&self, name: impl Into) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setItemName", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Checks for existence of a localized name. - pub fn has_localized_name(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasLocalizedName", - sig.as_str(), - vec![], - ); + .call_method(&self.jni_object(), "isHideTooltip", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Gets the localized display name that is set.Plugins should check that hasLocalizedName() returns true before calling this method. - pub fn localized_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLocalizedName", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - #[deprecated] - /// Sets the localized name. - pub fn set_localized_name( - &self, - name: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + /// Sets if this item has hide_tooltip set. An item with this set will not + /// show any tooltip whatsoever. + pub fn set_hide_tooltip(&self, hide_tooltip: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(hide_tooltip.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLocalizedName", + "setHideTooltip", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of lore. - pub fn has_lore(&self) -> Result> { + /// Return if the unbreakable tag is true. An unbreakable item will not lose + /// durability. + pub fn is_unbreakable(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasLore", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isUnbreakable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the lore that is set. - /// - /// Plugins should check if hasLore() returns true before - /// calling this method. - pub fn lore(&self) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getLore", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), - ); - } - Ok(Some(new_vec)) - } - /// Sets the lore for this item. - /// Removes lore when given null. - pub fn set_lore( - &self, - lore: Vec>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/List;)V"); - let raw_val_1 = self - .jni_ref() - .new_object("java/util/ArrayList", "()V", vec![])?; - for v in lore { - let map_val_0 = jni::objects::JValueGen::Object(v); - self.jni_ref().call_method( - &raw_val_1, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_1 = jni::objects::JValueGen::Object(raw_val_1); + /// Sets the unbreakable tag. An unbreakable item will not lose durability. + pub fn set_unbreakable(&self, unbreakable: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(unbreakable.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setLore", + "setUnbreakable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for existence of custom model data. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - pub fn has_custom_model_data(&self) -> Result> { + /// Gets if an enchantment_glint_override is set. + pub fn has_enchantment_glint_override(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasCustomModelData", + "hasEnchantmentGlintOverride", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the custom model data that is set. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - /// - /// Plugins should check that hasCustomModelData() returns true - /// before calling this method. - pub fn custom_model_data(&self) -> Result> { - let sig = String::from("()I"); + /// Sets the enchantment_glint_override. If true, the item will glint, even + /// without enchantments; if false, the item will not glint, even with + /// enchantments. + /// Plugins should check {@link #hasEnchantmentGlintOverride()} before + /// calling this method. + pub fn enchantment_glint_override(&self) -> Result> { + let sig = String::from("()Ljava/lang/Boolean;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCustomModelData", + "getEnchantmentGlintOverride", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the custom model data. - /// - /// CustomModelData is an integer that may be associated client side with a - /// custom item model. - pub fn set_custom_model_data(&self, data: i32) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/Integer;)V"); + /// Sets the enchantment_glint_override. If true, the item will glint, even + /// without enchantments; if false, the item will not glint, even with + /// enchantments. If null, the override will be cleared. + pub fn set_enchantment_glint_override( + &self, + val_override: bool, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/Boolean;)V"); let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( - "java/lang/Integer", + "java/lang/Boolean", "(Ljava/Lang/Object;)V", - vec![data.into()], + vec![val_override.into()], )?); let res = self.jni_ref().call_method( &self.jni_object(), - "setCustomModelData", + "setEnchantmentGlintOverride", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks for the existence of any enchantments. - pub fn has_enchants(&self) -> Result> { + /// Checks if this item is fire_resistant. If true, it will not burn in fire + /// or lava. + pub fn is_fire_resistant(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasEnchants", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isFireResistant", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Checks for existence of the specified enchantment. - pub fn has_enchant( + /// Sets if this item is fire_resistant. If true, it will not burn in fire + /// or lava. + pub fn set_fire_resistant( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) - }); + fire_resistant: bool, + ) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(fire_resistant.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "hasEnchant", + "setFireResistant", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the max_stack_size is set. + pub fn has_max_stack_size(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasMaxStackSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Checks for the level of the specified enchantment. - pub fn get_enchant_level( - &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)I"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) - }); + /// Gets the max_stack_size. This is the maximum amount which an item will + /// stack. + pub fn max_stack_size(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the max_stack_size. This is the maximum amount which an item will + /// stack. + pub fn set_max_stack_size(&self, max: i32) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/Integer;)V"); + let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( + "java/lang/Integer", + "(Ljava/Lang/Object;)V", + vec![max.into()], + )?); let res = self.jni_ref().call_method( &self.jni_object(), - "getEnchantLevel", + "setMaxStackSize", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets if the rarity is set. + pub fn has_rarity(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasRarity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Returns a copy the enchantments in this ItemMeta. - /// - /// Returns an empty map if none. - pub fn enchants( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEnchants", sig.as_str(), vec![]); + /// Gets the item rarity. + /// Plugins should check {@link #hasRarity()} before calling this method. + pub fn rarity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemRarity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRarity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + crate::inventory::ItemRarity::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Adds the specified enchantment to this item meta. - pub fn add_enchant( + /// Sets the item rarity. + pub fn set_rarity( &self, - ench: impl Into>, - level: i32, - ignore_level_restriction: bool, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;IZ)Z"); + rarity: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemRarity;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(rarity.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(level); - let val_3 = jni::objects::JValueGen::Bool(ignore_level_restriction.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "addEnchant", + "setRarity", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the food is set. + pub fn has_food(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasFood", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes the specified enchantment from this item meta. - pub fn remove_enchant( + /// Gets the food set on this item, or creates an empty food instance. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with {@link #setFood(FoodComponent)} to + /// apply the changes. + pub fn food( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/FoodComponent;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFood", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::components::FoodComponent::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the item food. + pub fn set_food( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + food: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/FoodComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(food.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeEnchant", + "setFood", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the tool is set. + pub fn has_tool(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasTool", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes all enchantments from this item meta. - pub fn remove_enchantments(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Gets the tool set on this item, or creates an empty tool instance. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with {@link #setTool(ToolComponent)} to + /// apply the changes. + pub fn tool( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/ToolComponent;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::components::ToolComponent::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the item tool. + pub fn set_tool( + &self, + tool: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(tool.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeEnchantments", + "setTool", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if the specified enchantment conflicts with any enchantments in - /// this ItemMeta. - pub fn has_conflicting_enchant( - &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) - }); + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasConflictingEnchant", + "hasJukeboxPlayable", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set itemflags which should be ignored when rendering a ItemStack in the Client. This Method does silently ignore double set itemFlags. - pub fn add_item_flags( + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( &self, - item_flags: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) - }); + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"); let res = self.jni_ref().call_method( &self.jni_object(), - "addItemFlags", + "getJukeboxPlayable", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) } - /// Remove specific set of itemFlags. This tells the Client it should render it again. This Method does silently ignore double removed itemFlags. - pub fn remove_item_flags( + /// Sets the item tool. + pub fn set_jukebox_playable( &self, - item_flags: impl Into>, + jukebox_playable: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)V"); + let sig = + String::from("(Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_flags.into().jni_object().clone()) + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeItemFlags", + "setJukeboxPlayable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get current set itemFlags. The collection returned is unmodifiable. - pub fn item_flags( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemFlags", sig.as_str(), vec![]); + /// Checks for the existence of any AttributeModifiers. + pub fn has_attribute_modifiers(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasAttributeModifiers", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Check if the specified flag is present on this item. - pub fn has_item_flag( + /// Return an immutable copy of all {@link AttributeModifier}s + /// for a given {@link Attribute} + pub fn get_attribute_modifiers( &self, - flag: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemFlag;)Z"); + attribute: impl Into>, + ) -> Result>>, Box> + { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/attribute/Attribute;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(flag.into().jni_object().clone()) + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) }); + args.push(val_1); + sig += ")Ljava/util/Collection;"; let res = self.jni_ref().call_method( &self.jni_object(), - "hasItemFlag", + "getAttributeModifiers", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets if this item has hide_tooltip set. An item with this set will not - /// show any tooltip whatsoever. - pub fn is_hide_tooltip(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isHideTooltip", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::attribute::AttributeModifier::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(Some(new_vec)) } - /// Sets if this item has hide_tooltip set. An item with this set will not - /// show any tooltip whatsoever. - pub fn set_hide_tooltip(&self, hide_tooltip: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(hide_tooltip.into()); + /// Add an Attribute and it's Modifier. + /// AttributeModifiers can now support {@link EquipmentSlot}s. + /// If not set, the {@link AttributeModifier} will be active in ALL slots. + /// + /// Two {@link AttributeModifier}s that have the same {@link java.util.UUID} + /// cannot exist on the same Attribute. + pub fn add_attribute_modifier( + &self, + attribute: impl Into>, + modifier: impl Into>, + ) -> Result> { + let sig = String::from( + "(Lorg/bukkit/attribute/Attribute;Lorg/bukkit/attribute/AttributeModifier;)Z", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(modifier.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setHideTooltip", + "addAttributeModifier", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Return if the unbreakable tag is true. An unbreakable item will not lose - /// durability. - pub fn is_unbreakable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isUnbreakable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the unbreakable tag. An unbreakable item will not lose durability. - pub fn set_unbreakable(&self, unbreakable: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(unbreakable.into()); + /// Set all {@link Attribute}s and their {@link AttributeModifier}s. + /// To clear all currently set Attributes and AttributeModifiers use + /// null or an empty Multimap. + /// If not null nor empty, this will filter all entries that are not-null + /// and add them to the ItemStack. + pub fn set_attribute_modifiers( + &self, + attribute_modifiers: jni::objects::JObject<'mc>, + ) -> Result<(), Box> { + let sig = String::from("(Lcom/google/common/collect/Multimap;)V"); + let val_1 = jni::objects::JValueGen::Object(attribute_modifiers); let res = self.jni_ref().call_method( &self.jni_object(), - "setUnbreakable", + "setAttributeModifiers", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if an enchantment_glint_override is set. - pub fn has_enchantment_glint_override(&self) -> Result> { - let sig = String::from("()Z"); + /// Remove a specific {@link Attribute} and {@link AttributeModifier}. + /// AttributeModifiers are matched according to their {@link java.util.UUID}. + pub fn remove_attribute_modifier( + &self, + attribute: impl Into>, + modifier: std::option::Option>>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/attribute/Attribute;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = modifier { + sig += "Lorg/bukkit/attribute/AttributeModifier;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; let res = self.jni_ref().call_method( &self.jni_object(), - "hasEnchantmentGlintOverride", + "removeAttributeModifier", sig.as_str(), - vec![], + args, ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the enchantment_glint_override. If true, the item will glint, even - /// without enchantments; if false, the item will not glint, even with - /// enchantments. - /// Plugins should check {@link #hasEnchantmentGlintOverride()} before - /// calling this method. - pub fn enchantment_glint_override(&self) -> Result> { - let sig = String::from("()Ljava/lang/Boolean;"); + /// Get this ItemMeta as an NBT string. If this ItemMeta does not have any + /// NBT, then {@code "{}"} will be returned. + /// + /// This string should NEVER be relied upon as a serializable value. If + /// serialization is desired, the {@link ConfigurationSerializable} API should be used + /// instead. + pub fn as_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Get this ItemMeta as a component-compliant string. If this ItemMeta does + /// not contain any components, then {@code "[]"} will be returned. + /// + /// The result of this method should yield a string representing the components + /// altered by this ItemMeta instance. When passed to {@link ItemFactory#createItemStack(String)} + /// with a prepended item type, it will create an ItemStack that has an ItemMeta + /// matching this ItemMeta instance exactly. Note that this method returns + /// ONLY the components and cannot be passed to createItemStack() alone. + /// An example may look something like this: + ///
+    /// ItemStack itemStack = // ... an item stack obtained from somewhere
+    /// ItemMeta itemMeta = itemStack.getItemMeta();
+    /// String components = itemMeta.getAsComponentString(); // example: "[minecraft:damage=53]"
+    /// String itemTypeKey = itemStack.getType().getKey().toString(); // example: "minecraft:diamond_sword"
+    /// String itemAsString = itemTypeKey + components; // results in: "minecraft:diamond_sword[minecraft:damage=53]"
+    /// ItemStack recreatedItemStack = Bukkit.getItemFactory().createItemStack(itemAsString);
+    /// assert itemStack.isSimilar(recreatedItemStack); // Should be true*
+    /// 
+ /// + /// *Components not represented or explicitly overridden by this ItemMeta instance + /// will not be included in the resulting string and therefore may result in ItemStacks + /// that do not match exactly. For example, if {@link #setDisplayName(String)} + /// is not set, then the custom name component will not be included. Or if this ItemMeta + /// is a PotionMeta, it will not include any components related to lodestone compasses, + /// banners, or books, etc., only components modifiable by a PotionMeta instance. + /// + /// This string should NEVER be relied upon as a serializable value. If + /// serialization is desired, the {@link ConfigurationSerializable} API should be used + /// instead. + pub fn as_component_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getEnchantmentGlintOverride", + "getAsComponentString", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Sets the enchantment_glint_override. If true, the item will glint, even - /// without enchantments; if false, the item will not glint, even with - /// enchantments. If null, the override will be cleared. - pub fn set_enchantment_glint_override( + #[deprecated] + /// Returns a public custom tag container capable of storing tags on the item. Those tags will be sent to the client with all of their content, so the client is capable of reading them. This will result in the player seeing a NBT Tag notification on the item. These tags can also be modified by the client once in creative mode + pub fn custom_tag_container( &self, - val_override: bool, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/Boolean;)V"); - let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( - "java/lang/Boolean", - "(Ljava/Lang/Object;)V", - vec![val_override.into()], - )?); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/tags/CustomItemTagContainer;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setEnchantmentGlintOverride", + "getCustomTagContainer", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks if this item is fire_resistant. If true, it will not burn in fire - /// or lava. - pub fn is_fire_resistant(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isFireResistant", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::meta::tags::CustomItemTagContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets if this item is fire_resistant. If true, it will not burn in fire - /// or lava. - pub fn set_fire_resistant( - &self, - fire_resistant: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(fire_resistant.into()); + /// Internal use only! Do not use under any circumstances! + pub fn set_version(&self, version: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(version); let res = self.jni_ref().call_method( &self.jni_object(), - "setFireResistant", + "setVersion", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets if the max_stack_size is set. - pub fn has_max_stack_size(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasMaxStackSize", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Gets the max_stack_size. This is the maximum amount which an item will - /// stack. - pub fn max_stack_size(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) +} +impl<'mc> Into> for SkullMeta<'mc> { + fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { + crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) + .expect("Error converting SkullMeta into crate::inventory::meta::ItemMeta") } - /// Sets the max_stack_size. This is the maximum amount which an item will - /// stack. - pub fn set_max_stack_size(&self, max: i32) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/Integer;)V"); - let val_1 = jni::objects::JValueGen::Object(self.jni_ref().new_object( - "java/lang/Integer", - "(Ljava/Lang/Object;)V", - vec![max.into()], - )?); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaxStackSize", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +} +#[repr(C)] +pub struct PotionMeta<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PotionMeta<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Gets if the rarity is set. - pub fn has_rarity(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasRarity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Gets the item rarity. - /// Plugins should check {@link #hasRarity()} before calling this method. - pub fn rarity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemRarity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getRarity", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemRarity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} +impl<'mc> JNIInstantiatable<'mc> for PotionMeta<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate PotionMeta from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/PotionMeta")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PotionMeta object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } - /// Sets the item rarity. - pub fn set_rarity( +} + +impl<'mc> PotionMeta<'mc> { + #[deprecated] + /// Sets the underlying potion data + pub fn set_base_potion_data( &self, - rarity: impl Into>, + data: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemRarity;)V"); + let sig = String::from("(Lorg/bukkit/potion/PotionData;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(rarity.into().jni_object().clone()) + jni::objects::JObject::from_raw(data.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setRarity", + "setBasePotionData", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if the food is set. - pub fn has_food(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasFood", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the food set on this item, or creates an empty food instance. - /// - /// The returned component is a snapshot of its current state and does not - /// reflect a live view of what is on an item. After changing any value on - /// this component, it must be set with {@link #setFood(FoodComponent)} to - /// apply the changes. - pub fn food( + #[deprecated] + /// Returns the potion data about the base potion + pub fn base_potion_data( &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/components/FoodComponent;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFood", sig.as_str(), vec![]); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/potion/PotionData;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBasePotionData", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::components::FoodComponent::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::potion::PotionData::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the item food. - pub fn set_food( + /// Sets the underlying potion type + pub fn set_base_potion_type( &self, - food: impl Into>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/components/FoodComponent;)V"); + let sig = String::from("(Lorg/bukkit/potion/PotionType;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(food.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setFood", + "setBasePotionType", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if the tool is set. - pub fn has_tool(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasTool", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the tool set on this item, or creates an empty tool instance. - /// - /// The returned component is a snapshot of its current state and does not - /// reflect a live view of what is on an item. After changing any value on - /// this component, it must be set with {@link #setTool(ToolComponent)} to - /// apply the changes. - pub fn tool( + /// Returns the potion type about the base potion + pub fn base_potion_type( &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/components/ToolComponent;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/potion/PotionType;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBasePotionType", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::components::ToolComponent::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::potion::PotionType::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the item tool. - pub fn set_tool( - &self, - tool: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tool.into().jni_object().clone()) - }); + /// Checks for the presence of a base potion type + pub fn has_base_potion_type(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "setTool", + "hasBasePotionType", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Checks for the existence of any AttributeModifiers. - pub fn has_attribute_modifiers(&self) -> Result> { + /// Checks for the presence of custom potion effects. + pub fn has_custom_effects(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "hasAttributeModifiers", + "hasCustomEffects", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Return an immutable copy of all {@link AttributeModifier}s - /// for a given {@link Attribute} - pub fn get_attribute_modifiers( + /// Gets an immutable list containing all custom potion effects applied to + /// this potion. + /// + /// Plugins should check that hasCustomEffects() returns true before calling + /// this method. + pub fn custom_effects( &self, - attribute: impl Into>, - ) -> Result>>, Box> - { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/attribute/Attribute;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Ljava/util/Collection;"; + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getAttributeModifiers", + "getCustomEffects", sig.as_str(), - args, + vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::attribute::AttributeModifier::from_raw( - &self.jni_ref(), - obj, - )?); + new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); } - Ok(Some(new_vec)) + Ok(new_vec) } - /// Add an Attribute and it's Modifier. - /// AttributeModifiers can now support {@link EquipmentSlot}s. - /// If not set, the {@link AttributeModifier} will be active in ALL slots. - /// - /// Two {@link AttributeModifier}s that have the same {@link java.util.UUID} - /// cannot exist on the same Attribute. - pub fn add_attribute_modifier( + /// Adds a custom potion effect to this potion. + pub fn add_custom_effect( &self, - attribute: impl Into>, - modifier: impl Into>, + effect: impl Into>, + overwrite: bool, ) -> Result> { - let sig = String::from( - "(Lorg/bukkit/attribute/Attribute;Lorg/bukkit/attribute/AttributeModifier;)Z", - ); + let sig = String::from("(Lorg/bukkit/potion/PotionEffect;Z)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(modifier.into().jni_object().clone()) + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Bool(overwrite.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "addAttributeModifier", + "addCustomEffect", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), @@ -17504,251 +19619,102 @@ impl<'mc> TropicalFishBucketMeta<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set all {@link Attribute}s and their {@link AttributeModifier}s. - /// To clear all currently set Attributes and AttributeModifiers use - /// null or an empty Multimap. - /// If not null nor empty, this will filter all entries that are not-null - /// and add them to the ItemStack. - pub fn set_attribute_modifiers( - &self, - attribute_modifiers: jni::objects::JObject<'mc>, - ) -> Result<(), Box> { - let sig = String::from("(Lcom/google/common/collect/Multimap;)V"); - let val_1 = jni::objects::JValueGen::Object(attribute_modifiers); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAttributeModifiers", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Remove a specific {@link Attribute} and {@link AttributeModifier}. - /// AttributeModifiers are matched according to their {@link java.util.UUID}. - pub fn remove_attribute_modifier( + /// Removes a custom potion effect from this potion. + pub fn remove_custom_effect( &self, - attribute: impl Into>, - modifier: std::option::Option>>, + val_type: impl Into>, ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/attribute/Attribute;"; + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); - args.push(val_1); - if let Some(a) = modifier { - sig += "Lorg/bukkit/attribute/AttributeModifier;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Z"; let res = self.jni_ref().call_method( &self.jni_object(), - "removeAttributeModifier", + "removeCustomEffect", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get this ItemMeta as an NBT string. If this ItemMeta does not have any - /// NBT, then {@code "{}"} will be returned. - /// - /// This string should NEVER be relied upon as a serializable value. If - /// serialization is desired, the {@link ConfigurationSerializable} API should be used - /// instead. - pub fn as_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAsString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Get this ItemMeta as a component-compliant string. If this ItemMeta does - /// not contain any components, then {@code "[]"} will be returned. - /// - /// The result of this method should yield a string representing the components - /// altered by this ItemMeta instance. When passed to {@link ItemFactory#createItemStack(String)} - /// with a prepended item type, it will create an ItemStack that has an ItemMeta - /// matching this ItemMeta instance exactly. Note that this method returns - /// ONLY the components and cannot be passed to createItemStack() alone. - /// An example may look something like this: - ///
-    /// ItemStack itemStack = // ... an item stack obtained from somewhere
-    /// ItemMeta itemMeta = itemStack.getItemMeta();
-    /// String components = itemMeta.getAsComponentString(); // example: "[minecraft:damage=53]"
-    /// String itemTypeKey = itemStack.getType().getKey().toString(); // example: "minecraft:diamond_sword"
-    /// String itemAsString = itemTypeKey + components; // results in: "minecraft:diamond_sword[minecraft:damage=53]"
-    /// ItemStack recreatedItemStack = Bukkit.getItemFactory().createItemStack(itemAsString);
-    /// assert itemStack.isSimilar(recreatedItemStack); // Should be true*
-    /// 
- /// - /// *Components not represented or explicitly overridden by this ItemMeta instance - /// will not be included in the resulting string and therefore may result in ItemStacks - /// that do not match exactly. For example, if {@link #setDisplayName(String)} - /// is not set, then the custom name component will not be included. Or if this ItemMeta - /// is a PotionMeta, it will not include any components related to lodestone compasses, - /// banners, or books, etc., only components modifiable by a PotionMeta instance. - /// - /// This string should NEVER be relied upon as a serializable value. If - /// serialization is desired, the {@link ConfigurationSerializable} API should be used - /// instead. - pub fn as_component_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Checks for a specific custom potion effect type on this potion. + pub fn has_custom_effect( + &self, + val_type: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getAsComponentString", + "hasCustomEffect", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } #[deprecated] - /// Returns a public custom tag container capable of storing tags on the item. Those tags will be sent to the client with all of their content, so the client is capable of reading them. This will result in the player seeing a NBT Tag notification on the item. These tags can also be modified by the client once in creative mode - pub fn custom_tag_container( + /// Moves a potion effect to the top of the potion effect list.This causes the client to display the potion effect in the potion's name. + pub fn set_main_effect( &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/tags/CustomItemTagContainer;"); + val_type: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getCustomTagContainer", + "setMainEffect", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::tags::CustomItemTagContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Internal use only! Do not use under any circumstances! - pub fn set_version(&self, version: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(version); + /// Removes all custom potion effects from this potion. + pub fn clear_custom_effects(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "setVersion", + "clearCustomEffects", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Creates a Map representation of this class. - /// - /// This class must provide a method to restore this class, as defined in - /// the {@link ConfigurationSerializable} interface javadocs. - pub fn serialize( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); + /// Checks for existence of a potion color. + pub fn has_color(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPersistentDataContainer", - sig.as_str(), - args, - ); + .call_method(&self.jni_object(), "hasColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for TropicalFishBucketMeta<'mc> { - fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { - crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) - .expect("Error converting TropicalFishBucketMeta into crate::inventory::meta::ItemMeta") - } -} -#[repr(C)] -pub struct LeatherArmorMeta<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for LeatherArmorMeta<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for LeatherArmorMeta<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate LeatherArmorMeta from null object.").into(), - ); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/inventory/meta/LeatherArmorMeta")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a LeatherArmorMeta object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + Ok(res.z()?) } -} - -impl<'mc> LeatherArmorMeta<'mc> { - /// Gets the color of the armor. If it has not been set otherwise, it will - /// be {@link ItemFactory#getDefaultLeatherColor()}. - pub fn color(&self) -> Result, Box> { + /// Gets the potion color that is set. A custom potion color will alter the + /// display of the potion in an inventory slot. + /// + /// Plugins should check that hasColor() returns true before + /// calling this method. + pub fn color(&self) -> Result>, Box> { let sig = String::from("()Lorg/bukkit/Color;"); let res = self .jni_ref() .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Color::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Color::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) + })?)) } - /// Sets the color of the armor. + /// Sets the potion color. A custom potion color will alter the display of + /// the potion in an inventory slot. pub fn set_color( &self, color: impl Into>, @@ -17769,13 +19735,13 @@ impl<'mc> LeatherArmorMeta<'mc> { pub fn clone( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/LeatherArmorMeta;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/PotionMeta;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::LeatherArmorMeta::from_raw(&self.jni_ref(), unsafe { + crate::inventory::meta::PotionMeta::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -18532,6 +20498,68 @@ impl<'mc> LeatherArmorMeta<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( + &self, + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) + } + /// Sets the item tool. + pub fn set_jukebox_playable( + &self, + jukebox_playable: impl Into>, + ) -> Result<(), Box> { + let sig = + String::from("(Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setJukeboxPlayable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } /// Checks for the existence of any AttributeModifiers. pub fn has_attribute_modifiers(&self) -> Result> { let sig = String::from("()Z"); @@ -18730,89 +20758,52 @@ impl<'mc> LeatherArmorMeta<'mc> { /// Returns a public custom tag container capable of storing tags on the item. Those tags will be sent to the client with all of their content, so the client is capable of reading them. This will result in the player seeing a NBT Tag notification on the item. These tags can also be modified by the client once in creative mode pub fn custom_tag_container( &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/tags/CustomItemTagContainer;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCustomTagContainer", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::tags::CustomItemTagContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Internal use only! Do not use under any circumstances! - pub fn set_version(&self, version: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(version); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setVersion", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Creates a Map representation of this class. - /// - /// This class must provide a method to restore this class, as defined in - /// the {@link ConfigurationSerializable} interface javadocs. - pub fn serialize( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/tags/CustomItemTagContainer;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "getCustomTagContainer", sig.as_str(), - args, + vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + crate::inventory::meta::tags::CustomItemTagContainer::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } + /// Internal use only! Do not use under any circumstances! + pub fn set_version(&self, version: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(version); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVersion", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for LeatherArmorMeta<'mc> { +impl<'mc> Into> for PotionMeta<'mc> { fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) - .expect("Error converting LeatherArmorMeta into crate::inventory::meta::ItemMeta") + .expect("Error converting PotionMeta into crate::inventory::meta::ItemMeta") } } #[repr(C)] -pub struct SkullMeta<'mc>( +pub struct ItemMeta<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for SkullMeta<'mc> { +impl<'mc> JNIRaw<'mc> for ItemMeta<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -18820,18 +20811,18 @@ impl<'mc> JNIRaw<'mc> for SkullMeta<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for SkullMeta<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ItemMeta<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate SkullMeta from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate ItemMeta from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/SkullMeta")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/ItemMeta")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SkullMeta object, got {}", + "Invalid argument passed. Expected a ItemMeta object, got {}", name ) .into()) @@ -18841,186 +20832,7 @@ impl<'mc> JNIInstantiatable<'mc> for SkullMeta<'mc> { } } -impl<'mc> SkullMeta<'mc> { - #[deprecated] - /// Gets the owner of the skull. - pub fn owner(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getOwner", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// Checks to see if the skull has an owner. - pub fn has_owner(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasOwner", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Sets the owner of the skull. - pub fn set_owner(&self, owner: impl Into) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(owner.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setOwner", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the owner of the skull. - pub fn owning_player( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/OfflinePlayer;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getOwningPlayer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::OfflinePlayer::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Sets the owner of the skull. - /// - /// Plugins should check that hasOwner() returns true before calling this - /// plugin. - pub fn set_owning_player( - &self, - owner: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/OfflinePlayer;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owner.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setOwningPlayer", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the profile of the player who owns the skull. This player profile - /// may appear as the texture depending on skull type. - pub fn owner_profile( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/profile/PlayerProfile;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getOwnerProfile", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::profile::PlayerProfile::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Sets the profile of the player who owns the skull. This player profile - /// may appear as the texture depending on skull type. - /// - /// The profile must contain both a unique id and a skin texture. If either - /// of these is missing, the profile must contain a name by which the server - /// will then attempt to look up the unique id and skin texture. - pub fn set_owner_profile( - &self, - profile: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/profile/PlayerProfile;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(profile.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setOwnerProfile", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Sets the sound to play if the skull is placed on a note block. - /// - /// Note: This only works for player heads. For other heads, - /// see {@link org.bukkit.Instrument}. - pub fn set_note_block_sound( - &self, - note_block_sound: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(note_block_sound.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setNoteBlockSound", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the sound to play if the skull is placed on a note block. - /// - /// Note: This only works for player heads. For other heads, - /// see {@link org.bukkit.Instrument}. - pub fn note_block_sound( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getNoteBlockSound", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::NamespacedKey::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - - pub fn clone( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/SkullMeta;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::SkullMeta::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } +impl<'mc> ItemMeta<'mc> { /// Checks for existence of a display name. pub fn has_display_name(&self) -> Result> { let sig = String::from("()Z"); @@ -19757,17 +21569,79 @@ impl<'mc> SkullMeta<'mc> { }) } /// Sets the item tool. - pub fn set_tool( + pub fn set_tool( + &self, + tool: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(tool.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTool", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( + &self, + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) + } + /// Sets the item tool. + pub fn set_jukebox_playable( &self, - tool: impl Into>, + jukebox_playable: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); + let sig = + String::from("(Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tool.into().jni_object().clone()) + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setTool", + "setJukeboxPlayable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -19999,6 +21873,19 @@ impl<'mc> SkullMeta<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } + + pub fn clone( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/ItemMeta;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } /// Creates a Map representation of this class. /// /// This class must provide a method to restore this class, as defined in @@ -20042,323 +21929,129 @@ impl<'mc> SkullMeta<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for SkullMeta<'mc> { - fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { - crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SkullMeta into crate::inventory::meta::ItemMeta") +impl<'mc> Into> + for ItemMeta<'mc> +{ + fn into(self) -> crate::configuration::serialization::ConfigurationSerializable<'mc> { + crate::configuration::serialization::ConfigurationSerializable::from_raw(&self.jni_ref(), self.1).expect("Error converting ItemMeta into crate::configuration::serialization::ConfigurationSerializable") + } +} +impl<'mc> Into> for ItemMeta<'mc> { + fn into(self) -> crate::persistence::PersistentDataHolder<'mc> { + crate::persistence::PersistentDataHolder::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ItemMeta into crate::persistence::PersistentDataHolder") } } #[repr(C)] -pub struct PotionMeta<'mc>( +pub struct BundleMeta<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PotionMeta<'mc> { +impl<'mc> JNIRaw<'mc> for BundleMeta<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PotionMeta<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate PotionMeta from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/PotionMeta")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PotionMeta object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> PotionMeta<'mc> { - #[deprecated] - /// Sets the underlying potion data - pub fn set_base_potion_data( - &self, - data: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/potion/PotionData;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setBasePotionData", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Returns the potion data about the base potion - pub fn base_potion_data( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/potion/PotionData;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getBasePotionData", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::potion::PotionData::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Sets the underlying potion type - pub fn set_base_potion_type( - &self, - val_type: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/potion/PotionType;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setBasePotionType", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns the potion type about the base potion - pub fn base_potion_type( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/potion/PotionType;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getBasePotionType", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::potion::PotionType::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Checks for the presence of a base potion type - pub fn has_base_potion_type(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasBasePotionType", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Checks for the presence of custom potion effects. - pub fn has_custom_effects(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasCustomEffects", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets an immutable list containing all custom potion effects applied to - /// this potion. - /// - /// Plugins should check that hasCustomEffects() returns true before calling - /// this method. - pub fn custom_effects( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCustomEffects", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::potion::PotionEffect::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Adds a custom potion effect to this potion. - pub fn add_custom_effect( - &self, - effect: impl Into>, - overwrite: bool, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffect;Z)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(effect.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Bool(overwrite.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addCustomEffect", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Removes a custom potion effect from this potion. - pub fn remove_custom_effect( - &self, - val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removeCustomEffect", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Checks for a specific custom potion effect type on this potion. - pub fn has_custom_effect( - &self, - val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasCustomEffect", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Moves a potion effect to the top of the potion effect list.This causes the client to display the potion effect in the potion's name. - pub fn set_main_effect( - &self, - val_type: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMainEffect", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Removes all custom potion effects from this potion. - pub fn clear_custom_effects(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "clearCustomEffects", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} +impl<'mc> JNIInstantiatable<'mc> for BundleMeta<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate BundleMeta from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/BundleMeta")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BundleMeta object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } - /// Checks for existence of a potion color. - pub fn has_color(&self) -> Result> { +} + +impl<'mc> BundleMeta<'mc> { + /// Returns whether the item has any items. + pub fn has_items(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "hasColor", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasItems", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the potion color that is set. A custom potion color will alter the - /// display of the potion in an inventory slot. - /// - /// Plugins should check that hasColor() returns true before - /// calling this method. - pub fn color(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Color;"); + /// Returns an immutable list of the items stored in this item. + pub fn items( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItems", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::inventory::ItemStack::from_raw(&self.jni_ref(), obj)?); } - Ok(Some(crate::Color::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(new_vec) } - /// Sets the potion color. A custom potion color will alter the display of - /// the potion in an inventory slot. - pub fn set_color( + /// Sets the items stored in this item. + /// + /// Removes all items when given null. + pub fn set_items( &self, - color: impl Into>, + items: Vec>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Color;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) - }); + let sig = String::from("(Ljava/util/List;)V"); + let raw_val_1 = self + .jni_ref() + .new_object("java/util/ArrayList", "()V", vec![])?; + for v in items { + let map_val_0 = jni::objects::JValueGen::Object(v); + self.jni_ref().call_method( + &raw_val_1, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_1 = jni::objects::JValueGen::Object(raw_val_1); let res = self.jni_ref().call_method( &self.jni_object(), - "setColor", + "setItems", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn clone( + /// Adds an item to this item. + pub fn add_item( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/PotionMeta;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::PotionMeta::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } /// Checks for existence of a display name. pub fn has_display_name(&self) -> Result> { @@ -21113,6 +22806,68 @@ impl<'mc> PotionMeta<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( + &self, + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) + } + /// Sets the item tool. + pub fn set_jukebox_playable( + &self, + jukebox_playable: impl Into>, + ) -> Result<(), Box> { + let sig = + String::from("(Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setJukeboxPlayable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } /// Checks for the existence of any AttributeModifiers. pub fn has_attribute_modifiers(&self) -> Result> { let sig = String::from("()Z"); @@ -21338,6 +23093,19 @@ impl<'mc> PotionMeta<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } + + pub fn clone( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/ItemMeta;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } /// Creates a Map representation of this class. /// /// This class must provide a method to restore this class, as defined in @@ -21381,19 +23149,19 @@ impl<'mc> PotionMeta<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PotionMeta<'mc> { +impl<'mc> Into> for BundleMeta<'mc> { fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PotionMeta into crate::inventory::meta::ItemMeta") + .expect("Error converting BundleMeta into crate::inventory::meta::ItemMeta") } } #[repr(C)] -pub struct BundleMeta<'mc>( +pub struct WritableBookMeta<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BundleMeta<'mc> { +impl<'mc> JNIRaw<'mc> for WritableBookMeta<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -21401,18 +23169,21 @@ impl<'mc> JNIRaw<'mc> for BundleMeta<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BundleMeta<'mc> { +impl<'mc> JNIInstantiatable<'mc> for WritableBookMeta<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate BundleMeta from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate WritableBookMeta from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/BundleMeta")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/inventory/meta/WritableBookMeta")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BundleMeta object, got {}", + "Invalid argument passed. Expected a WritableBookMeta object, got {}", name ) .into()) @@ -21422,82 +23193,140 @@ impl<'mc> JNIInstantiatable<'mc> for BundleMeta<'mc> { } } -impl<'mc> BundleMeta<'mc> { - /// Returns whether the item has any items. - pub fn has_items(&self) -> Result> { +impl<'mc> WritableBookMeta<'mc> { + /// Checks for the existence of pages in the book. + pub fn has_pages(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "hasItems", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasPages", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Returns an immutable list of the items stored in this item. - pub fn items( - &self, - ) -> Result>, Box> { + /// Gets the specified page in the book. The given page must exist. + /// + /// Pages are 1-indexed. + pub fn get_page(&self, page: i32) -> Result> { + let sig = String::from("(I)Ljava/lang/String;"); + let val_1 = jni::objects::JValueGen::Int(page); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPage", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the specified page in the book. Pages of the book must be + /// contiguous. + /// + /// The data can be up to 1024 characters in length, additional characters + /// are truncated. + /// + /// Pages are 1-indexed. + pub fn set_page( + &self, + page: i32, + data: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(ILjava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Int(page); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(data.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPage", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets all the pages in the book. + pub fn pages(&self) -> Result, Box> { let sig = String::from("()Ljava/util/List;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getItems", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPages", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::inventory::ItemStack::from_raw(&self.jni_ref(), obj)?); + new_vec.push( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); } Ok(new_vec) } - /// Sets the items stored in this item. - /// - /// Removes all items when given null. - pub fn set_items( - &self, - items: Vec>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/List;)V"); - let raw_val_1 = self + /// Clears the existing book pages, and sets the book to use the provided + /// pages. Maximum 100 pages with 1024 characters per page. + pub fn set_pages(&self, pages: impl Into) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(pages.into())?, + )); + args.push(val_1); + sig += ")V"; + let res = self .jni_ref() - .new_object("java/util/ArrayList", "()V", vec![])?; - for v in items { - let map_val_0 = jni::objects::JValueGen::Object(v); - self.jni_ref().call_method( - &raw_val_1, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_1 = jni::objects::JValueGen::Object(raw_val_1); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setItems", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "setPages", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Adds an item to this item. - pub fn add_item( - &self, - item: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); + /// Adds new pages to the end of the book. Up to a maximum of 100 pages with + /// 1024 characters per page. + pub fn add_page(&self, pages: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(pages.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "addItem", + "addPage", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } + /// Gets the number of pages in the book. + pub fn page_count(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPageCount", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + + pub fn clone( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/WritableBookMeta;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::WritableBookMeta::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } /// Checks for existence of a display name. pub fn has_display_name(&self) -> Result> { let sig = String::from("()Z"); @@ -22251,6 +24080,68 @@ impl<'mc> BundleMeta<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( + &self, + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) + } + /// Sets the item tool. + pub fn set_jukebox_playable( + &self, + jukebox_playable: impl Into>, + ) -> Result<(), Box> { + let sig = + String::from("(Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setJukeboxPlayable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } /// Checks for the existence of any AttributeModifiers. pub fn has_attribute_modifiers(&self) -> Result> { let sig = String::from("()Z"); @@ -22476,19 +24367,6 @@ impl<'mc> BundleMeta<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn clone( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/ItemMeta;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } /// Creates a Map representation of this class. /// /// This class must provide a method to restore this class, as defined in @@ -22532,181 +24410,96 @@ impl<'mc> BundleMeta<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BundleMeta<'mc> { +impl<'mc> Into> for WritableBookMeta<'mc> { fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BundleMeta into crate::inventory::meta::ItemMeta") + .expect("Error converting WritableBookMeta into crate::inventory::meta::ItemMeta") } } #[repr(C)] -pub struct WritableBookMeta<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for WritableBookMeta<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for WritableBookMeta<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate WritableBookMeta from null object.").into(), - ); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/inventory/meta/WritableBookMeta")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a WritableBookMeta object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> WritableBookMeta<'mc> { - /// Checks for the existence of pages in the book. - pub fn has_pages(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasPages", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the specified page in the book. The given page must exist. - /// - /// Pages are 1-indexed. - pub fn get_page(&self, page: i32) -> Result> { - let sig = String::from("(I)Ljava/lang/String;"); - let val_1 = jni::objects::JValueGen::Int(page); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPage", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Sets the specified page in the book. Pages of the book must be - /// contiguous. - /// - /// The data can be up to 1024 characters in length, additional characters - /// are truncated. - /// - /// Pages are 1-indexed. - pub fn set_page( - &self, - page: i32, - data: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(ILjava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Int(page); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(data.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPage", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +pub struct MusicInstrumentMeta<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for MusicInstrumentMeta<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Gets all the pages in the book. - pub fn pages(&self) -> Result, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPages", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for MusicInstrumentMeta<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate MusicInstrumentMeta from null object.").into(), ); } - Ok(new_vec) - } - /// Clears the existing book pages, and sets the book to use the provided - /// pages. Maximum 100 pages with 1024 characters per page. - pub fn set_pages(&self, pages: impl Into) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(pages.into())?, - )); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setPages", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + let (valid, name) = + env.validate_name(&obj, "org/bukkit/inventory/meta/MusicInstrumentMeta")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a MusicInstrumentMeta object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } - /// Adds new pages to the end of the book. Up to a maximum of 100 pages with - /// 1024 characters per page. - pub fn add_page(&self, pages: impl Into) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(pages.into())?, - )); +} + +impl<'mc> MusicInstrumentMeta<'mc> { + /// Sets the goat horn's instrument. + pub fn set_instrument( + &self, + instrument: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/MusicInstrument;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(instrument.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "addPage", + "setInstrument", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the number of pages in the book. - pub fn page_count(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the instrument of the goat horn. + pub fn instrument( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/MusicInstrument;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPageCount", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getInstrument", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::MusicInstrument::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } pub fn clone( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/WritableBookMeta;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/MusicInstrumentMeta;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::WritableBookMeta::from_raw(&self.jni_ref(), unsafe { + crate::inventory::meta::MusicInstrumentMeta::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -23463,6 +25256,68 @@ impl<'mc> WritableBookMeta<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( + &self, + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) + } + /// Sets the item tool. + pub fn set_jukebox_playable( + &self, + jukebox_playable: impl Into>, + ) -> Result<(), Box> { + let sig = + String::from("(Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setJukeboxPlayable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } /// Checks for the existence of any AttributeModifiers. pub fn has_attribute_modifiers(&self) -> Result> { let sig = String::from("()Z"); @@ -23731,19 +25586,19 @@ impl<'mc> WritableBookMeta<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for WritableBookMeta<'mc> { +impl<'mc> Into> for MusicInstrumentMeta<'mc> { fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) - .expect("Error converting WritableBookMeta into crate::inventory::meta::ItemMeta") + .expect("Error converting MusicInstrumentMeta into crate::inventory::meta::ItemMeta") } } #[repr(C)] -pub struct MusicInstrumentMeta<'mc>( +pub struct ArmorMeta<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for MusicInstrumentMeta<'mc> { +impl<'mc> JNIRaw<'mc> for ArmorMeta<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -23751,21 +25606,18 @@ impl<'mc> JNIRaw<'mc> for MusicInstrumentMeta<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for MusicInstrumentMeta<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ArmorMeta<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate MusicInstrumentMeta from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate ArmorMeta from null object.").into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/inventory/meta/MusicInstrumentMeta")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/ArmorMeta")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a MusicInstrumentMeta object, got {}", + "Invalid argument passed. Expected a ArmorMeta object, got {}", name ) .into()) @@ -23775,38 +25627,48 @@ impl<'mc> JNIInstantiatable<'mc> for MusicInstrumentMeta<'mc> { } } -impl<'mc> MusicInstrumentMeta<'mc> { - /// Sets the goat horn's instrument. - pub fn set_instrument( +impl<'mc> ArmorMeta<'mc> { + /// Check whether or not this item has an armor trim. + pub fn has_trim(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasTrim", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set the {@link ArmorTrim}. + pub fn set_trim( &self, - instrument: impl Into>, + trim: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/MusicInstrument;)V"); + let sig = String::from("(Lorg/bukkit/inventory/meta/trim/ArmorTrim;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(instrument.into().jni_object().clone()) + jni::objects::JObject::from_raw(trim.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setInstrument", + "setTrim", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the instrument of the goat horn. - pub fn instrument( + /// Get the {@link ArmorTrim}. + pub fn trim( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/MusicInstrument;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInstrument", sig.as_str(), vec![]); + ) -> Result>, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/trim/ArmorTrim;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTrim", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::MusicInstrument::from_raw( + Ok(Some(crate::inventory::meta::trim::ArmorTrim::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) @@ -23814,13 +25676,13 @@ impl<'mc> MusicInstrumentMeta<'mc> { pub fn clone( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/MusicInstrumentMeta;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/ArmorMeta;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::MusicInstrumentMeta::from_raw(&self.jni_ref(), unsafe { + crate::inventory::meta::ArmorMeta::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -24548,29 +26410,91 @@ impl<'mc> MusicInstrumentMeta<'mc> { /// apply the changes. pub fn tool( &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/components/ToolComponent;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/ToolComponent;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTool", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::meta::components::ToolComponent::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the item tool. + pub fn set_tool( + &self, + tool: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(tool.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTool", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( + &self, + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::components::ToolComponent::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) } /// Sets the item tool. - pub fn set_tool( + pub fn set_jukebox_playable( &self, - tool: impl Into>, + jukebox_playable: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); + let sig = + String::from("(Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tool.into().jni_object().clone()) + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setTool", + "setJukeboxPlayable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -24845,19 +26769,19 @@ impl<'mc> MusicInstrumentMeta<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for MusicInstrumentMeta<'mc> { +impl<'mc> Into> for ArmorMeta<'mc> { fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) - .expect("Error converting MusicInstrumentMeta into crate::inventory::meta::ItemMeta") + .expect("Error converting ArmorMeta into crate::inventory::meta::ItemMeta") } } #[repr(C)] -pub struct ArmorMeta<'mc>( +pub struct ShieldMeta<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ArmorMeta<'mc> { +impl<'mc> JNIRaw<'mc> for ShieldMeta<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -24865,18 +26789,18 @@ impl<'mc> JNIRaw<'mc> for ArmorMeta<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ArmorMeta<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ShieldMeta<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ArmorMeta from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate ShieldMeta from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/ArmorMeta")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/meta/ShieldMeta")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ArmorMeta object, got {}", + "Invalid argument passed. Expected a ShieldMeta object, got {}", name ) .into()) @@ -24886,65 +26810,183 @@ impl<'mc> JNIInstantiatable<'mc> for ArmorMeta<'mc> { } } -impl<'mc> ArmorMeta<'mc> { - /// Check whether or not this item has an armor trim. - pub fn has_trim(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasTrim", sig.as_str(), vec![]); +impl<'mc> ShieldMeta<'mc> { + /// Gets the base color for this shield. + pub fn base_color(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/DyeColor;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBaseColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::DyeColor::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Set the {@link ArmorTrim}. - pub fn set_trim( + /// Sets the base color for this shield. + /// + /// Note: If the shield contains a + /// {@link org.bukkit.block.banner.Pattern}, then a null base color will + /// retain the pattern but default the base color to {@link DyeColor#WHITE}. + pub fn set_base_color( &self, - trim: impl Into>, + color: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/trim/ArmorTrim;)V"); + let sig = String::from("(Lorg/bukkit/DyeColor;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(trim.into().jni_object().clone()) + jni::objects::JObject::from_raw(color.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setTrim", + "setBaseColor", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the {@link ArmorTrim}. - pub fn trim( + /// Returns a list of patterns on this banner + pub fn patterns( &self, - ) -> Result>, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/meta/trim/ArmorTrim;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTrim", sig.as_str(), vec![]); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPatterns", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::banner::Pattern::from_raw( + &self.jni_ref(), + obj, + )?); } - Ok(Some(crate::inventory::meta::trim::ArmorTrim::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(new_vec) } - - pub fn clone( + /// Sets the patterns used on this banner + pub fn set_patterns( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/ArmorMeta;"); - let res = self + patterns: Vec>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/List;)V"); + let raw_val_1 = self .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + .new_object("java/util/ArrayList", "()V", vec![])?; + for v in patterns { + let map_val_0 = jni::objects::JValueGen::Object(v); + self.jni_ref().call_method( + &raw_val_1, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_1 = jni::objects::JValueGen::Object(raw_val_1); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPatterns", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Adds a new pattern on top of the existing + /// patterns + pub fn add_pattern( + &self, + pattern: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/banner/Pattern;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(pattern.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addPattern", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the pattern at the specified index + pub fn get_pattern( + &self, + i: i32, + ) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/block/banner/Pattern;"); + let val_1 = jni::objects::JValueGen::Int(i); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPattern", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::meta::ArmorMeta::from_raw(&self.jni_ref(), unsafe { + crate::block::banner::Pattern::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Removes the pattern at the specified index + pub fn remove_pattern( + &self, + i: i32, + ) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/block/banner/Pattern;"); + let val_1 = jni::objects::JValueGen::Int(i); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removePattern", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::block::banner::Pattern::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } + /// Sets the pattern at the specified index + pub fn set_pattern( + &self, + i: i32, + pattern: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(ILorg/bukkit/block/banner/Pattern;)V"); + let val_1 = jni::objects::JValueGen::Int(i); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(pattern.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPattern", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the number of patterns on this + /// banner + pub fn number_of_patterns(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "numberOfPatterns", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } /// Checks for existence of a display name. pub fn has_display_name(&self) -> Result> { let sig = String::from("()Z"); @@ -25683,15 +27725,77 @@ impl<'mc> ArmorMeta<'mc> { /// Sets the item tool. pub fn set_tool( &self, - tool: impl Into>, + tool: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(tool.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTool", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( + &self, + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) + } + /// Sets the item tool. + pub fn set_jukebox_playable( + &self, + jukebox_playable: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/meta/components/ToolComponent;)V"); + let sig = + String::from("(Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tool.into().jni_object().clone()) + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setTool", + "setJukeboxPlayable", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -25923,40 +28027,16 @@ impl<'mc> ArmorMeta<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Creates a Map representation of this class. - /// - /// This class must provide a method to restore this class, as defined in - /// the {@link ConfigurationSerializable} interface javadocs. - pub fn serialize( + + pub fn clone( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/ItemMeta;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPersistentDataContainer", - sig.as_str(), - args, - ); + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -25966,10 +28046,10 @@ impl<'mc> ArmorMeta<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for ArmorMeta<'mc> { - fn into(self) -> crate::inventory::meta::ItemMeta<'mc> { - crate::inventory::meta::ItemMeta::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ArmorMeta into crate::inventory::meta::ItemMeta") +impl<'mc> Into> for ShieldMeta<'mc> { + fn into(self) -> crate::inventory::meta::BannerMeta<'mc> { + crate::inventory::meta::BannerMeta::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ShieldMeta into crate::inventory::meta::BannerMeta") } } #[repr(C)] @@ -26888,6 +28968,75 @@ impl<'mc> ColorableArmorMeta<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( + &self, + ) -> Result< + Option>, + Box, + > { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) + } + /// Sets the item tool. + pub fn set_jukebox_playable( + &self, + jukebox_playable: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "setJukeboxPlayable", + sig.as_str(), + args, + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } /// Checks for the existence of any AttributeModifiers. pub fn has_attribute_modifiers(&self) -> Result> { let args = Vec::new(); @@ -27127,12 +29276,10 @@ impl<'mc> ColorableArmorMeta<'mc> { pub fn serialize( &self, ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/Map;"; + let sig = String::from("()Ljava/util/Map;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), args); + .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) @@ -28139,6 +30286,75 @@ impl<'mc> OminousBottleMeta<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( + &self, + ) -> Result< + Option>, + Box, + > { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) + } + /// Sets the item tool. + pub fn set_jukebox_playable( + &self, + jukebox_playable: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "setJukeboxPlayable", + sig.as_str(), + args, + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } /// Checks for the existence of any AttributeModifiers. pub fn has_attribute_modifiers(&self) -> Result> { let args = Vec::new(); @@ -28385,12 +30601,10 @@ impl<'mc> OminousBottleMeta<'mc> { pub fn serialize( &self, ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/Map;"; + let sig = String::from("()Ljava/util/Map;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), args); + .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) @@ -28539,7 +30753,19 @@ impl<'mc> FireworkMeta<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } + /// Get whether this firework has power set by component. + pub fn has_power(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasPower", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } /// Gets the approximate height the firework will fly. + /// + /// Plugins should check that hasPower() returns true + /// before calling this method. pub fn power(&self) -> Result> { let sig = String::from("()I"); let res = self @@ -29407,6 +31633,75 @@ impl<'mc> FireworkMeta<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( + &self, + ) -> Result< + Option>, + Box, + > { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) + } + /// Sets the item tool. + pub fn set_jukebox_playable( + &self, + jukebox_playable: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "setJukeboxPlayable", + sig.as_str(), + args, + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } /// Checks for the existence of any AttributeModifiers. pub fn has_attribute_modifiers(&self) -> Result> { let args = Vec::new(); @@ -29653,12 +31948,10 @@ impl<'mc> FireworkMeta<'mc> { pub fn serialize( &self, ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/Map;"; + let sig = String::from("()Ljava/util/Map;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), args); + .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) @@ -30776,6 +33069,75 @@ impl<'mc> MapMeta<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } + /// Checks if the jukebox playable is set. + pub fn has_jukebox_playable(&self) -> Result> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Z"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasJukeboxPlayable", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the jukebox playable component set on this item. + /// + /// The returned component is a snapshot of its current state and does not + /// reflect a live view of what is on an item. After changing any value on + /// this component, it must be set with + /// {@link #setJukeboxPlayable(org.bukkit.inventory.meta.components.JukeboxComponent)} + /// to apply the changes. + pub fn jukebox_playable( + &self, + ) -> Result< + Option>, + Box, + > { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getJukeboxPlayable", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::inventory::meta::components::JukeboxPlayableComponent::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?, + )) + } + /// Sets the item tool. + pub fn set_jukebox_playable( + &self, + jukebox_playable: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/meta/components/JukeboxPlayableComponent;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(jukebox_playable.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "setJukeboxPlayable", + sig.as_str(), + args, + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } /// Checks for the existence of any AttributeModifiers. pub fn has_attribute_modifiers(&self) -> Result> { let args = Vec::new(); @@ -31022,12 +33384,10 @@ impl<'mc> MapMeta<'mc> { pub fn serialize( &self, ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/Map;"; + let sig = String::from("()Ljava/util/Map;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), args); + .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) diff --git a/blackboxmc-rs-bukkit/src/inventory/mod.rs b/blackboxmc-rs-bukkit/src/inventory/mod.rs index 79eae50..6821573 100644 --- a/blackboxmc-rs-bukkit/src/inventory/mod.rs +++ b/blackboxmc-rs-bukkit/src/inventory/mod.rs @@ -3,12 +3,12 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] -pub struct JukeboxInventory<'mc>( +pub struct ShapelessRecipe<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for JukeboxInventory<'mc> { +impl<'mc> JNIRaw<'mc> for ShapelessRecipe<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -16,20 +16,20 @@ impl<'mc> JNIRaw<'mc> for JukeboxInventory<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for JukeboxInventory<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ShapelessRecipe<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate JukeboxInventory from null object.").into(), + eyre::eyre!("Tried to instantiate ShapelessRecipe from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/JukeboxInventory")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/ShapelessRecipe")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a JukeboxInventory object, got {}", + "Invalid argument passed. Expected a ShapelessRecipe object, got {}", name ) .into()) @@ -39,507 +39,722 @@ impl<'mc> JNIInstantiatable<'mc> for JukeboxInventory<'mc> { } } -impl<'mc> JukeboxInventory<'mc> { - /// Set the record in the jukebox. - /// - /// This will immediately start playing the inserted item or stop playing if the - /// item provided is null. If the provided item is not a record (according to - /// {@link Tag#ITEMS_MUSIC_DISCS}), this method will do nothing and not set the - /// item in the inventory. - pub fn set_record( - &self, - item: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); +impl<'mc> ShapelessRecipe<'mc> { + /// Create a shapeless recipe to craft the specified ItemStack. The + /// constructor merely determines the result and type; to set the actual + /// recipe, you'll need to call the appropriate methods. + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + key: impl Into>, + result: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/NamespacedKey;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(key.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRecord", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + args.push(val_1); + if let Some(a) = result { + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/inventory/ShapelessRecipe"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::inventory::ShapelessRecipe::from_raw(&jni, res) } - /// Get the record in the jukebox. - pub fn record( + #[deprecated] + /// Adds multiples of the specified ingredient. + pub fn add_ingredient( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getRecord", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + count: i32, + ingredient: std::option::Option>>, + rawdata: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(count); + args.push(val_1); + if let Some(a) = ingredient { + sig += "Lorg/bukkit/Material;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - - pub fn holder(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/block/Jukebox;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHolder", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + if let Some(a) = rawdata { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); } - Ok(Some(crate::block::Jukebox::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Returns the size of the inventory - pub fn size(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); + sig += ")Lorg/bukkit/inventory/ShapelessRecipe;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "addIngredient", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::inventory::ShapelessRecipe::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the maximum stack size for an ItemStack in this inventory. - pub fn max_stack_size(&self) -> Result> { - let sig = String::from("()I"); + #[deprecated] + /// Removes an ingredient from the list. If the ingredient occurs multiple times, only one instance of it is removed. If the data value is -1, only ingredients with a -1 data value will be removed. + pub fn remove_ingredient( + &self, + ingredient: impl Into>, + rawdata: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ingredient.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = rawdata { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + sig += ")Lorg/bukkit/inventory/ShapelessRecipe;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "removeIngredient", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// This method allows you to change the maximum stack size for an - /// inventory. - /// - /// Caveats: - ///
    - ///
  • Not all inventories respect this value. - ///
  • Stacks larger than 127 may be clipped when the world is saved. - ///
  • This value is not guaranteed to be preserved; be sure to set it - /// before every time you want to set a slot over the max stack size. - ///
  • Stacks larger than the default max size for this type of inventory - /// may not display correctly in the client. - ///
- pub fn set_max_stack_size(&self, size: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(size); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaxStackSize", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::inventory::ShapelessRecipe::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the ItemStack found in the slot at the given index - pub fn get_item( + /// Get the list of ingredients used for this recipe. + pub fn ingredient_list( &self, - index: i32, - ) -> Result>, Box> { - let sig = String::from("(I)Lorg/bukkit/inventory/ItemStack;"); - let val_1 = jni::objects::JValueGen::Int(index); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getItem", + "getIngredientList", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::inventory::ItemStack::from_raw(&self.0, obj)?); } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(new_vec) } - /// Stores the ItemStack at the given index of the inventory. - pub fn set_item( + + pub fn choice_list( &self, - index: i32, - item: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(ILorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Int(index); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setItem", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getChoiceList", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::inventory::RecipeChoice::from_raw(&self.0, obj)?); + } + Ok(new_vec) } - /// Stores the given ItemStacks in the inventory. This will try to fill - /// existing stacks and empty slots as well as it can. - /// - /// The returned HashMap contains what it couldn't store, where the key is - /// the index of the parameter, and the value is the ItemStack at that - /// index of the varargs parameter. If all items are stored, it will return - /// an empty HashMap. - /// - /// If you pass in ItemStacks which exceed the maximum stack size for the - /// Material, first they will be added to partial stacks where - /// Material.getMaxStackSize() is not exceeded, up to - /// Material.getMaxStackSize(). When there are no partial stacks left - /// stacks will be split on Inventory.getMaxStackSize() allowing you to - /// exceed the maximum stack size for that material. - /// - /// It is known that in some implementations this method will also set - /// the inputted argument amount to the number of that item not placed in - /// slots. - pub fn add_item( + // SUPER CLASS: org.bukkit.inventory.CraftingRecipe ( ['addIngredient', 'removeIngredient', 'getIngredientList', 'getChoiceList']) + + pub fn key(&self) -> Result, Box> { + let temp_clone = crate::inventory::CraftingRecipe::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::inventory::CraftingRecipe = temp_clone.into(); + real.key() + } + /// Get the result of this recipe. + pub fn result(&self) -> Result, Box> { + let temp_clone = crate::inventory::CraftingRecipe::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::inventory::CraftingRecipe = temp_clone.into(); + real.result() + } + /// Get the group of this recipe. Recipes with the same group may be grouped + /// together when displayed in the client. + pub fn group(&self) -> Result> { + let temp_clone = crate::inventory::CraftingRecipe::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::inventory::CraftingRecipe = temp_clone.into(); + real.group() + } + /// Set the group of this recipe. Recipes with the same group may be grouped + /// together when displayed in the client. + pub fn set_group(&self, group: impl Into) -> Result<(), Box> { + let temp_clone = crate::inventory::CraftingRecipe::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::inventory::CraftingRecipe = temp_clone.into(); + real.set_group(group) + } + /// Gets the category which this recipe will appear in the recipe book under. + /// + /// Defaults to {@link CraftingBookCategory#MISC} if not set. + pub fn category( &self, - items: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/HashMap;"); + ) -> Result, Box> + { + let temp_clone = crate::inventory::CraftingRecipe::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::inventory::CraftingRecipe = temp_clone.into(); + real.category() + } + /// Sets the category which this recipe will appear in the recipe book under. + /// + /// Defaults to {@link CraftingBookCategory#MISC} if not set. + pub fn set_category( + &self, + category: impl Into>, + ) -> Result<(), Box> { + let temp_clone = crate::inventory::CraftingRecipe::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::inventory::CraftingRecipe = temp_clone.into(); + real.set_category(category) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for ShapelessRecipe<'mc> { + fn into(self) -> crate::inventory::CraftingRecipe<'mc> { + crate::inventory::CraftingRecipe::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ShapelessRecipe into crate::inventory::CraftingRecipe") + } +} +#[repr(C)] +pub struct ShapedRecipe<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ShapedRecipe<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for ShapedRecipe<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate ShapedRecipe from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/ShapedRecipe")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ShapedRecipe object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> ShapedRecipe<'mc> { + /// Create a shaped recipe to craft the specified ItemStack. The + /// constructor merely determines the result and type; to set the actual + /// recipe, you'll need to call the appropriate methods. + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + key: impl Into>, + result: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/NamespacedKey;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) + jni::objects::JObject::from_raw(key.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addItem", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + if let Some(a) = result { + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/inventory/ShapedRecipe"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::inventory::ShapedRecipe::from_raw(&jni, res) + } + /// Set the shape of this recipe to the specified rows. Each character + /// represents a different ingredient; excluding space characters, which + /// must be empty, exactly what each character represents is set separately. + /// The first row supplied corresponds with the upper most part of the recipe + /// on the workbench e.g. if all three rows are supplies the first string + /// represents the top row on the workbench. + pub fn shape( + &self, + shape: std::option::Option>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = shape { + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_1); + } + sig += ")Lorg/bukkit/inventory/ShapedRecipe;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "shape", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { + crate::inventory::ShapedRecipe::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Removes the given ItemStacks from the inventory. - /// - /// It will try to remove 'as much as possible' from the types and amounts - /// you give as arguments. - /// - /// The returned HashMap contains what it couldn't remove, where the key is - /// the index of the parameter, and the value is the ItemStack at that - /// index of the varargs parameter. If all the given ItemStacks are - /// removed, it will return an empty HashMap. - /// - /// It is known that in some implementations this method will also set the - /// inputted argument amount to the number of that item not removed from - /// slots. - pub fn remove_item( + #[deprecated] + /// Sets the material that a character in the recipe shape refers to.Note that before an ingredient can be set, the recipe's shape must be defined with {@link #shape(String...)}. + pub fn set_ingredient( &self, - items: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/HashMap;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) + key: u16, + ingredient: impl Into>, + raw: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "C"; + let val_1 = jni::objects::JValueGen::Char(key); + args.push(val_1); + sig += "Lorg/bukkit/Material;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ingredient.into().jni_object().clone()) }); + args.push(val_2); + if let Some(a) = raw { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + sig += ")Lorg/bukkit/inventory/ShapedRecipe;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setIngredient", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ShapedRecipe::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get a copy of the ingredients map. + pub fn ingredient_map( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Map;"); let res = self.jni_ref().call_method( &self.jni_object(), - "removeItem", + "getIngredientMap", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns all ItemStacks from the inventory - pub fn contents(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + /// Get a copy of the choice map. + pub fn choice_map( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Map;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getContents", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getChoiceMap", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Completely replaces the inventory's contents. Removes all existing - /// contents and replaces it with the ItemStacks given in the array. - pub fn set_contents( + /// Set the shape of this recipe to the specified rows. Each character + /// represents a different ingredient; excluding space characters, which + /// must be empty, exactly what each character represents is set separately. + /// The first row supplied corresponds with the upper most part of the recipe + /// on the workbench e.g. if all three rows are supplies the first string + /// represents the top row on the workbench. + pub fn shape_with_shape( &self, - items: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setContents", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + shape: std::option::Option>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = shape { + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_1); + } + sig += ")Lorg/bukkit/inventory/ShapedRecipe;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getShape", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ShapedRecipe::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Return the contents from the section of the inventory where items can - /// reasonably be expected to be stored. In most cases this will represent - /// the entire inventory, but in some cases it may exclude armor or result - /// slots. + // SUPER CLASS: org.bukkit.inventory.CraftingRecipe ( ['shape', 'setIngredient', 'getIngredientMap', 'getChoiceMap', 'getShape']) + + pub fn key(&self) -> Result, Box> { + let temp_clone = crate::inventory::CraftingRecipe::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::inventory::CraftingRecipe = temp_clone.into(); + real.key() + } + /// Get the result of this recipe. + pub fn result(&self) -> Result, Box> { + let temp_clone = crate::inventory::CraftingRecipe::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::inventory::CraftingRecipe = temp_clone.into(); + real.result() + } + /// Get the group of this recipe. Recipes with the same group may be grouped + /// together when displayed in the client. + pub fn group(&self) -> Result> { + let temp_clone = crate::inventory::CraftingRecipe::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::inventory::CraftingRecipe = temp_clone.into(); + real.group() + } + /// Set the group of this recipe. Recipes with the same group may be grouped + /// together when displayed in the client. + pub fn set_group(&self, group: impl Into) -> Result<(), Box> { + let temp_clone = crate::inventory::CraftingRecipe::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::inventory::CraftingRecipe = temp_clone.into(); + real.set_group(group) + } + /// Gets the category which this recipe will appear in the recipe book under. /// - /// It is these contents which will be used for add / contains / remove - /// methods which look for a specific stack. - pub fn storage_contents( + /// Defaults to {@link CraftingBookCategory#MISC} if not set. + pub fn category( + &self, + ) -> Result, Box> + { + let temp_clone = crate::inventory::CraftingRecipe::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::inventory::CraftingRecipe = temp_clone.into(); + real.category() + } + /// Sets the category which this recipe will appear in the recipe book under. + /// + /// Defaults to {@link CraftingBookCategory#MISC} if not set. + pub fn set_category( + &self, + category: impl Into>, + ) -> Result<(), Box> { + let temp_clone = crate::inventory::CraftingRecipe::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::inventory::CraftingRecipe = temp_clone.into(); + real.set_category(category) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for ShapedRecipe<'mc> { + fn into(self) -> crate::inventory::CraftingRecipe<'mc> { + crate::inventory::CraftingRecipe::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ShapedRecipe into crate::inventory::CraftingRecipe") + } +} +#[repr(C)] +pub struct RecipeChoice<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for RecipeChoice<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for RecipeChoice<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate RecipeChoice from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/RecipeChoice")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a RecipeChoice object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> RecipeChoice<'mc> { + #[deprecated] + /// Gets a single item stack representative of this stack choice. + pub fn item_stack( &self, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getStorageContents", - sig.as_str(), - vec![], - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemStack", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Put the given ItemStacks into the storage slots - pub fn set_storage_contents( - &self, - items: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setStorageContents", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks if the inventory contains any ItemStacks with the given - /// material, adding to at least the minimum amount specified. - pub fn contains( - &self, - material: impl Into>, - amount: std::option::Option, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = amount { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - sig += ")Z"; + + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/RecipeChoice;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "contains", sig.as_str(), args); + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::RecipeChoice::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Checks if the inventory contains ItemStacks matching the given - /// ItemStack whose amounts sum to at least the minimum amount specified. - pub fn contains_at_least( + + pub fn test( &self, - item: impl Into>, - amount: i32, + item_stack: impl Into>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;I)Z"); + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "containsAtLeast", + "test", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Finds all slots in the inventory containing any ItemStacks with the - /// given ItemStack. This will only match slots if both the type and the - /// amount of the stack match - /// - /// The HashMap contains entries where, the key is the slot index, and the - /// value is the ItemStack in that slot. If no matching ItemStack with the - /// given Material is found, an empty map is returned. - pub fn all( - &self, - item: impl Into>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Ljava/util/HashMap;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "all", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Returns the first slot in the inventory containing an ItemStack with - /// the given stack. This will only match a slot if both the type and the - /// amount of the stack match - pub fn first( - &self, - item: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")I"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "first", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) +} +impl<'mc> Into> for RecipeChoice<'mc> { + fn into(self) -> blackboxmc_java::util::function::JavaPredicate<'mc> { + blackboxmc_java::util::function::JavaPredicate::from_raw(&self.jni_ref(), self.1).expect( + "Error converting RecipeChoice into blackboxmc_java::util::function::JavaPredicate", + ) } - /// Returns the first empty Slot. - pub fn first_empty(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "firstEmpty", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) +} +#[repr(C)] +pub struct RecipeChoiceMaterialChoice<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for RecipeChoiceMaterialChoice<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Check whether or not this inventory is empty. An inventory is considered - /// to be empty if there are no ItemStacks in any slot of this inventory. - pub fn is_empty(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Removes all stacks in the inventory matching the given stack. - /// - /// This will only match a slot if both the type and the amount of the - /// stack match - pub fn remove( - &self, - item: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) +} +impl<'mc> JNIInstantiatable<'mc> for RecipeChoiceMaterialChoice<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate RecipeChoiceMaterialChoice from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/inventory/RecipeChoice/MaterialChoice")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a RecipeChoiceMaterialChoice object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } - /// Clears out a particular slot in the index. - pub fn clear(&self, index: std::option::Option) -> Result<(), Box> { +} + +impl<'mc> RecipeChoiceMaterialChoice<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + choices: Vec>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = index { - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(a); - args.push(val_1); + sig += "Ljava/util/List;"; + let raw_val_1 = jni.new_object("java/util/ArrayList", "()V", vec![])?; + for v in choices { + sig += "Ljava/lang/java/lang/Object;"; + let map_val_0 = jni::objects::JValueGen::Object(v); + jni.call_method( + &raw_val_1, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; } + let val_1 = jni::objects::JValueGen::Object(raw_val_1); + args.push(val_1); sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clear", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + let cls = jni.find_class("org/bukkit/inventory/RecipeChoice/MaterialChoice"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::inventory::RecipeChoiceMaterialChoice::from_raw(&jni, res) } - /// Gets a list of players viewing the inventory. Note that a player is - /// considered to be viewing their own inventory and internal crafting - /// screen even when said inventory is not open. They will normally be - /// considered to be viewing their inventory even when they have a - /// different inventory screen open, but it's possible for customized - /// inventory screens to exclude the viewer's inventory, so this should - /// never be assumed to be non-empty. - pub fn viewers( + + pub fn item_stack( &self, - ) -> Result>, Box> { + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemStack", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn choices(&self) -> Result>, Box> { let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getViewers", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getChoices", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::entity::HumanEntity::from_raw(&self.jni_ref(), obj)?); + new_vec.push(crate::Material::from_raw(&self.0, obj)?); } Ok(new_vec) } - /// Returns what type of inventory this is. - pub fn get_type( + + pub fn clone( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/RecipeChoice/MaterialChoice;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::event::inventory::InventoryType::from_raw(&self.jni_ref(), unsafe { + crate::inventory::RecipeChoiceMaterialChoice::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - pub fn iterator( + pub fn hash_code(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + + pub fn equals( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/ListIterator;"); + obj: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(Ljava/lang/Object;)Z"); + let val_1 = jni::objects::JValueGen::Object(obj); + let res = self.jni_ref().call_method( + &self.jni_object(), + "equals", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "iterator", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaListIterator::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Get the location of the block or entity which corresponds to this inventory. May return null if this container - /// was custom created or is a virtual / subcontainer. - pub fn location(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); + + pub fn test( + &self, + item_stack: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "test", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.z()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -547,19 +762,30 @@ impl<'mc> JukeboxInventory<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for JukeboxInventory<'mc> { - fn into(self) -> crate::inventory::Inventory<'mc> { - crate::inventory::Inventory::from_raw(&self.jni_ref(), self.1) - .expect("Error converting JukeboxInventory into crate::inventory::Inventory") + +impl<'mc> std::string::ToString for RecipeChoiceMaterialChoice<'mc> { + fn to_string(&self) -> String { + match &self.internal_to_string() { + Ok(a) => a.clone(), + Err(err) => format!("Error calling RecipeChoiceMaterialChoice.toString: {}", err), + } + } +} + +impl<'mc> Into> for RecipeChoiceMaterialChoice<'mc> { + fn into(self) -> crate::inventory::RecipeChoice<'mc> { + crate::inventory::RecipeChoice::from_raw(&self.jni_ref(), self.1).expect( + "Error converting RecipeChoiceMaterialChoice into crate::inventory::RecipeChoice", + ) } } #[repr(C)] -pub struct CrafterInventory<'mc>( +pub struct RecipeChoiceExactChoice<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for CrafterInventory<'mc> { +impl<'mc> JNIRaw<'mc> for RecipeChoiceExactChoice<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -567,20 +793,22 @@ impl<'mc> JNIRaw<'mc> for CrafterInventory<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for CrafterInventory<'mc> { +impl<'mc> JNIInstantiatable<'mc> for RecipeChoiceExactChoice<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate CrafterInventory from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate RecipeChoiceExactChoice from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/CrafterInventory")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/inventory/RecipeChoice/ExactChoice")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a CrafterInventory object, got {}", + "Invalid argument passed. Expected a RecipeChoiceExactChoice object, got {}", name ) .into()) @@ -590,469 +818,557 @@ impl<'mc> JNIInstantiatable<'mc> for CrafterInventory<'mc> { } } -impl<'mc> CrafterInventory<'mc> { - /// Returns the size of the inventory - pub fn size(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) +impl<'mc> RecipeChoiceExactChoice<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + choices: Vec>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/util/List;"; + let raw_val_1 = jni.new_object("java/util/ArrayList", "()V", vec![])?; + for v in choices { + sig += "Ljava/lang/java/lang/Object;"; + let map_val_0 = jni::objects::JValueGen::Object(v); + jni.call_method( + &raw_val_1, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_1 = jni::objects::JValueGen::Object(raw_val_1); + args.push(val_1); + sig += ")V"; + let cls = jni.find_class("org/bukkit/inventory/RecipeChoice/ExactChoice"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::inventory::RecipeChoiceExactChoice::from_raw(&jni, res) } - /// Returns the maximum stack size for an ItemStack in this inventory. - pub fn max_stack_size(&self) -> Result> { - let sig = String::from("()I"); + + pub fn item_stack( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItemStack", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// This method allows you to change the maximum stack size for an - /// inventory. - /// - /// Caveats: - ///
    - ///
  • Not all inventories respect this value. - ///
  • Stacks larger than 127 may be clipped when the world is saved. - ///
  • This value is not guaranteed to be preserved; be sure to set it - /// before every time you want to set a slot over the max stack size. - ///
  • Stacks larger than the default max size for this type of inventory - /// may not display correctly in the client. - ///
- pub fn set_max_stack_size(&self, size: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(size); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaxStackSize", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the ItemStack found in the slot at the given index - pub fn get_item( + + pub fn choices( &self, - index: i32, - ) -> Result>, Box> { - let sig = String::from("(I)Lorg/bukkit/inventory/ItemStack;"); - let val_1 = jni::objects::JValueGen::Int(index); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getItem", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getChoices", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::inventory::ItemStack::from_raw(&self.0, obj)?); } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(new_vec) } - /// Stores the ItemStack at the given index of the inventory. - pub fn set_item( + + pub fn clone( &self, - index: i32, - item: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(ILorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Int(index); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setItem", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/RecipeChoice/ExactChoice;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::RecipeChoiceExactChoice::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Stores the given ItemStacks in the inventory. This will try to fill - /// existing stacks and empty slots as well as it can. - /// - /// The returned HashMap contains what it couldn't store, where the key is - /// the index of the parameter, and the value is the ItemStack at that - /// index of the varargs parameter. If all items are stored, it will return - /// an empty HashMap. - /// - /// If you pass in ItemStacks which exceed the maximum stack size for the - /// Material, first they will be added to partial stacks where - /// Material.getMaxStackSize() is not exceeded, up to - /// Material.getMaxStackSize(). When there are no partial stacks left - /// stacks will be split on Inventory.getMaxStackSize() allowing you to - /// exceed the maximum stack size for that material. - /// - /// It is known that in some implementations this method will also set - /// the inputted argument amount to the number of that item not placed in - /// slots. - pub fn add_item( + + pub fn hash_code(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + + pub fn equals( &self, - items: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/HashMap;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) - }); + obj: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(Ljava/lang/Object;)Z"); + let val_1 = jni::objects::JValueGen::Object(obj); let res = self.jni_ref().call_method( &self.jni_object(), - "addItem", + "equals", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Removes the given ItemStacks from the inventory. - /// - /// It will try to remove 'as much as possible' from the types and amounts - /// you give as arguments. - /// - /// The returned HashMap contains what it couldn't remove, where the key is - /// the index of the parameter, and the value is the ItemStack at that - /// index of the varargs parameter. If all the given ItemStacks are - /// removed, it will return an empty HashMap. - /// - /// It is known that in some implementations this method will also set the - /// inputted argument amount to the number of that item not removed from - /// slots. - pub fn remove_item( + + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + + pub fn test( &self, - items: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/HashMap;"); + item_stack: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeItem", + "test", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns all ItemStacks from the inventory - pub fn contents(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getContents", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Completely replaces the inventory's contents. Removes all existing - /// contents and replaces it with the ItemStacks given in the array. - pub fn set_contents( + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} + +impl<'mc> std::string::ToString for RecipeChoiceExactChoice<'mc> { + fn to_string(&self) -> String { + match &self.internal_to_string() { + Ok(a) => a.clone(), + Err(err) => format!("Error calling RecipeChoiceExactChoice.toString: {}", err), + } + } +} + +impl<'mc> Into> for RecipeChoiceExactChoice<'mc> { + fn into(self) -> crate::inventory::RecipeChoice<'mc> { + crate::inventory::RecipeChoice::from_raw(&self.jni_ref(), self.1) + .expect("Error converting RecipeChoiceExactChoice into crate::inventory::RecipeChoice") + } +} +#[repr(C)] +pub struct MerchantRecipe<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for MerchantRecipe<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for MerchantRecipe<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate MerchantRecipe from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/MerchantRecipe")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a MerchantRecipe object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> MerchantRecipe<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + result: impl Into>, + uses: i32, + max_uses: std::option::Option, + experience_reward: std::option::Option, + villager_experience: std::option::Option, + price_multiplier: std::option::Option, + demand: std::option::Option, + special_price: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(result.into().jni_object().clone()) + }); + args.push(val_1); + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(uses); + args.push(val_2); + if let Some(a) = max_uses { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + if let Some(a) = experience_reward { + sig += "Z"; + let val_4 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_4); + } + if let Some(a) = villager_experience { + sig += "I"; + let val_5 = jni::objects::JValueGen::Int(a); + args.push(val_5); + } + if let Some(a) = price_multiplier { + sig += "F"; + let val_6 = jni::objects::JValueGen::Float(a); + args.push(val_6); + } + if let Some(a) = demand { + sig += "I"; + let val_7 = jni::objects::JValueGen::Int(a); + args.push(val_7); + } + if let Some(a) = special_price { + sig += "I"; + let val_8 = jni::objects::JValueGen::Int(a); + args.push(val_8); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/inventory/MerchantRecipe"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::inventory::MerchantRecipe::from_raw(&jni, res) + } + + pub fn result(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getResult", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn add_ingredient( &self, - items: impl Into>, + item: impl Into>, ) -> Result<(), Box> { let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) + jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setContents", + "addIngredient", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Return the contents from the section of the inventory where items can - /// reasonably be expected to be stored. In most cases this will represent - /// the entire inventory, but in some cases it may exclude armor or result - /// slots. - /// - /// It is these contents which will be used for add / contains / remove - /// methods which look for a specific stack. - pub fn storage_contents( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + + pub fn remove_ingredient(&self, index: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(index); let res = self.jni_ref().call_method( &self.jni_object(), - "getStorageContents", + "removeIngredient", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Put the given ItemStacks into the storage slots - pub fn set_storage_contents( + + pub fn set_ingredients( &self, - items: impl Into>, + ingredients: Vec>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) - }); + let sig = String::from("(Ljava/util/List;)V"); + let raw_val_1 = self + .jni_ref() + .new_object("java/util/ArrayList", "()V", vec![])?; + for v in ingredients { + let map_val_0 = jni::objects::JValueGen::Object(v); + self.jni_ref().call_method( + &raw_val_1, + "add", + "(Ljava/lang/Object;)Z", + vec![jni::objects::JValueGen::from(map_val_0)], + )?; + } + let val_1 = jni::objects::JValueGen::Object(raw_val_1); let res = self.jni_ref().call_method( &self.jni_object(), - "setStorageContents", + "setIngredients", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if the inventory contains any ItemStacks with the given - /// material, adding to at least the minimum amount specified. - pub fn contains( + + pub fn ingredients( &self, - material: impl Into>, - amount: std::option::Option, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = amount { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "contains", sig.as_str(), args); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getIngredients", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::inventory::ItemStack::from_raw(&self.0, obj)?); + } + Ok(new_vec) } - /// Checks if the inventory contains ItemStacks matching the given - /// ItemStack whose amounts sum to at least the minimum amount specified. - pub fn contains_at_least( + /// Gets the {@link #adjust(ItemStack) adjusted} first ingredient. + pub fn adjusted_ingredient1( &self, - item: impl Into>, - amount: i32, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;I)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(amount); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self.jni_ref().call_method( &self.jni_object(), - "containsAtLeast", + "getAdjustedIngredient1", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Finds all slots in the inventory containing any ItemStacks with the - /// given ItemStack. This will only match slots if both the type and the - /// amount of the stack match - /// - /// The HashMap contains entries where, the key is the slot index, and the - /// value is the ItemStack in that slot. If no matching ItemStack with the - /// given Material is found, an empty map is returned. - pub fn all( - &self, - item: impl Into>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Ljava/util/HashMap;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "all", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Returns the first slot in the inventory containing an ItemStack with - /// the given stack. This will only match a slot if both the type and the - /// amount of the stack match - pub fn first( + /// Modifies the amount of the given {@link ItemStack} in the same way as + /// MerchantRecipe dynamically adjusts the amount of the first ingredient + /// during trading. + /// + /// This is calculated by adding up the original amount of the item, the + /// demand scaled by the recipe's + /// {@link #getPriceMultiplier price multiplier} and truncated to the next + /// lowest integer value greater than or equal to 0, and the special price, + /// and then constraining the resulting value between 1 and the + /// {@link ItemStack}'s {@link ItemStack#getMaxStackSize() + /// maximum stack size}. + pub fn adjust( &self, - item: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; + item_stack: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) }); - args.push(val_1); - sig += ")I"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "adjust", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the demand for this trade. + pub fn demand(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "first", sig.as_str(), args); + .call_method(&self.jni_object(), "getDemand", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Returns the first empty Slot. - pub fn first_empty(&self) -> Result> { + /// Set the demand for this trade. + pub fn set_demand(&self, demand: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(demand); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDemand", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the special price for this trade. + pub fn special_price(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "firstEmpty", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSpecialPrice", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Check whether or not this inventory is empty. An inventory is considered - /// to be empty if there are no ItemStacks in any slot of this inventory. - pub fn is_empty(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Removes all stacks in the inventory matching the given stack. - /// - /// This will only match a slot if both the type and the amount of the - /// stack match - pub fn remove( - &self, - item: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), args); + /// Set the special price for this trade. + pub fn set_special_price(&self, special_price: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(special_price); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSpecialPrice", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Clears out a particular slot in the index. - pub fn clear(&self, index: std::option::Option) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = index { - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(a); - args.push(val_1); - } - sig += ")V"; + /// Get the number of times this trade has been used. + pub fn uses(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "clear", sig.as_str(), args); + .call_method(&self.jni_object(), "getUses", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the number of times this trade has been used. + pub fn set_uses(&self, uses: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(uses); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setUses", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets a list of players viewing the inventory. Note that a player is - /// considered to be viewing their own inventory and internal crafting - /// screen even when said inventory is not open. They will normally be - /// considered to be viewing their inventory even when they have a - /// different inventory screen open, but it's possible for customized - /// inventory screens to exclude the viewer's inventory, so this should - /// never be assumed to be non-empty. - pub fn viewers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + /// Get the maximum number of uses this trade has. + pub fn max_uses(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getViewers", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxUses", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::HumanEntity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(res.i()?) } - /// Returns what type of inventory this is. - pub fn get_type( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::inventory::InventoryType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Set the maximum number of uses this trade has. + pub fn set_max_uses(&self, max_uses: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(max_uses); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaxUses", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the block or entity belonging to the open inventory - pub fn holder( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/InventoryHolder;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHolder", sig.as_str(), vec![]); + /// Whether to reward experience to the player for the trade. + pub fn has_experience_reward(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasExperienceReward", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::InventoryHolder::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - - pub fn iterator( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/ListIterator;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "iterator", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaListIterator::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Set whether to reward experience to the player for the trade. + pub fn set_experience_reward(&self, flag: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(flag.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setExperienceReward", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the location of the block or entity which corresponds to this inventory. May return null if this container - /// was custom created or is a virtual / subcontainer. - pub fn location(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); + /// Gets the amount of experience the villager earns from this trade. + pub fn villager_experience(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getVillagerExperience", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.i()?) + } + /// Sets the amount of experience the villager earns from this trade. + pub fn set_villager_experience( + &self, + villager_experience: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(villager_experience); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVillagerExperience", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the price multiplier for the cost of this trade. + pub fn price_multiplier(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPriceMultiplier", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the price multiplier for the cost of this trade. + pub fn set_price_multiplier( + &self, + price_multiplier: f32, + ) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(price_multiplier); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPriceMultiplier", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1060,19 +1376,19 @@ impl<'mc> CrafterInventory<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for CrafterInventory<'mc> { - fn into(self) -> crate::inventory::Inventory<'mc> { - crate::inventory::Inventory::from_raw(&self.jni_ref(), self.1) - .expect("Error converting CrafterInventory into crate::inventory::Inventory") +impl<'mc> Into> for MerchantRecipe<'mc> { + fn into(self) -> crate::inventory::Recipe<'mc> { + crate::inventory::Recipe::from_raw(&self.jni_ref(), self.1) + .expect("Error converting MerchantRecipe into crate::inventory::Recipe") } } #[repr(C)] -pub struct InventoryView<'mc>( +pub struct ItemStack<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for InventoryView<'mc> { +impl<'mc> JNIRaw<'mc> for ItemStack<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1080,18 +1396,18 @@ impl<'mc> JNIRaw<'mc> for InventoryView<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for InventoryView<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ItemStack<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate InventoryView from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate ItemStack from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/InventoryView")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/ItemStack")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a InventoryView object, got {}", + "Invalid argument passed. Expected a ItemStack object, got {}", name ) .into()) @@ -1101,302 +1417,556 @@ impl<'mc> JNIInstantiatable<'mc> for InventoryView<'mc> { } } -impl<'mc> InventoryView<'mc> { +impl<'mc> ItemStack<'mc> { + #[deprecated] + pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/inventory/InventoryView"); + val_type: impl Into>, + amount: std::option::Option, + damage: std::option::Option, + data: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = amount { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + if let Some(a) = damage { + sig += "S"; + let val_3 = jni::objects::JValueGen::Short(a); + args.push(val_3); + } + if let Some(a) = data { + sig += "Ljava/lang/Byte;"; + let val_4 = jni::objects::JValueGen::Object(jni.new_object( + "java/lang/Byte", + "(Ljava/Lang/Object;)V", + vec![a.into()], + )?); + args.push(val_4); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/inventory/ItemStack"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), vec![]); + let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::inventory::InventoryView::from_raw(&jni, res) + crate::inventory::ItemStack::from_raw(&jni, res) } - /// Sets one item in this inventory view by its raw slot ID. + /// Gets the type of this item + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the type of this item /// - /// Note: If slot ID -999 is chosen, it may be expected that the item is - /// dropped on the ground. This is not required behaviour, however. - pub fn set_item( + /// Note that in doing so you will reset the MaterialData for this stack. + /// + /// IMPORTANT: An ItemStack is only designed to contain + /// items. Do not use this class to encapsulate Materials for which + /// {@link Material#isItem()} returns false. + pub fn set_type( &self, - slot: i32, - item: impl Into>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(ILorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Int(slot); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + let sig = String::from("(Lorg/bukkit/Material;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setItem", + "setType", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets one item in this inventory view by its raw slot ID. - pub fn get_item( - &self, - slot: i32, - ) -> Result>, Box> { - let sig = String::from("(I)Lorg/bukkit/inventory/ItemStack;"); - let val_1 = jni::objects::JValueGen::Int(slot); + /// Gets the amount of items in this stack + pub fn amount(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getAmount", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the amount of items in this stack + pub fn set_amount(&self, amount: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "getItem", + "setAmount", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the MaterialData for this stack of items + pub fn data( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/material/MaterialData;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::ItemStack::from_raw( + Ok(Some(crate::material::MaterialData::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets the item on the cursor of one of the viewing players. - pub fn set_cursor( + /// Sets the MaterialData for this stack of items + pub fn set_data( &self, - item: impl Into>, + data: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let sig = String::from("(Lorg/bukkit/material/MaterialData;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(data.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setCursor", + "setData", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the item on the cursor of one of the viewing players. - pub fn cursor( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getCursor", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Gets the inventory corresponding to the given raw slot ID. - /// If the slot ID is {@link #OUTSIDE} null will be returned, otherwise - /// behaviour for illegal and negative slot IDs is undefined. - /// May be used with {@link #convertSlot(int)} to directly index an - /// underlying inventory. - pub fn get_inventory( - &self, - raw_slot: i32, - ) -> Result>, Box> { - let sig = String::from("(I)Lorg/bukkit/inventory/Inventory;"); - let val_1 = jni::objects::JValueGen::Int(raw_slot); + #[deprecated] + /// Sets the durability of this item + pub fn set_durability(&self, durability: i16) -> Result<(), Box> { + let sig = String::from("(S)V"); + let val_1 = jni::objects::JValueGen::Short(durability); let res = self.jni_ref().call_method( &self.jni_object(), - "getInventory", + "setDurability", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::Inventory::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Converts a raw slot ID into its local slot ID into whichever of the two - /// inventories the slot points to. - /// - /// If the raw slot refers to the upper inventory, it will be returned - /// unchanged and thus be suitable for getTopInventory().getItem(); if it - /// refers to the lower inventory, the output will differ from the input - /// and be suitable for getBottomInventory().getItem(). - pub fn convert_slot(&self, raw_slot: i32) -> Result> { - let sig = String::from("(I)I"); - let val_1 = jni::objects::JValueGen::Int(raw_slot); + #[deprecated] + /// Gets the durability of this item + pub fn durability(&self) -> Result> { + let sig = String::from("()S"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDurability", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.s()?) + } + /// Get the maximum stack size for this item. If this item has a max stack + /// size component ({@link ItemMeta#hasMaxStackSize()}), the value of that + /// component will be returned. Otherwise, this item's Material's {@link + /// Material#getMaxStackSize() default maximum stack size} will be returned + /// instead. + pub fn max_stack_size(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + + pub fn equals( + &self, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(Ljava/lang/Object;)Z"); + let val_1 = jni::objects::JValueGen::Object(obj); let res = self.jni_ref().call_method( &self.jni_object(), - "convertSlot", + "equals", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Determine the type of the slot by its raw slot ID. - /// - /// If the type of the slot is unknown, then - /// {@link InventoryType.SlotType#CONTAINER} will be returned. - pub fn get_slot_type( + /// This method is the same as equals, but does not consider stack size + /// (amount). + pub fn is_similar( &self, - slot: i32, - ) -> Result, Box> - { - let sig = String::from("(I)Lorg/bukkit/event/inventory/InventoryType/SlotType;"); - let val_1 = jni::objects::JValueGen::Int(slot); + stack: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(stack.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getSlotType", + "isSimilar", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::event::inventory::InventoryTypeSlotType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Closes the inventory view. - pub fn close(&self) -> Result<(), Box> { - let sig = String::from("()V"); + + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "close", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Check the total number of slots in this view, combining the upper and - /// lower inventories. - /// - /// Note though that it's possible for this to be greater than the sum of - /// the two inventories if for example some slots are not being used. - pub fn count_slots(&self) -> Result> { + + pub fn hash_code(&self) -> Result> { let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "countSlots", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets an extra property of this inventory if supported by that - /// inventory, for example the state of a progress bar. - pub fn set_property( + /// Checks if this ItemStack contains the given {@link Enchantment} + pub fn contains_enchantment( &self, - prop: impl Into>, - value: i32, + ench: impl Into>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/InventoryView/Property;I)Z"); + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(prop.into().jni_object().clone()) + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(value); let res = self.jni_ref().call_method( &self.jni_object(), - "setProperty", + "containsEnchantment", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + /// Gets the level of the specified enchantment on this item stack + pub fn get_enchantment_level( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)I"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getEnchantmentLevel", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} -pub enum InventoryViewProperty<'mc> {} -impl<'mc> std::fmt::Display for InventoryViewProperty<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + /// Gets a map containing all enchantments and their levels on this item. + pub fn enchantments( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Map;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEnchantments", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} - -impl<'mc> InventoryViewProperty<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/inventory/InventoryView/Property"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/inventory/InventoryView/Property;", + /// Adds the specified enchantments to this item stack. + /// + /// This method is the same as calling {@link + /// #addEnchantment(org.bukkit.enchantments.Enchantment, int)} for each + /// element of the map. + pub fn add_enchantments( + &self, + enchantments: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/Map;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(enchantments.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addEnchantments", + sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct InventoryViewPropertyStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for InventoryViewProperty<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + self.jni_ref().translate_error(res)?; + Ok(()) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + /// Adds the specified {@link Enchantment} to this item stack. + /// + /// If this item stack already contained the given enchantment (at any + /// level), it will be replaced. + pub fn add_enchantment( + &self, + ench: impl Into>, + level: i32, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;I)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(level); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addEnchantment", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -impl<'mc> JNIInstantiatable<'mc> for InventoryViewProperty<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate InventoryViewProperty from null object." - ) - .into()); + /// Adds the specified enchantments to this item stack in an unsafe manner. + /// + /// This method is the same as calling {@link + /// #addUnsafeEnchantment(org.bukkit.enchantments.Enchantment, int)} for + /// each element of the map. + pub fn add_unsafe_enchantments( + &self, + enchantments: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/Map;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(enchantments.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addUnsafeEnchantments", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Adds the specified {@link Enchantment} to this item stack. + /// + /// If this item stack already contained the given enchantment (at any + /// level), it will be replaced. + /// + /// This method is unsafe and will ignore level restrictions or item type. + /// Use at your own discretion. + pub fn add_unsafe_enchantment( + &self, + ench: impl Into>, + level: i32, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;I)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(level); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addUnsafeEnchantment", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Removes the specified {@link Enchantment} if it exists on this + /// ItemStack + pub fn remove_enchantment( + &self, + ench: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)I"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeEnchantment", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Removes all enchantments on this ItemStack. + pub fn remove_enchantments(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeEnchantments", + sig.as_str(), + vec![], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn serialize( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Map;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Required method for configuration serialization + pub fn deserialize( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + val_args: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Ljava/util/Map;)Lorg/bukkit/inventory/ItemStack;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_args.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/inventory/ItemStack"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "deserialize", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::inventory::ItemStack::from_raw(&jni, obj) + } + /// Get a copy of this ItemStack's {@link ItemMeta}. + pub fn item_meta( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/meta/ItemMeta;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemMeta", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/inventory/InventoryView/Property")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a InventoryViewProperty object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + Ok(Some(crate::inventory::meta::ItemMeta::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Checks to see if any meta data has been defined. + pub fn has_item_meta(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasItemMeta", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set the ItemMeta of this ItemStack. + pub fn set_item_meta( + &self, + item_meta: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/meta/ItemMeta;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item_meta.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItemMeta", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn translation_key(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTranslationKey", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} + +impl<'mc> std::string::ToString for ItemStack<'mc> { + fn to_string(&self) -> String { + match &self.internal_to_string() { + Ok(a) => a.clone(), + Err(err) => format!("Error calling ItemStack.toString: {}", err), } } } -impl<'mc> JNIRaw<'mc> for InventoryViewPropertyStruct<'mc> { +impl<'mc> Into> + for ItemStack<'mc> +{ + fn into(self) -> crate::configuration::serialization::ConfigurationSerializable<'mc> { + crate::configuration::serialization::ConfigurationSerializable::from_raw(&self.jni_ref(), self.1).expect("Error converting ItemStack into crate::configuration::serialization::ConfigurationSerializable") + } +} +impl<'mc> Into> for ItemStack<'mc> { + fn into(self) -> crate::Translatable<'mc> { + crate::Translatable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ItemStack into crate::Translatable") + } +} +#[repr(C)] +pub struct InventoryView<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for InventoryView<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1404,22 +1974,18 @@ impl<'mc> JNIRaw<'mc> for InventoryViewPropertyStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for InventoryViewPropertyStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for InventoryView<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate InventoryViewPropertyStruct from null object." - ) - .into()); + return Err(eyre::eyre!("Tried to instantiate InventoryView from null object.").into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/inventory/InventoryView/Property")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/InventoryView")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a InventoryViewPropertyStruct object, got {}", + "Invalid argument passed. Expected a InventoryView object, got {}", name ) .into()) @@ -1429,349 +1995,278 @@ impl<'mc> JNIInstantiatable<'mc> for InventoryViewPropertyStruct<'mc> { } } -impl<'mc> InventoryViewPropertyStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/InventoryView/Property;"); - let cls = jni.find_class("org/bukkit/inventory/InventoryView/Property"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::inventory::InventoryViewProperty::from_raw(&jni, obj) - } - - pub fn get_type( +impl<'mc> InventoryView<'mc> { + /// Get the upper inventory involved in this transaction. + pub fn top_inventory( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::inventory::InventoryType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - #[deprecated] - /// Gets the id of this view. - pub fn id(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct ItemType<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for ItemType<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for ItemType<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ItemType from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/ItemType")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ItemType object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> ItemType<'mc> { - /// Yields this item type as a typed version of itself with a plain {@link ItemMeta} representing it. - pub fn typed( - &self, - item_meta_type: std::option::Option>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = item_meta_type { - sig += "Ljava/lang/Class;"; - let val_1 = jni::objects::JValueGen::Object(a.into()); - args.push(val_1); - } - sig += ")Lorg/bukkit/inventory/ItemType/Typed;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "typed", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemTypeTyped::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Constructs a new itemstack with this item type. - pub fn create_item_stack( - &self, - amount: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = amount { - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(a); - args.push(val_1); - } - sig += ")Lorg/bukkit/inventory/ItemStack;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "createItemStack", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns true if this ItemType has a corresponding {@link BlockType}. - pub fn has_block_type(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasBlockType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the corresponding {@link BlockType} for the given ItemType. - /// - /// If there is no corresponding {@link BlockType} an error will be thrown. - pub fn block_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockType;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBlockType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTopInventory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockType::from_raw(&self.jni_ref(), unsafe { + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the ItemMeta class of this ItemType - pub fn item_meta_class(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/Class;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getItemMetaClass", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(unsafe { jni::objects::JClass::from_raw(res.as_jni().l) }) - } - /// Gets the maximum amount of this item type that can be held in a stack - pub fn max_stack_size(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the maximum durability of this item type - pub fn max_durability(&self) -> Result> { - let sig = String::from("()S"); + /// Get the lower inventory involved in this transaction. + pub fn bottom_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getMaxDurability", + "getBottomInventory", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.s()?) - } - /// Checks if this item type is edible. - pub fn is_edible(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isEdible", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - - pub fn is_record(&self) -> Result> { - let sig = String::from("()Z"); + /// Get the player viewing. + pub fn player(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isRecord", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::entity::HumanEntity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Checks if this item type can be used as fuel in a Furnace - pub fn is_fuel(&self) -> Result> { - let sig = String::from("()Z"); + /// Determine the type of inventory involved in the transaction. This + /// indicates the window style being shown. It will never return PLAYER, + /// since that is common to all windows. + pub fn get_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isFuel", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Checks whether this item type is compostable (can be inserted into a - /// composter). - pub fn is_compostable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCompostable", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::event::inventory::InventoryType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get the chance that this item type will successfully compost. The - /// returned value is between 0 and 1 (inclusive). - /// Items with a compost chance of 1 will always raise the composter's level, - /// while items with a compost chance of 0 will never raise it. - /// Plugins should check that {@link #isCompostable} returns true before - /// calling this method. - pub fn compost_chance(&self) -> Result> { - let sig = String::from("()F"); + /// Sets one item in this inventory view by its raw slot ID. + /// + /// Note: If slot ID -999 is chosen, it may be expected that the item is + /// dropped on the ground. This is not required behaviour, however. + pub fn set_item( + &self, + slot: i32, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(ILorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Int(slot); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getCompostChance", + "setItem", sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Determines the remaining item in a crafting grid after crafting with this - /// ingredient. - pub fn crafting_remaining_item( + /// Gets one item in this inventory view by its raw slot ID. + pub fn get_item( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemType;"); + slot: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/ItemStack;"); + let val_1 = jni::objects::JValueGen::Int(slot); let res = self.jni_ref().call_method( &self.jni_object(), - "getCraftingRemainingItem", + "getItem", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::ItemType::from_raw( + Ok(Some(crate::inventory::ItemStack::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Return an immutable copy of all default {@link Attribute}s and their - /// {@link AttributeModifier}s for a given {@link EquipmentSlot}. - /// Default attributes are those that are always preset on some items, such - /// as the attack damage on weapons or the armor value on armor. - pub fn get_default_attribute_modifiers( + /// Sets the item on the cursor of one of the viewing players. + pub fn set_cursor( &self, - slot: impl Into>, - ) -> Result, Box> { - let sig = String::from( - "(Lorg/bukkit/inventory/EquipmentSlot;)Lcom/google/common/collect/Multimap;", - ); + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(slot.into().jni_object().clone()) + jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getDefaultAttributeModifiers", + "setCursor", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the item on the cursor of one of the viewing players. + pub fn cursor( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCursor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - #[deprecated] - /// Get the {@link CreativeCategory} to which this item type belongs. - pub fn creative_category( + /// Gets the inventory corresponding to the given raw slot ID. + /// If the slot ID is {@link #OUTSIDE} null will be returned, otherwise + /// behaviour for illegal and negative slot IDs is undefined. + /// May be used with {@link #convertSlot(int)} to directly index an + /// underlying inventory. + pub fn get_inventory( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/CreativeCategory;"); + raw_slot: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/Inventory;"); + let val_1 = jni::objects::JValueGen::Int(raw_slot); let res = self.jni_ref().call_method( &self.jni_object(), - "getCreativeCategory", + "getInventory", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::CreativeCategory::from_raw( + Ok(Some(crate::inventory::Inventory::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Gets if the ItemType is enabled by the features in a world. - pub fn is_enabled_by_feature( + /// Converts a raw slot ID into its local slot ID into whichever of the two + /// inventories the slot points to. + /// + /// If the raw slot refers to the upper inventory, it will be returned + /// unchanged and thus be suitable for getTopInventory().getItem(); if it + /// refers to the lower inventory, the output will differ from the input + /// and be suitable for getBottomInventory().getItem(). + pub fn convert_slot(&self, raw_slot: i32) -> Result> { + let sig = String::from("(I)I"); + let val_1 = jni::objects::JValueGen::Int(raw_slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "convertSlot", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Determine the type of the slot by its raw slot ID. + /// + /// If the type of the slot is unknown, then + /// {@link InventoryType.SlotType#CONTAINER} will be returned. + pub fn get_slot_type( &self, - world: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/World;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); + slot: i32, + ) -> Result, Box> + { + let sig = String::from("(I)Lorg/bukkit/event/inventory/InventoryType/SlotType;"); + let val_1 = jni::objects::JValueGen::Int(slot); let res = self.jni_ref().call_method( &self.jni_object(), - "isEnabledByFeature", + "getSlotType", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::event::inventory::InventoryTypeSlotType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - /// Tries to convert this ItemType into a Material - pub fn as_material(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); + /// Closes the inventory view. + pub fn close(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "close", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Check the total number of slots in this view, combining the upper and + /// lower inventories. + /// + /// Note though that it's possible for this to be greater than the sum of + /// the two inventories if for example some slots are not being used. + pub fn count_slots(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "asMaterial", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "countSlots", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.i()?) } - /// Return the namespaced identifier for this object. - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + /// Sets an extra property of this inventory if supported by that + /// inventory, for example the state of a progress bar. + pub fn set_property( + &self, + prop: impl Into>, + value: i32, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/InventoryView/Property;I)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(prop.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setProperty", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the title of this inventory window. + pub fn title(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTitle", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Get the translation key, suitable for use in a translation component. - pub fn translation_key(&self) -> Result> { + /// Get the original title of this inventory window, before any changes were + /// made using {@link #setTitle(String)}. + pub fn original_title(&self) -> Result> { let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getTranslationKey", + "getOriginalTitle", sig.as_str(), vec![], ); @@ -1782,358 +2277,738 @@ impl<'mc> ItemType<'mc> { .to_string_lossy() .to_string()) } + /// Sets the title of this inventory window to the specified title if the + /// inventory window supports it. + /// + /// Note if the inventory does not support titles that can be changed (ie, it + /// is not creatable or viewed by a player), then this method will throw an + /// exception. + pub fn set_title(&self, title: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(title.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTitle", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for ItemType<'mc> { - fn into(self) -> crate::Keyed<'mc> { - crate::Keyed::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ItemType into crate::Keyed") +pub enum InventoryViewProperty<'mc> { + BrewTime { + inner: InventoryViewPropertyStruct<'mc>, + }, + FuelTime { + inner: InventoryViewPropertyStruct<'mc>, + }, + BurnTime { + inner: InventoryViewPropertyStruct<'mc>, + }, + TicksForCurrentFuel { + inner: InventoryViewPropertyStruct<'mc>, + }, + CookTime { + inner: InventoryViewPropertyStruct<'mc>, + }, + TicksForCurrentSmelting { + inner: InventoryViewPropertyStruct<'mc>, + }, + EnchantButton1 { + inner: InventoryViewPropertyStruct<'mc>, + }, + EnchantButton2 { + inner: InventoryViewPropertyStruct<'mc>, + }, + EnchantButton3 { + inner: InventoryViewPropertyStruct<'mc>, + }, + EnchantXpSeed { + inner: InventoryViewPropertyStruct<'mc>, + }, + EnchantId1 { + inner: InventoryViewPropertyStruct<'mc>, + }, + EnchantId2 { + inner: InventoryViewPropertyStruct<'mc>, + }, + EnchantId3 { + inner: InventoryViewPropertyStruct<'mc>, + }, + EnchantLevel1 { + inner: InventoryViewPropertyStruct<'mc>, + }, + EnchantLevel2 { + inner: InventoryViewPropertyStruct<'mc>, + }, + EnchantLevel3 { + inner: InventoryViewPropertyStruct<'mc>, + }, + Levels { + inner: InventoryViewPropertyStruct<'mc>, + }, + PrimaryEffect { + inner: InventoryViewPropertyStruct<'mc>, + }, + SecondaryEffect { + inner: InventoryViewPropertyStruct<'mc>, + }, + RepairCost { + inner: InventoryViewPropertyStruct<'mc>, + }, + BookPage { + inner: InventoryViewPropertyStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for InventoryViewProperty<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + InventoryViewProperty::BrewTime { .. } => f.write_str("BREW_TIME"), + InventoryViewProperty::FuelTime { .. } => f.write_str("FUEL_TIME"), + InventoryViewProperty::BurnTime { .. } => f.write_str("BURN_TIME"), + InventoryViewProperty::TicksForCurrentFuel { .. } => { + f.write_str("TICKS_FOR_CURRENT_FUEL") + } + InventoryViewProperty::CookTime { .. } => f.write_str("COOK_TIME"), + InventoryViewProperty::TicksForCurrentSmelting { .. } => { + f.write_str("TICKS_FOR_CURRENT_SMELTING") + } + InventoryViewProperty::EnchantButton1 { .. } => f.write_str("ENCHANT_BUTTON1"), + InventoryViewProperty::EnchantButton2 { .. } => f.write_str("ENCHANT_BUTTON2"), + InventoryViewProperty::EnchantButton3 { .. } => f.write_str("ENCHANT_BUTTON3"), + InventoryViewProperty::EnchantXpSeed { .. } => f.write_str("ENCHANT_XP_SEED"), + InventoryViewProperty::EnchantId1 { .. } => f.write_str("ENCHANT_ID1"), + InventoryViewProperty::EnchantId2 { .. } => f.write_str("ENCHANT_ID2"), + InventoryViewProperty::EnchantId3 { .. } => f.write_str("ENCHANT_ID3"), + InventoryViewProperty::EnchantLevel1 { .. } => f.write_str("ENCHANT_LEVEL1"), + InventoryViewProperty::EnchantLevel2 { .. } => f.write_str("ENCHANT_LEVEL2"), + InventoryViewProperty::EnchantLevel3 { .. } => f.write_str("ENCHANT_LEVEL3"), + InventoryViewProperty::Levels { .. } => f.write_str("LEVELS"), + InventoryViewProperty::PrimaryEffect { .. } => f.write_str("PRIMARY_EFFECT"), + InventoryViewProperty::SecondaryEffect { .. } => f.write_str("SECONDARY_EFFECT"), + InventoryViewProperty::RepairCost { .. } => f.write_str("REPAIR_COST"), + InventoryViewProperty::BookPage { .. } => f.write_str("BOOK_PAGE"), + } } } -impl<'mc> Into> for ItemType<'mc> { - fn into(self) -> crate::Translatable<'mc> { - crate::Translatable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ItemType into crate::Translatable") +impl<'mc> std::ops::Deref for InventoryViewProperty<'mc> { + type Target = InventoryViewPropertyStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + InventoryViewProperty::BrewTime { inner } => inner, + InventoryViewProperty::FuelTime { inner } => inner, + InventoryViewProperty::BurnTime { inner } => inner, + InventoryViewProperty::TicksForCurrentFuel { inner } => inner, + InventoryViewProperty::CookTime { inner } => inner, + InventoryViewProperty::TicksForCurrentSmelting { inner } => inner, + InventoryViewProperty::EnchantButton1 { inner } => inner, + InventoryViewProperty::EnchantButton2 { inner } => inner, + InventoryViewProperty::EnchantButton3 { inner } => inner, + InventoryViewProperty::EnchantXpSeed { inner } => inner, + InventoryViewProperty::EnchantId1 { inner } => inner, + InventoryViewProperty::EnchantId2 { inner } => inner, + InventoryViewProperty::EnchantId3 { inner } => inner, + InventoryViewProperty::EnchantLevel1 { inner } => inner, + InventoryViewProperty::EnchantLevel2 { inner } => inner, + InventoryViewProperty::EnchantLevel3 { inner } => inner, + InventoryViewProperty::Levels { inner } => inner, + InventoryViewProperty::PrimaryEffect { inner } => inner, + InventoryViewProperty::SecondaryEffect { inner } => inner, + InventoryViewProperty::RepairCost { inner } => inner, + InventoryViewProperty::BookPage { inner } => inner, + } + } +} + +impl<'mc> InventoryViewProperty<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/inventory/InventoryView/Property"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/inventory/InventoryView/Property;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "BREW_TIME" => Ok(InventoryViewProperty::BrewTime { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "FUEL_TIME" => Ok(InventoryViewProperty::FuelTime { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "BURN_TIME" => Ok(InventoryViewProperty::BurnTime { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "TICKS_FOR_CURRENT_FUEL" => Ok(InventoryViewProperty::TicksForCurrentFuel { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "COOK_TIME" => Ok(InventoryViewProperty::CookTime { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "TICKS_FOR_CURRENT_SMELTING" => Ok(InventoryViewProperty::TicksForCurrentSmelting { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "ENCHANT_BUTTON1" => Ok(InventoryViewProperty::EnchantButton1 { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "ENCHANT_BUTTON2" => Ok(InventoryViewProperty::EnchantButton2 { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "ENCHANT_BUTTON3" => Ok(InventoryViewProperty::EnchantButton3 { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "ENCHANT_XP_SEED" => Ok(InventoryViewProperty::EnchantXpSeed { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "ENCHANT_ID1" => Ok(InventoryViewProperty::EnchantId1 { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "ENCHANT_ID2" => Ok(InventoryViewProperty::EnchantId2 { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "ENCHANT_ID3" => Ok(InventoryViewProperty::EnchantId3 { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "ENCHANT_LEVEL1" => Ok(InventoryViewProperty::EnchantLevel1 { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "ENCHANT_LEVEL2" => Ok(InventoryViewProperty::EnchantLevel2 { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "ENCHANT_LEVEL3" => Ok(InventoryViewProperty::EnchantLevel3 { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "LEVELS" => Ok(InventoryViewProperty::Levels { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "PRIMARY_EFFECT" => Ok(InventoryViewProperty::PrimaryEffect { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "SECONDARY_EFFECT" => Ok(InventoryViewProperty::SecondaryEffect { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "REPAIR_COST" => Ok(InventoryViewProperty::RepairCost { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "BOOK_PAGE" => Ok(InventoryViewProperty::BookPage { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } + #[repr(C)] -pub struct ItemTypeTyped<'mc>( +pub struct InventoryViewPropertyStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ItemTypeTyped<'mc> { +impl<'mc> JNIRaw<'mc> for InventoryViewProperty<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + match self { + Self::BrewTime { inner } => inner.0.clone(), + Self::FuelTime { inner } => inner.0.clone(), + Self::BurnTime { inner } => inner.0.clone(), + Self::TicksForCurrentFuel { inner } => inner.0.clone(), + Self::CookTime { inner } => inner.0.clone(), + Self::TicksForCurrentSmelting { inner } => inner.0.clone(), + Self::EnchantButton1 { inner } => inner.0.clone(), + Self::EnchantButton2 { inner } => inner.0.clone(), + Self::EnchantButton3 { inner } => inner.0.clone(), + Self::EnchantXpSeed { inner } => inner.0.clone(), + Self::EnchantId1 { inner } => inner.0.clone(), + Self::EnchantId2 { inner } => inner.0.clone(), + Self::EnchantId3 { inner } => inner.0.clone(), + Self::EnchantLevel1 { inner } => inner.0.clone(), + Self::EnchantLevel2 { inner } => inner.0.clone(), + Self::EnchantLevel3 { inner } => inner.0.clone(), + Self::Levels { inner } => inner.0.clone(), + Self::PrimaryEffect { inner } => inner.0.clone(), + Self::SecondaryEffect { inner } => inner.0.clone(), + Self::RepairCost { inner } => inner.0.clone(), + Self::BookPage { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + match self { + Self::BrewTime { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::FuelTime { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BurnTime { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::TicksForCurrentFuel { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CookTime { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::TicksForCurrentSmelting { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnchantButton1 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnchantButton2 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnchantButton3 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnchantXpSeed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnchantId1 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnchantId2 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnchantId3 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnchantLevel1 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnchantLevel2 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnchantLevel3 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Levels { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PrimaryEffect { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SecondaryEffect { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RepairCost { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BookPage { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for ItemTypeTyped<'mc> { +impl<'mc> JNIInstantiatable<'mc> for InventoryViewProperty<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ItemTypeTyped from null object.").into()); + return Err(eyre::eyre!( + "Tried to instantiate InventoryViewProperty from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/ItemType/Typed")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/inventory/InventoryView/Property")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ItemTypeTyped object, got {}", + "Invalid argument passed. Expected a InventoryViewProperty object, got {}", name ) .into()) } else { - Ok(Self(env.clone(), obj)) + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "BREW_TIME" => Ok(InventoryViewProperty::BrewTime { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "FUEL_TIME" => Ok(InventoryViewProperty::FuelTime { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "BURN_TIME" => Ok(InventoryViewProperty::BurnTime { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "TICKS_FOR_CURRENT_FUEL" => Ok(InventoryViewProperty::TicksForCurrentFuel { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "COOK_TIME" => Ok(InventoryViewProperty::CookTime { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "TICKS_FOR_CURRENT_SMELTING" => { + Ok(InventoryViewProperty::TicksForCurrentSmelting { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }) + } + "ENCHANT_BUTTON1" => Ok(InventoryViewProperty::EnchantButton1 { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "ENCHANT_BUTTON2" => Ok(InventoryViewProperty::EnchantButton2 { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "ENCHANT_BUTTON3" => Ok(InventoryViewProperty::EnchantButton3 { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "ENCHANT_XP_SEED" => Ok(InventoryViewProperty::EnchantXpSeed { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "ENCHANT_ID1" => Ok(InventoryViewProperty::EnchantId1 { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "ENCHANT_ID2" => Ok(InventoryViewProperty::EnchantId2 { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "ENCHANT_ID3" => Ok(InventoryViewProperty::EnchantId3 { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "ENCHANT_LEVEL1" => Ok(InventoryViewProperty::EnchantLevel1 { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "ENCHANT_LEVEL2" => Ok(InventoryViewProperty::EnchantLevel2 { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "ENCHANT_LEVEL3" => Ok(InventoryViewProperty::EnchantLevel3 { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "LEVELS" => Ok(InventoryViewProperty::Levels { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "PRIMARY_EFFECT" => Ok(InventoryViewProperty::PrimaryEffect { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "SECONDARY_EFFECT" => Ok(InventoryViewProperty::SecondaryEffect { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "REPAIR_COST" => Ok(InventoryViewProperty::RepairCost { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + "BOOK_PAGE" => Ok(InventoryViewProperty::BookPage { + inner: InventoryViewPropertyStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } } -impl<'mc> ItemTypeTyped<'mc> { - /// Gets the ItemMeta class of this ItemType - pub fn item_meta_class(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/Class;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getItemMetaClass", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(unsafe { jni::objects::JClass::from_raw(res.as_jni().l) }) +impl<'mc> JNIRaw<'mc> for InventoryViewPropertyStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Constructs a new item stack with this item type. - pub fn create_item_stack( - &self, - amount: std::option::Option, - meta_configurator: std::option::Option< - impl Into>, - >, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = amount { - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(a); - args.push(val_1); + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for InventoryViewPropertyStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate InventoryViewPropertyStruct from null object." + ) + .into()); } - if let Some(a) = meta_configurator { - sig += "Ljava/util/function/Consumer;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); + let (valid, name) = + env.validate_name(&obj, "org/bukkit/inventory/InventoryView/Property")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a InventoryViewPropertyStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - sig += ")Lorg/bukkit/inventory/ItemStack;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "createItemStack", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) } - /// Yields this item type as a typed version of itself with a plain {@link ItemMeta} representing it. - pub fn typed( +} + +impl<'mc> InventoryViewPropertyStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/InventoryView/Property;"); + let cls = jni.find_class("org/bukkit/inventory/InventoryView/Property"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::inventory::InventoryViewProperty::from_raw(&jni, obj) + } + + pub fn get_type( &self, - item_meta_type: std::option::Option>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = item_meta_type { - sig += "Ljava/lang/Class;"; - let val_1 = jni::objects::JValueGen::Object(a.into()); - args.push(val_1); - } - sig += ")Lorg/bukkit/inventory/ItemType/Typed;"; + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "typed", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemTypeTyped::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns true if this ItemType has a corresponding {@link BlockType}. - pub fn has_block_type(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasBlockType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns the corresponding {@link BlockType} for the given ItemType. - /// - /// If there is no corresponding {@link BlockType} an error will be thrown. - pub fn block_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockType;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBlockType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockType::from_raw(&self.jni_ref(), unsafe { + crate::event::inventory::InventoryType::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the maximum amount of this item type that can be held in a stack - pub fn max_stack_size(&self) -> Result> { + #[deprecated] + /// Gets the id of this view. + pub fn id(&self) -> Result> { let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the maximum durability of this item type - pub fn max_durability(&self) -> Result> { - let sig = String::from("()S"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMaxDurability", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.s()?) - } - /// Checks if this item type is edible. - pub fn is_edible(&self) -> Result> { - let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isEdible", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getId", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - pub fn is_record(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isRecord", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Checks if this item type can be used as fuel in a Furnace - pub fn is_fuel(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isFuel", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} +pub enum EquipmentSlot<'mc> { + Hand { inner: EquipmentSlotStruct<'mc> }, + OffHand { inner: EquipmentSlotStruct<'mc> }, + Feet { inner: EquipmentSlotStruct<'mc> }, + Legs { inner: EquipmentSlotStruct<'mc> }, + Chest { inner: EquipmentSlotStruct<'mc> }, + Head { inner: EquipmentSlotStruct<'mc> }, + Body { inner: EquipmentSlotStruct<'mc> }, +} +impl<'mc> std::fmt::Display for EquipmentSlot<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + EquipmentSlot::Hand { .. } => f.write_str("HAND"), + EquipmentSlot::OffHand { .. } => f.write_str("OFF_HAND"), + EquipmentSlot::Feet { .. } => f.write_str("FEET"), + EquipmentSlot::Legs { .. } => f.write_str("LEGS"), + EquipmentSlot::Chest { .. } => f.write_str("CHEST"), + EquipmentSlot::Head { .. } => f.write_str("HEAD"), + EquipmentSlot::Body { .. } => f.write_str("BODY"), + } } - /// Checks whether this item type is compostable (can be inserted into a - /// composter). - pub fn is_compostable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCompostable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} +impl<'mc> std::ops::Deref for EquipmentSlot<'mc> { + type Target = EquipmentSlotStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + EquipmentSlot::Hand { inner } => inner, + EquipmentSlot::OffHand { inner } => inner, + EquipmentSlot::Feet { inner } => inner, + EquipmentSlot::Legs { inner } => inner, + EquipmentSlot::Chest { inner } => inner, + EquipmentSlot::Head { inner } => inner, + EquipmentSlot::Body { inner } => inner, + } } - /// Get the chance that this item type will successfully compost. The - /// returned value is between 0 and 1 (inclusive). - /// Items with a compost chance of 1 will always raise the composter's level, - /// while items with a compost chance of 0 will never raise it. - /// Plugins should check that {@link #isCompostable} returns true before - /// calling this method. - pub fn compost_chance(&self) -> Result> { - let sig = String::from("()F"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCompostChance", - sig.as_str(), - vec![], +} + +impl<'mc> EquipmentSlot<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/inventory/EquipmentSlot"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/inventory/EquipmentSlot;", + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "HAND" => Ok(EquipmentSlot::Hand { + inner: EquipmentSlotStruct::from_raw(env, obj)?, + }), + "OFF_HAND" => Ok(EquipmentSlot::OffHand { + inner: EquipmentSlotStruct::from_raw(env, obj)?, + }), + "FEET" => Ok(EquipmentSlot::Feet { + inner: EquipmentSlotStruct::from_raw(env, obj)?, + }), + "LEGS" => Ok(EquipmentSlot::Legs { + inner: EquipmentSlotStruct::from_raw(env, obj)?, + }), + "CHEST" => Ok(EquipmentSlot::Chest { + inner: EquipmentSlotStruct::from_raw(env, obj)?, + }), + "HEAD" => Ok(EquipmentSlot::Head { + inner: EquipmentSlotStruct::from_raw(env, obj)?, + }), + "BODY" => Ok(EquipmentSlot::Body { + inner: EquipmentSlotStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } - /// Determines the remaining item in a crafting grid after crafting with this - /// ingredient. - pub fn crafting_remaining_item( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemType;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCraftingRemainingItem", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); +} + +#[repr(C)] +pub struct EquipmentSlotStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for EquipmentSlot<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Hand { inner } => inner.0.clone(), + Self::OffHand { inner } => inner.0.clone(), + Self::Feet { inner } => inner.0.clone(), + Self::Legs { inner } => inner.0.clone(), + Self::Chest { inner } => inner.0.clone(), + Self::Head { inner } => inner.0.clone(), + Self::Body { inner } => inner.0.clone(), } - Ok(Some(crate::inventory::ItemType::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) } - /// Return an immutable copy of all default {@link Attribute}s and their - /// {@link AttributeModifier}s for a given {@link EquipmentSlot}. - /// Default attributes are those that are always preset on some items, such - /// as the attack damage on weapons or the armor value on armor. - pub fn get_default_attribute_modifiers( - &self, - slot: impl Into>, - ) -> Result, Box> { - let sig = String::from( - "(Lorg/bukkit/inventory/EquipmentSlot;)Lcom/google/common/collect/Multimap;", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(slot.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getDefaultAttributeModifiers", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Hand { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::OffHand { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Feet { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Legs { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Chest { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Head { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Body { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } - #[deprecated] - /// Get the {@link CreativeCategory} to which this item type belongs. - pub fn creative_category( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/CreativeCategory;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCreativeCategory", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); +} +impl<'mc> JNIInstantiatable<'mc> for EquipmentSlot<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate EquipmentSlot from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/EquipmentSlot")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EquipmentSlot object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "HAND" => Ok(EquipmentSlot::Hand { + inner: EquipmentSlotStruct::from_raw(env, obj)?, + }), + "OFF_HAND" => Ok(EquipmentSlot::OffHand { + inner: EquipmentSlotStruct::from_raw(env, obj)?, + }), + "FEET" => Ok(EquipmentSlot::Feet { + inner: EquipmentSlotStruct::from_raw(env, obj)?, + }), + "LEGS" => Ok(EquipmentSlot::Legs { + inner: EquipmentSlotStruct::from_raw(env, obj)?, + }), + "CHEST" => Ok(EquipmentSlot::Chest { + inner: EquipmentSlotStruct::from_raw(env, obj)?, + }), + "HEAD" => Ok(EquipmentSlot::Head { + inner: EquipmentSlotStruct::from_raw(env, obj)?, + }), + "BODY" => Ok(EquipmentSlot::Body { + inner: EquipmentSlotStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } - Ok(Some(crate::inventory::CreativeCategory::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) } - /// Gets if the ItemType is enabled by the features in a world. - pub fn is_enabled_by_feature( - &self, - world: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/World;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isEnabledByFeature", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} + +impl<'mc> JNIRaw<'mc> for EquipmentSlotStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - #[deprecated] - /// Tries to convert this ItemType into a Material - pub fn as_material(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "asMaterial", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for EquipmentSlotStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate EquipmentSlotStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/EquipmentSlot")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EquipmentSlotStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - Ok(Some(crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) } - /// Return the namespaced identifier for this object. - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); +} + +impl<'mc> EquipmentSlotStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/EquipmentSlot;"); + let cls = jni.find_class("org/bukkit/inventory/EquipmentSlot"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::inventory::EquipmentSlot::from_raw(&jni, obj) + } + /// Gets the {@link EquipmentSlotGroup} corresponding to this slot. + pub fn group( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/EquipmentSlotGroup;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getGroup", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + crate::inventory::EquipmentSlotGroup::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the translation key, suitable for use in a translation component. - pub fn translation_key(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTranslationKey", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for ItemTypeTyped<'mc> { - fn into(self) -> crate::inventory::ItemType<'mc> { - crate::inventory::ItemType::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ItemTypeTyped into crate::inventory::ItemType") - } -} #[repr(C)] pub struct LlamaInventory<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, @@ -2769,12 +3644,12 @@ impl<'mc> Into> for ChiseledBookshelfInventory< } } #[repr(C)] -pub struct ShapedRecipe<'mc>( +pub struct EnchantingInventory<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ShapedRecipe<'mc> { +impl<'mc> JNIRaw<'mc> for EnchantingInventory<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2782,18 +3657,20 @@ impl<'mc> JNIRaw<'mc> for ShapedRecipe<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ShapedRecipe<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EnchantingInventory<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ShapedRecipe from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate EnchantingInventory from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/ShapedRecipe")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/EnchantingInventory")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ShapedRecipe object, got {}", + "Invalid argument passed. Expected a EnchantingInventory object, got {}", name ) .into()) @@ -2803,23 +3680,19 @@ impl<'mc> JNIInstantiatable<'mc> for ShapedRecipe<'mc> { } } -impl<'mc> ShapedRecipe<'mc> { - /// Create a shaped recipe to craft the specified ItemStack. The - /// constructor merely determines the result and type; to set the actual - /// recipe, you'll need to call the appropriate methods. - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - key: impl Into>, - result: std::option::Option>>, - ) -> Result, Box> { +impl<'mc> EnchantingInventory<'mc> { + /// Stores the ItemStack at the given index of the inventory. + pub fn set_item( + &self, + index: i32, + item: std::option::Option>>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/NamespacedKey;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) - }); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(index); args.push(val_1); - if let Some(a) = result { + if let Some(a) = item { sig += "Lorg/bukkit/inventory/ItemStack;"; let val_2 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) @@ -2827,265 +3700,14 @@ impl<'mc> ShapedRecipe<'mc> { args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/inventory/ShapedRecipe"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::inventory::ShapedRecipe::from_raw(&jni, res) - } - /// Set the shape of this recipe to the specified rows. Each character - /// represents a different ingredient; exactly what each character - /// represents is set separately. The first row supplied corresponds with - /// the upper most part of the recipe on the workbench e.g. if all three - /// rows are supplies the first string represents the top row on the - /// workbench. - pub fn shape( - &self, - shape: std::option::Option>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = shape { - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_1); - } - sig += ")Lorg/bukkit/inventory/ShapedRecipe;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "shape", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ShapedRecipe::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + .call_method(&self.jni_object(), "setItem", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - #[deprecated] - /// Sets the material that a character in the recipe shape refers to.Note that before an ingredient can be set, the recipe's shape must be defined with {@link #shape(String...)}. - pub fn set_ingredient( - &self, - key: u16, - ingredient: impl Into>, - raw: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "C"; - let val_1 = jni::objects::JValueGen::Char(key); - args.push(val_1); - sig += "Lorg/bukkit/Material;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ingredient.into().jni_object().clone()) - }); - args.push(val_2); - if let Some(a) = raw { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - sig += ")Lorg/bukkit/inventory/ShapedRecipe;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setIngredient", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ShapedRecipe::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get a copy of the ingredients map. - pub fn ingredient_map( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getIngredientMap", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get a copy of the choice map. - pub fn choice_map( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getChoiceMap", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Set the shape of this recipe to the specified rows. Each character - /// represents a different ingredient; exactly what each character - /// represents is set separately. The first row supplied corresponds with - /// the upper most part of the recipe on the workbench e.g. if all three - /// rows are supplies the first string represents the top row on the - /// workbench. - pub fn shape_with_shape( - &self, - shape: std::option::Option>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = shape { - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_1); - } - sig += ")Lorg/bukkit/inventory/ShapedRecipe;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getShape", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ShapedRecipe::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - // SUPER CLASS: org.bukkit.inventory.CraftingRecipe ( ['shape', 'setIngredient', 'getIngredientMap', 'getChoiceMap', 'getShape']) - - pub fn key(&self) -> Result, Box> { - let temp_clone = crate::inventory::CraftingRecipe::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::inventory::CraftingRecipe = temp_clone.into(); - real.key() - } - /// Get the result of this recipe. - pub fn result(&self) -> Result, Box> { - let temp_clone = crate::inventory::CraftingRecipe::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::inventory::CraftingRecipe = temp_clone.into(); - real.result() - } - /// Get the group of this recipe. Recipes with the same group may be grouped - /// together when displayed in the client. - pub fn group(&self) -> Result> { - let temp_clone = crate::inventory::CraftingRecipe::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::inventory::CraftingRecipe = temp_clone.into(); - real.group() - } - /// Set the group of this recipe. Recipes with the same group may be grouped - /// together when displayed in the client. - pub fn set_group(&self, group: impl Into) -> Result<(), Box> { - let temp_clone = crate::inventory::CraftingRecipe::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::inventory::CraftingRecipe = temp_clone.into(); - real.set_group(group) - } - /// Gets the category which this recipe will appear in the recipe book under. - /// Defaults to {@link CraftingBookCategory#MISC} if not set. - pub fn category( - &self, - ) -> Result, Box> - { - let temp_clone = crate::inventory::CraftingRecipe::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::inventory::CraftingRecipe = temp_clone.into(); - real.category() - } - /// Sets the category which this recipe will appear in the recipe book under. - /// Defaults to {@link CraftingBookCategory#MISC} if not set. - pub fn set_category( - &self, - category: impl Into>, - ) -> Result<(), Box> { - let temp_clone = crate::inventory::CraftingRecipe::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::inventory::CraftingRecipe = temp_clone.into(); - real.set_category(category) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for ShapedRecipe<'mc> { - fn into(self) -> crate::inventory::CraftingRecipe<'mc> { - crate::inventory::CraftingRecipe::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ShapedRecipe into crate::inventory::CraftingRecipe") - } -} -#[repr(C)] -pub struct EnchantingInventory<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for EnchantingInventory<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for EnchantingInventory<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate EnchantingInventory from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/EnchantingInventory")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EnchantingInventory object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> EnchantingInventory<'mc> { - /// Stores the ItemStack at the given index of the inventory. - pub fn set_item( - &self, - index: i32, - item: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(index); - args.push(val_1); - if let Some(a) = item { - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setItem", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns the ItemStack found in the slot at the given index - pub fn get_item( + /// Returns the ItemStack found in the slot at the given index + pub fn get_item( &self, index: i32, ) -> Result>, Box> { @@ -3572,12 +4194,12 @@ impl<'mc> Into> for EnchantingInventory<'mc> { } } #[repr(C)] -pub struct MerchantRecipe<'mc>( +pub struct CookingRecipe<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for MerchantRecipe<'mc> { +impl<'mc> JNIRaw<'mc> for CookingRecipe<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3585,20 +4207,18 @@ impl<'mc> JNIRaw<'mc> for MerchantRecipe<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for MerchantRecipe<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CookingRecipe<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate MerchantRecipe from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate CookingRecipe from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/MerchantRecipe")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/CookingRecipe")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a MerchantRecipe object, got {}", + "Invalid argument passed. Expected a CookingRecipe object, got {}", name ) .into()) @@ -3608,364 +4228,232 @@ impl<'mc> JNIInstantiatable<'mc> for MerchantRecipe<'mc> { } } -impl<'mc> MerchantRecipe<'mc> { +impl<'mc> CookingRecipe<'mc> { + /// Create a cooking recipe to craft the specified ItemStack. pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, + key: impl Into>, result: impl Into>, - uses: i32, - max_uses: std::option::Option, - experience_reward: std::option::Option, - villager_experience: std::option::Option, - price_multiplier: std::option::Option, - demand: std::option::Option, - special_price: std::option::Option, - ) -> Result, Box> { + input: impl Into>, + experience: f32, + cooking_time: i32, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; + sig += "Lorg/bukkit/NamespacedKey;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(result.into().jni_object().clone()) + jni::objects::JObject::from_raw(key.into().jni_object().clone()) }); args.push(val_1); - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(uses); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(result.into().jni_object().clone()) + }); args.push(val_2); - if let Some(a) = max_uses { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - if let Some(a) = experience_reward { - sig += "Z"; - let val_4 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_4); - } - if let Some(a) = villager_experience { - sig += "I"; - let val_5 = jni::objects::JValueGen::Int(a); - args.push(val_5); - } - if let Some(a) = price_multiplier { - sig += "F"; - let val_6 = jni::objects::JValueGen::Float(a); - args.push(val_6); - } - if let Some(a) = demand { - sig += "I"; - let val_7 = jni::objects::JValueGen::Int(a); - args.push(val_7); - } - if let Some(a) = special_price { - sig += "I"; - let val_8 = jni::objects::JValueGen::Int(a); - args.push(val_8); - } + sig += "Lorg/bukkit/inventory/RecipeChoice;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(input.into().jni_object().clone()) + }); + args.push(val_3); + sig += "F"; + let val_4 = jni::objects::JValueGen::Float(experience); + args.push(val_4); + sig += "I"; + let val_5 = jni::objects::JValueGen::Int(cooking_time); + args.push(val_5); sig += ")V"; - let cls = jni.find_class("org/bukkit/inventory/MerchantRecipe"); + let cls = jni.find_class("org/bukkit/inventory/CookingRecipe"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::inventory::MerchantRecipe::from_raw(&jni, res) - } - - pub fn result(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getResult", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + crate::inventory::CookingRecipe::from_raw(&jni, res) } - - pub fn add_ingredient( + /// Sets the input of this cooking recipe. + pub fn set_input( &self, - item: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + input: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/Material;)Lorg/bukkit/inventory/CookingRecipe;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(input.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "addIngredient", + "setInput", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::inventory::CookingRecipe::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - - pub fn remove_ingredient(&self, index: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(index); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removeIngredient", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Get the input material. + pub fn input(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getInput", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - - pub fn set_ingredients( + /// Sets the input of this cooking recipe. + pub fn set_input_choice( &self, - ingredients: Vec>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/List;)V"); - let raw_val_1 = self - .jni_ref() - .new_object("java/util/ArrayList", "()V", vec![])?; - for v in ingredients { - let map_val_0 = jni::objects::JValueGen::Object(v); - self.jni_ref().call_method( - &raw_val_1, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_1 = jni::objects::JValueGen::Object(raw_val_1); + input: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/RecipeChoice;)LT;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(input.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setIngredients", + "setInputChoice", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) } - - pub fn ingredients( + /// Get the input choice. + pub fn input_choice( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/RecipeChoice;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getIngredients", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getInputChoice", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::inventory::ItemStack::from_raw(&self.0, obj)?); - } - Ok(new_vec) + crate::inventory::RecipeChoice::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the {@link #adjust(ItemStack) adjusted} first ingredient. - pub fn adjusted_ingredient1( - &self, - ) -> Result>, Box> { + /// Get the result of this recipe. + pub fn result(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAdjustedIngredient1", - sig.as_str(), - vec![], - ); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getResult", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Modifies the amount of the given {@link ItemStack} in the same way as - /// MerchantRecipe dynamically adjusts the amount of the first ingredient - /// during trading. - /// - /// This is calculated by adding up the original amount of the item, the - /// demand scaled by the recipe's - /// {@link #getPriceMultiplier price multiplier} and truncated to the next - /// lowest integer value greater than or equal to 0, and the special price, - /// and then constraining the resulting value between 1 and the - /// {@link ItemStack}'s {@link ItemStack#getMaxStackSize() - /// maximum stack size}. - pub fn adjust( - &self, - item_stack: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) - }); + /// Sets the experience given by this recipe. + pub fn set_experience(&self, experience: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(experience); let res = self.jni_ref().call_method( &self.jni_object(), - "adjust", + "setExperience", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the demand for this trade. - pub fn demand(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getDemand", sig.as_str(), vec![]); + /// Get the experience given by this recipe. + pub fn experience(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getExperience", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.f()?) } - /// Set the demand for this trade. - pub fn set_demand(&self, demand: i32) -> Result<(), Box> { + /// Set the cooking time for this recipe in ticks. + pub fn set_cooking_time(&self, cooking_time: i32) -> Result<(), Box> { let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(demand); + let val_1 = jni::objects::JValueGen::Int(cooking_time); let res = self.jni_ref().call_method( &self.jni_object(), - "setDemand", + "setCookingTime", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the special price for this trade. - pub fn special_price(&self) -> Result> { + /// Get the cooking time for this recipe in ticks. + pub fn cooking_time(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getSpecialPrice", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCookingTime", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Set the special price for this trade. - pub fn set_special_price(&self, special_price: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(special_price); + + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the group of this recipe. Recipes with the same group may be grouped + /// together when displayed in the client. + pub fn group(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getGroup", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Set the group of this recipe. Recipes with the same group may be grouped + /// together when displayed in the client. + pub fn set_group(&self, group: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(group.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setSpecialPrice", + "setGroup", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the number of times this trade has been used. - pub fn uses(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getUses", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the number of times this trade has been used. - pub fn set_uses(&self, uses: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(uses); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setUses", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the maximum number of uses this trade has. - pub fn max_uses(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the category which this recipe will appear in the recipe book under. + /// Defaults to {@link CookingBookCategory#MISC} if not set. + pub fn category( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/recipe/CookingBookCategory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxUses", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the maximum number of uses this trade has. - pub fn set_max_uses(&self, max_uses: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(max_uses); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaxUses", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Whether to reward experience to the player for the trade. - pub fn has_experience_reward(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasExperienceReward", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Set whether to reward experience to the player for the trade. - pub fn set_experience_reward(&self, flag: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(flag.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setExperienceReward", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the amount of experience the villager earns from this trade. - pub fn villager_experience(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getVillagerExperience", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the amount of experience the villager earns from this trade. - pub fn set_villager_experience( - &self, - villager_experience: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(villager_experience); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setVillagerExperience", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the price multiplier for the cost of this trade. - pub fn price_multiplier(&self) -> Result> { - let sig = String::from("()F"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPriceMultiplier", - sig.as_str(), - vec![], - ); + .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + crate::inventory::recipe::CookingBookCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the price multiplier for the cost of this trade. - pub fn set_price_multiplier( + /// Sets the category which this recipe will appear in the recipe book under. + /// Defaults to {@link CookingBookCategory#MISC} if not set. + pub fn set_category( &self, - price_multiplier: f32, + category: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(price_multiplier); + let sig = String::from("(Lorg/bukkit/inventory/recipe/CookingBookCategory;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(category.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPriceMultiplier", + "setCategory", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -3978,19 +4466,25 @@ impl<'mc> MerchantRecipe<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for MerchantRecipe<'mc> { +impl<'mc> Into> for CookingRecipe<'mc> { fn into(self) -> crate::inventory::Recipe<'mc> { crate::inventory::Recipe::from_raw(&self.jni_ref(), self.1) - .expect("Error converting MerchantRecipe into crate::inventory::Recipe") + .expect("Error converting CookingRecipe into crate::inventory::Recipe") + } +} +impl<'mc> Into> for CookingRecipe<'mc> { + fn into(self) -> crate::Keyed<'mc> { + crate::Keyed::from_raw(&self.jni_ref(), self.1) + .expect("Error converting CookingRecipe into crate::Keyed") } } #[repr(C)] -pub struct CookingRecipe<'mc>( +pub struct AnvilInventory<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for CookingRecipe<'mc> { +impl<'mc> JNIRaw<'mc> for AnvilInventory<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3998,18 +4492,20 @@ impl<'mc> JNIRaw<'mc> for CookingRecipe<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for CookingRecipe<'mc> { +impl<'mc> JNIInstantiatable<'mc> for AnvilInventory<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate CookingRecipe from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate AnvilInventory from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/CookingRecipe")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/AnvilInventory")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a CookingRecipe object, got {}", + "Invalid argument passed. Expected a AnvilInventory object, got {}", name ) .into()) @@ -4019,337 +4515,53 @@ impl<'mc> JNIInstantiatable<'mc> for CookingRecipe<'mc> { } } -impl<'mc> CookingRecipe<'mc> { - /// Create a cooking recipe to craft the specified ItemStack. - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - key: impl Into>, - result: impl Into>, - input: impl Into>, - experience: f32, - cooking_time: i32, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/NamespacedKey;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(result.into().jni_object().clone()) - }); - args.push(val_2); - sig += "Lorg/bukkit/inventory/RecipeChoice;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(input.into().jni_object().clone()) - }); - args.push(val_3); - sig += "F"; - let val_4 = jni::objects::JValueGen::Float(experience); - args.push(val_4); - sig += "I"; - let val_5 = jni::objects::JValueGen::Int(cooking_time); - args.push(val_5); - sig += ")V"; - let cls = jni.find_class("org/bukkit/inventory/CookingRecipe"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::inventory::CookingRecipe::from_raw(&jni, res) +impl<'mc> AnvilInventory<'mc> { + #[deprecated] + /// Get the name to be applied to the repaired item. An empty string denotes the default item name. + pub fn rename_text(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRenameText", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Sets the input of this cooking recipe. - pub fn set_input( - &self, - input: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/Material;)Lorg/bukkit/inventory/CookingRecipe;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(input.into().jni_object().clone()) - }); + #[deprecated] + /// Get the item cost (in amount) to complete the current repair. + pub fn repair_cost_amount(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "setInput", + "getRepairCostAmount", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::CookingRecipe::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the input material. - pub fn input(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getInput", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Sets the input of this cooking recipe. - pub fn set_input_choice( - &self, - input: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/RecipeChoice;)LT;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(input.into().jni_object().clone()) - }); + #[deprecated] + /// Set the item cost (in amount) to complete the current repair. + pub fn set_repair_cost_amount(&self, amount: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "setInputChoice", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) - } - /// Get the input choice. - pub fn input_choice( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/RecipeChoice;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInputChoice", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::RecipeChoice::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the result of this recipe. - pub fn result(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getResult", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the experience given by this recipe. - pub fn set_experience(&self, experience: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(experience); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setExperience", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the experience given by this recipe. - pub fn experience(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getExperience", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Set the cooking time for this recipe in ticks. - pub fn set_cooking_time(&self, cooking_time: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(cooking_time); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCookingTime", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the cooking time for this recipe in ticks. - pub fn cooking_time(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCookingTime", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the group of this recipe. Recipes with the same group may be grouped - /// together when displayed in the client. - pub fn group(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getGroup", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Set the group of this recipe. Recipes with the same group may be grouped - /// together when displayed in the client. - pub fn set_group(&self, group: impl Into) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(group.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setGroup", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the category which this recipe will appear in the recipe book under. - /// Defaults to {@link CookingBookCategory#MISC} if not set. - pub fn category( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/recipe/CookingBookCategory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::recipe::CookingBookCategory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the category which this recipe will appear in the recipe book under. - /// Defaults to {@link CookingBookCategory#MISC} if not set. - pub fn set_category( - &self, - category: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/recipe/CookingBookCategory;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(category.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCategory", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for CookingRecipe<'mc> { - fn into(self) -> crate::inventory::Recipe<'mc> { - crate::inventory::Recipe::from_raw(&self.jni_ref(), self.1) - .expect("Error converting CookingRecipe into crate::inventory::Recipe") - } -} -impl<'mc> Into> for CookingRecipe<'mc> { - fn into(self) -> crate::Keyed<'mc> { - crate::Keyed::from_raw(&self.jni_ref(), self.1) - .expect("Error converting CookingRecipe into crate::Keyed") - } -} -#[repr(C)] -pub struct AnvilInventory<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for AnvilInventory<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for AnvilInventory<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate AnvilInventory from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/AnvilInventory")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a AnvilInventory object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> AnvilInventory<'mc> { - /// Get the name to be applied to the repaired item. An empty string denotes - /// the default item name. - pub fn rename_text(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRenameText", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// Get the item cost (in amount) to complete the current repair. - pub fn repair_cost_amount(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getRepairCostAmount", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the item cost (in amount) to complete the current repair. - pub fn set_repair_cost_amount(&self, amount: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(amount); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRepairCostAmount", + "setRepairCostAmount", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } + #[deprecated] /// Get the experience cost (in levels) to complete the current repair. pub fn repair_cost(&self) -> Result> { let sig = String::from("()I"); @@ -4359,6 +4571,7 @@ impl<'mc> AnvilInventory<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } + #[deprecated] /// Set the experience cost (in levels) to complete the current repair. pub fn set_repair_cost(&self, levels: i32) -> Result<(), Box> { let sig = String::from("(I)V"); @@ -4372,12 +4585,8 @@ impl<'mc> AnvilInventory<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the maximum experience cost (in levels) to be allowed by the current - /// repair. If the result of {@link #getRepairCost()} exceeds the returned - /// value, the repair result will be air to due being "too expensive". - /// - /// By default, this level is set to 40. Players in creative mode ignore the - /// maximum repair cost. + #[deprecated] + /// Get the maximum experience cost (in levels) to be allowed by the current repair. If the result of {@link #getRepairCost()} exceeds the returned value, the repair result will be air to due being "too expensive".By default, this level is set to 40. Players in creative mode ignore the maximum repair cost. pub fn maximum_repair_cost(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( @@ -4389,8 +4598,8 @@ impl<'mc> AnvilInventory<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Set the maximum experience cost (in levels) to be allowed by the current - /// repair. The default value set by vanilla Minecraft is 40. + #[deprecated] + /// Set the maximum experience cost (in levels) to be allowed by the current repair. The default value set by vanilla Minecraft is 40. pub fn set_maximum_repair_cost(&self, levels: i32) -> Result<(), Box> { let sig = String::from("(I)V"); let val_1 = jni::objects::JValueGen::Int(levels); @@ -6193,12 +6402,12 @@ impl<'mc> Into> for BlastingRecipe<'mc> { } } #[repr(C)] -pub struct InventoryHolder<'mc>( +pub struct MenuType<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for InventoryHolder<'mc> { +impl<'mc> JNIRaw<'mc> for MenuType<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6206,20 +6415,18 @@ impl<'mc> JNIRaw<'mc> for InventoryHolder<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for InventoryHolder<'mc> { +impl<'mc> JNIInstantiatable<'mc> for MenuType<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate InventoryHolder from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate MenuType from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/InventoryHolder")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/MenuType")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a InventoryHolder object, got {}", + "Invalid argument passed. Expected a MenuType object, got {}", name ) .into()) @@ -6229,17 +6436,51 @@ impl<'mc> JNIInstantiatable<'mc> for InventoryHolder<'mc> { } } -impl<'mc> InventoryHolder<'mc> { - /// Get the object's inventory. - pub fn inventory( +impl<'mc> MenuType<'mc> { + /// Yields this MenuType as a typed version of itself with a specific + /// {@link InventoryView} representing it. + pub fn typed( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + view_class: std::option::Option>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = view_class { + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(a.into()); + args.push(val_1); + } + sig += ")Lorg/bukkit/inventory/MenuType/Typed;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "typed", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + crate::inventory::MenuTypeTyped::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the {@link InventoryView} class of this MenuType. + pub fn inventory_view_class( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/lang/Class;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getInventoryViewClass", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(unsafe { jni::objects::JClass::from_raw(res.as_jni().l) }) + } + /// Return the namespaced identifier for this object. + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -6249,13 +6490,19 @@ impl<'mc> InventoryHolder<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for MenuType<'mc> { + fn into(self) -> crate::Keyed<'mc> { + crate::Keyed::from_raw(&self.jni_ref(), self.1) + .expect("Error converting MenuType into crate::Keyed") + } +} #[repr(C)] -pub struct ShapelessRecipe<'mc>( +pub struct MenuTypeTyped<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ShapelessRecipe<'mc> { +impl<'mc> JNIRaw<'mc> for MenuTypeTyped<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6263,20 +6510,18 @@ impl<'mc> JNIRaw<'mc> for ShapelessRecipe<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ShapelessRecipe<'mc> { +impl<'mc> JNIInstantiatable<'mc> for MenuTypeTyped<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate ShapelessRecipe from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate MenuTypeTyped from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/ShapelessRecipe")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/MenuType/Typed")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ShapelessRecipe object, got {}", + "Invalid argument passed. Expected a MenuTypeTyped object, got {}", name ) .into()) @@ -6286,195 +6531,82 @@ impl<'mc> JNIInstantiatable<'mc> for ShapelessRecipe<'mc> { } } -impl<'mc> ShapelessRecipe<'mc> { - /// Create a shapeless recipe to craft the specified ItemStack. The - /// constructor merely determines the result and type; to set the actual - /// recipe, you'll need to call the appropriate methods. - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - key: impl Into>, - result: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/NamespacedKey;"; +impl<'mc> MenuTypeTyped<'mc> { + /// Creates a view of the specified menu type. + /// + /// The player provided to create this view must be the player the view + /// is opened for. See {@link HumanEntity#openInventory(InventoryView)} + /// for more information. + pub fn create( + &self, + player: impl Into>, + title: impl Into, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/HumanEntity;Ljava/lang/String;)LV;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) + jni::objects::JObject::from_raw(player.into().jni_object().clone()) }); - args.push(val_1); - if let Some(a) = result { - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/inventory/ShapelessRecipe"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::inventory::ShapelessRecipe::from_raw(&jni, res) - } - #[deprecated] - /// Adds multiples of the specified ingredient. - pub fn add_ingredient( - &self, - count: i32, - ingredient: std::option::Option>>, - rawdata: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(count); - args.push(val_1); - if let Some(a) = ingredient { - sig += "Lorg/bukkit/Material;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - if let Some(a) = rawdata { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - sig += ")Lorg/bukkit/inventory/ShapelessRecipe;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "addIngredient", sig.as_str(), args); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(title.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "create", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ShapelessRecipe::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.l()?) } - #[deprecated] - /// Removes an ingredient from the list. If the ingredient occurs multiple times, only one instance of it is removed. If the data value is -1, only ingredients with a -1 data value will be removed. - pub fn remove_ingredient( + /// Yields this MenuType as a typed version of itself with a specific + /// {@link InventoryView} representing it. + pub fn typed( &self, - ingredient: impl Into>, - rawdata: std::option::Option, - ) -> Result, Box> { + view_class: std::option::Option>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ingredient.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = rawdata { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); + if let Some(a) = view_class { + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(a.into()); + args.push(val_1); } - sig += ")Lorg/bukkit/inventory/ShapelessRecipe;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "removeIngredient", sig.as_str(), args); + sig += ")Lorg/bukkit/inventory/MenuType/Typed;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "typed", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ShapelessRecipe::from_raw(&self.jni_ref(), unsafe { + crate::inventory::MenuTypeTyped::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the list of ingredients used for this recipe. - pub fn ingredient_list( + /// Gets the {@link InventoryView} class of this MenuType. + pub fn inventory_view_class( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + ) -> Result, Box> { + let sig = String::from("()Ljava/lang/Class;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getIngredientList", + "getInventoryViewClass", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::inventory::ItemStack::from_raw(&self.0, obj)?); - } - Ok(new_vec) - } - - pub fn choice_list( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getChoiceList", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::inventory::RecipeChoice::from_raw(&self.0, obj)?); - } - Ok(new_vec) + Ok(unsafe { jni::objects::JClass::from_raw(res.as_jni().l) }) } - // SUPER CLASS: org.bukkit.inventory.CraftingRecipe ( ['addIngredient', 'removeIngredient', 'getIngredientList', 'getChoiceList']) - + /// Return the namespaced identifier for this object. pub fn key(&self) -> Result, Box> { - let temp_clone = crate::inventory::CraftingRecipe::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::inventory::CraftingRecipe = temp_clone.into(); - real.key() - } - /// Get the result of this recipe. - pub fn result(&self) -> Result, Box> { - let temp_clone = crate::inventory::CraftingRecipe::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::inventory::CraftingRecipe = temp_clone.into(); - real.result() - } - /// Get the group of this recipe. Recipes with the same group may be grouped - /// together when displayed in the client. - pub fn group(&self) -> Result> { - let temp_clone = crate::inventory::CraftingRecipe::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::inventory::CraftingRecipe = temp_clone.into(); - real.group() - } - /// Set the group of this recipe. Recipes with the same group may be grouped - /// together when displayed in the client. - pub fn set_group(&self, group: impl Into) -> Result<(), Box> { - let temp_clone = crate::inventory::CraftingRecipe::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::inventory::CraftingRecipe = temp_clone.into(); - real.set_group(group) - } - /// Gets the category which this recipe will appear in the recipe book under. - /// Defaults to {@link CraftingBookCategory#MISC} if not set. - pub fn category( - &self, - ) -> Result, Box> - { - let temp_clone = crate::inventory::CraftingRecipe::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::inventory::CraftingRecipe = temp_clone.into(); - real.category() - } - /// Sets the category which this recipe will appear in the recipe book under. - /// Defaults to {@link CraftingBookCategory#MISC} if not set. - pub fn set_category( - &self, - category: impl Into>, - ) -> Result<(), Box> { - let temp_clone = crate::inventory::CraftingRecipe::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::inventory::CraftingRecipe = temp_clone.into(); - real.set_category(category) + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -6482,19 +6614,19 @@ impl<'mc> ShapelessRecipe<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for ShapelessRecipe<'mc> { - fn into(self) -> crate::inventory::CraftingRecipe<'mc> { - crate::inventory::CraftingRecipe::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ShapelessRecipe into crate::inventory::CraftingRecipe") +impl<'mc> Into> for MenuTypeTyped<'mc> { + fn into(self) -> crate::inventory::MenuType<'mc> { + crate::inventory::MenuType::from_raw(&self.jni_ref(), self.1) + .expect("Error converting MenuTypeTyped into crate::inventory::MenuType") } } #[repr(C)] -pub struct EquipmentSlotGroup<'mc>( +pub struct InventoryHolder<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EquipmentSlotGroup<'mc> { +impl<'mc> JNIRaw<'mc> for InventoryHolder<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6502,7 +6634,64 @@ impl<'mc> JNIRaw<'mc> for EquipmentSlotGroup<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EquipmentSlotGroup<'mc> { +impl<'mc> JNIInstantiatable<'mc> for InventoryHolder<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate InventoryHolder from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/InventoryHolder")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a InventoryHolder object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> InventoryHolder<'mc> { + /// Get the object's inventory. + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct EquipmentSlotGroup<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for EquipmentSlotGroup<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for EquipmentSlotGroup<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, @@ -6618,146 +6807,6 @@ impl<'mc> Into> for Equipmen blackboxmc_java::util::function::JavaPredicate::from_raw(&self.jni_ref(), self.1).expect("Error converting EquipmentSlotGroup into blackboxmc_java::util::function::JavaPredicate") } } -pub enum EquipmentSlot<'mc> {} -impl<'mc> std::fmt::Display for EquipmentSlot<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> EquipmentSlot<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/inventory/EquipmentSlot"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/inventory/EquipmentSlot;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct EquipmentSlotStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for EquipmentSlot<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for EquipmentSlot<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate EquipmentSlot from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/EquipmentSlot")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EquipmentSlot object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for EquipmentSlotStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for EquipmentSlotStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate EquipmentSlotStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/EquipmentSlot")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EquipmentSlotStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> EquipmentSlotStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/EquipmentSlot;"); - let cls = jni.find_class("org/bukkit/inventory/EquipmentSlot"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::inventory::EquipmentSlot::from_raw(&jni, obj) - } - /// Gets the {@link EquipmentSlotGroup} corresponding to this slot. - pub fn group( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/EquipmentSlotGroup;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getGroup", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::EquipmentSlotGroup::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} #[repr(C)] pub struct FurnaceInventory<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, @@ -9089,12 +9138,12 @@ impl<'mc> ItemCraftResult<'mc> { } } #[repr(C)] -pub struct SmithingInventory<'mc>( +pub struct ItemType<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for SmithingInventory<'mc> { +impl<'mc> JNIRaw<'mc> for ItemType<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -9102,20 +9151,18 @@ impl<'mc> JNIRaw<'mc> for SmithingInventory<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for SmithingInventory<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ItemType<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate SmithingInventory from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate ItemType from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/SmithingInventory")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/ItemType")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SmithingInventory object, got {}", + "Invalid argument passed. Expected a ItemType object, got {}", name ) .into()) @@ -9125,69 +9172,84 @@ impl<'mc> JNIInstantiatable<'mc> for SmithingInventory<'mc> { } } -impl<'mc> SmithingInventory<'mc> { - /// Check what item is in the result slot of this smithing table. - pub fn result( +impl<'mc> ItemType<'mc> { + /// Yields this item type as a typed version of itself with a plain {@link ItemMeta} representing it. + pub fn typed( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + item_meta_type: std::option::Option>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = item_meta_type { + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(a.into()); + args.push(val_1); + } + sig += ")Lorg/bukkit/inventory/ItemType/Typed;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getResult", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "typed", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::inventory::ItemTypeTyped::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the item in the result slot of the smithing table - pub fn set_result( + /// Constructs a new itemstack with this item type. + pub fn create_item_stack( &self, - new_result: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_result.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setResult", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + amount: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = amount { + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(a); + args.push(val_1); + } + sig += ")Lorg/bukkit/inventory/ItemStack;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createItemStack", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get the current recipe formed on the smithing table, if any. - pub fn recipe( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Recipe;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getRecipe", sig.as_str(), vec![]); + /// Returns true if this ItemType has a corresponding {@link BlockType}. + pub fn has_block_type(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasBlockType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::Recipe::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Returns the size of the inventory - pub fn size(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); + /// Returns the corresponding {@link BlockType} for the given ItemType. + /// + /// If there is no corresponding {@link BlockType} an error will be thrown. + pub fn block_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockType;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBlockType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::block::BlockType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the maximum stack size for an ItemStack in this inventory. + /// Gets the ItemMeta class of this ItemType + pub fn item_meta_class(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/Class;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItemMetaClass", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(unsafe { jni::objects::JClass::from_raw(res.as_jni().l) }) + } + /// Gets the maximum amount of this item type that can be held in a stack pub fn max_stack_size(&self) -> Result> { let sig = String::from("()I"); let res = @@ -9196,472 +9258,556 @@ impl<'mc> SmithingInventory<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// This method allows you to change the maximum stack size for an - /// inventory. - /// - /// Caveats: - ///
    - ///
  • Not all inventories respect this value. - ///
  • Stacks larger than 127 may be clipped when the world is saved. - ///
  • This value is not guaranteed to be preserved; be sure to set it - /// before every time you want to set a slot over the max stack size. - ///
  • Stacks larger than the default max size for this type of inventory - /// may not display correctly in the client. - ///
- pub fn set_max_stack_size(&self, size: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(size); + /// Gets the maximum durability of this item type + pub fn max_durability(&self) -> Result> { + let sig = String::from("()S"); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxStackSize", + "getMaxDurability", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.s()?) } - /// Returns the ItemStack found in the slot at the given index - pub fn get_item( + /// Checks if this item type is edible. + pub fn is_edible(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEdible", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn is_record(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isRecord", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks if this item type can be used as fuel in a Furnace + pub fn is_fuel(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFuel", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks whether this item type is compostable (can be inserted into a + /// composter). + pub fn is_compostable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCompostable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the chance that this item type will successfully compost. The + /// returned value is between 0 and 1 (inclusive). + /// Items with a compost chance of 1 will always raise the composter's level, + /// while items with a compost chance of 0 will never raise it. + /// Plugins should check that {@link #isCompostable} returns true before + /// calling this method. + pub fn compost_chance(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCompostChance", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Determines the remaining item in a crafting grid after crafting with this + /// ingredient. + pub fn crafting_remaining_item( &self, - index: i32, - ) -> Result>, Box> { - let sig = String::from("(I)Lorg/bukkit/inventory/ItemStack;"); - let val_1 = jni::objects::JValueGen::Int(index); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemType;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getItem", + "getCraftingRemainingItem", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::ItemStack::from_raw( + Ok(Some(crate::inventory::ItemType::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Stores the ItemStack at the given index of the inventory. - pub fn set_item( - &self, - index: i32, - item: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(index); - args.push(val_1); - if let Some(a) = item { - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setItem", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Stores the given ItemStacks in the inventory. This will try to fill - /// existing stacks and empty slots as well as it can. - /// - /// The returned HashMap contains what it couldn't store, where the key is - /// the index of the parameter, and the value is the ItemStack at that - /// index of the varargs parameter. If all items are stored, it will return - /// an empty HashMap. - /// - /// If you pass in ItemStacks which exceed the maximum stack size for the - /// Material, first they will be added to partial stacks where - /// Material.getMaxStackSize() is not exceeded, up to - /// Material.getMaxStackSize(). When there are no partial stacks left - /// stacks will be split on Inventory.getMaxStackSize() allowing you to - /// exceed the maximum stack size for that material. - /// - /// It is known that in some implementations this method will also set - /// the inputted argument amount to the number of that item not placed in - /// slots. - pub fn add_item( + /// Return an immutable copy of all default {@link Attribute}s and their + /// {@link AttributeModifier}s for a given {@link EquipmentSlot}. + /// Default attributes are those that are always preset on some items, such + /// as the attack damage on weapons or the armor value on armor. + pub fn get_default_attribute_modifiers( &self, - items: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/HashMap;"); + slot: impl Into>, + ) -> Result, Box> { + let sig = String::from( + "(Lorg/bukkit/inventory/EquipmentSlot;)Lcom/google/common/collect/Multimap;", + ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) + jni::objects::JObject::from_raw(slot.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "addItem", + "getDefaultAttributeModifiers", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.l()?) } - /// Removes the given ItemStacks from the inventory. - /// - /// It will try to remove 'as much as possible' from the types and amounts - /// you give as arguments. - /// - /// The returned HashMap contains what it couldn't remove, where the key is - /// the index of the parameter, and the value is the ItemStack at that - /// index of the varargs parameter. If all the given ItemStacks are - /// removed, it will return an empty HashMap. - /// - /// It is known that in some implementations this method will also set the - /// inputted argument amount to the number of that item not removed from - /// slots. - pub fn remove_item( + #[deprecated] + /// Get the {@link CreativeCategory} to which this item type belongs. + pub fn creative_category( &self, - items: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/HashMap;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) - }); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/CreativeCategory;"); let res = self.jni_ref().call_method( &self.jni_object(), - "removeItem", + "getCreativeCategory", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns all ItemStacks from the inventory - pub fn contents(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getContents", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::CreativeCategory::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Completely replaces the inventory's contents. Removes all existing - /// contents and replaces it with the ItemStacks given in the array. - pub fn set_contents( + /// Gets if the ItemType is enabled by the features in a world. + pub fn is_enabled_by_feature( &self, - items: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + world: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/World;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) + jni::objects::JObject::from_raw(world.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setContents", + "isEnabledByFeature", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Return the contents from the section of the inventory where items can - /// reasonably be expected to be stored. In most cases this will represent - /// the entire inventory, but in some cases it may exclude armor or result - /// slots. - /// - /// It is these contents which will be used for add / contains / remove - /// methods which look for a specific stack. - pub fn storage_contents( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + #[deprecated] + /// Tries to convert this ItemType into a Material + pub fn as_material(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "asMaterial", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Return the namespaced identifier for this object. + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the translation key, suitable for use in a translation component. + pub fn translation_key(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getStorageContents", + "getTranslationKey", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Put the given ItemStacks into the storage slots - pub fn set_storage_contents( - &self, - items: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) - }); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for ItemType<'mc> { + fn into(self) -> crate::Keyed<'mc> { + crate::Keyed::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ItemType into crate::Keyed") + } +} +impl<'mc> Into> for ItemType<'mc> { + fn into(self) -> crate::Translatable<'mc> { + crate::Translatable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ItemType into crate::Translatable") + } +} +#[repr(C)] +pub struct ItemTypeTyped<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ItemTypeTyped<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for ItemTypeTyped<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate ItemTypeTyped from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/ItemType/Typed")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ItemTypeTyped object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> ItemTypeTyped<'mc> { + /// Gets the ItemMeta class of this ItemType + pub fn item_meta_class(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/Class;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setStorageContents", + "getItemMetaClass", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(unsafe { jni::objects::JClass::from_raw(res.as_jni().l) }) } - /// Checks if the inventory contains any ItemStacks with the given - /// material, adding to at least the minimum amount specified. - pub fn contains( + /// Constructs a new item stack with this item type. + pub fn create_item_stack( &self, - material: impl Into>, amount: std::option::Option, - ) -> Result> { + meta_configurator: std::option::Option< + impl Into>, + >, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - args.push(val_1); if let Some(a) = amount { sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); + let val_1 = jni::objects::JValueGen::Int(a); + args.push(val_1); + } + if let Some(a) = meta_configurator { + sig += "Ljava/util/function/Consumer;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); args.push(val_2); } - sig += ")Z"; + sig += ")Lorg/bukkit/inventory/ItemStack;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createItemStack", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Yields this item type as a typed version of itself with a plain {@link ItemMeta} representing it. + pub fn typed( + &self, + item_meta_type: std::option::Option>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = item_meta_type { + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(a.into()); + args.push(val_1); + } + sig += ")Lorg/bukkit/inventory/ItemType/Typed;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "contains", sig.as_str(), args); + .call_method(&self.jni_object(), "typed", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::ItemTypeTyped::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Checks if the inventory contains ItemStacks matching the given - /// ItemStack whose amounts sum to at least the minimum amount specified. - pub fn contains_at_least( - &self, - item: impl Into>, - amount: i32, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;I)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(amount); - let res = self.jni_ref().call_method( - &self.jni_object(), - "containsAtLeast", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + /// Returns true if this ItemType has a corresponding {@link BlockType}. + pub fn has_block_type(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasBlockType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Finds all slots in the inventory containing any ItemStacks with the - /// given ItemStack. This will only match slots if both the type and the - /// amount of the stack match + /// Returns the corresponding {@link BlockType} for the given ItemType. /// - /// The HashMap contains entries where, the key is the slot index, and the - /// value is the ItemStack in that slot. If no matching ItemStack with the - /// given Material is found, an empty map is returned. - pub fn all( - &self, - item: impl Into>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Ljava/util/HashMap;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "all", sig.as_str(), args); + /// If there is no corresponding {@link BlockType} an error will be thrown. + pub fn block_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockType;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBlockType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { + crate::block::BlockType::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns the first slot in the inventory containing an ItemStack with - /// the given stack. This will only match a slot if both the type and the - /// amount of the stack match - pub fn first( - &self, - item: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")I"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "first", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the first empty Slot. - pub fn first_empty(&self) -> Result> { + /// Gets the maximum amount of this item type that can be held in a stack + pub fn max_stack_size(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "firstEmpty", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Check whether or not this inventory is empty. An inventory is considered - /// to be empty if there are no ItemStacks in any slot of this inventory. - pub fn is_empty(&self) -> Result> { + /// Gets the maximum durability of this item type + pub fn max_durability(&self) -> Result> { + let sig = String::from("()S"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaxDurability", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.s()?) + } + /// Checks if this item type is edible. + pub fn is_edible(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isEdible", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes all stacks in the inventory matching the given stack. - /// - /// This will only match a slot if both the type and the amount of the - /// stack match - pub fn remove( - &self, - item: impl Into>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")V"; + + pub fn is_record(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "isRecord", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Clears out a particular slot in the index. - pub fn clear(&self, index: std::option::Option) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = index { - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(a); - args.push(val_1); - } - sig += ")V"; + /// Checks if this item type can be used as fuel in a Furnace + pub fn is_fuel(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "clear", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "isFuel", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets a list of players viewing the inventory. Note that a player is - /// considered to be viewing their own inventory and internal crafting - /// screen even when said inventory is not open. They will normally be - /// considered to be viewing their inventory even when they have a - /// different inventory screen open, but it's possible for customized - /// inventory screens to exclude the viewer's inventory, so this should - /// never be assumed to be non-empty. - pub fn viewers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + /// Checks whether this item type is compostable (can be inserted into a + /// composter). + pub fn is_compostable(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getViewers", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isCompostable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::HumanEntity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(res.z()?) } - /// Returns what type of inventory this is. - pub fn get_type( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + /// Get the chance that this item type will successfully compost. The + /// returned value is between 0 and 1 (inclusive). + /// Items with a compost chance of 1 will always raise the composter's level, + /// while items with a compost chance of 0 will never raise it. + /// Plugins should check that {@link #isCompostable} returns true before + /// calling this method. + pub fn compost_chance(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCompostChance", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::event::inventory::InventoryType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.f()?) } - /// Gets the block or entity belonging to the open inventory - pub fn holder( + /// Determines the remaining item in a crafting grid after crafting with this + /// ingredient. + pub fn crafting_remaining_item( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/InventoryHolder;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHolder", sig.as_str(), vec![]); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemType;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCraftingRemainingItem", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::InventoryHolder::from_raw( + Ok(Some(crate::inventory::ItemType::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - - pub fn iterator( + /// Return an immutable copy of all default {@link Attribute}s and their + /// {@link AttributeModifier}s for a given {@link EquipmentSlot}. + /// Default attributes are those that are always preset on some items, such + /// as the attack damage on weapons or the armor value on armor. + pub fn get_default_attribute_modifiers( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/ListIterator;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "iterator", sig.as_str(), vec![]); + slot: impl Into>, + ) -> Result, Box> { + let sig = String::from( + "(Lorg/bukkit/inventory/EquipmentSlot;)Lcom/google/common/collect/Multimap;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(slot.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDefaultAttributeModifiers", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaListIterator::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.l()?) } - /// Get the location of the block or entity which corresponds to this inventory. May return null if this container - /// was custom created or is a virtual / subcontainer. - pub fn location(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); + #[deprecated] + /// Get the {@link CreativeCategory} to which this item type belongs. + pub fn creative_category( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/CreativeCategory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCreativeCategory", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for SmithingInventory<'mc> { - fn into(self) -> crate::inventory::Inventory<'mc> { - crate::inventory::Inventory::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SmithingInventory into crate::inventory::Inventory") + Ok(Some(crate::inventory::CreativeCategory::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } -} -#[repr(C)] -pub struct Inventory<'mc>( + /// Gets if the ItemType is enabled by the features in a world. + pub fn is_enabled_by_feature( + &self, + world: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/World;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(world.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isEnabledByFeature", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Tries to convert this ItemType into a Material + pub fn as_material(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "asMaterial", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Return the namespaced identifier for this object. + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the translation key, suitable for use in a translation component. + pub fn translation_key(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTranslationKey", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for ItemTypeTyped<'mc> { + fn into(self) -> crate::inventory::ItemType<'mc> { + crate::inventory::ItemType::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ItemTypeTyped into crate::inventory::ItemType") + } +} +#[repr(C)] +pub struct SmithingInventory<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Inventory<'mc> { +impl<'mc> JNIRaw<'mc> for SmithingInventory<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -9669,18 +9815,20 @@ impl<'mc> JNIRaw<'mc> for Inventory<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Inventory<'mc> { +impl<'mc> JNIInstantiatable<'mc> for SmithingInventory<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Inventory from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate SmithingInventory from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/Inventory")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/SmithingInventory")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Inventory object, got {}", + "Invalid argument passed. Expected a SmithingInventory object, got {}", name ) .into()) @@ -9690,7 +9838,59 @@ impl<'mc> JNIInstantiatable<'mc> for Inventory<'mc> { } } -impl<'mc> Inventory<'mc> { +impl<'mc> SmithingInventory<'mc> { + /// Check what item is in the result slot of this smithing table. + pub fn result( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getResult", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Set the item in the result slot of the smithing table + pub fn set_result( + &self, + new_result: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(new_result.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setResult", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the current recipe formed on the smithing table, if any. + pub fn recipe( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Recipe;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRecipe", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::Recipe::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } /// Returns the size of the inventory pub fn size(&self) -> Result> { let sig = String::from("()I"); @@ -10162,13 +10362,19 @@ impl<'mc> Inventory<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for SmithingInventory<'mc> { + fn into(self) -> crate::inventory::Inventory<'mc> { + crate::inventory::Inventory::from_raw(&self.jni_ref(), self.1) + .expect("Error converting SmithingInventory into crate::inventory::Inventory") + } +} #[repr(C)] -pub struct PlayerInventory<'mc>( +pub struct JukeboxInventory<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PlayerInventory<'mc> { +impl<'mc> JNIRaw<'mc> for JukeboxInventory<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -10176,20 +10382,20 @@ impl<'mc> JNIRaw<'mc> for PlayerInventory<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PlayerInventory<'mc> { +impl<'mc> JNIInstantiatable<'mc> for JukeboxInventory<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate PlayerInventory from null object.").into(), + eyre::eyre!("Tried to instantiate JukeboxInventory from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/PlayerInventory")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/JukeboxInventory")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PlayerInventory object, got {}", + "Invalid argument passed. Expected a JukeboxInventory object, got {}", name ) .into()) @@ -10199,51 +10405,36 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerInventory<'mc> { } } -impl<'mc> PlayerInventory<'mc> { - /// Gets all ItemStacks from the armor slots. - pub fn armor_contents( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getArmorContents", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get all additional ItemStacks stored in this inventory. +impl<'mc> JukeboxInventory<'mc> { + /// Set the record in the jukebox. /// - /// NB: What defines an extra slot is up to the implementation, however it - /// will not be contained within {@link #getStorageContents()} or - /// {@link #getArmorContents()} - pub fn extra_contents( + /// This will immediately start playing the inserted item or stop playing if the + /// item provided is null. + pub fn set_record( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getExtraContents", + "setRecord", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Return the ItemStack from the helmet slot - pub fn helmet( + /// Get the record in the jukebox. + pub fn record( &self, ) -> Result>, Box> { let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getHelmet", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getRecord", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); @@ -10253,89 +10444,59 @@ impl<'mc> PlayerInventory<'mc> { unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Return the ItemStack from the chestplate slot - pub fn chestplate( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getChestplate", sig.as_str(), vec![]); + + pub fn holder(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/block/Jukebox;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHolder", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::ItemStack::from_raw( + Ok(Some(crate::block::Jukebox::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Return the ItemStack from the leg slot - pub fn leggings( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + /// Returns the size of the inventory + pub fn size(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the maximum stack size for an ItemStack in this inventory. + pub fn max_stack_size(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLeggings", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - /// Return the ItemStack from the boots slot - pub fn boots( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBoots", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Stores the ItemStack at the given index of the inventory. - /// - /// Indexes 0 through 8 refer to the hotbar. 9 through 35 refer to the main inventory, counting up from 9 at the top - /// left corner of the inventory, moving to the right, and moving to the row below it back on the left side when it - /// reaches the end of the row. It follows the same path in the inventory like you would read a book. - /// - /// Indexes 36 through 39 refer to the armor slots. Though you can set armor with this method using these indexes, - /// you are encouraged to use the provided methods for those slots. - /// - /// Index 40 refers to the off hand (shield) item slot. Though you can set off hand with this method using this index, - /// you are encouraged to use the provided method for this slot. + /// This method allows you to change the maximum stack size for an + /// inventory. /// - /// If you attempt to use this method with an index less than 0 or greater than 40, an ArrayIndexOutOfBounds - /// exception will be thrown. - pub fn set_item( - &self, - index: i32, - item: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(ILorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Int(index); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); + /// Caveats: + ///
    + ///
  • Not all inventories respect this value. + ///
  • Stacks larger than 127 may be clipped when the world is saved. + ///
  • This value is not guaranteed to be preserved; be sure to set it + /// before every time you want to set a slot over the max stack size. + ///
  • Stacks larger than the default max size for this type of inventory + /// may not display correctly in the client. + ///
+ pub fn set_max_stack_size(&self, size: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(size); let res = self.jni_ref().call_method( &self.jni_object(), - "setItem", + "setMaxStackSize", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) @@ -10345,15 +10506,14 @@ impl<'mc> PlayerInventory<'mc> { &self, index: i32, ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; + let sig = String::from("(I)Lorg/bukkit/inventory/ItemStack;"); let val_1 = jni::objects::JValueGen::Int(index); - args.push(val_1); - sig += ")Lorg/bukkit/inventory/ItemStack;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), args); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); @@ -10363,129 +10523,144 @@ impl<'mc> PlayerInventory<'mc> { unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Put the given ItemStacks into the armor slots - pub fn set_armor_contents( + /// Stores the ItemStack at the given index of the inventory. + pub fn set_item( &self, - items: impl Into>, + index: i32, + item: std::option::Option>>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setArmorContents", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(index); + args.push(val_1); + if let Some(a) = item { + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setItem", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Put the given ItemStacks into the extra slots + /// Stores the given ItemStacks in the inventory. This will try to fill + /// existing stacks and empty slots as well as it can. /// - /// See {@link #getExtraContents()} for an explanation of extra slots. - pub fn set_extra_contents( + /// The returned HashMap contains what it couldn't store, where the key is + /// the index of the parameter, and the value is the ItemStack at that + /// index of the varargs parameter. If all items are stored, it will return + /// an empty HashMap. + /// + /// If you pass in ItemStacks which exceed the maximum stack size for the + /// Material, first they will be added to partial stacks where + /// Material.getMaxStackSize() is not exceeded, up to + /// Material.getMaxStackSize(). When there are no partial stacks left + /// stacks will be split on Inventory.getMaxStackSize() allowing you to + /// exceed the maximum stack size for that material. + /// + /// It is known that in some implementations this method will also set + /// the inputted argument amount to the number of that item not placed in + /// slots. + pub fn add_item( &self, items: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/HashMap;"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(items.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setExtraContents", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Put the given ItemStack into the helmet slot. This does not check if - /// the ItemStack is a helmet - pub fn set_helmet( - &self, - helmet: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(helmet.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setHelmet", + "addItem", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Put the given ItemStack into the chestplate slot. This does not check - /// if the ItemStack is a chestplate - pub fn set_chestplate( + /// Removes the given ItemStacks from the inventory. + /// + /// It will try to remove 'as much as possible' from the types and amounts + /// you give as arguments. + /// + /// The returned HashMap contains what it couldn't remove, where the key is + /// the index of the parameter, and the value is the ItemStack at that + /// index of the varargs parameter. If all the given ItemStacks are + /// removed, it will return an empty HashMap. + /// + /// It is known that in some implementations this method will also set the + /// inputted argument amount to the number of that item not removed from + /// slots. + pub fn remove_item( &self, - chestplate: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + items: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/HashMap;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(chestplate.into().jni_object().clone()) + jni::objects::JObject::from_raw(items.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setChestplate", + "removeItem", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Put the given ItemStack into the leg slot. This does not check if the - /// ItemStack is a pair of leggings - pub fn set_leggings( - &self, - leggings: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(leggings.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLeggings", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Returns all ItemStacks from the inventory + pub fn contents(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getContents", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Put the given ItemStack into the boots slot. This does not check if the - /// ItemStack is a boots - pub fn set_boots( + /// Completely replaces the inventory's contents. Removes all existing + /// contents and replaces it with the ItemStacks given in the array. + pub fn set_contents( &self, - boots: impl Into>, + items: impl Into>, ) -> Result<(), Box> { let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(boots.into().jni_object().clone()) + jni::objects::JObject::from_raw(items.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setBoots", + "setContents", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets a copy of the item the player is currently holding - /// in their main hand. - pub fn item_in_main_hand( + /// Return the contents from the section of the inventory where items can + /// reasonably be expected to be stored. In most cases this will represent + /// the entire inventory, but in some cases it may exclude armor or result + /// slots. + /// + /// It is these contents which will be used for add / contains / remove + /// methods which look for a specific stack. + pub fn storage_contents( &self, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getItemInMainHand", + "getStorageContents", sig.as_str(), vec![], ); @@ -10494,153 +10669,312 @@ impl<'mc> PlayerInventory<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the item the player is holding in their main hand. - pub fn set_item_in_main_hand( + /// Put the given ItemStacks into the storage slots + pub fn set_storage_contents( &self, - item: impl Into>, + items: impl Into>, ) -> Result<(), Box> { let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(items.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemInMainHand", + "setStorageContents", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets a copy of the item the player is currently holding - /// in their off hand. - pub fn item_in_off_hand( + /// Checks if the inventory contains any ItemStacks with the given + /// material, adding to at least the minimum amount specified. + pub fn contains( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getItemInOffHand", - sig.as_str(), - vec![], - ); + material: impl Into>, + amount: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = amount { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "contains", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets the item the player is holding in their off hand. - pub fn set_item_in_off_hand( + /// Checks if the inventory contains ItemStacks matching the given + /// ItemStack whose amounts sum to at least the minimum amount specified. + pub fn contains_at_least( &self, item: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + amount: i32, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;I)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Int(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemInOffHand", + "containsAtLeast", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - #[deprecated] - /// Gets a copy of the item the player is currently holding - pub fn item_in_hand( + /// Finds all slots in the inventory containing any ItemStacks with the + /// given ItemStack. This will only match slots if both the type and the + /// amount of the stack match + /// + /// The HashMap contains entries where, the key is the slot index, and the + /// value is the ItemStack in that slot. If no matching ItemStack with the + /// given Material is found, an empty map is returned. + pub fn all( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemInHand", sig.as_str(), vec![]); + item: impl Into>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Ljava/util/HashMap;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "all", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - #[deprecated] - /// Sets the item the player is holding - pub fn set_item_in_hand( + /// Returns the first slot in the inventory containing an ItemStack with + /// the given stack. This will only match a slot if both the type and the + /// amount of the stack match + pub fn first( &self, - stack: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + item: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(stack.into().jni_object().clone()) + jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setItemInHand", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + args.push(val_1); + sig += ")I"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "first", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Get the slot number of the currently held item - pub fn held_item_slot(&self) -> Result> { + /// Returns the first empty Slot. + pub fn first_empty(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getHeldItemSlot", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "firstEmpty", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Set the slot number of the currently held item. + /// Check whether or not this inventory is empty. An inventory is considered + /// to be empty if there are no ItemStacks in any slot of this inventory. + pub fn is_empty(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Removes all stacks in the inventory matching the given stack. /// - /// This validates whether the slot is between 0 and 8 inclusive. - pub fn set_held_item_slot(&self, slot: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(slot); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setHeldItemSlot", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// This will only match a slot if both the type and the amount of the + /// stack match + pub fn remove( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn holder( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); + /// Clears out a particular slot in the index. + pub fn clear(&self, index: std::option::Option) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = index { + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(a); + args.push(val_1); + } + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getHolder", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "clear", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets a list of players viewing the inventory. Note that a player is + /// considered to be viewing their own inventory and internal crafting + /// screen even when said inventory is not open. They will normally be + /// considered to be viewing their inventory even when they have a + /// different inventory screen open, but it's possible for customized + /// inventory screens to exclude the viewer's inventory, so this should + /// never be assumed to be non-empty. + pub fn viewers( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getViewers", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::HumanEntity::from_raw(&self.jni_ref(), obj)?); } - Ok(Some(crate::entity::HumanEntity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(new_vec) } - /// Returns the size of the inventory - pub fn size(&self) -> Result> { - let sig = String::from("()I"); + /// Returns what type of inventory this is. + pub fn get_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::event::inventory::InventoryType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the maximum stack size for an ItemStack in this inventory. - pub fn max_stack_size(&self) -> Result> { - let sig = String::from("()I"); + + pub fn iterator( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/ListIterator;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "iterator", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaListIterator::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the location of the block or entity which corresponds to this inventory. May return null if this container + /// was custom created or is a virtual / subcontainer. + pub fn location(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// This method allows you to change the maximum stack size for an - /// inventory. + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for JukeboxInventory<'mc> { + fn into(self) -> crate::inventory::Inventory<'mc> { + crate::inventory::Inventory::from_raw(&self.jni_ref(), self.1) + .expect("Error converting JukeboxInventory into crate::inventory::Inventory") + } +} +#[repr(C)] +pub struct Inventory<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Inventory<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Inventory<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Inventory from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/Inventory")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Inventory object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Inventory<'mc> { + /// Returns the size of the inventory + pub fn size(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the maximum stack size for an ItemStack in this inventory. + pub fn max_stack_size(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// This method allows you to change the maximum stack size for an + /// inventory. /// /// Caveats: ///
    @@ -10663,6 +10997,53 @@ impl<'mc> PlayerInventory<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } + /// Returns the ItemStack found in the slot at the given index + pub fn get_item( + &self, + index: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/ItemStack;"); + let val_1 = jni::objects::JValueGen::Int(index); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Stores the ItemStack at the given index of the inventory. + pub fn set_item( + &self, + index: i32, + item: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(index); + args.push(val_1); + if let Some(a) = item { + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setItem", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } /// Stores the given ItemStacks in the inventory. This will try to fill /// existing stacks and empty slots as well as it can. /// @@ -10994,6 +11375,23 @@ impl<'mc> PlayerInventory<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } + /// Gets the block or entity belonging to the open inventory + pub fn holder( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/InventoryHolder;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHolder", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::InventoryHolder::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } pub fn iterator( &self, @@ -11028,91 +11426,13 @@ impl<'mc> PlayerInventory<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PlayerInventory<'mc> { - fn into(self) -> crate::inventory::Inventory<'mc> { - crate::inventory::Inventory::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PlayerInventory into crate::inventory::Inventory") - } -} -pub enum ItemFlag<'mc> {} -impl<'mc> std::fmt::Display for ItemFlag<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> ItemFlag<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/inventory/ItemFlag"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/inventory/ItemFlag;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - #[repr(C)] -pub struct ItemFlagStruct<'mc>( +pub struct PlayerInventory<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ItemFlag<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for ItemFlag<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ItemFlag from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/ItemFlag")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ItemFlag object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for ItemFlagStruct<'mc> { +impl<'mc> JNIRaw<'mc> for PlayerInventory<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -11120,20 +11440,20 @@ impl<'mc> JNIRaw<'mc> for ItemFlagStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ItemFlagStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PlayerInventory<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate ItemFlagStruct from null object.").into(), + eyre::eyre!("Tried to instantiate PlayerInventory from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/ItemFlag")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/PlayerInventory")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ItemFlagStruct object, got {}", + "Invalid argument passed. Expected a PlayerInventory object, got {}", name ) .into()) @@ -11143,84 +11463,144 @@ impl<'mc> JNIInstantiatable<'mc> for ItemFlagStruct<'mc> { } } -impl<'mc> ItemFlagStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemFlag;"); - let cls = jni.find_class("org/bukkit/inventory/ItemFlag"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::inventory::ItemFlag::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) +impl<'mc> PlayerInventory<'mc> { + /// Gets all ItemStacks from the armor slots. + pub fn armor_contents( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getArmorContents", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -#[repr(C)] -pub struct BeaconInventory<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for BeaconInventory<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Get all additional ItemStacks stored in this inventory. + /// + /// NB: What defines an extra slot is up to the implementation, however it + /// will not be contained within {@link #getStorageContents()} or + /// {@link #getArmorContents()} + pub fn extra_contents( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getExtraContents", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Return the ItemStack from the helmet slot + pub fn helmet( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHelmet", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } -} -impl<'mc> JNIInstantiatable<'mc> for BeaconInventory<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate BeaconInventory from null object.").into(), - ); + /// Return the ItemStack from the chestplate slot + pub fn chestplate( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getChestplate", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/BeaconInventory")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a BeaconInventory object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Return the ItemStack from the leg slot + pub fn leggings( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLeggings", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Return the ItemStack from the boots slot + pub fn boots( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBoots", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } -} - -impl<'mc> BeaconInventory<'mc> { /// Stores the ItemStack at the given index of the inventory. + /// + /// Indexes 0 through 8 refer to the hotbar. 9 through 35 refer to the main inventory, counting up from 9 at the top + /// left corner of the inventory, moving to the right, and moving to the row below it back on the left side when it + /// reaches the end of the row. It follows the same path in the inventory like you would read a book. + /// + /// Indexes 36 through 39 refer to the armor slots. Though you can set armor with this method using these indexes, + /// you are encouraged to use the provided methods for those slots. + /// + /// Index 40 refers to the off hand (shield) item slot. Though you can set off hand with this method using this index, + /// you are encouraged to use the provided method for this slot. + /// + /// If you attempt to use this method with an index less than 0 or greater than 40, an ArrayIndexOutOfBounds + /// exception will be thrown. pub fn set_item( &self, index: i32, - item: std::option::Option>>, + item: impl Into>, ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; + let sig = String::from("(ILorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Int(index); - args.push(val_1); - if let Some(a) = item { - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setItem", sig.as_str(), args); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItem", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); self.jni_ref().translate_error(res)?; Ok(()) } @@ -11247,161 +11627,164 @@ impl<'mc> BeaconInventory<'mc> { unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Returns the size of the inventory - pub fn size(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the maximum stack size for an ItemStack in this inventory. - pub fn max_stack_size(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// This method allows you to change the maximum stack size for an - /// inventory. - /// - /// Caveats: - ///
      - ///
    • Not all inventories respect this value. - ///
    • Stacks larger than 127 may be clipped when the world is saved. - ///
    • This value is not guaranteed to be preserved; be sure to set it - /// before every time you want to set a slot over the max stack size. - ///
    • Stacks larger than the default max size for this type of inventory - /// may not display correctly in the client. - ///
    - pub fn set_max_stack_size(&self, size: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(size); + /// Put the given ItemStacks into the armor slots + pub fn set_armor_contents( + &self, + items: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(items.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxStackSize", + "setArmorContents", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Stores the given ItemStacks in the inventory. This will try to fill - /// existing stacks and empty slots as well as it can. - /// - /// The returned HashMap contains what it couldn't store, where the key is - /// the index of the parameter, and the value is the ItemStack at that - /// index of the varargs parameter. If all items are stored, it will return - /// an empty HashMap. - /// - /// If you pass in ItemStacks which exceed the maximum stack size for the - /// Material, first they will be added to partial stacks where - /// Material.getMaxStackSize() is not exceeded, up to - /// Material.getMaxStackSize(). When there are no partial stacks left - /// stacks will be split on Inventory.getMaxStackSize() allowing you to - /// exceed the maximum stack size for that material. + /// Put the given ItemStacks into the extra slots /// - /// It is known that in some implementations this method will also set - /// the inputted argument amount to the number of that item not placed in - /// slots. - pub fn add_item( + /// See {@link #getExtraContents()} for an explanation of extra slots. + pub fn set_extra_contents( &self, items: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/HashMap;"); + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(items.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "addItem", + "setExtraContents", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Removes the given ItemStacks from the inventory. - /// - /// It will try to remove 'as much as possible' from the types and amounts - /// you give as arguments. - /// - /// The returned HashMap contains what it couldn't remove, where the key is - /// the index of the parameter, and the value is the ItemStack at that - /// index of the varargs parameter. If all the given ItemStacks are - /// removed, it will return an empty HashMap. - /// - /// It is known that in some implementations this method will also set the - /// inputted argument amount to the number of that item not removed from - /// slots. - pub fn remove_item( + /// Put the given ItemStack into the helmet slot. This does not check if + /// the ItemStack is a helmet + pub fn set_helmet( &self, - items: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/HashMap;"); + helmet: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) + jni::objects::JObject::from_raw(helmet.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeItem", + "setHelmet", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns all ItemStacks from the inventory - pub fn contents(&self) -> Result, Box> { + /// Put the given ItemStack into the chestplate slot. This does not check + /// if the ItemStack is a chestplate + pub fn set_chestplate( + &self, + chestplate: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(chestplate.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setChestplate", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Put the given ItemStack into the leg slot. This does not check if the + /// ItemStack is a pair of leggings + pub fn set_leggings( + &self, + leggings: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(leggings.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLeggings", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Put the given ItemStack into the boots slot. This does not check if the + /// ItemStack is a boots + pub fn set_boots( + &self, + boots: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(boots.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBoots", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets a copy of the item the player is currently holding + /// in their main hand. + pub fn item_in_main_hand( + &self, + ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getContents", sig.as_str(), vec![]); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItemInMainHand", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Completely replaces the inventory's contents. Removes all existing - /// contents and replaces it with the ItemStacks given in the array. - pub fn set_contents( + /// Sets the item the player is holding in their main hand. + pub fn set_item_in_main_hand( &self, - items: impl Into>, + item: impl Into>, ) -> Result<(), Box> { let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) + jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setContents", + "setItemInMainHand", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Return the contents from the section of the inventory where items can - /// reasonably be expected to be stored. In most cases this will represent - /// the entire inventory, but in some cases it may exclude armor or result - /// slots. - /// - /// It is these contents which will be used for add / contains / remove - /// methods which look for a specific stack. - pub fn storage_contents( + /// Gets a copy of the item the player is currently holding + /// in their off hand. + pub fn item_in_off_hand( &self, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getStorageContents", + "getItemInOffHand", sig.as_str(), vec![], ); @@ -11410,128 +11793,383 @@ impl<'mc> BeaconInventory<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Put the given ItemStacks into the storage slots - pub fn set_storage_contents( + /// Sets the item the player is holding in their off hand. + pub fn set_item_in_off_hand( &self, - items: impl Into>, + item: impl Into>, ) -> Result<(), Box> { let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) + jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setStorageContents", + "setItemInOffHand", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if the inventory contains any ItemStacks with the given - /// material, adding to at least the minimum amount specified. - pub fn contains( + #[deprecated] + /// Gets a copy of the item the player is currently holding + pub fn item_in_hand( &self, - material: impl Into>, - amount: std::option::Option, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = amount { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "contains", sig.as_str(), args); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemInHand", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Checks if the inventory contains ItemStacks matching the given - /// ItemStack whose amounts sum to at least the minimum amount specified. - pub fn contains_at_least( + #[deprecated] + /// Sets the item the player is holding + pub fn set_item_in_hand( &self, - item: impl Into>, - amount: i32, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;I)Z"); + stack: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(stack.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "containsAtLeast", + "setItemInHand", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the slot number of the currently held item + pub fn held_item_slot(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHeldItemSlot", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Finds all slots in the inventory containing any ItemStacks with the - /// given ItemStack. This will only match slots if both the type and the - /// amount of the stack match + /// Set the slot number of the currently held item. /// - /// The HashMap contains entries where, the key is the slot index, and the - /// value is the ItemStack in that slot. If no matching ItemStack with the - /// given Material is found, an empty map is returned. - pub fn all( + /// This validates whether the slot is between 0 and 8 inclusive. + pub fn set_held_item_slot(&self, slot: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setHeldItemSlot", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn holder( &self, - item: impl Into>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Ljava/util/HashMap;"; + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "all", sig.as_str(), args); + .call_method(&self.jni_object(), "getHolder", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::HumanEntity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Returns the first slot in the inventory containing an ItemStack with - /// the given stack. This will only match a slot if both the type and the - /// amount of the stack match - pub fn first( - &self, - item: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")I"; + /// Returns the size of the inventory + pub fn size(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "first", sig.as_str(), args); + .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Returns the first empty Slot. - pub fn first_empty(&self) -> Result> { + /// Returns the maximum stack size for an ItemStack in this inventory. + pub fn max_stack_size(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "firstEmpty", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// This method allows you to change the maximum stack size for an + /// inventory. + /// + /// Caveats: + ///
      + ///
    • Not all inventories respect this value. + ///
    • Stacks larger than 127 may be clipped when the world is saved. + ///
    • This value is not guaranteed to be preserved; be sure to set it + /// before every time you want to set a slot over the max stack size. + ///
    • Stacks larger than the default max size for this type of inventory + /// may not display correctly in the client. + ///
    + pub fn set_max_stack_size(&self, size: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(size); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaxStackSize", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Stores the given ItemStacks in the inventory. This will try to fill + /// existing stacks and empty slots as well as it can. + /// + /// The returned HashMap contains what it couldn't store, where the key is + /// the index of the parameter, and the value is the ItemStack at that + /// index of the varargs parameter. If all items are stored, it will return + /// an empty HashMap. + /// + /// If you pass in ItemStacks which exceed the maximum stack size for the + /// Material, first they will be added to partial stacks where + /// Material.getMaxStackSize() is not exceeded, up to + /// Material.getMaxStackSize(). When there are no partial stacks left + /// stacks will be split on Inventory.getMaxStackSize() allowing you to + /// exceed the maximum stack size for that material. + /// + /// It is known that in some implementations this method will also set + /// the inputted argument amount to the number of that item not placed in + /// slots. + pub fn add_item( + &self, + items: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/HashMap;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(items.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Removes the given ItemStacks from the inventory. + /// + /// It will try to remove 'as much as possible' from the types and amounts + /// you give as arguments. + /// + /// The returned HashMap contains what it couldn't remove, where the key is + /// the index of the parameter, and the value is the ItemStack at that + /// index of the varargs parameter. If all the given ItemStacks are + /// removed, it will return an empty HashMap. + /// + /// It is known that in some implementations this method will also set the + /// inputted argument amount to the number of that item not removed from + /// slots. + pub fn remove_item( + &self, + items: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/HashMap;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(items.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns all ItemStacks from the inventory + pub fn contents(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getContents", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Completely replaces the inventory's contents. Removes all existing + /// contents and replaces it with the ItemStacks given in the array. + pub fn set_contents( + &self, + items: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(items.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setContents", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Return the contents from the section of the inventory where items can + /// reasonably be expected to be stored. In most cases this will represent + /// the entire inventory, but in some cases it may exclude armor or result + /// slots. + /// + /// It is these contents which will be used for add / contains / remove + /// methods which look for a specific stack. + pub fn storage_contents( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getStorageContents", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Put the given ItemStacks into the storage slots + pub fn set_storage_contents( + &self, + items: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(items.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setStorageContents", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the inventory contains any ItemStacks with the given + /// material, adding to at least the minimum amount specified. + pub fn contains( + &self, + material: impl Into>, + amount: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = amount { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "contains", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks if the inventory contains ItemStacks matching the given + /// ItemStack whose amounts sum to at least the minimum amount specified. + pub fn contains_at_least( + &self, + item: impl Into>, + amount: i32, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;I)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(amount); + let res = self.jni_ref().call_method( + &self.jni_object(), + "containsAtLeast", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Finds all slots in the inventory containing any ItemStacks with the + /// given ItemStack. This will only match slots if both the type and the + /// amount of the stack match + /// + /// The HashMap contains entries where, the key is the slot index, and the + /// value is the ItemStack in that slot. If no matching ItemStack with the + /// given Material is found, an empty map is returned. + pub fn all( + &self, + item: impl Into>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Ljava/util/HashMap;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "all", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns the first slot in the inventory containing an ItemStack with + /// the given stack. This will only match a slot if both the type and the + /// amount of the stack match + pub fn first( + &self, + item: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")I"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "first", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the first empty Slot. + pub fn first_empty(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "firstEmpty", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } @@ -11620,23 +12258,6 @@ impl<'mc> BeaconInventory<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the block or entity belonging to the open inventory - pub fn holder( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/InventoryHolder;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHolder", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::InventoryHolder::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } pub fn iterator( &self, @@ -11661,9 +12282,256 @@ impl<'mc> BeaconInventory<'mc> { if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for PlayerInventory<'mc> { + fn into(self) -> crate::inventory::Inventory<'mc> { + crate::inventory::Inventory::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PlayerInventory into crate::inventory::Inventory") + } +} +pub enum ItemFlag<'mc> { + HideEnchants { inner: ItemFlagStruct<'mc> }, + HideAttributes { inner: ItemFlagStruct<'mc> }, + HideUnbreakable { inner: ItemFlagStruct<'mc> }, + HideDestroys { inner: ItemFlagStruct<'mc> }, + HidePlacedOn { inner: ItemFlagStruct<'mc> }, + HideAdditionalTooltip { inner: ItemFlagStruct<'mc> }, + HideDye { inner: ItemFlagStruct<'mc> }, + HideArmorTrim { inner: ItemFlagStruct<'mc> }, +} +impl<'mc> std::fmt::Display for ItemFlag<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ItemFlag::HideEnchants { .. } => f.write_str("HIDE_ENCHANTS"), + ItemFlag::HideAttributes { .. } => f.write_str("HIDE_ATTRIBUTES"), + ItemFlag::HideUnbreakable { .. } => f.write_str("HIDE_UNBREAKABLE"), + ItemFlag::HideDestroys { .. } => f.write_str("HIDE_DESTROYS"), + ItemFlag::HidePlacedOn { .. } => f.write_str("HIDE_PLACED_ON"), + ItemFlag::HideAdditionalTooltip { .. } => f.write_str("HIDE_ADDITIONAL_TOOLTIP"), + ItemFlag::HideDye { .. } => f.write_str("HIDE_DYE"), + ItemFlag::HideArmorTrim { .. } => f.write_str("HIDE_ARMOR_TRIM"), + } + } +} +impl<'mc> std::ops::Deref for ItemFlag<'mc> { + type Target = ItemFlagStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + ItemFlag::HideEnchants { inner } => inner, + ItemFlag::HideAttributes { inner } => inner, + ItemFlag::HideUnbreakable { inner } => inner, + ItemFlag::HideDestroys { inner } => inner, + ItemFlag::HidePlacedOn { inner } => inner, + ItemFlag::HideAdditionalTooltip { inner } => inner, + ItemFlag::HideDye { inner } => inner, + ItemFlag::HideArmorTrim { inner } => inner, + } + } +} + +impl<'mc> ItemFlag<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/inventory/ItemFlag"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/inventory/ItemFlag;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "HIDE_ENCHANTS" => Ok(ItemFlag::HideEnchants { + inner: ItemFlagStruct::from_raw(env, obj)?, + }), + "HIDE_ATTRIBUTES" => Ok(ItemFlag::HideAttributes { + inner: ItemFlagStruct::from_raw(env, obj)?, + }), + "HIDE_UNBREAKABLE" => Ok(ItemFlag::HideUnbreakable { + inner: ItemFlagStruct::from_raw(env, obj)?, + }), + "HIDE_DESTROYS" => Ok(ItemFlag::HideDestroys { + inner: ItemFlagStruct::from_raw(env, obj)?, + }), + "HIDE_PLACED_ON" => Ok(ItemFlag::HidePlacedOn { + inner: ItemFlagStruct::from_raw(env, obj)?, + }), + "HIDE_ADDITIONAL_TOOLTIP" => Ok(ItemFlag::HideAdditionalTooltip { + inner: ItemFlagStruct::from_raw(env, obj)?, + }), + "HIDE_DYE" => Ok(ItemFlag::HideDye { + inner: ItemFlagStruct::from_raw(env, obj)?, + }), + "HIDE_ARMOR_TRIM" => Ok(ItemFlag::HideArmorTrim { + inner: ItemFlagStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct ItemFlagStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ItemFlag<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::HideEnchants { inner } => inner.0.clone(), + Self::HideAttributes { inner } => inner.0.clone(), + Self::HideUnbreakable { inner } => inner.0.clone(), + Self::HideDestroys { inner } => inner.0.clone(), + Self::HidePlacedOn { inner } => inner.0.clone(), + Self::HideAdditionalTooltip { inner } => inner.0.clone(), + Self::HideDye { inner } => inner.0.clone(), + Self::HideArmorTrim { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::HideEnchants { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HideAttributes { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HideUnbreakable { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HideDestroys { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HidePlacedOn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HideAdditionalTooltip { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HideDye { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::HideArmorTrim { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for ItemFlag<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate ItemFlag from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/ItemFlag")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ItemFlag object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "HIDE_ENCHANTS" => Ok(ItemFlag::HideEnchants { + inner: ItemFlagStruct::from_raw(env, obj)?, + }), + "HIDE_ATTRIBUTES" => Ok(ItemFlag::HideAttributes { + inner: ItemFlagStruct::from_raw(env, obj)?, + }), + "HIDE_UNBREAKABLE" => Ok(ItemFlag::HideUnbreakable { + inner: ItemFlagStruct::from_raw(env, obj)?, + }), + "HIDE_DESTROYS" => Ok(ItemFlag::HideDestroys { + inner: ItemFlagStruct::from_raw(env, obj)?, + }), + "HIDE_PLACED_ON" => Ok(ItemFlag::HidePlacedOn { + inner: ItemFlagStruct::from_raw(env, obj)?, + }), + "HIDE_ADDITIONAL_TOOLTIP" => Ok(ItemFlag::HideAdditionalTooltip { + inner: ItemFlagStruct::from_raw(env, obj)?, + }), + "HIDE_DYE" => Ok(ItemFlag::HideDye { + inner: ItemFlagStruct::from_raw(env, obj)?, + }), + "HIDE_ARMOR_TRIM" => Ok(ItemFlag::HideArmorTrim { + inner: ItemFlagStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for ItemFlagStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for ItemFlagStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate ItemFlagStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/ItemFlag")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ItemFlagStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> ItemFlagStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemFlag;"); + let cls = jni.find_class("org/bukkit/inventory/ItemFlag"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::inventory::ItemFlag::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -11671,19 +12539,13 @@ impl<'mc> BeaconInventory<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BeaconInventory<'mc> { - fn into(self) -> crate::inventory::Inventory<'mc> { - crate::inventory::Inventory::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BeaconInventory into crate::inventory::Inventory") - } -} #[repr(C)] -pub struct CraftingInventory<'mc>( +pub struct BeaconInventory<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for CraftingInventory<'mc> { +impl<'mc> JNIRaw<'mc> for BeaconInventory<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -11691,20 +12553,20 @@ impl<'mc> JNIRaw<'mc> for CraftingInventory<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for CraftingInventory<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BeaconInventory<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate CraftingInventory from null object.").into(), + eyre::eyre!("Tried to instantiate BeaconInventory from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/CraftingInventory")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/BeaconInventory")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a CraftingInventory object, got {}", + "Invalid argument passed. Expected a BeaconInventory object, got {}", name ) .into()) @@ -11714,84 +12576,51 @@ impl<'mc> JNIInstantiatable<'mc> for CraftingInventory<'mc> { } } -impl<'mc> CraftingInventory<'mc> { - /// Check what item is in the result slot of this crafting inventory. - pub fn result( +impl<'mc> BeaconInventory<'mc> { + /// Stores the ItemStack at the given index of the inventory. + pub fn set_item( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getResult", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + index: i32, + item: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(index); + args.push(val_1); + if let Some(a) = item { + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Get the contents of the crafting matrix. - pub fn matrix(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getMatrix", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Set the item in the result slot of the crafting inventory. - pub fn set_result( - &self, - new_result: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_result.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setResult", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Replace the contents of the crafting matrix - pub fn set_matrix( - &self, - contents: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(contents.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMatrix", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "setItem", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the current recipe formed on the crafting inventory, if any. - pub fn recipe( + /// Returns the ItemStack found in the slot at the given index + pub fn get_item( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Recipe;"); + index: i32, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(index); + args.push(val_1); + sig += ")Lorg/bukkit/inventory/ItemStack;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getRecipe", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::Recipe::from_raw( + Ok(Some(crate::inventory::ItemStack::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) @@ -11838,54 +12667,6 @@ impl<'mc> CraftingInventory<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the ItemStack found in the slot at the given index - pub fn get_item( - &self, - index: i32, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(index); - args.push(val_1); - sig += ")Lorg/bukkit/inventory/ItemStack;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Stores the ItemStack at the given index of the inventory. - pub fn set_item( - &self, - index: i32, - item: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(index); - args.push(val_1); - if let Some(a) = item { - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setItem", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } /// Stores the given ItemStacks in the inventory. This will try to fill /// existing stacks and empty slots as well as it can. /// @@ -12268,19 +13049,19 @@ impl<'mc> CraftingInventory<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for CraftingInventory<'mc> { +impl<'mc> Into> for BeaconInventory<'mc> { fn into(self) -> crate::inventory::Inventory<'mc> { crate::inventory::Inventory::from_raw(&self.jni_ref(), self.1) - .expect("Error converting CraftingInventory into crate::inventory::Inventory") + .expect("Error converting BeaconInventory into crate::inventory::Inventory") } } #[repr(C)] -pub struct EntityEquipment<'mc>( +pub struct CrafterInventory<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EntityEquipment<'mc> { +impl<'mc> JNIRaw<'mc> for CrafterInventory<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -12288,20 +13069,20 @@ impl<'mc> JNIRaw<'mc> for EntityEquipment<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EntityEquipment<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CrafterInventory<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate EntityEquipment from null object.").into(), + eyre::eyre!("Tried to instantiate CrafterInventory from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/EntityEquipment")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/CrafterInventory")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityEquipment object, got {}", + "Invalid argument passed. Expected a CrafterInventory object, got {}", name ) .into()) @@ -12309,32 +13090,91 @@ impl<'mc> JNIInstantiatable<'mc> for EntityEquipment<'mc> { Ok(Self(env.clone(), obj)) } } -} - -impl<'mc> EntityEquipment<'mc> { - /// Stores the ItemStack at the given equipment slot in the inventory. +} + +impl<'mc> CrafterInventory<'mc> { + /// Returns the size of the inventory + pub fn size(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the maximum stack size for an ItemStack in this inventory. + pub fn max_stack_size(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// This method allows you to change the maximum stack size for an + /// inventory. + /// + /// Caveats: + ///
      + ///
    • Not all inventories respect this value. + ///
    • Stacks larger than 127 may be clipped when the world is saved. + ///
    • This value is not guaranteed to be preserved; be sure to set it + /// before every time you want to set a slot over the max stack size. + ///
    • Stacks larger than the default max size for this type of inventory + /// may not display correctly in the client. + ///
    + pub fn set_max_stack_size(&self, size: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(size); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaxStackSize", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the ItemStack found in the slot at the given index + pub fn get_item( + &self, + index: i32, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(index); + args.push(val_1); + sig += ")Lorg/bukkit/inventory/ItemStack;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getItem", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Stores the ItemStack at the given index of the inventory. pub fn set_item( &self, - slot: impl Into>, - item: impl Into>, - silent: std::option::Option, + index: i32, + item: std::option::Option>>, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/EquipmentSlot;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(slot.into().jni_object().clone()) - }); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(index); args.push(val_1); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - args.push(val_2); - if let Some(a) = silent { - sig += "Z"; - let val_3 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_3); + if let Some(a) = item { + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); } sig += ")V"; let res = self @@ -12343,36 +13183,119 @@ impl<'mc> EntityEquipment<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the ItemStack at the given equipment slot in the inventory. - pub fn get_item( + /// Stores the given ItemStacks in the inventory. This will try to fill + /// existing stacks and empty slots as well as it can. + /// + /// The returned HashMap contains what it couldn't store, where the key is + /// the index of the parameter, and the value is the ItemStack at that + /// index of the varargs parameter. If all items are stored, it will return + /// an empty HashMap. + /// + /// If you pass in ItemStacks which exceed the maximum stack size for the + /// Material, first they will be added to partial stacks where + /// Material.getMaxStackSize() is not exceeded, up to + /// Material.getMaxStackSize(). When there are no partial stacks left + /// stacks will be split on Inventory.getMaxStackSize() allowing you to + /// exceed the maximum stack size for that material. + /// + /// It is known that in some implementations this method will also set + /// the inputted argument amount to the number of that item not placed in + /// slots. + pub fn add_item( &self, - slot: impl Into>, - ) -> Result, Box> { - let sig = - String::from("(Lorg/bukkit/inventory/EquipmentSlot;)Lorg/bukkit/inventory/ItemStack;"); + items: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/HashMap;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(slot.into().jni_object().clone()) + jni::objects::JObject::from_raw(items.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getItem", + "addItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Removes the given ItemStacks from the inventory. + /// + /// It will try to remove 'as much as possible' from the types and amounts + /// you give as arguments. + /// + /// The returned HashMap contains what it couldn't remove, where the key is + /// the index of the parameter, and the value is the ItemStack at that + /// index of the varargs parameter. If all the given ItemStacks are + /// removed, it will return an empty HashMap. + /// + /// It is known that in some implementations this method will also set the + /// inputted argument amount to the number of that item not removed from + /// slots. + pub fn remove_item( + &self, + items: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/HashMap;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(items.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeItem", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns all ItemStacks from the inventory + pub fn contents(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getContents", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets a copy of the item the entity is currently holding - /// in their main hand. - pub fn item_in_main_hand( + /// Completely replaces the inventory's contents. Removes all existing + /// contents and replaces it with the ItemStacks given in the array. + pub fn set_contents( + &self, + items: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(items.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setContents", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Return the contents from the section of the inventory where items can + /// reasonably be expected to be stored. In most cases this will represent + /// the entire inventory, but in some cases it may exclude armor or result + /// slots. + /// + /// It is these contents which will be used for add / contains / remove + /// methods which look for a specific stack. + pub fn storage_contents( &self, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getItemInMainHand", + "getStorageContents", sig.as_str(), vec![], ); @@ -12381,12 +13304,108 @@ impl<'mc> EntityEquipment<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the item the entity is holding in their main hand. - pub fn set_item_in_main_hand( + /// Put the given ItemStacks into the storage slots + pub fn set_storage_contents( + &self, + items: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(items.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setStorageContents", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the inventory contains any ItemStacks with the given + /// material, adding to at least the minimum amount specified. + pub fn contains( + &self, + material: impl Into>, + amount: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = amount { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "contains", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks if the inventory contains ItemStacks matching the given + /// ItemStack whose amounts sum to at least the minimum amount specified. + pub fn contains_at_least( + &self, + item: impl Into>, + amount: i32, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;I)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(amount); + let res = self.jni_ref().call_method( + &self.jni_object(), + "containsAtLeast", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Finds all slots in the inventory containing any ItemStacks with the + /// given ItemStack. This will only match slots if both the type and the + /// amount of the stack match + /// + /// The HashMap contains entries where, the key is the slot index, and the + /// value is the ItemStack in that slot. If no matching ItemStack with the + /// given Material is found, an empty map is returned. + pub fn all( + &self, + item: impl Into>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Ljava/util/HashMap;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "all", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns the first slot in the inventory containing an ItemStack with + /// the given stack. This will only match a slot if both the type and the + /// amount of the stack match + pub fn first( &self, item: impl Into>, - silent: std::option::Option, - ) -> Result<(), Box> { + ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "Lorg/bukkit/inventory/ItemStack;"; @@ -12394,40 +13413,39 @@ impl<'mc> EntityEquipment<'mc> { jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); args.push(val_1); - if let Some(a) = silent { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")V"; + sig += ")I"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "first", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the first empty Slot. + pub fn first_empty(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "setItemInMainHand", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "firstEmpty", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Gets a copy of the item the entity is currently holding - /// in their off hand. - pub fn item_in_off_hand( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getItemInOffHand", - sig.as_str(), - vec![], - ); + /// Check whether or not this inventory is empty. An inventory is considered + /// to be empty if there are no ItemStacks in any slot of this inventory. + pub fn is_empty(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets the item the entity is holding in their off hand. - pub fn set_item_in_off_hand( + /// Removes all stacks in the inventory matching the given stack. + /// + /// This will only match a slot if both the type and the amount of the + /// stack match + pub fn remove( &self, item: impl Into>, - silent: std::option::Option, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); @@ -12436,185 +13454,169 @@ impl<'mc> EntityEquipment<'mc> { jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); args.push(val_1); - if let Some(a) = silent { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Clears out a particular slot in the index. + pub fn clear(&self, index: std::option::Option) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = index { + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(a); + args.push(val_1); } sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setItemInOffHand", sig.as_str(), args); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clear", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets a copy of the item the entity is currently holding - pub fn item_in_hand( + /// Gets a list of players viewing the inventory. Note that a player is + /// considered to be viewing their own inventory and internal crafting + /// screen even when said inventory is not open. They will normally be + /// considered to be viewing their inventory even when they have a + /// different inventory screen open, but it's possible for customized + /// inventory screens to exclude the viewer's inventory, so this should + /// never be assumed to be non-empty. + pub fn viewers( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemInHand", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getViewers", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::HumanEntity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - #[deprecated] - /// Sets the item the entity is holding - pub fn set_item_in_hand( + /// Returns what type of inventory this is. + pub fn get_type( &self, - stack: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(stack.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setItemInHand", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets a copy of the helmet currently being worn by the entity - pub fn helmet( + /// Gets the block or entity belonging to the open inventory + pub fn holder( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/InventoryHolder;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getHelmet", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getHolder", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::ItemStack::from_raw( + Ok(Some(crate::inventory::InventoryHolder::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets the helmet worn by the entity - pub fn set_helmet( + + pub fn iterator( &self, - helmet: impl Into>, - silent: std::option::Option, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(helmet.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = silent { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")V"; + ) -> Result, Box> { + let sig = String::from("()Ljava/util/ListIterator;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "setHelmet", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "iterator", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaListIterator::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets a copy of the chest plate currently being worn by the entity - pub fn chestplate( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + /// Get the location of the block or entity which corresponds to this inventory. May return null if this container + /// was custom created or is a virtual / subcontainer. + pub fn location(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getChestplate", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Sets the chest plate worn by the entity - pub fn set_chestplate( - &self, - chestplate: impl Into>, - silent: std::option::Option, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(chestplate.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = silent { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setChestplate", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Gets a copy of the leggings currently being worn by the entity - pub fn leggings( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLeggings", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) +} +impl<'mc> Into> for CrafterInventory<'mc> { + fn into(self) -> crate::inventory::Inventory<'mc> { + crate::inventory::Inventory::from_raw(&self.jni_ref(), self.1) + .expect("Error converting CrafterInventory into crate::inventory::Inventory") + } +} +#[repr(C)] +pub struct CraftingInventory<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for CraftingInventory<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Sets the leggings worn by the entity - pub fn set_leggings( - &self, - leggings: impl Into>, - silent: std::option::Option, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(leggings.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = silent { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for CraftingInventory<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate CraftingInventory from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/CraftingInventory")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a CraftingInventory object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setLeggings", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) } - /// Gets a copy of the boots currently being worn by the entity - pub fn boots( +} + +impl<'mc> CraftingInventory<'mc> { + /// Check what item is in the result slot of this crafting inventory. + pub fn result( &self, ) -> Result>, Box> { let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getBoots", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getResult", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); @@ -12624,460 +13626,609 @@ impl<'mc> EntityEquipment<'mc> { unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets the boots worn by the entity - pub fn set_boots( - &self, - boots: impl Into>, - silent: std::option::Option, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(boots.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = silent { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")V"; + /// Get the contents of the crafting matrix. + pub fn matrix(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "setBoots", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets all ItemStacks from the armor slots. - pub fn armor_contents( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getArmorContents", - sig.as_str(), - vec![], - ); + .call_method(&self.jni_object(), "getMatrix", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the entities armor to the provided array of ItemStacks - pub fn set_armor_contents( + /// Set the item in the result slot of the crafting inventory. + pub fn set_result( &self, - items: impl Into>, + new_result: impl Into>, ) -> Result<(), Box> { let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) + jni::objects::JObject::from_raw(new_result.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setArmorContents", + "setResult", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Clears the entity of all armor and held items - pub fn clear(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clear", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - - pub fn item_in_hand_drop_chance(&self) -> Result> { - let sig = String::from("()F"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getItemInHandDropChance", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - #[deprecated] - - pub fn set_item_in_hand_drop_chance( + /// Replace the contents of the crafting matrix + pub fn set_matrix( &self, - chance: f32, + contents: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(chance); + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(contents.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemInHandDropChance", + "setMatrix", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the chance of the main hand item being dropped upon this creature's - /// death. - ///
      - ///
    • A drop chance of 0.0F will never drop - ///
    • A drop chance of 1.0F will always drop - ///
    - pub fn item_in_main_hand_drop_chance(&self) -> Result> { - let sig = String::from("()F"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getItemInMainHandDropChance", - sig.as_str(), - vec![], - ); + /// Get the current recipe formed on the crafting inventory, if any. + pub fn recipe( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Recipe;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRecipe", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::Recipe::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the chance of the item this creature is currently holding in their - /// main hand being dropped upon this creature's death. + /// Returns the size of the inventory + pub fn size(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the maximum stack size for an ItemStack in this inventory. + pub fn max_stack_size(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// This method allows you to change the maximum stack size for an + /// inventory. + /// + /// Caveats: ///
      - ///
    • A drop chance of 0.0F will never drop - ///
    • A drop chance of 1.0F will always drop + ///
    • Not all inventories respect this value. + ///
    • Stacks larger than 127 may be clipped when the world is saved. + ///
    • This value is not guaranteed to be preserved; be sure to set it + /// before every time you want to set a slot over the max stack size. + ///
    • Stacks larger than the default max size for this type of inventory + /// may not display correctly in the client. ///
    - pub fn set_item_in_main_hand_drop_chance( - &self, - chance: f32, - ) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(chance); + pub fn set_max_stack_size(&self, size: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(size); let res = self.jni_ref().call_method( &self.jni_object(), - "setItemInMainHandDropChance", + "setMaxStackSize", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the chance of the off hand item being dropped upon this creature's - /// death. - ///
      - ///
    • A drop chance of 0.0F will never drop - ///
    • A drop chance of 1.0F will always drop - ///
    - pub fn item_in_off_hand_drop_chance(&self) -> Result> { - let sig = String::from("()F"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getItemInOffHandDropChance", - sig.as_str(), - vec![], - ); + /// Returns the ItemStack found in the slot at the given index + pub fn get_item( + &self, + index: i32, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(index); + args.push(val_1); + sig += ")Lorg/bukkit/inventory/ItemStack;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the chance of the off hand item being dropped upon this creature's - /// death. - ///
      - ///
    • A drop chance of 0.0F will never drop - ///
    • A drop chance of 1.0F will always drop - ///
    - pub fn set_item_in_off_hand_drop_chance( + /// Stores the ItemStack at the given index of the inventory. + pub fn set_item( &self, - chance: f32, + index: i32, + item: std::option::Option>>, ) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(chance); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setItemInOffHandDropChance", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(index); + args.push(val_1); + if let Some(a) = item { + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setItem", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the chance of the helmet being dropped upon this creature's death. - ///
      - ///
    • A drop chance of 0.0F will never drop - ///
    • A drop chance of 1.0F will always drop - ///
    - pub fn helmet_drop_chance(&self) -> Result> { - let sig = String::from("()F"); + /// Stores the given ItemStacks in the inventory. This will try to fill + /// existing stacks and empty slots as well as it can. + /// + /// The returned HashMap contains what it couldn't store, where the key is + /// the index of the parameter, and the value is the ItemStack at that + /// index of the varargs parameter. If all items are stored, it will return + /// an empty HashMap. + /// + /// If you pass in ItemStacks which exceed the maximum stack size for the + /// Material, first they will be added to partial stacks where + /// Material.getMaxStackSize() is not exceeded, up to + /// Material.getMaxStackSize(). When there are no partial stacks left + /// stacks will be split on Inventory.getMaxStackSize() allowing you to + /// exceed the maximum stack size for that material. + /// + /// It is known that in some implementations this method will also set + /// the inputted argument amount to the number of that item not placed in + /// slots. + pub fn add_item( + &self, + items: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/HashMap;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(items.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getHelmetDropChance", + "addItem", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the chance of the helmet being dropped upon this creature's death. - ///
      - ///
    • A drop chance of 0.0F will never drop - ///
    • A drop chance of 1.0F will always drop - ///
    - pub fn set_helmet_drop_chance(&self, chance: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(chance); + /// Removes the given ItemStacks from the inventory. + /// + /// It will try to remove 'as much as possible' from the types and amounts + /// you give as arguments. + /// + /// The returned HashMap contains what it couldn't remove, where the key is + /// the index of the parameter, and the value is the ItemStack at that + /// index of the varargs parameter. If all the given ItemStacks are + /// removed, it will return an empty HashMap. + /// + /// It is known that in some implementations this method will also set the + /// inputted argument amount to the number of that item not removed from + /// slots. + pub fn remove_item( + &self, + items: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/HashMap;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(items.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setHelmetDropChance", + "removeItem", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the chance of the chest plate being dropped upon this creature's - /// death. - ///
      - ///
    • A drop chance of 0.0F will never drop - ///
    • A drop chance of 1.0F will always drop - ///
    - pub fn chestplate_drop_chance(&self) -> Result> { - let sig = String::from("()F"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getChestplateDropChance", - sig.as_str(), - vec![], - ); + /// Returns all ItemStacks from the inventory + pub fn contents(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getContents", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the chance of the chest plate being dropped upon this creature's - /// death. - ///
      - ///
    • A drop chance of 0.0F will never drop - ///
    • A drop chance of 1.0F will always drop - ///
    - pub fn set_chestplate_drop_chance( + /// Completely replaces the inventory's contents. Removes all existing + /// contents and replaces it with the ItemStacks given in the array. + pub fn set_contents( &self, - chance: f32, + items: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(chance); + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(items.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setChestplateDropChance", + "setContents", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the chance of the leggings being dropped upon this creature's - /// death. - ///
      - ///
    • A drop chance of 0.0F will never drop - ///
    • A drop chance of 1.0F will always drop - ///
    - pub fn leggings_drop_chance(&self) -> Result> { - let sig = String::from("()F"); + /// Return the contents from the section of the inventory where items can + /// reasonably be expected to be stored. In most cases this will represent + /// the entire inventory, but in some cases it may exclude armor or result + /// slots. + /// + /// It is these contents which will be used for add / contains / remove + /// methods which look for a specific stack. + pub fn storage_contents( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getLeggingsDropChance", + "getStorageContents", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the chance of the leggings being dropped upon this creature's - /// death. - ///
      - ///
    • A drop chance of 0.0F will never drop - ///
    • A drop chance of 1.0F will always drop - ///
    - pub fn set_leggings_drop_chance(&self, chance: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(chance); + /// Put the given ItemStacks into the storage slots + pub fn set_storage_contents( + &self, + items: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(items.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setLeggingsDropChance", + "setStorageContents", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the chance of the boots being dropped upon this creature's death. - ///
      - ///
    • A drop chance of 0.0F will never drop - ///
    • A drop chance of 1.0F will always drop - ///
    - pub fn boots_drop_chance(&self) -> Result> { - let sig = String::from("()F"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getBootsDropChance", - sig.as_str(), - vec![], - ); + /// Checks if the inventory contains any ItemStacks with the given + /// material, adding to at least the minimum amount specified. + pub fn contains( + &self, + material: impl Into>, + amount: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = amount { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "contains", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + Ok(res.z()?) } - /// Sets the chance of the boots being dropped upon this creature's death. - ///
      - ///
    • A drop chance of 0.0F will never drop - ///
    • A drop chance of 1.0F will always drop - ///
    - pub fn set_boots_drop_chance(&self, chance: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(chance); + /// Checks if the inventory contains ItemStacks matching the given + /// ItemStack whose amounts sum to at least the minimum amount specified. + pub fn contains_at_least( + &self, + item: impl Into>, + amount: i32, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;I)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "setBootsDropChance", + "containsAtLeast", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Get the entity this EntityEquipment belongs to - pub fn holder(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); + /// Finds all slots in the inventory containing any ItemStacks with the + /// given ItemStack. This will only match slots if both the type and the + /// amount of the stack match + /// + /// The HashMap contains entries where, the key is the slot index, and the + /// value is the ItemStack in that slot. If no matching ItemStack with the + /// given Material is found, an empty map is returned. + pub fn all( + &self, + item: impl Into>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Ljava/util/HashMap;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getHolder", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "all", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct StonecutterInventory<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for StonecutterInventory<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for StonecutterInventory<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate StonecutterInventory from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/StonecutterInventory")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a StonecutterInventory object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} - -impl<'mc> StonecutterInventory<'mc> { - /// Returns the size of the inventory - pub fn size(&self) -> Result> { - let sig = String::from("()I"); + /// Returns the first slot in the inventory containing an ItemStack with + /// the given stack. This will only match a slot if both the type and the + /// amount of the stack match + pub fn first( + &self, + item: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")I"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "first", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Returns the maximum stack size for an ItemStack in this inventory. - pub fn max_stack_size(&self) -> Result> { + /// Returns the first empty Slot. + pub fn first_empty(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "firstEmpty", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// This method allows you to change the maximum stack size for an - /// inventory. + /// Check whether or not this inventory is empty. An inventory is considered + /// to be empty if there are no ItemStacks in any slot of this inventory. + pub fn is_empty(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Removes all stacks in the inventory matching the given stack. /// - /// Caveats: - ///
      - ///
    • Not all inventories respect this value. - ///
    • Stacks larger than 127 may be clipped when the world is saved. - ///
    • This value is not guaranteed to be preserved; be sure to set it - /// before every time you want to set a slot over the max stack size. - ///
    • Stacks larger than the default max size for this type of inventory - /// may not display correctly in the client. - ///
    - pub fn set_max_stack_size(&self, size: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(size); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaxStackSize", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// This will only match a slot if both the type and the amount of the + /// stack match + pub fn remove( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the ItemStack found in the slot at the given index - pub fn get_item( - &self, - index: i32, - ) -> Result>, Box> { + /// Clears out a particular slot in the index. + pub fn clear(&self, index: std::option::Option) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(index); - args.push(val_1); - sig += ")Lorg/bukkit/inventory/ItemStack;"; + if let Some(a) = index { + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(a); + args.push(val_1); + } + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), args); + .call_method(&self.jni_object(), "clear", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets a list of players viewing the inventory. Note that a player is + /// considered to be viewing their own inventory and internal crafting + /// screen even when said inventory is not open. They will normally be + /// considered to be viewing their inventory even when they have a + /// different inventory screen open, but it's possible for customized + /// inventory screens to exclude the viewer's inventory, so this should + /// never be assumed to be non-empty. + pub fn viewers( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getViewers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::HumanEntity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Returns what type of inventory this is. + pub fn get_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the block or entity belonging to the open inventory + pub fn holder( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/InventoryHolder;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHolder", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::InventoryHolder::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + + pub fn iterator( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/ListIterator;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "iterator", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaListIterator::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the location of the block or entity which corresponds to this inventory. May return null if this container + /// was custom created or is a virtual / subcontainer. + pub fn location(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Stores the ItemStack at the given index of the inventory. + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for CraftingInventory<'mc> { + fn into(self) -> crate::inventory::Inventory<'mc> { + crate::inventory::Inventory::from_raw(&self.jni_ref(), self.1) + .expect("Error converting CraftingInventory into crate::inventory::Inventory") + } +} +#[repr(C)] +pub struct EntityEquipment<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for EntityEquipment<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for EntityEquipment<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate EntityEquipment from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/EntityEquipment")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EntityEquipment object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> EntityEquipment<'mc> { + /// Stores the ItemStack at the given equipment slot in the inventory. pub fn set_item( &self, - index: i32, - item: std::option::Option>>, + slot: impl Into>, + item: impl Into>, + silent: std::option::Option, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(index); + sig += "Lorg/bukkit/inventory/EquipmentSlot;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(slot.into().jni_object().clone()) + }); args.push(val_1); - if let Some(a) = item { - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_2); + if let Some(a) = silent { + sig += "Z"; + let val_3 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_3); } sig += ")V"; let res = self @@ -13086,119 +14237,78 @@ impl<'mc> StonecutterInventory<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Stores the given ItemStacks in the inventory. This will try to fill - /// existing stacks and empty slots as well as it can. - /// - /// The returned HashMap contains what it couldn't store, where the key is - /// the index of the parameter, and the value is the ItemStack at that - /// index of the varargs parameter. If all items are stored, it will return - /// an empty HashMap. - /// - /// If you pass in ItemStacks which exceed the maximum stack size for the - /// Material, first they will be added to partial stacks where - /// Material.getMaxStackSize() is not exceeded, up to - /// Material.getMaxStackSize(). When there are no partial stacks left - /// stacks will be split on Inventory.getMaxStackSize() allowing you to - /// exceed the maximum stack size for that material. - /// - /// It is known that in some implementations this method will also set - /// the inputted argument amount to the number of that item not placed in - /// slots. - pub fn add_item( + /// Gets the ItemStack at the given equipment slot in the inventory. + pub fn get_item( &self, - items: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/HashMap;"); + slot: impl Into>, + ) -> Result, Box> { + let sig = + String::from("(Lorg/bukkit/inventory/EquipmentSlot;)Lorg/bukkit/inventory/ItemStack;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) + jni::objects::JObject::from_raw(slot.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "addItem", + "getItem", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Removes the given ItemStacks from the inventory. - /// - /// It will try to remove 'as much as possible' from the types and amounts - /// you give as arguments. - /// - /// The returned HashMap contains what it couldn't remove, where the key is - /// the index of the parameter, and the value is the ItemStack at that - /// index of the varargs parameter. If all the given ItemStacks are - /// removed, it will return an empty HashMap. - /// - /// It is known that in some implementations this method will also set the - /// inputted argument amount to the number of that item not removed from - /// slots. - pub fn remove_item( + /// Gets a copy of the item the entity is currently holding + /// in their main hand. + pub fn item_in_main_hand( &self, - items: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/HashMap;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) - }); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self.jni_ref().call_method( &self.jni_object(), - "removeItem", + "getItemInMainHand", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns all ItemStacks from the inventory - pub fn contents(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getContents", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Completely replaces the inventory's contents. Removes all existing - /// contents and replaces it with the ItemStacks given in the array. - pub fn set_contents( + /// Sets the item the entity is holding in their main hand. + pub fn set_item_in_main_hand( &self, - items: impl Into>, + item: impl Into>, + silent: std::option::Option, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) + jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setContents", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + if let Some(a) = silent { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setItemInMainHand", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Return the contents from the section of the inventory where items can - /// reasonably be expected to be stored. In most cases this will represent - /// the entire inventory, but in some cases it may exclude armor or result - /// slots. - /// - /// It is these contents which will be used for add / contains / remove - /// methods which look for a specific stack. - pub fn storage_contents( + /// Gets a copy of the item the entity is currently holding + /// in their off hand. + pub fn item_in_off_hand( &self, ) -> Result, Box> { let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getStorageContents", + "getItemInOffHand", sig.as_str(), vec![], ); @@ -13207,534 +14317,534 @@ impl<'mc> StonecutterInventory<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Put the given ItemStacks into the storage slots - pub fn set_storage_contents( + /// Sets the item the entity is holding in their off hand. + pub fn set_item_in_off_hand( &self, - items: impl Into>, + item: impl Into>, + silent: std::option::Option, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setStorageContents", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks if the inventory contains any ItemStacks with the given - /// material, adding to at least the minimum amount specified. - pub fn contains( - &self, - material: impl Into>, - amount: std::option::Option, - ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; + sig += "Lorg/bukkit/inventory/ItemStack;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) + jni::objects::JObject::from_raw(item.into().jni_object().clone()) }); args.push(val_1); - if let Some(a) = amount { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); + if let Some(a) = silent { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); args.push(val_2); } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "contains", sig.as_str(), args); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setItemInOffHand", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets a copy of the item the entity is currently holding + pub fn item_in_hand( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemInHand", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Checks if the inventory contains ItemStacks matching the given - /// ItemStack whose amounts sum to at least the minimum amount specified. - pub fn contains_at_least( + #[deprecated] + /// Sets the item the entity is holding + pub fn set_item_in_hand( &self, - item: impl Into>, - amount: i32, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;I)Z"); + stack: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(stack.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "containsAtLeast", + "setItemInHand", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Finds all slots in the inventory containing any ItemStacks with the - /// given ItemStack. This will only match slots if both the type and the - /// amount of the stack match - /// - /// The HashMap contains entries where, the key is the slot index, and the - /// value is the ItemStack in that slot. If no matching ItemStack with the - /// given Material is found, an empty map is returned. - pub fn all( + /// Gets a copy of the helmet currently being worn by the entity + pub fn helmet( &self, - item: impl Into>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Ljava/util/HashMap;"; + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "all", sig.as_str(), args); + .call_method(&self.jni_object(), "getHelmet", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Returns the first slot in the inventory containing an ItemStack with - /// the given stack. This will only match a slot if both the type and the - /// amount of the stack match - pub fn first( + /// Sets the helmet worn by the entity + pub fn set_helmet( &self, - item: impl Into>, - ) -> Result> { + helmet: impl Into>, + silent: std::option::Option, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "Lorg/bukkit/inventory/ItemStack;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(helmet.into().jni_object().clone()) }); args.push(val_1); - sig += ")I"; + if let Some(a) = silent { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "first", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + .call_method(&self.jni_object(), "setHelmet", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns the first empty Slot. - pub fn first_empty(&self) -> Result> { - let sig = String::from("()I"); + /// Gets a copy of the chest plate currently being worn by the entity + pub fn chestplate( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "firstEmpty", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Check whether or not this inventory is empty. An inventory is considered - /// to be empty if there are no ItemStacks in any slot of this inventory. - pub fn is_empty(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getChestplate", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Removes all stacks in the inventory matching the given stack. - /// - /// This will only match a slot if both the type and the amount of the - /// stack match - pub fn remove( + /// Sets the chest plate worn by the entity + pub fn set_chestplate( &self, - item: impl Into>, + chestplate: impl Into>, + silent: std::option::Option, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "Lorg/bukkit/inventory/ItemStack;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(chestplate.into().jni_object().clone()) }); args.push(val_1); + if let Some(a) = silent { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), args); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setChestplate", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Clears out a particular slot in the index. - pub fn clear(&self, index: std::option::Option) -> Result<(), Box> { + /// Gets a copy of the leggings currently being worn by the entity + pub fn leggings( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLeggings", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets the leggings worn by the entity + pub fn set_leggings( + &self, + leggings: impl Into>, + silent: std::option::Option, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = index { - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(a); - args.push(val_1); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(leggings.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = silent { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); } sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "clear", sig.as_str(), args); + .call_method(&self.jni_object(), "setLeggings", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets a list of players viewing the inventory. Note that a player is - /// considered to be viewing their own inventory and internal crafting - /// screen even when said inventory is not open. They will normally be - /// considered to be viewing their inventory even when they have a - /// different inventory screen open, but it's possible for customized - /// inventory screens to exclude the viewer's inventory, so this should - /// never be assumed to be non-empty. - pub fn viewers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getViewers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::HumanEntity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Returns what type of inventory this is. - pub fn get_type( + /// Gets a copy of the boots currently being worn by the entity + pub fn boots( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBoots", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::event::inventory::InventoryType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets the block or entity belonging to the open inventory - pub fn holder( + /// Sets the boots worn by the entity + pub fn set_boots( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/InventoryHolder;"); + boots: impl Into>, + silent: std::option::Option, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(boots.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = silent { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getHolder", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::InventoryHolder::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + .call_method(&self.jni_object(), "setBoots", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - - pub fn iterator( + /// Gets all ItemStacks from the armor slots. + pub fn armor_contents( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/ListIterator;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "iterator", sig.as_str(), vec![]); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getArmorContents", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaListIterator::from_raw(&self.jni_ref(), unsafe { + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the location of the block or entity which corresponds to this inventory. May return null if this container - /// was custom created or is a virtual / subcontainer. - pub fn location(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + /// Sets the entities armor to the provided array of ItemStacks + pub fn set_armor_contents( + &self, + items: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(items.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setArmorContents", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -impl<'mc> Into> for StonecutterInventory<'mc> { - fn into(self) -> crate::inventory::Inventory<'mc> { - crate::inventory::Inventory::from_raw(&self.jni_ref(), self.1) - .expect("Error converting StonecutterInventory into crate::inventory::Inventory") + /// Clears the entity of all armor and held items + pub fn clear(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clear", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -#[repr(C)] -pub struct ItemFactory<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); + #[deprecated] -impl<'mc> JNIRaw<'mc> for ItemFactory<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + pub fn item_in_hand_drop_chance(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItemInHandDropChance", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + #[deprecated] + + pub fn set_item_in_hand_drop_chance( + &self, + chance: f32, + ) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(chance); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItemInHandDropChance", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -impl<'mc> JNIInstantiatable<'mc> for ItemFactory<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ItemFactory from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/ItemFactory")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ItemFactory object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Gets the chance of the main hand item being dropped upon this creature's + /// death. + ///
      + ///
    • A drop chance of 0.0F will never drop + ///
    • A drop chance of 1.0F will always drop + ///
    + pub fn item_in_main_hand_drop_chance(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItemInMainHandDropChance", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) } -} - -impl<'mc> ItemFactory<'mc> { - /// This creates a new item meta for the material. - pub fn get_item_meta( + /// Sets the chance of the item this creature is currently holding in their + /// main hand being dropped upon this creature's death. + ///
      + ///
    • A drop chance of 0.0F will never drop + ///
    • A drop chance of 1.0F will always drop + ///
    + pub fn set_item_in_main_hand_drop_chance( &self, - material: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Material;)Lorg/bukkit/inventory/meta/ItemMeta;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); + chance: f32, + ) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(chance); let res = self.jni_ref().call_method( &self.jni_object(), - "getItemMeta", + "setItemInMainHandDropChance", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the chance of the off hand item being dropped upon this creature's + /// death. + ///
      + ///
    • A drop chance of 0.0F will never drop + ///
    • A drop chance of 1.0F will always drop + ///
    + pub fn item_in_off_hand_drop_chance(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItemInOffHandDropChance", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::meta::ItemMeta::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.f()?) } - /// This method checks the item meta to confirm that it is applicable (no - /// data lost if applied) to the specified Material. - /// - /// A {@link SkullMeta} would not be valid for a sword, but a normal {@link - /// ItemMeta} from an enchanted dirt block would. - pub fn is_applicable( + /// Sets the chance of the off hand item being dropped upon this creature's + /// death. + ///
      + ///
    • A drop chance of 0.0F will never drop + ///
    • A drop chance of 1.0F will always drop + ///
    + pub fn set_item_in_off_hand_drop_chance( &self, - meta: impl Into>, - material: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/meta/ItemMeta;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(meta.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/Material;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - args.push(val_2); - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isApplicable", sig.as_str(), args); + chance: f32, + ) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(chance); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItemInOffHandDropChance", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the chance of the helmet being dropped upon this creature's death. + ///
      + ///
    • A drop chance of 0.0F will never drop + ///
    • A drop chance of 1.0F will always drop + ///
    + pub fn helmet_drop_chance(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getHelmetDropChance", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.f()?) } - /// This method is used to compare two item meta data objects. - pub fn equals( - &self, - meta1: impl Into>, - meta2: impl Into>, - ) -> Result> { - let sig = String::from( - "(Lorg/bukkit/inventory/meta/ItemMeta;Lorg/bukkit/inventory/meta/ItemMeta;)Z", + /// Sets the chance of the helmet being dropped upon this creature's death. + ///
      + ///
    • A drop chance of 0.0F will never drop + ///
    • A drop chance of 1.0F will always drop + ///
    + pub fn set_helmet_drop_chance(&self, chance: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(chance); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setHelmetDropChance", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(meta1.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(meta2.into().jni_object().clone()) - }); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the chance of the chest plate being dropped upon this creature's + /// death. + ///
      + ///
    • A drop chance of 0.0F will never drop + ///
    • A drop chance of 1.0F will always drop + ///
    + pub fn chestplate_drop_chance(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref().call_method( &self.jni_object(), - "equals", + "getChestplateDropChance", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.f()?) } - /// Returns an appropriate item meta for the specified material. - /// - /// The item meta returned will always be a valid meta for a given - /// ItemStack of the specified material. It may be a more or less specific - /// meta, and could also be the same meta or meta type as the parameter. - /// The item meta returned will also always be the most appropriate meta. - /// - /// Example, if a {@link SkullMeta} is being applied to a book, this method - /// would return a {@link BookMeta} containing all information in the - /// specified meta that is applicable to an {@link ItemMeta}, the highest - /// common interface. - pub fn as_meta_for( + /// Sets the chance of the chest plate being dropped upon this creature's + /// death. + ///
      + ///
    • A drop chance of 0.0F will never drop + ///
    • A drop chance of 1.0F will always drop + ///
    + pub fn set_chestplate_drop_chance( &self, - meta: impl Into>, - material: impl Into>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/meta/ItemMeta;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(meta.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/Material;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - args.push(val_2); - sig += ")Lorg/bukkit/inventory/meta/ItemMeta;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "asMetaFor", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::meta::ItemMeta::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + chance: f32, + ) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(chance); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setChestplateDropChance", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Returns the default color for all leather armor. - pub fn default_leather_color(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Color;"); + /// Gets the chance of the leggings being dropped upon this creature's + /// death. + ///
      + ///
    • A drop chance of 0.0F will never drop + ///
    • A drop chance of 1.0F will always drop + ///
    + pub fn leggings_drop_chance(&self) -> Result> { + let sig = String::from("()F"); let res = self.jni_ref().call_method( &self.jni_object(), - "getDefaultLeatherColor", + "getLeggingsDropChance", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::Color::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.f()?) } - /// Create a new {@link ItemStack} given the supplied input. - /// - /// The input should match the same input as expected by Minecraft's {@code /give} - /// command. For example, - ///
    "minecraft:diamond_sword[minecraft:enchantments={levels:{"minecraft:sharpness": 3}}]"
    - /// would yield an ItemStack of {@link Material#DIAMOND_SWORD} with an {@link ItemMeta} - /// containing a level 3 {@link Enchantment#SHARPNESS} enchantment. - pub fn create_item_stack( - &self, - input: impl Into, - ) -> Result, Box> { - let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/inventory/ItemStack;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(input.into())?, - )); + /// Sets the chance of the leggings being dropped upon this creature's + /// death. + ///
      + ///
    • A drop chance of 0.0F will never drop + ///
    • A drop chance of 1.0F will always drop + ///
    + pub fn set_leggings_drop_chance(&self, chance: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(chance); let res = self.jni_ref().call_method( &self.jni_object(), - "createItemStack", + "setLeggingsDropChance", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the chance of the boots being dropped upon this creature's death. + ///
      + ///
    • A drop chance of 0.0F will never drop + ///
    • A drop chance of 1.0F will always drop + ///
    + pub fn boots_drop_chance(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBootsDropChance", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.f()?) } - /// Gets a {@link Material} representing the spawn egg for the provided - /// {@link EntityType}. - /// - /// Will return null for EntityTypes that do not have a corresponding spawn egg. - pub fn get_spawn_egg( - &self, - val_type: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/entity/EntityType;)Lorg/bukkit/Material;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); + /// Sets the chance of the boots being dropped upon this creature's death. + ///
      + ///
    • A drop chance of 0.0F will never drop + ///
    • A drop chance of 1.0F will always drop + ///
    + pub fn set_boots_drop_chance(&self, chance: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(chance); let res = self.jni_ref().call_method( &self.jni_object(), - "getSpawnEgg", + "setBootsDropChance", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Enchants the given item at the provided level. - /// - /// If an item that is air is passed through an error is thrown. - pub fn enchant_item( - &self, - world: impl Into>, - item: impl Into>, - level: i32, - allow_treasures: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/World;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - args.push(val_2); - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(level); - args.push(val_3); - if let Some(a) = allow_treasures { - sig += "Z"; - let val_4 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_4); - } - sig += ")Lorg/bukkit/inventory/ItemStack;"; + /// Get the entity this EntityEquipment belongs to + pub fn holder(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "enchantItem", sig.as_str(), args); + .call_method(&self.jni_object(), "getHolder", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -13743,12 +14853,12 @@ impl<'mc> ItemFactory<'mc> { } } #[repr(C)] -pub struct BlockInventoryHolder<'mc>( +pub struct StonecutterInventory<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockInventoryHolder<'mc> { +impl<'mc> JNIRaw<'mc> for StonecutterInventory<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -13756,20 +14866,20 @@ impl<'mc> JNIRaw<'mc> for BlockInventoryHolder<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockInventoryHolder<'mc> { +impl<'mc> JNIInstantiatable<'mc> for StonecutterInventory<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate BlockInventoryHolder from null object.").into(), + eyre::eyre!("Tried to instantiate StonecutterInventory from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/BlockInventoryHolder")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/StonecutterInventory")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockInventoryHolder object, got {}", + "Invalid argument passed. Expected a StonecutterInventory object, got {}", name ) .into()) @@ -13779,402 +14889,592 @@ impl<'mc> JNIInstantiatable<'mc> for BlockInventoryHolder<'mc> { } } -impl<'mc> BlockInventoryHolder<'mc> { - /// Gets the block associated with this holder. - pub fn block(&self) -> Result, Box> { - let args = Vec::new(); +impl<'mc> StonecutterInventory<'mc> { + /// Returns the size of the inventory + pub fn size(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the maximum stack size for an ItemStack in this inventory. + pub fn max_stack_size(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// This method allows you to change the maximum stack size for an + /// inventory. + /// + /// Caveats: + ///
      + ///
    • Not all inventories respect this value. + ///
    • Stacks larger than 127 may be clipped when the world is saved. + ///
    • This value is not guaranteed to be preserved; be sure to set it + /// before every time you want to set a slot over the max stack size. + ///
    • Stacks larger than the default max size for this type of inventory + /// may not display correctly in the client. + ///
    + pub fn set_max_stack_size(&self, size: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(size); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaxStackSize", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the ItemStack found in the slot at the given index + pub fn get_item( + &self, + index: i32, + ) -> Result>, Box> { + let mut args = Vec::new(); let mut sig = String::from("("); - sig += ")Lorg/bukkit/block/Block;"; + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(index); + args.push(val_1); + sig += ")Lorg/bukkit/inventory/ItemStack;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getBlock", sig.as_str(), args); + .call_method(&self.jni_object(), "getItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Stores the ItemStack at the given index of the inventory. + pub fn set_item( + &self, + index: i32, + item: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(index); + args.push(val_1); + if let Some(a) = item { + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setItem", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Stores the given ItemStacks in the inventory. This will try to fill + /// existing stacks and empty slots as well as it can. + /// + /// The returned HashMap contains what it couldn't store, where the key is + /// the index of the parameter, and the value is the ItemStack at that + /// index of the varargs parameter. If all items are stored, it will return + /// an empty HashMap. + /// + /// If you pass in ItemStacks which exceed the maximum stack size for the + /// Material, first they will be added to partial stacks where + /// Material.getMaxStackSize() is not exceeded, up to + /// Material.getMaxStackSize(). When there are no partial stacks left + /// stacks will be split on Inventory.getMaxStackSize() allowing you to + /// exceed the maximum stack size for that material. + /// + /// It is known that in some implementations this method will also set + /// the inputted argument amount to the number of that item not placed in + /// slots. + pub fn add_item( + &self, + items: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/HashMap;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(items.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the object's inventory. - pub fn inventory( + /// Removes the given ItemStacks from the inventory. + /// + /// It will try to remove 'as much as possible' from the types and amounts + /// you give as arguments. + /// + /// The returned HashMap contains what it couldn't remove, where the key is + /// the index of the parameter, and the value is the ItemStack at that + /// index of the varargs parameter. If all the given ItemStacks are + /// removed, it will return an empty HashMap. + /// + /// It is known that in some implementations this method will also set the + /// inputted argument amount to the number of that item not removed from + /// slots. + pub fn remove_item( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + items: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/HashMap;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(items.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns all ItemStacks from the inventory + pub fn contents(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getContents", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for BlockInventoryHolder<'mc> { - fn into(self) -> crate::inventory::InventoryHolder<'mc> { - crate::inventory::InventoryHolder::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockInventoryHolder into crate::inventory::InventoryHolder") - } -} -#[repr(C)] -pub struct MerchantInventory<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for MerchantInventory<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for MerchantInventory<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate MerchantInventory from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/MerchantInventory")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a MerchantInventory object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Completely replaces the inventory's contents. Removes all existing + /// contents and replaces it with the ItemStacks given in the array. + pub fn set_contents( + &self, + items: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(items.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setContents", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> MerchantInventory<'mc> { - /// Get the index of the currently selected recipe. - pub fn selected_recipe_index(&self) -> Result> { - let sig = String::from("()I"); + /// Return the contents from the section of the inventory where items can + /// reasonably be expected to be stored. In most cases this will represent + /// the entire inventory, but in some cases it may exclude armor or result + /// slots. + /// + /// It is these contents which will be used for add / contains / remove + /// methods which look for a specific stack. + pub fn storage_contents( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getSelectedRecipeIndex", + "getStorageContents", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get the currently active recipe. - /// - /// This will be null if the items provided by the player do - /// not match the ingredients of the selected recipe. This does not - /// necessarily match the recipe selected by the player: If the player has - /// selected the first recipe, the merchant will search all of its offers - /// for a matching recipe to activate. - pub fn selected_recipe( + /// Put the given ItemStacks into the storage slots + pub fn set_storage_contents( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/MerchantRecipe;"); + items: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(items.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getSelectedRecipe", + "setStorageContents", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if the inventory contains any ItemStacks with the given + /// material, adding to at least the minimum amount specified. + pub fn contains( + &self, + material: impl Into>, + amount: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = amount { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); } - Ok(Some(crate::inventory::MerchantRecipe::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "contains", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the Merchant associated with this inventory. - pub fn merchant(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/Merchant;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMerchant", sig.as_str(), vec![]); + /// Checks if the inventory contains ItemStacks matching the given + /// ItemStack whose amounts sum to at least the minimum amount specified. + pub fn contains_at_least( + &self, + item: impl Into>, + amount: i32, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;I)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(amount); + let res = self.jni_ref().call_method( + &self.jni_object(), + "containsAtLeast", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Merchant::from_raw(&self.jni_ref(), unsafe { + Ok(res.z()?) + } + /// Finds all slots in the inventory containing any ItemStacks with the + /// given ItemStack. This will only match slots if both the type and the + /// amount of the stack match + /// + /// The HashMap contains entries where, the key is the slot index, and the + /// value is the ItemStack in that slot. If no matching ItemStack with the + /// given Material is found, an empty map is returned. + pub fn all( + &self, + item: impl Into>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Ljava/util/HashMap;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "all", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns the size of the inventory - pub fn size(&self) -> Result> { - let sig = String::from("()I"); + /// Returns the first slot in the inventory containing an ItemStack with + /// the given stack. This will only match a slot if both the type and the + /// amount of the stack match + pub fn first( + &self, + item: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")I"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "first", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Returns the maximum stack size for an ItemStack in this inventory. - pub fn max_stack_size(&self) -> Result> { + /// Returns the first empty Slot. + pub fn first_empty(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "firstEmpty", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// This method allows you to change the maximum stack size for an - /// inventory. + /// Check whether or not this inventory is empty. An inventory is considered + /// to be empty if there are no ItemStacks in any slot of this inventory. + pub fn is_empty(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Removes all stacks in the inventory matching the given stack. /// - /// Caveats: - ///
      - ///
    • Not all inventories respect this value. - ///
    • Stacks larger than 127 may be clipped when the world is saved. - ///
    • This value is not guaranteed to be preserved; be sure to set it - /// before every time you want to set a slot over the max stack size. - ///
    • Stacks larger than the default max size for this type of inventory - /// may not display correctly in the client. - ///
    - pub fn set_max_stack_size(&self, size: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(size); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMaxStackSize", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// This will only match a slot if both the type and the amount of the + /// stack match + pub fn remove( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns the ItemStack found in the slot at the given index - pub fn get_item( - &self, - index: i32, - ) -> Result>, Box> { + /// Clears out a particular slot in the index. + pub fn clear(&self, index: std::option::Option) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(index); - args.push(val_1); - sig += ")Lorg/bukkit/inventory/ItemStack;"; + if let Some(a) = index { + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(a); + args.push(val_1); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clear", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets a list of players viewing the inventory. Note that a player is + /// considered to be viewing their own inventory and internal crafting + /// screen even when said inventory is not open. They will normally be + /// considered to be viewing their inventory even when they have a + /// different inventory screen open, but it's possible for customized + /// inventory screens to exclude the viewer's inventory, so this should + /// never be assumed to be non-empty. + pub fn viewers( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getViewers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::HumanEntity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Returns what type of inventory this is. + pub fn get_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the block or entity belonging to the open inventory + pub fn holder( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/InventoryHolder;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getItem", sig.as_str(), args); + .call_method(&self.jni_object(), "getHolder", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::ItemStack::from_raw( + Ok(Some(crate::inventory::InventoryHolder::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Stores the ItemStack at the given index of the inventory. - pub fn set_item( + + pub fn iterator( &self, - index: i32, - item: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(index); - args.push(val_1); - if let Some(a) = item { - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; + ) -> Result, Box> { + let sig = String::from("()Ljava/util/ListIterator;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "setItem", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Stores the given ItemStacks in the inventory. This will try to fill - /// existing stacks and empty slots as well as it can. - /// - /// The returned HashMap contains what it couldn't store, where the key is - /// the index of the parameter, and the value is the ItemStack at that - /// index of the varargs parameter. If all items are stored, it will return - /// an empty HashMap. - /// - /// If you pass in ItemStacks which exceed the maximum stack size for the - /// Material, first they will be added to partial stacks where - /// Material.getMaxStackSize() is not exceeded, up to - /// Material.getMaxStackSize(). When there are no partial stacks left - /// stacks will be split on Inventory.getMaxStackSize() allowing you to - /// exceed the maximum stack size for that material. - /// - /// It is known that in some implementations this method will also set - /// the inputted argument amount to the number of that item not placed in - /// slots. - pub fn add_item( - &self, - items: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/HashMap;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addItem", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Removes the given ItemStacks from the inventory. - /// - /// It will try to remove 'as much as possible' from the types and amounts - /// you give as arguments. - /// - /// The returned HashMap contains what it couldn't remove, where the key is - /// the index of the parameter, and the value is the ItemStack at that - /// index of the varargs parameter. If all the given ItemStacks are - /// removed, it will return an empty HashMap. - /// - /// It is known that in some implementations this method will also set the - /// inputted argument amount to the number of that item not removed from - /// slots. - pub fn remove_item( - &self, - items: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/HashMap;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removeItem", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "iterator", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaListIterator::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns all ItemStacks from the inventory - pub fn contents(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + /// Get the location of the block or entity which corresponds to this inventory. May return null if this container + /// was custom created or is a virtual / subcontainer. + pub fn location(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getContents", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) + })?)) } - /// Completely replaces the inventory's contents. Removes all existing - /// contents and replaces it with the ItemStacks given in the array. - pub fn set_contents( - &self, - items: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setContents", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Return the contents from the section of the inventory where items can - /// reasonably be expected to be stored. In most cases this will represent - /// the entire inventory, but in some cases it may exclude armor or result - /// slots. - /// - /// It is these contents which will be used for add / contains / remove - /// methods which look for a specific stack. - pub fn storage_contents( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getStorageContents", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} +impl<'mc> Into> for StonecutterInventory<'mc> { + fn into(self) -> crate::inventory::Inventory<'mc> { + crate::inventory::Inventory::from_raw(&self.jni_ref(), self.1) + .expect("Error converting StonecutterInventory into crate::inventory::Inventory") } - /// Put the given ItemStacks into the storage slots - pub fn set_storage_contents( +} +#[repr(C)] +pub struct ItemFactory<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ItemFactory<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for ItemFactory<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate ItemFactory from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/ItemFactory")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ItemFactory object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> ItemFactory<'mc> { + /// This creates a new item meta for the material. + pub fn get_item_meta( &self, - items: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + material: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Material;)Lorg/bukkit/inventory/meta/ItemMeta;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(items.into().jni_object().clone()) + jni::objects::JObject::from_raw(material.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setStorageContents", + "getItemMeta", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::meta::ItemMeta::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Checks if the inventory contains any ItemStacks with the given - /// material, adding to at least the minimum amount specified. - pub fn contains( + /// This method checks the item meta to confirm that it is applicable (no + /// data lost if applied) to the specified Material. + /// + /// A {@link SkullMeta} would not be valid for a sword, but a normal {@link + /// ItemMeta} from an enchanted dirt block would. + pub fn is_applicable( &self, + meta: impl Into>, material: impl Into>, - amount: std::option::Option, ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; + sig += "Lorg/bukkit/inventory/meta/ItemMeta;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) + jni::objects::JObject::from_raw(meta.into().jni_object().clone()) }); args.push(val_1); - if let Some(a) = amount { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "contains", sig.as_str(), args); + sig += "Lorg/bukkit/Material;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + args.push(val_2); + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isApplicable", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Checks if the inventory contains ItemStacks matching the given - /// ItemStack whose amounts sum to at least the minimum amount specified. - pub fn contains_at_least( + /// This method is used to compare two item meta data objects. + pub fn equals( &self, - item: impl Into>, - amount: i32, + meta1: impl Into>, + meta2: impl Into>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;I)Z"); + let sig = String::from( + "(Lorg/bukkit/inventory/meta/ItemMeta;Lorg/bukkit/inventory/meta/ItemMeta;)Z", + ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(meta1.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(meta2.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "containsAtLeast", + "equals", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), @@ -14184,192 +15484,221 @@ impl<'mc> MerchantInventory<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Finds all slots in the inventory containing any ItemStacks with the - /// given ItemStack. This will only match slots if both the type and the - /// amount of the stack match + /// Returns an appropriate item meta for the specified material. /// - /// The HashMap contains entries where, the key is the slot index, and the - /// value is the ItemStack in that slot. If no matching ItemStack with the - /// given Material is found, an empty map is returned. - pub fn all( + /// The item meta returned will always be a valid meta for a given + /// ItemStack of the specified material. It may be a more or less specific + /// meta, and could also be the same meta or meta type as the parameter. + /// The item meta returned will also always be the most appropriate meta. + /// + /// Example, if a {@link SkullMeta} is being applied to a book, this method + /// would return a {@link BookMeta} containing all information in the + /// specified meta that is applicable to an {@link ItemMeta}, the highest + /// common interface. + pub fn as_meta_for( &self, - item: impl Into>, - ) -> Result, Box> { + meta: impl Into>, + material: impl Into>, + ) -> Result>, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; + sig += "Lorg/bukkit/inventory/meta/ItemMeta;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(meta.into().jni_object().clone()) }); args.push(val_1); - sig += ")Ljava/util/HashMap;"; + sig += "Lorg/bukkit/Material;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + args.push(val_2); + sig += ")Lorg/bukkit/inventory/meta/ItemMeta;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "all", sig.as_str(), args); + .call_method(&self.jni_object(), "asMetaFor", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::meta::ItemMeta::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Returns the default color for all leather armor. + pub fn default_leather_color(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Color;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDefaultLeatherColor", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Color::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns the first slot in the inventory containing an ItemStack with - /// the given stack. This will only match a slot if both the type and the - /// amount of the stack match - pub fn first( + /// Create a new {@link ItemStack} given the supplied input. + /// + /// The input should match the same input as expected by Minecraft's {@code /give} + /// command. For example, + ///
    "minecraft:diamond_sword[minecraft:enchantments={levels:{"minecraft:sharpness": 3}}]"
    + /// would yield an ItemStack of {@link Material#DIAMOND_SWORD} with an {@link ItemMeta} + /// containing a level 3 {@link Enchantment#SHARPNESS} enchantment. + pub fn create_item_stack( &self, - item: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")I"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "first", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Returns the first empty Slot. - pub fn first_empty(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "firstEmpty", sig.as_str(), vec![]); + input: impl Into, + ) -> Result, Box> { + let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/inventory/ItemStack;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(input.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "createItemStack", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Check whether or not this inventory is empty. An inventory is considered - /// to be empty if there are no ItemStacks in any slot of this inventory. - pub fn is_empty(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + /// Gets a {@link Material} representing the spawn egg for the provided + /// {@link EntityType}. + /// + /// Will return null for EntityTypes that do not have a corresponding spawn egg. + pub fn get_spawn_egg( + &self, + val_type: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/entity/EntityType;)Lorg/bukkit/Material;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSpawnEgg", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Removes all stacks in the inventory matching the given stack. + /// Enchants the given item at the provided level. /// - /// This will only match a slot if both the type and the amount of the - /// stack match - pub fn remove( + /// If an item that is air is passed through an error is thrown. + pub fn enchant_item( &self, + world: impl Into>, item: impl Into>, - ) -> Result<(), Box> { + level: i32, + allow_treasures: std::option::Option, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; + sig += "Lorg/bukkit/World;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + jni::objects::JObject::from_raw(world.into().jni_object().clone()) }); args.push(val_1); - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Clears out a particular slot in the index. - pub fn clear(&self, index: std::option::Option) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = index { - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(a); - args.push(val_1); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clear", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets a list of players viewing the inventory. Note that a player is - /// considered to be viewing their own inventory and internal crafting - /// screen even when said inventory is not open. They will normally be - /// considered to be viewing their inventory even when they have a - /// different inventory screen open, but it's possible for customized - /// inventory screens to exclude the viewer's inventory, so this should - /// never be assumed to be non-empty. - pub fn viewers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getViewers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::HumanEntity::from_raw(&self.jni_ref(), obj)?); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_2); + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(level); + args.push(val_3); + if let Some(a) = allow_treasures { + sig += "Z"; + let val_4 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_4); } - Ok(new_vec) - } - /// Returns what type of inventory this is. - pub fn get_type( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType;"); + sig += ")Lorg/bukkit/inventory/ItemStack;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "enchantItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::event::inventory::InventoryType::from_raw(&self.jni_ref(), unsafe { + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the block or entity belonging to the open inventory - pub fn holder( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/InventoryHolder;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHolder", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct BlockInventoryHolder<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for BlockInventoryHolder<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for BlockInventoryHolder<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate BlockInventoryHolder from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/BlockInventoryHolder")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BlockInventoryHolder object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - Ok(Some(crate::inventory::InventoryHolder::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) } +} - pub fn iterator( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/ListIterator;"); +impl<'mc> BlockInventoryHolder<'mc> { + /// Gets the block associated with this holder. + pub fn block(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/block/Block;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "iterator", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBlock", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaListIterator::from_raw(&self.jni_ref(), unsafe { + crate::block::Block::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the location of the block or entity which corresponds to this inventory. May return null if this container - /// was custom created or is a virtual / subcontainer. - pub fn location(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); + /// Get the object's inventory. + pub fn inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getInventory", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -14377,19 +15706,19 @@ impl<'mc> MerchantInventory<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for MerchantInventory<'mc> { - fn into(self) -> crate::inventory::Inventory<'mc> { - crate::inventory::Inventory::from_raw(&self.jni_ref(), self.1) - .expect("Error converting MerchantInventory into crate::inventory::Inventory") +impl<'mc> Into> for BlockInventoryHolder<'mc> { + fn into(self) -> crate::inventory::InventoryHolder<'mc> { + crate::inventory::InventoryHolder::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockInventoryHolder into crate::inventory::InventoryHolder") } } #[repr(C)] -pub struct LecternInventory<'mc>( +pub struct MerchantInventory<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for LecternInventory<'mc> { +impl<'mc> JNIRaw<'mc> for MerchantInventory<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -14397,20 +15726,20 @@ impl<'mc> JNIRaw<'mc> for LecternInventory<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for LecternInventory<'mc> { +impl<'mc> JNIInstantiatable<'mc> for MerchantInventory<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate LecternInventory from null object.").into(), + eyre::eyre!("Tried to instantiate MerchantInventory from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/LecternInventory")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/MerchantInventory")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a LecternInventory object, got {}", + "Invalid argument passed. Expected a MerchantInventory object, got {}", name ) .into()) @@ -14420,21 +15749,56 @@ impl<'mc> JNIInstantiatable<'mc> for LecternInventory<'mc> { } } -impl<'mc> LecternInventory<'mc> { - pub fn holder(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/block/Lectern;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHolder", sig.as_str(), vec![]); +impl<'mc> MerchantInventory<'mc> { + /// Get the index of the currently selected recipe. + pub fn selected_recipe_index(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSelectedRecipeIndex", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Get the currently active recipe. + /// + /// This will be null if the items provided by the player do + /// not match the ingredients of the selected recipe. This does not + /// necessarily match the recipe selected by the player: If the player has + /// selected the first recipe, the merchant will search all of its offers + /// for a matching recipe to activate. + pub fn selected_recipe( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/MerchantRecipe;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSelectedRecipe", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::block::Lectern::from_raw( + Ok(Some(crate::inventory::MerchantRecipe::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } + /// Gets the Merchant associated with this inventory. + pub fn merchant(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Merchant;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMerchant", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Merchant::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } /// Returns the size of the inventory pub fn size(&self) -> Result> { let sig = String::from("()I"); @@ -14856,6 +16220,23 @@ impl<'mc> LecternInventory<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } + /// Gets the block or entity belonging to the open inventory + pub fn holder( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/InventoryHolder;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHolder", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::InventoryHolder::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } pub fn iterator( &self, @@ -14890,19 +16271,19 @@ impl<'mc> LecternInventory<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for LecternInventory<'mc> { +impl<'mc> Into> for MerchantInventory<'mc> { fn into(self) -> crate::inventory::Inventory<'mc> { crate::inventory::Inventory::from_raw(&self.jni_ref(), self.1) - .expect("Error converting LecternInventory into crate::inventory::Inventory") + .expect("Error converting MerchantInventory into crate::inventory::Inventory") } } #[repr(C)] -pub struct BrewerInventory<'mc>( +pub struct LecternInventory<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BrewerInventory<'mc> { +impl<'mc> JNIRaw<'mc> for LecternInventory<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -14910,106 +16291,32 @@ impl<'mc> JNIRaw<'mc> for BrewerInventory<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BrewerInventory<'mc> { +impl<'mc> JNIInstantiatable<'mc> for LecternInventory<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate BrewerInventory from null object.").into(), + eyre::eyre!("Tried to instantiate LecternInventory from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/BrewerInventory")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/LecternInventory")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BrewerInventory object, got {}", + "Invalid argument passed. Expected a LecternInventory object, got {}", name ) .into()) } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> BrewerInventory<'mc> { - /// Get the current ingredient for brewing. - pub fn ingredient( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getIngredient", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Set the current ingredient for brewing. - pub fn set_ingredient( - &self, - ingredient: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ingredient.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setIngredient", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the current fuel for brewing. - pub fn fuel( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFuel", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemStack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Set the current fuel for brewing. Generally only - /// {@link Material#BLAZE_POWDER} will be of use. - pub fn set_fuel( - &self, - fuel: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(fuel.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFuel", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(Self(env.clone(), obj)) + } } +} - pub fn holder( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/block/BrewingStand;"); +impl<'mc> LecternInventory<'mc> { + pub fn holder(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/block/Lectern;"); let res = self .jni_ref() .call_method(&self.jni_object(), "getHolder", sig.as_str(), vec![]); @@ -15017,7 +16324,7 @@ impl<'mc> BrewerInventory<'mc> { if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::block::BrewingStand::from_raw( + Ok(Some(crate::block::Lectern::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) @@ -15453,288 +16760,23 @@ impl<'mc> BrewerInventory<'mc> { .call_method(&self.jni_object(), "iterator", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; blackboxmc_java::util::JavaListIterator::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the location of the block or entity which corresponds to this inventory. May return null if this container - /// was custom created or is a virtual / subcontainer. - pub fn location(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for BrewerInventory<'mc> { - fn into(self) -> crate::inventory::Inventory<'mc> { - crate::inventory::Inventory::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BrewerInventory into crate::inventory::Inventory") - } -} -pub enum CreativeCategory<'mc> {} -impl<'mc> std::fmt::Display for CreativeCategory<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> CreativeCategory<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/inventory/CreativeCategory"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/inventory/CreativeCategory;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct CreativeCategoryStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for CreativeCategory<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for CreativeCategory<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate CreativeCategory from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/CreativeCategory")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a CreativeCategory object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for CreativeCategoryStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for CreativeCategoryStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate CreativeCategoryStruct from null object." - ) - .into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/CreativeCategory")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a CreativeCategoryStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> CreativeCategoryStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/CreativeCategory;"); - let cls = jni.find_class("org/bukkit/inventory/CreativeCategory"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::inventory::CreativeCategory::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct CraftingRecipe<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for CraftingRecipe<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for CraftingRecipe<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate CraftingRecipe from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/CraftingRecipe")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a CraftingRecipe object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> CraftingRecipe<'mc> { - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the result of this recipe. - pub fn result(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getResult", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the group of this recipe. Recipes with the same group may be grouped - /// together when displayed in the client. - pub fn group(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getGroup", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Set the group of this recipe. Recipes with the same group may be grouped - /// together when displayed in the client. - pub fn set_group(&self, group: impl Into) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(group.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setGroup", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the category which this recipe will appear in the recipe book under. - /// Defaults to {@link CraftingBookCategory#MISC} if not set. - pub fn category( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/inventory/recipe/CraftingBookCategory;"); + /// Get the location of the block or entity which corresponds to this inventory. May return null if this container + /// was custom created or is a virtual / subcontainer. + pub fn location(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::recipe::CraftingBookCategory::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the category which this recipe will appear in the recipe book under. - /// Defaults to {@link CraftingBookCategory#MISC} if not set. - pub fn set_category( - &self, - category: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/inventory/recipe/CraftingBookCategory;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(category.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCategory", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + })?)) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -15742,97 +16784,19 @@ impl<'mc> CraftingRecipe<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for CraftingRecipe<'mc> { - fn into(self) -> crate::inventory::Recipe<'mc> { - crate::inventory::Recipe::from_raw(&self.jni_ref(), self.1) - .expect("Error converting CraftingRecipe into crate::inventory::Recipe") - } -} -impl<'mc> Into> for CraftingRecipe<'mc> { - fn into(self) -> crate::Keyed<'mc> { - crate::Keyed::from_raw(&self.jni_ref(), self.1) - .expect("Error converting CraftingRecipe into crate::Keyed") - } -} -pub enum ItemRarity<'mc> {} -impl<'mc> std::fmt::Display for ItemRarity<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> ItemRarity<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/inventory/ItemRarity"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/inventory/ItemRarity;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } +impl<'mc> Into> for LecternInventory<'mc> { + fn into(self) -> crate::inventory::Inventory<'mc> { + crate::inventory::Inventory::from_raw(&self.jni_ref(), self.1) + .expect("Error converting LecternInventory into crate::inventory::Inventory") } } - #[repr(C)] -pub struct ItemRarityStruct<'mc>( +pub struct BrewerInventory<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ItemRarity<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for ItemRarity<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ItemRarity from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/ItemRarity")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ItemRarity object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for ItemRarityStruct<'mc> { +impl<'mc> JNIRaw<'mc> for BrewerInventory<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -15840,73 +16804,20 @@ impl<'mc> JNIRaw<'mc> for ItemRarityStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ItemRarityStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BrewerInventory<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate ItemRarityStruct from null object.").into(), + eyre::eyre!("Tried to instantiate BrewerInventory from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/ItemRarity")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ItemRarityStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> ItemRarityStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemRarity;"); - let cls = jni.find_class("org/bukkit/inventory/ItemRarity"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::inventory::ItemRarity::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct ItemStack<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for ItemStack<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for ItemStack<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ItemStack from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/ItemStack")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/BrewerInventory")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ItemStack object, got {}", + "Invalid argument passed. Expected a BrewerInventory object, got {}", name ) .into()) @@ -15916,170 +16827,105 @@ impl<'mc> JNIInstantiatable<'mc> for ItemStack<'mc> { } } -impl<'mc> ItemStack<'mc> { - #[deprecated] - - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: impl Into>, - amount: std::option::Option, - damage: std::option::Option, - data: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = amount { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - if let Some(a) = damage { - sig += "S"; - let val_3 = jni::objects::JValueGen::Short(a); - args.push(val_3); - } - if let Some(a) = data { - sig += "Ljava/lang/Byte;"; - let val_4 = jni::objects::JValueGen::Object(jni.new_object( - "java/lang/Byte", - "(Ljava/Lang/Object;)V", - vec![a.into()], - )?); - args.push(val_4); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/inventory/ItemStack"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::inventory::ItemStack::from_raw(&jni, res) - } - /// Gets the type of this item - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); +impl<'mc> BrewerInventory<'mc> { + /// Get the current ingredient for brewing. + pub fn ingredient( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getIngredient", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the type of this item - /// - /// Note that in doing so you will reset the MaterialData for this stack. - /// - /// IMPORTANT: An ItemStack is only designed to contain - /// items. Do not use this class to encapsulate Materials for which - /// {@link Material#isItem()} returns false. - pub fn set_type( + /// Set the current ingredient for brewing. + pub fn set_ingredient( &self, - val_type: impl Into>, + ingredient: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Material;)V"); + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(ingredient.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setType", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the amount of items in this stack - pub fn amount(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getAmount", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the amount of items in this stack - pub fn set_amount(&self, amount: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(amount); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAmount", + "setIngredient", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the MaterialData for this stack of items - pub fn data( + /// Get the current fuel for brewing. + pub fn fuel( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/material/MaterialData;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFuel", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::material::MaterialData::from_raw( + Ok(Some(crate::inventory::ItemStack::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Sets the MaterialData for this stack of items - pub fn set_data( + /// Set the current fuel for brewing. Generally only + /// {@link Material#BLAZE_POWDER} will be of use. + pub fn set_fuel( &self, - data: impl Into>, + fuel: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/material/MaterialData;)V"); + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data.into().jni_object().clone()) + jni::objects::JObject::from_raw(fuel.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setData", + "setFuel", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Sets the durability of this item - pub fn set_durability(&self, durability: i16) -> Result<(), Box> { - let sig = String::from("(S)V"); - let val_1 = jni::objects::JValueGen::Short(durability); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setDurability", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + + pub fn holder( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/block/BrewingStand;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHolder", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::block::BrewingStand::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - #[deprecated] - /// Gets the durability of this item - pub fn durability(&self) -> Result> { - let sig = String::from("()S"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDurability", sig.as_str(), vec![]); + /// Returns the size of the inventory + pub fn size(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.s()?) + Ok(res.i()?) } - /// Get the maximum stack size for this item. If this item has a max stack - /// size component ({@link ItemMeta#hasMaxStackSize()}), the value of that - /// component will be returned. Otherwise, this item's Material's {@link - /// Material#getMaxStackSize() default maximum stack size} will be returned - /// instead. + /// Returns the maximum stack size for an ItemStack in this inventory. pub fn max_stack_size(&self) -> Result> { let sig = String::from("()I"); let res = @@ -16088,384 +16934,703 @@ impl<'mc> ItemStack<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - - pub fn equals( - &self, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - let sig = String::from("(Ljava/lang/Object;)Z"); - let val_1 = jni::objects::JValueGen::Object(obj); + /// This method allows you to change the maximum stack size for an + /// inventory. + /// + /// Caveats: + ///
      + ///
    • Not all inventories respect this value. + ///
    • Stacks larger than 127 may be clipped when the world is saved. + ///
    • This value is not guaranteed to be preserved; be sure to set it + /// before every time you want to set a slot over the max stack size. + ///
    • Stacks larger than the default max size for this type of inventory + /// may not display correctly in the client. + ///
    + pub fn set_max_stack_size(&self, size: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(size); let res = self.jni_ref().call_method( &self.jni_object(), - "equals", + "setMaxStackSize", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// This method is the same as equals, but does not consider stack size - /// (amount). - pub fn is_similar( + /// Returns the ItemStack found in the slot at the given index + pub fn get_item( &self, - stack: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(stack.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isSimilar", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + index: i32, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(index); + args.push(val_1); + sig += ")Lorg/bukkit/inventory/ItemStack;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - - pub fn hash_code(&self) -> Result> { - let sig = String::from("()I"); + /// Stores the ItemStack at the given index of the inventory. + pub fn set_item( + &self, + index: i32, + item: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(index); + args.push(val_1); + if let Some(a) = item { + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + .call_method(&self.jni_object(), "setItem", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Checks if this ItemStack contains the given {@link Enchantment} - pub fn contains_enchantment( + /// Stores the given ItemStacks in the inventory. This will try to fill + /// existing stacks and empty slots as well as it can. + /// + /// The returned HashMap contains what it couldn't store, where the key is + /// the index of the parameter, and the value is the ItemStack at that + /// index of the varargs parameter. If all items are stored, it will return + /// an empty HashMap. + /// + /// If you pass in ItemStacks which exceed the maximum stack size for the + /// Material, first they will be added to partial stacks where + /// Material.getMaxStackSize() is not exceeded, up to + /// Material.getMaxStackSize(). When there are no partial stacks left + /// stacks will be split on Inventory.getMaxStackSize() allowing you to + /// exceed the maximum stack size for that material. + /// + /// It is known that in some implementations this method will also set + /// the inputted argument amount to the number of that item not placed in + /// slots. + pub fn add_item( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)Z"); + items: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/HashMap;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(items.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "containsEnchantment", + "addItem", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the level of the specified enchantment on this item stack - pub fn get_enchantment_level( + /// Removes the given ItemStacks from the inventory. + /// + /// It will try to remove 'as much as possible' from the types and amounts + /// you give as arguments. + /// + /// The returned HashMap contains what it couldn't remove, where the key is + /// the index of the parameter, and the value is the ItemStack at that + /// index of the varargs parameter. If all the given ItemStacks are + /// removed, it will return an empty HashMap. + /// + /// It is known that in some implementations this method will also set the + /// inputted argument amount to the number of that item not removed from + /// slots. + pub fn remove_item( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)I"); + items: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/HashMap;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(items.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getEnchantmentLevel", + "removeItem", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets a map containing all enchantments and their levels on this item. - pub fn enchantments( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); + /// Returns all ItemStacks from the inventory + pub fn contents(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getEnchantments", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getContents", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Adds the specified enchantments to this item stack. - /// - /// This method is the same as calling {@link - /// #addEnchantment(org.bukkit.enchantments.Enchantment, int)} for each - /// element of the map. - pub fn add_enchantments( + /// Completely replaces the inventory's contents. Removes all existing + /// contents and replaces it with the ItemStacks given in the array. + pub fn set_contents( &self, - enchantments: impl Into>, + items: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/Map;)V"); + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(enchantments.into().jni_object().clone()) + jni::objects::JObject::from_raw(items.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "addEnchantments", + "setContents", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Adds the specified {@link Enchantment} to this item stack. + /// Return the contents from the section of the inventory where items can + /// reasonably be expected to be stored. In most cases this will represent + /// the entire inventory, but in some cases it may exclude armor or result + /// slots. /// - /// If this item stack already contained the given enchantment (at any - /// level), it will be replaced. - pub fn add_enchantment( + /// It is these contents which will be used for add / contains / remove + /// methods which look for a specific stack. + pub fn storage_contents( &self, - ench: impl Into>, - level: i32, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;I)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(level); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self.jni_ref().call_method( &self.jni_object(), - "addEnchantment", + "getStorageContents", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Adds the specified enchantments to this item stack in an unsafe manner. - /// - /// This method is the same as calling {@link - /// #addUnsafeEnchantment(org.bukkit.enchantments.Enchantment, int)} for - /// each element of the map. - pub fn add_unsafe_enchantments( + /// Put the given ItemStacks into the storage slots + pub fn set_storage_contents( &self, - enchantments: impl Into>, + items: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/Map;)V"); + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(enchantments.into().jni_object().clone()) + jni::objects::JObject::from_raw(items.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "addUnsafeEnchantments", + "setStorageContents", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Adds the specified {@link Enchantment} to this item stack. - /// - /// If this item stack already contained the given enchantment (at any - /// level), it will be replaced. - /// - /// This method is unsafe and will ignore level restrictions or item type. - /// Use at your own discretion. - pub fn add_unsafe_enchantment( + /// Checks if the inventory contains any ItemStacks with the given + /// material, adding to at least the minimum amount specified. + pub fn contains( &self, - ench: impl Into>, - level: i32, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;I)V"); + material: impl Into>, + amount: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) + jni::objects::JObject::from_raw(material.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(level); + args.push(val_1); + if let Some(a) = amount { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "contains", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks if the inventory contains ItemStacks matching the given + /// ItemStack whose amounts sum to at least the minimum amount specified. + pub fn contains_at_least( + &self, + item: impl Into>, + amount: i32, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;I)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(amount); let res = self.jni_ref().call_method( &self.jni_object(), - "addUnsafeEnchantment", + "containsAtLeast", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), ], ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Finds all slots in the inventory containing any ItemStacks with the + /// given ItemStack. This will only match slots if both the type and the + /// amount of the stack match + /// + /// The HashMap contains entries where, the key is the slot index, and the + /// value is the ItemStack in that slot. If no matching ItemStack with the + /// given Material is found, an empty map is returned. + pub fn all( + &self, + item: impl Into>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Ljava/util/HashMap;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "all", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaHashMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns the first slot in the inventory containing an ItemStack with + /// the given stack. This will only match a slot if both the type and the + /// amount of the stack match + pub fn first( + &self, + item: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")I"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "first", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the first empty Slot. + pub fn first_empty(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "firstEmpty", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Check whether or not this inventory is empty. An inventory is considered + /// to be empty if there are no ItemStacks in any slot of this inventory. + pub fn is_empty(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Removes all stacks in the inventory matching the given stack. + /// + /// This will only match a slot if both the type and the amount of the + /// stack match + pub fn remove( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Removes the specified {@link Enchantment} if it exists on this - /// ItemStack - pub fn remove_enchantment( + /// Clears out a particular slot in the index. + pub fn clear(&self, index: std::option::Option) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = index { + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(a); + args.push(val_1); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clear", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets a list of players viewing the inventory. Note that a player is + /// considered to be viewing their own inventory and internal crafting + /// screen even when said inventory is not open. They will normally be + /// considered to be viewing their inventory even when they have a + /// different inventory screen open, but it's possible for customized + /// inventory screens to exclude the viewer's inventory, so this should + /// never be assumed to be non-empty. + pub fn viewers( &self, - ench: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/enchantments/Enchantment;)I"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ench.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removeEnchantment", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getViewers", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::HumanEntity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Removes all enchantments on this ItemStack. - pub fn remove_enchantments(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removeEnchantments", - sig.as_str(), - vec![], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Returns what type of inventory this is. + pub fn get_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - pub fn serialize( + pub fn iterator( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/ListIterator;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "iterator", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaListIterator::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Required method for configuration serialization - pub fn deserialize( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_args: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Ljava/util/Map;)Lorg/bukkit/inventory/ItemStack;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_args.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/inventory/ItemStack"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "deserialize", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::inventory::ItemStack::from_raw(&jni, obj) - } - /// Get a copy of this ItemStack's {@link ItemMeta}. - pub fn item_meta( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/meta/ItemMeta;"); + /// Get the location of the block or entity which corresponds to this inventory. May return null if this container + /// was custom created or is a virtual / subcontainer. + pub fn location(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemMeta", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::meta::ItemMeta::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Checks to see if any meta data has been defined. - pub fn has_item_meta(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasItemMeta", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Set the ItemMeta of this ItemStack. - pub fn set_item_meta( - &self, - item_meta: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/meta/ItemMeta;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_meta.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setItemMeta", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} +impl<'mc> Into> for BrewerInventory<'mc> { + fn into(self) -> crate::inventory::Inventory<'mc> { + crate::inventory::Inventory::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BrewerInventory into crate::inventory::Inventory") + } +} +pub enum CreativeCategory<'mc> { + BuildingBlocks { inner: CreativeCategoryStruct<'mc> }, + Decorations { inner: CreativeCategoryStruct<'mc> }, + Redstone { inner: CreativeCategoryStruct<'mc> }, + Transportation { inner: CreativeCategoryStruct<'mc> }, + Misc { inner: CreativeCategoryStruct<'mc> }, + Food { inner: CreativeCategoryStruct<'mc> }, + Tools { inner: CreativeCategoryStruct<'mc> }, + Combat { inner: CreativeCategoryStruct<'mc> }, + Brewing { inner: CreativeCategoryStruct<'mc> }, +} +impl<'mc> std::fmt::Display for CreativeCategory<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + CreativeCategory::BuildingBlocks { .. } => f.write_str("BUILDING_BLOCKS"), + CreativeCategory::Decorations { .. } => f.write_str("DECORATIONS"), + CreativeCategory::Redstone { .. } => f.write_str("REDSTONE"), + CreativeCategory::Transportation { .. } => f.write_str("TRANSPORTATION"), + CreativeCategory::Misc { .. } => f.write_str("MISC"), + CreativeCategory::Food { .. } => f.write_str("FOOD"), + CreativeCategory::Tools { .. } => f.write_str("TOOLS"), + CreativeCategory::Combat { .. } => f.write_str("COMBAT"), + CreativeCategory::Brewing { .. } => f.write_str("BREWING"), + } + } +} +impl<'mc> std::ops::Deref for CreativeCategory<'mc> { + type Target = CreativeCategoryStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + CreativeCategory::BuildingBlocks { inner } => inner, + CreativeCategory::Decorations { inner } => inner, + CreativeCategory::Redstone { inner } => inner, + CreativeCategory::Transportation { inner } => inner, + CreativeCategory::Misc { inner } => inner, + CreativeCategory::Food { inner } => inner, + CreativeCategory::Tools { inner } => inner, + CreativeCategory::Combat { inner } => inner, + CreativeCategory::Brewing { inner } => inner, + } } +} - pub fn translation_key(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTranslationKey", - sig.as_str(), - vec![], +impl<'mc> CreativeCategory<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/inventory/CreativeCategory"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/inventory/CreativeCategory;", + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? .to_string_lossy() - .to_string()) + .to_string(); + match variant_str.as_str() { + "BUILDING_BLOCKS" => Ok(CreativeCategory::BuildingBlocks { + inner: CreativeCategoryStruct::from_raw(env, obj)?, + }), + "DECORATIONS" => Ok(CreativeCategory::Decorations { + inner: CreativeCategoryStruct::from_raw(env, obj)?, + }), + "REDSTONE" => Ok(CreativeCategory::Redstone { + inner: CreativeCategoryStruct::from_raw(env, obj)?, + }), + "TRANSPORTATION" => Ok(CreativeCategory::Transportation { + inner: CreativeCategoryStruct::from_raw(env, obj)?, + }), + "MISC" => Ok(CreativeCategory::Misc { + inner: CreativeCategoryStruct::from_raw(env, obj)?, + }), + "FOOD" => Ok(CreativeCategory::Food { + inner: CreativeCategoryStruct::from_raw(env, obj)?, + }), + "TOOLS" => Ok(CreativeCategory::Tools { + inner: CreativeCategoryStruct::from_raw(env, obj)?, + }), + "COMBAT" => Ok(CreativeCategory::Combat { + inner: CreativeCategoryStruct::from_raw(env, obj)?, + }), + "BREWING" => Ok(CreativeCategory::Brewing { + inner: CreativeCategoryStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } +} - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) +#[repr(C)] +pub struct CreativeCategoryStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for CreativeCategory<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::BuildingBlocks { inner } => inner.0.clone(), + Self::Decorations { inner } => inner.0.clone(), + Self::Redstone { inner } => inner.0.clone(), + Self::Transportation { inner } => inner.0.clone(), + Self::Misc { inner } => inner.0.clone(), + Self::Food { inner } => inner.0.clone(), + Self::Tools { inner } => inner.0.clone(), + Self::Combat { inner } => inner.0.clone(), + Self::Brewing { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::BuildingBlocks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Decorations { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Redstone { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Transportation { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Misc { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Food { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Tools { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Combat { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Brewing { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for CreativeCategory<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate CreativeCategory from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/CreativeCategory")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a CreativeCategory object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "BUILDING_BLOCKS" => Ok(CreativeCategory::BuildingBlocks { + inner: CreativeCategoryStruct::from_raw(env, obj)?, + }), + "DECORATIONS" => Ok(CreativeCategory::Decorations { + inner: CreativeCategoryStruct::from_raw(env, obj)?, + }), + "REDSTONE" => Ok(CreativeCategory::Redstone { + inner: CreativeCategoryStruct::from_raw(env, obj)?, + }), + "TRANSPORTATION" => Ok(CreativeCategory::Transportation { + inner: CreativeCategoryStruct::from_raw(env, obj)?, + }), + "MISC" => Ok(CreativeCategory::Misc { + inner: CreativeCategoryStruct::from_raw(env, obj)?, + }), + "FOOD" => Ok(CreativeCategory::Food { + inner: CreativeCategoryStruct::from_raw(env, obj)?, + }), + "TOOLS" => Ok(CreativeCategory::Tools { + inner: CreativeCategoryStruct::from_raw(env, obj)?, + }), + "COMBAT" => Ok(CreativeCategory::Combat { + inner: CreativeCategoryStruct::from_raw(env, obj)?, + }), + "BREWING" => Ok(CreativeCategory::Brewing { + inner: CreativeCategoryStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for CreativeCategoryStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } - -impl<'mc> std::string::ToString for ItemStack<'mc> { - fn to_string(&self) -> String { - match &self.internal_to_string() { - Ok(a) => a.clone(), - Err(err) => format!("Error calling ItemStack.toString: {}", err), +impl<'mc> JNIInstantiatable<'mc> for CreativeCategoryStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate CreativeCategoryStruct from null object." + ) + .into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/CreativeCategory")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a CreativeCategoryStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } } } -impl<'mc> Into> - for ItemStack<'mc> -{ - fn into(self) -> crate::configuration::serialization::ConfigurationSerializable<'mc> { - crate::configuration::serialization::ConfigurationSerializable::from_raw(&self.jni_ref(), self.1).expect("Error converting ItemStack into crate::configuration::serialization::ConfigurationSerializable") +impl<'mc> CreativeCategoryStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/CreativeCategory;"); + let cls = jni.find_class("org/bukkit/inventory/CreativeCategory"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::inventory::CreativeCategory::from_raw(&jni, obj) } -} -impl<'mc> Into> for ItemStack<'mc> { - fn into(self) -> crate::Translatable<'mc> { - crate::Translatable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ItemStack into crate::Translatable") + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } } #[repr(C)] -pub struct SmithingTrimRecipe<'mc>( +pub struct CraftingRecipe<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for SmithingTrimRecipe<'mc> { +impl<'mc> JNIRaw<'mc> for CraftingRecipe<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -16473,20 +17638,20 @@ impl<'mc> JNIRaw<'mc> for SmithingTrimRecipe<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for SmithingTrimRecipe<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CraftingRecipe<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate SmithingTrimRecipe from null object.").into(), + eyre::eyre!("Tried to instantiate CraftingRecipe from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/SmithingTrimRecipe")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/CraftingRecipe")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SmithingTrimRecipe object, got {}", + "Invalid argument passed. Expected a CraftingRecipe object, got {}", name ) .into()) @@ -16496,53 +17661,14 @@ impl<'mc> JNIInstantiatable<'mc> for SmithingTrimRecipe<'mc> { } } -impl<'mc> SmithingTrimRecipe<'mc> { - /// Create a smithing recipe to produce the specified result ItemStack. - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - key: impl Into>, - template: impl Into>, - base: impl Into>, - addition: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;Lorg/bukkit/inventory/RecipeChoice;Lorg/bukkit/inventory/RecipeChoice;Lorg/bukkit/inventory/RecipeChoice;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(template.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(base.into().jni_object().clone()) - }); - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(addition.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/inventory/SmithingTrimRecipe"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - ], - ); - let res = jni.translate_error_no_gen(res)?; - crate::inventory::SmithingTrimRecipe::from_raw(&jni, res) - } - /// Get the template recipe item. - pub fn template( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/RecipeChoice;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTemplate", sig.as_str(), vec![]); +impl<'mc> CraftingRecipe<'mc> { + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::RecipeChoice::from_raw(&self.jni_ref(), unsafe { + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -16557,35 +17683,71 @@ impl<'mc> SmithingTrimRecipe<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Return the namespaced identifier for this object. - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + /// Get the group of this recipe. Recipes with the same group may be grouped + /// together when displayed in the client. + pub fn group(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getGroup", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Set the group of this recipe. Recipes with the same group may be grouped + /// together when displayed in the client. + pub fn set_group(&self, group: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(group.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setGroup", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the category which this recipe will appear in the recipe book under. + /// + /// Defaults to {@link CraftingBookCategory#MISC} if not set. + pub fn category( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/inventory/recipe/CraftingBookCategory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCategory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::recipe::CraftingBookCategory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.inventory.SmithingRecipe ( ['getTemplate', 'getResult', 'getKey']) - /// Get the base recipe item. - pub fn base(&self) -> Result, Box> { - let temp_clone = crate::inventory::SmithingRecipe::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::inventory::SmithingRecipe = temp_clone.into(); - real.base() - } - /// Get the addition recipe item. - pub fn addition( + /// Sets the category which this recipe will appear in the recipe book under. + /// + /// Defaults to {@link CraftingBookCategory#MISC} if not set. + pub fn set_category( &self, - ) -> Result, Box> { - let temp_clone = crate::inventory::SmithingRecipe::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::inventory::SmithingRecipe = temp_clone.into(); - real.addition() + category: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/recipe/CraftingBookCategory;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(category.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCategory", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -16593,117 +17755,153 @@ impl<'mc> SmithingTrimRecipe<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for SmithingTrimRecipe<'mc> { - fn into(self) -> crate::inventory::ComplexRecipe<'mc> { - crate::inventory::ComplexRecipe::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SmithingTrimRecipe into crate::inventory::ComplexRecipe") +impl<'mc> Into> for CraftingRecipe<'mc> { + fn into(self) -> crate::inventory::Recipe<'mc> { + crate::inventory::Recipe::from_raw(&self.jni_ref(), self.1) + .expect("Error converting CraftingRecipe into crate::inventory::Recipe") } } -impl<'mc> Into> for SmithingTrimRecipe<'mc> { - fn into(self) -> crate::inventory::SmithingRecipe<'mc> { - crate::inventory::SmithingRecipe::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SmithingTrimRecipe into crate::inventory::SmithingRecipe") +impl<'mc> Into> for CraftingRecipe<'mc> { + fn into(self) -> crate::Keyed<'mc> { + crate::Keyed::from_raw(&self.jni_ref(), self.1) + .expect("Error converting CraftingRecipe into crate::Keyed") + } +} +pub enum ItemRarity<'mc> { + Common { inner: ItemRarityStruct<'mc> }, + Uncommon { inner: ItemRarityStruct<'mc> }, + Rare { inner: ItemRarityStruct<'mc> }, + Epic { inner: ItemRarityStruct<'mc> }, +} +impl<'mc> std::fmt::Display for ItemRarity<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ItemRarity::Common { .. } => f.write_str("COMMON"), + ItemRarity::Uncommon { .. } => f.write_str("UNCOMMON"), + ItemRarity::Rare { .. } => f.write_str("RARE"), + ItemRarity::Epic { .. } => f.write_str("EPIC"), + } + } +} +impl<'mc> std::ops::Deref for ItemRarity<'mc> { + type Target = ItemRarityStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + ItemRarity::Common { inner } => inner, + ItemRarity::Uncommon { inner } => inner, + ItemRarity::Rare { inner } => inner, + ItemRarity::Epic { inner } => inner, + } } } + +impl<'mc> ItemRarity<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/inventory/ItemRarity"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/inventory/ItemRarity;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "COMMON" => Ok(ItemRarity::Common { + inner: ItemRarityStruct::from_raw(env, obj)?, + }), + "UNCOMMON" => Ok(ItemRarity::Uncommon { + inner: ItemRarityStruct::from_raw(env, obj)?, + }), + "RARE" => Ok(ItemRarity::Rare { + inner: ItemRarityStruct::from_raw(env, obj)?, + }), + "EPIC" => Ok(ItemRarity::Epic { + inner: ItemRarityStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + #[repr(C)] -pub struct RecipeChoice<'mc>( +pub struct ItemRarityStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for RecipeChoice<'mc> { +impl<'mc> JNIRaw<'mc> for ItemRarity<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + match self { + Self::Common { inner } => inner.0.clone(), + Self::Uncommon { inner } => inner.0.clone(), + Self::Rare { inner } => inner.0.clone(), + Self::Epic { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + match self { + Self::Common { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Uncommon { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Rare { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Epic { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for RecipeChoice<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ItemRarity<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate RecipeChoice from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate ItemRarity from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/RecipeChoice")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/ItemRarity")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a RecipeChoice object, got {}", + "Invalid argument passed. Expected a ItemRarity object, got {}", name ) .into()) } else { - Ok(Self(env.clone(), obj)) + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "COMMON" => Ok(ItemRarity::Common { + inner: ItemRarityStruct::from_raw(env, obj)?, + }), + "UNCOMMON" => Ok(ItemRarity::Uncommon { + inner: ItemRarityStruct::from_raw(env, obj)?, + }), + "RARE" => Ok(ItemRarity::Rare { + inner: ItemRarityStruct::from_raw(env, obj)?, + }), + "EPIC" => Ok(ItemRarity::Epic { + inner: ItemRarityStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } } -impl<'mc> RecipeChoice<'mc> { - #[deprecated] - /// Gets a single item stack representative of this stack choice. - pub fn item_stack( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemStack", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/RecipeChoice;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::RecipeChoice::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn test( - &self, - item_stack: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "test", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for RecipeChoice<'mc> { - fn into(self) -> blackboxmc_java::util::function::JavaPredicate<'mc> { - blackboxmc_java::util::function::JavaPredicate::from_raw(&self.jni_ref(), self.1).expect( - "Error converting RecipeChoice into blackboxmc_java::util::function::JavaPredicate", - ) - } -} -#[repr(C)] -pub struct RecipeChoiceMaterialChoice<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for RecipeChoiceMaterialChoice<'mc> { +impl<'mc> JNIRaw<'mc> for ItemRarityStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -16711,22 +17909,20 @@ impl<'mc> JNIRaw<'mc> for RecipeChoiceMaterialChoice<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for RecipeChoiceMaterialChoice<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ItemRarityStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate RecipeChoiceMaterialChoice from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate ItemRarityStruct from null object.").into(), + ); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/inventory/RecipeChoice/MaterialChoice")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/ItemRarity")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a RecipeChoiceMaterialChoice object, got {}", + "Invalid argument passed. Expected a ItemRarityStruct object, got {}", name ) .into()) @@ -16736,163 +17932,31 @@ impl<'mc> JNIInstantiatable<'mc> for RecipeChoiceMaterialChoice<'mc> { } } -impl<'mc> RecipeChoiceMaterialChoice<'mc> { - pub fn new( +impl<'mc> ItemRarityStruct<'mc> { + pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - choices: Vec>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/util/List;"; - let raw_val_1 = jni.new_object("java/util/ArrayList", "()V", vec![])?; - for v in choices { - sig += "Ljava/lang/java/lang/Object;"; - let map_val_0 = jni::objects::JValueGen::Object(v); - jni.call_method( - &raw_val_1, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_1 = jni::objects::JValueGen::Object(raw_val_1); - args.push(val_1); - sig += ")V"; - let cls = jni.find_class("org/bukkit/inventory/RecipeChoice/MaterialChoice"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemRarity;"); + let cls = jni.find_class("org/bukkit/inventory/ItemRarity"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::inventory::RecipeChoiceMaterialChoice::from_raw(&jni, res) - } - - pub fn item_stack( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemStack", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn choices(&self) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getChoices", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::Material::from_raw(&self.0, obj)?); - } - Ok(new_vec) - } - - pub fn clone( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/RecipeChoice/MaterialChoice;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::RecipeChoiceMaterialChoice::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn hash_code(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - - pub fn equals( - &self, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - let sig = String::from("(Ljava/lang/Object;)Z"); - let val_1 = jni::objects::JValueGen::Object(obj); - let res = self.jni_ref().call_method( - &self.jni_object(), - "equals", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - - pub fn test( - &self, - item_stack: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "test", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} - -impl<'mc> std::string::ToString for RecipeChoiceMaterialChoice<'mc> { - fn to_string(&self) -> String { - match &self.internal_to_string() { - Ok(a) => a.clone(), - Err(err) => format!("Error calling RecipeChoiceMaterialChoice.toString: {}", err), - } - } -} - -impl<'mc> Into> for RecipeChoiceMaterialChoice<'mc> { - fn into(self) -> crate::inventory::RecipeChoice<'mc> { - crate::inventory::RecipeChoice::from_raw(&self.jni_ref(), self.1).expect( - "Error converting RecipeChoiceMaterialChoice into crate::inventory::RecipeChoice", - ) + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::inventory::ItemRarity::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } } #[repr(C)] -pub struct RecipeChoiceExactChoice<'mc>( +pub struct SmithingTrimRecipe<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for RecipeChoiceExactChoice<'mc> { +impl<'mc> JNIRaw<'mc> for SmithingTrimRecipe<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -16900,22 +17964,20 @@ impl<'mc> JNIRaw<'mc> for RecipeChoiceExactChoice<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for RecipeChoiceExactChoice<'mc> { +impl<'mc> JNIInstantiatable<'mc> for SmithingTrimRecipe<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate RecipeChoiceExactChoice from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate SmithingTrimRecipe from null object.").into(), + ); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/inventory/RecipeChoice/ExactChoice")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/SmithingTrimRecipe")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a RecipeChoiceExactChoice object, got {}", + "Invalid argument passed. Expected a SmithingTrimRecipe object, got {}", name ) .into()) @@ -16925,134 +17987,102 @@ impl<'mc> JNIInstantiatable<'mc> for RecipeChoiceExactChoice<'mc> { } } -impl<'mc> RecipeChoiceExactChoice<'mc> { +impl<'mc> SmithingTrimRecipe<'mc> { + /// Create a smithing recipe to produce the specified result ItemStack. pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - choices: Vec>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/util/List;"; - let raw_val_1 = jni.new_object("java/util/ArrayList", "()V", vec![])?; - for v in choices { - sig += "Ljava/lang/java/lang/Object;"; - let map_val_0 = jni::objects::JValueGen::Object(v); - jni.call_method( - &raw_val_1, - "add", - "(Ljava/lang/Object;)Z", - vec![jni::objects::JValueGen::from(map_val_0)], - )?; - } - let val_1 = jni::objects::JValueGen::Object(raw_val_1); - args.push(val_1); - sig += ")V"; - let cls = jni.find_class("org/bukkit/inventory/RecipeChoice/ExactChoice"); + key: impl Into>, + template: impl Into>, + base: impl Into>, + addition: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;Lorg/bukkit/inventory/RecipeChoice;Lorg/bukkit/inventory/RecipeChoice;Lorg/bukkit/inventory/RecipeChoice;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(key.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(template.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(base.into().jni_object().clone()) + }); + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(addition.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/inventory/SmithingTrimRecipe"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + ], + ); let res = jni.translate_error_no_gen(res)?; - crate::inventory::RecipeChoiceExactChoice::from_raw(&jni, res) - } - - pub fn item_stack( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemStack", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + crate::inventory::SmithingTrimRecipe::from_raw(&jni, res) } - - pub fn choices( + /// Get the template recipe item. + pub fn template( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/RecipeChoice;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getChoices", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTemplate", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::inventory::ItemStack::from_raw(&self.0, obj)?); + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - Ok(new_vec) + Ok(Some(crate::inventory::RecipeChoice::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - - pub fn clone( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/RecipeChoice/ExactChoice;"); + /// Get the result of this recipe. + pub fn result(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getResult", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::RecipeChoiceExactChoice::from_raw(&self.jni_ref(), unsafe { + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn hash_code(&self) -> Result> { - let sig = String::from("()I"); + /// Return the namespaced identifier for this object. + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - - pub fn equals( + // SUPER CLASS: org.bukkit.inventory.SmithingRecipe ( ['getTemplate', 'getResult', 'getKey']) + /// Get the base recipe item. + pub fn base( &self, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - let sig = String::from("(Ljava/lang/Object;)Z"); - let val_1 = jni::objects::JValueGen::Object(obj); - let res = self.jni_ref().call_method( - &self.jni_object(), - "equals", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + ) -> Result>, Box> { + let temp_clone = crate::inventory::SmithingRecipe::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::inventory::SmithingRecipe = temp_clone.into(); + real.base() } - - pub fn test( + /// Get the addition recipe item. + pub fn addition( &self, - item_stack: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item_stack.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "test", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + ) -> Result>, Box> { + let temp_clone = crate::inventory::SmithingRecipe::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::inventory::SmithingRecipe = temp_clone.into(); + real.addition() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -17060,20 +18090,16 @@ impl<'mc> RecipeChoiceExactChoice<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } - -impl<'mc> std::string::ToString for RecipeChoiceExactChoice<'mc> { - fn to_string(&self) -> String { - match &self.internal_to_string() { - Ok(a) => a.clone(), - Err(err) => format!("Error calling RecipeChoiceExactChoice.toString: {}", err), - } +impl<'mc> Into> for SmithingTrimRecipe<'mc> { + fn into(self) -> crate::inventory::ComplexRecipe<'mc> { + crate::inventory::ComplexRecipe::from_raw(&self.jni_ref(), self.1) + .expect("Error converting SmithingTrimRecipe into crate::inventory::ComplexRecipe") } } - -impl<'mc> Into> for RecipeChoiceExactChoice<'mc> { - fn into(self) -> crate::inventory::RecipeChoice<'mc> { - crate::inventory::RecipeChoice::from_raw(&self.jni_ref(), self.1) - .expect("Error converting RecipeChoiceExactChoice into crate::inventory::RecipeChoice") +impl<'mc> Into> for SmithingTrimRecipe<'mc> { + fn into(self) -> crate::inventory::SmithingRecipe<'mc> { + crate::inventory::SmithingRecipe::from_raw(&self.jni_ref(), self.1) + .expect("Error converting SmithingTrimRecipe into crate::inventory::SmithingRecipe") } } #[repr(C)] @@ -18088,28 +19114,38 @@ impl<'mc> SmithingRecipe<'mc> { crate::inventory::SmithingRecipe::from_raw(&jni, res) } /// Get the base recipe item. - pub fn base(&self) -> Result, Box> { + pub fn base( + &self, + ) -> Result>, Box> { let sig = String::from("()Lorg/bukkit/inventory/RecipeChoice;"); let res = self .jni_ref() .call_method(&self.jni_object(), "getBase", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::RecipeChoice::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::RecipeChoice::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } /// Get the addition recipe item. pub fn addition( &self, - ) -> Result, Box> { + ) -> Result>, Box> { let sig = String::from("()Lorg/bukkit/inventory/RecipeChoice;"); let res = self.jni_ref() .call_method(&self.jni_object(), "getAddition", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::RecipeChoice::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::RecipeChoice::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } pub fn result(&self) -> Result, Box> { @@ -18669,10 +19705,25 @@ impl<'mc> Into> for DecoratedPotInventory<'mc> .expect("Error converting DecoratedPotInventory into crate::inventory::Inventory") } } -pub enum MainHand<'mc> {} +pub enum MainHand<'mc> { + Left { inner: MainHandStruct<'mc> }, + Right { inner: MainHandStruct<'mc> }, +} impl<'mc> std::fmt::Display for MainHand<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + MainHand::Left { .. } => f.write_str("LEFT"), + MainHand::Right { .. } => f.write_str("RIGHT"), + } + } +} +impl<'mc> std::ops::Deref for MainHand<'mc> { + type Target = MainHandStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + MainHand::Left { inner } => inner, + MainHand::Right { inner } => inner, + } } } @@ -18699,6 +19750,13 @@ impl<'mc> MainHand<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "LEFT" => Ok(MainHand::Left { + inner: MainHandStruct::from_raw(env, obj)?, + }), + "RIGHT" => Ok(MainHand::Right { + inner: MainHandStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -18712,10 +19770,16 @@ pub struct MainHandStruct<'mc>( impl<'mc> JNIRaw<'mc> for MainHand<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Left { inner } => inner.0.clone(), + Self::Right { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Left { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Right { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for MainHand<'mc> { @@ -18741,6 +19805,12 @@ impl<'mc> JNIInstantiatable<'mc> for MainHand<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "LEFT" => Ok(MainHand::Left { + inner: MainHandStruct::from_raw(env, obj)?, + }), + "RIGHT" => Ok(MainHand::Right { + inner: MainHandStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -19396,19 +20466,25 @@ impl<'mc> SmithingTransformRecipe<'mc> { /// Get the template recipe item. pub fn template( &self, - ) -> Result, Box> { + ) -> Result>, Box> { let sig = String::from("()Lorg/bukkit/inventory/RecipeChoice;"); let res = self.jni_ref() .call_method(&self.jni_object(), "getTemplate", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::RecipeChoice::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::RecipeChoice::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } // SUPER CLASS: org.bukkit.inventory.SmithingRecipe ( ['getTemplate']) /// Get the base recipe item. - pub fn base(&self) -> Result, Box> { + pub fn base( + &self, + ) -> Result>, Box> { let temp_clone = crate::inventory::SmithingRecipe::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; @@ -19418,7 +20494,7 @@ impl<'mc> SmithingTransformRecipe<'mc> { /// Get the addition recipe item. pub fn addition( &self, - ) -> Result, Box> { + ) -> Result>, Box> { let temp_clone = crate::inventory::SmithingRecipe::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; @@ -19707,3 +20783,4 @@ impl<'mc> Into> for FurnaceRecipe<'mc> { } pub mod meta; pub mod recipe; +pub mod view; diff --git a/blackboxmc-rs-bukkit/src/inventory/recipe/mod.rs b/blackboxmc-rs-bukkit/src/inventory/recipe/mod.rs index de0a2e6..8f06183 100644 --- a/blackboxmc-rs-bukkit/src/inventory/recipe/mod.rs +++ b/blackboxmc-rs-bukkit/src/inventory/recipe/mod.rs @@ -2,10 +2,39 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; -pub enum CraftingBookCategory<'mc> {} +pub enum CraftingBookCategory<'mc> { + Building { + inner: CraftingBookCategoryStruct<'mc>, + }, + Redstone { + inner: CraftingBookCategoryStruct<'mc>, + }, + Equipment { + inner: CraftingBookCategoryStruct<'mc>, + }, + Misc { + inner: CraftingBookCategoryStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for CraftingBookCategory<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + CraftingBookCategory::Building { .. } => f.write_str("BUILDING"), + CraftingBookCategory::Redstone { .. } => f.write_str("REDSTONE"), + CraftingBookCategory::Equipment { .. } => f.write_str("EQUIPMENT"), + CraftingBookCategory::Misc { .. } => f.write_str("MISC"), + } + } +} +impl<'mc> std::ops::Deref for CraftingBookCategory<'mc> { + type Target = CraftingBookCategoryStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + CraftingBookCategory::Building { inner } => inner, + CraftingBookCategory::Redstone { inner } => inner, + CraftingBookCategory::Equipment { inner } => inner, + CraftingBookCategory::Misc { inner } => inner, + } } } @@ -32,6 +61,19 @@ impl<'mc> CraftingBookCategory<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "BUILDING" => Ok(CraftingBookCategory::Building { + inner: CraftingBookCategoryStruct::from_raw(env, obj)?, + }), + "REDSTONE" => Ok(CraftingBookCategory::Redstone { + inner: CraftingBookCategoryStruct::from_raw(env, obj)?, + }), + "EQUIPMENT" => Ok(CraftingBookCategory::Equipment { + inner: CraftingBookCategoryStruct::from_raw(env, obj)?, + }), + "MISC" => Ok(CraftingBookCategory::Misc { + inner: CraftingBookCategoryStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -45,10 +87,22 @@ pub struct CraftingBookCategoryStruct<'mc>( impl<'mc> JNIRaw<'mc> for CraftingBookCategory<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Building { inner } => inner.0.clone(), + Self::Redstone { inner } => inner.0.clone(), + Self::Equipment { inner } => inner.0.clone(), + Self::Misc { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Building { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Redstone { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Equipment { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Misc { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for CraftingBookCategory<'mc> { @@ -77,6 +131,18 @@ impl<'mc> JNIInstantiatable<'mc> for CraftingBookCategory<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "BUILDING" => Ok(CraftingBookCategory::Building { + inner: CraftingBookCategoryStruct::from_raw(env, obj)?, + }), + "REDSTONE" => Ok(CraftingBookCategory::Redstone { + inner: CraftingBookCategoryStruct::from_raw(env, obj)?, + }), + "EQUIPMENT" => Ok(CraftingBookCategory::Equipment { + inner: CraftingBookCategoryStruct::from_raw(env, obj)?, + }), + "MISC" => Ok(CraftingBookCategory::Misc { + inner: CraftingBookCategoryStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -135,10 +201,34 @@ impl<'mc> CraftingBookCategoryStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum CookingBookCategory<'mc> {} +pub enum CookingBookCategory<'mc> { + Food { + inner: CookingBookCategoryStruct<'mc>, + }, + Blocks { + inner: CookingBookCategoryStruct<'mc>, + }, + Misc { + inner: CookingBookCategoryStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for CookingBookCategory<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + CookingBookCategory::Food { .. } => f.write_str("FOOD"), + CookingBookCategory::Blocks { .. } => f.write_str("BLOCKS"), + CookingBookCategory::Misc { .. } => f.write_str("MISC"), + } + } +} +impl<'mc> std::ops::Deref for CookingBookCategory<'mc> { + type Target = CookingBookCategoryStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + CookingBookCategory::Food { inner } => inner, + CookingBookCategory::Blocks { inner } => inner, + CookingBookCategory::Misc { inner } => inner, + } } } @@ -165,6 +255,16 @@ impl<'mc> CookingBookCategory<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "FOOD" => Ok(CookingBookCategory::Food { + inner: CookingBookCategoryStruct::from_raw(env, obj)?, + }), + "BLOCKS" => Ok(CookingBookCategory::Blocks { + inner: CookingBookCategoryStruct::from_raw(env, obj)?, + }), + "MISC" => Ok(CookingBookCategory::Misc { + inner: CookingBookCategoryStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -178,10 +278,18 @@ pub struct CookingBookCategoryStruct<'mc>( impl<'mc> JNIRaw<'mc> for CookingBookCategory<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Food { inner } => inner.0.clone(), + Self::Blocks { inner } => inner.0.clone(), + Self::Misc { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Food { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Blocks { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Misc { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for CookingBookCategory<'mc> { @@ -210,6 +318,15 @@ impl<'mc> JNIInstantiatable<'mc> for CookingBookCategory<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "FOOD" => Ok(CookingBookCategory::Food { + inner: CookingBookCategoryStruct::from_raw(env, obj)?, + }), + "BLOCKS" => Ok(CookingBookCategory::Blocks { + inner: CookingBookCategoryStruct::from_raw(env, obj)?, + }), + "MISC" => Ok(CookingBookCategory::Misc { + inner: CookingBookCategoryStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } diff --git a/blackboxmc-rs-bukkit/src/inventory/view/mod.rs b/blackboxmc-rs-bukkit/src/inventory/view/mod.rs new file mode 100644 index 0000000..7852241 --- /dev/null +++ b/blackboxmc-rs-bukkit/src/inventory/view/mod.rs @@ -0,0 +1,4042 @@ +#![allow(deprecated)] +use blackboxmc_general::JNIInstantiatable; +use blackboxmc_general::JNIRaw; +use color_eyre::eyre::Result; +#[repr(C)] +pub struct LoomView<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for LoomView<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for LoomView<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate LoomView from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/view/LoomView")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a LoomView object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> LoomView<'mc> { + /// Gets a list of all selectable to the player. + pub fn selectable_patterns( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSelectablePatterns", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::banner::PatternType::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(new_vec) + } + /// Gets an index of the selected pattern. + pub fn selected_pattern_index(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSelectedPatternIndex", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Get the upper inventory involved in this transaction. + pub fn top_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTopInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the lower inventory involved in this transaction. + pub fn bottom_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBottomInventory", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the player viewing. + pub fn player(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::HumanEntity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Determine the type of inventory involved in the transaction. This + /// indicates the window style being shown. It will never return PLAYER, + /// since that is common to all windows. + pub fn get_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets one item in this inventory view by its raw slot ID. + /// + /// Note: If slot ID -999 is chosen, it may be expected that the item is + /// dropped on the ground. This is not required behaviour, however. + pub fn set_item( + &self, + slot: i32, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(ILorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Int(slot); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItem", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets one item in this inventory view by its raw slot ID. + pub fn get_item( + &self, + slot: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/ItemStack;"); + let val_1 = jni::objects::JValueGen::Int(slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets the item on the cursor of one of the viewing players. + pub fn set_cursor( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCursor", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the item on the cursor of one of the viewing players. + pub fn cursor( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCursor", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the inventory corresponding to the given raw slot ID. + /// If the slot ID is {@link #OUTSIDE} null will be returned, otherwise + /// behaviour for illegal and negative slot IDs is undefined. + /// May be used with {@link #convertSlot(int)} to directly index an + /// underlying inventory. + pub fn get_inventory( + &self, + raw_slot: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/Inventory;"); + let val_1 = jni::objects::JValueGen::Int(raw_slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getInventory", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::Inventory::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Converts a raw slot ID into its local slot ID into whichever of the two + /// inventories the slot points to. + /// + /// If the raw slot refers to the upper inventory, it will be returned + /// unchanged and thus be suitable for getTopInventory().getItem(); if it + /// refers to the lower inventory, the output will differ from the input + /// and be suitable for getBottomInventory().getItem(). + pub fn convert_slot(&self, raw_slot: i32) -> Result> { + let sig = String::from("(I)I"); + let val_1 = jni::objects::JValueGen::Int(raw_slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "convertSlot", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Determine the type of the slot by its raw slot ID. + /// + /// If the type of the slot is unknown, then + /// {@link InventoryType.SlotType#CONTAINER} will be returned. + pub fn get_slot_type( + &self, + slot: i32, + ) -> Result, Box> + { + let sig = String::from("(I)Lorg/bukkit/event/inventory/InventoryType/SlotType;"); + let val_1 = jni::objects::JValueGen::Int(slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSlotType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryTypeSlotType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Closes the inventory view. + pub fn close(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "close", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Check the total number of slots in this view, combining the upper and + /// lower inventories. + /// + /// Note though that it's possible for this to be greater than the sum of + /// the two inventories if for example some slots are not being used. + pub fn count_slots(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "countSlots", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets an extra property of this inventory if supported by that + /// inventory, for example the state of a progress bar. + pub fn set_property( + &self, + prop: impl Into>, + value: i32, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/InventoryView/Property;I)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(prop.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setProperty", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the title of this inventory window. + pub fn title(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTitle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Get the original title of this inventory window, before any changes were + /// made using {@link #setTitle(String)}. + pub fn original_title(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getOriginalTitle", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the title of this inventory window to the specified title if the + /// inventory window supports it. + /// + /// Note if the inventory does not support titles that can be changed (ie, it + /// is not creatable or viewed by a player), then this method will throw an + /// exception. + pub fn set_title(&self, title: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(title.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTitle", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for LoomView<'mc> { + fn into(self) -> crate::inventory::InventoryView<'mc> { + crate::inventory::InventoryView::from_raw(&self.jni_ref(), self.1) + .expect("Error converting LoomView into crate::inventory::InventoryView") + } +} +#[repr(C)] +pub struct EnchantmentView<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for EnchantmentView<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for EnchantmentView<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate EnchantmentView from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/view/EnchantmentView")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EnchantmentView object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> EnchantmentView<'mc> { + /// Gets the random enchantment seed used in this view + pub fn enchantment_seed(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getEnchantmentSeed", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the offers of this EnchantmentView + pub fn offers( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/enchantments/EnchantmentOffer;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getOffers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::enchantments::EnchantmentOffer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the offers to provide to the player. + pub fn set_offers( + &self, + offers: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/enchantments/EnchantmentOffer;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(offers.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setOffers", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the upper inventory involved in this transaction. + pub fn top_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTopInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the lower inventory involved in this transaction. + pub fn bottom_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBottomInventory", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the player viewing. + pub fn player(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::HumanEntity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Determine the type of inventory involved in the transaction. This + /// indicates the window style being shown. It will never return PLAYER, + /// since that is common to all windows. + pub fn get_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets one item in this inventory view by its raw slot ID. + /// + /// Note: If slot ID -999 is chosen, it may be expected that the item is + /// dropped on the ground. This is not required behaviour, however. + pub fn set_item( + &self, + slot: i32, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(ILorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Int(slot); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItem", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets one item in this inventory view by its raw slot ID. + pub fn get_item( + &self, + slot: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/ItemStack;"); + let val_1 = jni::objects::JValueGen::Int(slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets the item on the cursor of one of the viewing players. + pub fn set_cursor( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCursor", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the item on the cursor of one of the viewing players. + pub fn cursor( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCursor", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the inventory corresponding to the given raw slot ID. + /// If the slot ID is {@link #OUTSIDE} null will be returned, otherwise + /// behaviour for illegal and negative slot IDs is undefined. + /// May be used with {@link #convertSlot(int)} to directly index an + /// underlying inventory. + pub fn get_inventory( + &self, + raw_slot: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/Inventory;"); + let val_1 = jni::objects::JValueGen::Int(raw_slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getInventory", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::Inventory::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Converts a raw slot ID into its local slot ID into whichever of the two + /// inventories the slot points to. + /// + /// If the raw slot refers to the upper inventory, it will be returned + /// unchanged and thus be suitable for getTopInventory().getItem(); if it + /// refers to the lower inventory, the output will differ from the input + /// and be suitable for getBottomInventory().getItem(). + pub fn convert_slot(&self, raw_slot: i32) -> Result> { + let sig = String::from("(I)I"); + let val_1 = jni::objects::JValueGen::Int(raw_slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "convertSlot", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Determine the type of the slot by its raw slot ID. + /// + /// If the type of the slot is unknown, then + /// {@link InventoryType.SlotType#CONTAINER} will be returned. + pub fn get_slot_type( + &self, + slot: i32, + ) -> Result, Box> + { + let sig = String::from("(I)Lorg/bukkit/event/inventory/InventoryType/SlotType;"); + let val_1 = jni::objects::JValueGen::Int(slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSlotType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryTypeSlotType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Closes the inventory view. + pub fn close(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "close", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Check the total number of slots in this view, combining the upper and + /// lower inventories. + /// + /// Note though that it's possible for this to be greater than the sum of + /// the two inventories if for example some slots are not being used. + pub fn count_slots(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "countSlots", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets an extra property of this inventory if supported by that + /// inventory, for example the state of a progress bar. + pub fn set_property( + &self, + prop: impl Into>, + value: i32, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/InventoryView/Property;I)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(prop.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setProperty", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the title of this inventory window. + pub fn title(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTitle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Get the original title of this inventory window, before any changes were + /// made using {@link #setTitle(String)}. + pub fn original_title(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getOriginalTitle", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the title of this inventory window to the specified title if the + /// inventory window supports it. + /// + /// Note if the inventory does not support titles that can be changed (ie, it + /// is not creatable or viewed by a player), then this method will throw an + /// exception. + pub fn set_title(&self, title: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(title.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTitle", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for EnchantmentView<'mc> { + fn into(self) -> crate::inventory::InventoryView<'mc> { + crate::inventory::InventoryView::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EnchantmentView into crate::inventory::InventoryView") + } +} +#[repr(C)] +pub struct CrafterView<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for CrafterView<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for CrafterView<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate CrafterView from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/view/CrafterView")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a CrafterView object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> CrafterView<'mc> { + /// Checks if the given crafter slot is disabled. + pub fn is_slot_disabled(&self, slot: i32) -> Result> { + let sig = String::from("(I)Z"); + let val_1 = jni::objects::JValueGen::Int(slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isSlotDisabled", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks whether or not this crafter view is powered. + pub fn is_powered(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the status of the crafter slot. + pub fn set_slot_disabled( + &self, + slot: i32, + disabled: bool, + ) -> Result<(), Box> { + let sig = String::from("(IZ)V"); + let val_1 = jni::objects::JValueGen::Int(slot); + let val_2 = jni::objects::JValueGen::Bool(disabled.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSlotDisabled", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the upper inventory involved in this transaction. + pub fn top_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTopInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the lower inventory involved in this transaction. + pub fn bottom_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBottomInventory", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the player viewing. + pub fn player(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::HumanEntity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Determine the type of inventory involved in the transaction. This + /// indicates the window style being shown. It will never return PLAYER, + /// since that is common to all windows. + pub fn get_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets one item in this inventory view by its raw slot ID. + /// + /// Note: If slot ID -999 is chosen, it may be expected that the item is + /// dropped on the ground. This is not required behaviour, however. + pub fn set_item( + &self, + slot: i32, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(ILorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Int(slot); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItem", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets one item in this inventory view by its raw slot ID. + pub fn get_item( + &self, + slot: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/ItemStack;"); + let val_1 = jni::objects::JValueGen::Int(slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets the item on the cursor of one of the viewing players. + pub fn set_cursor( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCursor", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the item on the cursor of one of the viewing players. + pub fn cursor( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCursor", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the inventory corresponding to the given raw slot ID. + /// If the slot ID is {@link #OUTSIDE} null will be returned, otherwise + /// behaviour for illegal and negative slot IDs is undefined. + /// May be used with {@link #convertSlot(int)} to directly index an + /// underlying inventory. + pub fn get_inventory( + &self, + raw_slot: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/Inventory;"); + let val_1 = jni::objects::JValueGen::Int(raw_slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getInventory", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::Inventory::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Converts a raw slot ID into its local slot ID into whichever of the two + /// inventories the slot points to. + /// + /// If the raw slot refers to the upper inventory, it will be returned + /// unchanged and thus be suitable for getTopInventory().getItem(); if it + /// refers to the lower inventory, the output will differ from the input + /// and be suitable for getBottomInventory().getItem(). + pub fn convert_slot(&self, raw_slot: i32) -> Result> { + let sig = String::from("(I)I"); + let val_1 = jni::objects::JValueGen::Int(raw_slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "convertSlot", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Determine the type of the slot by its raw slot ID. + /// + /// If the type of the slot is unknown, then + /// {@link InventoryType.SlotType#CONTAINER} will be returned. + pub fn get_slot_type( + &self, + slot: i32, + ) -> Result, Box> + { + let sig = String::from("(I)Lorg/bukkit/event/inventory/InventoryType/SlotType;"); + let val_1 = jni::objects::JValueGen::Int(slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSlotType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryTypeSlotType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Closes the inventory view. + pub fn close(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "close", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Check the total number of slots in this view, combining the upper and + /// lower inventories. + /// + /// Note though that it's possible for this to be greater than the sum of + /// the two inventories if for example some slots are not being used. + pub fn count_slots(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "countSlots", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets an extra property of this inventory if supported by that + /// inventory, for example the state of a progress bar. + pub fn set_property( + &self, + prop: impl Into>, + value: i32, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/InventoryView/Property;I)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(prop.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setProperty", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the title of this inventory window. + pub fn title(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTitle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Get the original title of this inventory window, before any changes were + /// made using {@link #setTitle(String)}. + pub fn original_title(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getOriginalTitle", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the title of this inventory window to the specified title if the + /// inventory window supports it. + /// + /// Note if the inventory does not support titles that can be changed (ie, it + /// is not creatable or viewed by a player), then this method will throw an + /// exception. + pub fn set_title(&self, title: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(title.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTitle", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for CrafterView<'mc> { + fn into(self) -> crate::inventory::InventoryView<'mc> { + crate::inventory::InventoryView::from_raw(&self.jni_ref(), self.1) + .expect("Error converting CrafterView into crate::inventory::InventoryView") + } +} +#[repr(C)] +pub struct MerchantView<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for MerchantView<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for MerchantView<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate MerchantView from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/view/MerchantView")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a MerchantView object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> MerchantView<'mc> { + /// Gets the merchant that this view is for. + pub fn merchant(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Merchant;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMerchant", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Merchant::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the upper inventory involved in this transaction. + pub fn top_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTopInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the lower inventory involved in this transaction. + pub fn bottom_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBottomInventory", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the player viewing. + pub fn player(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::HumanEntity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Determine the type of inventory involved in the transaction. This + /// indicates the window style being shown. It will never return PLAYER, + /// since that is common to all windows. + pub fn get_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets one item in this inventory view by its raw slot ID. + /// + /// Note: If slot ID -999 is chosen, it may be expected that the item is + /// dropped on the ground. This is not required behaviour, however. + pub fn set_item( + &self, + slot: i32, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(ILorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Int(slot); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItem", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets one item in this inventory view by its raw slot ID. + pub fn get_item( + &self, + slot: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/ItemStack;"); + let val_1 = jni::objects::JValueGen::Int(slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets the item on the cursor of one of the viewing players. + pub fn set_cursor( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCursor", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the item on the cursor of one of the viewing players. + pub fn cursor( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCursor", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the inventory corresponding to the given raw slot ID. + /// If the slot ID is {@link #OUTSIDE} null will be returned, otherwise + /// behaviour for illegal and negative slot IDs is undefined. + /// May be used with {@link #convertSlot(int)} to directly index an + /// underlying inventory. + pub fn get_inventory( + &self, + raw_slot: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/Inventory;"); + let val_1 = jni::objects::JValueGen::Int(raw_slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getInventory", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::Inventory::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Converts a raw slot ID into its local slot ID into whichever of the two + /// inventories the slot points to. + /// + /// If the raw slot refers to the upper inventory, it will be returned + /// unchanged and thus be suitable for getTopInventory().getItem(); if it + /// refers to the lower inventory, the output will differ from the input + /// and be suitable for getBottomInventory().getItem(). + pub fn convert_slot(&self, raw_slot: i32) -> Result> { + let sig = String::from("(I)I"); + let val_1 = jni::objects::JValueGen::Int(raw_slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "convertSlot", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Determine the type of the slot by its raw slot ID. + /// + /// If the type of the slot is unknown, then + /// {@link InventoryType.SlotType#CONTAINER} will be returned. + pub fn get_slot_type( + &self, + slot: i32, + ) -> Result, Box> + { + let sig = String::from("(I)Lorg/bukkit/event/inventory/InventoryType/SlotType;"); + let val_1 = jni::objects::JValueGen::Int(slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSlotType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryTypeSlotType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Closes the inventory view. + pub fn close(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "close", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Check the total number of slots in this view, combining the upper and + /// lower inventories. + /// + /// Note though that it's possible for this to be greater than the sum of + /// the two inventories if for example some slots are not being used. + pub fn count_slots(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "countSlots", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets an extra property of this inventory if supported by that + /// inventory, for example the state of a progress bar. + pub fn set_property( + &self, + prop: impl Into>, + value: i32, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/InventoryView/Property;I)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(prop.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setProperty", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the title of this inventory window. + pub fn title(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTitle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Get the original title of this inventory window, before any changes were + /// made using {@link #setTitle(String)}. + pub fn original_title(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getOriginalTitle", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the title of this inventory window to the specified title if the + /// inventory window supports it. + /// + /// Note if the inventory does not support titles that can be changed (ie, it + /// is not creatable or viewed by a player), then this method will throw an + /// exception. + pub fn set_title(&self, title: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(title.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTitle", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for MerchantView<'mc> { + fn into(self) -> crate::inventory::InventoryView<'mc> { + crate::inventory::InventoryView::from_raw(&self.jni_ref(), self.1) + .expect("Error converting MerchantView into crate::inventory::InventoryView") + } +} +#[repr(C)] +pub struct BeaconView<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for BeaconView<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for BeaconView<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate BeaconView from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/view/BeaconView")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BeaconView object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> BeaconView<'mc> { + /// Gets the tier of the beacon + /// + /// Beacon tier is deduced by the height of the pyramid the beacon is + /// standing on. The level of the beacon is 0 unless the beacon is activated. + pub fn tier(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTier", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the primary effect of the beacon. + /// + /// If the beacon level is high enough where the primary effect can be + /// upgraded to level two, e.g. Speed 2. Instead of + /// {@link #getSecondaryEffect()} being null it {@link #getSecondaryEffect()} + /// returns the same {@link PotionEffectType} as this method. + pub fn primary_effect( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/potion/PotionEffectType;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPrimaryEffect", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::potion::PotionEffectType::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the secondary effect of the beacon. + /// + /// If the beacon level is high enough where the primary effect can be + /// upgraded to level two, e.g. Speed 2. The secondary effect will return the + /// same effect as {@link #getPrimaryEffect()}. + pub fn secondary_effect( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/potion/PotionEffectType;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSecondaryEffect", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::potion::PotionEffectType::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets the primary effect of the beacon, or null to clear + /// + /// The {@link PotionEffectType} provided must be one that is already within + /// the beacon as a valid option. + ///
      + ///
    1. {@link PotionEffectType#SPEED} + ///
    2. {@link PotionEffectType#HASTE} + ///
    3. {@link PotionEffectType#RESISTANCE} + ///
    4. {@link PotionEffectType#JUMP_BOOST} + ///
    5. {@link PotionEffectType#STRENGTH} + ///
    6. {@link PotionEffectType#REGENERATION} + ///
    + pub fn set_primary_effect( + &self, + effect: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPrimaryEffect", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets the secondary effect on this beacon, or null to clear. Note that + /// tier must be >= 4 and a primary effect must be set in order for this + /// effect to be active. + /// + /// The {@link PotionEffectType} provided must be one that is already within + /// the beacon as a valid option. + ///
      + ///
    1. {@link PotionEffectType#SPEED} + ///
    2. {@link PotionEffectType#HASTE} + ///
    3. {@link PotionEffectType#RESISTANCE} + ///
    4. {@link PotionEffectType#JUMP_BOOST} + ///
    5. {@link PotionEffectType#STRENGTH} + ///
    6. {@link PotionEffectType#REGENERATION} + ///
    + pub fn set_secondary_effect( + &self, + effect: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/potion/PotionEffectType;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSecondaryEffect", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the upper inventory involved in this transaction. + pub fn top_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTopInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the lower inventory involved in this transaction. + pub fn bottom_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBottomInventory", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the player viewing. + pub fn player(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::HumanEntity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Determine the type of inventory involved in the transaction. This + /// indicates the window style being shown. It will never return PLAYER, + /// since that is common to all windows. + pub fn get_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets one item in this inventory view by its raw slot ID. + /// + /// Note: If slot ID -999 is chosen, it may be expected that the item is + /// dropped on the ground. This is not required behaviour, however. + pub fn set_item( + &self, + slot: i32, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(ILorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Int(slot); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItem", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets one item in this inventory view by its raw slot ID. + pub fn get_item( + &self, + slot: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/ItemStack;"); + let val_1 = jni::objects::JValueGen::Int(slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets the item on the cursor of one of the viewing players. + pub fn set_cursor( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCursor", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the item on the cursor of one of the viewing players. + pub fn cursor( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCursor", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the inventory corresponding to the given raw slot ID. + /// If the slot ID is {@link #OUTSIDE} null will be returned, otherwise + /// behaviour for illegal and negative slot IDs is undefined. + /// May be used with {@link #convertSlot(int)} to directly index an + /// underlying inventory. + pub fn get_inventory( + &self, + raw_slot: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/Inventory;"); + let val_1 = jni::objects::JValueGen::Int(raw_slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getInventory", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::Inventory::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Converts a raw slot ID into its local slot ID into whichever of the two + /// inventories the slot points to. + /// + /// If the raw slot refers to the upper inventory, it will be returned + /// unchanged and thus be suitable for getTopInventory().getItem(); if it + /// refers to the lower inventory, the output will differ from the input + /// and be suitable for getBottomInventory().getItem(). + pub fn convert_slot(&self, raw_slot: i32) -> Result> { + let sig = String::from("(I)I"); + let val_1 = jni::objects::JValueGen::Int(raw_slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "convertSlot", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Determine the type of the slot by its raw slot ID. + /// + /// If the type of the slot is unknown, then + /// {@link InventoryType.SlotType#CONTAINER} will be returned. + pub fn get_slot_type( + &self, + slot: i32, + ) -> Result, Box> + { + let sig = String::from("(I)Lorg/bukkit/event/inventory/InventoryType/SlotType;"); + let val_1 = jni::objects::JValueGen::Int(slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSlotType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryTypeSlotType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Closes the inventory view. + pub fn close(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "close", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Check the total number of slots in this view, combining the upper and + /// lower inventories. + /// + /// Note though that it's possible for this to be greater than the sum of + /// the two inventories if for example some slots are not being used. + pub fn count_slots(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "countSlots", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets an extra property of this inventory if supported by that + /// inventory, for example the state of a progress bar. + pub fn set_property( + &self, + prop: impl Into>, + value: i32, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/InventoryView/Property;I)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(prop.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setProperty", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the title of this inventory window. + pub fn title(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTitle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Get the original title of this inventory window, before any changes were + /// made using {@link #setTitle(String)}. + pub fn original_title(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getOriginalTitle", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the title of this inventory window to the specified title if the + /// inventory window supports it. + /// + /// Note if the inventory does not support titles that can be changed (ie, it + /// is not creatable or viewed by a player), then this method will throw an + /// exception. + pub fn set_title(&self, title: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(title.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTitle", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for BeaconView<'mc> { + fn into(self) -> crate::inventory::InventoryView<'mc> { + crate::inventory::InventoryView::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BeaconView into crate::inventory::InventoryView") + } +} +#[repr(C)] +pub struct AnvilView<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for AnvilView<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for AnvilView<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate AnvilView from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/view/AnvilView")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a AnvilView object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> AnvilView<'mc> { + /// Gets the rename text specified within the anvil's text field. + pub fn rename_text(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRenameText", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Gets the amount of items needed to repair. + pub fn repair_item_count_cost(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getRepairItemCountCost", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the experience cost needed to repair. + pub fn repair_cost(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRepairCost", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the maximum repair cost needed to repair. + pub fn maximum_repair_cost(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaximumRepairCost", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the amount of repair materials required to repair the item. + pub fn set_repair_item_count_cost( + &self, + amount: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(amount); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRepairItemCountCost", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets the repair cost in experience. + pub fn set_repair_cost(&self, cost: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(cost); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRepairCost", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets maximum repair cost in experience. + pub fn set_maximum_repair_cost(&self, levels: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(levels); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaximumRepairCost", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the upper inventory involved in this transaction. + pub fn top_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTopInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the lower inventory involved in this transaction. + pub fn bottom_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBottomInventory", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the player viewing. + pub fn player(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::HumanEntity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Determine the type of inventory involved in the transaction. This + /// indicates the window style being shown. It will never return PLAYER, + /// since that is common to all windows. + pub fn get_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets one item in this inventory view by its raw slot ID. + /// + /// Note: If slot ID -999 is chosen, it may be expected that the item is + /// dropped on the ground. This is not required behaviour, however. + pub fn set_item( + &self, + slot: i32, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(ILorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Int(slot); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItem", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets one item in this inventory view by its raw slot ID. + pub fn get_item( + &self, + slot: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/ItemStack;"); + let val_1 = jni::objects::JValueGen::Int(slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets the item on the cursor of one of the viewing players. + pub fn set_cursor( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCursor", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the item on the cursor of one of the viewing players. + pub fn cursor( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCursor", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the inventory corresponding to the given raw slot ID. + /// If the slot ID is {@link #OUTSIDE} null will be returned, otherwise + /// behaviour for illegal and negative slot IDs is undefined. + /// May be used with {@link #convertSlot(int)} to directly index an + /// underlying inventory. + pub fn get_inventory( + &self, + raw_slot: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/Inventory;"); + let val_1 = jni::objects::JValueGen::Int(raw_slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getInventory", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::Inventory::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Converts a raw slot ID into its local slot ID into whichever of the two + /// inventories the slot points to. + /// + /// If the raw slot refers to the upper inventory, it will be returned + /// unchanged and thus be suitable for getTopInventory().getItem(); if it + /// refers to the lower inventory, the output will differ from the input + /// and be suitable for getBottomInventory().getItem(). + pub fn convert_slot(&self, raw_slot: i32) -> Result> { + let sig = String::from("(I)I"); + let val_1 = jni::objects::JValueGen::Int(raw_slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "convertSlot", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Determine the type of the slot by its raw slot ID. + /// + /// If the type of the slot is unknown, then + /// {@link InventoryType.SlotType#CONTAINER} will be returned. + pub fn get_slot_type( + &self, + slot: i32, + ) -> Result, Box> + { + let sig = String::from("(I)Lorg/bukkit/event/inventory/InventoryType/SlotType;"); + let val_1 = jni::objects::JValueGen::Int(slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSlotType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryTypeSlotType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Closes the inventory view. + pub fn close(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "close", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Check the total number of slots in this view, combining the upper and + /// lower inventories. + /// + /// Note though that it's possible for this to be greater than the sum of + /// the two inventories if for example some slots are not being used. + pub fn count_slots(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "countSlots", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets an extra property of this inventory if supported by that + /// inventory, for example the state of a progress bar. + pub fn set_property( + &self, + prop: impl Into>, + value: i32, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/InventoryView/Property;I)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(prop.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setProperty", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the title of this inventory window. + pub fn title(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTitle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Get the original title of this inventory window, before any changes were + /// made using {@link #setTitle(String)}. + pub fn original_title(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getOriginalTitle", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the title of this inventory window to the specified title if the + /// inventory window supports it. + /// + /// Note if the inventory does not support titles that can be changed (ie, it + /// is not creatable or viewed by a player), then this method will throw an + /// exception. + pub fn set_title(&self, title: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(title.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTitle", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for AnvilView<'mc> { + fn into(self) -> crate::inventory::InventoryView<'mc> { + crate::inventory::InventoryView::from_raw(&self.jni_ref(), self.1) + .expect("Error converting AnvilView into crate::inventory::InventoryView") + } +} +#[repr(C)] +pub struct StonecutterView<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for StonecutterView<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for StonecutterView<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate StonecutterView from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/view/StonecutterView")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a StonecutterView object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> StonecutterView<'mc> { + /// Gets the current index of the selected recipe. + pub fn selected_recipe_index(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSelectedRecipeIndex", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets a copy of all recipes currently available to the player. + pub fn recipes( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRecipes", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::inventory::StonecuttingRecipe::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(new_vec) + } + /// Gets the amount of recipes currently available. + pub fn recipe_amount(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRecipeAmount", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Get the upper inventory involved in this transaction. + pub fn top_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTopInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the lower inventory involved in this transaction. + pub fn bottom_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBottomInventory", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the player viewing. + pub fn player(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::HumanEntity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Determine the type of inventory involved in the transaction. This + /// indicates the window style being shown. It will never return PLAYER, + /// since that is common to all windows. + pub fn get_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets one item in this inventory view by its raw slot ID. + /// + /// Note: If slot ID -999 is chosen, it may be expected that the item is + /// dropped on the ground. This is not required behaviour, however. + pub fn set_item( + &self, + slot: i32, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(ILorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Int(slot); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItem", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets one item in this inventory view by its raw slot ID. + pub fn get_item( + &self, + slot: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/ItemStack;"); + let val_1 = jni::objects::JValueGen::Int(slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets the item on the cursor of one of the viewing players. + pub fn set_cursor( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCursor", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the item on the cursor of one of the viewing players. + pub fn cursor( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCursor", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the inventory corresponding to the given raw slot ID. + /// If the slot ID is {@link #OUTSIDE} null will be returned, otherwise + /// behaviour for illegal and negative slot IDs is undefined. + /// May be used with {@link #convertSlot(int)} to directly index an + /// underlying inventory. + pub fn get_inventory( + &self, + raw_slot: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/Inventory;"); + let val_1 = jni::objects::JValueGen::Int(raw_slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getInventory", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::Inventory::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Converts a raw slot ID into its local slot ID into whichever of the two + /// inventories the slot points to. + /// + /// If the raw slot refers to the upper inventory, it will be returned + /// unchanged and thus be suitable for getTopInventory().getItem(); if it + /// refers to the lower inventory, the output will differ from the input + /// and be suitable for getBottomInventory().getItem(). + pub fn convert_slot(&self, raw_slot: i32) -> Result> { + let sig = String::from("(I)I"); + let val_1 = jni::objects::JValueGen::Int(raw_slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "convertSlot", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Determine the type of the slot by its raw slot ID. + /// + /// If the type of the slot is unknown, then + /// {@link InventoryType.SlotType#CONTAINER} will be returned. + pub fn get_slot_type( + &self, + slot: i32, + ) -> Result, Box> + { + let sig = String::from("(I)Lorg/bukkit/event/inventory/InventoryType/SlotType;"); + let val_1 = jni::objects::JValueGen::Int(slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSlotType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryTypeSlotType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Closes the inventory view. + pub fn close(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "close", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Check the total number of slots in this view, combining the upper and + /// lower inventories. + /// + /// Note though that it's possible for this to be greater than the sum of + /// the two inventories if for example some slots are not being used. + pub fn count_slots(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "countSlots", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets an extra property of this inventory if supported by that + /// inventory, for example the state of a progress bar. + pub fn set_property( + &self, + prop: impl Into>, + value: i32, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/InventoryView/Property;I)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(prop.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setProperty", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the title of this inventory window. + pub fn title(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTitle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Get the original title of this inventory window, before any changes were + /// made using {@link #setTitle(String)}. + pub fn original_title(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getOriginalTitle", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the title of this inventory window to the specified title if the + /// inventory window supports it. + /// + /// Note if the inventory does not support titles that can be changed (ie, it + /// is not creatable or viewed by a player), then this method will throw an + /// exception. + pub fn set_title(&self, title: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(title.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTitle", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for StonecutterView<'mc> { + fn into(self) -> crate::inventory::InventoryView<'mc> { + crate::inventory::InventoryView::from_raw(&self.jni_ref(), self.1) + .expect("Error converting StonecutterView into crate::inventory::InventoryView") + } +} +#[repr(C)] +pub struct BrewingStandView<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for BrewingStandView<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for BrewingStandView<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate BrewingStandView from null object.").into(), + ); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/inventory/view/BrewingStandView")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BrewingStandView object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> BrewingStandView<'mc> { + /// Gets the fuel level of this brewing stand. + /// + /// The default maximum fuel level in minecraft is 20. + pub fn fuel_level(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFuelLevel", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the amount of brewing ticks left. + pub fn brewing_ticks(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBrewingTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the fuel level left. + pub fn set_fuel_level(&self, level: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(level); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFuelLevel", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets the brewing ticks left. + pub fn set_brewing_ticks(&self, ticks: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBrewingTicks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the upper inventory involved in this transaction. + pub fn top_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTopInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the lower inventory involved in this transaction. + pub fn bottom_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBottomInventory", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the player viewing. + pub fn player(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::HumanEntity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Determine the type of inventory involved in the transaction. This + /// indicates the window style being shown. It will never return PLAYER, + /// since that is common to all windows. + pub fn get_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets one item in this inventory view by its raw slot ID. + /// + /// Note: If slot ID -999 is chosen, it may be expected that the item is + /// dropped on the ground. This is not required behaviour, however. + pub fn set_item( + &self, + slot: i32, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(ILorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Int(slot); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItem", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets one item in this inventory view by its raw slot ID. + pub fn get_item( + &self, + slot: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/ItemStack;"); + let val_1 = jni::objects::JValueGen::Int(slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets the item on the cursor of one of the viewing players. + pub fn set_cursor( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCursor", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the item on the cursor of one of the viewing players. + pub fn cursor( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCursor", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the inventory corresponding to the given raw slot ID. + /// If the slot ID is {@link #OUTSIDE} null will be returned, otherwise + /// behaviour for illegal and negative slot IDs is undefined. + /// May be used with {@link #convertSlot(int)} to directly index an + /// underlying inventory. + pub fn get_inventory( + &self, + raw_slot: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/Inventory;"); + let val_1 = jni::objects::JValueGen::Int(raw_slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getInventory", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::Inventory::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Converts a raw slot ID into its local slot ID into whichever of the two + /// inventories the slot points to. + /// + /// If the raw slot refers to the upper inventory, it will be returned + /// unchanged and thus be suitable for getTopInventory().getItem(); if it + /// refers to the lower inventory, the output will differ from the input + /// and be suitable for getBottomInventory().getItem(). + pub fn convert_slot(&self, raw_slot: i32) -> Result> { + let sig = String::from("(I)I"); + let val_1 = jni::objects::JValueGen::Int(raw_slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "convertSlot", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Determine the type of the slot by its raw slot ID. + /// + /// If the type of the slot is unknown, then + /// {@link InventoryType.SlotType#CONTAINER} will be returned. + pub fn get_slot_type( + &self, + slot: i32, + ) -> Result, Box> + { + let sig = String::from("(I)Lorg/bukkit/event/inventory/InventoryType/SlotType;"); + let val_1 = jni::objects::JValueGen::Int(slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSlotType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryTypeSlotType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Closes the inventory view. + pub fn close(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "close", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Check the total number of slots in this view, combining the upper and + /// lower inventories. + /// + /// Note though that it's possible for this to be greater than the sum of + /// the two inventories if for example some slots are not being used. + pub fn count_slots(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "countSlots", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets an extra property of this inventory if supported by that + /// inventory, for example the state of a progress bar. + pub fn set_property( + &self, + prop: impl Into>, + value: i32, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/InventoryView/Property;I)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(prop.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setProperty", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the title of this inventory window. + pub fn title(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTitle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Get the original title of this inventory window, before any changes were + /// made using {@link #setTitle(String)}. + pub fn original_title(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getOriginalTitle", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the title of this inventory window to the specified title if the + /// inventory window supports it. + /// + /// Note if the inventory does not support titles that can be changed (ie, it + /// is not creatable or viewed by a player), then this method will throw an + /// exception. + pub fn set_title(&self, title: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(title.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTitle", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for BrewingStandView<'mc> { + fn into(self) -> crate::inventory::InventoryView<'mc> { + crate::inventory::InventoryView::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BrewingStandView into crate::inventory::InventoryView") + } +} +#[repr(C)] +pub struct LecternView<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for LecternView<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for LecternView<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate LecternView from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/view/LecternView")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a LecternView object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> LecternView<'mc> { + /// Gets the page that the LecternView is on. + pub fn page(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPage", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets the page of the lectern book. + pub fn set_page(&self, page: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(page); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPage", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the upper inventory involved in this transaction. + pub fn top_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTopInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the lower inventory involved in this transaction. + pub fn bottom_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBottomInventory", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the player viewing. + pub fn player(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::HumanEntity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Determine the type of inventory involved in the transaction. This + /// indicates the window style being shown. It will never return PLAYER, + /// since that is common to all windows. + pub fn get_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets one item in this inventory view by its raw slot ID. + /// + /// Note: If slot ID -999 is chosen, it may be expected that the item is + /// dropped on the ground. This is not required behaviour, however. + pub fn set_item( + &self, + slot: i32, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(ILorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Int(slot); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItem", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets one item in this inventory view by its raw slot ID. + pub fn get_item( + &self, + slot: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/ItemStack;"); + let val_1 = jni::objects::JValueGen::Int(slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets the item on the cursor of one of the viewing players. + pub fn set_cursor( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCursor", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the item on the cursor of one of the viewing players. + pub fn cursor( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCursor", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the inventory corresponding to the given raw slot ID. + /// If the slot ID is {@link #OUTSIDE} null will be returned, otherwise + /// behaviour for illegal and negative slot IDs is undefined. + /// May be used with {@link #convertSlot(int)} to directly index an + /// underlying inventory. + pub fn get_inventory( + &self, + raw_slot: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/Inventory;"); + let val_1 = jni::objects::JValueGen::Int(raw_slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getInventory", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::Inventory::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Converts a raw slot ID into its local slot ID into whichever of the two + /// inventories the slot points to. + /// + /// If the raw slot refers to the upper inventory, it will be returned + /// unchanged and thus be suitable for getTopInventory().getItem(); if it + /// refers to the lower inventory, the output will differ from the input + /// and be suitable for getBottomInventory().getItem(). + pub fn convert_slot(&self, raw_slot: i32) -> Result> { + let sig = String::from("(I)I"); + let val_1 = jni::objects::JValueGen::Int(raw_slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "convertSlot", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Determine the type of the slot by its raw slot ID. + /// + /// If the type of the slot is unknown, then + /// {@link InventoryType.SlotType#CONTAINER} will be returned. + pub fn get_slot_type( + &self, + slot: i32, + ) -> Result, Box> + { + let sig = String::from("(I)Lorg/bukkit/event/inventory/InventoryType/SlotType;"); + let val_1 = jni::objects::JValueGen::Int(slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSlotType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryTypeSlotType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Closes the inventory view. + pub fn close(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "close", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Check the total number of slots in this view, combining the upper and + /// lower inventories. + /// + /// Note though that it's possible for this to be greater than the sum of + /// the two inventories if for example some slots are not being used. + pub fn count_slots(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "countSlots", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets an extra property of this inventory if supported by that + /// inventory, for example the state of a progress bar. + pub fn set_property( + &self, + prop: impl Into>, + value: i32, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/InventoryView/Property;I)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(prop.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setProperty", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the title of this inventory window. + pub fn title(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTitle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Get the original title of this inventory window, before any changes were + /// made using {@link #setTitle(String)}. + pub fn original_title(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getOriginalTitle", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the title of this inventory window to the specified title if the + /// inventory window supports it. + /// + /// Note if the inventory does not support titles that can be changed (ie, it + /// is not creatable or viewed by a player), then this method will throw an + /// exception. + pub fn set_title(&self, title: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(title.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTitle", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for LecternView<'mc> { + fn into(self) -> crate::inventory::InventoryView<'mc> { + crate::inventory::InventoryView::from_raw(&self.jni_ref(), self.1) + .expect("Error converting LecternView into crate::inventory::InventoryView") + } +} +#[repr(C)] +pub struct FurnaceView<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for FurnaceView<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for FurnaceView<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate FurnaceView from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/inventory/view/FurnaceView")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a FurnaceView object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> FurnaceView<'mc> { + /// The cook time for this view. + /// + /// See {@link Furnace#getCookTime()} for more information. + pub fn cook_time(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCookTime", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// The total burn time for this view. + /// + /// See {@link Furnace#getBurnTime()} for more information. + pub fn burn_time(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBurnTime", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Checks whether or not the furnace is burning + pub fn is_burning(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isBurning", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the cook time + /// + /// Setting cook time requires manipulation of both cookProgress and + /// cookDuration. This method does a simple division to get total progress + /// within the furnaces visual duration bar. For a clear visual effect + /// (cookProgress / cookDuration) should return a number between 0 and 1 + /// inclusively. + pub fn set_cook_time( + &self, + cook_progress: i32, + cook_duration: i32, + ) -> Result<(), Box> { + let sig = String::from("(II)V"); + let val_1 = jni::objects::JValueGen::Int(cook_progress); + let val_2 = jni::objects::JValueGen::Int(cook_duration); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCookTime", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets the burn time + /// + /// Setting burn time requires manipulation of both burnProgress and + /// burnDuration. This method does a simple division to get total progress + /// within the furnaces visual burning bar. For a clear visual effect + /// (burnProgress / burnDuration) should return a number between 0 and 1 + /// inclusively. + pub fn set_burn_time( + &self, + burn_progress: i32, + burn_duration: i32, + ) -> Result<(), Box> { + let sig = String::from("(II)V"); + let val_1 = jni::objects::JValueGen::Int(burn_progress); + let val_2 = jni::objects::JValueGen::Int(burn_duration); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBurnTime", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the upper inventory involved in this transaction. + pub fn top_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTopInventory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the lower inventory involved in this transaction. + pub fn bottom_inventory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/Inventory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBottomInventory", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the player viewing. + pub fn player(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/HumanEntity;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::HumanEntity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Determine the type of inventory involved in the transaction. This + /// indicates the window style being shown. It will never return PLAYER, + /// since that is common to all windows. + pub fn get_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/inventory/InventoryType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets one item in this inventory view by its raw slot ID. + /// + /// Note: If slot ID -999 is chosen, it may be expected that the item is + /// dropped on the ground. This is not required behaviour, however. + pub fn set_item( + &self, + slot: i32, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(ILorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Int(slot); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setItem", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets one item in this inventory view by its raw slot ID. + pub fn get_item( + &self, + slot: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/ItemStack;"); + let val_1 = jni::objects::JValueGen::Int(slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItem", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets the item on the cursor of one of the viewing players. + pub fn set_cursor( + &self, + item: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCursor", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the item on the cursor of one of the viewing players. + pub fn cursor( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemStack;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCursor", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemStack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the inventory corresponding to the given raw slot ID. + /// If the slot ID is {@link #OUTSIDE} null will be returned, otherwise + /// behaviour for illegal and negative slot IDs is undefined. + /// May be used with {@link #convertSlot(int)} to directly index an + /// underlying inventory. + pub fn get_inventory( + &self, + raw_slot: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/inventory/Inventory;"); + let val_1 = jni::objects::JValueGen::Int(raw_slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getInventory", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::Inventory::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Converts a raw slot ID into its local slot ID into whichever of the two + /// inventories the slot points to. + /// + /// If the raw slot refers to the upper inventory, it will be returned + /// unchanged and thus be suitable for getTopInventory().getItem(); if it + /// refers to the lower inventory, the output will differ from the input + /// and be suitable for getBottomInventory().getItem(). + pub fn convert_slot(&self, raw_slot: i32) -> Result> { + let sig = String::from("(I)I"); + let val_1 = jni::objects::JValueGen::Int(raw_slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "convertSlot", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Determine the type of the slot by its raw slot ID. + /// + /// If the type of the slot is unknown, then + /// {@link InventoryType.SlotType#CONTAINER} will be returned. + pub fn get_slot_type( + &self, + slot: i32, + ) -> Result, Box> + { + let sig = String::from("(I)Lorg/bukkit/event/inventory/InventoryType/SlotType;"); + let val_1 = jni::objects::JValueGen::Int(slot); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSlotType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::event::inventory::InventoryTypeSlotType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Closes the inventory view. + pub fn close(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "close", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Check the total number of slots in this view, combining the upper and + /// lower inventories. + /// + /// Note though that it's possible for this to be greater than the sum of + /// the two inventories if for example some slots are not being used. + pub fn count_slots(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "countSlots", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Sets an extra property of this inventory if supported by that + /// inventory, for example the state of a progress bar. + pub fn set_property( + &self, + prop: impl Into>, + value: i32, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/InventoryView/Property;I)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(prop.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setProperty", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the title of this inventory window. + pub fn title(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTitle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Get the original title of this inventory window, before any changes were + /// made using {@link #setTitle(String)}. + pub fn original_title(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getOriginalTitle", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Sets the title of this inventory window to the specified title if the + /// inventory window supports it. + /// + /// Note if the inventory does not support titles that can be changed (ie, it + /// is not creatable or viewed by a player), then this method will throw an + /// exception. + pub fn set_title(&self, title: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(title.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTitle", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for FurnaceView<'mc> { + fn into(self) -> crate::inventory::InventoryView<'mc> { + crate::inventory::InventoryView::from_raw(&self.jni_ref(), self.1) + .expect("Error converting FurnaceView into crate::inventory::InventoryView") + } +} diff --git a/blackboxmc-rs-bukkit/src/lib.rs b/blackboxmc-rs-bukkit/src/lib.rs index f72b850..4d6b4d3 100644 --- a/blackboxmc-rs-bukkit/src/lib.rs +++ b/blackboxmc-rs-bukkit/src/lib.rs @@ -2,25 +2,46 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; -pub enum Art<'mc> {} -impl<'mc> std::fmt::Display for Art<'mc> { +pub enum WorldType<'mc> { + Normal { inner: WorldTypeStruct<'mc> }, + Flat { inner: WorldTypeStruct<'mc> }, + LargeBiomes { inner: WorldTypeStruct<'mc> }, + Amplified { inner: WorldTypeStruct<'mc> }, +} +impl<'mc> std::fmt::Display for WorldType<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + WorldType::Normal { .. } => f.write_str("NORMAL"), + WorldType::Flat { .. } => f.write_str("FLAT"), + WorldType::LargeBiomes { .. } => f.write_str("LARGE_BIOMES"), + WorldType::Amplified { .. } => f.write_str("AMPLIFIED"), + } + } +} +impl<'mc> std::ops::Deref for WorldType<'mc> { + type Target = WorldTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + WorldType::Normal { inner } => inner, + WorldType::Flat { inner } => inner, + WorldType::LargeBiomes { inner } => inner, + WorldType::Amplified { inner } => inner, + } } } -impl<'mc> Art<'mc> { +impl<'mc> WorldType<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/Art"); + let cls = env.find_class("org/bukkit/WorldType"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/Art;", + "(Ljava/lang/String;)Lorg/bukkit/WorldType;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -32,37 +53,64 @@ impl<'mc> Art<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NORMAL" => Ok(WorldType::Normal { + inner: WorldTypeStruct::from_raw(env, obj)?, + }), + "FLAT" => Ok(WorldType::Flat { + inner: WorldTypeStruct::from_raw(env, obj)?, + }), + "LARGE_BIOMES" => Ok(WorldType::LargeBiomes { + inner: WorldTypeStruct::from_raw(env, obj)?, + }), + "AMPLIFIED" => Ok(WorldType::Amplified { + inner: WorldTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct ArtStruct<'mc>( +pub struct WorldTypeStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Art<'mc> { +impl<'mc> JNIRaw<'mc> for WorldType<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Normal { inner } => inner.0.clone(), + Self::Flat { inner } => inner.0.clone(), + Self::LargeBiomes { inner } => inner.0.clone(), + Self::Amplified { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Normal { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Flat { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::LargeBiomes { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Amplified { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } -impl<'mc> JNIInstantiatable<'mc> for Art<'mc> { +impl<'mc> JNIInstantiatable<'mc> for WorldType<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Art from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate WorldType from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Art")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/WorldType")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Art object, got {}", + "Invalid argument passed. Expected a WorldType object, got {}", name ) .into()) @@ -74,13 +122,25 @@ impl<'mc> JNIInstantiatable<'mc> for Art<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NORMAL" => Ok(WorldType::Normal { + inner: WorldTypeStruct::from_raw(env, obj)?, + }), + "FLAT" => Ok(WorldType::Flat { + inner: WorldTypeStruct::from_raw(env, obj)?, + }), + "LARGE_BIOMES" => Ok(WorldType::LargeBiomes { + inner: WorldTypeStruct::from_raw(env, obj)?, + }), + "AMPLIFIED" => Ok(WorldType::Amplified { + inner: WorldTypeStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for ArtStruct<'mc> { +impl<'mc> JNIRaw<'mc> for WorldTypeStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -88,18 +148,20 @@ impl<'mc> JNIRaw<'mc> for ArtStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ArtStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for WorldTypeStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ArtStruct from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate WorldTypeStruct from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Art")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/WorldType")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ArtStruct object, got {}", + "Invalid argument passed. Expected a WorldTypeStruct object, got {}", name ) .into()) @@ -109,92 +171,41 @@ impl<'mc> JNIInstantiatable<'mc> for ArtStruct<'mc> { } } -impl<'mc> ArtStruct<'mc> { +impl<'mc> WorldTypeStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Art;"); - let cls = jni.find_class("org/bukkit/Art"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/WorldType;"); + let cls = jni.find_class("org/bukkit/WorldType"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::Art::from_raw(&jni, obj) - } - /// Gets the width of the painting, in blocks - pub fn block_width(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBlockWidth", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the height of the painting, in blocks - pub fn block_height(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBlockHeight", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::WorldType::from_raw(&jni, obj) } - #[deprecated] - /// Get the ID of this painting. - pub fn id(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the name of this WorldType + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getId", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); - let res = self + Ok(self .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - #[deprecated] - /// Get a painting by its numeric ID - pub fn get_by_id( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - id: i32, - ) -> Result>, Box> { - let sig = String::from("(I)Lorg/bukkit/Art;"); - let val_1 = jni::objects::JValueGen::Int(id); - let cls = jni.find_class("org/bukkit/Art"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getById", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::Art::from_raw(&jni, obj)?)) + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Get a painting by its unique name - /// - /// This ignores underscores and capitalization + /// Gets a WorldType by its name pub fn get_by_name( jni: &blackboxmc_general::SharedJNIEnv<'mc>, name: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/Art;"); + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/WorldType;"); let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( jni.new_string(name.into())?, )); - let cls = jni.find_class("org/bukkit/Art"); + let cls = jni.find_class("org/bukkit/WorldType"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method( cls, @@ -207,7 +218,7 @@ impl<'mc> ArtStruct<'mc> { return Ok(None); } let obj = res.l()?; - Ok(Some(crate::Art::from_raw(&jni, obj)?)) + Ok(Some(crate::WorldType::from_raw(&jni, obj)?)) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -216,12 +227,12 @@ impl<'mc> ArtStruct<'mc> { } } #[repr(C)] -pub struct MinecraftExperimental<'mc>( +pub struct WorldCreator<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for MinecraftExperimental<'mc> { +impl<'mc> JNIRaw<'mc> for WorldCreator<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -229,2226 +240,2616 @@ impl<'mc> JNIRaw<'mc> for MinecraftExperimental<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for MinecraftExperimental<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate MinecraftExperimental from null object." - ) - .into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/MinecraftExperimental")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a MinecraftExperimental object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> MinecraftExperimental<'mc> { - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -pub enum MinecraftExperimentalRequires<'mc> {} -impl<'mc> std::fmt::Display for MinecraftExperimentalRequires<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> MinecraftExperimentalRequires<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/MinecraftExperimental/Requires"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/MinecraftExperimental/Requires;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct MinecraftExperimentalRequiresStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for MinecraftExperimentalRequires<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for MinecraftExperimentalRequires<'mc> { +impl<'mc> JNIInstantiatable<'mc> for WorldCreator<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate MinecraftExperimentalRequires from null object." - ) - .into()); + return Err(eyre::eyre!("Tried to instantiate WorldCreator from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/MinecraftExperimental/Requires")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/WorldCreator")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a MinecraftExperimentalRequires object, got {}", + "Invalid argument passed. Expected a WorldCreator object, got {}", name ) .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for MinecraftExperimentalRequiresStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for MinecraftExperimentalRequiresStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate MinecraftExperimentalRequiresStruct from null object." - ) - .into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/MinecraftExperimental/Requires")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a MinecraftExperimentalRequiresStruct object, got {}", - name - ) - .into()) } else { Ok(Self(env.clone(), obj)) } } } -impl<'mc> MinecraftExperimentalRequiresStruct<'mc> { - pub fn values( +impl<'mc> WorldCreator<'mc> { + /// Creates an empty WorldCreationOptions for the given world name + pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/MinecraftExperimental/Requires;"); - let cls = jni.find_class("org/bukkit/MinecraftExperimental/Requires"); + name: impl Into, + ) -> Result, Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(name.into())?, + )); + let cls = jni.find_class("org/bukkit/WorldCreator"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::MinecraftExperimentalRequires::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -pub enum Material<'mc> { - LegacyPrefix { inner: MaterialStruct<'mc> }, - Data { inner: MaterialStruct<'mc> }, -} -impl<'mc> std::fmt::Display for Material<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Material::LegacyPrefix { .. } => f.write_str("LEGACY_PREFIX"), - Material::Data { .. } => f.write_str("data"), - } - } -} - -impl<'mc> Material<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/Material"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( + let res = jni.new_object( cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/Material;", + sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - "LEGACY_PREFIX" => Ok(Material::LegacyPrefix { - inner: MaterialStruct::from_raw(env, obj)?, - }), - "data" => Ok(Material::Data { - inner: MaterialStruct::from_raw(env, obj)?, - }), - - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct MaterialStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Material<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self { - Self::LegacyPrefix { inner } => inner.0.clone(), - Self::Data { inner } => inner.0.clone(), - } - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self { - Self::LegacyPrefix { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::Data { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - } - } -} -impl<'mc> JNIInstantiatable<'mc> for Material<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Material from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Material")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Material object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - "LEGACY_PREFIX" => Ok(Material::LegacyPrefix { - inner: MaterialStruct::from_raw(env, obj)?, - }), - "data" => Ok(Material::Data { - inner: MaterialStruct::from_raw(env, obj)?, - }), - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for MaterialStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + let res = jni.translate_error_no_gen(res)?; + crate::WorldCreator::from_raw(&jni, res) } -} -impl<'mc> JNIInstantiatable<'mc> for MaterialStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate MaterialStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Material")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a MaterialStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Copies the options from the specified {@link WorldCreator} + pub fn copy( + &self, + creator: impl Into>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/WorldCreator;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(creator.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Lorg/bukkit/WorldCreator;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::WorldCreator::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} - -impl<'mc> MaterialStruct<'mc> { - pub fn values( + /// Creates a new {@link WorldCreator} for the given world name + pub fn name( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); - let cls = jni.find_class("org/bukkit/Material"); + name: std::option::Option>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = name { + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(a.into())?, + )); + args.push(val_1); + } + sig += ")Lorg/bukkit/WorldCreator;"; + let cls = jni.find_class("org/bukkit/WorldCreator"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.call_static_method(cls, "name", sig.as_str(), args); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::Material::from_raw(&jni, obj) + crate::WorldCreator::from_raw(&jni, obj) } - #[deprecated] - /// Do not use for any reason. - pub fn id(&self) -> Result> { - let sig = String::from("()I"); + /// Sets the seed that will be used to create this world + pub fn seed( + &self, + seed: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = seed { + sig += "J"; + let val_1 = jni::objects::JValueGen::Long(a); + args.push(val_1); + } + sig += ")Lorg/bukkit/WorldCreator;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getId", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "seed", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::WorldCreator::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - /// Do not use for any reason. - pub fn is_legacy(&self) -> Result> { - let sig = String::from("()Z"); + /// Sets the environment that will be used to create or load the world + pub fn environment( + &self, + env: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = env { + sig += "Lorg/bukkit/World/Environment;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Lorg/bukkit/WorldCreator;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isLegacy", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "environment", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::WorldCreator::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + /// Sets the type of the world that will be created or loaded + pub fn get_type( + &self, + val_type: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = val_type { + sig += "Lorg/bukkit/WorldType;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Lorg/bukkit/WorldCreator;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "type", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + crate::WorldCreator::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the maximum amount of this material that can be held in a stack. + /// Sets the generator that will be used to create or load the world. /// - /// Note that this is the default maximum size for this Material. - /// {@link ItemStack ItemStacks} are able to change their maximum stack size per - /// stack with {@link ItemMeta#setMaxStackSize(Integer)}. If an ItemStack instance - /// is available, {@link ItemStack#getMaxStackSize()} may be preferred. - pub fn max_stack_size(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the maximum durability of this material - pub fn max_durability(&self) -> Result> { - let sig = String::from("()S"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMaxDurability", - sig.as_str(), - vec![], - ); + /// This may be null, in which case the "natural" generator for this + /// environment will be used. + /// + /// If the generator cannot be found for the given name, the natural + /// environment generator will be used instead and a warning will be + /// printed to the specified output + pub fn generator( + &self, + generator: std::option::Option>, + output: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = generator { + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_1); + } + if let Some(a) = output { + sig += "Lorg/bukkit/command/CommandSender;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/WorldCreator;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "generator", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.s()?) + crate::WorldCreator::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Creates a new {@link BlockData} instance for this Material, with all - /// properties initialized to unspecified defaults, except for those provided - /// in data. - pub fn create_block_data( + /// Sets the biome provider that will be used to create or load the world. + /// + /// This may be null, in which case the biome provider from the + /// {@link ChunkGenerator} will be used. If no {@link ChunkGenerator} is + /// specific the "natural" biome provider for this environment will be used. + /// + /// If the biome provider cannot be found for the given name and no + /// {@link ChunkGenerator} is specific, the natural environment biome + /// provider will be used instead and a warning will be printed to the + /// specified output + pub fn biome_provider( &self, - data: std::option::Option>, - ) -> Result, Box> { + biome_provider: std::option::Option>, + output: std::option::Option>>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = data { + if let Some(a) = biome_provider { sig += "Ljava/lang/String;"; let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( self.jni_ref().new_string(a.into())?, )); args.push(val_1); } - sig += ")Lorg/bukkit/block/data/BlockData;"; + if let Some(a) = output { + sig += "Lorg/bukkit/command/CommandSender;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/WorldCreator;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "createBlockData", sig.as_str(), args); + .call_method(&self.jni_object(), "biomeProvider", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { + crate::WorldCreator::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the MaterialData class associated with this Material - pub fn data(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/Class;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + /// Sets the generator settings of the world that will be created or loaded. + /// + /// Currently only {@link WorldType#FLAT} uses these settings, and expects + /// them to be in JSON format with a valid biome (1.18.2 and + /// above) defined. An example valid configuration is as follows: + /// {"layers": [{"block": "stone", "height": 1}, {"block": "grass_block", "height": 1}], "biome":"plains"} + pub fn generator_settings( + &self, + generator_settings: std::option::Option>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = generator_settings { + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_1); + } + sig += ")Lorg/bukkit/WorldCreator;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "generatorSettings", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(unsafe { jni::objects::JClass::from_raw(res.as_jni().l) }) + crate::WorldCreator::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - /// Constructs a new MaterialData relevant for this Material, with the given initial data - pub fn get_new_data( + /// Sets whether or not worlds created or loaded with this creator will + /// have structures. + pub fn generate_structures( &self, - raw: i8, - ) -> Result, Box> { - let sig = String::from("(B)Lorg/bukkit/material/MaterialData;"); - let val_1 = jni::objects::JValueGen::Byte(raw); + generate: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = generate { + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_1); + } + sig += ")Lorg/bukkit/WorldCreator;"; let res = self.jni_ref().call_method( &self.jni_object(), - "getNewData", + "generateStructures", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); let res = self.jni_ref().translate_error(res)?; - crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { + crate::WorldCreator::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Checks if this Material is a placable block - pub fn is_block(&self) -> Result> { - let sig = String::from("()Z"); + /// Sets whether the world will be hardcore or not. + /// In a hardcore world the difficulty will be locked to hard. + pub fn hardcore( + &self, + hardcore: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = hardcore { + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_1); + } + sig += ")Lorg/bukkit/WorldCreator;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isBlock", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hardcore", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::WorldCreator::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Checks if this Material is edible. - pub fn is_edible(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isEdible", sig.as_str(), vec![]); + /// Sets whether the spawn chunks will be kept loaded. + /// + /// Setting this to false will also stop the spawn chunks from being generated + /// when creating a new world. + /// + /// Has little performance benefit unless paired with a {@link ChunkGenerator} + /// that overrides {@link ChunkGenerator#getFixedSpawnLocation(World, Random)}. + pub fn keep_spawn_in_memory( + &self, + keep_spawn_in_memory: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = keep_spawn_in_memory { + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_1); + } + sig += ")Lorg/bukkit/WorldCreator;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "keepSpawnInMemory", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::WorldCreator::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Attempts to get the Material with the given name. + /// Creates a world with the specified options. /// - /// This is a normal lookup, names must be the precise name they are given in - /// the enum (but optionally including the LEGACY_PREFIX if legacyName is - /// true). + /// If the world already exists, it will be loaded from disk and some + /// options may be ignored. + pub fn create_world(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Attempts to get the {@link ChunkGenerator} with the given name. /// - /// If legacyName is true, then the lookup will be against legacy materials, - /// but the returned Material will be a modern material (ie this method is - /// useful for updating stored data). - pub fn get_material( + /// If the generator is not found, null will be returned and a message will + /// be printed to the specified {@link CommandSender} explaining why. + /// + /// The name must be in the "plugin:id" notation, or optionally just + /// "plugin", where "plugin" is the safe-name of a plugin and "id" is an + /// optional unique identifier for the generator you wish to request from + /// the plugin. + pub fn get_generator_for_name( jni: &blackboxmc_general::SharedJNIEnv<'mc>, + world: impl Into, name: impl Into, - legacy_name: std::option::Option, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; + output: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;Ljava/lang/String;Lorg/bukkit/command/CommandSender;)Lorg/bukkit/generator/ChunkGenerator;"); let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(world.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( jni.new_string(name.into())?, )); - args.push(val_1); - if let Some(a) = legacy_name { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")Lorg/bukkit/Material;"; - let cls = jni.find_class("org/bukkit/Material"); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(output.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/WorldCreator"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getMaterial", sig.as_str(), args); + let res = jni.call_static_method( + cls, + "getGeneratorForName", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); let res = jni.translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } let obj = res.l()?; - Ok(Some(crate::Material::from_raw(&jni, obj)?)) + Ok(Some(crate::generator::ChunkGenerator::from_raw(&jni, obj)?)) } - /// Attempts to match the Material with the given name. + /// Attempts to get the {@link BiomeProvider} with the given name. /// - /// This is a match lookup; names will be stripped of the "minecraft:" - /// namespace, converted to uppercase, then stripped of special characters in - /// an attempt to format it like the enum. - pub fn match_material( + /// If the biome provider is not found, null will be returned and a message + /// will be printed to the specified {@link CommandSender} explaining why. + /// + /// The name must be in the "plugin:id" notation, or optionally just + /// "plugin", where "plugin" is the safe-name of a plugin and "id" is an + /// optional unique identifier for the biome provider you wish to request + /// from the plugin. + pub fn get_biome_provider_for_name( jni: &blackboxmc_general::SharedJNIEnv<'mc>, + world: impl Into, name: impl Into, - legacy_name: std::option::Option, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; + output: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;Ljava/lang/String;Lorg/bukkit/command/CommandSender;)Lorg/bukkit/generator/BiomeProvider;"); let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(world.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( jni.new_string(name.into())?, )); - args.push(val_1); - if let Some(a) = legacy_name { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")Lorg/bukkit/Material;"; - let cls = jni.find_class("org/bukkit/Material"); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(output.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/WorldCreator"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "matchMaterial", sig.as_str(), args); + let res = jni.call_static_method( + cls, + "getBiomeProviderForName", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); let res = jni.translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } let obj = res.l()?; - Ok(Some(crate::Material::from_raw(&jni, obj)?)) + Ok(Some(crate::generator::BiomeProvider::from_raw(&jni, obj)?)) } - pub fn is_record(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isRecord", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Check if the material is a block and solid (can be built upon) - pub fn is_solid(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSolid", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} +#[repr(C)] +pub struct World<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for World<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Check if the material is an air block. - pub fn is_air(&self) -> Result> { - let sig = String::from("()Z"); + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for World<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate World from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/World")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a World object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> World<'mc> { + /// Gets the {@link Block} at the given coordinates + pub fn get_block_at( + &self, + x: i32, + y: std::option::Option, + z: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); + args.push(val_1); + if let Some(a) = y { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + if let Some(a) = z { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + sig += ")Lorg/bukkit/block/Block;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isAir", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBlockAt", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - /// Check if the material is a block and does not block any light - pub fn is_transparent(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the highest block corresponding to the {@link HeightMap} at the + /// given coordinates. + pub fn get_highest_block_at( + &self, + location: impl Into>, + height_map: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = height_map { + sig += "Lorg/bukkit/HeightMap;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/block/Block;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "isTransparent", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getHighestBlockAt", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Check if the material is a block and can catch fire - pub fn is_flammable(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the {@link Chunk} at the given coordinates + pub fn get_chunk_at( + &self, + x: i32, + z: std::option::Option, + generate: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); + args.push(val_1); + if let Some(a) = z { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + if let Some(a) = generate { + sig += "Z"; + let val_3 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_3); + } + sig += ")Lorg/bukkit/Chunk;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getChunkAt", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::Chunk::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Checks if the {@link Chunk} at the specified coordinates is loaded + pub fn is_chunk_loaded( + &self, + x: i32, + z: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); + args.push(val_1); + if let Some(a) = z { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + sig += ")Z"; let res = self.jni_ref() - .call_method(&self.jni_object(), "isFlammable", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isChunkLoaded", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Check if the material is a block and can burn away - pub fn is_burnable(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets an array of all loaded {@link Chunk}s + pub fn loaded_chunks(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Chunk;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isBurnable", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLoadedChunks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Chunk::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Checks if this Material can be used as fuel in a Furnace - pub fn is_fuel(&self) -> Result> { - let sig = String::from("()Z"); + /// Loads the {@link Chunk} at the specified coordinates. + /// + /// This method will keep the specified chunk loaded until one of the + /// unload methods is manually called. Callers are advised to instead use + /// getChunkAt which will only temporarily load the requested chunk. + pub fn load_chunk( + &self, + x: i32, + z: std::option::Option, + generate: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); + args.push(val_1); + if let Some(a) = z { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + if let Some(a) = generate { + sig += "Z"; + let val_3 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_3); + } + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isFuel", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "loadChunk", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Check if the material is a block and occludes light in the lighting engine. - /// - /// Generally speaking, most full blocks will occlude light. Non-full blocks are - /// not occluding (e.g. anvils, chests, tall grass, stairs, etc.), nor are specific - /// full blocks such as barriers or spawners which block light despite their texture. - /// - /// An occluding block will have the following effects: - ///
      - ///
    • Chests cannot be opened if an occluding block is above it. - ///
    • Mobs cannot spawn inside of occluding blocks. - ///
    • Only occluding blocks can be "powered" ({@link Block#isBlockPowered()}). - ///
    - /// This list may be inconclusive. For a full list of the side effects of an occluding - /// block, see the Minecraft Wiki. - pub fn is_occluding(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isOccluding", sig.as_str(), vec![]); + /// Checks if the {@link Chunk} at the specified coordinates is generated + pub fn is_chunk_generated(&self, x: i32, z: i32) -> Result> { + let sig = String::from("(II)Z"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(z); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isChunkGenerated", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - - pub fn has_gravity(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); + #[deprecated] + /// Checks if the {@link Chunk} at the specified coordinates is loaded and in use by one or more players + pub fn is_chunk_in_use(&self, x: i32, z: i32) -> Result> { + let sig = String::from("(II)Z"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(z); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isChunkInUse", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Checks if this Material is an obtainable item. - pub fn is_item(&self) -> Result> { - let sig = String::from("()Z"); + /// Safely unloads and optionally saves the {@link Chunk} at the specified + /// coordinates. + pub fn unload_chunk( + &self, + x: i32, + z: std::option::Option, + save: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); + args.push(val_1); + if let Some(a) = z { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + if let Some(a) = save { + sig += "Z"; + let val_3 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_3); + } + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isItem", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "unloadChunk", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Checks if this Material can be interacted with. - /// Interactable materials include those with functionality when they are - /// interacted with by a player such as chests, furnaces, etc. - /// Some blocks such as piston heads and stairs are considered interactable - /// though may not perform any additional functionality. - /// Note that the interactability of some materials may be dependant on their - /// state as well. This method will return true if there is at least one - /// state in which additional interact handling is performed for the - /// material. - pub fn is_interactable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInteractable", sig.as_str(), vec![]); + /// Safely queues the {@link Chunk} at the specified coordinates for + /// unloading. + pub fn unload_chunk_request(&self, x: i32, z: i32) -> Result> { + let sig = String::from("(II)Z"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(z); + let res = self.jni_ref().call_method( + &self.jni_object(), + "unloadChunkRequest", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Obtains the block's hardness level (also known as "strength"). - /// - /// This number is used to calculate the time required to break each block. - /// - /// Only available when {@link #isBlock()} is true. - pub fn hardness(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHardness", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Obtains the blast resistance value (also known as block "durability"). - /// - /// This value is used in explosions to calculate whether a block should be - /// broken or not. - /// - /// Only available when {@link #isBlock()} is true. - pub fn blast_resistance(&self) -> Result> { - let sig = String::from("()F"); + #[deprecated] + /// Regenerates the {@link Chunk} at the specified coordinates + pub fn regenerate_chunk(&self, x: i32, z: i32) -> Result> { + let sig = String::from("(II)Z"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(z); let res = self.jni_ref().call_method( &self.jni_object(), - "getBlastResistance", + "regenerateChunk", sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Returns a value that represents how 'slippery' the block is. - /// Blocks with higher slipperiness, like {@link Material#ICE} can be slid on - /// further by the player and other entities. - /// Most blocks have a default slipperiness of {@code 0.6f}. - /// Only available when {@link #isBlock()} is true. - pub fn slipperiness(&self) -> Result> { - let sig = String::from("()F"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSlipperiness", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + Ok(res.z()?) } - /// Determines the remaining item in a crafting grid after crafting with this - /// ingredient. - /// - /// Only available when {@link #isItem()} is true. - pub fn crafting_remaining_item( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); + #[deprecated] + /// Resends the {@link Chunk} to all clients + pub fn refresh_chunk(&self, x: i32, z: i32) -> Result> { + let sig = String::from("(II)Z"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(z); let res = self.jni_ref().call_method( &self.jni_object(), - "getCraftingRemainingItem", + "refreshChunk", sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.z()?) } - /// Get the best suitable slot for this Material. - /// For most items this will be {@link EquipmentSlot#HAND}. - pub fn equipment_slot( + /// Get a list of all players who are can view the specified chunk from their + /// client + /// + /// This list will be empty if no players are viewing the chunk, or the chunk + /// is unloaded. + pub fn get_players_seeing_chunk( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/EquipmentSlot;"); + x: i32, + z: std::option::Option, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); + args.push(val_1); + if let Some(a) = z { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + sig += ")Ljava/util/Collection;"; let res = self.jni_ref().call_method( &self.jni_object(), - "getEquipmentSlot", + "getPlayersSeeingChunk", sig.as_str(), - vec![], + args, ); let res = self.jni_ref().translate_error(res)?; - crate::inventory::EquipmentSlot::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Player::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Return an immutable copy of all default {@link Attribute}s and their - /// {@link AttributeModifier}s for a given {@link EquipmentSlot}. - /// Default attributes are those that are always preset on some items, such - /// as the attack damage on weapons or the armor value on armor. - /// Only available when {@link #isItem()} is true. - pub fn get_default_attribute_modifiers( + /// Gets whether the chunk at the specified chunk coordinates is force + /// loaded. + /// + /// A force loaded chunk will not be unloaded due to lack of player activity. + pub fn is_chunk_force_loaded( &self, - slot: impl Into>, - ) -> Result, Box> { - let sig = String::from( - "(Lorg/bukkit/inventory/EquipmentSlot;)Lcom/google/common/collect/Multimap;", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(slot.into().jni_object().clone()) - }); + x: i32, + z: i32, + ) -> Result> { + let sig = String::from("(II)Z"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(z); let res = self.jni_ref().call_method( &self.jni_object(), - "getDefaultAttributeModifiers", + "isChunkForceLoaded", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) + Ok(res.z()?) } - /// Get the {@link CreativeCategory} to which this material belongs. - pub fn creative_category( + /// Sets whether the chunk at the specified chunk coordinates is force + /// loaded. + /// + /// A force loaded chunk will not be unloaded due to lack of player activity. + pub fn set_chunk_force_loaded( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/CreativeCategory;"); + x: i32, + z: i32, + forced: bool, + ) -> Result<(), Box> { + let sig = String::from("(IIZ)V"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(z); + let val_3 = jni::objects::JValueGen::Bool(forced.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getCreativeCategory", + "setChunkForceLoaded", sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::CreativeCategory::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the translation key of the item or block associated with this - /// material. - /// If this material has both an item and a block form, the item form is - /// used. - pub fn translation_key(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Returns all force loaded chunks in this world. + /// + /// A force loaded chunk will not be unloaded due to lack of player activity. + pub fn force_loaded_chunks( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getTranslationKey", + "getForceLoadedChunks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::Chunk::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Get the translation key of the block associated with this material, or - /// null if this material does not have an associated block. - pub fn block_translation_key(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); + /// Adds a plugin ticket for the specified chunk, loading the chunk if it is + /// not already loaded. + /// + /// A plugin ticket will prevent a chunk from unloading until it is + /// explicitly removed. A plugin instance may only have one ticket per chunk, + /// but each chunk can have multiple plugin tickets. + /// + pub fn add_plugin_chunk_ticket( + &self, + x: i32, + z: i32, + plugin: impl Into>, + ) -> Result> { + let sig = String::from("(IILorg/bukkit/plugin/Plugin;)Z"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(z); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getBlockTranslationKey", + "addPluginChunkTicket", sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(res.z()?) } - /// Get the translation key of the item associated with this material, or - /// null if this material does not have an associated item. - pub fn item_translation_key(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); + /// Removes the specified plugin's ticket for the specified chunk + /// + /// A plugin ticket will prevent a chunk from unloading until it is + /// explicitly removed. A plugin instance may only have one ticket per chunk, + /// but each chunk can have multiple plugin tickets. + /// + pub fn remove_plugin_chunk_ticket( + &self, + x: i32, + z: i32, + plugin: impl Into>, + ) -> Result> { + let sig = String::from("(IILorg/bukkit/plugin/Plugin;)Z"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(z); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getItemTranslationKey", + "removePluginChunkTicket", sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(res.z()?) } - /// Gets if the Material is enabled by the features in a world. - pub fn is_enabled_by_feature( + /// Removes all plugin tickets for the specified plugin + /// + /// A plugin ticket will prevent a chunk from unloading until it is + /// explicitly removed. A plugin instance may only have one ticket per chunk, + /// but each chunk can have multiple plugin tickets. + /// + pub fn remove_plugin_chunk_tickets( &self, - world: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/World;)Z"); + plugin: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "isEnabledByFeature", + "removePluginChunkTickets", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Checks whether this material is compostable (can be inserted into a - /// composter). - pub fn is_compostable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCompostable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the chance that this material will successfully compost. The returned - /// value is between 0 and 1 (inclusive). - /// Materials with a compost chance of 1 will always raise the composter's - /// level, while materials with a compost chance of 0 will never raise it. - /// Plugins should check that {@link #isCompostable} returns true before - /// calling this method. - pub fn compost_chance(&self) -> Result> { - let sig = String::from("()F"); + /// Returns a map of which plugins have tickets for what chunks. The returned + /// map is not updated when plugin tickets are added or removed to chunks. If + /// a plugin has no tickets, it will be absent from the map. + /// + /// A plugin ticket will prevent a chunk from unloading until it is + /// explicitly removed. A plugin instance may only have one ticket per chunk, + /// but each chunk can have multiple plugin tickets. + /// + pub fn plugin_chunk_tickets( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Map;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getCompostChance", + "getPluginChunkTickets", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Tries to convert this Material to an item type - pub fn as_item_type( + /// Gets all Chunks intersecting the given BoundingBox. + pub fn get_intersecting_chunks( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemType;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "asItemType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::inventory::ItemType::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Tries to convert this Material to a block type - pub fn as_block_type( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockType;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "asBlockType", sig.as_str(), vec![]); + val_box: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/util/BoundingBox;)Ljava/util/Collection;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_box.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getIntersectingChunks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::Chunk::from_raw(&self.jni_ref(), obj)?); } - Ok(Some(crate::block::BlockType::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct FeatureFlag<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for FeatureFlag<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + Ok(new_vec) } -} -impl<'mc> JNIInstantiatable<'mc> for FeatureFlag<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate FeatureFlag from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/FeatureFlag")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a FeatureFlag object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + /// Drops an item at the specified {@link Location} + /// Note that functions will run before the entity is spawned + pub fn drop_item( + &self, + location: impl Into>, + item: impl Into>, + function: std::option::Option< + impl Into>, + >, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_2); + if let Some(a) = function { + sig += "Ljava/util/function/Consumer;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_3); } - } -} - -impl<'mc> FeatureFlag<'mc> { - /// Return the namespaced identifier for this object. - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + sig += ")Lorg/bukkit/entity/Item;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "dropItem", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + crate::entity::Item::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for FeatureFlag<'mc> { - fn into(self) -> crate::Keyed<'mc> { - crate::Keyed::from_raw(&self.jni_ref(), self.1) - .expect("Error converting FeatureFlag into crate::Keyed") - } -} -#[repr(C)] -pub struct Registry<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Registry<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Drops an item at the specified {@link Location} with a random offset + /// Note that functions will run before the entity is spawned + pub fn drop_item_naturally( + &self, + location: impl Into>, + item: impl Into>, + function: std::option::Option< + impl Into>, + >, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(item.into().jni_object().clone()) + }); + args.push(val_2); + if let Some(a) = function { + sig += "Ljava/util/function/Consumer;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_3); + } + sig += ")Lorg/bukkit/entity/Item;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "dropItemNaturally", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Item::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Creates an arrow entity of the given class at the given {@link Location} + pub fn spawn_arrow( + &self, + location: impl Into>, + direction: impl Into>, + speed: f32, + spread: f32, + clazz: std::option::Option>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Lorg/bukkit/util/Vector;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(direction.into().jni_object().clone()) + }); + args.push(val_2); + sig += "F"; + let val_3 = jni::objects::JValueGen::Float(speed); + args.push(val_3); + sig += "F"; + let val_4 = jni::objects::JValueGen::Float(spread); + args.push(val_4); + if let Some(a) = clazz { + sig += "Ljava/lang/Class;"; + let val_5 = jni::objects::JValueGen::Object(a.into()); + args.push(val_5); + } + sig += ")LT;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "spawnArrow", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) } -} -impl<'mc> JNIInstantiatable<'mc> for Registry<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Registry from null object.").into()); + /// Creates a tree at the given {@link Location} + /// + /// The provided predicate gets called for every block which gets changed + /// as a result of the tree generation. When the predicate gets called no + /// modifications to the world are done yet. Which means, that calling + /// {@link #getBlockState(Location)} in the predicate will return the state + /// of the block before the generation. + /// + /// If the predicate returns {@code true} the block gets set in the world. + /// If it returns {@code false} the block won't get set in the world. + pub fn generate_tree( + &self, + location: impl Into>, + random: impl Into>, + val_type: std::option::Option>>, + state_predicate: std::option::Option< + impl Into>, + >, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Ljava/util/Random;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(random.into().jni_object().clone()) + }); + args.push(val_2); + if let Some(a) = val_type { + sig += "Lorg/bukkit/TreeType;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_3); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Registry")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Registry object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + if let Some(a) = state_predicate { + sig += "Ljava/util/function/Predicate;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_4); } + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "generateTree", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} - -impl<'mc> Registry<'mc> { - /// Get the object by its key. - pub fn get( + /// Strikes lightning at the given {@link Location} + pub fn strike_lightning( &self, - key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)LT;"); + loc: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/entity/LightningStrike;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "get", + "strikeLightning", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(res.l()?)) + crate::entity::LightningStrike::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Attempts to match the registered object with the given key. - /// - /// This will attempt to find a reasonable match based on the provided input - /// and may do so through unspecified means. - pub fn get_match( + /// Strikes lightning at the given {@link Location} without doing damage + pub fn strike_lightning_effect( &self, - input: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)LT;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(input.into())?, - )); + loc: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/entity/LightningStrike;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "match", + "strikeLightningEffect", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(res.l()?)) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct RegistrySimpleRegistry<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for RegistrySimpleRegistry<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + crate::entity::LightningStrike::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> JNIInstantiatable<'mc> for RegistrySimpleRegistry<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate RegistrySimpleRegistry from null object." - ) - .into()); + /// Get a list of all entities in this RegionAccessor + pub fn entities(&self) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/util/List;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getEntities", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Registry/SimpleRegistry")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a RegistrySimpleRegistry object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + Ok(new_vec) + } + /// Get a list of all living entities in this RegionAccessor + pub fn living_entities( + &self, + ) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/util/List;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLivingEntities", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::LivingEntity::from_raw(&self.jni_ref(), obj)?); } + Ok(new_vec) } -} - -impl<'mc> RegistrySimpleRegistry<'mc> { - pub fn get( + /// Get a collection of all entities in this RegionAccessor matching the given + /// class/interface + pub fn get_entities_by_class( &self, - key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)LT;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) - }); + cls: jni::objects::JClass<'mc>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(cls.into()); + args.push(val_1); + sig += ")Ljava/util/Collection;"; let res = self.jni_ref().call_method( &self.jni_object(), - "get", + "getEntitiesByClass", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(obj); } - Ok(Some(res.l()?)) - } - - pub fn iterator( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Iterator;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "iterator", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaIterator::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - #[deprecated] - - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/Class;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(unsafe { jni::objects::JClass::from_raw(res.as_jni().l) }) + Ok(new_vec) } - /// Attempts to match the registered object with the given key. - /// - /// This will attempt to find a reasonable match based on the provided input - /// and may do so through unspecified means. - pub fn get_match( + /// Get a collection of all entities in this RegionAccessor matching any of the + /// given classes/interfaces + pub fn get_entities_by_classes( &self, - input: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)LT;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(input.into())?, - )); + classes: jni::objects::JClass<'mc>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(classes.into()); + args.push(val_1); + sig += ")Ljava/util/Collection;"; let res = self.jni_ref().call_method( &self.jni_object(), - "match", + "getEntitiesByClasses", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); } - Ok(Some(res.l()?)) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for RegistrySimpleRegistry<'mc> { - fn into(self) -> crate::Registry<'mc> { - crate::Registry::from_raw(&self.jni_ref(), self.1) - .expect("Error converting RegistrySimpleRegistry into crate::Registry") + Ok(new_vec) } -} -#[repr(C)] -pub struct ServerTickManager<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for ServerTickManager<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Get a list of all players in this World + pub fn players(&self) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPlayers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Player::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Returns a list of entities within a bounding box centered around a + /// Location. + /// + /// This may not consider entities in currently unloaded chunks. Some + /// implementations may impose artificial restrictions on the size of the + /// search bounding box. + pub fn get_nearby_entities( + &self, + location: impl Into>, + x: std::option::Option, + y: std::option::Option, + z: std::option::Option, + filter: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = x { + sig += "D"; + let val_2 = jni::objects::JValueGen::Double(a); + args.push(val_2); + } + if let Some(a) = y { + sig += "D"; + let val_3 = jni::objects::JValueGen::Double(a); + args.push(val_3); + } + if let Some(a) = z { + sig += "D"; + let val_4 = jni::objects::JValueGen::Double(a); + args.push(val_4); + } + if let Some(a) = filter { + sig += "Ljava/util/function/Predicate;"; + let val_5 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_5); + } + sig += ")Ljava/util/Collection;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getNearbyEntities", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } -} -impl<'mc> JNIInstantiatable<'mc> for ServerTickManager<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate ServerTickManager from null object.").into(), - ); + /// Performs a ray trace that checks for entity collisions. + /// + /// This may not consider entities in currently unloaded chunks. Some + /// implementations may impose artificial restrictions on the maximum + /// distance. + pub fn ray_trace_entities( + &self, + start: impl Into>, + direction: impl Into>, + max_distance: f64, + ray_size: std::option::Option, + filter: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(start.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Lorg/bukkit/util/Vector;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(direction.into().jni_object().clone()) + }); + args.push(val_2); + sig += "D"; + let val_3 = jni::objects::JValueGen::Double(max_distance); + args.push(val_3); + if let Some(a) = ray_size { + sig += "D"; + let val_4 = jni::objects::JValueGen::Double(a); + args.push(val_4); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/ServerTickManager")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ServerTickManager object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + if let Some(a) = filter { + sig += "Ljava/util/function/Predicate;"; + let val_5 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_5); + } + sig += ")Lorg/bukkit/util/RayTraceResult;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "rayTraceEntities", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some(crate::util::RayTraceResult::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } -} - -impl<'mc> ServerTickManager<'mc> { - /// Checks if the server is running normally. + /// Performs a ray trace that checks for block collisions using the blocks' + /// precise collision shapes. /// - /// When the server is running normally it indicates that the server is not - /// currently frozen. - pub fn is_running_normally(&self) -> Result> { - let sig = String::from("()Z"); + /// If collisions with passable blocks are ignored, fluid collisions are + /// ignored as well regardless of the fluid collision mode. + /// + /// Portal blocks are only considered passable if the ray starts within + /// them. Apart from that collisions with portal blocks will be considered + /// even if collisions with passable blocks are otherwise ignored. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn ray_trace_blocks( + &self, + start: impl Into>, + direction: impl Into>, + max_distance: f64, + fluid_collision_mode: std::option::Option>>, + ignore_passable_blocks: std::option::Option, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(start.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Lorg/bukkit/util/Vector;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(direction.into().jni_object().clone()) + }); + args.push(val_2); + sig += "D"; + let val_3 = jni::objects::JValueGen::Double(max_distance); + args.push(val_3); + if let Some(a) = fluid_collision_mode { + sig += "Lorg/bukkit/FluidCollisionMode;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_4); + } + if let Some(a) = ignore_passable_blocks { + sig += "Z"; + let val_5 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_5); + } + sig += ")Lorg/bukkit/util/RayTraceResult;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::util::RayTraceResult::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Performs a ray trace that checks for both block and entity collisions. + /// + /// Block collisions use the blocks' precise collision shapes. The + /// raySize parameter is only taken into account for entity + /// collision checks. + /// + /// If collisions with passable blocks are ignored, fluid collisions are + /// ignored as well regardless of the fluid collision mode. + /// + /// Portal blocks are only considered passable if the ray starts within them. + /// Apart from that collisions with portal blocks will be considered even if + /// collisions with passable blocks are otherwise ignored. + /// + /// This may cause loading of chunks! Some implementations may impose + /// artificial restrictions on the maximum distance. + pub fn ray_trace( + &self, + start: impl Into>, + direction: impl Into>, + max_distance: f64, + fluid_collision_mode: impl Into>, + ignore_passable_blocks: bool, + ray_size: f64, + filter: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;Lorg/bukkit/util/Vector;DLorg/bukkit/FluidCollisionMode;ZDLjava/util/function/Predicate;)Lorg/bukkit/util/RayTraceResult;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(start.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(direction.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Double(max_distance); + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(fluid_collision_mode.into().jni_object().clone()) + }); + let val_5 = jni::objects::JValueGen::Bool(ignore_passable_blocks.into()); + let val_6 = jni::objects::JValueGen::Double(ray_size); + let val_7 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(filter.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "isRunningNormally", + "rayTrace", sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + jni::objects::JValueGen::from(val_5), + jni::objects::JValueGen::from(val_6), + jni::objects::JValueGen::from(val_7), + ], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Checks if the server is currently stepping. - pub fn is_stepping(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isStepping", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::util::RayTraceResult::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Checks if the server is currently sprinting. - pub fn is_sprinting(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isSprinting", sig.as_str(), vec![]); + /// Gets the default spawn {@link Location} of this world + pub fn spawn_location(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSpawnLocation", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Checks if a given entity is frozen. - pub fn is_frozen( + /// Sets the spawn location of the world + pub fn set_spawn_location( &self, - entity: std::option::Option>>, + x: i32, + y: std::option::Option, + z: std::option::Option, + angle: std::option::Option, ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = entity { - sig += "Lorg/bukkit/entity/Entity;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); + args.push(val_1); + if let Some(a) = y { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + if let Some(a) = z { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + if let Some(a) = angle { + sig += "F"; + let val_4 = jni::objects::JValueGen::Float(a); + args.push(val_4); } sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setSpawnLocation", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the relative in-game time of this world. + /// + /// The relative time is analogous to hours * 1000 + pub fn time(&self) -> Result> { + let sig = String::from("()J"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isFrozen", sig.as_str(), args); + .call_method(&self.jni_object(), "getTime", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.j()?) } - /// Gets the current tick rate of the server. - pub fn tick_rate(&self) -> Result> { - let sig = String::from("()F"); + /// Sets the relative in-game time on the server. + /// + /// The relative time is analogous to hours * 1000 + /// + /// Note that setting the relative time below the current relative time + /// will actually move the clock forward a day. If you require to rewind + /// time, please see {@link #setFullTime(long)} + pub fn set_time(&self, time: i64) -> Result<(), Box> { + let sig = String::from("(J)V"); + let val_1 = jni::objects::JValueGen::Long(time); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTime", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the full in-game time on this world + pub fn full_time(&self) -> Result> { + let sig = String::from("()J"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getTickRate", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFullTime", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + Ok(res.j()?) } - /// Sets the tick rate of the server. + /// Sets the in-game time on the server /// - /// The normal tick rate of the server is 20. No tick rate below 1.0F or - /// above 10,000 can be applied to the server. - pub fn set_tick_rate(&self, tick: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(tick); + /// Note that this sets the full time of the world, which may cause adverse + /// effects such as breaking redstone clocks and any scheduled events + pub fn set_full_time(&self, time: i64) -> Result<(), Box> { + let sig = String::from("(J)V"); + let val_1 = jni::objects::JValueGen::Long(time); let res = self.jni_ref().call_method( &self.jni_object(), - "setTickRate", + "setFullTime", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets the server to a frozen state that does not tick most things. - pub fn set_frozen(&self, frozen: bool) -> Result<(), Box> { + /// Gets the full in-game time on this world since the world generation + pub fn game_time(&self) -> Result> { + let sig = String::from("()J"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getGameTime", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.j()?) + } + /// Returns whether the world has an ongoing storm. + pub fn has_storm(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasStorm", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set whether there is a storm. A duration will be set for the new + /// current conditions. + /// This will implicitly call {@link #setClearWeatherDuration(int)} with 0 + /// ticks to reset the world's clear weather. + pub fn set_storm(&self, has_storm: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(frozen.into()); + let val_1 = jni::objects::JValueGen::Bool(has_storm.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setFrozen", + "setStorm", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Steps the game a certain amount of ticks if the server is currently - /// frozen. - /// - /// Steps occur when the server is in a frozen state which can be started by - /// either using the in game /tick freeze command or the - /// {@link #setFrozen(boolean)} method. - pub fn step_game_if_frozen(&self, ticks: i32) -> Result> { - let sig = String::from("(I)Z"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Get the remaining time in ticks of the current conditions. + pub fn weather_duration(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "stepGameIfFrozen", + "getWeatherDuration", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Stops the current stepping if stepping is occurring. - pub fn stop_stepping(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "stopStepping", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Attempts to initiate a sprint, which executes all server ticks at a - /// faster rate then normal. - pub fn request_game_to_sprint(&self, ticks: i32) -> Result> { - let sig = String::from("(I)Z"); - let val_1 = jni::objects::JValueGen::Int(ticks); + /// Set the remaining time in ticks of the current conditions. + pub fn set_weather_duration(&self, duration: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(duration); let res = self.jni_ref().call_method( &self.jni_object(), - "requestGameToSprint", + "setWeatherDuration", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Stops the current sprint if one is currently happening. - pub fn stop_sprinting(&self) -> Result> { + /// Returns whether there is thunder. + pub fn is_thundering(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "stopSprinting", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isThundering", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the amount of frozen ticks left to run. - pub fn frozen_ticks_to_run(&self) -> Result> { + /// Set whether it is thundering. + /// This will implicitly call {@link #setClearWeatherDuration(int)} with 0 + /// ticks to reset the world's clear weather. + pub fn set_thundering(&self, thundering: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(thundering.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setThundering", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the thundering duration. + pub fn thunder_duration(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getFrozenTicksToRun", + "getThunderDuration", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -pub enum Particle<'mc> {} -impl<'mc> std::fmt::Display for Particle<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + /// Set the thundering duration. + pub fn set_thunder_duration(&self, duration: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(duration); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setThunderDuration", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} - -impl<'mc> Particle<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/Particle"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/Particle;", + /// Returns whether the world has clear weather. + /// This will be true such that {@link #isThundering()} and + /// {@link #hasStorm()} are both false. + pub fn is_clear_weather(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isClearWeather", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set the clear weather duration. + /// The clear weather ticks determine whether or not the world will be + /// allowed to rain or storm. If clear weather ticks are > 0, the world will + /// not naturally do either until the duration has elapsed. + /// This method is equivalent to calling {@code /weather clear} with a set + /// amount of ticks. + pub fn set_clear_weather_duration( + &self, + duration: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(duration); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setClearWeatherDuration", + sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct ParticleStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Particle<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + self.jni_ref().translate_error(res)?; + Ok(()) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + /// Get the clear weather duration. + pub fn clear_weather_duration(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getClearWeatherDuration", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} -impl<'mc> JNIInstantiatable<'mc> for Particle<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Particle from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Particle")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Particle object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + /// Creates explosion at given coordinates with given power and optionally + /// setting blocks on fire or breaking blocks. + /// + /// Note that if a non-null {@code source} Entity is provided and {@code + /// breakBlocks} is {@code true}, the value of {@code breakBlocks} will be + /// ignored if {@link GameRule#MOB_GRIEFING} is {@code false} in the world + /// in which the explosion occurs. In other words, the mob griefing gamerule + /// will take priority over {@code breakBlocks} if explosions are not allowed. + pub fn create_explosion( + &self, + loc: impl Into>, + power: f32, + set_fire: std::option::Option, + break_blocks: std::option::Option, + source: std::option::Option>>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); + args.push(val_1); + sig += "F"; + let val_2 = jni::objects::JValueGen::Float(power); + args.push(val_2); + if let Some(a) = set_fire { + sig += "Z"; + let val_3 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_3); } - } -} - -impl<'mc> JNIRaw<'mc> for ParticleStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for ParticleStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate ParticleStruct from null object.").into(), - ); + if let Some(a) = break_blocks { + sig += "Z"; + let val_4 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_4); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Particle")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ParticleStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + if let Some(a) = source { + sig += "Lorg/bukkit/entity/Entity;"; + let val_5 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_5); } + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createExplosion", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} - -impl<'mc> ParticleStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Particle;"); - let cls = jni.find_class("org/bukkit/Particle"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::Particle::from_raw(&jni, obj) - } - - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + /// Gets the current PVP setting for this world. + pub fn pvp(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPVP", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct ParticleDustOptions<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for ParticleDustOptions<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + Ok(res.z()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Sets the PVP setting for this world. + pub fn set_pvp(&self, pvp: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(pvp.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPVP", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -impl<'mc> JNIInstantiatable<'mc> for ParticleDustOptions<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate ParticleDustOptions from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Particle/DustOptions")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ParticleDustOptions object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + /// Gets the chunk generator for this world + pub fn generator( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/generator/ChunkGenerator;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getGenerator", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some(crate::generator::ChunkGenerator::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } -} - -impl<'mc> ParticleDustOptions<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - color: impl Into>, - size: f32, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/Color;F)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Float(size); - let cls = jni.find_class("org/bukkit/Particle/DustOptions"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, + /// Gets the biome provider for this world + pub fn biome_provider( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/generator/BiomeProvider;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBiomeProvider", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![], ); - let res = jni.translate_error_no_gen(res)?; - crate::ParticleDustOptions::from_raw(&jni, res) - } - /// The color of the particles to be displayed. - pub fn color(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Color;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Color::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::generator::BiomeProvider::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Relative size of the particle. - pub fn size(&self) -> Result> { - let sig = String::from("()F"); + /// Saves world to disk + pub fn save(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct ParticleDustTransition<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for ParticleDustTransition<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + .call_method(&self.jni_object(), "save", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets a list of all applied {@link BlockPopulator}s for this World + pub fn populators( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPopulators", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::generator::BlockPopulator::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(new_vec) } -} -impl<'mc> JNIInstantiatable<'mc> for ParticleDustTransition<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate ParticleDustTransition from null object." - ) - .into()); + /// Creates a new entity at the given {@link Location} with the supplied + /// function run before the entity is added to the world. + /// + /// Note that when the function is run, the entity will not be actually in + /// the world. Any operation involving such as teleporting the entity is undefined + /// until after this function returns. + /// The passed function however is run after the potential entity's spawn + /// randomization and hence already allows access to the values of the mob, + /// whether or not those were randomized, such as attributes or the entity + /// equipment. + pub fn spawn( + &self, + location: impl Into>, + clazz: jni::objects::JClass<'mc>, + spawn_reason: std::option::Option< + impl Into>, + >, + randomize_data: std::option::Option, + function: std::option::Option< + impl Into>, + >, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Ljava/lang/Class;"; + let val_2 = jni::objects::JValueGen::Object(clazz.into()); + args.push(val_2); + if let Some(a) = spawn_reason { + sig += "Lorg/bukkit/event/entity/CreatureSpawnEvent/SpawnReason;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_3); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Particle/DustTransition")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ParticleDustTransition object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + if let Some(a) = randomize_data { + sig += "Z"; + let val_4 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_4); + } + if let Some(a) = function { + sig += "Ljava/util/function/Consumer;"; + let val_5 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_5); } + sig += ")LT;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "spawn", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) } -} - -impl<'mc> ParticleDustTransition<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - from_color: impl Into>, - to_color: impl Into>, - size: f32, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/Color;Lorg/bukkit/Color;F)V"); + #[deprecated] + /// Spawn a {@link FallingBlock} entity at the given {@link Location} of the specified {@link Material}. The material dictates what is falling. When the FallingBlock hits the ground, it will place that block.The Material must be a block type, check with {@link Material#isBlock() material.isBlock()}. The Material may not be air. + pub fn spawn_falling_block( + &self, + location: impl Into>, + material: impl Into>, + data: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(from_color.into().jni_object().clone()) + jni::objects::JObject::from_raw(location.into().jni_object().clone()) }); + args.push(val_1); + sig += "Lorg/bukkit/Material;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(to_color.into().jni_object().clone()) + jni::objects::JObject::from_raw(material.into().jni_object().clone()) }); - let val_3 = jni::objects::JValueGen::Float(size); - let cls = jni.find_class("org/bukkit/Particle/DustTransition"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = jni.translate_error_no_gen(res)?; - crate::ParticleDustTransition::from_raw(&jni, res) - } - /// The final of the particles to be displayed. - pub fn to_color(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Color;"); + args.push(val_2); + if let Some(a) = data { + sig += "B"; + let val_3 = jni::objects::JValueGen::Byte(a); + args.push(val_3); + } + sig += ")Lorg/bukkit/entity/FallingBlock;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getToColor", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "spawnFallingBlock", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::Color::from_raw(&self.jni_ref(), unsafe { + crate::entity::FallingBlock::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.Particle.DustOptions ( ['getToColor']) - /// The color of the particles to be displayed. - pub fn color(&self) -> Result, Box> { - let temp_clone = crate::ParticleDustOptions::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::ParticleDustOptions = temp_clone.into(); - real.color() - } - /// Relative size of the particle. - pub fn size(&self) -> Result> { - let temp_clone = crate::ParticleDustOptions::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::ParticleDustOptions = temp_clone.into(); - real.size() - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for ParticleDustTransition<'mc> { - fn into(self) -> crate::ParticleDustOptions<'mc> { - crate::ParticleDustOptions::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ParticleDustTransition into crate::ParticleDustOptions") - } -} -#[repr(C)] -pub struct Server<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Server<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Server<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Server from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Server")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Server object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + /// Plays an effect to all players within a given radius around a location. + pub fn play_effect( + &self, + location: impl Into>, + effect: impl Into>, + data: jni::objects::JObject<'mc>, + radius: std::option::Option, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Lorg/bukkit/Effect;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(effect.into().jni_object().clone()) + }); + args.push(val_2); + sig += "LT;"; + let val_3 = jni::objects::JValueGen::Object(data); + args.push(val_3); + if let Some(a) = radius { + sig += "I"; + let val_4 = jni::objects::JValueGen::Int(a); + args.push(val_4); } - } -} - -impl<'mc> Server<'mc> { - /// Gets the name of this server implementation. - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Gets the version string of this server implementation. - pub fn version(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getVersion", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + .call_method(&self.jni_object(), "playEffect", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the Bukkit version that this server is running. - pub fn bukkit_version(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Get empty chunk snapshot (equivalent to all air blocks), optionally + /// including valid biome data. Used for representing an ungenerated chunk, + /// or for fetching only biome data without loading a chunk. + pub fn get_empty_chunk_snapshot( + &self, + x: i32, + z: i32, + include_biome: bool, + include_biome_temp: bool, + ) -> Result, Box> { + let sig = String::from("(IIZZ)Lorg/bukkit/ChunkSnapshot;"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(z); + let val_3 = jni::objects::JValueGen::Bool(include_biome.into()); + let val_4 = jni::objects::JValueGen::Bool(include_biome_temp.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getBukkitVersion", + "getEmptyChunkSnapshot", sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + ], ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + crate::ChunkSnapshot::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets a view of all currently logged in players. This {@linkplain - /// Collections#unmodifiableCollection(Collection) view} is a reused - /// object, making some operations like {@link Collection#size()} - /// zero-allocation. - /// - /// The collection is a view backed by the internal representation, such - /// that, changes to the internal state of the server will be reflected - /// immediately. However, the reuse of the returned collection (identity) - /// is not strictly guaranteed for future or all implementations. Casting - /// the collection, or relying on interface implementations (like {@link - /// Serializable} or {@link List}), is deprecated. - /// - /// Iteration behavior is undefined outside of self-contained main-thread - /// uses. Normal and immediate iterator use without consequences that - /// affect the collection are fully supported. The effects following - /// (non-exhaustive) {@link Entity#teleport(Location) teleportation}, - /// {@link Player#setHealth(double) death}, and {@link Player#kickPlayer( - /// String) kicking} are undefined. Any use of this collection from - /// asynchronous threads is unsafe. - /// - /// For safe consequential iteration or mimicking the old array behavior, - /// using {@link Collection#toArray(Object[])} is recommended. For making - /// snapshots, {@link ImmutableList#copyOf(Collection)} is recommended. - pub fn online_players( + /// Sets the spawn flags for this. + pub fn set_spawn_flags( &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); + allow_monsters: bool, + allow_animals: bool, + ) -> Result<(), Box> { + let sig = String::from("(ZZ)V"); + let val_1 = jni::objects::JValueGen::Bool(allow_monsters.into()); + let val_2 = jni::objects::JValueGen::Bool(allow_animals.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getOnlinePlayers", + "setSpawnFlags", sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Player::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the maximum amount of players which can login to this server. - pub fn max_players(&self) -> Result> { - let sig = String::from("()I"); + /// Gets whether animals can spawn in this world. + pub fn allow_animals(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxPlayers", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAllowAnimals", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Set the maximum amount of players allowed to be logged in at once. - pub fn set_max_players(&self, max_players: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(max_players); + /// Gets whether monsters can spawn in this world. + pub fn allow_monsters(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaxPlayers", + "getAllowMonsters", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Get the game port that the server runs on. - pub fn port(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the {@link Biome} at the given coordinates. + pub fn get_biome( + &self, + x: i32, + y: std::option::Option, + z: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); + args.push(val_1); + if let Some(a) = y { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + if let Some(a) = z { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + sig += ")Lorg/bukkit/block/Biome;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getPort", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBiome", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::block::Biome::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get the view distance from this server. - pub fn view_distance(&self) -> Result> { - let sig = String::from("()I"); + /// Sets the {@link Biome} for the given block coordinates + pub fn set_biome( + &self, + x: i32, + y: i32, + z: std::option::Option, + biome: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); + args.push(val_1); + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(y); + args.push(val_2); + if let Some(a) = z { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + if let Some(a) = biome { + sig += "Lorg/bukkit/block/Biome;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_4); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setBiome", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the temperature for the given block coordinates. + /// + /// It is safe to run this method when the block does not exist, it will + /// not create the block. + /// + /// This method will return the raw temperature without adjusting for block + /// height effects. + pub fn get_temperature( + &self, + x: i32, + y: i32, + z: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); + args.push(val_1); + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(y); + args.push(val_2); + if let Some(a) = z { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + sig += ")D"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getViewDistance", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTemperature", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.d()?) } - /// Get the simulation distance from this server. - pub fn simulation_distance(&self) -> Result> { + /// Gets the humidity for the given block coordinates. + /// + /// It is safe to run this method when the block does not exist, it will + /// not create the block. + pub fn get_humidity( + &self, + x: i32, + y: i32, + z: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); + args.push(val_1); + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(y); + args.push(val_2); + if let Some(a) = z { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + sig += ")D"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHumidity", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the maximum height to which chorus fruits and nether portals can + /// bring players within this dimension. + /// This excludes portals that were already built above the limit as they + /// still connect normally. May not be greater than {@link #getMaxHeight()}. + pub fn logical_height(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getSimulationDistance", + "getLogicalHeight", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Get the IP that this server is bound to, or empty string if not - /// specified. - pub fn ip(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Gets if this world is natural. + /// When false, compasses spin randomly, and using a bed to set the respawn + /// point or sleep, is disabled. When true, nether portals can spawn + /// zombified piglins. + pub fn is_natural(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getIp", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isNatural", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - /// Get world type (level-type setting) for default world. - pub fn world_type(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Gets if beds work in this world. + /// A non-working bed will blow up when trying to sleep. {@link #isNatural()} + /// defines if a bed can be used to set spawn point. + pub fn is_bed_works(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getWorldType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isBedWorks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.z()?) } - /// Get generate-structures setting. - pub fn generate_structures(&self) -> Result> { + /// Gets if this world has skylight access. + pub fn has_sky_light(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getGenerateStructures", - sig.as_str(), - vec![], - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasSkyLight", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get max world size. - pub fn max_world_size(&self) -> Result> { - let sig = String::from("()I"); + /// Gets if this world has a ceiling. + pub fn has_ceiling(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxWorldSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasCeiling", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Gets whether this server allows the End or not. - pub fn allow_end(&self) -> Result> { + /// Gets if this world allow to piglins to survive without shaking and + /// transforming to zombified piglins. + pub fn is_piglin_safe(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAllowEnd", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isPiglinSafe", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets whether this server allows the Nether or not. - pub fn allow_nether(&self) -> Result> { + /// Gets if this world allows players to charge and use respawn anchors. + pub fn is_respawn_anchor_works(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAllowNether", sig.as_str(), vec![]); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isRespawnAnchorWorks", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets whether the server is logging the IP addresses of players. - pub fn is_logging_ips(&self) -> Result> { + /// Gets if players with the bad omen effect in this world will trigger a + /// raid. + pub fn has_raids(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasRaids", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets if various water/lava mechanics will be triggered in this world, eg: + /// + ///
      + ///
    • Water is evaporated
    • + ///
    • Sponges dry
    • + ///
    • Lava spreads faster and further
    • + ///
    + pub fn is_ultra_warm(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isLoggingIPs", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isUltraWarm", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets a list of packs to be enabled. - pub fn initial_enabled_packs(&self) -> Result, Box> { - let sig = String::from("()Ljava/util/List;"); + /// Gets the sea level for this world. + /// + /// This is often half of {@link #getMaxHeight()} + pub fn sea_level(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSeaLevel", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + #[deprecated] + /// Gets whether the world's spawn area should be kept loaded into memory or not. + pub fn keep_spawn_in_memory(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getInitialEnabledPacks", + "getKeepSpawnInMemory", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), - ); - } - Ok(new_vec) + Ok(res.z()?) } - /// Gets a list of packs that will not be enabled automatically. - pub fn initial_disabled_packs(&self) -> Result, Box> { - let sig = String::from("()Ljava/util/List;"); + #[deprecated] + /// Sets whether the world's spawn area should be kept loaded into memory or not. + pub fn set_keep_spawn_in_memory( + &self, + keep_loaded: bool, + ) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(keep_loaded.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getInitialDisabledPacks", + "setKeepSpawnInMemory", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether or not the world will automatically save + pub fn is_auto_save(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isAutoSave", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), - ); - } - Ok(new_vec) + Ok(res.z()?) } - /// Get the DataPack Manager. - pub fn data_pack_manager( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/packs/DataPackManager;"); + /// Sets whether or not the world will automatically save + pub fn set_auto_save(&self, value: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(value.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getDataPackManager", + "setAutoSave", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::packs::DataPackManager::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the ServerTick Manager. - pub fn server_tick_manager( + /// Sets the Difficulty of the world. + pub fn set_difficulty( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/ServerTickManager;"); + difficulty: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Difficulty;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(difficulty.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getServerTickManager", + "setDifficulty", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the Difficulty of the world. + pub fn difficulty(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Difficulty;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDifficulty", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::ServerTickManager::from_raw(&self.jni_ref(), unsafe { + crate::Difficulty::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the resource pack configured to be sent to clients by the server. - pub fn server_resource_pack( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/packs/ResourcePack;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getServerResourcePack", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::packs::ResourcePack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Gets the server resource pack uri, or empty string if not specified. - pub fn resource_pack(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Returns the view distance used for this world. + pub fn view_distance(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getResourcePack", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getViewDistance", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.i()?) } - /// Gets the SHA-1 digest of the server resource pack, or empty string if - /// not specified. - pub fn resource_pack_hash(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Returns the simulation distance used for this world. + pub fn simulation_distance(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getResourcePackHash", + "getSimulationDistance", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.i()?) } - /// Gets the custom prompt message to be shown when the server resource - /// pack is required, or empty string if not specified. - pub fn resource_pack_prompt(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getResourcePackPrompt", - sig.as_str(), - vec![], - ); + #[deprecated] + /// Gets the type of this world. + pub fn world_type(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/WorldType;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getWorldType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::WorldType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Gets whether the server resource pack is enforced. - pub fn is_resource_pack_required(&self) -> Result> { + /// Gets whether or not structures are being generated. + pub fn can_generate_structures(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "isResourcePackRequired", + "canGenerateStructures", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets whether this server has a whitelist or not. - pub fn has_whitelist(&self) -> Result> { + /// Gets whether the world is hardcore or not. + /// In a hardcore world the difficulty is locked to hard. + pub fn is_hardcore(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasWhitelist", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isHardcore", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets if the server is whitelisted. - pub fn set_whitelist(&self, value: bool) -> Result<(), Box> { + /// Sets whether the world is hardcore or not. + /// In a hardcore world the difficulty is locked to hard. + pub fn set_hardcore(&self, hardcore: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(value.into()); + let val_1 = jni::objects::JValueGen::Bool(hardcore.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setWhitelist", + "setHardcore", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets whether the server whitelist is enforced. - /// If the whitelist is enforced, non-whitelisted players will be - /// disconnected when the server whitelist is reloaded. - pub fn is_whitelist_enforced(&self) -> Result> { - let sig = String::from("()Z"); + #[deprecated] + /// Gets the world's ticks per animal spawns valueThis value determines how many ticks there are between attempts to spawn animals.Example Usage:
    • A value of 1 will mean the server will attempt to spawn animals in this world every tick.
    • A value of 400 will mean the server will attempt to spawn animals in this world every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, animal spawning will be disabled for this world. We recommend using {@link #setSpawnFlags(boolean, boolean)} to control this instead.Minecraft default: 400. + pub fn ticks_per_animal_spawns(&self) -> Result> { + let sig = String::from("()J"); let res = self.jni_ref().call_method( &self.jni_object(), - "isWhitelistEnforced", + "getTicksPerAnimalSpawns", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.j()?) } - /// Sets if the server whitelist is enforced. - /// If the whitelist is enforced, non-whitelisted players will be - /// disconnected when the server whitelist is reloaded. - pub fn set_whitelist_enforced(&self, value: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(value.into()); + #[deprecated] + /// Sets the world's ticks per animal spawns valueThis value determines how many ticks there are between attempts to spawn animals.Example Usage:
    • A value of 1 will mean the server will attempt to spawn animals in this world every tick.
    • A value of 400 will mean the server will attempt to spawn animals in this world every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, animal spawning will be disabled for this world. We recommend using {@link #setSpawnFlags(boolean, boolean)} to control this instead.Minecraft default: 400. + pub fn set_ticks_per_animal_spawns( + &self, + ticks_per_animal_spawns: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks_per_animal_spawns); let res = self.jni_ref().call_method( &self.jni_object(), - "setWhitelistEnforced", + "setTicksPerAnimalSpawns", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets a list of whitelisted players. - pub fn whitelisted_players( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + #[deprecated] + /// Gets the world's ticks per monster spawns valueThis value determines how many ticks there are between attempts to spawn monsters.Example Usage:
    • A value of 1 will mean the server will attempt to spawn monsters in this world every tick.
    • A value of 400 will mean the server will attempt to spawn monsters in this world every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, monsters spawning will be disabled for this world. We recommend using {@link #setSpawnFlags(boolean, boolean)} to control this instead.Minecraft default: 1. + pub fn ticks_per_monster_spawns(&self) -> Result> { + let sig = String::from("()J"); let res = self.jni_ref().call_method( &self.jni_object(), - "getWhitelistedPlayers", + "getTicksPerMonsterSpawns", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Reloads the whitelist from disk. - pub fn reload_whitelist(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "reloadWhitelist", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.j()?) } - /// Broadcast a message to all players. - /// - /// This is the same as calling {@link #broadcast(java.lang.String, - /// java.lang.String)} to {@link #BROADCAST_CHANNEL_USERS} - pub fn broadcast_message( + #[deprecated] + /// Sets the world's ticks per monster spawns valueThis value determines how many ticks there are between attempts to spawn monsters.Example Usage:
    • A value of 1 will mean the server will attempt to spawn monsters in this world on every tick.
    • A value of 400 will mean the server will attempt to spawn monsters in this world every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, monsters spawning will be disabled for this world. We recommend using {@link #setSpawnFlags(boolean, boolean)} to control this instead.Minecraft default: 1. + pub fn set_ticks_per_monster_spawns( &self, - message: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)I"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(message.into())?, - )); + ticks_per_monster_spawns: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks_per_monster_spawns); let res = self.jni_ref().call_method( &self.jni_object(), - "broadcastMessage", + "setTicksPerMonsterSpawns", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the name of the update folder. The update folder is used to safely - /// update plugins at the right moment on a plugin load. - /// - /// The update folder name is relative to the plugins folder. - pub fn update_folder(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getUpdateFolder", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the value of the connection throttle setting. - pub fn connection_throttle(&self) -> Result> { + #[deprecated] + /// Gets the world's ticks per water mob spawns valueThis value determines how many ticks there are between attempts to spawn water mobs.Example Usage:
    • A value of 1 will mean the server will attempt to spawn water mobs in this world every tick.
    • A value of 400 will mean the server will attempt to spawn water mobs in this world every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, water mobs spawning will be disabled for this world.Minecraft default: 1. + pub fn ticks_per_water_spawns(&self) -> Result> { let sig = String::from("()J"); let res = self.jni_ref().call_method( &self.jni_object(), - "getConnectionThrottle", + "getTicksPerWaterSpawns", sig.as_str(), vec![], ); @@ -2456,76 +2857,88 @@ impl<'mc> Server<'mc> { Ok(res.j()?) } #[deprecated] - /// Gets default ticks per animal spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn monsters every tick.
    • A value of 400 will mean the server will attempt to spawn monsters every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, animal spawning will be disabled. We recommend using spawn-animals to control this instead.Minecraft default: 400. - pub fn ticks_per_animal_spawns(&self) -> Result> { - let sig = String::from("()I"); + /// Sets the world's ticks per water mob spawns valueThis value determines how many ticks there are between attempts to spawn water mobs.Example Usage:
    • A value of 1 will mean the server will attempt to spawn water mobs in this world on every tick.
    • A value of 400 will mean the server will attempt to spawn water mobs in this world every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, water mobs spawning will be disabled for this world.Minecraft default: 1. + pub fn set_ticks_per_water_spawns( + &self, + ticks_per_water_spawns: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks_per_water_spawns); let res = self.jni_ref().call_method( &self.jni_object(), - "getTicksPerAnimalSpawns", + "setTicksPerWaterSpawns", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + self.jni_ref().translate_error(res)?; + Ok(()) } #[deprecated] - /// Gets the default ticks per monster spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn monsters every tick.
    • A value of 400 will mean the server will attempt to spawn monsters every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, monsters spawning will be disabled. We recommend using spawn-monsters to control this instead.Minecraft default: 1. - pub fn ticks_per_monster_spawns(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the default ticks per water ambient mob spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn water ambient mobs every tick.
    • A value of 400 will mean the server will attempt to spawn water ambient mobs every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, ambient mobs spawning will be disabled.Minecraft default: 1. + pub fn ticks_per_water_ambient_spawns(&self) -> Result> { + let sig = String::from("()J"); let res = self.jni_ref().call_method( &self.jni_object(), - "getTicksPerMonsterSpawns", + "getTicksPerWaterAmbientSpawns", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.j()?) } #[deprecated] - /// Gets the default ticks per water mob spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn water mobs every tick.
    • A value of 400 will mean the server will attempt to spawn water mobs every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, water mobs spawning will be disabled.Minecraft default: 1. - pub fn ticks_per_water_spawns(&self) -> Result> { - let sig = String::from("()I"); + /// Sets the world's ticks per water ambient mob spawns valueThis value determines how many ticks there are between attempts to spawn water ambient mobs.Example Usage:
    • A value of 1 will mean the server will attempt to spawn water ambient mobs in this world on every tick.
    • A value of 400 will mean the server will attempt to spawn water ambient mobs in this world every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, water ambient mobs spawning will be disabled for this world.Minecraft default: 1. + pub fn set_ticks_per_water_ambient_spawns( + &self, + ticks_per_ambient_spawns: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks_per_ambient_spawns); let res = self.jni_ref().call_method( &self.jni_object(), - "getTicksPerWaterSpawns", + "setTicksPerWaterAmbientSpawns", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + self.jni_ref().translate_error(res)?; + Ok(()) } #[deprecated] - /// Gets the default ticks per water ambient mob spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn water ambient mobs every tick.
    • A value of 400 will mean the server will attempt to spawn water ambient mobs every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, ambient mobs spawning will be disabled.Minecraft default: 1. - pub fn ticks_per_water_ambient_spawns(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the default ticks per water underground creature spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn water underground creature every tick.
    • A value of 400 will mean the server will attempt to spawn water underground creature every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, water underground creature spawning will be disabled.Minecraft default: 1. + pub fn ticks_per_water_underground_creature_spawns( + &self, + ) -> Result> { + let sig = String::from("()J"); let res = self.jni_ref().call_method( &self.jni_object(), - "getTicksPerWaterAmbientSpawns", + "getTicksPerWaterUndergroundCreatureSpawns", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.j()?) } #[deprecated] - /// Gets the default ticks per water underground creature spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn water underground creature every tick.
    • A value of 400 will mean the server will attempt to spawn water underground creature every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, water underground creature spawning will be disabled.Minecraft default: 1. - pub fn ticks_per_water_underground_creature_spawns( + /// Sets the world's ticks per water underground creature spawns valueThis value determines how many ticks there are between attempts to spawn water underground creature.Example Usage:
    • A value of 1 will mean the server will attempt to spawn water underground creature in this world on every tick.
    • A value of 400 will mean the server will attempt to spawn water underground creature in this world every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, water underground creature spawning will be disabled for this world.Minecraft default: 1. + pub fn set_ticks_per_water_underground_creature_spawns( &self, - ) -> Result> { - let sig = String::from("()I"); + ticks_per_water_underground_creature_spawns: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks_per_water_underground_creature_spawns); let res = self.jni_ref().call_method( &self.jni_object(), - "getTicksPerWaterUndergroundCreatureSpawns", + "setTicksPerWaterUndergroundCreatureSpawns", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + self.jni_ref().translate_error(res)?; + Ok(()) } #[deprecated] - /// Gets the default ticks per ambient mob spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn ambient mobs every tick.
    • A value of 400 will mean the server will attempt to spawn ambient mobs every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, ambient mobs spawning will be disabled.Minecraft default: 1. - pub fn ticks_per_ambient_spawns(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the world's ticks per ambient mob spawns valueThis value determines how many ticks there are between attempts to spawn ambient mobs.Example Usage:
    • A value of 1 will mean the server will attempt to spawn ambient mobs in this world every tick.
    • A value of 400 will mean the server will attempt to spawn ambient mobs in this world every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, ambient mobs spawning will be disabled for this world.Minecraft default: 1. + pub fn ticks_per_ambient_spawns(&self) -> Result> { + let sig = String::from("()J"); let res = self.jni_ref().call_method( &self.jni_object(), "getTicksPerAmbientSpawns", @@ -2533,29 +2946,48 @@ impl<'mc> Server<'mc> { vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.j()?) } - /// Gets the default ticks per {@link SpawnCategory} spawns value. + #[deprecated] + /// Sets the world's ticks per ambient mob spawns valueThis value determines how many ticks there are between attempts to spawn ambient mobs.Example Usage:
    • A value of 1 will mean the server will attempt to spawn ambient mobs in this world on every tick.
    • A value of 400 will mean the server will attempt to spawn ambient mobs in this world every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, ambient mobs spawning will be disabled for this world.Minecraft default: 1. + pub fn set_ticks_per_ambient_spawns( + &self, + ticks_per_ambient_spawns: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(ticks_per_ambient_spawns); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTicksPerAmbientSpawns", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the world's ticks per {@link SpawnCategory} mob spawns value + /// + /// This value determines how many ticks there are between attempts to + /// spawn {@link SpawnCategory} mobs. /// /// Example Usage: ///
      - ///
    • A value of 1 will mean the server will attempt to spawn {@link SpawnCategory} mobs - /// every tick. + ///
    • A value of 1 will mean the server will attempt to spawn {@link SpawnCategory} mobs in + /// this world every tick. ///
    • A value of 400 will mean the server will attempt to spawn {@link SpawnCategory} mobs - /// every 400th tick. + /// in this world every 400th tick. ///
    • A value below 0 will be reset back to Minecraft's default. ///
    /// - /// Note: If set to 0, {@link SpawnCategory} mobs spawning will be disabled. + /// Note: + /// If set to 0, {@link SpawnCategory} mobs spawning will be disabled for this world. /// /// Minecraft default: 1. - /// - /// Note: the {@link SpawnCategory#MISC} are not consider. pub fn get_ticks_per_spawns( &self, spawn_category: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/SpawnCategory;)I"); + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/SpawnCategory;)J"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(spawn_category.into().jni_object().clone()) }); @@ -2566,413 +2998,405 @@ impl<'mc> Server<'mc> { vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.j()?) } - /// Gets the player with the given UUID. - pub fn get_player( + /// Sets the world's ticks per {@link SpawnCategory} mob spawns value + /// + /// This value determines how many ticks there are between attempts to + /// spawn {@link SpawnCategory} mobs. + /// + /// Example Usage: + ///
      + ///
    • A value of 1 will mean the server will attempt to spawn {@link SpawnCategory} mobs in + /// this world on every tick. + ///
    • A value of 400 will mean the server will attempt to spawn {@link SpawnCategory} mobs + /// in this world every 400th tick. + ///
    • A value below 0 will be reset back to Minecraft's default. + ///
    + /// + /// Note: + /// If set to 0, {@link SpawnCategory} mobs spawning will be disabled for this world. + /// + /// Minecraft default: 1. + pub fn set_ticks_per_spawns( &self, - id: impl Into>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; + spawn_category: impl Into>, + ticks_per_category_spawn: i32, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/SpawnCategory;I)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(id.into().jni_object().clone()) + jni::objects::JObject::from_raw(spawn_category.into().jni_object().clone()) }); - args.push(val_1); - sig += ")Lorg/bukkit/entity/Player;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPlayer", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Player::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + let val_2 = jni::objects::JValueGen::Int(ticks_per_category_spawn); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTicksPerSpawns", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the player with the exact given name, case insensitive. - pub fn get_player_exact( - &self, - name: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/entity/Player;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + #[deprecated] + /// Gets limit for number of monsters that can spawn in a chunk in this world + pub fn monster_spawn_limit(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPlayerExact", + "getMonsterSpawnLimit", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Player::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - /// Attempts to match any players with the given name, and returns a list - /// of all possibly matches. - /// - /// This list is not sorted in any particular order. If an exact match is - /// found, the returned list will only contain a single result. - pub fn match_player( - &self, - name: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); + #[deprecated] + /// Sets the limit for number of monsters that can spawn in a chunk in this worldNote: If set to a negative number the world will use the server-wide spawn limit instead. + pub fn set_monster_spawn_limit(&self, limit: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(limit); let res = self.jni_ref().call_method( &self.jni_object(), - "matchPlayer", + "setMonsterSpawnLimit", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Player::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the plugin manager for interfacing with plugins. - pub fn plugin_manager( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/plugin/PluginManager;"); + #[deprecated] + /// Gets the limit for number of animals that can spawn in a chunk in this world + pub fn animal_spawn_limit(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPluginManager", + "getAnimalSpawnLimit", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::plugin::PluginManager::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Gets the scheduler for managing scheduled events. - pub fn scheduler( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/scheduler/BukkitScheduler;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getScheduler", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::scheduler::BukkitScheduler::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + #[deprecated] + /// Sets the limit for number of animals that can spawn in a chunk in this worldNote: If set to a negative number the world will use the server-wide spawn limit instead. + pub fn set_animal_spawn_limit(&self, limit: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(limit); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAnimalSpawnLimit", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets a services manager. - pub fn services_manager( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/plugin/ServicesManager;"); + #[deprecated] + /// Gets the limit for number of water animals that can spawn in a chunk in this world + pub fn water_animal_spawn_limit(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getServicesManager", + "getWaterAnimalSpawnLimit", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::plugin::ServicesManager::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets a list of all worlds on this server. - pub fn worlds(&self) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorlds", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::World::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(res.i()?) } - /// Creates or loads a world with the given name using the specified - /// options. - /// - /// If the world is already loaded, it will just return the equivalent of - /// getWorld(creator.name()). - pub fn create_world( + #[deprecated] + /// Sets the limit for number of water animals that can spawn in a chunk in this worldNote: If set to a negative number the world will use the server-wide spawn limit instead. + pub fn set_water_animal_spawn_limit( &self, - creator: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/WorldCreator;)Lorg/bukkit/World;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(creator.into().jni_object().clone()) - }); + limit: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(limit); let res = self.jni_ref().call_method( &self.jni_object(), - "createWorld", + "setWaterAnimalSpawnLimit", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::World::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Unloads the given world. - pub fn unload_world( + #[deprecated] + /// Gets the limit for number of water underground creature that can spawn in a chunk in this world + pub fn water_underground_creature_spawn_limit( &self, - world: impl Into>, - save: bool, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/World;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(save.into()); - args.push(val_2); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "unloadWorld", sig.as_str(), args); + ) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getWaterUndergroundCreatureSpawnLimit", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Gets the world from the given Unique ID. - pub fn get_world( + #[deprecated] + /// Sets the limit for number of water underground creature that can spawn in a chunk in this worldNote: If set to a negative number the world will use the server-wide spawn limit instead. + pub fn set_water_underground_creature_spawn_limit( &self, - uid: impl Into>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uid.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Lorg/bukkit/World;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::World::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + limit: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(limit); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setWaterUndergroundCreatureSpawnLimit", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Create a new virtual {@link WorldBorder}. - /// - /// Note that world borders created by the server will not respect any world - /// scaling effects (i.e. coordinates are not divided by 8 in the nether). - pub fn create_world_border( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/WorldBorder;"); + #[deprecated] + /// Gets user-specified limit for number of water ambient mobs that can spawn in a chunk. + pub fn water_ambient_spawn_limit(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "createWorldBorder", + "getWaterAmbientSpawnLimit", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::WorldBorder::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } #[deprecated] - /// Gets the map from the given item ID. - pub fn get_map( + /// Sets the limit for number of water ambient mobs that can spawn in a chunk in this worldNote: If set to a negative number the world will use the server-wide spawn limit instead. + pub fn set_water_ambient_spawn_limit( &self, - id: i32, - ) -> Result>, Box> { - let sig = String::from("(I)Lorg/bukkit/map/MapView;"); - let val_1 = jni::objects::JValueGen::Int(id); + limit: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(limit); let res = self.jni_ref().call_method( &self.jni_object(), - "getMap", + "setWaterAmbientSpawnLimit", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Gets the limit for number of ambient mobs that can spawn in a chunk in this world + pub fn ambient_spawn_limit(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAmbientSpawnLimit", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::map::MapView::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - /// Create a new map with an automatically assigned ID. - pub fn create_map( + #[deprecated] + /// Sets the limit for number of ambient mobs that can spawn in a chunk in this worldNote: If set to a negative number the world will use the server-wide spawn limit instead. + pub fn set_ambient_spawn_limit(&self, limit: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(limit); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAmbientSpawnLimit", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the limit for number of {@link SpawnCategory} entities that can spawn in a chunk in + /// this world + pub fn get_spawn_limit( &self, - world: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/World;)Lorg/bukkit/map/MapView;"); + spawn_category: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/SpawnCategory;)I"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) + jni::objects::JObject::from_raw(spawn_category.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "createMap", + "getSpawnLimit", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::map::MapView::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Create a new explorer map targeting the closest nearby structure of a - /// given {@link StructureType}. + /// Sets the limit for number of {@link SpawnCategory} entities that can spawn in a chunk in + /// this world /// - /// This method uses implementation default values for radius and - /// findUnexplored (usually 100, true). - pub fn create_explorer_map( + /// Note: If set to a negative number the world will use the + /// server-wide spawn limit instead. + pub fn set_spawn_limit( + &self, + spawn_category: impl Into>, + limit: i32, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/SpawnCategory;I)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(spawn_category.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(limit); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSpawnLimit", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Play a note at the provided Location in the World. + /// + /// This will work with cake. + /// + /// This method will fail silently when called with {@link Instrument#CUSTOM_HEAD}. + pub fn play_note( + &self, + loc: impl Into>, + instrument: impl Into>, + note: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Location;Lorg/bukkit/Instrument;Lorg/bukkit/Note;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(instrument.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(note.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "playNote", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Play a Sound at the provided Location in the World. For sounds with multiple + /// variations passing the same seed will always play the same variation. + /// + /// This function will fail silently if Location or Sound are null. No sound will + /// be heard by the players if their clients do not have the respective sound for + /// the value passed. + pub fn play_sound( &self, - world: impl Into>, location: impl Into>, - structure_type: impl Into>, - radius: std::option::Option, - find_unexplored: std::option::Option, - ) -> Result, Box> { + sound: impl Into, + category: impl Into>, + volume: f32, + pitch: std::option::Option, + seed: std::option::Option, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/World;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); - args.push(val_1); sig += "Lorg/bukkit/Location;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { + let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(location.into().jni_object().clone()) }); + args.push(val_1); + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(sound.into())?, + )); args.push(val_2); - sig += "Lorg/bukkit/StructureType;"; + sig += "Lorg/bukkit/SoundCategory;"; let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(structure_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(category.into().jni_object().clone()) }); args.push(val_3); - if let Some(a) = radius { - sig += "I"; - let val_4 = jni::objects::JValueGen::Int(a); - args.push(val_4); - } - if let Some(a) = find_unexplored { - sig += "Z"; - let val_5 = jni::objects::JValueGen::Bool(a.into()); + sig += "F"; + let val_4 = jni::objects::JValueGen::Float(volume); + args.push(val_4); + if let Some(a) = pitch { + sig += "F"; + let val_5 = jni::objects::JValueGen::Float(a); args.push(val_5); } - sig += ")Lorg/bukkit/inventory/ItemStack;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "createExplorerMap", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Reloads the server, refreshing settings and plugin information. - pub fn reload(&self) -> Result<(), Box> { - let sig = String::from("()V"); + if let Some(a) = seed { + sig += "J"; + let val_6 = jni::objects::JValueGen::Long(a); + args.push(val_6); + } + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "reload", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "playSound", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Reload only the Minecraft data for the server. This includes custom - /// advancements and loot tables. - pub fn reload_data(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Get an array containing the names of all the {@link GameRule}s. + pub fn game_rules(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "reloadData", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns the primary logger associated with this server instance. - pub fn logger( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/logging/Logger;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getLogger", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getGameRules", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::logging::JavaLogger::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Gets a {@link PluginCommand} with the given name or alias. - pub fn get_plugin_command( + /// Get the current value for a given {@link GameRule}. + pub fn get_game_rule_value( &self, - name: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/command/PluginCommand;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPluginCommand", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + rule: impl Into>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/GameRule;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(rule.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")LT;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getGameRuleValue", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::command::PluginCommand::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Writes loaded players to disk. - pub fn save_players(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "savePlayers", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(Some(res.l()?)) } - /// Dispatches a command on this server, and executes it if found. - pub fn dispatch_command( + #[deprecated] + /// Set the specified gamerule to specified value.The rule may attempt to validate the value passed, will return true if value was set.If rule is null, the function will return false. + pub fn set_game_rule_value( &self, - sender: impl Into>, - command_line: impl Into, + rule: impl Into, + value: impl Into, ) -> Result> { - let sig = String::from("(Lorg/bukkit/command/CommandSender;Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) - }); + let sig = String::from("(Ljava/lang/String;Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(rule.into())?, + )); let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(command_line.into())?, + self.jni_ref().new_string(value.into())?, )); let res = self.jni_ref().call_method( &self.jni_object(), - "dispatchCommand", + "setGameRuleValue", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), @@ -2982,1512 +3406,1110 @@ impl<'mc> Server<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Adds a recipe to the crafting manager. - pub fn add_recipe( + /// Checks if string is a valid game rule + pub fn is_game_rule( &self, - recipe: impl Into>, + rule: impl Into, ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/Recipe;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) - }); + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(rule.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "addRecipe", + "isGameRule", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get a list of all recipes for a given item. The stack size is ignored - /// in comparisons. If the durability is -1, it will match any data value. - pub fn get_recipes_for( + /// Get the default value for a given {@link GameRule}. This value is not + /// guaranteed to match the current value. + pub fn get_game_rule_default( &self, - result: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/List;"); + rule: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/GameRule;)LT;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(result.into().jni_object().clone()) + jni::objects::JObject::from_raw(rule.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "getRecipesFor", + "getGameRuleDefault", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::inventory::Recipe::from_raw(&self.jni_ref(), obj)?); + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - Ok(new_vec) + Ok(Some(res.l()?)) } - /// Get the {@link Recipe} for the given key. - pub fn get_recipe( + /// Set the given {@link GameRule}'s new value. + pub fn set_game_rule( &self, - recipe_key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/inventory/Recipe;"); + rule: impl Into>, + new_value: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/GameRule;LT;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(recipe_key.into().jni_object().clone()) + jni::objects::JObject::from_raw(rule.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Object(new_value); let res = self.jni_ref().call_method( &self.jni_object(), - "getRecipe", + "setGameRule", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + Ok(res.z()?) + } + /// Gets the world border for this world. + pub fn world_border(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/WorldBorder;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getWorldBorder", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::WorldBorder::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Spawns the particle (the number of times specified by count) + /// at the target location. The position of each particle will be + /// randomized positively and negatively by the offset parameters + /// on each axis. + pub fn spawn_particle( + &self, + particle: impl Into>, + x: f64, + y: f64, + z: std::option::Option, + count: std::option::Option, + offset_x: std::option::Option, + offset_y: std::option::Option, + offset_z: std::option::Option, + extra: std::option::Option, + data: std::option::Option>, + force: std::option::Option, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Particle;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(particle.into().jni_object().clone()) + }); + args.push(val_1); + sig += "D"; + let val_2 = jni::objects::JValueGen::Double(x); + args.push(val_2); + sig += "D"; + let val_3 = jni::objects::JValueGen::Double(y); + args.push(val_3); + if let Some(a) = z { + sig += "D"; + let val_4 = jni::objects::JValueGen::Double(a); + args.push(val_4); } - Ok(Some(crate::inventory::Recipe::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + if let Some(a) = count { + sig += "I"; + let val_5 = jni::objects::JValueGen::Int(a); + args.push(val_5); + } + if let Some(a) = offset_x { + sig += "D"; + let val_6 = jni::objects::JValueGen::Double(a); + args.push(val_6); + } + if let Some(a) = offset_y { + sig += "D"; + let val_7 = jni::objects::JValueGen::Double(a); + args.push(val_7); + } + if let Some(a) = offset_z { + sig += "D"; + let val_8 = jni::objects::JValueGen::Double(a); + args.push(val_8); + } + if let Some(a) = extra { + sig += "D"; + let val_9 = jni::objects::JValueGen::Double(a); + args.push(val_9); + } + if let Some(a) = data { + sig += "LT;"; + let val_10 = jni::objects::JValueGen::Object(a); + args.push(val_10); + } + if let Some(a) = force { + sig += "Z"; + let val_11 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_11); + } + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "spawnParticle", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get the {@link Recipe} for the list of ItemStacks provided. - /// The list is formatted as a crafting matrix where the index follow - /// the pattern below: - ///
    -    /// [ 0 1 2 ]
    -    /// [ 3 4 5 ]
    -    /// [ 6 7 8 ]
    -    /// 
    - /// NOTE: This method will not modify the provided ItemStack array, for that, use - /// {@link #craftItem(ItemStack[], World, Player)}. - pub fn get_crafting_recipe( + /// Find the closest nearby structure of a given {@link Structure}. Finding + /// unexplored structures can, and will, block if the world is looking in + /// chunks that gave not generated yet. This can lead to the world + /// temporarily freezing while locating an unexplored structure. + /// + /// The {@code radius} is not a rigid square radius. Each structure may alter + /// how many chunks to check for each iteration. Do not assume that only a + /// radius x radius chunk area will be checked. For example, + /// {@link Structure#MANSION} can potentially check up to 20,000 blocks away + /// (or more) regardless of the radius used. + /// + /// This will not load or generate chunks. This can also lead to + /// instances where the server can hang if you are only looking for + /// unexplored structures. This is because it will keep looking further and + /// further out in order to find the structure. + /// + /// The difference between searching for a {@link StructureType} and a + /// {@link Structure} is, that a {@link StructureType} can refer to multiple + /// {@link Structure Structures} while searching for a {@link Structure} + /// while only search for the given {@link Structure}. + pub fn locate_nearest_structure( &self, - crafting_matrix: impl Into>, - world: impl Into>, - ) -> Result>, Box> { - let sig = String::from( - "(Lorg/bukkit/inventory/ItemStack;Lorg/bukkit/World;)Lorg/bukkit/inventory/Recipe;", - ); + origin: impl Into>, + structure: impl Into>, + radius: i32, + find_unexplored: bool, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(crafting_matrix.into().jni_object().clone()) + jni::objects::JObject::from_raw(origin.into().jni_object().clone()) }); + args.push(val_1); + sig += "Lorg/bukkit/generator/structure/Structure;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) + jni::objects::JObject::from_raw(structure.into().jni_object().clone()) }); + args.push(val_2); + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(radius); + args.push(val_3); + sig += "Z"; + let val_4 = jni::objects::JValueGen::Bool(find_unexplored.into()); + args.push(val_4); + sig += ")Lorg/bukkit/util/StructureSearchResult;"; let res = self.jni_ref().call_method( &self.jni_object(), - "getCraftingRecipe", + "locateNearestStructure", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + args, ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::inventory::Recipe::from_raw( + Ok(Some(crate::util::StructureSearchResult::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Get the crafted item using the list of {@link ItemStack} provided. - /// The list is formatted as a crafting matrix where the index follow - /// the pattern below: - ///
    -    /// [ 0 1 2 ]
    -    /// [ 3 4 5 ]
    -    /// [ 6 7 8 ]
    -    /// 
    - /// The {@link World} and {@link Player} arguments are required to fulfill the Bukkit Crafting - /// events. - /// Calls {@link org.bukkit.event.inventory.PrepareItemCraftEvent} to imitate the {@link Player} - /// initiating the crafting event. - pub fn craft_item( + /// Find the closest nearby location with a biome matching the provided + /// {@link Biome}(s). Finding biomes can, and will, block if the world is looking + /// in chunks that have not generated yet. This can lead to the world temporarily + /// freezing while locating a biome. + /// + /// Note: This will not reflect changes made to the world after + /// generation, this method only sees the biome at the time of world generation. + /// This will not load or generate chunks. + /// + /// If multiple biomes are provided {@link BiomeSearchResult#getBiome()} will + /// indicate which one was located. Higher values for {@code horizontalInterval} + /// and {@code verticalInterval} will result in faster searches, but may lead to + /// small biomes being missed. + pub fn locate_nearest_biome( &self, - crafting_matrix: impl Into>, - world: impl Into>, - player: std::option::Option>>, - ) -> Result, Box> { + origin: impl Into>, + radius: i32, + horizontal_interval: i32, + vertical_interval: std::option::Option, + biomes: std::option::Option>>, + ) -> Result>, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; + sig += "Lorg/bukkit/Location;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(crafting_matrix.into().jni_object().clone()) + jni::objects::JObject::from_raw(origin.into().jni_object().clone()) }); args.push(val_1); - sig += "Lorg/bukkit/World;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(radius); args.push(val_2); - if let Some(a) = player { - sig += "Lorg/bukkit/entity/Player;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(horizontal_interval); + args.push(val_3); + if let Some(a) = vertical_interval { + sig += "I"; + let val_4 = jni::objects::JValueGen::Int(a); + args.push(val_4); + } + if let Some(a) = biomes { + sig += "Lorg/bukkit/block/Biome;"; + let val_5 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); - args.push(val_3); + args.push(val_5); } - sig += ")Lorg/bukkit/inventory/ItemStack;"; + sig += ")Lorg/bukkit/util/BiomeSearchResult;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "locateNearestBiome", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::util::BiomeSearchResult::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Finds the nearest raid close to the given location. + pub fn locate_nearest_raid( + &self, + location: impl Into>, + radius: i32, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Location;I)Lorg/bukkit/Raid;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(radius); + let res = self.jni_ref().call_method( + &self.jni_object(), + "locateNearestRaid", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Raid::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Gets all raids that are going on over this world. + pub fn raids(&self) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "craftItem", sig.as_str(), args); + .call_method(&self.jni_object(), "getRaids", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::Raid::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Get the {@link DragonBattle} associated with this world. + /// If this world's environment is not {@link Environment#THE_END}, null will + /// be returned. + /// + /// If an end world, a dragon battle instance will be returned regardless of + /// whether or not a dragon is present in the world or a fight sequence has + /// been activated. The dragon battle instance acts as a state holder. + pub fn ender_dragon_battle( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/boss/DragonBattle;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getEnderDragonBattle", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::boss::DragonBattle::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Get all {@link FeatureFlag} enabled in this world. + pub fn feature_flags( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFeatureFlags", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the crafted item using the list of {@link ItemStack} provided. - /// The list is formatted as a crafting matrix where the index follow - /// the pattern below: - ///
    -    /// [ 0 1 2 ]
    -    /// [ 3 4 5 ]
    -    /// [ 6 7 8 ]
    -    /// 
    - /// The {@link World} and {@link Player} arguments are required to fulfill the Bukkit Crafting - /// events. - /// Calls {@link org.bukkit.event.inventory.PrepareItemCraftEvent} to imitate the {@link Player} - /// initiating the crafting event. - pub fn craft_item_result( + /// Gets all generated structures of a given {@link Structure} that intersect + /// the chunk at the given coordinates. + /// + /// If no structures are present an empty collection will be returned. + pub fn get_structures( &self, - crafting_matrix: impl Into>, - world: impl Into>, - player: std::option::Option>>, - ) -> Result, Box> { + x: i32, + z: i32, + structure: std::option::Option>>, + ) -> Result>, Box> + { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(crafting_matrix.into().jni_object().clone()) - }); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); args.push(val_1); - sig += "Lorg/bukkit/World;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(z); args.push(val_2); - if let Some(a) = player { - sig += "Lorg/bukkit/entity/Player;"; + if let Some(a) = structure { + sig += "Lorg/bukkit/generator/structure/Structure;"; let val_3 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); args.push(val_3); } - sig += ")Lorg/bukkit/inventory/ItemCraftResult;"; + sig += ")Ljava/util/Collection;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "craftItemResult", sig.as_str(), args); + .call_method(&self.jni_object(), "getStructures", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemCraftResult::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::generator::structure::GeneratedStructure::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(new_vec) } - /// Get an iterator through the list of crafting recipes. - pub fn recipe_iterator( + /// Gets the {@link BlockState} at the given coordinates. + pub fn get_block_state( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Iterator;"); + x: i32, + y: std::option::Option, + z: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); + args.push(val_1); + if let Some(a) = y { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + if let Some(a) = z { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + sig += ")Lorg/bukkit/block/BlockState;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "recipeIterator", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBlockState", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaIterator::from_raw(&self.jni_ref(), unsafe { + crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Clears the list of crafting recipes. - pub fn clear_recipes(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "clearRecipes", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Resets the list of crafting recipes to the default. - pub fn reset_recipes(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Gets the {@link BlockData} at the given coordinates. + pub fn get_block_data( + &self, + x: i32, + y: std::option::Option, + z: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); + args.push(val_1); + if let Some(a) = y { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + if let Some(a) = z { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + sig += ")Lorg/bukkit/block/data/BlockData;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "resetRecipes", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Remove a recipe from the server. - /// Note that removing a recipe may cause permanent loss of data - /// associated with that recipe (eg whether it has been discovered by - /// players). - pub fn remove_recipe( - &self, - key: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removeRecipe", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets a list of command aliases defined in the server properties. - pub fn command_aliases( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCommandAliases", - sig.as_str(), - vec![], - ); + .call_method(&self.jni_object(), "getBlockData", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the radius, in blocks, around each worlds spawn point to protect. - pub fn spawn_radius(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSpawnRadius", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the radius, in blocks, around each worlds spawn point to protect. - pub fn set_spawn_radius(&self, value: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(value); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSpawnRadius", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Gets whether the server should send a preview of the player's chat message to the client when the player types a message - pub fn should_send_chat_previews(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "shouldSendChatPreviews", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets whether the server only allow players with Mojang-signed public key - /// to join - pub fn is_enforcing_secure_profiles(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isEnforcingSecureProfiles", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets whether this server is allowing connections transferred from other - /// servers. - pub fn is_accepting_transfers(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isAcceptingTransfers", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets whether the Server hide online players in server status. - pub fn hide_online_players(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getHideOnlinePlayers", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets whether the Server is in online mode or not. - pub fn online_mode(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getOnlineMode", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets whether this server allows flying or not. - pub fn allow_flight(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAllowFlight", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets whether the server is in hardcore mode or not. - pub fn is_hardcore(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isHardcore", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Shutdowns the server, stopping everything. - pub fn shutdown(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "shutdown", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Broadcasts the specified message to every user with the given - /// permission name. - pub fn broadcast( - &self, - message: impl Into, - permission: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;Ljava/lang/String;)I"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(message.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(permission.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "broadcast", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the player by the given UUID, regardless if they are offline or - /// online. - /// - /// This will return an object even if the player does not exist. To this - /// method, all players will exist. - pub fn get_offline_player( - &self, - id: impl Into>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(id.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Lorg/bukkit/OfflinePlayer;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getOfflinePlayer", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::OfflinePlayer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Creates a new {@link PlayerProfile}. - pub fn create_player_profile( + /// Gets the type of the block at the given coordinates. + pub fn get_type( &self, - unique_id: impl Into>, - name: std::option::Option>, - ) -> Result, Box> { + x: i32, + y: std::option::Option, + z: std::option::Option, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(unique_id.into().jni_object().clone()) - }); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); args.push(val_1); - if let Some(a) = name { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); + if let Some(a) = y { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); args.push(val_2); } - sig += ")Lorg/bukkit/profile/PlayerProfile;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "createPlayerProfile", - sig.as_str(), - args, - ); - let res = self.jni_ref().translate_error(res)?; - crate::profile::PlayerProfile::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets a set containing all current IPs that are banned. - pub fn ipbans( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + if let Some(a) = z { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + sig += ")Lorg/bukkit/Material;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getIPBans", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getType", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + crate::Material::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Bans the specified address from the server. - pub fn ban_ip( + /// Sets the {@link BlockData} at the given coordinates. + pub fn set_block_data( &self, - address: jni::objects::JObject<'mc>, + x: i32, + y: i32, + z: std::option::Option, + block_data: std::option::Option>>, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/net/InetAddress;"; - let val_1 = jni::objects::JValueGen::Object(address); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); args.push(val_1); + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(y); + args.push(val_2); + if let Some(a) = z { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + if let Some(a) = block_data { + sig += "Lorg/bukkit/block/data/BlockData;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_4); + } sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "banIP", sig.as_str(), args); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setBlockData", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Unbans the specified address from the server. - pub fn unban_ip( + /// Sets the {@link Material} at the given coordinates. + pub fn set_type( &self, - address: jni::objects::JObject<'mc>, + x: i32, + y: i32, + z: std::option::Option, + material: std::option::Option>>, ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/net/InetAddress;"; - let val_1 = jni::objects::JValueGen::Object(address); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); args.push(val_1); + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(y); + args.push(val_2); + if let Some(a) = z { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + if let Some(a) = material { + sig += "Lorg/bukkit/Material;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_4); + } sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "unbanIP", sig.as_str(), args); + .call_method(&self.jni_object(), "setType", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets a set containing all banned players. - pub fn banned_players( + /// Creates a new entity at the given {@link Location}. + pub fn spawn_entity( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getBannedPlayers", - sig.as_str(), - vec![], - ); + loc: impl Into>, + val_type: impl Into>, + randomize_data: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Lorg/bukkit/entity/EntityType;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + args.push(val_2); + if let Some(a) = randomize_data { + sig += "Z"; + let val_3 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_3); + } + sig += ")Lorg/bukkit/entity/Entity;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "spawnEntity", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets a ban list for the supplied type. - pub fn get_ban_list( + /// Creates an entity of a specific class at the given {@link Location} but + /// does not spawn it in the world. + /// + /// Note: The created entity keeps a reference to the world it was + /// created in, care should be taken that the entity does not outlive the + /// world instance as this will lead to memory leaks. + pub fn create_entity( &self, - val_type: impl Into>, + location: impl Into>, + clazz: jni::objects::JClass<'mc>, ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/BanList/Type;)LT;"); + let sig = String::from("(Lorg/bukkit/Location;Ljava/lang/Class;)LT;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(location.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Object(clazz.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getBanList", + "createEntity", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; Ok(res.l()?) } - /// Gets a set containing all player operators. - pub fn operators( + /// Gets the highest coordinate corresponding to the {@link HeightMap} at the + /// given {@link Location}. + pub fn get_highest_block_yat( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getOperators", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the default {@link GameMode} for new players. - pub fn default_game_mode(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/GameMode;"); + location: impl Into>, + height_map: std::option::Option>>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = height_map { + sig += "Lorg/bukkit/HeightMap;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")I"; let res = self.jni_ref().call_method( &self.jni_object(), - "getDefaultGameMode", + "getHighestBlockYAt", sig.as_str(), - vec![], + args, ); let res = self.jni_ref().translate_error(res)?; - crate::GameMode::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Sets the default {@link GameMode} for new players. - pub fn set_default_game_mode( + /// Spawns a previously created entity in the world. + /// + /// The provided entity must not have already been spawned in a world. + pub fn add_entity( &self, - mode: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/GameMode;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(mode.into().jni_object().clone()) - }); + entity: jni::objects::JObject<'mc>, + ) -> Result, Box> { + let sig = String::from("(LT;)LT;"); + let val_1 = jni::objects::JValueGen::Object(entity); let res = self.jni_ref().call_method( &self.jni_object(), - "setDefaultGameMode", + "addEntity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) } - /// Gets a {@link ConsoleCommandSender} that may be used as an input source - /// for this server. - pub fn console_sender( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/command/ConsoleCommandSender;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getConsoleSender", - sig.as_str(), - vec![], - ); + /// Gets the unique name of this world + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::command::ConsoleCommandSender::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Gets every player that has ever played on this server. - pub fn offline_players(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/OfflinePlayer;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getOfflinePlayers", - sig.as_str(), - vec![], - ); + /// Gets the Unique ID of this world + pub fn uid(&self) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getUID", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::OfflinePlayer::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the {@link Messenger} responsible for this server. - pub fn messenger( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/plugin/messaging/Messenger;"); + /// Gets the {@link World.Environment} type of this world + pub fn environment(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World/Environment;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMessenger", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEnvironment", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::plugin::messaging::Messenger::from_raw(&self.jni_ref(), unsafe { + crate::WorldEnvironment::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the {@link HelpMap} providing help topics for this server. - pub fn help_map(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/help/HelpMap;"); + /// Gets the Seed for this world. + pub fn seed(&self) -> Result> { + let sig = String::from("()J"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSeed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.j()?) + } + /// Gets the minimum height of this world. + /// + /// If the min height is 0, there are only blocks from y=0. + pub fn min_height(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getHelpMap", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMinHeight", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::help::HelpMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Creates an empty inventory of type {@link InventoryType#CHEST} with the - /// specified size and title. - pub fn create_inventory( - &self, - owner: impl Into>, - size: i32, - title: std::option::Option>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/InventoryHolder;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owner.into().jni_object().clone()) - }); - args.push(val_1); - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(size); - args.push(val_2); - if let Some(a) = title { - sig += "Ljava/lang/String;"; - let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_3); - } - sig += ")Lorg/bukkit/inventory/Inventory;"; + /// Gets the maximum height of this world. + /// + /// If the max height is 100, there are only blocks from y=0 to y=99. + pub fn max_height(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "createInventory", sig.as_str(), args); + .call_method(&self.jni_object(), "getMaxHeight", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Creates an empty merchant. - pub fn create_merchant( - &self, - title: impl Into, - ) -> Result, Box> { - let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/inventory/Merchant;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(title.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "createMerchant", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::Merchant::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the amount of consecutive neighbor updates before skipping - /// additional ones. - pub fn max_chained_neighbor_updates(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMaxChainedNeighborUpdates", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - #[deprecated] - /// Gets user-specified limit for number of monsters that can spawn in a chunk. - pub fn monster_spawn_limit(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMonsterSpawnLimit", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - #[deprecated] - /// Gets user-specified limit for number of animals that can spawn in a chunk. - pub fn animal_spawn_limit(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAnimalSpawnLimit", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - #[deprecated] - /// Gets user-specified limit for number of water animals that can spawn in a chunk. - pub fn water_animal_spawn_limit(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getWaterAnimalSpawnLimit", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - #[deprecated] - /// Gets user-specified limit for number of water ambient mobs that can spawn in a chunk. - pub fn water_ambient_spawn_limit(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getWaterAmbientSpawnLimit", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - #[deprecated] - /// Get user-specified limit for number of water creature underground that can spawn in a chunk. - pub fn water_underground_creature_spawn_limit( - &self, - ) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getWaterUndergroundCreatureSpawnLimit", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - #[deprecated] - /// Gets user-specified limit for number of ambient mobs that can spawn in a chunk. - pub fn ambient_spawn_limit(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAmbientSpawnLimit", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets user-specified limit for number of {@link SpawnCategory} mobs that can spawn in - /// a chunk. - /// Note: the {@link SpawnCategory#MISC} are not consider. - pub fn get_spawn_limit( + /// Sends this recipient a Plugin Message on the specified outgoing + /// channel. + /// + /// The message may not be larger than {@link Messenger#MAX_MESSAGE_SIZE} + /// bytes, and the plugin must be registered to send messages on the + /// specified channel. + pub fn send_plugin_message( &self, - spawn_category: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/SpawnCategory;)I"); + source: impl Into>, + channel: impl Into, + message: i8, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;Ljava/lang/String;B)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(spawn_category.into().jni_object().clone()) + jni::objects::JObject::from_raw(source.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSpawnLimit", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Checks the current thread against the expected primary thread for the - /// server. - /// - /// Note: this method should not be used to indicate the current - /// synchronized state of the runtime. A current thread matching the main - /// thread indicates that it is synchronized, but a mismatch does not - /// preclude the same assumption. - pub fn is_primary_thread(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isPrimaryThread", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the message that is displayed on the server list. - pub fn motd(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getMotd", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Set the message that is displayed on the server list. - pub fn set_motd(&self, motd: impl Into) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(motd.into())?, + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(channel.into())?, )); + let val_3 = jni::objects::JValueGen::Byte(message); let res = self.jni_ref().call_method( &self.jni_object(), - "setMotd", + "sendPluginMessage", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the default message that is displayed when the server is stopped. - pub fn shutdown_message(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getShutdownMessage", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// Gets the current warning state for the server. - pub fn warning_state( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Warning/WarningState;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getWarningState", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::WarningWarningState::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the instance of the item factory (for {@link ItemMeta}). - pub fn item_factory( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemFactory;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getItemFactory", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemFactory::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the instance of the entity factory (for {@link EntitySnapshot}). - pub fn entity_factory( + /// Gets a set containing all the Plugin Channels that this client is + /// listening on. + pub fn listening_plugin_channels( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityFactory;"); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getEntityFactory", + "getListeningPluginChannels", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityFactory::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the instance of the scoreboard manager. - /// - /// This will only exist after the first world has loaded. - pub fn scoreboard_manager( + /// Sets a metadata value in the implementing object's metadata store. + pub fn set_metadata( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/scoreboard/ScoreboardManager;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getScoreboardManager", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + metadata_key: impl Into, + new_metadata_value: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + if let Some(a) = new_metadata_value { + sig += "Lorg/bukkit/metadata/MetadataValue;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); } - Ok(Some(crate::scoreboard::ScoreboardManager::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setMetadata", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get (or create) a new {@link Criteria} by its name. - pub fn get_scoreboard_criteria( + /// Returns a list of previously set metadata values from the implementing + /// object's metadata store. + pub fn get_metadata( &self, - name: impl Into, - ) -> Result, Box> { - let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/scoreboard/Criteria;"); + metadata_key: impl Into, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, + self.jni_ref().new_string(metadata_key.into())?, )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getScoreboardCriteria", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + args.push(val_1); + sig += ")Ljava/util/List;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getMetadata", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::scoreboard::Criteria::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::metadata::MetadataValue::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(new_vec) } - /// Gets an instance of the server's default server-icon. - pub fn server_icon( + /// Tests to see whether the implementing object contains the given + /// metadata value in its metadata store. + pub fn has_metadata( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/util/CachedServerIcon;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getServerIcon", sig.as_str(), vec![]); + metadata_key: impl Into, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasMetadata", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::util::CachedServerIcon::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Creates a cached server-icon for the specific image. - /// - /// Size and type are implementation defined. An incompatible file is - /// guaranteed to throw an implementation-defined {@link Exception}. - pub fn load_server_icon( + /// Removes the given metadata value from the implementing object's + /// metadata store. + pub fn remove_metadata( &self, - image: jni::objects::JObject<'mc>, - ) -> Result, Box> { + metadata_key: impl Into, + owning_plugin: impl Into>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/awt/image/BufferedImage;"; - let val_1 = jni::objects::JValueGen::Object(image); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); args.push(val_1); - sig += ")Lorg/bukkit/util/CachedServerIcon;"; + sig += "Lorg/bukkit/plugin/Plugin;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + }); + args.push(val_2); + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "loadServerIcon", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::util::CachedServerIcon::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Set the idle kick timeout. Any players idle for the specified amount of - /// time will be automatically kicked. - /// - /// A value of 0 will disable the idle kick timeout. - pub fn set_idle_timeout(&self, threshold: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(threshold); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setIdleTimeout", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "removeMetadata", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the idle kick timeout. - pub fn idle_timeout(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getIdleTimeout", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Create a ChunkData for use in a generator. - /// See {@link ChunkGenerator#generateChunkData(org.bukkit.World, java.util.Random, int, int, org.bukkit.generator.ChunkGenerator.BiomeGrid)} - pub fn create_chunk_data( + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + pub fn persistent_data_container( &self, - world: impl Into>, - ) -> Result, Box> { - let sig = - String::from("(Lorg/bukkit/World;)Lorg/bukkit/generator/ChunkGenerator/ChunkData;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); + ) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; let res = self.jni_ref().call_method( &self.jni_object(), - "createChunkData", + "getPersistentDataContainer", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); let res = self.jni_ref().translate_error(res)?; - crate::generator::ChunkGeneratorChunkData::from_raw(&self.jni_ref(), unsafe { + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Creates a boss bar instance to display to players. The progress defaults - /// to 1.0. - /// - /// This instance is added to the persistent storage of the server and will - /// be editable by commands and restored after restart. - pub fn create_boss_bar( - &self, - key: impl Into>, - title: impl Into, - color: impl Into>, - style: impl Into>, - flags: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/NamespacedKey;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(title.into())?, - )); - args.push(val_2); - sig += "Lorg/bukkit/boss/BarColor;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) - }); - args.push(val_3); - sig += "Lorg/bukkit/boss/BarStyle;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(style.into().jni_object().clone()) - }); - args.push(val_4); - if let Some(a) = flags { - sig += "Lorg/bukkit/boss/BarFlag;"; - let val_5 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_5); - } - sig += ")Lorg/bukkit/boss/KeyedBossBar;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "createBossBar", sig.as_str(), args); + /// Return the namespaced identifier for this object. + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::boss::KeyedBossBar::from_raw(&self.jni_ref(), unsafe { + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets an unmodifiable iterator through all persistent bossbars. - ///
      - ///
    • not bound to a {@link org.bukkit.entity.Boss}
    • - ///
    • - /// not created using - /// {@link #createBossBar(String, BarColor, BarStyle, BarFlag...)} - ///
    • - ///
    - /// e.g. bossbars created using the bossbar command - pub fn boss_bars( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Iterator;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBossBars", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaIterator::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the {@link KeyedBossBar} specified by this key. - ///
      - ///
    • not bound to a {@link org.bukkit.entity.Boss}
    • - ///
    • - /// not created using - /// {@link #createBossBar(String, BarColor, BarStyle, BarFlag...)} - ///
    • - ///
    - /// e.g. bossbars created using the bossbar command - pub fn get_boss_bar( - &self, - key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/boss/KeyedBossBar;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getBossBar", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::boss::KeyedBossBar::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Removes a {@link KeyedBossBar} specified by this key. - ///
      - ///
    • not bound to a {@link org.bukkit.entity.Boss}
    • - ///
    • - /// not created using - /// {@link #createBossBar(String, BarColor, BarStyle, BarFlag...)} - ///
    • - ///
    - /// e.g. bossbars created using the bossbar command - pub fn remove_boss_bar( - &self, - key: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removeBossBar", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} +impl<'mc> Into> for World<'mc> { + fn into(self) -> crate::RegionAccessor<'mc> { + crate::RegionAccessor::from_raw(&self.jni_ref(), self.1) + .expect("Error converting World into crate::RegionAccessor") } - /// Gets an entity on the server by its UUID - pub fn get_entity( - &self, - uuid: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Ljava/util/UUID;)Lorg/bukkit/entity/Entity;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getEntity", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::entity::Entity::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) +} +impl<'mc> Into> for World<'mc> { + fn into(self) -> crate::generator::WorldInfo<'mc> { + crate::generator::WorldInfo::from_raw(&self.jni_ref(), self.1) + .expect("Error converting World into crate::generator::WorldInfo") } - /// Get the advancement specified by this key. - pub fn get_advancement( - &self, - key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/advancement/Advancement;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAdvancement", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::advancement::Advancement::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) +} +impl<'mc> Into> for World<'mc> { + fn into(self) -> crate::plugin::messaging::PluginMessageRecipient<'mc> { + crate::plugin::messaging::PluginMessageRecipient::from_raw(&self.jni_ref(), self.1) + .expect("Error converting World into crate::plugin::messaging::PluginMessageRecipient") } - /// Get an iterator through all advancements. Advancements cannot be removed - /// from this iterator, - pub fn advancement_iterator( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Iterator;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "advancementIterator", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaIterator::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} +impl<'mc> Into> for World<'mc> { + fn into(self) -> crate::metadata::Metadatable<'mc> { + crate::metadata::Metadatable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting World into crate::metadata::Metadatable") } - /// Creates a new {@link BlockData} instance for the specified Material, with - /// all properties initialized to unspecified defaults, except for those - /// provided in data. - /// - /// If material is specified, then the data string must not also - /// contain the material. - pub fn create_block_data( - &self, - material: impl Into>, - data: std::option::Option>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = data { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_2); - } - sig += ")Lorg/bukkit/block/data/BlockData;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "createBlockData", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} +impl<'mc> Into> for World<'mc> { + fn into(self) -> crate::persistence::PersistentDataHolder<'mc> { + crate::persistence::PersistentDataHolder::from_raw(&self.jni_ref(), self.1) + .expect("Error converting World into crate::persistence::PersistentDataHolder") } - /// Gets a tag which has already been defined within the server. Plugins are - /// suggested to use the concrete tags in {@link Tag} rather than this method - /// which makes no guarantees about which tags are available, and may also be - /// less performant due to lack of caching. - /// - /// Tags will be searched for in an implementation specific manner, but a - /// path consisting of namespace/tags/registry/key is expected. - /// - /// Server implementations are allowed to handle only the registries - /// indicated in {@link Tag}. - pub fn get_tag( - &self, - registry: impl Into, - tag: impl Into>, - clazz: jni::objects::JClass<'mc>, - ) -> Result>, Box> { - let sig = String::from( - "(Ljava/lang/String;Lorg/bukkit/NamespacedKey;Ljava/lang/Class;)Lorg/bukkit/Tag;", - ); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(registry.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tag.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(clazz.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTag", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Tag::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) +} +impl<'mc> Into> for World<'mc> { + fn into(self) -> crate::Keyed<'mc> { + crate::Keyed::from_raw(&self.jni_ref(), self.1) + .expect("Error converting World into crate::Keyed") } - /// Gets the specified {@link LootTable}. - pub fn get_loot_table( - &self, - key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/loot/LootTable;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLootTable", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); +} +pub enum WorldEnvironment<'mc> { + Normal { inner: WorldEnvironmentStruct<'mc> }, + Nether { inner: WorldEnvironmentStruct<'mc> }, + TheEnd { inner: WorldEnvironmentStruct<'mc> }, + Custom { inner: WorldEnvironmentStruct<'mc> }, +} +impl<'mc> std::fmt::Display for WorldEnvironment<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + WorldEnvironment::Normal { .. } => f.write_str("NORMAL"), + WorldEnvironment::Nether { .. } => f.write_str("NETHER"), + WorldEnvironment::TheEnd { .. } => f.write_str("THE_END"), + WorldEnvironment::Custom { .. } => f.write_str("CUSTOM"), } - Ok(Some(crate::loot::LootTable::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) } - /// Selects entities using the given Vanilla selector. - /// - /// No guarantees are made about the selector format, other than they match - /// the Vanilla format for the active Minecraft version. - /// - /// Usually a selector will start with '@', unless selecting a Player in - /// which case it may simply be the Player's name or UUID. - /// - /// Note that in Vanilla, elevated permissions are usually required to use - /// '@' selectors, but this method should not check such permissions from the - /// sender. - pub fn select_entities( - &self, - sender: impl Into>, - selector: impl Into, - ) -> Result>, Box> { - let sig = - String::from("(Lorg/bukkit/command/CommandSender;Ljava/lang/String;)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(selector.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "selectEntities", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); +} +impl<'mc> std::ops::Deref for WorldEnvironment<'mc> { + type Target = WorldEnvironmentStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + WorldEnvironment::Normal { inner } => inner, + WorldEnvironment::Nether { inner } => inner, + WorldEnvironment::TheEnd { inner } => inner, + WorldEnvironment::Custom { inner } => inner, } - Ok(new_vec) - } - /// Gets the structure manager for loading and saving structures. - pub fn structure_manager( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/structure/StructureManager;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getStructureManager", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::structure::StructureManager::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) } - /// Returns the registry for the given class. - /// - /// If no registry is present for the given class null will be returned. - /// - /// Depending on the implementation not every registry present in - /// {@link Registry} will be returned by this method. - pub fn get_registry( - &self, - t_class: jni::objects::JClass<'mc>, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/Class;)Lorg/bukkit/Registry;"); - let val_1 = jni::objects::JValueGen::Object(t_class.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getRegistry", - sig.as_str(), +} + +impl<'mc> WorldEnvironment<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/World/Environment"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/World/Environment;", vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "NORMAL" => Ok(WorldEnvironment::Normal { + inner: WorldEnvironmentStruct::from_raw(env, obj)?, + }), + "NETHER" => Ok(WorldEnvironment::Nether { + inner: WorldEnvironmentStruct::from_raw(env, obj)?, + }), + "THE_END" => Ok(WorldEnvironment::TheEnd { + inner: WorldEnvironmentStruct::from_raw(env, obj)?, + }), + "CUSTOM" => Ok(WorldEnvironment::Custom { + inner: WorldEnvironmentStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } - Ok(Some(crate::Registry::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) } - #[deprecated] +} - pub fn get_unsafe(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/UnsafeValues;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getUnsafe", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::UnsafeValues::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sends this recipient a Plugin Message on the specified outgoing - /// channel. - /// - /// The message may not be larger than {@link Messenger#MAX_MESSAGE_SIZE} - /// bytes, and the plugin must be registered to send messages on the - /// specified channel. - pub fn send_plugin_message( - &self, - source: impl Into>, - channel: impl Into, - message: i8, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;Ljava/lang/String;B)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(source.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(channel.into())?, - )); - let val_3 = jni::objects::JValueGen::Byte(message); - let res = self.jni_ref().call_method( - &self.jni_object(), - "sendPluginMessage", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets a set containing all the Plugin Channels that this client is - /// listening on. - pub fn listening_plugin_channels( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getListeningPluginChannels", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } +#[repr(C)] +pub struct WorldEnvironmentStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) +impl<'mc> JNIRaw<'mc> for WorldEnvironment<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Normal { inner } => inner.0.clone(), + Self::Nether { inner } => inner.0.clone(), + Self::TheEnd { inner } => inner.0.clone(), + Self::Custom { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Normal { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Nether { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::TheEnd { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Custom { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> Into> for Server<'mc> { - fn into(self) -> crate::plugin::messaging::PluginMessageRecipient<'mc> { - crate::plugin::messaging::PluginMessageRecipient::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Server into crate::plugin::messaging::PluginMessageRecipient") +impl<'mc> JNIInstantiatable<'mc> for WorldEnvironment<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate WorldEnvironment from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/World/Environment")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a WorldEnvironment object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "NORMAL" => Ok(WorldEnvironment::Normal { + inner: WorldEnvironmentStruct::from_raw(env, obj)?, + }), + "NETHER" => Ok(WorldEnvironment::Nether { + inner: WorldEnvironmentStruct::from_raw(env, obj)?, + }), + "THE_END" => Ok(WorldEnvironment::TheEnd { + inner: WorldEnvironmentStruct::from_raw(env, obj)?, + }), + "CUSTOM" => Ok(WorldEnvironment::Custom { + inner: WorldEnvironmentStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } } } -#[repr(C)] -pub struct Tag<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); -impl<'mc> JNIRaw<'mc> for Tag<'mc> { +impl<'mc> JNIRaw<'mc> for WorldEnvironmentStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -4495,18 +4517,21 @@ impl<'mc> JNIRaw<'mc> for Tag<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Tag<'mc> { +impl<'mc> JNIInstantiatable<'mc> for WorldEnvironmentStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Tag from null object.").into()); + return Err(eyre::eyre!( + "Tried to instantiate WorldEnvironmentStruct from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Tag")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/World/Environment")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Tag object, got {}", + "Invalid argument passed. Expected a WorldEnvironmentStruct object, got {}", name ) .into()) @@ -4516,46 +4541,50 @@ impl<'mc> JNIInstantiatable<'mc> for Tag<'mc> { } } -impl<'mc> Tag<'mc> { - /// Returns whether or not this tag has an entry for the specified item. - pub fn is_tagged( - &self, - item: jni::objects::JObject<'mc>, - ) -> Result> { - let sig = String::from("(LT;)Z"); - let val_1 = jni::objects::JValueGen::Object(item); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isTagged", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets an immutable set of all tagged items. +impl<'mc> WorldEnvironmentStruct<'mc> { pub fn values( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getValues", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World/Environment;"); + let cls = jni.find_class("org/bukkit/World/Environment"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::WorldEnvironment::from_raw(&jni, obj) } - /// Return the namespaced identifier for this object. - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + #[deprecated] + /// Gets the dimension ID of this environment + pub fn id(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getId", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) + } + #[deprecated] + /// Get an environment by ID + pub fn get_environment( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + id: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/World/Environment;"); + let val_1 = jni::objects::JValueGen::Int(id); + let cls = jni.find_class("org/bukkit/World/Environment"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getEnvironment", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::WorldEnvironment::from_raw(&jni, obj)?)) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -4563,19 +4592,13 @@ impl<'mc> Tag<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Tag<'mc> { - fn into(self) -> crate::Keyed<'mc> { - crate::Keyed::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Tag into crate::Keyed") - } -} #[repr(C)] -pub struct Bukkit<'mc>( +pub struct Warning<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Bukkit<'mc> { +impl<'mc> JNIRaw<'mc> for Warning<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -4583,18 +4606,18 @@ impl<'mc> JNIRaw<'mc> for Bukkit<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Bukkit<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Warning<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Bukkit from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Warning from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Bukkit")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/Warning")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Bukkit object, got {}", + "Invalid argument passed. Expected a Warning object, got {}", name ) .into()) @@ -4604,2790 +4627,53077 @@ impl<'mc> JNIInstantiatable<'mc> for Bukkit<'mc> { } } -impl<'mc> Bukkit<'mc> { - /// Gets the current {@link Server} singleton - pub fn server( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Server;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getServer", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::Server::from_raw(&jni, obj) +impl<'mc> Warning<'mc> { + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Attempts to set the {@link Server} singleton. - /// - /// This cannot be done if the Server is already set. - pub fn set_server( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - server: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Server;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(server.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( +} +pub enum WarningWarningState<'mc> { + On { + inner: WarningWarningStateStruct<'mc>, + }, + Off { + inner: WarningWarningStateStruct<'mc>, + }, + Default { + inner: WarningWarningStateStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for WarningWarningState<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + WarningWarningState::On { .. } => f.write_str("ON"), + WarningWarningState::Off { .. } => f.write_str("OFF"), + WarningWarningState::Default { .. } => f.write_str("DEFAULT"), + } + } +} +impl<'mc> std::ops::Deref for WarningWarningState<'mc> { + type Target = WarningWarningStateStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + WarningWarningState::On { inner } => inner, + WarningWarningState::Off { inner } => inner, + WarningWarningState::Default { inner } => inner, + } + } +} + +impl<'mc> WarningWarningState<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/Warning/WarningState"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( cls, - "setServer", - sig.as_str(), + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/Warning/WarningState;", vec![jni::objects::JValueGen::from(val_1)], ); - jni.translate_error(res)?; - Ok(()) - } - /// Gets the name of this server implementation. - pub fn name( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getName", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(jni - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? .to_string_lossy() - .to_string()) + .to_string(); + match variant_str.as_str() { + "ON" => Ok(WarningWarningState::On { + inner: WarningWarningStateStruct::from_raw(env, obj)?, + }), + "OFF" => Ok(WarningWarningState::Off { + inner: WarningWarningStateStruct::from_raw(env, obj)?, + }), + "DEFAULT" => Ok(WarningWarningState::Default { + inner: WarningWarningStateStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } - /// Gets the version string of this server implementation. - pub fn version( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getVersion", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(jni - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) +} + +#[repr(C)] +pub struct WarningWarningStateStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for WarningWarningState<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::On { inner } => inner.0.clone(), + Self::Off { inner } => inner.0.clone(), + Self::Default { inner } => inner.0.clone(), + } } - /// Gets the Bukkit version that this server is running. - pub fn bukkit_version( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getBukkitVersion", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(jni - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::On { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Off { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Default { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } - /// Gets a view of all currently logged in players. This {@linkplain - /// Collections#unmodifiableCollection(Collection) view} is a reused - /// object, making some operations like {@link Collection#size()} - /// zero-allocation. - /// - /// The collection is a view backed by the internal representation, such - /// that, changes to the internal state of the server will be reflected - /// immediately. However, the reuse of the returned collection (identity) - /// is not strictly guaranteed for future or all implementations. Casting - /// the collection, or relying on interface implementations (like {@link - /// Serializable} or {@link List}), is deprecated. - /// - /// Iteration behavior is undefined outside of self-contained main-thread - /// uses. Normal and immediate iterator use without consequences that - /// affect the collection are fully supported. The effects following - /// (non-exhaustive) {@link Entity#teleport(Location) teleportation}, - /// {@link Player#setHealth(double) death}, and {@link Player#kickPlayer( - /// String) kicking} are undefined. Any use of this collection from - /// asynchronous threads is unsafe. - /// - /// For safe consequential iteration or mimicking the old array behavior, - /// using {@link Collection#toArray(Object[])} is recommended. For making - /// snapshots, {@link ImmutableList#copyOf(Collection)} is recommended. - pub fn online_players( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getOnlinePlayers", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&jni, res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Player::from_raw(&jni, obj)?); +} +impl<'mc> JNIInstantiatable<'mc> for WarningWarningState<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate WarningWarningState from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Warning/WarningState")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a WarningWarningState object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "ON" => Ok(WarningWarningState::On { + inner: WarningWarningStateStruct::from_raw(env, obj)?, + }), + "OFF" => Ok(WarningWarningState::Off { + inner: WarningWarningStateStruct::from_raw(env, obj)?, + }), + "DEFAULT" => Ok(WarningWarningState::Default { + inner: WarningWarningStateStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } - Ok(new_vec) } - /// Get the maximum amount of players which can login to this server. - pub fn max_players( +} + +impl<'mc> JNIRaw<'mc> for WarningWarningStateStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for WarningWarningStateStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate WarningWarningStateStruct from null object." + ) + .into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Warning/WarningState")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a WarningWarningStateStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> WarningWarningStateStruct<'mc> { + pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()I"); - let cls = jni.find_class("org/bukkit/Bukkit"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Warning/WarningState;"); + let cls = jni.find_class("org/bukkit/Warning/WarningState"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getMaxPlayers", sig.as_str(), vec![]); + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; - Ok(res.i()?) + let obj = res.l()?; + crate::WarningWarningState::from_raw(&jni, obj) } - /// Set the maximum amount of players allowed to be logged in at once. - pub fn set_max_players( + /// This method checks the provided warning should be printed for this + /// state + pub fn print_for( + &self, + warning: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/Warning;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(warning.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "printFor", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// This method returns the corresponding warning state for the given + /// string value. + pub fn value( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - max_players: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(max_players); - let cls = jni.find_class("org/bukkit/Bukkit"); + value: impl Into, + ) -> Result, Box> { + let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/Warning/WarningState;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(value.into())?, + )); + let cls = jni.find_class("org/bukkit/Warning/WarningState"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method( cls, - "setMaxPlayers", + "value", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - jni.translate_error(res)?; - Ok(()) - } - /// Get the game port that the server runs on. - pub fn port( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()I"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getPort", sig.as_str(), vec![]); let res = jni.translate_error(res)?; - Ok(res.i()?) + let obj = res.l()?; + crate::WarningWarningState::from_raw(&jni, obj) } - /// Get the view distance from this server. - pub fn view_distance( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()I"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getViewDistance", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(res.i()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Get the simulation distance from this server. - pub fn simulation_distance( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()I"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getSimulationDistance", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(res.i()?) +} +pub enum TreeSpecies<'mc> { + Generic { inner: TreeSpeciesStruct<'mc> }, + Redwood { inner: TreeSpeciesStruct<'mc> }, + Birch { inner: TreeSpeciesStruct<'mc> }, + Jungle { inner: TreeSpeciesStruct<'mc> }, + Acacia { inner: TreeSpeciesStruct<'mc> }, + DarkOak { inner: TreeSpeciesStruct<'mc> }, +} +impl<'mc> std::fmt::Display for TreeSpecies<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + TreeSpecies::Generic { .. } => f.write_str("GENERIC"), + TreeSpecies::Redwood { .. } => f.write_str("REDWOOD"), + TreeSpecies::Birch { .. } => f.write_str("BIRCH"), + TreeSpecies::Jungle { .. } => f.write_str("JUNGLE"), + TreeSpecies::Acacia { .. } => f.write_str("ACACIA"), + TreeSpecies::DarkOak { .. } => f.write_str("DARK_OAK"), + } } - /// Get the IP that this server is bound to, or empty string if not - /// specified. - pub fn ip( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getIp", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(jni - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) +} +impl<'mc> std::ops::Deref for TreeSpecies<'mc> { + type Target = TreeSpeciesStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + TreeSpecies::Generic { inner } => inner, + TreeSpecies::Redwood { inner } => inner, + TreeSpecies::Birch { inner } => inner, + TreeSpecies::Jungle { inner } => inner, + TreeSpecies::Acacia { inner } => inner, + TreeSpecies::DarkOak { inner } => inner, + } } - /// Get world type (level-type setting) for default world. - pub fn world_type( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getWorldType", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(jni - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? +} + +impl<'mc> TreeSpecies<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/TreeSpecies"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/TreeSpecies;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? .to_string_lossy() - .to_string()) + .to_string(); + match variant_str.as_str() { + "GENERIC" => Ok(TreeSpecies::Generic { + inner: TreeSpeciesStruct::from_raw(env, obj)?, + }), + "REDWOOD" => Ok(TreeSpecies::Redwood { + inner: TreeSpeciesStruct::from_raw(env, obj)?, + }), + "BIRCH" => Ok(TreeSpecies::Birch { + inner: TreeSpeciesStruct::from_raw(env, obj)?, + }), + "JUNGLE" => Ok(TreeSpecies::Jungle { + inner: TreeSpeciesStruct::from_raw(env, obj)?, + }), + "ACACIA" => Ok(TreeSpecies::Acacia { + inner: TreeSpeciesStruct::from_raw(env, obj)?, + }), + "DARK_OAK" => Ok(TreeSpecies::DarkOak { + inner: TreeSpeciesStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } - /// Get generate-structures setting. - pub fn generate_structures( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()Z"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getGenerateStructures", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(res.z()?) +} + +#[repr(C)] +pub struct TreeSpeciesStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for TreeSpecies<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Generic { inner } => inner.0.clone(), + Self::Redwood { inner } => inner.0.clone(), + Self::Birch { inner } => inner.0.clone(), + Self::Jungle { inner } => inner.0.clone(), + Self::Acacia { inner } => inner.0.clone(), + Self::DarkOak { inner } => inner.0.clone(), + } } - /// Get max world size. - pub fn max_world_size( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()I"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getMaxWorldSize", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(res.i()?) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Generic { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Redwood { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Birch { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Jungle { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Acacia { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DarkOak { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } - /// Gets whether this server allows the End or not. - pub fn allow_end( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()Z"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getAllowEnd", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(res.z()?) +} +impl<'mc> JNIInstantiatable<'mc> for TreeSpecies<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate TreeSpecies from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/TreeSpecies")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a TreeSpecies object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "GENERIC" => Ok(TreeSpecies::Generic { + inner: TreeSpeciesStruct::from_raw(env, obj)?, + }), + "REDWOOD" => Ok(TreeSpecies::Redwood { + inner: TreeSpeciesStruct::from_raw(env, obj)?, + }), + "BIRCH" => Ok(TreeSpecies::Birch { + inner: TreeSpeciesStruct::from_raw(env, obj)?, + }), + "JUNGLE" => Ok(TreeSpecies::Jungle { + inner: TreeSpeciesStruct::from_raw(env, obj)?, + }), + "ACACIA" => Ok(TreeSpecies::Acacia { + inner: TreeSpeciesStruct::from_raw(env, obj)?, + }), + "DARK_OAK" => Ok(TreeSpecies::DarkOak { + inner: TreeSpeciesStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } } - /// Gets whether this server allows the Nether or not. - pub fn allow_nether( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()Z"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getAllowNether", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(res.z()?) +} + +impl<'mc> JNIRaw<'mc> for TreeSpeciesStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Gets whether the server is logging the IP addresses of players. - pub fn is_logging_ips( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()Z"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "isLoggingIPs", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(res.z()?) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - - pub fn initial_enabled_packs( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/List;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getInitialEnabledPacks", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&jni, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - jni.get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), +} +impl<'mc> JNIInstantiatable<'mc> for TreeSpeciesStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate TreeSpeciesStruct from null object.").into(), ); } - Ok(new_vec) - } - - pub fn initial_disabled_packs( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/List;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getInitialDisabledPacks", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&jni, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - jni.get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), - ); + let (valid, name) = env.validate_name(&obj, "org/bukkit/TreeSpecies")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a TreeSpeciesStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - Ok(new_vec) } - /// Get the DataPack Manager. - pub fn data_pack_manager( +} + +impl<'mc> TreeSpeciesStruct<'mc> { + pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/packs/DataPackManager;"); - let cls = jni.find_class("org/bukkit/Bukkit"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/TreeSpecies;"); + let cls = jni.find_class("org/bukkit/TreeSpecies"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getDataPackManager", sig.as_str(), vec![]); + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::packs::DataPackManager::from_raw(&jni, obj) + crate::TreeSpecies::from_raw(&jni, obj) } - /// Gets the resource pack configured to be sent to clients by the server. - pub fn server_resource_pack( + #[deprecated] + /// Gets the associated data value representing this species + pub fn data(&self) -> Result> { + let sig = String::from("()B"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.b()?) + } + #[deprecated] + /// Gets the TreeSpecies with the given data value + pub fn get_by_data( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/packs/ResourcePack;"); - let cls = jni.find_class("org/bukkit/Bukkit"); + data: i8, + ) -> Result>, Box> { + let sig = String::from("(B)Lorg/bukkit/TreeSpecies;"); + let val_1 = jni::objects::JValueGen::Byte(data); + let cls = jni.find_class("org/bukkit/TreeSpecies"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getServerResourcePack", sig.as_str(), vec![]); + let res = jni.call_static_method( + cls, + "getByData", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = jni.translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } let obj = res.l()?; - Ok(Some(crate::packs::ResourcePack::from_raw(&jni, obj)?)) + Ok(Some(crate::TreeSpecies::from_raw(&jni, obj)?)) } - /// Get the ServerTick Manager. - pub fn server_tick_manager( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/ServerTickManager;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getServerTickManager", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::ServerTickManager::from_raw(&jni, obj) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Gets the server resource pack uri, or empty string if not specified. - pub fn resource_pack( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getResourcePack", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(jni - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) +} +#[repr(C)] +pub struct StructureType<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for StructureType<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Gets the SHA-1 digest of the server resource pack, or empty string if - /// not specified. - pub fn resource_pack_hash( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getResourcePackHash", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(jni - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Gets the custom prompt message to be shown when the server resource - /// pack is required, or empty string if not specified. - pub fn resource_pack_prompt( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { +} +impl<'mc> JNIInstantiatable<'mc> for StructureType<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate StructureType from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/StructureType")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a StructureType object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> StructureType<'mc> { + /// Get the name of this structure. This is case-sensitive when used in + /// commands. + pub fn name(&self) -> Result> { let sig = String::from("()Ljava/lang/String;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getResourcePackPrompt", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(jni + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? .to_string_lossy() .to_string()) } - /// Gets whether the server resource pack is enforced. - pub fn is_resource_pack_required( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()Z"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "isResourcePackRequired", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(res.z()?) + /// Get the {@link org.bukkit.map.MapCursor.Type} that this structure can use on maps. If + /// this is null, this structure will not appear on explorer maps. + pub fn map_icon( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/map/MapCursor/Type;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMapIcon", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::map::MapCursorType::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets whether this server has a whitelist or not. - pub fn has_whitelist( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, + + pub fn equals( + &self, + other: jni::objects::JObject<'mc>, ) -> Result> { - let sig = String::from("()Z"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "hasWhitelist", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(res.z()?) - } - /// Sets if the server is whitelisted. - pub fn set_whitelist( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - value: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(value.into()); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "setWhitelist", + let sig = String::from("(Ljava/lang/Object;)Z"); + let val_1 = jni::objects::JValueGen::Object(other); + let res = self.jni_ref().call_method( + &self.jni_object(), + "equals", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - jni.translate_error(res)?; - Ok(()) - } - /// Gets whether the server whitelist is enforced. - /// If the whitelist is enforced, non-whitelisted players will be - /// disconnected when the server whitelist is reloaded. - pub fn is_whitelist_enforced( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()Z"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "isWhitelistEnforced", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; + let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets if the server whitelist is enforced. - /// If the whitelist is enforced, non-whitelisted players will be - /// disconnected when the server whitelist is reloaded. - pub fn set_whitelist_enforced( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - value: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(value.into()); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "setWhitelistEnforced", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - jni.translate_error(res)?; - Ok(()) - } - /// Gets a list of whitelisted players. - pub fn whitelisted_players( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getWhitelistedPlayers", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - blackboxmc_java::util::JavaSet::from_raw(&jni, obj) - } - /// Reloads the whitelist from disk. - pub fn reload_whitelist( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result<(), Box> { - let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "reloadWhitelist", sig.as_str(), vec![]); - jni.translate_error(res)?; - Ok(()) - } - /// Broadcast a message to all players. - /// - /// This is the same as calling {@link #broadcast(java.lang.String, - /// java.lang.String)} to {@link Server#BROADCAST_CHANNEL_USERS} - pub fn broadcast_message( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - message: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)I"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(message.into())?, - )); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "broadcastMessage", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; + + pub fn hash_code(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Gets the name of the update folder. The update folder is used to safely - /// update plugins at the right moment on a plugin load. - /// - /// The update folder name is relative to the plugins folder. - pub fn update_folder( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { + + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { let sig = String::from("()Ljava/lang/String;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getUpdateFolder", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(jni + let res = self + .jni_ref() + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? .to_string_lossy() .to_string()) } - /// Gets the value of the connection throttle setting. - pub fn connection_throttle( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()J"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getConnectionThrottle", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(res.j()?) - } - #[deprecated] - /// Gets default ticks per animal spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn monsters every tick.
    • A value of 400 will mean the server will attempt to spawn monsters every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, animal spawning will be disabled. We recommend using spawn-animals to control this instead.Minecraft default: 400. - pub fn ticks_per_animal_spawns( + /// Get all registered {@link StructureType}s. + pub fn structure_types( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()I"); - let cls = jni.find_class("org/bukkit/Bukkit"); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Map;"); + let cls = jni.find_class("org/bukkit/StructureType"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getTicksPerAnimalSpawns", sig.as_str(), vec![]); + let res = jni.call_static_method(cls, "getStructureTypes", sig.as_str(), vec![]); let res = jni.translate_error(res)?; - Ok(res.i()?) + let obj = res.l()?; + blackboxmc_java::util::JavaMap::from_raw(&jni, obj) } - #[deprecated] - /// Gets the default ticks per monster spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn monsters every tick.
    • A value of 400 will mean the server will attempt to spawn monsters every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, monsters spawning will be disabled. We recommend using spawn-monsters to control this instead.Minecraft default: 1. - pub fn ticks_per_monster_spawns( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()I"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getTicksPerMonsterSpawns", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(res.i()?) + + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - /// Gets the default ticks per water mob spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn water mobs every tick.
    • A value of 400 will mean the server will attempt to spawn water mobs every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, water mobs spawning will be disabled.Minecraft default: 1. - pub fn ticks_per_water_spawns( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()I"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getTicksPerWaterSpawns", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(res.i()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - #[deprecated] - /// Gets the default ticks per ambient mob spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn ambient mobs every tick.
    • A value of 400 will mean the server will attempt to spawn ambient mobs every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, ambient mobs spawning will be disabled.Minecraft default: 1. - pub fn ticks_per_ambient_spawns( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()I"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getTicksPerAmbientSpawns", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(res.i()?) +} + +impl<'mc> std::string::ToString for StructureType<'mc> { + fn to_string(&self) -> String { + match &self.internal_to_string() { + Ok(a) => a.clone(), + Err(err) => format!("Error calling StructureType.toString: {}", err), + } } - #[deprecated] - /// Gets the default ticks per water ambient mob spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn water ambient mobs every tick.
    • A value of 400 will mean the server will attempt to spawn water ambient mobs every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, ambient mobs spawning will be disabled.Minecraft default: 1. - pub fn ticks_per_water_ambient_spawns( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()I"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = - jni.call_static_method(cls, "getTicksPerWaterAmbientSpawns", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(res.i()?) - } - #[deprecated] - /// Gets the default ticks per water underground creature spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn water underground creature every tick.
    • A value of 400 will mean the server will attempt to spawn water underground creature every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, water underground creature spawning will be disabled.Minecraft default: 1. - pub fn ticks_per_water_underground_creature_spawns( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()I"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getTicksPerWaterUndergroundCreatureSpawns", - sig.as_str(), - vec![], - ); - let res = jni.translate_error(res)?; - Ok(res.i()?) - } - /// Gets the default ticks per {@link SpawnCategory} spawns value. - /// - /// Example Usage: - ///
      - ///
    • A value of 1 will mean the server will attempt to spawn {@link SpawnCategory} mobs - /// every tick. - ///
    • A value of 400 will mean the server will attempt to spawn {@link SpawnCategory} mobs - /// every 400th tick. - ///
    • A value below 0 will be reset back to Minecraft's default. - ///
    - /// - /// Note: If set to 0, {@link SpawnCategory} mobs spawning will be disabled. - /// - /// Minecraft default: 1. - /// - /// Note: the {@link SpawnCategory#MISC} are not consider. - pub fn get_ticks_per_spawns( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - spawn_category: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/SpawnCategory;)I"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(spawn_category.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getTicksPerSpawns", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - Ok(res.i()?) +} + +impl<'mc> Into> for StructureType<'mc> { + fn into(self) -> crate::Keyed<'mc> { + crate::Keyed::from_raw(&self.jni_ref(), self.1) + .expect("Error converting StructureType into crate::Keyed") } - /// Gets the player with the given UUID. - pub fn get_player( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - id: impl Into>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(id.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Lorg/bukkit/entity/Player;"; - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getPlayer", sig.as_str(), args); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); +} +pub enum Statistic<'mc> { + DamageDealt { inner: StatisticStruct<'mc> }, + DamageTaken { inner: StatisticStruct<'mc> }, + Deaths { inner: StatisticStruct<'mc> }, + MobKills { inner: StatisticStruct<'mc> }, + PlayerKills { inner: StatisticStruct<'mc> }, + FishCaught { inner: StatisticStruct<'mc> }, + AnimalsBred { inner: StatisticStruct<'mc> }, + LeaveGame { inner: StatisticStruct<'mc> }, + Jump { inner: StatisticStruct<'mc> }, + DropCount { inner: StatisticStruct<'mc> }, + Drop { inner: StatisticStruct<'mc> }, + Pickup { inner: StatisticStruct<'mc> }, + PlayOneMinute { inner: StatisticStruct<'mc> }, + TotalWorldTime { inner: StatisticStruct<'mc> }, + WalkOneCm { inner: StatisticStruct<'mc> }, + WalkOnWaterOneCm { inner: StatisticStruct<'mc> }, + FallOneCm { inner: StatisticStruct<'mc> }, + SneakTime { inner: StatisticStruct<'mc> }, + ClimbOneCm { inner: StatisticStruct<'mc> }, + FlyOneCm { inner: StatisticStruct<'mc> }, + WalkUnderWaterOneCm { inner: StatisticStruct<'mc> }, + MinecartOneCm { inner: StatisticStruct<'mc> }, + BoatOneCm { inner: StatisticStruct<'mc> }, + PigOneCm { inner: StatisticStruct<'mc> }, + HorseOneCm { inner: StatisticStruct<'mc> }, + SprintOneCm { inner: StatisticStruct<'mc> }, + CrouchOneCm { inner: StatisticStruct<'mc> }, + AviateOneCm { inner: StatisticStruct<'mc> }, + MineBlock { inner: StatisticStruct<'mc> }, + UseItem { inner: StatisticStruct<'mc> }, + BreakItem { inner: StatisticStruct<'mc> }, + CraftItem { inner: StatisticStruct<'mc> }, + KillEntity { inner: StatisticStruct<'mc> }, + EntityKilledBy { inner: StatisticStruct<'mc> }, + TimeSinceDeath { inner: StatisticStruct<'mc> }, + TalkedToVillager { inner: StatisticStruct<'mc> }, + TradedWithVillager { inner: StatisticStruct<'mc> }, + CakeSlicesEaten { inner: StatisticStruct<'mc> }, + CauldronFilled { inner: StatisticStruct<'mc> }, + CauldronUsed { inner: StatisticStruct<'mc> }, + ArmorCleaned { inner: StatisticStruct<'mc> }, + BannerCleaned { inner: StatisticStruct<'mc> }, + BrewingstandInteraction { inner: StatisticStruct<'mc> }, + BeaconInteraction { inner: StatisticStruct<'mc> }, + DropperInspected { inner: StatisticStruct<'mc> }, + HopperInspected { inner: StatisticStruct<'mc> }, + DispenserInspected { inner: StatisticStruct<'mc> }, + NoteblockPlayed { inner: StatisticStruct<'mc> }, + NoteblockTuned { inner: StatisticStruct<'mc> }, + FlowerPotted { inner: StatisticStruct<'mc> }, + TrappedChestTriggered { inner: StatisticStruct<'mc> }, + EnderchestOpened { inner: StatisticStruct<'mc> }, + ItemEnchanted { inner: StatisticStruct<'mc> }, + RecordPlayed { inner: StatisticStruct<'mc> }, + FurnaceInteraction { inner: StatisticStruct<'mc> }, + CraftingTableInteraction { inner: StatisticStruct<'mc> }, + ChestOpened { inner: StatisticStruct<'mc> }, + SleepInBed { inner: StatisticStruct<'mc> }, + ShulkerBoxOpened { inner: StatisticStruct<'mc> }, + TimeSinceRest { inner: StatisticStruct<'mc> }, + SwimOneCm { inner: StatisticStruct<'mc> }, + DamageDealtAbsorbed { inner: StatisticStruct<'mc> }, + DamageDealtResisted { inner: StatisticStruct<'mc> }, + DamageBlockedByShield { inner: StatisticStruct<'mc> }, + DamageAbsorbed { inner: StatisticStruct<'mc> }, + DamageResisted { inner: StatisticStruct<'mc> }, + CleanShulkerBox { inner: StatisticStruct<'mc> }, + OpenBarrel { inner: StatisticStruct<'mc> }, + InteractWithBlastFurnace { inner: StatisticStruct<'mc> }, + InteractWithSmoker { inner: StatisticStruct<'mc> }, + InteractWithLectern { inner: StatisticStruct<'mc> }, + InteractWithCampfire { inner: StatisticStruct<'mc> }, + InteractWithCartographyTable { inner: StatisticStruct<'mc> }, + InteractWithLoom { inner: StatisticStruct<'mc> }, + InteractWithStonecutter { inner: StatisticStruct<'mc> }, + BellRing { inner: StatisticStruct<'mc> }, + RaidTrigger { inner: StatisticStruct<'mc> }, + RaidWin { inner: StatisticStruct<'mc> }, + InteractWithAnvil { inner: StatisticStruct<'mc> }, + InteractWithGrindstone { inner: StatisticStruct<'mc> }, + TargetHit { inner: StatisticStruct<'mc> }, + InteractWithSmithingTable { inner: StatisticStruct<'mc> }, + StriderOneCm { inner: StatisticStruct<'mc> }, +} +impl<'mc> std::fmt::Display for Statistic<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Statistic::DamageDealt { .. } => f.write_str("DAMAGE_DEALT"), + Statistic::DamageTaken { .. } => f.write_str("DAMAGE_TAKEN"), + Statistic::Deaths { .. } => f.write_str("DEATHS"), + Statistic::MobKills { .. } => f.write_str("MOB_KILLS"), + Statistic::PlayerKills { .. } => f.write_str("PLAYER_KILLS"), + Statistic::FishCaught { .. } => f.write_str("FISH_CAUGHT"), + Statistic::AnimalsBred { .. } => f.write_str("ANIMALS_BRED"), + Statistic::LeaveGame { .. } => f.write_str("LEAVE_GAME"), + Statistic::Jump { .. } => f.write_str("JUMP"), + Statistic::DropCount { .. } => f.write_str("DROP_COUNT"), + Statistic::Drop { .. } => f.write_str("DROP"), + Statistic::Pickup { .. } => f.write_str("PICKUP"), + Statistic::PlayOneMinute { .. } => f.write_str("PLAY_ONE_MINUTE"), + Statistic::TotalWorldTime { .. } => f.write_str("TOTAL_WORLD_TIME"), + Statistic::WalkOneCm { .. } => f.write_str("WALK_ONE_CM"), + Statistic::WalkOnWaterOneCm { .. } => f.write_str("WALK_ON_WATER_ONE_CM"), + Statistic::FallOneCm { .. } => f.write_str("FALL_ONE_CM"), + Statistic::SneakTime { .. } => f.write_str("SNEAK_TIME"), + Statistic::ClimbOneCm { .. } => f.write_str("CLIMB_ONE_CM"), + Statistic::FlyOneCm { .. } => f.write_str("FLY_ONE_CM"), + Statistic::WalkUnderWaterOneCm { .. } => f.write_str("WALK_UNDER_WATER_ONE_CM"), + Statistic::MinecartOneCm { .. } => f.write_str("MINECART_ONE_CM"), + Statistic::BoatOneCm { .. } => f.write_str("BOAT_ONE_CM"), + Statistic::PigOneCm { .. } => f.write_str("PIG_ONE_CM"), + Statistic::HorseOneCm { .. } => f.write_str("HORSE_ONE_CM"), + Statistic::SprintOneCm { .. } => f.write_str("SPRINT_ONE_CM"), + Statistic::CrouchOneCm { .. } => f.write_str("CROUCH_ONE_CM"), + Statistic::AviateOneCm { .. } => f.write_str("AVIATE_ONE_CM"), + Statistic::MineBlock { .. } => f.write_str("MINE_BLOCK"), + Statistic::UseItem { .. } => f.write_str("USE_ITEM"), + Statistic::BreakItem { .. } => f.write_str("BREAK_ITEM"), + Statistic::CraftItem { .. } => f.write_str("CRAFT_ITEM"), + Statistic::KillEntity { .. } => f.write_str("KILL_ENTITY"), + Statistic::EntityKilledBy { .. } => f.write_str("ENTITY_KILLED_BY"), + Statistic::TimeSinceDeath { .. } => f.write_str("TIME_SINCE_DEATH"), + Statistic::TalkedToVillager { .. } => f.write_str("TALKED_TO_VILLAGER"), + Statistic::TradedWithVillager { .. } => f.write_str("TRADED_WITH_VILLAGER"), + Statistic::CakeSlicesEaten { .. } => f.write_str("CAKE_SLICES_EATEN"), + Statistic::CauldronFilled { .. } => f.write_str("CAULDRON_FILLED"), + Statistic::CauldronUsed { .. } => f.write_str("CAULDRON_USED"), + Statistic::ArmorCleaned { .. } => f.write_str("ARMOR_CLEANED"), + Statistic::BannerCleaned { .. } => f.write_str("BANNER_CLEANED"), + Statistic::BrewingstandInteraction { .. } => f.write_str("BREWINGSTAND_INTERACTION"), + Statistic::BeaconInteraction { .. } => f.write_str("BEACON_INTERACTION"), + Statistic::DropperInspected { .. } => f.write_str("DROPPER_INSPECTED"), + Statistic::HopperInspected { .. } => f.write_str("HOPPER_INSPECTED"), + Statistic::DispenserInspected { .. } => f.write_str("DISPENSER_INSPECTED"), + Statistic::NoteblockPlayed { .. } => f.write_str("NOTEBLOCK_PLAYED"), + Statistic::NoteblockTuned { .. } => f.write_str("NOTEBLOCK_TUNED"), + Statistic::FlowerPotted { .. } => f.write_str("FLOWER_POTTED"), + Statistic::TrappedChestTriggered { .. } => f.write_str("TRAPPED_CHEST_TRIGGERED"), + Statistic::EnderchestOpened { .. } => f.write_str("ENDERCHEST_OPENED"), + Statistic::ItemEnchanted { .. } => f.write_str("ITEM_ENCHANTED"), + Statistic::RecordPlayed { .. } => f.write_str("RECORD_PLAYED"), + Statistic::FurnaceInteraction { .. } => f.write_str("FURNACE_INTERACTION"), + Statistic::CraftingTableInteraction { .. } => f.write_str("CRAFTING_TABLE_INTERACTION"), + Statistic::ChestOpened { .. } => f.write_str("CHEST_OPENED"), + Statistic::SleepInBed { .. } => f.write_str("SLEEP_IN_BED"), + Statistic::ShulkerBoxOpened { .. } => f.write_str("SHULKER_BOX_OPENED"), + Statistic::TimeSinceRest { .. } => f.write_str("TIME_SINCE_REST"), + Statistic::SwimOneCm { .. } => f.write_str("SWIM_ONE_CM"), + Statistic::DamageDealtAbsorbed { .. } => f.write_str("DAMAGE_DEALT_ABSORBED"), + Statistic::DamageDealtResisted { .. } => f.write_str("DAMAGE_DEALT_RESISTED"), + Statistic::DamageBlockedByShield { .. } => f.write_str("DAMAGE_BLOCKED_BY_SHIELD"), + Statistic::DamageAbsorbed { .. } => f.write_str("DAMAGE_ABSORBED"), + Statistic::DamageResisted { .. } => f.write_str("DAMAGE_RESISTED"), + Statistic::CleanShulkerBox { .. } => f.write_str("CLEAN_SHULKER_BOX"), + Statistic::OpenBarrel { .. } => f.write_str("OPEN_BARREL"), + Statistic::InteractWithBlastFurnace { .. } => { + f.write_str("INTERACT_WITH_BLAST_FURNACE") + } + Statistic::InteractWithSmoker { .. } => f.write_str("INTERACT_WITH_SMOKER"), + Statistic::InteractWithLectern { .. } => f.write_str("INTERACT_WITH_LECTERN"), + Statistic::InteractWithCampfire { .. } => f.write_str("INTERACT_WITH_CAMPFIRE"), + Statistic::InteractWithCartographyTable { .. } => { + f.write_str("INTERACT_WITH_CARTOGRAPHY_TABLE") + } + Statistic::InteractWithLoom { .. } => f.write_str("INTERACT_WITH_LOOM"), + Statistic::InteractWithStonecutter { .. } => f.write_str("INTERACT_WITH_STONECUTTER"), + Statistic::BellRing { .. } => f.write_str("BELL_RING"), + Statistic::RaidTrigger { .. } => f.write_str("RAID_TRIGGER"), + Statistic::RaidWin { .. } => f.write_str("RAID_WIN"), + Statistic::InteractWithAnvil { .. } => f.write_str("INTERACT_WITH_ANVIL"), + Statistic::InteractWithGrindstone { .. } => f.write_str("INTERACT_WITH_GRINDSTONE"), + Statistic::TargetHit { .. } => f.write_str("TARGET_HIT"), + Statistic::InteractWithSmithingTable { .. } => { + f.write_str("INTERACT_WITH_SMITHING_TABLE") + } + Statistic::StriderOneCm { .. } => f.write_str("STRIDER_ONE_CM"), } - let obj = res.l()?; - Ok(Some(crate::entity::Player::from_raw(&jni, obj)?)) } - /// Gets the player with the exact given name, case insensitive. - pub fn get_player_exact( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - name: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/entity/Player;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(name.into())?, - )); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getPlayerExact", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); +} +impl<'mc> std::ops::Deref for Statistic<'mc> { + type Target = StatisticStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + Statistic::DamageDealt { inner } => inner, + Statistic::DamageTaken { inner } => inner, + Statistic::Deaths { inner } => inner, + Statistic::MobKills { inner } => inner, + Statistic::PlayerKills { inner } => inner, + Statistic::FishCaught { inner } => inner, + Statistic::AnimalsBred { inner } => inner, + Statistic::LeaveGame { inner } => inner, + Statistic::Jump { inner } => inner, + Statistic::DropCount { inner } => inner, + Statistic::Drop { inner } => inner, + Statistic::Pickup { inner } => inner, + Statistic::PlayOneMinute { inner } => inner, + Statistic::TotalWorldTime { inner } => inner, + Statistic::WalkOneCm { inner } => inner, + Statistic::WalkOnWaterOneCm { inner } => inner, + Statistic::FallOneCm { inner } => inner, + Statistic::SneakTime { inner } => inner, + Statistic::ClimbOneCm { inner } => inner, + Statistic::FlyOneCm { inner } => inner, + Statistic::WalkUnderWaterOneCm { inner } => inner, + Statistic::MinecartOneCm { inner } => inner, + Statistic::BoatOneCm { inner } => inner, + Statistic::PigOneCm { inner } => inner, + Statistic::HorseOneCm { inner } => inner, + Statistic::SprintOneCm { inner } => inner, + Statistic::CrouchOneCm { inner } => inner, + Statistic::AviateOneCm { inner } => inner, + Statistic::MineBlock { inner } => inner, + Statistic::UseItem { inner } => inner, + Statistic::BreakItem { inner } => inner, + Statistic::CraftItem { inner } => inner, + Statistic::KillEntity { inner } => inner, + Statistic::EntityKilledBy { inner } => inner, + Statistic::TimeSinceDeath { inner } => inner, + Statistic::TalkedToVillager { inner } => inner, + Statistic::TradedWithVillager { inner } => inner, + Statistic::CakeSlicesEaten { inner } => inner, + Statistic::CauldronFilled { inner } => inner, + Statistic::CauldronUsed { inner } => inner, + Statistic::ArmorCleaned { inner } => inner, + Statistic::BannerCleaned { inner } => inner, + Statistic::BrewingstandInteraction { inner } => inner, + Statistic::BeaconInteraction { inner } => inner, + Statistic::DropperInspected { inner } => inner, + Statistic::HopperInspected { inner } => inner, + Statistic::DispenserInspected { inner } => inner, + Statistic::NoteblockPlayed { inner } => inner, + Statistic::NoteblockTuned { inner } => inner, + Statistic::FlowerPotted { inner } => inner, + Statistic::TrappedChestTriggered { inner } => inner, + Statistic::EnderchestOpened { inner } => inner, + Statistic::ItemEnchanted { inner } => inner, + Statistic::RecordPlayed { inner } => inner, + Statistic::FurnaceInteraction { inner } => inner, + Statistic::CraftingTableInteraction { inner } => inner, + Statistic::ChestOpened { inner } => inner, + Statistic::SleepInBed { inner } => inner, + Statistic::ShulkerBoxOpened { inner } => inner, + Statistic::TimeSinceRest { inner } => inner, + Statistic::SwimOneCm { inner } => inner, + Statistic::DamageDealtAbsorbed { inner } => inner, + Statistic::DamageDealtResisted { inner } => inner, + Statistic::DamageBlockedByShield { inner } => inner, + Statistic::DamageAbsorbed { inner } => inner, + Statistic::DamageResisted { inner } => inner, + Statistic::CleanShulkerBox { inner } => inner, + Statistic::OpenBarrel { inner } => inner, + Statistic::InteractWithBlastFurnace { inner } => inner, + Statistic::InteractWithSmoker { inner } => inner, + Statistic::InteractWithLectern { inner } => inner, + Statistic::InteractWithCampfire { inner } => inner, + Statistic::InteractWithCartographyTable { inner } => inner, + Statistic::InteractWithLoom { inner } => inner, + Statistic::InteractWithStonecutter { inner } => inner, + Statistic::BellRing { inner } => inner, + Statistic::RaidTrigger { inner } => inner, + Statistic::RaidWin { inner } => inner, + Statistic::InteractWithAnvil { inner } => inner, + Statistic::InteractWithGrindstone { inner } => inner, + Statistic::TargetHit { inner } => inner, + Statistic::InteractWithSmithingTable { inner } => inner, + Statistic::StriderOneCm { inner } => inner, } - let obj = res.l()?; - Ok(Some(crate::entity::Player::from_raw(&jni, obj)?)) } - /// Attempts to match any players with the given name, and returns a list - /// of all possibly matches. - /// - /// This list is not sorted in any particular order. If an exact match is - /// found, the returned list will only contain a single result. - pub fn match_player( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - name: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(name.into())?, - )); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( +} + +impl<'mc> Statistic<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/Statistic"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( cls, - "matchPlayer", - sig.as_str(), + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/Statistic;", vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&jni, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Player::from_raw(&jni, obj)?); - } - Ok(new_vec) - } - /// Gets the plugin manager for interfacing with plugins. - pub fn plugin_manager( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/plugin/PluginManager;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getPluginManager", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::plugin::PluginManager::from_raw(&jni, obj) - } - /// Gets the scheduler for managing scheduled events. - pub fn scheduler( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/scheduler/BukkitScheduler;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getScheduler", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::scheduler::BukkitScheduler::from_raw(&jni, obj) - } - /// Gets a services manager. - pub fn services_manager( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/plugin/ServicesManager;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getServicesManager", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; + let res = env.translate_error(res)?; let obj = res.l()?; - crate::plugin::ServicesManager::from_raw(&jni, obj) + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "DAMAGE_DEALT" => Ok(Statistic::DamageDealt { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "DAMAGE_TAKEN" => Ok(Statistic::DamageTaken { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "DEATHS" => Ok(Statistic::Deaths { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "MOB_KILLS" => Ok(Statistic::MobKills { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "PLAYER_KILLS" => Ok(Statistic::PlayerKills { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "FISH_CAUGHT" => Ok(Statistic::FishCaught { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "ANIMALS_BRED" => Ok(Statistic::AnimalsBred { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "LEAVE_GAME" => Ok(Statistic::LeaveGame { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "JUMP" => Ok(Statistic::Jump { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "DROP_COUNT" => Ok(Statistic::DropCount { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "DROP" => Ok(Statistic::Drop { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "PICKUP" => Ok(Statistic::Pickup { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "PLAY_ONE_MINUTE" => Ok(Statistic::PlayOneMinute { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "TOTAL_WORLD_TIME" => Ok(Statistic::TotalWorldTime { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "WALK_ONE_CM" => Ok(Statistic::WalkOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "WALK_ON_WATER_ONE_CM" => Ok(Statistic::WalkOnWaterOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "FALL_ONE_CM" => Ok(Statistic::FallOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "SNEAK_TIME" => Ok(Statistic::SneakTime { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "CLIMB_ONE_CM" => Ok(Statistic::ClimbOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "FLY_ONE_CM" => Ok(Statistic::FlyOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "WALK_UNDER_WATER_ONE_CM" => Ok(Statistic::WalkUnderWaterOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "MINECART_ONE_CM" => Ok(Statistic::MinecartOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "BOAT_ONE_CM" => Ok(Statistic::BoatOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "PIG_ONE_CM" => Ok(Statistic::PigOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "HORSE_ONE_CM" => Ok(Statistic::HorseOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "SPRINT_ONE_CM" => Ok(Statistic::SprintOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "CROUCH_ONE_CM" => Ok(Statistic::CrouchOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "AVIATE_ONE_CM" => Ok(Statistic::AviateOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "MINE_BLOCK" => Ok(Statistic::MineBlock { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "USE_ITEM" => Ok(Statistic::UseItem { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "BREAK_ITEM" => Ok(Statistic::BreakItem { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "CRAFT_ITEM" => Ok(Statistic::CraftItem { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "KILL_ENTITY" => Ok(Statistic::KillEntity { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "ENTITY_KILLED_BY" => Ok(Statistic::EntityKilledBy { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "TIME_SINCE_DEATH" => Ok(Statistic::TimeSinceDeath { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "TALKED_TO_VILLAGER" => Ok(Statistic::TalkedToVillager { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "TRADED_WITH_VILLAGER" => Ok(Statistic::TradedWithVillager { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "CAKE_SLICES_EATEN" => Ok(Statistic::CakeSlicesEaten { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "CAULDRON_FILLED" => Ok(Statistic::CauldronFilled { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "CAULDRON_USED" => Ok(Statistic::CauldronUsed { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "ARMOR_CLEANED" => Ok(Statistic::ArmorCleaned { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "BANNER_CLEANED" => Ok(Statistic::BannerCleaned { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "BREWINGSTAND_INTERACTION" => Ok(Statistic::BrewingstandInteraction { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "BEACON_INTERACTION" => Ok(Statistic::BeaconInteraction { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "DROPPER_INSPECTED" => Ok(Statistic::DropperInspected { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "HOPPER_INSPECTED" => Ok(Statistic::HopperInspected { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "DISPENSER_INSPECTED" => Ok(Statistic::DispenserInspected { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "NOTEBLOCK_PLAYED" => Ok(Statistic::NoteblockPlayed { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "NOTEBLOCK_TUNED" => Ok(Statistic::NoteblockTuned { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "FLOWER_POTTED" => Ok(Statistic::FlowerPotted { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "TRAPPED_CHEST_TRIGGERED" => Ok(Statistic::TrappedChestTriggered { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "ENDERCHEST_OPENED" => Ok(Statistic::EnderchestOpened { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "ITEM_ENCHANTED" => Ok(Statistic::ItemEnchanted { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "RECORD_PLAYED" => Ok(Statistic::RecordPlayed { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "FURNACE_INTERACTION" => Ok(Statistic::FurnaceInteraction { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "CRAFTING_TABLE_INTERACTION" => Ok(Statistic::CraftingTableInteraction { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "CHEST_OPENED" => Ok(Statistic::ChestOpened { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "SLEEP_IN_BED" => Ok(Statistic::SleepInBed { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "SHULKER_BOX_OPENED" => Ok(Statistic::ShulkerBoxOpened { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "TIME_SINCE_REST" => Ok(Statistic::TimeSinceRest { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "SWIM_ONE_CM" => Ok(Statistic::SwimOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "DAMAGE_DEALT_ABSORBED" => Ok(Statistic::DamageDealtAbsorbed { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "DAMAGE_DEALT_RESISTED" => Ok(Statistic::DamageDealtResisted { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "DAMAGE_BLOCKED_BY_SHIELD" => Ok(Statistic::DamageBlockedByShield { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "DAMAGE_ABSORBED" => Ok(Statistic::DamageAbsorbed { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "DAMAGE_RESISTED" => Ok(Statistic::DamageResisted { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "CLEAN_SHULKER_BOX" => Ok(Statistic::CleanShulkerBox { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "OPEN_BARREL" => Ok(Statistic::OpenBarrel { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "INTERACT_WITH_BLAST_FURNACE" => Ok(Statistic::InteractWithBlastFurnace { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "INTERACT_WITH_SMOKER" => Ok(Statistic::InteractWithSmoker { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "INTERACT_WITH_LECTERN" => Ok(Statistic::InteractWithLectern { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "INTERACT_WITH_CAMPFIRE" => Ok(Statistic::InteractWithCampfire { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "INTERACT_WITH_CARTOGRAPHY_TABLE" => Ok(Statistic::InteractWithCartographyTable { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "INTERACT_WITH_LOOM" => Ok(Statistic::InteractWithLoom { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "INTERACT_WITH_STONECUTTER" => Ok(Statistic::InteractWithStonecutter { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "BELL_RING" => Ok(Statistic::BellRing { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "RAID_TRIGGER" => Ok(Statistic::RaidTrigger { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "RAID_WIN" => Ok(Statistic::RaidWin { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "INTERACT_WITH_ANVIL" => Ok(Statistic::InteractWithAnvil { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "INTERACT_WITH_GRINDSTONE" => Ok(Statistic::InteractWithGrindstone { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "TARGET_HIT" => Ok(Statistic::TargetHit { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "INTERACT_WITH_SMITHING_TABLE" => Ok(Statistic::InteractWithSmithingTable { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "STRIDER_ONE_CM" => Ok(Statistic::StriderOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } - /// Gets a list of all worlds on this server. - pub fn worlds( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getWorlds", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&jni, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::World::from_raw(&jni, obj)?); +} + +#[repr(C)] +pub struct StatisticStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Statistic<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::DamageDealt { inner } => inner.0.clone(), + Self::DamageTaken { inner } => inner.0.clone(), + Self::Deaths { inner } => inner.0.clone(), + Self::MobKills { inner } => inner.0.clone(), + Self::PlayerKills { inner } => inner.0.clone(), + Self::FishCaught { inner } => inner.0.clone(), + Self::AnimalsBred { inner } => inner.0.clone(), + Self::LeaveGame { inner } => inner.0.clone(), + Self::Jump { inner } => inner.0.clone(), + Self::DropCount { inner } => inner.0.clone(), + Self::Drop { inner } => inner.0.clone(), + Self::Pickup { inner } => inner.0.clone(), + Self::PlayOneMinute { inner } => inner.0.clone(), + Self::TotalWorldTime { inner } => inner.0.clone(), + Self::WalkOneCm { inner } => inner.0.clone(), + Self::WalkOnWaterOneCm { inner } => inner.0.clone(), + Self::FallOneCm { inner } => inner.0.clone(), + Self::SneakTime { inner } => inner.0.clone(), + Self::ClimbOneCm { inner } => inner.0.clone(), + Self::FlyOneCm { inner } => inner.0.clone(), + Self::WalkUnderWaterOneCm { inner } => inner.0.clone(), + Self::MinecartOneCm { inner } => inner.0.clone(), + Self::BoatOneCm { inner } => inner.0.clone(), + Self::PigOneCm { inner } => inner.0.clone(), + Self::HorseOneCm { inner } => inner.0.clone(), + Self::SprintOneCm { inner } => inner.0.clone(), + Self::CrouchOneCm { inner } => inner.0.clone(), + Self::AviateOneCm { inner } => inner.0.clone(), + Self::MineBlock { inner } => inner.0.clone(), + Self::UseItem { inner } => inner.0.clone(), + Self::BreakItem { inner } => inner.0.clone(), + Self::CraftItem { inner } => inner.0.clone(), + Self::KillEntity { inner } => inner.0.clone(), + Self::EntityKilledBy { inner } => inner.0.clone(), + Self::TimeSinceDeath { inner } => inner.0.clone(), + Self::TalkedToVillager { inner } => inner.0.clone(), + Self::TradedWithVillager { inner } => inner.0.clone(), + Self::CakeSlicesEaten { inner } => inner.0.clone(), + Self::CauldronFilled { inner } => inner.0.clone(), + Self::CauldronUsed { inner } => inner.0.clone(), + Self::ArmorCleaned { inner } => inner.0.clone(), + Self::BannerCleaned { inner } => inner.0.clone(), + Self::BrewingstandInteraction { inner } => inner.0.clone(), + Self::BeaconInteraction { inner } => inner.0.clone(), + Self::DropperInspected { inner } => inner.0.clone(), + Self::HopperInspected { inner } => inner.0.clone(), + Self::DispenserInspected { inner } => inner.0.clone(), + Self::NoteblockPlayed { inner } => inner.0.clone(), + Self::NoteblockTuned { inner } => inner.0.clone(), + Self::FlowerPotted { inner } => inner.0.clone(), + Self::TrappedChestTriggered { inner } => inner.0.clone(), + Self::EnderchestOpened { inner } => inner.0.clone(), + Self::ItemEnchanted { inner } => inner.0.clone(), + Self::RecordPlayed { inner } => inner.0.clone(), + Self::FurnaceInteraction { inner } => inner.0.clone(), + Self::CraftingTableInteraction { inner } => inner.0.clone(), + Self::ChestOpened { inner } => inner.0.clone(), + Self::SleepInBed { inner } => inner.0.clone(), + Self::ShulkerBoxOpened { inner } => inner.0.clone(), + Self::TimeSinceRest { inner } => inner.0.clone(), + Self::SwimOneCm { inner } => inner.0.clone(), + Self::DamageDealtAbsorbed { inner } => inner.0.clone(), + Self::DamageDealtResisted { inner } => inner.0.clone(), + Self::DamageBlockedByShield { inner } => inner.0.clone(), + Self::DamageAbsorbed { inner } => inner.0.clone(), + Self::DamageResisted { inner } => inner.0.clone(), + Self::CleanShulkerBox { inner } => inner.0.clone(), + Self::OpenBarrel { inner } => inner.0.clone(), + Self::InteractWithBlastFurnace { inner } => inner.0.clone(), + Self::InteractWithSmoker { inner } => inner.0.clone(), + Self::InteractWithLectern { inner } => inner.0.clone(), + Self::InteractWithCampfire { inner } => inner.0.clone(), + Self::InteractWithCartographyTable { inner } => inner.0.clone(), + Self::InteractWithLoom { inner } => inner.0.clone(), + Self::InteractWithStonecutter { inner } => inner.0.clone(), + Self::BellRing { inner } => inner.0.clone(), + Self::RaidTrigger { inner } => inner.0.clone(), + Self::RaidWin { inner } => inner.0.clone(), + Self::InteractWithAnvil { inner } => inner.0.clone(), + Self::InteractWithGrindstone { inner } => inner.0.clone(), + Self::TargetHit { inner } => inner.0.clone(), + Self::InteractWithSmithingTable { inner } => inner.0.clone(), + Self::StriderOneCm { inner } => inner.0.clone(), } - Ok(new_vec) } - /// Creates or loads a world with the given name using the specified - /// options. - /// - /// If the world is already loaded, it will just return the equivalent of - /// getWorld(creator.name()). - pub fn create_world( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - creator: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/WorldCreator;)Lorg/bukkit/World;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(creator.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "createWorld", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::DamageDealt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DamageTaken { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Deaths { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::MobKills { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PlayerKills { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FishCaught { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AnimalsBred { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LeaveGame { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Jump { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DropCount { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Drop { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Pickup { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PlayOneMinute { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TotalWorldTime { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WalkOneCm { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WalkOnWaterOneCm { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FallOneCm { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SneakTime { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ClimbOneCm { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FlyOneCm { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::WalkUnderWaterOneCm { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MinecartOneCm { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BoatOneCm { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PigOneCm { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::HorseOneCm { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SprintOneCm { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrouchOneCm { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AviateOneCm { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MineBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::UseItem { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BreakItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CraftItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::KillEntity { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityKilledBy { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TimeSinceDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TalkedToVillager { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TradedWithVillager { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CakeSlicesEaten { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CauldronFilled { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CauldronUsed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ArmorCleaned { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BannerCleaned { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrewingstandInteraction { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BeaconInteraction { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DropperInspected { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HopperInspected { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DispenserInspected { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NoteblockPlayed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NoteblockTuned { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FlowerPotted { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrappedChestTriggered { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnderchestOpened { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemEnchanted { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RecordPlayed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FurnaceInteraction { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CraftingTableInteraction { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChestOpened { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SleepInBed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ShulkerBoxOpened { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TimeSinceRest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SwimOneCm { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DamageDealtAbsorbed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DamageDealtResisted { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DamageBlockedByShield { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DamageAbsorbed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DamageResisted { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CleanShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OpenBarrel { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::InteractWithBlastFurnace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::InteractWithSmoker { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::InteractWithLectern { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::InteractWithCampfire { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::InteractWithCartographyTable { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::InteractWithLoom { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::InteractWithStonecutter { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BellRing { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::RaidTrigger { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RaidWin { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::InteractWithAnvil { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::InteractWithGrindstone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TargetHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::InteractWithSmithingTable { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StriderOneCm { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, } - let obj = res.l()?; - Ok(Some(crate::World::from_raw(&jni, obj)?)) } - /// Unloads the given world. - pub fn unload_world( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - world: impl Into>, - save: bool, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/World;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(save.into()); - args.push(val_2); - sig += ")Z"; - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "unloadWorld", sig.as_str(), args); - let res = jni.translate_error(res)?; - Ok(res.z()?) +} +impl<'mc> JNIInstantiatable<'mc> for Statistic<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Statistic from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Statistic")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Statistic object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "DAMAGE_DEALT" => Ok(Statistic::DamageDealt { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "DAMAGE_TAKEN" => Ok(Statistic::DamageTaken { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "DEATHS" => Ok(Statistic::Deaths { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "MOB_KILLS" => Ok(Statistic::MobKills { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "PLAYER_KILLS" => Ok(Statistic::PlayerKills { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "FISH_CAUGHT" => Ok(Statistic::FishCaught { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "ANIMALS_BRED" => Ok(Statistic::AnimalsBred { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "LEAVE_GAME" => Ok(Statistic::LeaveGame { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "JUMP" => Ok(Statistic::Jump { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "DROP_COUNT" => Ok(Statistic::DropCount { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "DROP" => Ok(Statistic::Drop { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "PICKUP" => Ok(Statistic::Pickup { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "PLAY_ONE_MINUTE" => Ok(Statistic::PlayOneMinute { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "TOTAL_WORLD_TIME" => Ok(Statistic::TotalWorldTime { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "WALK_ONE_CM" => Ok(Statistic::WalkOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "WALK_ON_WATER_ONE_CM" => Ok(Statistic::WalkOnWaterOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "FALL_ONE_CM" => Ok(Statistic::FallOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "SNEAK_TIME" => Ok(Statistic::SneakTime { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "CLIMB_ONE_CM" => Ok(Statistic::ClimbOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "FLY_ONE_CM" => Ok(Statistic::FlyOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "WALK_UNDER_WATER_ONE_CM" => Ok(Statistic::WalkUnderWaterOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "MINECART_ONE_CM" => Ok(Statistic::MinecartOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "BOAT_ONE_CM" => Ok(Statistic::BoatOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "PIG_ONE_CM" => Ok(Statistic::PigOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "HORSE_ONE_CM" => Ok(Statistic::HorseOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "SPRINT_ONE_CM" => Ok(Statistic::SprintOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "CROUCH_ONE_CM" => Ok(Statistic::CrouchOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "AVIATE_ONE_CM" => Ok(Statistic::AviateOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "MINE_BLOCK" => Ok(Statistic::MineBlock { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "USE_ITEM" => Ok(Statistic::UseItem { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "BREAK_ITEM" => Ok(Statistic::BreakItem { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "CRAFT_ITEM" => Ok(Statistic::CraftItem { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "KILL_ENTITY" => Ok(Statistic::KillEntity { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "ENTITY_KILLED_BY" => Ok(Statistic::EntityKilledBy { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "TIME_SINCE_DEATH" => Ok(Statistic::TimeSinceDeath { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "TALKED_TO_VILLAGER" => Ok(Statistic::TalkedToVillager { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "TRADED_WITH_VILLAGER" => Ok(Statistic::TradedWithVillager { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "CAKE_SLICES_EATEN" => Ok(Statistic::CakeSlicesEaten { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "CAULDRON_FILLED" => Ok(Statistic::CauldronFilled { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "CAULDRON_USED" => Ok(Statistic::CauldronUsed { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "ARMOR_CLEANED" => Ok(Statistic::ArmorCleaned { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "BANNER_CLEANED" => Ok(Statistic::BannerCleaned { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "BREWINGSTAND_INTERACTION" => Ok(Statistic::BrewingstandInteraction { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "BEACON_INTERACTION" => Ok(Statistic::BeaconInteraction { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "DROPPER_INSPECTED" => Ok(Statistic::DropperInspected { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "HOPPER_INSPECTED" => Ok(Statistic::HopperInspected { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "DISPENSER_INSPECTED" => Ok(Statistic::DispenserInspected { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "NOTEBLOCK_PLAYED" => Ok(Statistic::NoteblockPlayed { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "NOTEBLOCK_TUNED" => Ok(Statistic::NoteblockTuned { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "FLOWER_POTTED" => Ok(Statistic::FlowerPotted { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "TRAPPED_CHEST_TRIGGERED" => Ok(Statistic::TrappedChestTriggered { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "ENDERCHEST_OPENED" => Ok(Statistic::EnderchestOpened { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "ITEM_ENCHANTED" => Ok(Statistic::ItemEnchanted { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "RECORD_PLAYED" => Ok(Statistic::RecordPlayed { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "FURNACE_INTERACTION" => Ok(Statistic::FurnaceInteraction { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "CRAFTING_TABLE_INTERACTION" => Ok(Statistic::CraftingTableInteraction { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "CHEST_OPENED" => Ok(Statistic::ChestOpened { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "SLEEP_IN_BED" => Ok(Statistic::SleepInBed { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "SHULKER_BOX_OPENED" => Ok(Statistic::ShulkerBoxOpened { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "TIME_SINCE_REST" => Ok(Statistic::TimeSinceRest { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "SWIM_ONE_CM" => Ok(Statistic::SwimOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "DAMAGE_DEALT_ABSORBED" => Ok(Statistic::DamageDealtAbsorbed { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "DAMAGE_DEALT_RESISTED" => Ok(Statistic::DamageDealtResisted { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "DAMAGE_BLOCKED_BY_SHIELD" => Ok(Statistic::DamageBlockedByShield { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "DAMAGE_ABSORBED" => Ok(Statistic::DamageAbsorbed { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "DAMAGE_RESISTED" => Ok(Statistic::DamageResisted { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "CLEAN_SHULKER_BOX" => Ok(Statistic::CleanShulkerBox { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "OPEN_BARREL" => Ok(Statistic::OpenBarrel { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "INTERACT_WITH_BLAST_FURNACE" => Ok(Statistic::InteractWithBlastFurnace { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "INTERACT_WITH_SMOKER" => Ok(Statistic::InteractWithSmoker { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "INTERACT_WITH_LECTERN" => Ok(Statistic::InteractWithLectern { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "INTERACT_WITH_CAMPFIRE" => Ok(Statistic::InteractWithCampfire { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "INTERACT_WITH_CARTOGRAPHY_TABLE" => Ok(Statistic::InteractWithCartographyTable { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "INTERACT_WITH_LOOM" => Ok(Statistic::InteractWithLoom { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "INTERACT_WITH_STONECUTTER" => Ok(Statistic::InteractWithStonecutter { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "BELL_RING" => Ok(Statistic::BellRing { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "RAID_TRIGGER" => Ok(Statistic::RaidTrigger { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "RAID_WIN" => Ok(Statistic::RaidWin { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "INTERACT_WITH_ANVIL" => Ok(Statistic::InteractWithAnvil { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "INTERACT_WITH_GRINDSTONE" => Ok(Statistic::InteractWithGrindstone { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "TARGET_HIT" => Ok(Statistic::TargetHit { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "INTERACT_WITH_SMITHING_TABLE" => Ok(Statistic::InteractWithSmithingTable { + inner: StatisticStruct::from_raw(env, obj)?, + }), + "STRIDER_ONE_CM" => Ok(Statistic::StriderOneCm { + inner: StatisticStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } } - /// Gets the world from the given Unique ID. - pub fn get_world( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - uid: impl Into>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uid.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Lorg/bukkit/World;"; - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getWorld", sig.as_str(), args); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); +} + +impl<'mc> JNIRaw<'mc> for StatisticStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for StatisticStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate StatisticStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Statistic")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a StatisticStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - let obj = res.l()?; - Ok(Some(crate::World::from_raw(&jni, obj)?)) } - /// Create a new virtual {@link WorldBorder}. - pub fn create_world_border( +} + +impl<'mc> StatisticStruct<'mc> { + pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/WorldBorder;"); - let cls = jni.find_class("org/bukkit/Bukkit"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Statistic;"); + let cls = jni.find_class("org/bukkit/Statistic"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "createWorldBorder", sig.as_str(), vec![]); + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::WorldBorder::from_raw(&jni, obj) + crate::Statistic::from_raw(&jni, obj) } - #[deprecated] - /// Gets the map from the given item ID. - pub fn get_map( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - id: i32, - ) -> Result>, Box> { - let sig = String::from("(I)Lorg/bukkit/map/MapView;"); - let val_1 = jni::objects::JValueGen::Int(id); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( + /// Gets the type of this statistic. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Statistic/Type;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::StatisticType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Checks if this is a substatistic. + /// + /// A substatistic exists en masse for each block, item, or entitytype, depending on + /// {@link #getType()}. + /// + /// This is a redundant method and equivalent to checking + /// getType() != Type.UNTYPED + pub fn is_substatistic(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isSubstatistic", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks if this is a substatistic dealing with blocks. + /// + /// This is a redundant method and equivalent to checking + /// getType() == Type.BLOCK + pub fn is_block(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isBlock", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +pub enum StatisticType<'mc> { + Untyped { inner: StatisticTypeStruct<'mc> }, + Item { inner: StatisticTypeStruct<'mc> }, + Block { inner: StatisticTypeStruct<'mc> }, + Entity { inner: StatisticTypeStruct<'mc> }, +} +impl<'mc> std::fmt::Display for StatisticType<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + StatisticType::Untyped { .. } => f.write_str("UNTYPED"), + StatisticType::Item { .. } => f.write_str("ITEM"), + StatisticType::Block { .. } => f.write_str("BLOCK"), + StatisticType::Entity { .. } => f.write_str("ENTITY"), + } + } +} +impl<'mc> std::ops::Deref for StatisticType<'mc> { + type Target = StatisticTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + StatisticType::Untyped { inner } => inner, + StatisticType::Item { inner } => inner, + StatisticType::Block { inner } => inner, + StatisticType::Entity { inner } => inner, + } + } +} + +impl<'mc> StatisticType<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/Statistic/Type"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( cls, - "getMap", - sig.as_str(), + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/Statistic/Type;", vec![jni::objects::JValueGen::from(val_1)], ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "UNTYPED" => Ok(StatisticType::Untyped { + inner: StatisticTypeStruct::from_raw(env, obj)?, + }), + "ITEM" => Ok(StatisticType::Item { + inner: StatisticTypeStruct::from_raw(env, obj)?, + }), + "BLOCK" => Ok(StatisticType::Block { + inner: StatisticTypeStruct::from_raw(env, obj)?, + }), + "ENTITY" => Ok(StatisticType::Entity { + inner: StatisticTypeStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct StatisticTypeStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for StatisticType<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Untyped { inner } => inner.0.clone(), + Self::Item { inner } => inner.0.clone(), + Self::Block { inner } => inner.0.clone(), + Self::Entity { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Untyped { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Item { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Block { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Entity { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for StatisticType<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate StatisticType from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Statistic/Type")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a StatisticType object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "UNTYPED" => Ok(StatisticType::Untyped { + inner: StatisticTypeStruct::from_raw(env, obj)?, + }), + "ITEM" => Ok(StatisticType::Item { + inner: StatisticTypeStruct::from_raw(env, obj)?, + }), + "BLOCK" => Ok(StatisticType::Block { + inner: StatisticTypeStruct::from_raw(env, obj)?, + }), + "ENTITY" => Ok(StatisticType::Entity { + inner: StatisticTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for StatisticTypeStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for StatisticTypeStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate StatisticTypeStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Statistic/Type")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a StatisticTypeStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> StatisticTypeStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Statistic/Type;"); + let cls = jni.find_class("org/bukkit/Statistic/Type"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + let obj = res.l()?; + crate::StatisticType::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +pub enum Sound<'mc> { + AmbientBasaltDeltasAdditions { inner: SoundStruct<'mc> }, + AmbientBasaltDeltasLoop { inner: SoundStruct<'mc> }, + AmbientBasaltDeltasMood { inner: SoundStruct<'mc> }, + AmbientCave { inner: SoundStruct<'mc> }, + AmbientCrimsonForestAdditions { inner: SoundStruct<'mc> }, + AmbientCrimsonForestLoop { inner: SoundStruct<'mc> }, + AmbientCrimsonForestMood { inner: SoundStruct<'mc> }, + AmbientNetherWastesAdditions { inner: SoundStruct<'mc> }, + AmbientNetherWastesLoop { inner: SoundStruct<'mc> }, + AmbientNetherWastesMood { inner: SoundStruct<'mc> }, + AmbientSoulSandValleyAdditions { inner: SoundStruct<'mc> }, + AmbientSoulSandValleyLoop { inner: SoundStruct<'mc> }, + AmbientSoulSandValleyMood { inner: SoundStruct<'mc> }, + AmbientUnderwaterEnter { inner: SoundStruct<'mc> }, + AmbientUnderwaterExit { inner: SoundStruct<'mc> }, + AmbientUnderwaterLoop { inner: SoundStruct<'mc> }, + AmbientUnderwaterLoopAdditions { inner: SoundStruct<'mc> }, + AmbientUnderwaterLoopAdditionsRare { inner: SoundStruct<'mc> }, + AmbientUnderwaterLoopAdditionsUltraRare { inner: SoundStruct<'mc> }, + AmbientWarpedForestAdditions { inner: SoundStruct<'mc> }, + AmbientWarpedForestLoop { inner: SoundStruct<'mc> }, + AmbientWarpedForestMood { inner: SoundStruct<'mc> }, + BlockAmethystBlockBreak { inner: SoundStruct<'mc> }, + BlockAmethystBlockChime { inner: SoundStruct<'mc> }, + BlockAmethystBlockFall { inner: SoundStruct<'mc> }, + BlockAmethystBlockHit { inner: SoundStruct<'mc> }, + BlockAmethystBlockPlace { inner: SoundStruct<'mc> }, + BlockAmethystBlockResonate { inner: SoundStruct<'mc> }, + BlockAmethystBlockStep { inner: SoundStruct<'mc> }, + BlockAmethystClusterBreak { inner: SoundStruct<'mc> }, + BlockAmethystClusterFall { inner: SoundStruct<'mc> }, + BlockAmethystClusterHit { inner: SoundStruct<'mc> }, + BlockAmethystClusterPlace { inner: SoundStruct<'mc> }, + BlockAmethystClusterStep { inner: SoundStruct<'mc> }, + BlockAncientDebrisBreak { inner: SoundStruct<'mc> }, + BlockAncientDebrisFall { inner: SoundStruct<'mc> }, + BlockAncientDebrisHit { inner: SoundStruct<'mc> }, + BlockAncientDebrisPlace { inner: SoundStruct<'mc> }, + BlockAncientDebrisStep { inner: SoundStruct<'mc> }, + BlockAnvilBreak { inner: SoundStruct<'mc> }, + BlockAnvilDestroy { inner: SoundStruct<'mc> }, + BlockAnvilFall { inner: SoundStruct<'mc> }, + BlockAnvilHit { inner: SoundStruct<'mc> }, + BlockAnvilLand { inner: SoundStruct<'mc> }, + BlockAnvilPlace { inner: SoundStruct<'mc> }, + BlockAnvilStep { inner: SoundStruct<'mc> }, + BlockAnvilUse { inner: SoundStruct<'mc> }, + BlockAzaleaBreak { inner: SoundStruct<'mc> }, + BlockAzaleaFall { inner: SoundStruct<'mc> }, + BlockAzaleaHit { inner: SoundStruct<'mc> }, + BlockAzaleaLeavesBreak { inner: SoundStruct<'mc> }, + BlockAzaleaLeavesFall { inner: SoundStruct<'mc> }, + BlockAzaleaLeavesHit { inner: SoundStruct<'mc> }, + BlockAzaleaLeavesPlace { inner: SoundStruct<'mc> }, + BlockAzaleaLeavesStep { inner: SoundStruct<'mc> }, + BlockAzaleaPlace { inner: SoundStruct<'mc> }, + BlockAzaleaStep { inner: SoundStruct<'mc> }, + BlockBambooBreak { inner: SoundStruct<'mc> }, + BlockBambooFall { inner: SoundStruct<'mc> }, + BlockBambooHit { inner: SoundStruct<'mc> }, + BlockBambooPlace { inner: SoundStruct<'mc> }, + BlockBambooSaplingBreak { inner: SoundStruct<'mc> }, + BlockBambooSaplingHit { inner: SoundStruct<'mc> }, + BlockBambooSaplingPlace { inner: SoundStruct<'mc> }, + BlockBambooStep { inner: SoundStruct<'mc> }, + BlockBambooWoodBreak { inner: SoundStruct<'mc> }, + BlockBambooWoodButtonClickOff { inner: SoundStruct<'mc> }, + BlockBambooWoodButtonClickOn { inner: SoundStruct<'mc> }, + BlockBambooWoodDoorClose { inner: SoundStruct<'mc> }, + BlockBambooWoodDoorOpen { inner: SoundStruct<'mc> }, + BlockBambooWoodFall { inner: SoundStruct<'mc> }, + BlockBambooWoodFenceGateClose { inner: SoundStruct<'mc> }, + BlockBambooWoodFenceGateOpen { inner: SoundStruct<'mc> }, + BlockBambooWoodHangingSignBreak { inner: SoundStruct<'mc> }, + BlockBambooWoodHangingSignFall { inner: SoundStruct<'mc> }, + BlockBambooWoodHangingSignHit { inner: SoundStruct<'mc> }, + BlockBambooWoodHangingSignPlace { inner: SoundStruct<'mc> }, + BlockBambooWoodHangingSignStep { inner: SoundStruct<'mc> }, + BlockBambooWoodHit { inner: SoundStruct<'mc> }, + BlockBambooWoodPlace { inner: SoundStruct<'mc> }, + BlockBambooWoodPressurePlateClickOff { inner: SoundStruct<'mc> }, + BlockBambooWoodPressurePlateClickOn { inner: SoundStruct<'mc> }, + BlockBambooWoodStep { inner: SoundStruct<'mc> }, + BlockBambooWoodTrapdoorClose { inner: SoundStruct<'mc> }, + BlockBambooWoodTrapdoorOpen { inner: SoundStruct<'mc> }, + BlockBarrelClose { inner: SoundStruct<'mc> }, + BlockBarrelOpen { inner: SoundStruct<'mc> }, + BlockBasaltBreak { inner: SoundStruct<'mc> }, + BlockBasaltFall { inner: SoundStruct<'mc> }, + BlockBasaltHit { inner: SoundStruct<'mc> }, + BlockBasaltPlace { inner: SoundStruct<'mc> }, + BlockBasaltStep { inner: SoundStruct<'mc> }, + BlockBeaconActivate { inner: SoundStruct<'mc> }, + BlockBeaconAmbient { inner: SoundStruct<'mc> }, + BlockBeaconDeactivate { inner: SoundStruct<'mc> }, + BlockBeaconPowerSelect { inner: SoundStruct<'mc> }, + BlockBeehiveDrip { inner: SoundStruct<'mc> }, + BlockBeehiveEnter { inner: SoundStruct<'mc> }, + BlockBeehiveExit { inner: SoundStruct<'mc> }, + BlockBeehiveShear { inner: SoundStruct<'mc> }, + BlockBeehiveWork { inner: SoundStruct<'mc> }, + BlockBellResonate { inner: SoundStruct<'mc> }, + BlockBellUse { inner: SoundStruct<'mc> }, + BlockBigDripleafBreak { inner: SoundStruct<'mc> }, + BlockBigDripleafFall { inner: SoundStruct<'mc> }, + BlockBigDripleafHit { inner: SoundStruct<'mc> }, + BlockBigDripleafPlace { inner: SoundStruct<'mc> }, + BlockBigDripleafStep { inner: SoundStruct<'mc> }, + BlockBigDripleafTiltDown { inner: SoundStruct<'mc> }, + BlockBigDripleafTiltUp { inner: SoundStruct<'mc> }, + BlockBlastfurnaceFireCrackle { inner: SoundStruct<'mc> }, + BlockBoneBlockBreak { inner: SoundStruct<'mc> }, + BlockBoneBlockFall { inner: SoundStruct<'mc> }, + BlockBoneBlockHit { inner: SoundStruct<'mc> }, + BlockBoneBlockPlace { inner: SoundStruct<'mc> }, + BlockBoneBlockStep { inner: SoundStruct<'mc> }, + BlockBrewingStandBrew { inner: SoundStruct<'mc> }, + BlockBubbleColumnBubblePop { inner: SoundStruct<'mc> }, + BlockBubbleColumnUpwardsAmbient { inner: SoundStruct<'mc> }, + BlockBubbleColumnUpwardsInside { inner: SoundStruct<'mc> }, + BlockBubbleColumnWhirlpoolAmbient { inner: SoundStruct<'mc> }, + BlockBubbleColumnWhirlpoolInside { inner: SoundStruct<'mc> }, + BlockCakeAddCandle { inner: SoundStruct<'mc> }, + BlockCalciteBreak { inner: SoundStruct<'mc> }, + BlockCalciteFall { inner: SoundStruct<'mc> }, + BlockCalciteHit { inner: SoundStruct<'mc> }, + BlockCalcitePlace { inner: SoundStruct<'mc> }, + BlockCalciteStep { inner: SoundStruct<'mc> }, + BlockCampfireCrackle { inner: SoundStruct<'mc> }, + BlockCandleAmbient { inner: SoundStruct<'mc> }, + BlockCandleBreak { inner: SoundStruct<'mc> }, + BlockCandleExtinguish { inner: SoundStruct<'mc> }, + BlockCandleFall { inner: SoundStruct<'mc> }, + BlockCandleHit { inner: SoundStruct<'mc> }, + BlockCandlePlace { inner: SoundStruct<'mc> }, + BlockCandleStep { inner: SoundStruct<'mc> }, + BlockCaveVinesBreak { inner: SoundStruct<'mc> }, + BlockCaveVinesFall { inner: SoundStruct<'mc> }, + BlockCaveVinesHit { inner: SoundStruct<'mc> }, + BlockCaveVinesPickBerries { inner: SoundStruct<'mc> }, + BlockCaveVinesPlace { inner: SoundStruct<'mc> }, + BlockCaveVinesStep { inner: SoundStruct<'mc> }, + BlockChainBreak { inner: SoundStruct<'mc> }, + BlockChainFall { inner: SoundStruct<'mc> }, + BlockChainHit { inner: SoundStruct<'mc> }, + BlockChainPlace { inner: SoundStruct<'mc> }, + BlockChainStep { inner: SoundStruct<'mc> }, + BlockCherryLeavesBreak { inner: SoundStruct<'mc> }, + BlockCherryLeavesFall { inner: SoundStruct<'mc> }, + BlockCherryLeavesHit { inner: SoundStruct<'mc> }, + BlockCherryLeavesPlace { inner: SoundStruct<'mc> }, + BlockCherryLeavesStep { inner: SoundStruct<'mc> }, + BlockCherrySaplingBreak { inner: SoundStruct<'mc> }, + BlockCherrySaplingFall { inner: SoundStruct<'mc> }, + BlockCherrySaplingHit { inner: SoundStruct<'mc> }, + BlockCherrySaplingPlace { inner: SoundStruct<'mc> }, + BlockCherrySaplingStep { inner: SoundStruct<'mc> }, + BlockCherryWoodBreak { inner: SoundStruct<'mc> }, + BlockCherryWoodButtonClickOff { inner: SoundStruct<'mc> }, + BlockCherryWoodButtonClickOn { inner: SoundStruct<'mc> }, + BlockCherryWoodDoorClose { inner: SoundStruct<'mc> }, + BlockCherryWoodDoorOpen { inner: SoundStruct<'mc> }, + BlockCherryWoodFall { inner: SoundStruct<'mc> }, + BlockCherryWoodFenceGateClose { inner: SoundStruct<'mc> }, + BlockCherryWoodFenceGateOpen { inner: SoundStruct<'mc> }, + BlockCherryWoodHangingSignBreak { inner: SoundStruct<'mc> }, + BlockCherryWoodHangingSignFall { inner: SoundStruct<'mc> }, + BlockCherryWoodHangingSignHit { inner: SoundStruct<'mc> }, + BlockCherryWoodHangingSignPlace { inner: SoundStruct<'mc> }, + BlockCherryWoodHangingSignStep { inner: SoundStruct<'mc> }, + BlockCherryWoodHit { inner: SoundStruct<'mc> }, + BlockCherryWoodPlace { inner: SoundStruct<'mc> }, + BlockCherryWoodPressurePlateClickOff { inner: SoundStruct<'mc> }, + BlockCherryWoodPressurePlateClickOn { inner: SoundStruct<'mc> }, + BlockCherryWoodStep { inner: SoundStruct<'mc> }, + BlockCherryWoodTrapdoorClose { inner: SoundStruct<'mc> }, + BlockCherryWoodTrapdoorOpen { inner: SoundStruct<'mc> }, + BlockChestClose { inner: SoundStruct<'mc> }, + BlockChestLocked { inner: SoundStruct<'mc> }, + BlockChestOpen { inner: SoundStruct<'mc> }, + BlockChiseledBookshelfBreak { inner: SoundStruct<'mc> }, + BlockChiseledBookshelfFall { inner: SoundStruct<'mc> }, + BlockChiseledBookshelfHit { inner: SoundStruct<'mc> }, + BlockChiseledBookshelfInsert { inner: SoundStruct<'mc> }, + BlockChiseledBookshelfInsertEnchanted { inner: SoundStruct<'mc> }, + BlockChiseledBookshelfPickup { inner: SoundStruct<'mc> }, + BlockChiseledBookshelfPickupEnchanted { inner: SoundStruct<'mc> }, + BlockChiseledBookshelfPlace { inner: SoundStruct<'mc> }, + BlockChiseledBookshelfStep { inner: SoundStruct<'mc> }, + BlockChorusFlowerDeath { inner: SoundStruct<'mc> }, + BlockChorusFlowerGrow { inner: SoundStruct<'mc> }, + BlockCobwebBreak { inner: SoundStruct<'mc> }, + BlockCobwebFall { inner: SoundStruct<'mc> }, + BlockCobwebHit { inner: SoundStruct<'mc> }, + BlockCobwebPlace { inner: SoundStruct<'mc> }, + BlockCobwebStep { inner: SoundStruct<'mc> }, + BlockComparatorClick { inner: SoundStruct<'mc> }, + BlockComposterEmpty { inner: SoundStruct<'mc> }, + BlockComposterFill { inner: SoundStruct<'mc> }, + BlockComposterFillSuccess { inner: SoundStruct<'mc> }, + BlockComposterReady { inner: SoundStruct<'mc> }, + BlockConduitActivate { inner: SoundStruct<'mc> }, + BlockConduitAmbient { inner: SoundStruct<'mc> }, + BlockConduitAmbientShort { inner: SoundStruct<'mc> }, + BlockConduitAttackTarget { inner: SoundStruct<'mc> }, + BlockConduitDeactivate { inner: SoundStruct<'mc> }, + BlockCopperBreak { inner: SoundStruct<'mc> }, + BlockCopperBulbBreak { inner: SoundStruct<'mc> }, + BlockCopperBulbFall { inner: SoundStruct<'mc> }, + BlockCopperBulbHit { inner: SoundStruct<'mc> }, + BlockCopperBulbPlace { inner: SoundStruct<'mc> }, + BlockCopperBulbStep { inner: SoundStruct<'mc> }, + BlockCopperBulbTurnOff { inner: SoundStruct<'mc> }, + BlockCopperBulbTurnOn { inner: SoundStruct<'mc> }, + BlockCopperDoorClose { inner: SoundStruct<'mc> }, + BlockCopperDoorOpen { inner: SoundStruct<'mc> }, + BlockCopperFall { inner: SoundStruct<'mc> }, + BlockCopperGrateBreak { inner: SoundStruct<'mc> }, + BlockCopperGrateFall { inner: SoundStruct<'mc> }, + BlockCopperGrateHit { inner: SoundStruct<'mc> }, + BlockCopperGratePlace { inner: SoundStruct<'mc> }, + BlockCopperGrateStep { inner: SoundStruct<'mc> }, + BlockCopperHit { inner: SoundStruct<'mc> }, + BlockCopperPlace { inner: SoundStruct<'mc> }, + BlockCopperStep { inner: SoundStruct<'mc> }, + BlockCopperTrapdoorClose { inner: SoundStruct<'mc> }, + BlockCopperTrapdoorOpen { inner: SoundStruct<'mc> }, + BlockCoralBlockBreak { inner: SoundStruct<'mc> }, + BlockCoralBlockFall { inner: SoundStruct<'mc> }, + BlockCoralBlockHit { inner: SoundStruct<'mc> }, + BlockCoralBlockPlace { inner: SoundStruct<'mc> }, + BlockCoralBlockStep { inner: SoundStruct<'mc> }, + BlockCrafterCraft { inner: SoundStruct<'mc> }, + BlockCrafterFail { inner: SoundStruct<'mc> }, + BlockCropBreak { inner: SoundStruct<'mc> }, + BlockDecoratedPotBreak { inner: SoundStruct<'mc> }, + BlockDecoratedPotFall { inner: SoundStruct<'mc> }, + BlockDecoratedPotHit { inner: SoundStruct<'mc> }, + BlockDecoratedPotInsert { inner: SoundStruct<'mc> }, + BlockDecoratedPotInsertFail { inner: SoundStruct<'mc> }, + BlockDecoratedPotPlace { inner: SoundStruct<'mc> }, + BlockDecoratedPotShatter { inner: SoundStruct<'mc> }, + BlockDecoratedPotStep { inner: SoundStruct<'mc> }, + BlockDeepslateBreak { inner: SoundStruct<'mc> }, + BlockDeepslateBricksBreak { inner: SoundStruct<'mc> }, + BlockDeepslateBricksFall { inner: SoundStruct<'mc> }, + BlockDeepslateBricksHit { inner: SoundStruct<'mc> }, + BlockDeepslateBricksPlace { inner: SoundStruct<'mc> }, + BlockDeepslateBricksStep { inner: SoundStruct<'mc> }, + BlockDeepslateFall { inner: SoundStruct<'mc> }, + BlockDeepslateHit { inner: SoundStruct<'mc> }, + BlockDeepslatePlace { inner: SoundStruct<'mc> }, + BlockDeepslateStep { inner: SoundStruct<'mc> }, + BlockDeepslateTilesBreak { inner: SoundStruct<'mc> }, + BlockDeepslateTilesFall { inner: SoundStruct<'mc> }, + BlockDeepslateTilesHit { inner: SoundStruct<'mc> }, + BlockDeepslateTilesPlace { inner: SoundStruct<'mc> }, + BlockDeepslateTilesStep { inner: SoundStruct<'mc> }, + BlockDispenserDispense { inner: SoundStruct<'mc> }, + BlockDispenserFail { inner: SoundStruct<'mc> }, + BlockDispenserLaunch { inner: SoundStruct<'mc> }, + BlockDripstoneBlockBreak { inner: SoundStruct<'mc> }, + BlockDripstoneBlockFall { inner: SoundStruct<'mc> }, + BlockDripstoneBlockHit { inner: SoundStruct<'mc> }, + BlockDripstoneBlockPlace { inner: SoundStruct<'mc> }, + BlockDripstoneBlockStep { inner: SoundStruct<'mc> }, + BlockEnchantmentTableUse { inner: SoundStruct<'mc> }, + BlockEnderChestClose { inner: SoundStruct<'mc> }, + BlockEnderChestOpen { inner: SoundStruct<'mc> }, + BlockEndGatewaySpawn { inner: SoundStruct<'mc> }, + BlockEndPortalFrameFill { inner: SoundStruct<'mc> }, + BlockEndPortalSpawn { inner: SoundStruct<'mc> }, + BlockFenceGateClose { inner: SoundStruct<'mc> }, + BlockFenceGateOpen { inner: SoundStruct<'mc> }, + BlockFireAmbient { inner: SoundStruct<'mc> }, + BlockFireExtinguish { inner: SoundStruct<'mc> }, + BlockFloweringAzaleaBreak { inner: SoundStruct<'mc> }, + BlockFloweringAzaleaFall { inner: SoundStruct<'mc> }, + BlockFloweringAzaleaHit { inner: SoundStruct<'mc> }, + BlockFloweringAzaleaPlace { inner: SoundStruct<'mc> }, + BlockFloweringAzaleaStep { inner: SoundStruct<'mc> }, + BlockFroglightBreak { inner: SoundStruct<'mc> }, + BlockFroglightFall { inner: SoundStruct<'mc> }, + BlockFroglightHit { inner: SoundStruct<'mc> }, + BlockFroglightPlace { inner: SoundStruct<'mc> }, + BlockFroglightStep { inner: SoundStruct<'mc> }, + BlockFrogspawnBreak { inner: SoundStruct<'mc> }, + BlockFrogspawnFall { inner: SoundStruct<'mc> }, + BlockFrogspawnHatch { inner: SoundStruct<'mc> }, + BlockFrogspawnHit { inner: SoundStruct<'mc> }, + BlockFrogspawnPlace { inner: SoundStruct<'mc> }, + BlockFrogspawnStep { inner: SoundStruct<'mc> }, + BlockFungusBreak { inner: SoundStruct<'mc> }, + BlockFungusFall { inner: SoundStruct<'mc> }, + BlockFungusHit { inner: SoundStruct<'mc> }, + BlockFungusPlace { inner: SoundStruct<'mc> }, + BlockFungusStep { inner: SoundStruct<'mc> }, + BlockFurnaceFireCrackle { inner: SoundStruct<'mc> }, + BlockGildedBlackstoneBreak { inner: SoundStruct<'mc> }, + BlockGildedBlackstoneFall { inner: SoundStruct<'mc> }, + BlockGildedBlackstoneHit { inner: SoundStruct<'mc> }, + BlockGildedBlackstonePlace { inner: SoundStruct<'mc> }, + BlockGildedBlackstoneStep { inner: SoundStruct<'mc> }, + BlockGlassBreak { inner: SoundStruct<'mc> }, + BlockGlassFall { inner: SoundStruct<'mc> }, + BlockGlassHit { inner: SoundStruct<'mc> }, + BlockGlassPlace { inner: SoundStruct<'mc> }, + BlockGlassStep { inner: SoundStruct<'mc> }, + BlockGrassBreak { inner: SoundStruct<'mc> }, + BlockGrassFall { inner: SoundStruct<'mc> }, + BlockGrassHit { inner: SoundStruct<'mc> }, + BlockGrassPlace { inner: SoundStruct<'mc> }, + BlockGrassStep { inner: SoundStruct<'mc> }, + BlockGravelBreak { inner: SoundStruct<'mc> }, + BlockGravelFall { inner: SoundStruct<'mc> }, + BlockGravelHit { inner: SoundStruct<'mc> }, + BlockGravelPlace { inner: SoundStruct<'mc> }, + BlockGravelStep { inner: SoundStruct<'mc> }, + BlockGrindstoneUse { inner: SoundStruct<'mc> }, + BlockGrowingPlantCrop { inner: SoundStruct<'mc> }, + BlockHangingRootsBreak { inner: SoundStruct<'mc> }, + BlockHangingRootsFall { inner: SoundStruct<'mc> }, + BlockHangingRootsHit { inner: SoundStruct<'mc> }, + BlockHangingRootsPlace { inner: SoundStruct<'mc> }, + BlockHangingRootsStep { inner: SoundStruct<'mc> }, + BlockHangingSignBreak { inner: SoundStruct<'mc> }, + BlockHangingSignFall { inner: SoundStruct<'mc> }, + BlockHangingSignHit { inner: SoundStruct<'mc> }, + BlockHangingSignPlace { inner: SoundStruct<'mc> }, + BlockHangingSignStep { inner: SoundStruct<'mc> }, + BlockHangingSignWaxedInteractFail { inner: SoundStruct<'mc> }, + BlockHeavyCoreBreak { inner: SoundStruct<'mc> }, + BlockHeavyCoreFall { inner: SoundStruct<'mc> }, + BlockHeavyCoreHit { inner: SoundStruct<'mc> }, + BlockHeavyCorePlace { inner: SoundStruct<'mc> }, + BlockHeavyCoreStep { inner: SoundStruct<'mc> }, + BlockHoneyBlockBreak { inner: SoundStruct<'mc> }, + BlockHoneyBlockFall { inner: SoundStruct<'mc> }, + BlockHoneyBlockHit { inner: SoundStruct<'mc> }, + BlockHoneyBlockPlace { inner: SoundStruct<'mc> }, + BlockHoneyBlockSlide { inner: SoundStruct<'mc> }, + BlockHoneyBlockStep { inner: SoundStruct<'mc> }, + BlockIronDoorClose { inner: SoundStruct<'mc> }, + BlockIronDoorOpen { inner: SoundStruct<'mc> }, + BlockIronTrapdoorClose { inner: SoundStruct<'mc> }, + BlockIronTrapdoorOpen { inner: SoundStruct<'mc> }, + BlockLadderBreak { inner: SoundStruct<'mc> }, + BlockLadderFall { inner: SoundStruct<'mc> }, + BlockLadderHit { inner: SoundStruct<'mc> }, + BlockLadderPlace { inner: SoundStruct<'mc> }, + BlockLadderStep { inner: SoundStruct<'mc> }, + BlockLanternBreak { inner: SoundStruct<'mc> }, + BlockLanternFall { inner: SoundStruct<'mc> }, + BlockLanternHit { inner: SoundStruct<'mc> }, + BlockLanternPlace { inner: SoundStruct<'mc> }, + BlockLanternStep { inner: SoundStruct<'mc> }, + BlockLargeAmethystBudBreak { inner: SoundStruct<'mc> }, + BlockLargeAmethystBudPlace { inner: SoundStruct<'mc> }, + BlockLavaAmbient { inner: SoundStruct<'mc> }, + BlockLavaExtinguish { inner: SoundStruct<'mc> }, + BlockLavaPop { inner: SoundStruct<'mc> }, + BlockLeverClick { inner: SoundStruct<'mc> }, + BlockLilyPadPlace { inner: SoundStruct<'mc> }, + BlockLodestoneBreak { inner: SoundStruct<'mc> }, + BlockLodestoneFall { inner: SoundStruct<'mc> }, + BlockLodestoneHit { inner: SoundStruct<'mc> }, + BlockLodestonePlace { inner: SoundStruct<'mc> }, + BlockLodestoneStep { inner: SoundStruct<'mc> }, + BlockMangroveRootsBreak { inner: SoundStruct<'mc> }, + BlockMangroveRootsFall { inner: SoundStruct<'mc> }, + BlockMangroveRootsHit { inner: SoundStruct<'mc> }, + BlockMangroveRootsPlace { inner: SoundStruct<'mc> }, + BlockMangroveRootsStep { inner: SoundStruct<'mc> }, + BlockMediumAmethystBudBreak { inner: SoundStruct<'mc> }, + BlockMediumAmethystBudPlace { inner: SoundStruct<'mc> }, + BlockMetalBreak { inner: SoundStruct<'mc> }, + BlockMetalFall { inner: SoundStruct<'mc> }, + BlockMetalHit { inner: SoundStruct<'mc> }, + BlockMetalPlace { inner: SoundStruct<'mc> }, + BlockMetalPressurePlateClickOff { inner: SoundStruct<'mc> }, + BlockMetalPressurePlateClickOn { inner: SoundStruct<'mc> }, + BlockMetalStep { inner: SoundStruct<'mc> }, + BlockMossBreak { inner: SoundStruct<'mc> }, + BlockMossCarpetBreak { inner: SoundStruct<'mc> }, + BlockMossCarpetFall { inner: SoundStruct<'mc> }, + BlockMossCarpetHit { inner: SoundStruct<'mc> }, + BlockMossCarpetPlace { inner: SoundStruct<'mc> }, + BlockMossCarpetStep { inner: SoundStruct<'mc> }, + BlockMossFall { inner: SoundStruct<'mc> }, + BlockMossHit { inner: SoundStruct<'mc> }, + BlockMossPlace { inner: SoundStruct<'mc> }, + BlockMossStep { inner: SoundStruct<'mc> }, + BlockMuddyMangroveRootsBreak { inner: SoundStruct<'mc> }, + BlockMuddyMangroveRootsFall { inner: SoundStruct<'mc> }, + BlockMuddyMangroveRootsHit { inner: SoundStruct<'mc> }, + BlockMuddyMangroveRootsPlace { inner: SoundStruct<'mc> }, + BlockMuddyMangroveRootsStep { inner: SoundStruct<'mc> }, + BlockMudBreak { inner: SoundStruct<'mc> }, + BlockMudBricksBreak { inner: SoundStruct<'mc> }, + BlockMudBricksFall { inner: SoundStruct<'mc> }, + BlockMudBricksHit { inner: SoundStruct<'mc> }, + BlockMudBricksPlace { inner: SoundStruct<'mc> }, + BlockMudBricksStep { inner: SoundStruct<'mc> }, + BlockMudFall { inner: SoundStruct<'mc> }, + BlockMudHit { inner: SoundStruct<'mc> }, + BlockMudPlace { inner: SoundStruct<'mc> }, + BlockMudStep { inner: SoundStruct<'mc> }, + BlockNetheriteBlockBreak { inner: SoundStruct<'mc> }, + BlockNetheriteBlockFall { inner: SoundStruct<'mc> }, + BlockNetheriteBlockHit { inner: SoundStruct<'mc> }, + BlockNetheriteBlockPlace { inner: SoundStruct<'mc> }, + BlockNetheriteBlockStep { inner: SoundStruct<'mc> }, + BlockNetherrackBreak { inner: SoundStruct<'mc> }, + BlockNetherrackFall { inner: SoundStruct<'mc> }, + BlockNetherrackHit { inner: SoundStruct<'mc> }, + BlockNetherrackPlace { inner: SoundStruct<'mc> }, + BlockNetherrackStep { inner: SoundStruct<'mc> }, + BlockNetherBricksBreak { inner: SoundStruct<'mc> }, + BlockNetherBricksFall { inner: SoundStruct<'mc> }, + BlockNetherBricksHit { inner: SoundStruct<'mc> }, + BlockNetherBricksPlace { inner: SoundStruct<'mc> }, + BlockNetherBricksStep { inner: SoundStruct<'mc> }, + BlockNetherGoldOreBreak { inner: SoundStruct<'mc> }, + BlockNetherGoldOreFall { inner: SoundStruct<'mc> }, + BlockNetherGoldOreHit { inner: SoundStruct<'mc> }, + BlockNetherGoldOrePlace { inner: SoundStruct<'mc> }, + BlockNetherGoldOreStep { inner: SoundStruct<'mc> }, + BlockNetherOreBreak { inner: SoundStruct<'mc> }, + BlockNetherOreFall { inner: SoundStruct<'mc> }, + BlockNetherOreHit { inner: SoundStruct<'mc> }, + BlockNetherOrePlace { inner: SoundStruct<'mc> }, + BlockNetherOreStep { inner: SoundStruct<'mc> }, + BlockNetherSproutsBreak { inner: SoundStruct<'mc> }, + BlockNetherSproutsFall { inner: SoundStruct<'mc> }, + BlockNetherSproutsHit { inner: SoundStruct<'mc> }, + BlockNetherSproutsPlace { inner: SoundStruct<'mc> }, + BlockNetherSproutsStep { inner: SoundStruct<'mc> }, + BlockNetherWartBreak { inner: SoundStruct<'mc> }, + BlockNetherWoodBreak { inner: SoundStruct<'mc> }, + BlockNetherWoodButtonClickOff { inner: SoundStruct<'mc> }, + BlockNetherWoodButtonClickOn { inner: SoundStruct<'mc> }, + BlockNetherWoodDoorClose { inner: SoundStruct<'mc> }, + BlockNetherWoodDoorOpen { inner: SoundStruct<'mc> }, + BlockNetherWoodFall { inner: SoundStruct<'mc> }, + BlockNetherWoodFenceGateClose { inner: SoundStruct<'mc> }, + BlockNetherWoodFenceGateOpen { inner: SoundStruct<'mc> }, + BlockNetherWoodHangingSignBreak { inner: SoundStruct<'mc> }, + BlockNetherWoodHangingSignFall { inner: SoundStruct<'mc> }, + BlockNetherWoodHangingSignHit { inner: SoundStruct<'mc> }, + BlockNetherWoodHangingSignPlace { inner: SoundStruct<'mc> }, + BlockNetherWoodHangingSignStep { inner: SoundStruct<'mc> }, + BlockNetherWoodHit { inner: SoundStruct<'mc> }, + BlockNetherWoodPlace { inner: SoundStruct<'mc> }, + BlockNetherWoodPressurePlateClickOff { inner: SoundStruct<'mc> }, + BlockNetherWoodPressurePlateClickOn { inner: SoundStruct<'mc> }, + BlockNetherWoodStep { inner: SoundStruct<'mc> }, + BlockNetherWoodTrapdoorClose { inner: SoundStruct<'mc> }, + BlockNetherWoodTrapdoorOpen { inner: SoundStruct<'mc> }, + BlockNoteBlockBanjo { inner: SoundStruct<'mc> }, + BlockNoteBlockBasedrum { inner: SoundStruct<'mc> }, + BlockNoteBlockBass { inner: SoundStruct<'mc> }, + BlockNoteBlockBell { inner: SoundStruct<'mc> }, + BlockNoteBlockBit { inner: SoundStruct<'mc> }, + BlockNoteBlockChime { inner: SoundStruct<'mc> }, + BlockNoteBlockCowBell { inner: SoundStruct<'mc> }, + BlockNoteBlockDidgeridoo { inner: SoundStruct<'mc> }, + BlockNoteBlockFlute { inner: SoundStruct<'mc> }, + BlockNoteBlockGuitar { inner: SoundStruct<'mc> }, + BlockNoteBlockHarp { inner: SoundStruct<'mc> }, + BlockNoteBlockHat { inner: SoundStruct<'mc> }, + BlockNoteBlockImitateCreeper { inner: SoundStruct<'mc> }, + BlockNoteBlockImitateEnderDragon { inner: SoundStruct<'mc> }, + BlockNoteBlockImitatePiglin { inner: SoundStruct<'mc> }, + BlockNoteBlockImitateSkeleton { inner: SoundStruct<'mc> }, + BlockNoteBlockImitateWitherSkeleton { inner: SoundStruct<'mc> }, + BlockNoteBlockImitateZombie { inner: SoundStruct<'mc> }, + BlockNoteBlockIronXylophone { inner: SoundStruct<'mc> }, + BlockNoteBlockPling { inner: SoundStruct<'mc> }, + BlockNoteBlockSnare { inner: SoundStruct<'mc> }, + BlockNoteBlockXylophone { inner: SoundStruct<'mc> }, + BlockNyliumBreak { inner: SoundStruct<'mc> }, + BlockNyliumFall { inner: SoundStruct<'mc> }, + BlockNyliumHit { inner: SoundStruct<'mc> }, + BlockNyliumPlace { inner: SoundStruct<'mc> }, + BlockNyliumStep { inner: SoundStruct<'mc> }, + BlockPackedMudBreak { inner: SoundStruct<'mc> }, + BlockPackedMudFall { inner: SoundStruct<'mc> }, + BlockPackedMudHit { inner: SoundStruct<'mc> }, + BlockPackedMudPlace { inner: SoundStruct<'mc> }, + BlockPackedMudStep { inner: SoundStruct<'mc> }, + BlockPinkPetalsBreak { inner: SoundStruct<'mc> }, + BlockPinkPetalsFall { inner: SoundStruct<'mc> }, + BlockPinkPetalsHit { inner: SoundStruct<'mc> }, + BlockPinkPetalsPlace { inner: SoundStruct<'mc> }, + BlockPinkPetalsStep { inner: SoundStruct<'mc> }, + BlockPistonContract { inner: SoundStruct<'mc> }, + BlockPistonExtend { inner: SoundStruct<'mc> }, + BlockPointedDripstoneBreak { inner: SoundStruct<'mc> }, + BlockPointedDripstoneDripLava { inner: SoundStruct<'mc> }, + BlockPointedDripstoneDripLavaIntoCauldron { inner: SoundStruct<'mc> }, + BlockPointedDripstoneDripWater { inner: SoundStruct<'mc> }, + BlockPointedDripstoneDripWaterIntoCauldron { inner: SoundStruct<'mc> }, + BlockPointedDripstoneFall { inner: SoundStruct<'mc> }, + BlockPointedDripstoneHit { inner: SoundStruct<'mc> }, + BlockPointedDripstoneLand { inner: SoundStruct<'mc> }, + BlockPointedDripstonePlace { inner: SoundStruct<'mc> }, + BlockPointedDripstoneStep { inner: SoundStruct<'mc> }, + BlockPolishedDeepslateBreak { inner: SoundStruct<'mc> }, + BlockPolishedDeepslateFall { inner: SoundStruct<'mc> }, + BlockPolishedDeepslateHit { inner: SoundStruct<'mc> }, + BlockPolishedDeepslatePlace { inner: SoundStruct<'mc> }, + BlockPolishedDeepslateStep { inner: SoundStruct<'mc> }, + BlockPolishedTuffBreak { inner: SoundStruct<'mc> }, + BlockPolishedTuffFall { inner: SoundStruct<'mc> }, + BlockPolishedTuffHit { inner: SoundStruct<'mc> }, + BlockPolishedTuffPlace { inner: SoundStruct<'mc> }, + BlockPolishedTuffStep { inner: SoundStruct<'mc> }, + BlockPortalAmbient { inner: SoundStruct<'mc> }, + BlockPortalTravel { inner: SoundStruct<'mc> }, + BlockPortalTrigger { inner: SoundStruct<'mc> }, + BlockPowderSnowBreak { inner: SoundStruct<'mc> }, + BlockPowderSnowFall { inner: SoundStruct<'mc> }, + BlockPowderSnowHit { inner: SoundStruct<'mc> }, + BlockPowderSnowPlace { inner: SoundStruct<'mc> }, + BlockPowderSnowStep { inner: SoundStruct<'mc> }, + BlockPumpkinCarve { inner: SoundStruct<'mc> }, + BlockRedstoneTorchBurnout { inner: SoundStruct<'mc> }, + BlockRespawnAnchorAmbient { inner: SoundStruct<'mc> }, + BlockRespawnAnchorCharge { inner: SoundStruct<'mc> }, + BlockRespawnAnchorDeplete { inner: SoundStruct<'mc> }, + BlockRespawnAnchorSetSpawn { inner: SoundStruct<'mc> }, + BlockRootedDirtBreak { inner: SoundStruct<'mc> }, + BlockRootedDirtFall { inner: SoundStruct<'mc> }, + BlockRootedDirtHit { inner: SoundStruct<'mc> }, + BlockRootedDirtPlace { inner: SoundStruct<'mc> }, + BlockRootedDirtStep { inner: SoundStruct<'mc> }, + BlockRootsBreak { inner: SoundStruct<'mc> }, + BlockRootsFall { inner: SoundStruct<'mc> }, + BlockRootsHit { inner: SoundStruct<'mc> }, + BlockRootsPlace { inner: SoundStruct<'mc> }, + BlockRootsStep { inner: SoundStruct<'mc> }, + BlockSandBreak { inner: SoundStruct<'mc> }, + BlockSandFall { inner: SoundStruct<'mc> }, + BlockSandHit { inner: SoundStruct<'mc> }, + BlockSandPlace { inner: SoundStruct<'mc> }, + BlockSandStep { inner: SoundStruct<'mc> }, + BlockScaffoldingBreak { inner: SoundStruct<'mc> }, + BlockScaffoldingFall { inner: SoundStruct<'mc> }, + BlockScaffoldingHit { inner: SoundStruct<'mc> }, + BlockScaffoldingPlace { inner: SoundStruct<'mc> }, + BlockScaffoldingStep { inner: SoundStruct<'mc> }, + BlockSculkBreak { inner: SoundStruct<'mc> }, + BlockSculkCatalystBloom { inner: SoundStruct<'mc> }, + BlockSculkCatalystBreak { inner: SoundStruct<'mc> }, + BlockSculkCatalystFall { inner: SoundStruct<'mc> }, + BlockSculkCatalystHit { inner: SoundStruct<'mc> }, + BlockSculkCatalystPlace { inner: SoundStruct<'mc> }, + BlockSculkCatalystStep { inner: SoundStruct<'mc> }, + BlockSculkCharge { inner: SoundStruct<'mc> }, + BlockSculkFall { inner: SoundStruct<'mc> }, + BlockSculkHit { inner: SoundStruct<'mc> }, + BlockSculkPlace { inner: SoundStruct<'mc> }, + BlockSculkSensorBreak { inner: SoundStruct<'mc> }, + BlockSculkSensorClicking { inner: SoundStruct<'mc> }, + BlockSculkSensorClickingStop { inner: SoundStruct<'mc> }, + BlockSculkSensorFall { inner: SoundStruct<'mc> }, + BlockSculkSensorHit { inner: SoundStruct<'mc> }, + BlockSculkSensorPlace { inner: SoundStruct<'mc> }, + BlockSculkSensorStep { inner: SoundStruct<'mc> }, + BlockSculkShriekerBreak { inner: SoundStruct<'mc> }, + BlockSculkShriekerFall { inner: SoundStruct<'mc> }, + BlockSculkShriekerHit { inner: SoundStruct<'mc> }, + BlockSculkShriekerPlace { inner: SoundStruct<'mc> }, + BlockSculkShriekerShriek { inner: SoundStruct<'mc> }, + BlockSculkShriekerStep { inner: SoundStruct<'mc> }, + BlockSculkSpread { inner: SoundStruct<'mc> }, + BlockSculkStep { inner: SoundStruct<'mc> }, + BlockSculkVeinBreak { inner: SoundStruct<'mc> }, + BlockSculkVeinFall { inner: SoundStruct<'mc> }, + BlockSculkVeinHit { inner: SoundStruct<'mc> }, + BlockSculkVeinPlace { inner: SoundStruct<'mc> }, + BlockSculkVeinStep { inner: SoundStruct<'mc> }, + BlockShroomlightBreak { inner: SoundStruct<'mc> }, + BlockShroomlightFall { inner: SoundStruct<'mc> }, + BlockShroomlightHit { inner: SoundStruct<'mc> }, + BlockShroomlightPlace { inner: SoundStruct<'mc> }, + BlockShroomlightStep { inner: SoundStruct<'mc> }, + BlockShulkerBoxClose { inner: SoundStruct<'mc> }, + BlockShulkerBoxOpen { inner: SoundStruct<'mc> }, + BlockSignWaxedInteractFail { inner: SoundStruct<'mc> }, + BlockSlimeBlockBreak { inner: SoundStruct<'mc> }, + BlockSlimeBlockFall { inner: SoundStruct<'mc> }, + BlockSlimeBlockHit { inner: SoundStruct<'mc> }, + BlockSlimeBlockPlace { inner: SoundStruct<'mc> }, + BlockSlimeBlockStep { inner: SoundStruct<'mc> }, + BlockSmallAmethystBudBreak { inner: SoundStruct<'mc> }, + BlockSmallAmethystBudPlace { inner: SoundStruct<'mc> }, + BlockSmallDripleafBreak { inner: SoundStruct<'mc> }, + BlockSmallDripleafFall { inner: SoundStruct<'mc> }, + BlockSmallDripleafHit { inner: SoundStruct<'mc> }, + BlockSmallDripleafPlace { inner: SoundStruct<'mc> }, + BlockSmallDripleafStep { inner: SoundStruct<'mc> }, + BlockSmithingTableUse { inner: SoundStruct<'mc> }, + BlockSmokerSmoke { inner: SoundStruct<'mc> }, + BlockSnifferEggCrack { inner: SoundStruct<'mc> }, + BlockSnifferEggHatch { inner: SoundStruct<'mc> }, + BlockSnifferEggPlop { inner: SoundStruct<'mc> }, + BlockSnowBreak { inner: SoundStruct<'mc> }, + BlockSnowFall { inner: SoundStruct<'mc> }, + BlockSnowHit { inner: SoundStruct<'mc> }, + BlockSnowPlace { inner: SoundStruct<'mc> }, + BlockSnowStep { inner: SoundStruct<'mc> }, + BlockSoulSandBreak { inner: SoundStruct<'mc> }, + BlockSoulSandFall { inner: SoundStruct<'mc> }, + BlockSoulSandHit { inner: SoundStruct<'mc> }, + BlockSoulSandPlace { inner: SoundStruct<'mc> }, + BlockSoulSandStep { inner: SoundStruct<'mc> }, + BlockSoulSoilBreak { inner: SoundStruct<'mc> }, + BlockSoulSoilFall { inner: SoundStruct<'mc> }, + BlockSoulSoilHit { inner: SoundStruct<'mc> }, + BlockSoulSoilPlace { inner: SoundStruct<'mc> }, + BlockSoulSoilStep { inner: SoundStruct<'mc> }, + BlockSpongeAbsorb { inner: SoundStruct<'mc> }, + BlockSpongeBreak { inner: SoundStruct<'mc> }, + BlockSpongeFall { inner: SoundStruct<'mc> }, + BlockSpongeHit { inner: SoundStruct<'mc> }, + BlockSpongePlace { inner: SoundStruct<'mc> }, + BlockSpongeStep { inner: SoundStruct<'mc> }, + BlockSporeBlossomBreak { inner: SoundStruct<'mc> }, + BlockSporeBlossomFall { inner: SoundStruct<'mc> }, + BlockSporeBlossomHit { inner: SoundStruct<'mc> }, + BlockSporeBlossomPlace { inner: SoundStruct<'mc> }, + BlockSporeBlossomStep { inner: SoundStruct<'mc> }, + BlockStemBreak { inner: SoundStruct<'mc> }, + BlockStemFall { inner: SoundStruct<'mc> }, + BlockStemHit { inner: SoundStruct<'mc> }, + BlockStemPlace { inner: SoundStruct<'mc> }, + BlockStemStep { inner: SoundStruct<'mc> }, + BlockStoneBreak { inner: SoundStruct<'mc> }, + BlockStoneButtonClickOff { inner: SoundStruct<'mc> }, + BlockStoneButtonClickOn { inner: SoundStruct<'mc> }, + BlockStoneFall { inner: SoundStruct<'mc> }, + BlockStoneHit { inner: SoundStruct<'mc> }, + BlockStonePlace { inner: SoundStruct<'mc> }, + BlockStonePressurePlateClickOff { inner: SoundStruct<'mc> }, + BlockStonePressurePlateClickOn { inner: SoundStruct<'mc> }, + BlockStoneStep { inner: SoundStruct<'mc> }, + BlockSuspiciousGravelBreak { inner: SoundStruct<'mc> }, + BlockSuspiciousGravelFall { inner: SoundStruct<'mc> }, + BlockSuspiciousGravelHit { inner: SoundStruct<'mc> }, + BlockSuspiciousGravelPlace { inner: SoundStruct<'mc> }, + BlockSuspiciousGravelStep { inner: SoundStruct<'mc> }, + BlockSuspiciousSandBreak { inner: SoundStruct<'mc> }, + BlockSuspiciousSandFall { inner: SoundStruct<'mc> }, + BlockSuspiciousSandHit { inner: SoundStruct<'mc> }, + BlockSuspiciousSandPlace { inner: SoundStruct<'mc> }, + BlockSuspiciousSandStep { inner: SoundStruct<'mc> }, + BlockSweetBerryBushBreak { inner: SoundStruct<'mc> }, + BlockSweetBerryBushPickBerries { inner: SoundStruct<'mc> }, + BlockSweetBerryBushPlace { inner: SoundStruct<'mc> }, + BlockTrialSpawnerAboutToSpawnItem { inner: SoundStruct<'mc> }, + BlockTrialSpawnerAmbient { inner: SoundStruct<'mc> }, + BlockTrialSpawnerAmbientOminous { inner: SoundStruct<'mc> }, + BlockTrialSpawnerBreak { inner: SoundStruct<'mc> }, + BlockTrialSpawnerCloseShutter { inner: SoundStruct<'mc> }, + BlockTrialSpawnerDetectPlayer { inner: SoundStruct<'mc> }, + BlockTrialSpawnerEjectItem { inner: SoundStruct<'mc> }, + BlockTrialSpawnerFall { inner: SoundStruct<'mc> }, + BlockTrialSpawnerHit { inner: SoundStruct<'mc> }, + BlockTrialSpawnerOminousActivate { inner: SoundStruct<'mc> }, + BlockTrialSpawnerOpenShutter { inner: SoundStruct<'mc> }, + BlockTrialSpawnerPlace { inner: SoundStruct<'mc> }, + BlockTrialSpawnerSpawnItem { inner: SoundStruct<'mc> }, + BlockTrialSpawnerSpawnItemBegin { inner: SoundStruct<'mc> }, + BlockTrialSpawnerSpawnMob { inner: SoundStruct<'mc> }, + BlockTrialSpawnerStep { inner: SoundStruct<'mc> }, + BlockTripwireAttach { inner: SoundStruct<'mc> }, + BlockTripwireClickOff { inner: SoundStruct<'mc> }, + BlockTripwireClickOn { inner: SoundStruct<'mc> }, + BlockTripwireDetach { inner: SoundStruct<'mc> }, + BlockTuffBreak { inner: SoundStruct<'mc> }, + BlockTuffBricksBreak { inner: SoundStruct<'mc> }, + BlockTuffBricksFall { inner: SoundStruct<'mc> }, + BlockTuffBricksHit { inner: SoundStruct<'mc> }, + BlockTuffBricksPlace { inner: SoundStruct<'mc> }, + BlockTuffBricksStep { inner: SoundStruct<'mc> }, + BlockTuffFall { inner: SoundStruct<'mc> }, + BlockTuffHit { inner: SoundStruct<'mc> }, + BlockTuffPlace { inner: SoundStruct<'mc> }, + BlockTuffStep { inner: SoundStruct<'mc> }, + BlockVaultActivate { inner: SoundStruct<'mc> }, + BlockVaultAmbient { inner: SoundStruct<'mc> }, + BlockVaultBreak { inner: SoundStruct<'mc> }, + BlockVaultCloseShutter { inner: SoundStruct<'mc> }, + BlockVaultDeactivate { inner: SoundStruct<'mc> }, + BlockVaultEjectItem { inner: SoundStruct<'mc> }, + BlockVaultFall { inner: SoundStruct<'mc> }, + BlockVaultHit { inner: SoundStruct<'mc> }, + BlockVaultInsertItem { inner: SoundStruct<'mc> }, + BlockVaultInsertItemFail { inner: SoundStruct<'mc> }, + BlockVaultOpenShutter { inner: SoundStruct<'mc> }, + BlockVaultPlace { inner: SoundStruct<'mc> }, + BlockVaultRejectRewardedPlayer { inner: SoundStruct<'mc> }, + BlockVaultStep { inner: SoundStruct<'mc> }, + BlockVineBreak { inner: SoundStruct<'mc> }, + BlockVineFall { inner: SoundStruct<'mc> }, + BlockVineHit { inner: SoundStruct<'mc> }, + BlockVinePlace { inner: SoundStruct<'mc> }, + BlockVineStep { inner: SoundStruct<'mc> }, + BlockWartBlockBreak { inner: SoundStruct<'mc> }, + BlockWartBlockFall { inner: SoundStruct<'mc> }, + BlockWartBlockHit { inner: SoundStruct<'mc> }, + BlockWartBlockPlace { inner: SoundStruct<'mc> }, + BlockWartBlockStep { inner: SoundStruct<'mc> }, + BlockWaterAmbient { inner: SoundStruct<'mc> }, + BlockWeepingVinesBreak { inner: SoundStruct<'mc> }, + BlockWeepingVinesFall { inner: SoundStruct<'mc> }, + BlockWeepingVinesHit { inner: SoundStruct<'mc> }, + BlockWeepingVinesPlace { inner: SoundStruct<'mc> }, + BlockWeepingVinesStep { inner: SoundStruct<'mc> }, + BlockWetGrassBreak { inner: SoundStruct<'mc> }, + BlockWetGrassFall { inner: SoundStruct<'mc> }, + BlockWetGrassHit { inner: SoundStruct<'mc> }, + BlockWetGrassPlace { inner: SoundStruct<'mc> }, + BlockWetGrassStep { inner: SoundStruct<'mc> }, + BlockWetSpongeBreak { inner: SoundStruct<'mc> }, + BlockWetSpongeDries { inner: SoundStruct<'mc> }, + BlockWetSpongeFall { inner: SoundStruct<'mc> }, + BlockWetSpongeHit { inner: SoundStruct<'mc> }, + BlockWetSpongePlace { inner: SoundStruct<'mc> }, + BlockWetSpongeStep { inner: SoundStruct<'mc> }, + BlockWoodenButtonClickOff { inner: SoundStruct<'mc> }, + BlockWoodenButtonClickOn { inner: SoundStruct<'mc> }, + BlockWoodenDoorClose { inner: SoundStruct<'mc> }, + BlockWoodenDoorOpen { inner: SoundStruct<'mc> }, + BlockWoodenPressurePlateClickOff { inner: SoundStruct<'mc> }, + BlockWoodenPressurePlateClickOn { inner: SoundStruct<'mc> }, + BlockWoodenTrapdoorClose { inner: SoundStruct<'mc> }, + BlockWoodenTrapdoorOpen { inner: SoundStruct<'mc> }, + BlockWoodBreak { inner: SoundStruct<'mc> }, + BlockWoodFall { inner: SoundStruct<'mc> }, + BlockWoodHit { inner: SoundStruct<'mc> }, + BlockWoodPlace { inner: SoundStruct<'mc> }, + BlockWoodStep { inner: SoundStruct<'mc> }, + BlockWoolBreak { inner: SoundStruct<'mc> }, + BlockWoolFall { inner: SoundStruct<'mc> }, + BlockWoolHit { inner: SoundStruct<'mc> }, + BlockWoolPlace { inner: SoundStruct<'mc> }, + BlockWoolStep { inner: SoundStruct<'mc> }, + EnchantThornsHit { inner: SoundStruct<'mc> }, + EntityAllayAmbientWithoutItem { inner: SoundStruct<'mc> }, + EntityAllayAmbientWithItem { inner: SoundStruct<'mc> }, + EntityAllayDeath { inner: SoundStruct<'mc> }, + EntityAllayHurt { inner: SoundStruct<'mc> }, + EntityAllayItemGiven { inner: SoundStruct<'mc> }, + EntityAllayItemTaken { inner: SoundStruct<'mc> }, + EntityAllayItemThrown { inner: SoundStruct<'mc> }, + EntityArmadilloAmbient { inner: SoundStruct<'mc> }, + EntityArmadilloBrush { inner: SoundStruct<'mc> }, + EntityArmadilloDeath { inner: SoundStruct<'mc> }, + EntityArmadilloEat { inner: SoundStruct<'mc> }, + EntityArmadilloHurt { inner: SoundStruct<'mc> }, + EntityArmadilloHurtReduced { inner: SoundStruct<'mc> }, + EntityArmadilloLand { inner: SoundStruct<'mc> }, + EntityArmadilloPeek { inner: SoundStruct<'mc> }, + EntityArmadilloRoll { inner: SoundStruct<'mc> }, + EntityArmadilloScuteDrop { inner: SoundStruct<'mc> }, + EntityArmadilloStep { inner: SoundStruct<'mc> }, + EntityArmadilloUnrollFinish { inner: SoundStruct<'mc> }, + EntityArmadilloUnrollStart { inner: SoundStruct<'mc> }, + EntityArmorStandBreak { inner: SoundStruct<'mc> }, + EntityArmorStandFall { inner: SoundStruct<'mc> }, + EntityArmorStandHit { inner: SoundStruct<'mc> }, + EntityArmorStandPlace { inner: SoundStruct<'mc> }, + EntityArrowHit { inner: SoundStruct<'mc> }, + EntityArrowHitPlayer { inner: SoundStruct<'mc> }, + EntityArrowShoot { inner: SoundStruct<'mc> }, + EntityAxolotlAttack { inner: SoundStruct<'mc> }, + EntityAxolotlDeath { inner: SoundStruct<'mc> }, + EntityAxolotlHurt { inner: SoundStruct<'mc> }, + EntityAxolotlIdleAir { inner: SoundStruct<'mc> }, + EntityAxolotlIdleWater { inner: SoundStruct<'mc> }, + EntityAxolotlSplash { inner: SoundStruct<'mc> }, + EntityAxolotlSwim { inner: SoundStruct<'mc> }, + EntityBatAmbient { inner: SoundStruct<'mc> }, + EntityBatDeath { inner: SoundStruct<'mc> }, + EntityBatHurt { inner: SoundStruct<'mc> }, + EntityBatLoop { inner: SoundStruct<'mc> }, + EntityBatTakeoff { inner: SoundStruct<'mc> }, + EntityBeeDeath { inner: SoundStruct<'mc> }, + EntityBeeHurt { inner: SoundStruct<'mc> }, + EntityBeeLoop { inner: SoundStruct<'mc> }, + EntityBeeLoopAggressive { inner: SoundStruct<'mc> }, + EntityBeePollinate { inner: SoundStruct<'mc> }, + EntityBeeSting { inner: SoundStruct<'mc> }, + EntityBlazeAmbient { inner: SoundStruct<'mc> }, + EntityBlazeBurn { inner: SoundStruct<'mc> }, + EntityBlazeDeath { inner: SoundStruct<'mc> }, + EntityBlazeHurt { inner: SoundStruct<'mc> }, + EntityBlazeShoot { inner: SoundStruct<'mc> }, + EntityBoatPaddleLand { inner: SoundStruct<'mc> }, + EntityBoatPaddleWater { inner: SoundStruct<'mc> }, + EntityBoggedAmbient { inner: SoundStruct<'mc> }, + EntityBoggedDeath { inner: SoundStruct<'mc> }, + EntityBoggedHurt { inner: SoundStruct<'mc> }, + EntityBoggedShear { inner: SoundStruct<'mc> }, + EntityBoggedStep { inner: SoundStruct<'mc> }, + EntityBreezeCharge { inner: SoundStruct<'mc> }, + EntityBreezeDeath { inner: SoundStruct<'mc> }, + EntityBreezeDeflect { inner: SoundStruct<'mc> }, + EntityBreezeHurt { inner: SoundStruct<'mc> }, + EntityBreezeIdleAir { inner: SoundStruct<'mc> }, + EntityBreezeIdleGround { inner: SoundStruct<'mc> }, + EntityBreezeInhale { inner: SoundStruct<'mc> }, + EntityBreezeJump { inner: SoundStruct<'mc> }, + EntityBreezeLand { inner: SoundStruct<'mc> }, + EntityBreezeShoot { inner: SoundStruct<'mc> }, + EntityBreezeSlide { inner: SoundStruct<'mc> }, + EntityBreezeWhirl { inner: SoundStruct<'mc> }, + EntityBreezeWindBurst { inner: SoundStruct<'mc> }, + EntityCamelAmbient { inner: SoundStruct<'mc> }, + EntityCamelDash { inner: SoundStruct<'mc> }, + EntityCamelDashReady { inner: SoundStruct<'mc> }, + EntityCamelDeath { inner: SoundStruct<'mc> }, + EntityCamelEat { inner: SoundStruct<'mc> }, + EntityCamelHurt { inner: SoundStruct<'mc> }, + EntityCamelSaddle { inner: SoundStruct<'mc> }, + EntityCamelSit { inner: SoundStruct<'mc> }, + EntityCamelStand { inner: SoundStruct<'mc> }, + EntityCamelStep { inner: SoundStruct<'mc> }, + EntityCamelStepSand { inner: SoundStruct<'mc> }, + EntityCatAmbient { inner: SoundStruct<'mc> }, + EntityCatBegForFood { inner: SoundStruct<'mc> }, + EntityCatDeath { inner: SoundStruct<'mc> }, + EntityCatEat { inner: SoundStruct<'mc> }, + EntityCatHiss { inner: SoundStruct<'mc> }, + EntityCatHurt { inner: SoundStruct<'mc> }, + EntityCatPurr { inner: SoundStruct<'mc> }, + EntityCatPurreow { inner: SoundStruct<'mc> }, + EntityCatStrayAmbient { inner: SoundStruct<'mc> }, + EntityChickenAmbient { inner: SoundStruct<'mc> }, + EntityChickenDeath { inner: SoundStruct<'mc> }, + EntityChickenEgg { inner: SoundStruct<'mc> }, + EntityChickenHurt { inner: SoundStruct<'mc> }, + EntityChickenStep { inner: SoundStruct<'mc> }, + EntityCodAmbient { inner: SoundStruct<'mc> }, + EntityCodDeath { inner: SoundStruct<'mc> }, + EntityCodFlop { inner: SoundStruct<'mc> }, + EntityCodHurt { inner: SoundStruct<'mc> }, + EntityCowAmbient { inner: SoundStruct<'mc> }, + EntityCowDeath { inner: SoundStruct<'mc> }, + EntityCowHurt { inner: SoundStruct<'mc> }, + EntityCowMilk { inner: SoundStruct<'mc> }, + EntityCowStep { inner: SoundStruct<'mc> }, + EntityCreeperDeath { inner: SoundStruct<'mc> }, + EntityCreeperHurt { inner: SoundStruct<'mc> }, + EntityCreeperPrimed { inner: SoundStruct<'mc> }, + EntityDolphinAmbient { inner: SoundStruct<'mc> }, + EntityDolphinAmbientWater { inner: SoundStruct<'mc> }, + EntityDolphinAttack { inner: SoundStruct<'mc> }, + EntityDolphinDeath { inner: SoundStruct<'mc> }, + EntityDolphinEat { inner: SoundStruct<'mc> }, + EntityDolphinHurt { inner: SoundStruct<'mc> }, + EntityDolphinJump { inner: SoundStruct<'mc> }, + EntityDolphinPlay { inner: SoundStruct<'mc> }, + EntityDolphinSplash { inner: SoundStruct<'mc> }, + EntityDolphinSwim { inner: SoundStruct<'mc> }, + EntityDonkeyAmbient { inner: SoundStruct<'mc> }, + EntityDonkeyAngry { inner: SoundStruct<'mc> }, + EntityDonkeyChest { inner: SoundStruct<'mc> }, + EntityDonkeyDeath { inner: SoundStruct<'mc> }, + EntityDonkeyEat { inner: SoundStruct<'mc> }, + EntityDonkeyHurt { inner: SoundStruct<'mc> }, + EntityDonkeyJump { inner: SoundStruct<'mc> }, + EntityDragonFireballExplode { inner: SoundStruct<'mc> }, + EntityDrownedAmbient { inner: SoundStruct<'mc> }, + EntityDrownedAmbientWater { inner: SoundStruct<'mc> }, + EntityDrownedDeath { inner: SoundStruct<'mc> }, + EntityDrownedDeathWater { inner: SoundStruct<'mc> }, + EntityDrownedHurt { inner: SoundStruct<'mc> }, + EntityDrownedHurtWater { inner: SoundStruct<'mc> }, + EntityDrownedShoot { inner: SoundStruct<'mc> }, + EntityDrownedStep { inner: SoundStruct<'mc> }, + EntityDrownedSwim { inner: SoundStruct<'mc> }, + EntityEggThrow { inner: SoundStruct<'mc> }, + EntityElderGuardianAmbient { inner: SoundStruct<'mc> }, + EntityElderGuardianAmbientLand { inner: SoundStruct<'mc> }, + EntityElderGuardianCurse { inner: SoundStruct<'mc> }, + EntityElderGuardianDeath { inner: SoundStruct<'mc> }, + EntityElderGuardianDeathLand { inner: SoundStruct<'mc> }, + EntityElderGuardianFlop { inner: SoundStruct<'mc> }, + EntityElderGuardianHurt { inner: SoundStruct<'mc> }, + EntityElderGuardianHurtLand { inner: SoundStruct<'mc> }, + EntityEndermanAmbient { inner: SoundStruct<'mc> }, + EntityEndermanDeath { inner: SoundStruct<'mc> }, + EntityEndermanHurt { inner: SoundStruct<'mc> }, + EntityEndermanScream { inner: SoundStruct<'mc> }, + EntityEndermanStare { inner: SoundStruct<'mc> }, + EntityEndermanTeleport { inner: SoundStruct<'mc> }, + EntityEndermiteAmbient { inner: SoundStruct<'mc> }, + EntityEndermiteDeath { inner: SoundStruct<'mc> }, + EntityEndermiteHurt { inner: SoundStruct<'mc> }, + EntityEndermiteStep { inner: SoundStruct<'mc> }, + EntityEnderDragonAmbient { inner: SoundStruct<'mc> }, + EntityEnderDragonDeath { inner: SoundStruct<'mc> }, + EntityEnderDragonFlap { inner: SoundStruct<'mc> }, + EntityEnderDragonGrowl { inner: SoundStruct<'mc> }, + EntityEnderDragonHurt { inner: SoundStruct<'mc> }, + EntityEnderDragonShoot { inner: SoundStruct<'mc> }, + EntityEnderEyeDeath { inner: SoundStruct<'mc> }, + EntityEnderEyeLaunch { inner: SoundStruct<'mc> }, + EntityEnderPearlThrow { inner: SoundStruct<'mc> }, + EntityEvokerAmbient { inner: SoundStruct<'mc> }, + EntityEvokerCastSpell { inner: SoundStruct<'mc> }, + EntityEvokerCelebrate { inner: SoundStruct<'mc> }, + EntityEvokerDeath { inner: SoundStruct<'mc> }, + EntityEvokerFangsAttack { inner: SoundStruct<'mc> }, + EntityEvokerHurt { inner: SoundStruct<'mc> }, + EntityEvokerPrepareAttack { inner: SoundStruct<'mc> }, + EntityEvokerPrepareSummon { inner: SoundStruct<'mc> }, + EntityEvokerPrepareWololo { inner: SoundStruct<'mc> }, + EntityExperienceBottleThrow { inner: SoundStruct<'mc> }, + EntityExperienceOrbPickup { inner: SoundStruct<'mc> }, + EntityFireworkRocketBlast { inner: SoundStruct<'mc> }, + EntityFireworkRocketBlastFar { inner: SoundStruct<'mc> }, + EntityFireworkRocketLargeBlast { inner: SoundStruct<'mc> }, + EntityFireworkRocketLargeBlastFar { inner: SoundStruct<'mc> }, + EntityFireworkRocketLaunch { inner: SoundStruct<'mc> }, + EntityFireworkRocketShoot { inner: SoundStruct<'mc> }, + EntityFireworkRocketTwinkle { inner: SoundStruct<'mc> }, + EntityFireworkRocketTwinkleFar { inner: SoundStruct<'mc> }, + EntityFishingBobberRetrieve { inner: SoundStruct<'mc> }, + EntityFishingBobberSplash { inner: SoundStruct<'mc> }, + EntityFishingBobberThrow { inner: SoundStruct<'mc> }, + EntityFishSwim { inner: SoundStruct<'mc> }, + EntityFoxAggro { inner: SoundStruct<'mc> }, + EntityFoxAmbient { inner: SoundStruct<'mc> }, + EntityFoxBite { inner: SoundStruct<'mc> }, + EntityFoxDeath { inner: SoundStruct<'mc> }, + EntityFoxEat { inner: SoundStruct<'mc> }, + EntityFoxHurt { inner: SoundStruct<'mc> }, + EntityFoxScreech { inner: SoundStruct<'mc> }, + EntityFoxSleep { inner: SoundStruct<'mc> }, + EntityFoxSniff { inner: SoundStruct<'mc> }, + EntityFoxSpit { inner: SoundStruct<'mc> }, + EntityFoxTeleport { inner: SoundStruct<'mc> }, + EntityFrogAmbient { inner: SoundStruct<'mc> }, + EntityFrogDeath { inner: SoundStruct<'mc> }, + EntityFrogEat { inner: SoundStruct<'mc> }, + EntityFrogHurt { inner: SoundStruct<'mc> }, + EntityFrogLaySpawn { inner: SoundStruct<'mc> }, + EntityFrogLongJump { inner: SoundStruct<'mc> }, + EntityFrogStep { inner: SoundStruct<'mc> }, + EntityFrogTongue { inner: SoundStruct<'mc> }, + EntityGenericBigFall { inner: SoundStruct<'mc> }, + EntityGenericBurn { inner: SoundStruct<'mc> }, + EntityGenericDeath { inner: SoundStruct<'mc> }, + EntityGenericDrink { inner: SoundStruct<'mc> }, + EntityGenericEat { inner: SoundStruct<'mc> }, + EntityGenericExplode { inner: SoundStruct<'mc> }, + EntityGenericExtinguishFire { inner: SoundStruct<'mc> }, + EntityGenericHurt { inner: SoundStruct<'mc> }, + EntityGenericSmallFall { inner: SoundStruct<'mc> }, + EntityGenericSplash { inner: SoundStruct<'mc> }, + EntityGenericSwim { inner: SoundStruct<'mc> }, + EntityGhastAmbient { inner: SoundStruct<'mc> }, + EntityGhastDeath { inner: SoundStruct<'mc> }, + EntityGhastHurt { inner: SoundStruct<'mc> }, + EntityGhastScream { inner: SoundStruct<'mc> }, + EntityGhastShoot { inner: SoundStruct<'mc> }, + EntityGhastWarn { inner: SoundStruct<'mc> }, + EntityGlowItemFrameAddItem { inner: SoundStruct<'mc> }, + EntityGlowItemFrameBreak { inner: SoundStruct<'mc> }, + EntityGlowItemFramePlace { inner: SoundStruct<'mc> }, + EntityGlowItemFrameRemoveItem { inner: SoundStruct<'mc> }, + EntityGlowItemFrameRotateItem { inner: SoundStruct<'mc> }, + EntityGlowSquidAmbient { inner: SoundStruct<'mc> }, + EntityGlowSquidDeath { inner: SoundStruct<'mc> }, + EntityGlowSquidHurt { inner: SoundStruct<'mc> }, + EntityGlowSquidSquirt { inner: SoundStruct<'mc> }, + EntityGoatAmbient { inner: SoundStruct<'mc> }, + EntityGoatDeath { inner: SoundStruct<'mc> }, + EntityGoatEat { inner: SoundStruct<'mc> }, + EntityGoatHornBreak { inner: SoundStruct<'mc> }, + EntityGoatHurt { inner: SoundStruct<'mc> }, + EntityGoatLongJump { inner: SoundStruct<'mc> }, + EntityGoatMilk { inner: SoundStruct<'mc> }, + EntityGoatPrepareRam { inner: SoundStruct<'mc> }, + EntityGoatRamImpact { inner: SoundStruct<'mc> }, + EntityGoatScreamingAmbient { inner: SoundStruct<'mc> }, + EntityGoatScreamingDeath { inner: SoundStruct<'mc> }, + EntityGoatScreamingEat { inner: SoundStruct<'mc> }, + EntityGoatScreamingHornBreak { inner: SoundStruct<'mc> }, + EntityGoatScreamingHurt { inner: SoundStruct<'mc> }, + EntityGoatScreamingLongJump { inner: SoundStruct<'mc> }, + EntityGoatScreamingMilk { inner: SoundStruct<'mc> }, + EntityGoatScreamingPrepareRam { inner: SoundStruct<'mc> }, + EntityGoatScreamingRamImpact { inner: SoundStruct<'mc> }, + EntityGoatStep { inner: SoundStruct<'mc> }, + EntityGuardianAmbient { inner: SoundStruct<'mc> }, + EntityGuardianAmbientLand { inner: SoundStruct<'mc> }, + EntityGuardianAttack { inner: SoundStruct<'mc> }, + EntityGuardianDeath { inner: SoundStruct<'mc> }, + EntityGuardianDeathLand { inner: SoundStruct<'mc> }, + EntityGuardianFlop { inner: SoundStruct<'mc> }, + EntityGuardianHurt { inner: SoundStruct<'mc> }, + EntityGuardianHurtLand { inner: SoundStruct<'mc> }, + EntityHoglinAmbient { inner: SoundStruct<'mc> }, + EntityHoglinAngry { inner: SoundStruct<'mc> }, + EntityHoglinAttack { inner: SoundStruct<'mc> }, + EntityHoglinConvertedToZombified { inner: SoundStruct<'mc> }, + EntityHoglinDeath { inner: SoundStruct<'mc> }, + EntityHoglinHurt { inner: SoundStruct<'mc> }, + EntityHoglinRetreat { inner: SoundStruct<'mc> }, + EntityHoglinStep { inner: SoundStruct<'mc> }, + EntityHorseAmbient { inner: SoundStruct<'mc> }, + EntityHorseAngry { inner: SoundStruct<'mc> }, + EntityHorseArmor { inner: SoundStruct<'mc> }, + EntityHorseBreathe { inner: SoundStruct<'mc> }, + EntityHorseDeath { inner: SoundStruct<'mc> }, + EntityHorseEat { inner: SoundStruct<'mc> }, + EntityHorseGallop { inner: SoundStruct<'mc> }, + EntityHorseHurt { inner: SoundStruct<'mc> }, + EntityHorseJump { inner: SoundStruct<'mc> }, + EntityHorseLand { inner: SoundStruct<'mc> }, + EntityHorseSaddle { inner: SoundStruct<'mc> }, + EntityHorseStep { inner: SoundStruct<'mc> }, + EntityHorseStepWood { inner: SoundStruct<'mc> }, + EntityHostileBigFall { inner: SoundStruct<'mc> }, + EntityHostileDeath { inner: SoundStruct<'mc> }, + EntityHostileHurt { inner: SoundStruct<'mc> }, + EntityHostileSmallFall { inner: SoundStruct<'mc> }, + EntityHostileSplash { inner: SoundStruct<'mc> }, + EntityHostileSwim { inner: SoundStruct<'mc> }, + EntityHuskAmbient { inner: SoundStruct<'mc> }, + EntityHuskConvertedToZombie { inner: SoundStruct<'mc> }, + EntityHuskDeath { inner: SoundStruct<'mc> }, + EntityHuskHurt { inner: SoundStruct<'mc> }, + EntityHuskStep { inner: SoundStruct<'mc> }, + EntityIllusionerAmbient { inner: SoundStruct<'mc> }, + EntityIllusionerCastSpell { inner: SoundStruct<'mc> }, + EntityIllusionerDeath { inner: SoundStruct<'mc> }, + EntityIllusionerHurt { inner: SoundStruct<'mc> }, + EntityIllusionerMirrorMove { inner: SoundStruct<'mc> }, + EntityIllusionerPrepareBlindness { inner: SoundStruct<'mc> }, + EntityIllusionerPrepareMirror { inner: SoundStruct<'mc> }, + EntityIronGolemAttack { inner: SoundStruct<'mc> }, + EntityIronGolemDamage { inner: SoundStruct<'mc> }, + EntityIronGolemDeath { inner: SoundStruct<'mc> }, + EntityIronGolemHurt { inner: SoundStruct<'mc> }, + EntityIronGolemRepair { inner: SoundStruct<'mc> }, + EntityIronGolemStep { inner: SoundStruct<'mc> }, + EntityItemBreak { inner: SoundStruct<'mc> }, + EntityItemFrameAddItem { inner: SoundStruct<'mc> }, + EntityItemFrameBreak { inner: SoundStruct<'mc> }, + EntityItemFramePlace { inner: SoundStruct<'mc> }, + EntityItemFrameRemoveItem { inner: SoundStruct<'mc> }, + EntityItemFrameRotateItem { inner: SoundStruct<'mc> }, + EntityItemPickup { inner: SoundStruct<'mc> }, + EntityLeashKnotBreak { inner: SoundStruct<'mc> }, + EntityLeashKnotPlace { inner: SoundStruct<'mc> }, + EntityLightningBoltImpact { inner: SoundStruct<'mc> }, + EntityLightningBoltThunder { inner: SoundStruct<'mc> }, + EntityLingeringPotionThrow { inner: SoundStruct<'mc> }, + EntityLlamaAmbient { inner: SoundStruct<'mc> }, + EntityLlamaAngry { inner: SoundStruct<'mc> }, + EntityLlamaChest { inner: SoundStruct<'mc> }, + EntityLlamaDeath { inner: SoundStruct<'mc> }, + EntityLlamaEat { inner: SoundStruct<'mc> }, + EntityLlamaHurt { inner: SoundStruct<'mc> }, + EntityLlamaSpit { inner: SoundStruct<'mc> }, + EntityLlamaStep { inner: SoundStruct<'mc> }, + EntityLlamaSwag { inner: SoundStruct<'mc> }, + EntityMagmaCubeDeath { inner: SoundStruct<'mc> }, + EntityMagmaCubeDeathSmall { inner: SoundStruct<'mc> }, + EntityMagmaCubeHurt { inner: SoundStruct<'mc> }, + EntityMagmaCubeHurtSmall { inner: SoundStruct<'mc> }, + EntityMagmaCubeJump { inner: SoundStruct<'mc> }, + EntityMagmaCubeSquish { inner: SoundStruct<'mc> }, + EntityMagmaCubeSquishSmall { inner: SoundStruct<'mc> }, + EntityMinecartInside { inner: SoundStruct<'mc> }, + EntityMinecartInsideUnderwater { inner: SoundStruct<'mc> }, + EntityMinecartRiding { inner: SoundStruct<'mc> }, + EntityMooshroomConvert { inner: SoundStruct<'mc> }, + EntityMooshroomEat { inner: SoundStruct<'mc> }, + EntityMooshroomMilk { inner: SoundStruct<'mc> }, + EntityMooshroomShear { inner: SoundStruct<'mc> }, + EntityMooshroomSuspiciousMilk { inner: SoundStruct<'mc> }, + EntityMuleAmbient { inner: SoundStruct<'mc> }, + EntityMuleAngry { inner: SoundStruct<'mc> }, + EntityMuleChest { inner: SoundStruct<'mc> }, + EntityMuleDeath { inner: SoundStruct<'mc> }, + EntityMuleEat { inner: SoundStruct<'mc> }, + EntityMuleHurt { inner: SoundStruct<'mc> }, + EntityMuleJump { inner: SoundStruct<'mc> }, + EntityOcelotAmbient { inner: SoundStruct<'mc> }, + EntityOcelotDeath { inner: SoundStruct<'mc> }, + EntityOcelotHurt { inner: SoundStruct<'mc> }, + EntityPaintingBreak { inner: SoundStruct<'mc> }, + EntityPaintingPlace { inner: SoundStruct<'mc> }, + EntityPandaAggressiveAmbient { inner: SoundStruct<'mc> }, + EntityPandaAmbient { inner: SoundStruct<'mc> }, + EntityPandaBite { inner: SoundStruct<'mc> }, + EntityPandaCantBreed { inner: SoundStruct<'mc> }, + EntityPandaDeath { inner: SoundStruct<'mc> }, + EntityPandaEat { inner: SoundStruct<'mc> }, + EntityPandaHurt { inner: SoundStruct<'mc> }, + EntityPandaPreSneeze { inner: SoundStruct<'mc> }, + EntityPandaSneeze { inner: SoundStruct<'mc> }, + EntityPandaStep { inner: SoundStruct<'mc> }, + EntityPandaWorriedAmbient { inner: SoundStruct<'mc> }, + EntityParrotAmbient { inner: SoundStruct<'mc> }, + EntityParrotDeath { inner: SoundStruct<'mc> }, + EntityParrotEat { inner: SoundStruct<'mc> }, + EntityParrotFly { inner: SoundStruct<'mc> }, + EntityParrotHurt { inner: SoundStruct<'mc> }, + EntityParrotImitateBlaze { inner: SoundStruct<'mc> }, + EntityParrotImitateBogged { inner: SoundStruct<'mc> }, + EntityParrotImitateBreeze { inner: SoundStruct<'mc> }, + EntityParrotImitateCreeper { inner: SoundStruct<'mc> }, + EntityParrotImitateDrowned { inner: SoundStruct<'mc> }, + EntityParrotImitateElderGuardian { inner: SoundStruct<'mc> }, + EntityParrotImitateEndermite { inner: SoundStruct<'mc> }, + EntityParrotImitateEnderDragon { inner: SoundStruct<'mc> }, + EntityParrotImitateEvoker { inner: SoundStruct<'mc> }, + EntityParrotImitateGhast { inner: SoundStruct<'mc> }, + EntityParrotImitateGuardian { inner: SoundStruct<'mc> }, + EntityParrotImitateHoglin { inner: SoundStruct<'mc> }, + EntityParrotImitateHusk { inner: SoundStruct<'mc> }, + EntityParrotImitateIllusioner { inner: SoundStruct<'mc> }, + EntityParrotImitateMagmaCube { inner: SoundStruct<'mc> }, + EntityParrotImitatePhantom { inner: SoundStruct<'mc> }, + EntityParrotImitatePiglin { inner: SoundStruct<'mc> }, + EntityParrotImitatePiglinBrute { inner: SoundStruct<'mc> }, + EntityParrotImitatePillager { inner: SoundStruct<'mc> }, + EntityParrotImitateRavager { inner: SoundStruct<'mc> }, + EntityParrotImitateShulker { inner: SoundStruct<'mc> }, + EntityParrotImitateSilverfish { inner: SoundStruct<'mc> }, + EntityParrotImitateSkeleton { inner: SoundStruct<'mc> }, + EntityParrotImitateSlime { inner: SoundStruct<'mc> }, + EntityParrotImitateSpider { inner: SoundStruct<'mc> }, + EntityParrotImitateStray { inner: SoundStruct<'mc> }, + EntityParrotImitateVex { inner: SoundStruct<'mc> }, + EntityParrotImitateVindicator { inner: SoundStruct<'mc> }, + EntityParrotImitateWarden { inner: SoundStruct<'mc> }, + EntityParrotImitateWitch { inner: SoundStruct<'mc> }, + EntityParrotImitateWither { inner: SoundStruct<'mc> }, + EntityParrotImitateWitherSkeleton { inner: SoundStruct<'mc> }, + EntityParrotImitateZoglin { inner: SoundStruct<'mc> }, + EntityParrotImitateZombie { inner: SoundStruct<'mc> }, + EntityParrotImitateZombieVillager { inner: SoundStruct<'mc> }, + EntityParrotStep { inner: SoundStruct<'mc> }, + EntityPhantomAmbient { inner: SoundStruct<'mc> }, + EntityPhantomBite { inner: SoundStruct<'mc> }, + EntityPhantomDeath { inner: SoundStruct<'mc> }, + EntityPhantomFlap { inner: SoundStruct<'mc> }, + EntityPhantomHurt { inner: SoundStruct<'mc> }, + EntityPhantomSwoop { inner: SoundStruct<'mc> }, + EntityPiglinAdmiringItem { inner: SoundStruct<'mc> }, + EntityPiglinAmbient { inner: SoundStruct<'mc> }, + EntityPiglinAngry { inner: SoundStruct<'mc> }, + EntityPiglinBruteAmbient { inner: SoundStruct<'mc> }, + EntityPiglinBruteAngry { inner: SoundStruct<'mc> }, + EntityPiglinBruteConvertedToZombified { inner: SoundStruct<'mc> }, + EntityPiglinBruteDeath { inner: SoundStruct<'mc> }, + EntityPiglinBruteHurt { inner: SoundStruct<'mc> }, + EntityPiglinBruteStep { inner: SoundStruct<'mc> }, + EntityPiglinCelebrate { inner: SoundStruct<'mc> }, + EntityPiglinConvertedToZombified { inner: SoundStruct<'mc> }, + EntityPiglinDeath { inner: SoundStruct<'mc> }, + EntityPiglinHurt { inner: SoundStruct<'mc> }, + EntityPiglinJealous { inner: SoundStruct<'mc> }, + EntityPiglinRetreat { inner: SoundStruct<'mc> }, + EntityPiglinStep { inner: SoundStruct<'mc> }, + EntityPigAmbient { inner: SoundStruct<'mc> }, + EntityPigDeath { inner: SoundStruct<'mc> }, + EntityPigHurt { inner: SoundStruct<'mc> }, + EntityPigSaddle { inner: SoundStruct<'mc> }, + EntityPigStep { inner: SoundStruct<'mc> }, + EntityPillagerAmbient { inner: SoundStruct<'mc> }, + EntityPillagerCelebrate { inner: SoundStruct<'mc> }, + EntityPillagerDeath { inner: SoundStruct<'mc> }, + EntityPillagerHurt { inner: SoundStruct<'mc> }, + EntityPlayerAttackCrit { inner: SoundStruct<'mc> }, + EntityPlayerAttackKnockback { inner: SoundStruct<'mc> }, + EntityPlayerAttackNodamage { inner: SoundStruct<'mc> }, + EntityPlayerAttackStrong { inner: SoundStruct<'mc> }, + EntityPlayerAttackSweep { inner: SoundStruct<'mc> }, + EntityPlayerAttackWeak { inner: SoundStruct<'mc> }, + EntityPlayerBigFall { inner: SoundStruct<'mc> }, + EntityPlayerBreath { inner: SoundStruct<'mc> }, + EntityPlayerBurp { inner: SoundStruct<'mc> }, + EntityPlayerDeath { inner: SoundStruct<'mc> }, + EntityPlayerHurt { inner: SoundStruct<'mc> }, + EntityPlayerHurtDrown { inner: SoundStruct<'mc> }, + EntityPlayerHurtFreeze { inner: SoundStruct<'mc> }, + EntityPlayerHurtOnFire { inner: SoundStruct<'mc> }, + EntityPlayerHurtSweetBerryBush { inner: SoundStruct<'mc> }, + EntityPlayerLevelup { inner: SoundStruct<'mc> }, + EntityPlayerSmallFall { inner: SoundStruct<'mc> }, + EntityPlayerSplash { inner: SoundStruct<'mc> }, + EntityPlayerSplashHighSpeed { inner: SoundStruct<'mc> }, + EntityPlayerSwim { inner: SoundStruct<'mc> }, + EntityPlayerTeleport { inner: SoundStruct<'mc> }, + EntityPolarBearAmbient { inner: SoundStruct<'mc> }, + EntityPolarBearAmbientBaby { inner: SoundStruct<'mc> }, + EntityPolarBearDeath { inner: SoundStruct<'mc> }, + EntityPolarBearHurt { inner: SoundStruct<'mc> }, + EntityPolarBearStep { inner: SoundStruct<'mc> }, + EntityPolarBearWarning { inner: SoundStruct<'mc> }, + EntityPufferFishAmbient { inner: SoundStruct<'mc> }, + EntityPufferFishBlowOut { inner: SoundStruct<'mc> }, + EntityPufferFishBlowUp { inner: SoundStruct<'mc> }, + EntityPufferFishDeath { inner: SoundStruct<'mc> }, + EntityPufferFishFlop { inner: SoundStruct<'mc> }, + EntityPufferFishHurt { inner: SoundStruct<'mc> }, + EntityPufferFishSting { inner: SoundStruct<'mc> }, + EntityRabbitAmbient { inner: SoundStruct<'mc> }, + EntityRabbitAttack { inner: SoundStruct<'mc> }, + EntityRabbitDeath { inner: SoundStruct<'mc> }, + EntityRabbitHurt { inner: SoundStruct<'mc> }, + EntityRabbitJump { inner: SoundStruct<'mc> }, + EntityRavagerAmbient { inner: SoundStruct<'mc> }, + EntityRavagerAttack { inner: SoundStruct<'mc> }, + EntityRavagerCelebrate { inner: SoundStruct<'mc> }, + EntityRavagerDeath { inner: SoundStruct<'mc> }, + EntityRavagerHurt { inner: SoundStruct<'mc> }, + EntityRavagerRoar { inner: SoundStruct<'mc> }, + EntityRavagerStep { inner: SoundStruct<'mc> }, + EntityRavagerStunned { inner: SoundStruct<'mc> }, + EntitySalmonAmbient { inner: SoundStruct<'mc> }, + EntitySalmonDeath { inner: SoundStruct<'mc> }, + EntitySalmonFlop { inner: SoundStruct<'mc> }, + EntitySalmonHurt { inner: SoundStruct<'mc> }, + EntitySheepAmbient { inner: SoundStruct<'mc> }, + EntitySheepDeath { inner: SoundStruct<'mc> }, + EntitySheepHurt { inner: SoundStruct<'mc> }, + EntitySheepShear { inner: SoundStruct<'mc> }, + EntitySheepStep { inner: SoundStruct<'mc> }, + EntityShulkerAmbient { inner: SoundStruct<'mc> }, + EntityShulkerBulletHit { inner: SoundStruct<'mc> }, + EntityShulkerBulletHurt { inner: SoundStruct<'mc> }, + EntityShulkerClose { inner: SoundStruct<'mc> }, + EntityShulkerDeath { inner: SoundStruct<'mc> }, + EntityShulkerHurt { inner: SoundStruct<'mc> }, + EntityShulkerHurtClosed { inner: SoundStruct<'mc> }, + EntityShulkerOpen { inner: SoundStruct<'mc> }, + EntityShulkerShoot { inner: SoundStruct<'mc> }, + EntityShulkerTeleport { inner: SoundStruct<'mc> }, + EntitySilverfishAmbient { inner: SoundStruct<'mc> }, + EntitySilverfishDeath { inner: SoundStruct<'mc> }, + EntitySilverfishHurt { inner: SoundStruct<'mc> }, + EntitySilverfishStep { inner: SoundStruct<'mc> }, + EntitySkeletonAmbient { inner: SoundStruct<'mc> }, + EntitySkeletonConvertedToStray { inner: SoundStruct<'mc> }, + EntitySkeletonDeath { inner: SoundStruct<'mc> }, + EntitySkeletonHorseAmbient { inner: SoundStruct<'mc> }, + EntitySkeletonHorseAmbientWater { inner: SoundStruct<'mc> }, + EntitySkeletonHorseDeath { inner: SoundStruct<'mc> }, + EntitySkeletonHorseGallopWater { inner: SoundStruct<'mc> }, + EntitySkeletonHorseHurt { inner: SoundStruct<'mc> }, + EntitySkeletonHorseJumpWater { inner: SoundStruct<'mc> }, + EntitySkeletonHorseStepWater { inner: SoundStruct<'mc> }, + EntitySkeletonHorseSwim { inner: SoundStruct<'mc> }, + EntitySkeletonHurt { inner: SoundStruct<'mc> }, + EntitySkeletonShoot { inner: SoundStruct<'mc> }, + EntitySkeletonStep { inner: SoundStruct<'mc> }, + EntitySlimeAttack { inner: SoundStruct<'mc> }, + EntitySlimeDeath { inner: SoundStruct<'mc> }, + EntitySlimeDeathSmall { inner: SoundStruct<'mc> }, + EntitySlimeHurt { inner: SoundStruct<'mc> }, + EntitySlimeHurtSmall { inner: SoundStruct<'mc> }, + EntitySlimeJump { inner: SoundStruct<'mc> }, + EntitySlimeJumpSmall { inner: SoundStruct<'mc> }, + EntitySlimeSquish { inner: SoundStruct<'mc> }, + EntitySlimeSquishSmall { inner: SoundStruct<'mc> }, + EntitySnifferDeath { inner: SoundStruct<'mc> }, + EntitySnifferDigging { inner: SoundStruct<'mc> }, + EntitySnifferDiggingStop { inner: SoundStruct<'mc> }, + EntitySnifferDropSeed { inner: SoundStruct<'mc> }, + EntitySnifferEat { inner: SoundStruct<'mc> }, + EntitySnifferHappy { inner: SoundStruct<'mc> }, + EntitySnifferHurt { inner: SoundStruct<'mc> }, + EntitySnifferIdle { inner: SoundStruct<'mc> }, + EntitySnifferScenting { inner: SoundStruct<'mc> }, + EntitySnifferSearching { inner: SoundStruct<'mc> }, + EntitySnifferSniffing { inner: SoundStruct<'mc> }, + EntitySnifferStep { inner: SoundStruct<'mc> }, + EntitySnowballThrow { inner: SoundStruct<'mc> }, + EntitySnowGolemAmbient { inner: SoundStruct<'mc> }, + EntitySnowGolemDeath { inner: SoundStruct<'mc> }, + EntitySnowGolemHurt { inner: SoundStruct<'mc> }, + EntitySnowGolemShear { inner: SoundStruct<'mc> }, + EntitySnowGolemShoot { inner: SoundStruct<'mc> }, + EntitySpiderAmbient { inner: SoundStruct<'mc> }, + EntitySpiderDeath { inner: SoundStruct<'mc> }, + EntitySpiderHurt { inner: SoundStruct<'mc> }, + EntitySpiderStep { inner: SoundStruct<'mc> }, + EntitySplashPotionBreak { inner: SoundStruct<'mc> }, + EntitySplashPotionThrow { inner: SoundStruct<'mc> }, + EntitySquidAmbient { inner: SoundStruct<'mc> }, + EntitySquidDeath { inner: SoundStruct<'mc> }, + EntitySquidHurt { inner: SoundStruct<'mc> }, + EntitySquidSquirt { inner: SoundStruct<'mc> }, + EntityStrayAmbient { inner: SoundStruct<'mc> }, + EntityStrayDeath { inner: SoundStruct<'mc> }, + EntityStrayHurt { inner: SoundStruct<'mc> }, + EntityStrayStep { inner: SoundStruct<'mc> }, + EntityStriderAmbient { inner: SoundStruct<'mc> }, + EntityStriderDeath { inner: SoundStruct<'mc> }, + EntityStriderEat { inner: SoundStruct<'mc> }, + EntityStriderHappy { inner: SoundStruct<'mc> }, + EntityStriderHurt { inner: SoundStruct<'mc> }, + EntityStriderRetreat { inner: SoundStruct<'mc> }, + EntityStriderSaddle { inner: SoundStruct<'mc> }, + EntityStriderStep { inner: SoundStruct<'mc> }, + EntityStriderStepLava { inner: SoundStruct<'mc> }, + EntityTadpoleDeath { inner: SoundStruct<'mc> }, + EntityTadpoleFlop { inner: SoundStruct<'mc> }, + EntityTadpoleGrowUp { inner: SoundStruct<'mc> }, + EntityTadpoleHurt { inner: SoundStruct<'mc> }, + EntityTntPrimed { inner: SoundStruct<'mc> }, + EntityTropicalFishAmbient { inner: SoundStruct<'mc> }, + EntityTropicalFishDeath { inner: SoundStruct<'mc> }, + EntityTropicalFishFlop { inner: SoundStruct<'mc> }, + EntityTropicalFishHurt { inner: SoundStruct<'mc> }, + EntityTurtleAmbientLand { inner: SoundStruct<'mc> }, + EntityTurtleDeath { inner: SoundStruct<'mc> }, + EntityTurtleDeathBaby { inner: SoundStruct<'mc> }, + EntityTurtleEggBreak { inner: SoundStruct<'mc> }, + EntityTurtleEggCrack { inner: SoundStruct<'mc> }, + EntityTurtleEggHatch { inner: SoundStruct<'mc> }, + EntityTurtleHurt { inner: SoundStruct<'mc> }, + EntityTurtleHurtBaby { inner: SoundStruct<'mc> }, + EntityTurtleLayEgg { inner: SoundStruct<'mc> }, + EntityTurtleShamble { inner: SoundStruct<'mc> }, + EntityTurtleShambleBaby { inner: SoundStruct<'mc> }, + EntityTurtleSwim { inner: SoundStruct<'mc> }, + EntityVexAmbient { inner: SoundStruct<'mc> }, + EntityVexCharge { inner: SoundStruct<'mc> }, + EntityVexDeath { inner: SoundStruct<'mc> }, + EntityVexHurt { inner: SoundStruct<'mc> }, + EntityVillagerAmbient { inner: SoundStruct<'mc> }, + EntityVillagerCelebrate { inner: SoundStruct<'mc> }, + EntityVillagerDeath { inner: SoundStruct<'mc> }, + EntityVillagerHurt { inner: SoundStruct<'mc> }, + EntityVillagerNo { inner: SoundStruct<'mc> }, + EntityVillagerTrade { inner: SoundStruct<'mc> }, + EntityVillagerWorkArmorer { inner: SoundStruct<'mc> }, + EntityVillagerWorkButcher { inner: SoundStruct<'mc> }, + EntityVillagerWorkCartographer { inner: SoundStruct<'mc> }, + EntityVillagerWorkCleric { inner: SoundStruct<'mc> }, + EntityVillagerWorkFarmer { inner: SoundStruct<'mc> }, + EntityVillagerWorkFisherman { inner: SoundStruct<'mc> }, + EntityVillagerWorkFletcher { inner: SoundStruct<'mc> }, + EntityVillagerWorkLeatherworker { inner: SoundStruct<'mc> }, + EntityVillagerWorkLibrarian { inner: SoundStruct<'mc> }, + EntityVillagerWorkMason { inner: SoundStruct<'mc> }, + EntityVillagerWorkShepherd { inner: SoundStruct<'mc> }, + EntityVillagerWorkToolsmith { inner: SoundStruct<'mc> }, + EntityVillagerWorkWeaponsmith { inner: SoundStruct<'mc> }, + EntityVillagerYes { inner: SoundStruct<'mc> }, + EntityVindicatorAmbient { inner: SoundStruct<'mc> }, + EntityVindicatorCelebrate { inner: SoundStruct<'mc> }, + EntityVindicatorDeath { inner: SoundStruct<'mc> }, + EntityVindicatorHurt { inner: SoundStruct<'mc> }, + EntityWanderingTraderAmbient { inner: SoundStruct<'mc> }, + EntityWanderingTraderDeath { inner: SoundStruct<'mc> }, + EntityWanderingTraderDisappeared { inner: SoundStruct<'mc> }, + EntityWanderingTraderDrinkMilk { inner: SoundStruct<'mc> }, + EntityWanderingTraderDrinkPotion { inner: SoundStruct<'mc> }, + EntityWanderingTraderHurt { inner: SoundStruct<'mc> }, + EntityWanderingTraderNo { inner: SoundStruct<'mc> }, + EntityWanderingTraderReappeared { inner: SoundStruct<'mc> }, + EntityWanderingTraderTrade { inner: SoundStruct<'mc> }, + EntityWanderingTraderYes { inner: SoundStruct<'mc> }, + EntityWardenAgitated { inner: SoundStruct<'mc> }, + EntityWardenAmbient { inner: SoundStruct<'mc> }, + EntityWardenAngry { inner: SoundStruct<'mc> }, + EntityWardenAttackImpact { inner: SoundStruct<'mc> }, + EntityWardenDeath { inner: SoundStruct<'mc> }, + EntityWardenDig { inner: SoundStruct<'mc> }, + EntityWardenEmerge { inner: SoundStruct<'mc> }, + EntityWardenHeartbeat { inner: SoundStruct<'mc> }, + EntityWardenHurt { inner: SoundStruct<'mc> }, + EntityWardenListening { inner: SoundStruct<'mc> }, + EntityWardenListeningAngry { inner: SoundStruct<'mc> }, + EntityWardenNearbyClose { inner: SoundStruct<'mc> }, + EntityWardenNearbyCloser { inner: SoundStruct<'mc> }, + EntityWardenNearbyClosest { inner: SoundStruct<'mc> }, + EntityWardenRoar { inner: SoundStruct<'mc> }, + EntityWardenSniff { inner: SoundStruct<'mc> }, + EntityWardenSonicBoom { inner: SoundStruct<'mc> }, + EntityWardenSonicCharge { inner: SoundStruct<'mc> }, + EntityWardenStep { inner: SoundStruct<'mc> }, + EntityWardenTendrilClicks { inner: SoundStruct<'mc> }, + EntityWindChargeThrow { inner: SoundStruct<'mc> }, + EntityWindChargeWindBurst { inner: SoundStruct<'mc> }, + EntityWitchAmbient { inner: SoundStruct<'mc> }, + EntityWitchCelebrate { inner: SoundStruct<'mc> }, + EntityWitchDeath { inner: SoundStruct<'mc> }, + EntityWitchDrink { inner: SoundStruct<'mc> }, + EntityWitchHurt { inner: SoundStruct<'mc> }, + EntityWitchThrow { inner: SoundStruct<'mc> }, + EntityWitherAmbient { inner: SoundStruct<'mc> }, + EntityWitherBreakBlock { inner: SoundStruct<'mc> }, + EntityWitherDeath { inner: SoundStruct<'mc> }, + EntityWitherHurt { inner: SoundStruct<'mc> }, + EntityWitherShoot { inner: SoundStruct<'mc> }, + EntityWitherSkeletonAmbient { inner: SoundStruct<'mc> }, + EntityWitherSkeletonDeath { inner: SoundStruct<'mc> }, + EntityWitherSkeletonHurt { inner: SoundStruct<'mc> }, + EntityWitherSkeletonStep { inner: SoundStruct<'mc> }, + EntityWitherSpawn { inner: SoundStruct<'mc> }, + EntityWolfAmbient { inner: SoundStruct<'mc> }, + EntityWolfDeath { inner: SoundStruct<'mc> }, + EntityWolfGrowl { inner: SoundStruct<'mc> }, + EntityWolfHowl { inner: SoundStruct<'mc> }, + EntityWolfHurt { inner: SoundStruct<'mc> }, + EntityWolfPant { inner: SoundStruct<'mc> }, + EntityWolfShake { inner: SoundStruct<'mc> }, + EntityWolfStep { inner: SoundStruct<'mc> }, + EntityWolfWhine { inner: SoundStruct<'mc> }, + EntityZoglinAmbient { inner: SoundStruct<'mc> }, + EntityZoglinAngry { inner: SoundStruct<'mc> }, + EntityZoglinAttack { inner: SoundStruct<'mc> }, + EntityZoglinDeath { inner: SoundStruct<'mc> }, + EntityZoglinHurt { inner: SoundStruct<'mc> }, + EntityZoglinStep { inner: SoundStruct<'mc> }, + EntityZombieAmbient { inner: SoundStruct<'mc> }, + EntityZombieAttackIronDoor { inner: SoundStruct<'mc> }, + EntityZombieAttackWoodenDoor { inner: SoundStruct<'mc> }, + EntityZombieBreakWoodenDoor { inner: SoundStruct<'mc> }, + EntityZombieConvertedToDrowned { inner: SoundStruct<'mc> }, + EntityZombieDeath { inner: SoundStruct<'mc> }, + EntityZombieDestroyEgg { inner: SoundStruct<'mc> }, + EntityZombieHorseAmbient { inner: SoundStruct<'mc> }, + EntityZombieHorseDeath { inner: SoundStruct<'mc> }, + EntityZombieHorseHurt { inner: SoundStruct<'mc> }, + EntityZombieHurt { inner: SoundStruct<'mc> }, + EntityZombieInfect { inner: SoundStruct<'mc> }, + EntityZombieStep { inner: SoundStruct<'mc> }, + EntityZombieVillagerAmbient { inner: SoundStruct<'mc> }, + EntityZombieVillagerConverted { inner: SoundStruct<'mc> }, + EntityZombieVillagerCure { inner: SoundStruct<'mc> }, + EntityZombieVillagerDeath { inner: SoundStruct<'mc> }, + EntityZombieVillagerHurt { inner: SoundStruct<'mc> }, + EntityZombieVillagerStep { inner: SoundStruct<'mc> }, + EntityZombifiedPiglinAmbient { inner: SoundStruct<'mc> }, + EntityZombifiedPiglinAngry { inner: SoundStruct<'mc> }, + EntityZombifiedPiglinDeath { inner: SoundStruct<'mc> }, + EntityZombifiedPiglinHurt { inner: SoundStruct<'mc> }, + EventMobEffectBadOmen { inner: SoundStruct<'mc> }, + EventMobEffectRaidOmen { inner: SoundStruct<'mc> }, + EventMobEffectTrialOmen { inner: SoundStruct<'mc> }, + EventRaidHorn { inner: SoundStruct<'mc> }, + IntentionallyEmpty { inner: SoundStruct<'mc> }, + ItemArmorEquipChain { inner: SoundStruct<'mc> }, + ItemArmorEquipDiamond { inner: SoundStruct<'mc> }, + ItemArmorEquipElytra { inner: SoundStruct<'mc> }, + ItemArmorEquipGeneric { inner: SoundStruct<'mc> }, + ItemArmorEquipGold { inner: SoundStruct<'mc> }, + ItemArmorEquipIron { inner: SoundStruct<'mc> }, + ItemArmorEquipLeather { inner: SoundStruct<'mc> }, + ItemArmorEquipNetherite { inner: SoundStruct<'mc> }, + ItemArmorEquipTurtle { inner: SoundStruct<'mc> }, + ItemArmorEquipWolf { inner: SoundStruct<'mc> }, + ItemArmorUnequipWolf { inner: SoundStruct<'mc> }, + ItemAxeScrape { inner: SoundStruct<'mc> }, + ItemAxeStrip { inner: SoundStruct<'mc> }, + ItemAxeWaxOff { inner: SoundStruct<'mc> }, + ItemBoneMealUse { inner: SoundStruct<'mc> }, + ItemBookPageTurn { inner: SoundStruct<'mc> }, + ItemBookPut { inner: SoundStruct<'mc> }, + ItemBottleEmpty { inner: SoundStruct<'mc> }, + ItemBottleFill { inner: SoundStruct<'mc> }, + ItemBottleFillDragonbreath { inner: SoundStruct<'mc> }, + ItemBrushBrushingGeneric { inner: SoundStruct<'mc> }, + ItemBrushBrushingGravel { inner: SoundStruct<'mc> }, + ItemBrushBrushingGravelComplete { inner: SoundStruct<'mc> }, + ItemBrushBrushingSand { inner: SoundStruct<'mc> }, + ItemBrushBrushingSandComplete { inner: SoundStruct<'mc> }, + ItemBucketEmpty { inner: SoundStruct<'mc> }, + ItemBucketEmptyAxolotl { inner: SoundStruct<'mc> }, + ItemBucketEmptyFish { inner: SoundStruct<'mc> }, + ItemBucketEmptyLava { inner: SoundStruct<'mc> }, + ItemBucketEmptyPowderSnow { inner: SoundStruct<'mc> }, + ItemBucketEmptyTadpole { inner: SoundStruct<'mc> }, + ItemBucketFill { inner: SoundStruct<'mc> }, + ItemBucketFillAxolotl { inner: SoundStruct<'mc> }, + ItemBucketFillFish { inner: SoundStruct<'mc> }, + ItemBucketFillLava { inner: SoundStruct<'mc> }, + ItemBucketFillPowderSnow { inner: SoundStruct<'mc> }, + ItemBucketFillTadpole { inner: SoundStruct<'mc> }, + ItemBundleDropContents { inner: SoundStruct<'mc> }, + ItemBundleInsert { inner: SoundStruct<'mc> }, + ItemBundleRemoveOne { inner: SoundStruct<'mc> }, + ItemChorusFruitTeleport { inner: SoundStruct<'mc> }, + ItemCropPlant { inner: SoundStruct<'mc> }, + ItemCrossbowHit { inner: SoundStruct<'mc> }, + ItemCrossbowLoadingEnd { inner: SoundStruct<'mc> }, + ItemCrossbowLoadingMiddle { inner: SoundStruct<'mc> }, + ItemCrossbowLoadingStart { inner: SoundStruct<'mc> }, + ItemCrossbowQuickCharge1 { inner: SoundStruct<'mc> }, + ItemCrossbowQuickCharge2 { inner: SoundStruct<'mc> }, + ItemCrossbowQuickCharge3 { inner: SoundStruct<'mc> }, + ItemCrossbowShoot { inner: SoundStruct<'mc> }, + ItemDyeUse { inner: SoundStruct<'mc> }, + ItemElytraFlying { inner: SoundStruct<'mc> }, + ItemFirechargeUse { inner: SoundStruct<'mc> }, + ItemFlintandsteelUse { inner: SoundStruct<'mc> }, + ItemGlowInkSacUse { inner: SoundStruct<'mc> }, + ItemGoatHornPlay { inner: SoundStruct<'mc> }, + ItemGoatHornSound0 { inner: SoundStruct<'mc> }, + ItemGoatHornSound1 { inner: SoundStruct<'mc> }, + ItemGoatHornSound2 { inner: SoundStruct<'mc> }, + ItemGoatHornSound3 { inner: SoundStruct<'mc> }, + ItemGoatHornSound4 { inner: SoundStruct<'mc> }, + ItemGoatHornSound5 { inner: SoundStruct<'mc> }, + ItemGoatHornSound6 { inner: SoundStruct<'mc> }, + ItemGoatHornSound7 { inner: SoundStruct<'mc> }, + ItemHoeTill { inner: SoundStruct<'mc> }, + ItemHoneycombWaxOn { inner: SoundStruct<'mc> }, + ItemHoneyBottleDrink { inner: SoundStruct<'mc> }, + ItemInkSacUse { inner: SoundStruct<'mc> }, + ItemLodestoneCompassLock { inner: SoundStruct<'mc> }, + ItemMaceSmashAir { inner: SoundStruct<'mc> }, + ItemMaceSmashGround { inner: SoundStruct<'mc> }, + ItemMaceSmashGroundHeavy { inner: SoundStruct<'mc> }, + ItemNetherWartPlant { inner: SoundStruct<'mc> }, + ItemOminousBottleDispose { inner: SoundStruct<'mc> }, + ItemShieldBlock { inner: SoundStruct<'mc> }, + ItemShieldBreak { inner: SoundStruct<'mc> }, + ItemShovelFlatten { inner: SoundStruct<'mc> }, + ItemSpyglassStopUsing { inner: SoundStruct<'mc> }, + ItemSpyglassUse { inner: SoundStruct<'mc> }, + ItemTotemUse { inner: SoundStruct<'mc> }, + ItemTridentHit { inner: SoundStruct<'mc> }, + ItemTridentHitGround { inner: SoundStruct<'mc> }, + ItemTridentReturn { inner: SoundStruct<'mc> }, + ItemTridentRiptide1 { inner: SoundStruct<'mc> }, + ItemTridentRiptide2 { inner: SoundStruct<'mc> }, + ItemTridentRiptide3 { inner: SoundStruct<'mc> }, + ItemTridentThrow { inner: SoundStruct<'mc> }, + ItemTridentThunder { inner: SoundStruct<'mc> }, + ItemWolfArmorBreak { inner: SoundStruct<'mc> }, + ItemWolfArmorCrack { inner: SoundStruct<'mc> }, + ItemWolfArmorDamage { inner: SoundStruct<'mc> }, + ItemWolfArmorRepair { inner: SoundStruct<'mc> }, + MusicCreative { inner: SoundStruct<'mc> }, + MusicCredits { inner: SoundStruct<'mc> }, + MusicDisc11 { inner: SoundStruct<'mc> }, + MusicDisc13 { inner: SoundStruct<'mc> }, + MusicDisc5 { inner: SoundStruct<'mc> }, + MusicDiscBlocks { inner: SoundStruct<'mc> }, + MusicDiscCat { inner: SoundStruct<'mc> }, + MusicDiscChirp { inner: SoundStruct<'mc> }, + MusicDiscCreator { inner: SoundStruct<'mc> }, + MusicDiscCreatorMusicBox { inner: SoundStruct<'mc> }, + MusicDiscFar { inner: SoundStruct<'mc> }, + MusicDiscMall { inner: SoundStruct<'mc> }, + MusicDiscMellohi { inner: SoundStruct<'mc> }, + MusicDiscOtherside { inner: SoundStruct<'mc> }, + MusicDiscPigstep { inner: SoundStruct<'mc> }, + MusicDiscPrecipice { inner: SoundStruct<'mc> }, + MusicDiscRelic { inner: SoundStruct<'mc> }, + MusicDiscStal { inner: SoundStruct<'mc> }, + MusicDiscStrad { inner: SoundStruct<'mc> }, + MusicDiscWait { inner: SoundStruct<'mc> }, + MusicDiscWard { inner: SoundStruct<'mc> }, + MusicDragon { inner: SoundStruct<'mc> }, + MusicEnd { inner: SoundStruct<'mc> }, + MusicGame { inner: SoundStruct<'mc> }, + MusicMenu { inner: SoundStruct<'mc> }, + MusicNetherBasaltDeltas { inner: SoundStruct<'mc> }, + MusicNetherCrimsonForest { inner: SoundStruct<'mc> }, + MusicNetherNetherWastes { inner: SoundStruct<'mc> }, + MusicNetherSoulSandValley { inner: SoundStruct<'mc> }, + MusicNetherWarpedForest { inner: SoundStruct<'mc> }, + MusicOverworldBadlands { inner: SoundStruct<'mc> }, + MusicOverworldBambooJungle { inner: SoundStruct<'mc> }, + MusicOverworldCherryGrove { inner: SoundStruct<'mc> }, + MusicOverworldDeepDark { inner: SoundStruct<'mc> }, + MusicOverworldDesert { inner: SoundStruct<'mc> }, + MusicOverworldDripstoneCaves { inner: SoundStruct<'mc> }, + MusicOverworldFlowerForest { inner: SoundStruct<'mc> }, + MusicOverworldForest { inner: SoundStruct<'mc> }, + MusicOverworldFrozenPeaks { inner: SoundStruct<'mc> }, + MusicOverworldGrove { inner: SoundStruct<'mc> }, + MusicOverworldJaggedPeaks { inner: SoundStruct<'mc> }, + MusicOverworldJungle { inner: SoundStruct<'mc> }, + MusicOverworldLushCaves { inner: SoundStruct<'mc> }, + MusicOverworldMeadow { inner: SoundStruct<'mc> }, + MusicOverworldOldGrowthTaiga { inner: SoundStruct<'mc> }, + MusicOverworldSnowySlopes { inner: SoundStruct<'mc> }, + MusicOverworldSparseJungle { inner: SoundStruct<'mc> }, + MusicOverworldStonyPeaks { inner: SoundStruct<'mc> }, + MusicOverworldSwamp { inner: SoundStruct<'mc> }, + MusicUnderWater { inner: SoundStruct<'mc> }, + ParticleSoulEscape { inner: SoundStruct<'mc> }, + UiButtonClick { inner: SoundStruct<'mc> }, + UiCartographyTableTakeResult { inner: SoundStruct<'mc> }, + UiLoomSelectPattern { inner: SoundStruct<'mc> }, + UiLoomTakeResult { inner: SoundStruct<'mc> }, + UiStonecutterSelectRecipe { inner: SoundStruct<'mc> }, + UiStonecutterTakeResult { inner: SoundStruct<'mc> }, + UiToastChallengeComplete { inner: SoundStruct<'mc> }, + UiToastIn { inner: SoundStruct<'mc> }, + UiToastOut { inner: SoundStruct<'mc> }, + WeatherRain { inner: SoundStruct<'mc> }, + WeatherRainAbove { inner: SoundStruct<'mc> }, +} +impl<'mc> std::fmt::Display for Sound<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Sound::AmbientBasaltDeltasAdditions { .. } => { + f.write_str("AMBIENT_BASALT_DELTAS_ADDITIONS") + } + Sound::AmbientBasaltDeltasLoop { .. } => f.write_str("AMBIENT_BASALT_DELTAS_LOOP"), + Sound::AmbientBasaltDeltasMood { .. } => f.write_str("AMBIENT_BASALT_DELTAS_MOOD"), + Sound::AmbientCave { .. } => f.write_str("AMBIENT_CAVE"), + Sound::AmbientCrimsonForestAdditions { .. } => { + f.write_str("AMBIENT_CRIMSON_FOREST_ADDITIONS") + } + Sound::AmbientCrimsonForestLoop { .. } => f.write_str("AMBIENT_CRIMSON_FOREST_LOOP"), + Sound::AmbientCrimsonForestMood { .. } => f.write_str("AMBIENT_CRIMSON_FOREST_MOOD"), + Sound::AmbientNetherWastesAdditions { .. } => { + f.write_str("AMBIENT_NETHER_WASTES_ADDITIONS") + } + Sound::AmbientNetherWastesLoop { .. } => f.write_str("AMBIENT_NETHER_WASTES_LOOP"), + Sound::AmbientNetherWastesMood { .. } => f.write_str("AMBIENT_NETHER_WASTES_MOOD"), + Sound::AmbientSoulSandValleyAdditions { .. } => { + f.write_str("AMBIENT_SOUL_SAND_VALLEY_ADDITIONS") + } + Sound::AmbientSoulSandValleyLoop { .. } => f.write_str("AMBIENT_SOUL_SAND_VALLEY_LOOP"), + Sound::AmbientSoulSandValleyMood { .. } => f.write_str("AMBIENT_SOUL_SAND_VALLEY_MOOD"), + Sound::AmbientUnderwaterEnter { .. } => f.write_str("AMBIENT_UNDERWATER_ENTER"), + Sound::AmbientUnderwaterExit { .. } => f.write_str("AMBIENT_UNDERWATER_EXIT"), + Sound::AmbientUnderwaterLoop { .. } => f.write_str("AMBIENT_UNDERWATER_LOOP"), + Sound::AmbientUnderwaterLoopAdditions { .. } => { + f.write_str("AMBIENT_UNDERWATER_LOOP_ADDITIONS") + } + Sound::AmbientUnderwaterLoopAdditionsRare { .. } => { + f.write_str("AMBIENT_UNDERWATER_LOOP_ADDITIONS_RARE") + } + Sound::AmbientUnderwaterLoopAdditionsUltraRare { .. } => { + f.write_str("AMBIENT_UNDERWATER_LOOP_ADDITIONS_ULTRA_RARE") + } + Sound::AmbientWarpedForestAdditions { .. } => { + f.write_str("AMBIENT_WARPED_FOREST_ADDITIONS") + } + Sound::AmbientWarpedForestLoop { .. } => f.write_str("AMBIENT_WARPED_FOREST_LOOP"), + Sound::AmbientWarpedForestMood { .. } => f.write_str("AMBIENT_WARPED_FOREST_MOOD"), + Sound::BlockAmethystBlockBreak { .. } => f.write_str("BLOCK_AMETHYST_BLOCK_BREAK"), + Sound::BlockAmethystBlockChime { .. } => f.write_str("BLOCK_AMETHYST_BLOCK_CHIME"), + Sound::BlockAmethystBlockFall { .. } => f.write_str("BLOCK_AMETHYST_BLOCK_FALL"), + Sound::BlockAmethystBlockHit { .. } => f.write_str("BLOCK_AMETHYST_BLOCK_HIT"), + Sound::BlockAmethystBlockPlace { .. } => f.write_str("BLOCK_AMETHYST_BLOCK_PLACE"), + Sound::BlockAmethystBlockResonate { .. } => { + f.write_str("BLOCK_AMETHYST_BLOCK_RESONATE") + } + Sound::BlockAmethystBlockStep { .. } => f.write_str("BLOCK_AMETHYST_BLOCK_STEP"), + Sound::BlockAmethystClusterBreak { .. } => f.write_str("BLOCK_AMETHYST_CLUSTER_BREAK"), + Sound::BlockAmethystClusterFall { .. } => f.write_str("BLOCK_AMETHYST_CLUSTER_FALL"), + Sound::BlockAmethystClusterHit { .. } => f.write_str("BLOCK_AMETHYST_CLUSTER_HIT"), + Sound::BlockAmethystClusterPlace { .. } => f.write_str("BLOCK_AMETHYST_CLUSTER_PLACE"), + Sound::BlockAmethystClusterStep { .. } => f.write_str("BLOCK_AMETHYST_CLUSTER_STEP"), + Sound::BlockAncientDebrisBreak { .. } => f.write_str("BLOCK_ANCIENT_DEBRIS_BREAK"), + Sound::BlockAncientDebrisFall { .. } => f.write_str("BLOCK_ANCIENT_DEBRIS_FALL"), + Sound::BlockAncientDebrisHit { .. } => f.write_str("BLOCK_ANCIENT_DEBRIS_HIT"), + Sound::BlockAncientDebrisPlace { .. } => f.write_str("BLOCK_ANCIENT_DEBRIS_PLACE"), + Sound::BlockAncientDebrisStep { .. } => f.write_str("BLOCK_ANCIENT_DEBRIS_STEP"), + Sound::BlockAnvilBreak { .. } => f.write_str("BLOCK_ANVIL_BREAK"), + Sound::BlockAnvilDestroy { .. } => f.write_str("BLOCK_ANVIL_DESTROY"), + Sound::BlockAnvilFall { .. } => f.write_str("BLOCK_ANVIL_FALL"), + Sound::BlockAnvilHit { .. } => f.write_str("BLOCK_ANVIL_HIT"), + Sound::BlockAnvilLand { .. } => f.write_str("BLOCK_ANVIL_LAND"), + Sound::BlockAnvilPlace { .. } => f.write_str("BLOCK_ANVIL_PLACE"), + Sound::BlockAnvilStep { .. } => f.write_str("BLOCK_ANVIL_STEP"), + Sound::BlockAnvilUse { .. } => f.write_str("BLOCK_ANVIL_USE"), + Sound::BlockAzaleaBreak { .. } => f.write_str("BLOCK_AZALEA_BREAK"), + Sound::BlockAzaleaFall { .. } => f.write_str("BLOCK_AZALEA_FALL"), + Sound::BlockAzaleaHit { .. } => f.write_str("BLOCK_AZALEA_HIT"), + Sound::BlockAzaleaLeavesBreak { .. } => f.write_str("BLOCK_AZALEA_LEAVES_BREAK"), + Sound::BlockAzaleaLeavesFall { .. } => f.write_str("BLOCK_AZALEA_LEAVES_FALL"), + Sound::BlockAzaleaLeavesHit { .. } => f.write_str("BLOCK_AZALEA_LEAVES_HIT"), + Sound::BlockAzaleaLeavesPlace { .. } => f.write_str("BLOCK_AZALEA_LEAVES_PLACE"), + Sound::BlockAzaleaLeavesStep { .. } => f.write_str("BLOCK_AZALEA_LEAVES_STEP"), + Sound::BlockAzaleaPlace { .. } => f.write_str("BLOCK_AZALEA_PLACE"), + Sound::BlockAzaleaStep { .. } => f.write_str("BLOCK_AZALEA_STEP"), + Sound::BlockBambooBreak { .. } => f.write_str("BLOCK_BAMBOO_BREAK"), + Sound::BlockBambooFall { .. } => f.write_str("BLOCK_BAMBOO_FALL"), + Sound::BlockBambooHit { .. } => f.write_str("BLOCK_BAMBOO_HIT"), + Sound::BlockBambooPlace { .. } => f.write_str("BLOCK_BAMBOO_PLACE"), + Sound::BlockBambooSaplingBreak { .. } => f.write_str("BLOCK_BAMBOO_SAPLING_BREAK"), + Sound::BlockBambooSaplingHit { .. } => f.write_str("BLOCK_BAMBOO_SAPLING_HIT"), + Sound::BlockBambooSaplingPlace { .. } => f.write_str("BLOCK_BAMBOO_SAPLING_PLACE"), + Sound::BlockBambooStep { .. } => f.write_str("BLOCK_BAMBOO_STEP"), + Sound::BlockBambooWoodBreak { .. } => f.write_str("BLOCK_BAMBOO_WOOD_BREAK"), + Sound::BlockBambooWoodButtonClickOff { .. } => { + f.write_str("BLOCK_BAMBOO_WOOD_BUTTON_CLICK_OFF") + } + Sound::BlockBambooWoodButtonClickOn { .. } => { + f.write_str("BLOCK_BAMBOO_WOOD_BUTTON_CLICK_ON") + } + Sound::BlockBambooWoodDoorClose { .. } => f.write_str("BLOCK_BAMBOO_WOOD_DOOR_CLOSE"), + Sound::BlockBambooWoodDoorOpen { .. } => f.write_str("BLOCK_BAMBOO_WOOD_DOOR_OPEN"), + Sound::BlockBambooWoodFall { .. } => f.write_str("BLOCK_BAMBOO_WOOD_FALL"), + Sound::BlockBambooWoodFenceGateClose { .. } => { + f.write_str("BLOCK_BAMBOO_WOOD_FENCE_GATE_CLOSE") + } + Sound::BlockBambooWoodFenceGateOpen { .. } => { + f.write_str("BLOCK_BAMBOO_WOOD_FENCE_GATE_OPEN") + } + Sound::BlockBambooWoodHangingSignBreak { .. } => { + f.write_str("BLOCK_BAMBOO_WOOD_HANGING_SIGN_BREAK") + } + Sound::BlockBambooWoodHangingSignFall { .. } => { + f.write_str("BLOCK_BAMBOO_WOOD_HANGING_SIGN_FALL") + } + Sound::BlockBambooWoodHangingSignHit { .. } => { + f.write_str("BLOCK_BAMBOO_WOOD_HANGING_SIGN_HIT") + } + Sound::BlockBambooWoodHangingSignPlace { .. } => { + f.write_str("BLOCK_BAMBOO_WOOD_HANGING_SIGN_PLACE") + } + Sound::BlockBambooWoodHangingSignStep { .. } => { + f.write_str("BLOCK_BAMBOO_WOOD_HANGING_SIGN_STEP") + } + Sound::BlockBambooWoodHit { .. } => f.write_str("BLOCK_BAMBOO_WOOD_HIT"), + Sound::BlockBambooWoodPlace { .. } => f.write_str("BLOCK_BAMBOO_WOOD_PLACE"), + Sound::BlockBambooWoodPressurePlateClickOff { .. } => { + f.write_str("BLOCK_BAMBOO_WOOD_PRESSURE_PLATE_CLICK_OFF") + } + Sound::BlockBambooWoodPressurePlateClickOn { .. } => { + f.write_str("BLOCK_BAMBOO_WOOD_PRESSURE_PLATE_CLICK_ON") + } + Sound::BlockBambooWoodStep { .. } => f.write_str("BLOCK_BAMBOO_WOOD_STEP"), + Sound::BlockBambooWoodTrapdoorClose { .. } => { + f.write_str("BLOCK_BAMBOO_WOOD_TRAPDOOR_CLOSE") + } + Sound::BlockBambooWoodTrapdoorOpen { .. } => { + f.write_str("BLOCK_BAMBOO_WOOD_TRAPDOOR_OPEN") + } + Sound::BlockBarrelClose { .. } => f.write_str("BLOCK_BARREL_CLOSE"), + Sound::BlockBarrelOpen { .. } => f.write_str("BLOCK_BARREL_OPEN"), + Sound::BlockBasaltBreak { .. } => f.write_str("BLOCK_BASALT_BREAK"), + Sound::BlockBasaltFall { .. } => f.write_str("BLOCK_BASALT_FALL"), + Sound::BlockBasaltHit { .. } => f.write_str("BLOCK_BASALT_HIT"), + Sound::BlockBasaltPlace { .. } => f.write_str("BLOCK_BASALT_PLACE"), + Sound::BlockBasaltStep { .. } => f.write_str("BLOCK_BASALT_STEP"), + Sound::BlockBeaconActivate { .. } => f.write_str("BLOCK_BEACON_ACTIVATE"), + Sound::BlockBeaconAmbient { .. } => f.write_str("BLOCK_BEACON_AMBIENT"), + Sound::BlockBeaconDeactivate { .. } => f.write_str("BLOCK_BEACON_DEACTIVATE"), + Sound::BlockBeaconPowerSelect { .. } => f.write_str("BLOCK_BEACON_POWER_SELECT"), + Sound::BlockBeehiveDrip { .. } => f.write_str("BLOCK_BEEHIVE_DRIP"), + Sound::BlockBeehiveEnter { .. } => f.write_str("BLOCK_BEEHIVE_ENTER"), + Sound::BlockBeehiveExit { .. } => f.write_str("BLOCK_BEEHIVE_EXIT"), + Sound::BlockBeehiveShear { .. } => f.write_str("BLOCK_BEEHIVE_SHEAR"), + Sound::BlockBeehiveWork { .. } => f.write_str("BLOCK_BEEHIVE_WORK"), + Sound::BlockBellResonate { .. } => f.write_str("BLOCK_BELL_RESONATE"), + Sound::BlockBellUse { .. } => f.write_str("BLOCK_BELL_USE"), + Sound::BlockBigDripleafBreak { .. } => f.write_str("BLOCK_BIG_DRIPLEAF_BREAK"), + Sound::BlockBigDripleafFall { .. } => f.write_str("BLOCK_BIG_DRIPLEAF_FALL"), + Sound::BlockBigDripleafHit { .. } => f.write_str("BLOCK_BIG_DRIPLEAF_HIT"), + Sound::BlockBigDripleafPlace { .. } => f.write_str("BLOCK_BIG_DRIPLEAF_PLACE"), + Sound::BlockBigDripleafStep { .. } => f.write_str("BLOCK_BIG_DRIPLEAF_STEP"), + Sound::BlockBigDripleafTiltDown { .. } => f.write_str("BLOCK_BIG_DRIPLEAF_TILT_DOWN"), + Sound::BlockBigDripleafTiltUp { .. } => f.write_str("BLOCK_BIG_DRIPLEAF_TILT_UP"), + Sound::BlockBlastfurnaceFireCrackle { .. } => { + f.write_str("BLOCK_BLASTFURNACE_FIRE_CRACKLE") + } + Sound::BlockBoneBlockBreak { .. } => f.write_str("BLOCK_BONE_BLOCK_BREAK"), + Sound::BlockBoneBlockFall { .. } => f.write_str("BLOCK_BONE_BLOCK_FALL"), + Sound::BlockBoneBlockHit { .. } => f.write_str("BLOCK_BONE_BLOCK_HIT"), + Sound::BlockBoneBlockPlace { .. } => f.write_str("BLOCK_BONE_BLOCK_PLACE"), + Sound::BlockBoneBlockStep { .. } => f.write_str("BLOCK_BONE_BLOCK_STEP"), + Sound::BlockBrewingStandBrew { .. } => f.write_str("BLOCK_BREWING_STAND_BREW"), + Sound::BlockBubbleColumnBubblePop { .. } => { + f.write_str("BLOCK_BUBBLE_COLUMN_BUBBLE_POP") + } + Sound::BlockBubbleColumnUpwardsAmbient { .. } => { + f.write_str("BLOCK_BUBBLE_COLUMN_UPWARDS_AMBIENT") + } + Sound::BlockBubbleColumnUpwardsInside { .. } => { + f.write_str("BLOCK_BUBBLE_COLUMN_UPWARDS_INSIDE") + } + Sound::BlockBubbleColumnWhirlpoolAmbient { .. } => { + f.write_str("BLOCK_BUBBLE_COLUMN_WHIRLPOOL_AMBIENT") + } + Sound::BlockBubbleColumnWhirlpoolInside { .. } => { + f.write_str("BLOCK_BUBBLE_COLUMN_WHIRLPOOL_INSIDE") + } + Sound::BlockCakeAddCandle { .. } => f.write_str("BLOCK_CAKE_ADD_CANDLE"), + Sound::BlockCalciteBreak { .. } => f.write_str("BLOCK_CALCITE_BREAK"), + Sound::BlockCalciteFall { .. } => f.write_str("BLOCK_CALCITE_FALL"), + Sound::BlockCalciteHit { .. } => f.write_str("BLOCK_CALCITE_HIT"), + Sound::BlockCalcitePlace { .. } => f.write_str("BLOCK_CALCITE_PLACE"), + Sound::BlockCalciteStep { .. } => f.write_str("BLOCK_CALCITE_STEP"), + Sound::BlockCampfireCrackle { .. } => f.write_str("BLOCK_CAMPFIRE_CRACKLE"), + Sound::BlockCandleAmbient { .. } => f.write_str("BLOCK_CANDLE_AMBIENT"), + Sound::BlockCandleBreak { .. } => f.write_str("BLOCK_CANDLE_BREAK"), + Sound::BlockCandleExtinguish { .. } => f.write_str("BLOCK_CANDLE_EXTINGUISH"), + Sound::BlockCandleFall { .. } => f.write_str("BLOCK_CANDLE_FALL"), + Sound::BlockCandleHit { .. } => f.write_str("BLOCK_CANDLE_HIT"), + Sound::BlockCandlePlace { .. } => f.write_str("BLOCK_CANDLE_PLACE"), + Sound::BlockCandleStep { .. } => f.write_str("BLOCK_CANDLE_STEP"), + Sound::BlockCaveVinesBreak { .. } => f.write_str("BLOCK_CAVE_VINES_BREAK"), + Sound::BlockCaveVinesFall { .. } => f.write_str("BLOCK_CAVE_VINES_FALL"), + Sound::BlockCaveVinesHit { .. } => f.write_str("BLOCK_CAVE_VINES_HIT"), + Sound::BlockCaveVinesPickBerries { .. } => f.write_str("BLOCK_CAVE_VINES_PICK_BERRIES"), + Sound::BlockCaveVinesPlace { .. } => f.write_str("BLOCK_CAVE_VINES_PLACE"), + Sound::BlockCaveVinesStep { .. } => f.write_str("BLOCK_CAVE_VINES_STEP"), + Sound::BlockChainBreak { .. } => f.write_str("BLOCK_CHAIN_BREAK"), + Sound::BlockChainFall { .. } => f.write_str("BLOCK_CHAIN_FALL"), + Sound::BlockChainHit { .. } => f.write_str("BLOCK_CHAIN_HIT"), + Sound::BlockChainPlace { .. } => f.write_str("BLOCK_CHAIN_PLACE"), + Sound::BlockChainStep { .. } => f.write_str("BLOCK_CHAIN_STEP"), + Sound::BlockCherryLeavesBreak { .. } => f.write_str("BLOCK_CHERRY_LEAVES_BREAK"), + Sound::BlockCherryLeavesFall { .. } => f.write_str("BLOCK_CHERRY_LEAVES_FALL"), + Sound::BlockCherryLeavesHit { .. } => f.write_str("BLOCK_CHERRY_LEAVES_HIT"), + Sound::BlockCherryLeavesPlace { .. } => f.write_str("BLOCK_CHERRY_LEAVES_PLACE"), + Sound::BlockCherryLeavesStep { .. } => f.write_str("BLOCK_CHERRY_LEAVES_STEP"), + Sound::BlockCherrySaplingBreak { .. } => f.write_str("BLOCK_CHERRY_SAPLING_BREAK"), + Sound::BlockCherrySaplingFall { .. } => f.write_str("BLOCK_CHERRY_SAPLING_FALL"), + Sound::BlockCherrySaplingHit { .. } => f.write_str("BLOCK_CHERRY_SAPLING_HIT"), + Sound::BlockCherrySaplingPlace { .. } => f.write_str("BLOCK_CHERRY_SAPLING_PLACE"), + Sound::BlockCherrySaplingStep { .. } => f.write_str("BLOCK_CHERRY_SAPLING_STEP"), + Sound::BlockCherryWoodBreak { .. } => f.write_str("BLOCK_CHERRY_WOOD_BREAK"), + Sound::BlockCherryWoodButtonClickOff { .. } => { + f.write_str("BLOCK_CHERRY_WOOD_BUTTON_CLICK_OFF") + } + Sound::BlockCherryWoodButtonClickOn { .. } => { + f.write_str("BLOCK_CHERRY_WOOD_BUTTON_CLICK_ON") + } + Sound::BlockCherryWoodDoorClose { .. } => f.write_str("BLOCK_CHERRY_WOOD_DOOR_CLOSE"), + Sound::BlockCherryWoodDoorOpen { .. } => f.write_str("BLOCK_CHERRY_WOOD_DOOR_OPEN"), + Sound::BlockCherryWoodFall { .. } => f.write_str("BLOCK_CHERRY_WOOD_FALL"), + Sound::BlockCherryWoodFenceGateClose { .. } => { + f.write_str("BLOCK_CHERRY_WOOD_FENCE_GATE_CLOSE") + } + Sound::BlockCherryWoodFenceGateOpen { .. } => { + f.write_str("BLOCK_CHERRY_WOOD_FENCE_GATE_OPEN") + } + Sound::BlockCherryWoodHangingSignBreak { .. } => { + f.write_str("BLOCK_CHERRY_WOOD_HANGING_SIGN_BREAK") + } + Sound::BlockCherryWoodHangingSignFall { .. } => { + f.write_str("BLOCK_CHERRY_WOOD_HANGING_SIGN_FALL") + } + Sound::BlockCherryWoodHangingSignHit { .. } => { + f.write_str("BLOCK_CHERRY_WOOD_HANGING_SIGN_HIT") + } + Sound::BlockCherryWoodHangingSignPlace { .. } => { + f.write_str("BLOCK_CHERRY_WOOD_HANGING_SIGN_PLACE") + } + Sound::BlockCherryWoodHangingSignStep { .. } => { + f.write_str("BLOCK_CHERRY_WOOD_HANGING_SIGN_STEP") + } + Sound::BlockCherryWoodHit { .. } => f.write_str("BLOCK_CHERRY_WOOD_HIT"), + Sound::BlockCherryWoodPlace { .. } => f.write_str("BLOCK_CHERRY_WOOD_PLACE"), + Sound::BlockCherryWoodPressurePlateClickOff { .. } => { + f.write_str("BLOCK_CHERRY_WOOD_PRESSURE_PLATE_CLICK_OFF") + } + Sound::BlockCherryWoodPressurePlateClickOn { .. } => { + f.write_str("BLOCK_CHERRY_WOOD_PRESSURE_PLATE_CLICK_ON") + } + Sound::BlockCherryWoodStep { .. } => f.write_str("BLOCK_CHERRY_WOOD_STEP"), + Sound::BlockCherryWoodTrapdoorClose { .. } => { + f.write_str("BLOCK_CHERRY_WOOD_TRAPDOOR_CLOSE") + } + Sound::BlockCherryWoodTrapdoorOpen { .. } => { + f.write_str("BLOCK_CHERRY_WOOD_TRAPDOOR_OPEN") + } + Sound::BlockChestClose { .. } => f.write_str("BLOCK_CHEST_CLOSE"), + Sound::BlockChestLocked { .. } => f.write_str("BLOCK_CHEST_LOCKED"), + Sound::BlockChestOpen { .. } => f.write_str("BLOCK_CHEST_OPEN"), + Sound::BlockChiseledBookshelfBreak { .. } => { + f.write_str("BLOCK_CHISELED_BOOKSHELF_BREAK") + } + Sound::BlockChiseledBookshelfFall { .. } => { + f.write_str("BLOCK_CHISELED_BOOKSHELF_FALL") + } + Sound::BlockChiseledBookshelfHit { .. } => f.write_str("BLOCK_CHISELED_BOOKSHELF_HIT"), + Sound::BlockChiseledBookshelfInsert { .. } => { + f.write_str("BLOCK_CHISELED_BOOKSHELF_INSERT") + } + Sound::BlockChiseledBookshelfInsertEnchanted { .. } => { + f.write_str("BLOCK_CHISELED_BOOKSHELF_INSERT_ENCHANTED") + } + Sound::BlockChiseledBookshelfPickup { .. } => { + f.write_str("BLOCK_CHISELED_BOOKSHELF_PICKUP") + } + Sound::BlockChiseledBookshelfPickupEnchanted { .. } => { + f.write_str("BLOCK_CHISELED_BOOKSHELF_PICKUP_ENCHANTED") + } + Sound::BlockChiseledBookshelfPlace { .. } => { + f.write_str("BLOCK_CHISELED_BOOKSHELF_PLACE") + } + Sound::BlockChiseledBookshelfStep { .. } => { + f.write_str("BLOCK_CHISELED_BOOKSHELF_STEP") + } + Sound::BlockChorusFlowerDeath { .. } => f.write_str("BLOCK_CHORUS_FLOWER_DEATH"), + Sound::BlockChorusFlowerGrow { .. } => f.write_str("BLOCK_CHORUS_FLOWER_GROW"), + Sound::BlockCobwebBreak { .. } => f.write_str("BLOCK_COBWEB_BREAK"), + Sound::BlockCobwebFall { .. } => f.write_str("BLOCK_COBWEB_FALL"), + Sound::BlockCobwebHit { .. } => f.write_str("BLOCK_COBWEB_HIT"), + Sound::BlockCobwebPlace { .. } => f.write_str("BLOCK_COBWEB_PLACE"), + Sound::BlockCobwebStep { .. } => f.write_str("BLOCK_COBWEB_STEP"), + Sound::BlockComparatorClick { .. } => f.write_str("BLOCK_COMPARATOR_CLICK"), + Sound::BlockComposterEmpty { .. } => f.write_str("BLOCK_COMPOSTER_EMPTY"), + Sound::BlockComposterFill { .. } => f.write_str("BLOCK_COMPOSTER_FILL"), + Sound::BlockComposterFillSuccess { .. } => f.write_str("BLOCK_COMPOSTER_FILL_SUCCESS"), + Sound::BlockComposterReady { .. } => f.write_str("BLOCK_COMPOSTER_READY"), + Sound::BlockConduitActivate { .. } => f.write_str("BLOCK_CONDUIT_ACTIVATE"), + Sound::BlockConduitAmbient { .. } => f.write_str("BLOCK_CONDUIT_AMBIENT"), + Sound::BlockConduitAmbientShort { .. } => f.write_str("BLOCK_CONDUIT_AMBIENT_SHORT"), + Sound::BlockConduitAttackTarget { .. } => f.write_str("BLOCK_CONDUIT_ATTACK_TARGET"), + Sound::BlockConduitDeactivate { .. } => f.write_str("BLOCK_CONDUIT_DEACTIVATE"), + Sound::BlockCopperBreak { .. } => f.write_str("BLOCK_COPPER_BREAK"), + Sound::BlockCopperBulbBreak { .. } => f.write_str("BLOCK_COPPER_BULB_BREAK"), + Sound::BlockCopperBulbFall { .. } => f.write_str("BLOCK_COPPER_BULB_FALL"), + Sound::BlockCopperBulbHit { .. } => f.write_str("BLOCK_COPPER_BULB_HIT"), + Sound::BlockCopperBulbPlace { .. } => f.write_str("BLOCK_COPPER_BULB_PLACE"), + Sound::BlockCopperBulbStep { .. } => f.write_str("BLOCK_COPPER_BULB_STEP"), + Sound::BlockCopperBulbTurnOff { .. } => f.write_str("BLOCK_COPPER_BULB_TURN_OFF"), + Sound::BlockCopperBulbTurnOn { .. } => f.write_str("BLOCK_COPPER_BULB_TURN_ON"), + Sound::BlockCopperDoorClose { .. } => f.write_str("BLOCK_COPPER_DOOR_CLOSE"), + Sound::BlockCopperDoorOpen { .. } => f.write_str("BLOCK_COPPER_DOOR_OPEN"), + Sound::BlockCopperFall { .. } => f.write_str("BLOCK_COPPER_FALL"), + Sound::BlockCopperGrateBreak { .. } => f.write_str("BLOCK_COPPER_GRATE_BREAK"), + Sound::BlockCopperGrateFall { .. } => f.write_str("BLOCK_COPPER_GRATE_FALL"), + Sound::BlockCopperGrateHit { .. } => f.write_str("BLOCK_COPPER_GRATE_HIT"), + Sound::BlockCopperGratePlace { .. } => f.write_str("BLOCK_COPPER_GRATE_PLACE"), + Sound::BlockCopperGrateStep { .. } => f.write_str("BLOCK_COPPER_GRATE_STEP"), + Sound::BlockCopperHit { .. } => f.write_str("BLOCK_COPPER_HIT"), + Sound::BlockCopperPlace { .. } => f.write_str("BLOCK_COPPER_PLACE"), + Sound::BlockCopperStep { .. } => f.write_str("BLOCK_COPPER_STEP"), + Sound::BlockCopperTrapdoorClose { .. } => f.write_str("BLOCK_COPPER_TRAPDOOR_CLOSE"), + Sound::BlockCopperTrapdoorOpen { .. } => f.write_str("BLOCK_COPPER_TRAPDOOR_OPEN"), + Sound::BlockCoralBlockBreak { .. } => f.write_str("BLOCK_CORAL_BLOCK_BREAK"), + Sound::BlockCoralBlockFall { .. } => f.write_str("BLOCK_CORAL_BLOCK_FALL"), + Sound::BlockCoralBlockHit { .. } => f.write_str("BLOCK_CORAL_BLOCK_HIT"), + Sound::BlockCoralBlockPlace { .. } => f.write_str("BLOCK_CORAL_BLOCK_PLACE"), + Sound::BlockCoralBlockStep { .. } => f.write_str("BLOCK_CORAL_BLOCK_STEP"), + Sound::BlockCrafterCraft { .. } => f.write_str("BLOCK_CRAFTER_CRAFT"), + Sound::BlockCrafterFail { .. } => f.write_str("BLOCK_CRAFTER_FAIL"), + Sound::BlockCropBreak { .. } => f.write_str("BLOCK_CROP_BREAK"), + Sound::BlockDecoratedPotBreak { .. } => f.write_str("BLOCK_DECORATED_POT_BREAK"), + Sound::BlockDecoratedPotFall { .. } => f.write_str("BLOCK_DECORATED_POT_FALL"), + Sound::BlockDecoratedPotHit { .. } => f.write_str("BLOCK_DECORATED_POT_HIT"), + Sound::BlockDecoratedPotInsert { .. } => f.write_str("BLOCK_DECORATED_POT_INSERT"), + Sound::BlockDecoratedPotInsertFail { .. } => { + f.write_str("BLOCK_DECORATED_POT_INSERT_FAIL") + } + Sound::BlockDecoratedPotPlace { .. } => f.write_str("BLOCK_DECORATED_POT_PLACE"), + Sound::BlockDecoratedPotShatter { .. } => f.write_str("BLOCK_DECORATED_POT_SHATTER"), + Sound::BlockDecoratedPotStep { .. } => f.write_str("BLOCK_DECORATED_POT_STEP"), + Sound::BlockDeepslateBreak { .. } => f.write_str("BLOCK_DEEPSLATE_BREAK"), + Sound::BlockDeepslateBricksBreak { .. } => f.write_str("BLOCK_DEEPSLATE_BRICKS_BREAK"), + Sound::BlockDeepslateBricksFall { .. } => f.write_str("BLOCK_DEEPSLATE_BRICKS_FALL"), + Sound::BlockDeepslateBricksHit { .. } => f.write_str("BLOCK_DEEPSLATE_BRICKS_HIT"), + Sound::BlockDeepslateBricksPlace { .. } => f.write_str("BLOCK_DEEPSLATE_BRICKS_PLACE"), + Sound::BlockDeepslateBricksStep { .. } => f.write_str("BLOCK_DEEPSLATE_BRICKS_STEP"), + Sound::BlockDeepslateFall { .. } => f.write_str("BLOCK_DEEPSLATE_FALL"), + Sound::BlockDeepslateHit { .. } => f.write_str("BLOCK_DEEPSLATE_HIT"), + Sound::BlockDeepslatePlace { .. } => f.write_str("BLOCK_DEEPSLATE_PLACE"), + Sound::BlockDeepslateStep { .. } => f.write_str("BLOCK_DEEPSLATE_STEP"), + Sound::BlockDeepslateTilesBreak { .. } => f.write_str("BLOCK_DEEPSLATE_TILES_BREAK"), + Sound::BlockDeepslateTilesFall { .. } => f.write_str("BLOCK_DEEPSLATE_TILES_FALL"), + Sound::BlockDeepslateTilesHit { .. } => f.write_str("BLOCK_DEEPSLATE_TILES_HIT"), + Sound::BlockDeepslateTilesPlace { .. } => f.write_str("BLOCK_DEEPSLATE_TILES_PLACE"), + Sound::BlockDeepslateTilesStep { .. } => f.write_str("BLOCK_DEEPSLATE_TILES_STEP"), + Sound::BlockDispenserDispense { .. } => f.write_str("BLOCK_DISPENSER_DISPENSE"), + Sound::BlockDispenserFail { .. } => f.write_str("BLOCK_DISPENSER_FAIL"), + Sound::BlockDispenserLaunch { .. } => f.write_str("BLOCK_DISPENSER_LAUNCH"), + Sound::BlockDripstoneBlockBreak { .. } => f.write_str("BLOCK_DRIPSTONE_BLOCK_BREAK"), + Sound::BlockDripstoneBlockFall { .. } => f.write_str("BLOCK_DRIPSTONE_BLOCK_FALL"), + Sound::BlockDripstoneBlockHit { .. } => f.write_str("BLOCK_DRIPSTONE_BLOCK_HIT"), + Sound::BlockDripstoneBlockPlace { .. } => f.write_str("BLOCK_DRIPSTONE_BLOCK_PLACE"), + Sound::BlockDripstoneBlockStep { .. } => f.write_str("BLOCK_DRIPSTONE_BLOCK_STEP"), + Sound::BlockEnchantmentTableUse { .. } => f.write_str("BLOCK_ENCHANTMENT_TABLE_USE"), + Sound::BlockEnderChestClose { .. } => f.write_str("BLOCK_ENDER_CHEST_CLOSE"), + Sound::BlockEnderChestOpen { .. } => f.write_str("BLOCK_ENDER_CHEST_OPEN"), + Sound::BlockEndGatewaySpawn { .. } => f.write_str("BLOCK_END_GATEWAY_SPAWN"), + Sound::BlockEndPortalFrameFill { .. } => f.write_str("BLOCK_END_PORTAL_FRAME_FILL"), + Sound::BlockEndPortalSpawn { .. } => f.write_str("BLOCK_END_PORTAL_SPAWN"), + Sound::BlockFenceGateClose { .. } => f.write_str("BLOCK_FENCE_GATE_CLOSE"), + Sound::BlockFenceGateOpen { .. } => f.write_str("BLOCK_FENCE_GATE_OPEN"), + Sound::BlockFireAmbient { .. } => f.write_str("BLOCK_FIRE_AMBIENT"), + Sound::BlockFireExtinguish { .. } => f.write_str("BLOCK_FIRE_EXTINGUISH"), + Sound::BlockFloweringAzaleaBreak { .. } => f.write_str("BLOCK_FLOWERING_AZALEA_BREAK"), + Sound::BlockFloweringAzaleaFall { .. } => f.write_str("BLOCK_FLOWERING_AZALEA_FALL"), + Sound::BlockFloweringAzaleaHit { .. } => f.write_str("BLOCK_FLOWERING_AZALEA_HIT"), + Sound::BlockFloweringAzaleaPlace { .. } => f.write_str("BLOCK_FLOWERING_AZALEA_PLACE"), + Sound::BlockFloweringAzaleaStep { .. } => f.write_str("BLOCK_FLOWERING_AZALEA_STEP"), + Sound::BlockFroglightBreak { .. } => f.write_str("BLOCK_FROGLIGHT_BREAK"), + Sound::BlockFroglightFall { .. } => f.write_str("BLOCK_FROGLIGHT_FALL"), + Sound::BlockFroglightHit { .. } => f.write_str("BLOCK_FROGLIGHT_HIT"), + Sound::BlockFroglightPlace { .. } => f.write_str("BLOCK_FROGLIGHT_PLACE"), + Sound::BlockFroglightStep { .. } => f.write_str("BLOCK_FROGLIGHT_STEP"), + Sound::BlockFrogspawnBreak { .. } => f.write_str("BLOCK_FROGSPAWN_BREAK"), + Sound::BlockFrogspawnFall { .. } => f.write_str("BLOCK_FROGSPAWN_FALL"), + Sound::BlockFrogspawnHatch { .. } => f.write_str("BLOCK_FROGSPAWN_HATCH"), + Sound::BlockFrogspawnHit { .. } => f.write_str("BLOCK_FROGSPAWN_HIT"), + Sound::BlockFrogspawnPlace { .. } => f.write_str("BLOCK_FROGSPAWN_PLACE"), + Sound::BlockFrogspawnStep { .. } => f.write_str("BLOCK_FROGSPAWN_STEP"), + Sound::BlockFungusBreak { .. } => f.write_str("BLOCK_FUNGUS_BREAK"), + Sound::BlockFungusFall { .. } => f.write_str("BLOCK_FUNGUS_FALL"), + Sound::BlockFungusHit { .. } => f.write_str("BLOCK_FUNGUS_HIT"), + Sound::BlockFungusPlace { .. } => f.write_str("BLOCK_FUNGUS_PLACE"), + Sound::BlockFungusStep { .. } => f.write_str("BLOCK_FUNGUS_STEP"), + Sound::BlockFurnaceFireCrackle { .. } => f.write_str("BLOCK_FURNACE_FIRE_CRACKLE"), + Sound::BlockGildedBlackstoneBreak { .. } => { + f.write_str("BLOCK_GILDED_BLACKSTONE_BREAK") + } + Sound::BlockGildedBlackstoneFall { .. } => f.write_str("BLOCK_GILDED_BLACKSTONE_FALL"), + Sound::BlockGildedBlackstoneHit { .. } => f.write_str("BLOCK_GILDED_BLACKSTONE_HIT"), + Sound::BlockGildedBlackstonePlace { .. } => { + f.write_str("BLOCK_GILDED_BLACKSTONE_PLACE") + } + Sound::BlockGildedBlackstoneStep { .. } => f.write_str("BLOCK_GILDED_BLACKSTONE_STEP"), + Sound::BlockGlassBreak { .. } => f.write_str("BLOCK_GLASS_BREAK"), + Sound::BlockGlassFall { .. } => f.write_str("BLOCK_GLASS_FALL"), + Sound::BlockGlassHit { .. } => f.write_str("BLOCK_GLASS_HIT"), + Sound::BlockGlassPlace { .. } => f.write_str("BLOCK_GLASS_PLACE"), + Sound::BlockGlassStep { .. } => f.write_str("BLOCK_GLASS_STEP"), + Sound::BlockGrassBreak { .. } => f.write_str("BLOCK_GRASS_BREAK"), + Sound::BlockGrassFall { .. } => f.write_str("BLOCK_GRASS_FALL"), + Sound::BlockGrassHit { .. } => f.write_str("BLOCK_GRASS_HIT"), + Sound::BlockGrassPlace { .. } => f.write_str("BLOCK_GRASS_PLACE"), + Sound::BlockGrassStep { .. } => f.write_str("BLOCK_GRASS_STEP"), + Sound::BlockGravelBreak { .. } => f.write_str("BLOCK_GRAVEL_BREAK"), + Sound::BlockGravelFall { .. } => f.write_str("BLOCK_GRAVEL_FALL"), + Sound::BlockGravelHit { .. } => f.write_str("BLOCK_GRAVEL_HIT"), + Sound::BlockGravelPlace { .. } => f.write_str("BLOCK_GRAVEL_PLACE"), + Sound::BlockGravelStep { .. } => f.write_str("BLOCK_GRAVEL_STEP"), + Sound::BlockGrindstoneUse { .. } => f.write_str("BLOCK_GRINDSTONE_USE"), + Sound::BlockGrowingPlantCrop { .. } => f.write_str("BLOCK_GROWING_PLANT_CROP"), + Sound::BlockHangingRootsBreak { .. } => f.write_str("BLOCK_HANGING_ROOTS_BREAK"), + Sound::BlockHangingRootsFall { .. } => f.write_str("BLOCK_HANGING_ROOTS_FALL"), + Sound::BlockHangingRootsHit { .. } => f.write_str("BLOCK_HANGING_ROOTS_HIT"), + Sound::BlockHangingRootsPlace { .. } => f.write_str("BLOCK_HANGING_ROOTS_PLACE"), + Sound::BlockHangingRootsStep { .. } => f.write_str("BLOCK_HANGING_ROOTS_STEP"), + Sound::BlockHangingSignBreak { .. } => f.write_str("BLOCK_HANGING_SIGN_BREAK"), + Sound::BlockHangingSignFall { .. } => f.write_str("BLOCK_HANGING_SIGN_FALL"), + Sound::BlockHangingSignHit { .. } => f.write_str("BLOCK_HANGING_SIGN_HIT"), + Sound::BlockHangingSignPlace { .. } => f.write_str("BLOCK_HANGING_SIGN_PLACE"), + Sound::BlockHangingSignStep { .. } => f.write_str("BLOCK_HANGING_SIGN_STEP"), + Sound::BlockHangingSignWaxedInteractFail { .. } => { + f.write_str("BLOCK_HANGING_SIGN_WAXED_INTERACT_FAIL") + } + Sound::BlockHeavyCoreBreak { .. } => f.write_str("BLOCK_HEAVY_CORE_BREAK"), + Sound::BlockHeavyCoreFall { .. } => f.write_str("BLOCK_HEAVY_CORE_FALL"), + Sound::BlockHeavyCoreHit { .. } => f.write_str("BLOCK_HEAVY_CORE_HIT"), + Sound::BlockHeavyCorePlace { .. } => f.write_str("BLOCK_HEAVY_CORE_PLACE"), + Sound::BlockHeavyCoreStep { .. } => f.write_str("BLOCK_HEAVY_CORE_STEP"), + Sound::BlockHoneyBlockBreak { .. } => f.write_str("BLOCK_HONEY_BLOCK_BREAK"), + Sound::BlockHoneyBlockFall { .. } => f.write_str("BLOCK_HONEY_BLOCK_FALL"), + Sound::BlockHoneyBlockHit { .. } => f.write_str("BLOCK_HONEY_BLOCK_HIT"), + Sound::BlockHoneyBlockPlace { .. } => f.write_str("BLOCK_HONEY_BLOCK_PLACE"), + Sound::BlockHoneyBlockSlide { .. } => f.write_str("BLOCK_HONEY_BLOCK_SLIDE"), + Sound::BlockHoneyBlockStep { .. } => f.write_str("BLOCK_HONEY_BLOCK_STEP"), + Sound::BlockIronDoorClose { .. } => f.write_str("BLOCK_IRON_DOOR_CLOSE"), + Sound::BlockIronDoorOpen { .. } => f.write_str("BLOCK_IRON_DOOR_OPEN"), + Sound::BlockIronTrapdoorClose { .. } => f.write_str("BLOCK_IRON_TRAPDOOR_CLOSE"), + Sound::BlockIronTrapdoorOpen { .. } => f.write_str("BLOCK_IRON_TRAPDOOR_OPEN"), + Sound::BlockLadderBreak { .. } => f.write_str("BLOCK_LADDER_BREAK"), + Sound::BlockLadderFall { .. } => f.write_str("BLOCK_LADDER_FALL"), + Sound::BlockLadderHit { .. } => f.write_str("BLOCK_LADDER_HIT"), + Sound::BlockLadderPlace { .. } => f.write_str("BLOCK_LADDER_PLACE"), + Sound::BlockLadderStep { .. } => f.write_str("BLOCK_LADDER_STEP"), + Sound::BlockLanternBreak { .. } => f.write_str("BLOCK_LANTERN_BREAK"), + Sound::BlockLanternFall { .. } => f.write_str("BLOCK_LANTERN_FALL"), + Sound::BlockLanternHit { .. } => f.write_str("BLOCK_LANTERN_HIT"), + Sound::BlockLanternPlace { .. } => f.write_str("BLOCK_LANTERN_PLACE"), + Sound::BlockLanternStep { .. } => f.write_str("BLOCK_LANTERN_STEP"), + Sound::BlockLargeAmethystBudBreak { .. } => { + f.write_str("BLOCK_LARGE_AMETHYST_BUD_BREAK") + } + Sound::BlockLargeAmethystBudPlace { .. } => { + f.write_str("BLOCK_LARGE_AMETHYST_BUD_PLACE") + } + Sound::BlockLavaAmbient { .. } => f.write_str("BLOCK_LAVA_AMBIENT"), + Sound::BlockLavaExtinguish { .. } => f.write_str("BLOCK_LAVA_EXTINGUISH"), + Sound::BlockLavaPop { .. } => f.write_str("BLOCK_LAVA_POP"), + Sound::BlockLeverClick { .. } => f.write_str("BLOCK_LEVER_CLICK"), + Sound::BlockLilyPadPlace { .. } => f.write_str("BLOCK_LILY_PAD_PLACE"), + Sound::BlockLodestoneBreak { .. } => f.write_str("BLOCK_LODESTONE_BREAK"), + Sound::BlockLodestoneFall { .. } => f.write_str("BLOCK_LODESTONE_FALL"), + Sound::BlockLodestoneHit { .. } => f.write_str("BLOCK_LODESTONE_HIT"), + Sound::BlockLodestonePlace { .. } => f.write_str("BLOCK_LODESTONE_PLACE"), + Sound::BlockLodestoneStep { .. } => f.write_str("BLOCK_LODESTONE_STEP"), + Sound::BlockMangroveRootsBreak { .. } => f.write_str("BLOCK_MANGROVE_ROOTS_BREAK"), + Sound::BlockMangroveRootsFall { .. } => f.write_str("BLOCK_MANGROVE_ROOTS_FALL"), + Sound::BlockMangroveRootsHit { .. } => f.write_str("BLOCK_MANGROVE_ROOTS_HIT"), + Sound::BlockMangroveRootsPlace { .. } => f.write_str("BLOCK_MANGROVE_ROOTS_PLACE"), + Sound::BlockMangroveRootsStep { .. } => f.write_str("BLOCK_MANGROVE_ROOTS_STEP"), + Sound::BlockMediumAmethystBudBreak { .. } => { + f.write_str("BLOCK_MEDIUM_AMETHYST_BUD_BREAK") + } + Sound::BlockMediumAmethystBudPlace { .. } => { + f.write_str("BLOCK_MEDIUM_AMETHYST_BUD_PLACE") + } + Sound::BlockMetalBreak { .. } => f.write_str("BLOCK_METAL_BREAK"), + Sound::BlockMetalFall { .. } => f.write_str("BLOCK_METAL_FALL"), + Sound::BlockMetalHit { .. } => f.write_str("BLOCK_METAL_HIT"), + Sound::BlockMetalPlace { .. } => f.write_str("BLOCK_METAL_PLACE"), + Sound::BlockMetalPressurePlateClickOff { .. } => { + f.write_str("BLOCK_METAL_PRESSURE_PLATE_CLICK_OFF") + } + Sound::BlockMetalPressurePlateClickOn { .. } => { + f.write_str("BLOCK_METAL_PRESSURE_PLATE_CLICK_ON") + } + Sound::BlockMetalStep { .. } => f.write_str("BLOCK_METAL_STEP"), + Sound::BlockMossBreak { .. } => f.write_str("BLOCK_MOSS_BREAK"), + Sound::BlockMossCarpetBreak { .. } => f.write_str("BLOCK_MOSS_CARPET_BREAK"), + Sound::BlockMossCarpetFall { .. } => f.write_str("BLOCK_MOSS_CARPET_FALL"), + Sound::BlockMossCarpetHit { .. } => f.write_str("BLOCK_MOSS_CARPET_HIT"), + Sound::BlockMossCarpetPlace { .. } => f.write_str("BLOCK_MOSS_CARPET_PLACE"), + Sound::BlockMossCarpetStep { .. } => f.write_str("BLOCK_MOSS_CARPET_STEP"), + Sound::BlockMossFall { .. } => f.write_str("BLOCK_MOSS_FALL"), + Sound::BlockMossHit { .. } => f.write_str("BLOCK_MOSS_HIT"), + Sound::BlockMossPlace { .. } => f.write_str("BLOCK_MOSS_PLACE"), + Sound::BlockMossStep { .. } => f.write_str("BLOCK_MOSS_STEP"), + Sound::BlockMuddyMangroveRootsBreak { .. } => { + f.write_str("BLOCK_MUDDY_MANGROVE_ROOTS_BREAK") + } + Sound::BlockMuddyMangroveRootsFall { .. } => { + f.write_str("BLOCK_MUDDY_MANGROVE_ROOTS_FALL") + } + Sound::BlockMuddyMangroveRootsHit { .. } => { + f.write_str("BLOCK_MUDDY_MANGROVE_ROOTS_HIT") + } + Sound::BlockMuddyMangroveRootsPlace { .. } => { + f.write_str("BLOCK_MUDDY_MANGROVE_ROOTS_PLACE") + } + Sound::BlockMuddyMangroveRootsStep { .. } => { + f.write_str("BLOCK_MUDDY_MANGROVE_ROOTS_STEP") + } + Sound::BlockMudBreak { .. } => f.write_str("BLOCK_MUD_BREAK"), + Sound::BlockMudBricksBreak { .. } => f.write_str("BLOCK_MUD_BRICKS_BREAK"), + Sound::BlockMudBricksFall { .. } => f.write_str("BLOCK_MUD_BRICKS_FALL"), + Sound::BlockMudBricksHit { .. } => f.write_str("BLOCK_MUD_BRICKS_HIT"), + Sound::BlockMudBricksPlace { .. } => f.write_str("BLOCK_MUD_BRICKS_PLACE"), + Sound::BlockMudBricksStep { .. } => f.write_str("BLOCK_MUD_BRICKS_STEP"), + Sound::BlockMudFall { .. } => f.write_str("BLOCK_MUD_FALL"), + Sound::BlockMudHit { .. } => f.write_str("BLOCK_MUD_HIT"), + Sound::BlockMudPlace { .. } => f.write_str("BLOCK_MUD_PLACE"), + Sound::BlockMudStep { .. } => f.write_str("BLOCK_MUD_STEP"), + Sound::BlockNetheriteBlockBreak { .. } => f.write_str("BLOCK_NETHERITE_BLOCK_BREAK"), + Sound::BlockNetheriteBlockFall { .. } => f.write_str("BLOCK_NETHERITE_BLOCK_FALL"), + Sound::BlockNetheriteBlockHit { .. } => f.write_str("BLOCK_NETHERITE_BLOCK_HIT"), + Sound::BlockNetheriteBlockPlace { .. } => f.write_str("BLOCK_NETHERITE_BLOCK_PLACE"), + Sound::BlockNetheriteBlockStep { .. } => f.write_str("BLOCK_NETHERITE_BLOCK_STEP"), + Sound::BlockNetherrackBreak { .. } => f.write_str("BLOCK_NETHERRACK_BREAK"), + Sound::BlockNetherrackFall { .. } => f.write_str("BLOCK_NETHERRACK_FALL"), + Sound::BlockNetherrackHit { .. } => f.write_str("BLOCK_NETHERRACK_HIT"), + Sound::BlockNetherrackPlace { .. } => f.write_str("BLOCK_NETHERRACK_PLACE"), + Sound::BlockNetherrackStep { .. } => f.write_str("BLOCK_NETHERRACK_STEP"), + Sound::BlockNetherBricksBreak { .. } => f.write_str("BLOCK_NETHER_BRICKS_BREAK"), + Sound::BlockNetherBricksFall { .. } => f.write_str("BLOCK_NETHER_BRICKS_FALL"), + Sound::BlockNetherBricksHit { .. } => f.write_str("BLOCK_NETHER_BRICKS_HIT"), + Sound::BlockNetherBricksPlace { .. } => f.write_str("BLOCK_NETHER_BRICKS_PLACE"), + Sound::BlockNetherBricksStep { .. } => f.write_str("BLOCK_NETHER_BRICKS_STEP"), + Sound::BlockNetherGoldOreBreak { .. } => f.write_str("BLOCK_NETHER_GOLD_ORE_BREAK"), + Sound::BlockNetherGoldOreFall { .. } => f.write_str("BLOCK_NETHER_GOLD_ORE_FALL"), + Sound::BlockNetherGoldOreHit { .. } => f.write_str("BLOCK_NETHER_GOLD_ORE_HIT"), + Sound::BlockNetherGoldOrePlace { .. } => f.write_str("BLOCK_NETHER_GOLD_ORE_PLACE"), + Sound::BlockNetherGoldOreStep { .. } => f.write_str("BLOCK_NETHER_GOLD_ORE_STEP"), + Sound::BlockNetherOreBreak { .. } => f.write_str("BLOCK_NETHER_ORE_BREAK"), + Sound::BlockNetherOreFall { .. } => f.write_str("BLOCK_NETHER_ORE_FALL"), + Sound::BlockNetherOreHit { .. } => f.write_str("BLOCK_NETHER_ORE_HIT"), + Sound::BlockNetherOrePlace { .. } => f.write_str("BLOCK_NETHER_ORE_PLACE"), + Sound::BlockNetherOreStep { .. } => f.write_str("BLOCK_NETHER_ORE_STEP"), + Sound::BlockNetherSproutsBreak { .. } => f.write_str("BLOCK_NETHER_SPROUTS_BREAK"), + Sound::BlockNetherSproutsFall { .. } => f.write_str("BLOCK_NETHER_SPROUTS_FALL"), + Sound::BlockNetherSproutsHit { .. } => f.write_str("BLOCK_NETHER_SPROUTS_HIT"), + Sound::BlockNetherSproutsPlace { .. } => f.write_str("BLOCK_NETHER_SPROUTS_PLACE"), + Sound::BlockNetherSproutsStep { .. } => f.write_str("BLOCK_NETHER_SPROUTS_STEP"), + Sound::BlockNetherWartBreak { .. } => f.write_str("BLOCK_NETHER_WART_BREAK"), + Sound::BlockNetherWoodBreak { .. } => f.write_str("BLOCK_NETHER_WOOD_BREAK"), + Sound::BlockNetherWoodButtonClickOff { .. } => { + f.write_str("BLOCK_NETHER_WOOD_BUTTON_CLICK_OFF") + } + Sound::BlockNetherWoodButtonClickOn { .. } => { + f.write_str("BLOCK_NETHER_WOOD_BUTTON_CLICK_ON") + } + Sound::BlockNetherWoodDoorClose { .. } => f.write_str("BLOCK_NETHER_WOOD_DOOR_CLOSE"), + Sound::BlockNetherWoodDoorOpen { .. } => f.write_str("BLOCK_NETHER_WOOD_DOOR_OPEN"), + Sound::BlockNetherWoodFall { .. } => f.write_str("BLOCK_NETHER_WOOD_FALL"), + Sound::BlockNetherWoodFenceGateClose { .. } => { + f.write_str("BLOCK_NETHER_WOOD_FENCE_GATE_CLOSE") + } + Sound::BlockNetherWoodFenceGateOpen { .. } => { + f.write_str("BLOCK_NETHER_WOOD_FENCE_GATE_OPEN") + } + Sound::BlockNetherWoodHangingSignBreak { .. } => { + f.write_str("BLOCK_NETHER_WOOD_HANGING_SIGN_BREAK") + } + Sound::BlockNetherWoodHangingSignFall { .. } => { + f.write_str("BLOCK_NETHER_WOOD_HANGING_SIGN_FALL") + } + Sound::BlockNetherWoodHangingSignHit { .. } => { + f.write_str("BLOCK_NETHER_WOOD_HANGING_SIGN_HIT") + } + Sound::BlockNetherWoodHangingSignPlace { .. } => { + f.write_str("BLOCK_NETHER_WOOD_HANGING_SIGN_PLACE") + } + Sound::BlockNetherWoodHangingSignStep { .. } => { + f.write_str("BLOCK_NETHER_WOOD_HANGING_SIGN_STEP") + } + Sound::BlockNetherWoodHit { .. } => f.write_str("BLOCK_NETHER_WOOD_HIT"), + Sound::BlockNetherWoodPlace { .. } => f.write_str("BLOCK_NETHER_WOOD_PLACE"), + Sound::BlockNetherWoodPressurePlateClickOff { .. } => { + f.write_str("BLOCK_NETHER_WOOD_PRESSURE_PLATE_CLICK_OFF") + } + Sound::BlockNetherWoodPressurePlateClickOn { .. } => { + f.write_str("BLOCK_NETHER_WOOD_PRESSURE_PLATE_CLICK_ON") + } + Sound::BlockNetherWoodStep { .. } => f.write_str("BLOCK_NETHER_WOOD_STEP"), + Sound::BlockNetherWoodTrapdoorClose { .. } => { + f.write_str("BLOCK_NETHER_WOOD_TRAPDOOR_CLOSE") + } + Sound::BlockNetherWoodTrapdoorOpen { .. } => { + f.write_str("BLOCK_NETHER_WOOD_TRAPDOOR_OPEN") + } + Sound::BlockNoteBlockBanjo { .. } => f.write_str("BLOCK_NOTE_BLOCK_BANJO"), + Sound::BlockNoteBlockBasedrum { .. } => f.write_str("BLOCK_NOTE_BLOCK_BASEDRUM"), + Sound::BlockNoteBlockBass { .. } => f.write_str("BLOCK_NOTE_BLOCK_BASS"), + Sound::BlockNoteBlockBell { .. } => f.write_str("BLOCK_NOTE_BLOCK_BELL"), + Sound::BlockNoteBlockBit { .. } => f.write_str("BLOCK_NOTE_BLOCK_BIT"), + Sound::BlockNoteBlockChime { .. } => f.write_str("BLOCK_NOTE_BLOCK_CHIME"), + Sound::BlockNoteBlockCowBell { .. } => f.write_str("BLOCK_NOTE_BLOCK_COW_BELL"), + Sound::BlockNoteBlockDidgeridoo { .. } => f.write_str("BLOCK_NOTE_BLOCK_DIDGERIDOO"), + Sound::BlockNoteBlockFlute { .. } => f.write_str("BLOCK_NOTE_BLOCK_FLUTE"), + Sound::BlockNoteBlockGuitar { .. } => f.write_str("BLOCK_NOTE_BLOCK_GUITAR"), + Sound::BlockNoteBlockHarp { .. } => f.write_str("BLOCK_NOTE_BLOCK_HARP"), + Sound::BlockNoteBlockHat { .. } => f.write_str("BLOCK_NOTE_BLOCK_HAT"), + Sound::BlockNoteBlockImitateCreeper { .. } => { + f.write_str("BLOCK_NOTE_BLOCK_IMITATE_CREEPER") + } + Sound::BlockNoteBlockImitateEnderDragon { .. } => { + f.write_str("BLOCK_NOTE_BLOCK_IMITATE_ENDER_DRAGON") + } + Sound::BlockNoteBlockImitatePiglin { .. } => { + f.write_str("BLOCK_NOTE_BLOCK_IMITATE_PIGLIN") + } + Sound::BlockNoteBlockImitateSkeleton { .. } => { + f.write_str("BLOCK_NOTE_BLOCK_IMITATE_SKELETON") + } + Sound::BlockNoteBlockImitateWitherSkeleton { .. } => { + f.write_str("BLOCK_NOTE_BLOCK_IMITATE_WITHER_SKELETON") + } + Sound::BlockNoteBlockImitateZombie { .. } => { + f.write_str("BLOCK_NOTE_BLOCK_IMITATE_ZOMBIE") + } + Sound::BlockNoteBlockIronXylophone { .. } => { + f.write_str("BLOCK_NOTE_BLOCK_IRON_XYLOPHONE") + } + Sound::BlockNoteBlockPling { .. } => f.write_str("BLOCK_NOTE_BLOCK_PLING"), + Sound::BlockNoteBlockSnare { .. } => f.write_str("BLOCK_NOTE_BLOCK_SNARE"), + Sound::BlockNoteBlockXylophone { .. } => f.write_str("BLOCK_NOTE_BLOCK_XYLOPHONE"), + Sound::BlockNyliumBreak { .. } => f.write_str("BLOCK_NYLIUM_BREAK"), + Sound::BlockNyliumFall { .. } => f.write_str("BLOCK_NYLIUM_FALL"), + Sound::BlockNyliumHit { .. } => f.write_str("BLOCK_NYLIUM_HIT"), + Sound::BlockNyliumPlace { .. } => f.write_str("BLOCK_NYLIUM_PLACE"), + Sound::BlockNyliumStep { .. } => f.write_str("BLOCK_NYLIUM_STEP"), + Sound::BlockPackedMudBreak { .. } => f.write_str("BLOCK_PACKED_MUD_BREAK"), + Sound::BlockPackedMudFall { .. } => f.write_str("BLOCK_PACKED_MUD_FALL"), + Sound::BlockPackedMudHit { .. } => f.write_str("BLOCK_PACKED_MUD_HIT"), + Sound::BlockPackedMudPlace { .. } => f.write_str("BLOCK_PACKED_MUD_PLACE"), + Sound::BlockPackedMudStep { .. } => f.write_str("BLOCK_PACKED_MUD_STEP"), + Sound::BlockPinkPetalsBreak { .. } => f.write_str("BLOCK_PINK_PETALS_BREAK"), + Sound::BlockPinkPetalsFall { .. } => f.write_str("BLOCK_PINK_PETALS_FALL"), + Sound::BlockPinkPetalsHit { .. } => f.write_str("BLOCK_PINK_PETALS_HIT"), + Sound::BlockPinkPetalsPlace { .. } => f.write_str("BLOCK_PINK_PETALS_PLACE"), + Sound::BlockPinkPetalsStep { .. } => f.write_str("BLOCK_PINK_PETALS_STEP"), + Sound::BlockPistonContract { .. } => f.write_str("BLOCK_PISTON_CONTRACT"), + Sound::BlockPistonExtend { .. } => f.write_str("BLOCK_PISTON_EXTEND"), + Sound::BlockPointedDripstoneBreak { .. } => { + f.write_str("BLOCK_POINTED_DRIPSTONE_BREAK") + } + Sound::BlockPointedDripstoneDripLava { .. } => { + f.write_str("BLOCK_POINTED_DRIPSTONE_DRIP_LAVA") + } + Sound::BlockPointedDripstoneDripLavaIntoCauldron { .. } => { + f.write_str("BLOCK_POINTED_DRIPSTONE_DRIP_LAVA_INTO_CAULDRON") + } + Sound::BlockPointedDripstoneDripWater { .. } => { + f.write_str("BLOCK_POINTED_DRIPSTONE_DRIP_WATER") + } + Sound::BlockPointedDripstoneDripWaterIntoCauldron { .. } => { + f.write_str("BLOCK_POINTED_DRIPSTONE_DRIP_WATER_INTO_CAULDRON") + } + Sound::BlockPointedDripstoneFall { .. } => f.write_str("BLOCK_POINTED_DRIPSTONE_FALL"), + Sound::BlockPointedDripstoneHit { .. } => f.write_str("BLOCK_POINTED_DRIPSTONE_HIT"), + Sound::BlockPointedDripstoneLand { .. } => f.write_str("BLOCK_POINTED_DRIPSTONE_LAND"), + Sound::BlockPointedDripstonePlace { .. } => { + f.write_str("BLOCK_POINTED_DRIPSTONE_PLACE") + } + Sound::BlockPointedDripstoneStep { .. } => f.write_str("BLOCK_POINTED_DRIPSTONE_STEP"), + Sound::BlockPolishedDeepslateBreak { .. } => { + f.write_str("BLOCK_POLISHED_DEEPSLATE_BREAK") + } + Sound::BlockPolishedDeepslateFall { .. } => { + f.write_str("BLOCK_POLISHED_DEEPSLATE_FALL") + } + Sound::BlockPolishedDeepslateHit { .. } => f.write_str("BLOCK_POLISHED_DEEPSLATE_HIT"), + Sound::BlockPolishedDeepslatePlace { .. } => { + f.write_str("BLOCK_POLISHED_DEEPSLATE_PLACE") + } + Sound::BlockPolishedDeepslateStep { .. } => { + f.write_str("BLOCK_POLISHED_DEEPSLATE_STEP") + } + Sound::BlockPolishedTuffBreak { .. } => f.write_str("BLOCK_POLISHED_TUFF_BREAK"), + Sound::BlockPolishedTuffFall { .. } => f.write_str("BLOCK_POLISHED_TUFF_FALL"), + Sound::BlockPolishedTuffHit { .. } => f.write_str("BLOCK_POLISHED_TUFF_HIT"), + Sound::BlockPolishedTuffPlace { .. } => f.write_str("BLOCK_POLISHED_TUFF_PLACE"), + Sound::BlockPolishedTuffStep { .. } => f.write_str("BLOCK_POLISHED_TUFF_STEP"), + Sound::BlockPortalAmbient { .. } => f.write_str("BLOCK_PORTAL_AMBIENT"), + Sound::BlockPortalTravel { .. } => f.write_str("BLOCK_PORTAL_TRAVEL"), + Sound::BlockPortalTrigger { .. } => f.write_str("BLOCK_PORTAL_TRIGGER"), + Sound::BlockPowderSnowBreak { .. } => f.write_str("BLOCK_POWDER_SNOW_BREAK"), + Sound::BlockPowderSnowFall { .. } => f.write_str("BLOCK_POWDER_SNOW_FALL"), + Sound::BlockPowderSnowHit { .. } => f.write_str("BLOCK_POWDER_SNOW_HIT"), + Sound::BlockPowderSnowPlace { .. } => f.write_str("BLOCK_POWDER_SNOW_PLACE"), + Sound::BlockPowderSnowStep { .. } => f.write_str("BLOCK_POWDER_SNOW_STEP"), + Sound::BlockPumpkinCarve { .. } => f.write_str("BLOCK_PUMPKIN_CARVE"), + Sound::BlockRedstoneTorchBurnout { .. } => f.write_str("BLOCK_REDSTONE_TORCH_BURNOUT"), + Sound::BlockRespawnAnchorAmbient { .. } => f.write_str("BLOCK_RESPAWN_ANCHOR_AMBIENT"), + Sound::BlockRespawnAnchorCharge { .. } => f.write_str("BLOCK_RESPAWN_ANCHOR_CHARGE"), + Sound::BlockRespawnAnchorDeplete { .. } => f.write_str("BLOCK_RESPAWN_ANCHOR_DEPLETE"), + Sound::BlockRespawnAnchorSetSpawn { .. } => { + f.write_str("BLOCK_RESPAWN_ANCHOR_SET_SPAWN") + } + Sound::BlockRootedDirtBreak { .. } => f.write_str("BLOCK_ROOTED_DIRT_BREAK"), + Sound::BlockRootedDirtFall { .. } => f.write_str("BLOCK_ROOTED_DIRT_FALL"), + Sound::BlockRootedDirtHit { .. } => f.write_str("BLOCK_ROOTED_DIRT_HIT"), + Sound::BlockRootedDirtPlace { .. } => f.write_str("BLOCK_ROOTED_DIRT_PLACE"), + Sound::BlockRootedDirtStep { .. } => f.write_str("BLOCK_ROOTED_DIRT_STEP"), + Sound::BlockRootsBreak { .. } => f.write_str("BLOCK_ROOTS_BREAK"), + Sound::BlockRootsFall { .. } => f.write_str("BLOCK_ROOTS_FALL"), + Sound::BlockRootsHit { .. } => f.write_str("BLOCK_ROOTS_HIT"), + Sound::BlockRootsPlace { .. } => f.write_str("BLOCK_ROOTS_PLACE"), + Sound::BlockRootsStep { .. } => f.write_str("BLOCK_ROOTS_STEP"), + Sound::BlockSandBreak { .. } => f.write_str("BLOCK_SAND_BREAK"), + Sound::BlockSandFall { .. } => f.write_str("BLOCK_SAND_FALL"), + Sound::BlockSandHit { .. } => f.write_str("BLOCK_SAND_HIT"), + Sound::BlockSandPlace { .. } => f.write_str("BLOCK_SAND_PLACE"), + Sound::BlockSandStep { .. } => f.write_str("BLOCK_SAND_STEP"), + Sound::BlockScaffoldingBreak { .. } => f.write_str("BLOCK_SCAFFOLDING_BREAK"), + Sound::BlockScaffoldingFall { .. } => f.write_str("BLOCK_SCAFFOLDING_FALL"), + Sound::BlockScaffoldingHit { .. } => f.write_str("BLOCK_SCAFFOLDING_HIT"), + Sound::BlockScaffoldingPlace { .. } => f.write_str("BLOCK_SCAFFOLDING_PLACE"), + Sound::BlockScaffoldingStep { .. } => f.write_str("BLOCK_SCAFFOLDING_STEP"), + Sound::BlockSculkBreak { .. } => f.write_str("BLOCK_SCULK_BREAK"), + Sound::BlockSculkCatalystBloom { .. } => f.write_str("BLOCK_SCULK_CATALYST_BLOOM"), + Sound::BlockSculkCatalystBreak { .. } => f.write_str("BLOCK_SCULK_CATALYST_BREAK"), + Sound::BlockSculkCatalystFall { .. } => f.write_str("BLOCK_SCULK_CATALYST_FALL"), + Sound::BlockSculkCatalystHit { .. } => f.write_str("BLOCK_SCULK_CATALYST_HIT"), + Sound::BlockSculkCatalystPlace { .. } => f.write_str("BLOCK_SCULK_CATALYST_PLACE"), + Sound::BlockSculkCatalystStep { .. } => f.write_str("BLOCK_SCULK_CATALYST_STEP"), + Sound::BlockSculkCharge { .. } => f.write_str("BLOCK_SCULK_CHARGE"), + Sound::BlockSculkFall { .. } => f.write_str("BLOCK_SCULK_FALL"), + Sound::BlockSculkHit { .. } => f.write_str("BLOCK_SCULK_HIT"), + Sound::BlockSculkPlace { .. } => f.write_str("BLOCK_SCULK_PLACE"), + Sound::BlockSculkSensorBreak { .. } => f.write_str("BLOCK_SCULK_SENSOR_BREAK"), + Sound::BlockSculkSensorClicking { .. } => f.write_str("BLOCK_SCULK_SENSOR_CLICKING"), + Sound::BlockSculkSensorClickingStop { .. } => { + f.write_str("BLOCK_SCULK_SENSOR_CLICKING_STOP") + } + Sound::BlockSculkSensorFall { .. } => f.write_str("BLOCK_SCULK_SENSOR_FALL"), + Sound::BlockSculkSensorHit { .. } => f.write_str("BLOCK_SCULK_SENSOR_HIT"), + Sound::BlockSculkSensorPlace { .. } => f.write_str("BLOCK_SCULK_SENSOR_PLACE"), + Sound::BlockSculkSensorStep { .. } => f.write_str("BLOCK_SCULK_SENSOR_STEP"), + Sound::BlockSculkShriekerBreak { .. } => f.write_str("BLOCK_SCULK_SHRIEKER_BREAK"), + Sound::BlockSculkShriekerFall { .. } => f.write_str("BLOCK_SCULK_SHRIEKER_FALL"), + Sound::BlockSculkShriekerHit { .. } => f.write_str("BLOCK_SCULK_SHRIEKER_HIT"), + Sound::BlockSculkShriekerPlace { .. } => f.write_str("BLOCK_SCULK_SHRIEKER_PLACE"), + Sound::BlockSculkShriekerShriek { .. } => f.write_str("BLOCK_SCULK_SHRIEKER_SHRIEK"), + Sound::BlockSculkShriekerStep { .. } => f.write_str("BLOCK_SCULK_SHRIEKER_STEP"), + Sound::BlockSculkSpread { .. } => f.write_str("BLOCK_SCULK_SPREAD"), + Sound::BlockSculkStep { .. } => f.write_str("BLOCK_SCULK_STEP"), + Sound::BlockSculkVeinBreak { .. } => f.write_str("BLOCK_SCULK_VEIN_BREAK"), + Sound::BlockSculkVeinFall { .. } => f.write_str("BLOCK_SCULK_VEIN_FALL"), + Sound::BlockSculkVeinHit { .. } => f.write_str("BLOCK_SCULK_VEIN_HIT"), + Sound::BlockSculkVeinPlace { .. } => f.write_str("BLOCK_SCULK_VEIN_PLACE"), + Sound::BlockSculkVeinStep { .. } => f.write_str("BLOCK_SCULK_VEIN_STEP"), + Sound::BlockShroomlightBreak { .. } => f.write_str("BLOCK_SHROOMLIGHT_BREAK"), + Sound::BlockShroomlightFall { .. } => f.write_str("BLOCK_SHROOMLIGHT_FALL"), + Sound::BlockShroomlightHit { .. } => f.write_str("BLOCK_SHROOMLIGHT_HIT"), + Sound::BlockShroomlightPlace { .. } => f.write_str("BLOCK_SHROOMLIGHT_PLACE"), + Sound::BlockShroomlightStep { .. } => f.write_str("BLOCK_SHROOMLIGHT_STEP"), + Sound::BlockShulkerBoxClose { .. } => f.write_str("BLOCK_SHULKER_BOX_CLOSE"), + Sound::BlockShulkerBoxOpen { .. } => f.write_str("BLOCK_SHULKER_BOX_OPEN"), + Sound::BlockSignWaxedInteractFail { .. } => { + f.write_str("BLOCK_SIGN_WAXED_INTERACT_FAIL") + } + Sound::BlockSlimeBlockBreak { .. } => f.write_str("BLOCK_SLIME_BLOCK_BREAK"), + Sound::BlockSlimeBlockFall { .. } => f.write_str("BLOCK_SLIME_BLOCK_FALL"), + Sound::BlockSlimeBlockHit { .. } => f.write_str("BLOCK_SLIME_BLOCK_HIT"), + Sound::BlockSlimeBlockPlace { .. } => f.write_str("BLOCK_SLIME_BLOCK_PLACE"), + Sound::BlockSlimeBlockStep { .. } => f.write_str("BLOCK_SLIME_BLOCK_STEP"), + Sound::BlockSmallAmethystBudBreak { .. } => { + f.write_str("BLOCK_SMALL_AMETHYST_BUD_BREAK") + } + Sound::BlockSmallAmethystBudPlace { .. } => { + f.write_str("BLOCK_SMALL_AMETHYST_BUD_PLACE") + } + Sound::BlockSmallDripleafBreak { .. } => f.write_str("BLOCK_SMALL_DRIPLEAF_BREAK"), + Sound::BlockSmallDripleafFall { .. } => f.write_str("BLOCK_SMALL_DRIPLEAF_FALL"), + Sound::BlockSmallDripleafHit { .. } => f.write_str("BLOCK_SMALL_DRIPLEAF_HIT"), + Sound::BlockSmallDripleafPlace { .. } => f.write_str("BLOCK_SMALL_DRIPLEAF_PLACE"), + Sound::BlockSmallDripleafStep { .. } => f.write_str("BLOCK_SMALL_DRIPLEAF_STEP"), + Sound::BlockSmithingTableUse { .. } => f.write_str("BLOCK_SMITHING_TABLE_USE"), + Sound::BlockSmokerSmoke { .. } => f.write_str("BLOCK_SMOKER_SMOKE"), + Sound::BlockSnifferEggCrack { .. } => f.write_str("BLOCK_SNIFFER_EGG_CRACK"), + Sound::BlockSnifferEggHatch { .. } => f.write_str("BLOCK_SNIFFER_EGG_HATCH"), + Sound::BlockSnifferEggPlop { .. } => f.write_str("BLOCK_SNIFFER_EGG_PLOP"), + Sound::BlockSnowBreak { .. } => f.write_str("BLOCK_SNOW_BREAK"), + Sound::BlockSnowFall { .. } => f.write_str("BLOCK_SNOW_FALL"), + Sound::BlockSnowHit { .. } => f.write_str("BLOCK_SNOW_HIT"), + Sound::BlockSnowPlace { .. } => f.write_str("BLOCK_SNOW_PLACE"), + Sound::BlockSnowStep { .. } => f.write_str("BLOCK_SNOW_STEP"), + Sound::BlockSoulSandBreak { .. } => f.write_str("BLOCK_SOUL_SAND_BREAK"), + Sound::BlockSoulSandFall { .. } => f.write_str("BLOCK_SOUL_SAND_FALL"), + Sound::BlockSoulSandHit { .. } => f.write_str("BLOCK_SOUL_SAND_HIT"), + Sound::BlockSoulSandPlace { .. } => f.write_str("BLOCK_SOUL_SAND_PLACE"), + Sound::BlockSoulSandStep { .. } => f.write_str("BLOCK_SOUL_SAND_STEP"), + Sound::BlockSoulSoilBreak { .. } => f.write_str("BLOCK_SOUL_SOIL_BREAK"), + Sound::BlockSoulSoilFall { .. } => f.write_str("BLOCK_SOUL_SOIL_FALL"), + Sound::BlockSoulSoilHit { .. } => f.write_str("BLOCK_SOUL_SOIL_HIT"), + Sound::BlockSoulSoilPlace { .. } => f.write_str("BLOCK_SOUL_SOIL_PLACE"), + Sound::BlockSoulSoilStep { .. } => f.write_str("BLOCK_SOUL_SOIL_STEP"), + Sound::BlockSpongeAbsorb { .. } => f.write_str("BLOCK_SPONGE_ABSORB"), + Sound::BlockSpongeBreak { .. } => f.write_str("BLOCK_SPONGE_BREAK"), + Sound::BlockSpongeFall { .. } => f.write_str("BLOCK_SPONGE_FALL"), + Sound::BlockSpongeHit { .. } => f.write_str("BLOCK_SPONGE_HIT"), + Sound::BlockSpongePlace { .. } => f.write_str("BLOCK_SPONGE_PLACE"), + Sound::BlockSpongeStep { .. } => f.write_str("BLOCK_SPONGE_STEP"), + Sound::BlockSporeBlossomBreak { .. } => f.write_str("BLOCK_SPORE_BLOSSOM_BREAK"), + Sound::BlockSporeBlossomFall { .. } => f.write_str("BLOCK_SPORE_BLOSSOM_FALL"), + Sound::BlockSporeBlossomHit { .. } => f.write_str("BLOCK_SPORE_BLOSSOM_HIT"), + Sound::BlockSporeBlossomPlace { .. } => f.write_str("BLOCK_SPORE_BLOSSOM_PLACE"), + Sound::BlockSporeBlossomStep { .. } => f.write_str("BLOCK_SPORE_BLOSSOM_STEP"), + Sound::BlockStemBreak { .. } => f.write_str("BLOCK_STEM_BREAK"), + Sound::BlockStemFall { .. } => f.write_str("BLOCK_STEM_FALL"), + Sound::BlockStemHit { .. } => f.write_str("BLOCK_STEM_HIT"), + Sound::BlockStemPlace { .. } => f.write_str("BLOCK_STEM_PLACE"), + Sound::BlockStemStep { .. } => f.write_str("BLOCK_STEM_STEP"), + Sound::BlockStoneBreak { .. } => f.write_str("BLOCK_STONE_BREAK"), + Sound::BlockStoneButtonClickOff { .. } => f.write_str("BLOCK_STONE_BUTTON_CLICK_OFF"), + Sound::BlockStoneButtonClickOn { .. } => f.write_str("BLOCK_STONE_BUTTON_CLICK_ON"), + Sound::BlockStoneFall { .. } => f.write_str("BLOCK_STONE_FALL"), + Sound::BlockStoneHit { .. } => f.write_str("BLOCK_STONE_HIT"), + Sound::BlockStonePlace { .. } => f.write_str("BLOCK_STONE_PLACE"), + Sound::BlockStonePressurePlateClickOff { .. } => { + f.write_str("BLOCK_STONE_PRESSURE_PLATE_CLICK_OFF") + } + Sound::BlockStonePressurePlateClickOn { .. } => { + f.write_str("BLOCK_STONE_PRESSURE_PLATE_CLICK_ON") + } + Sound::BlockStoneStep { .. } => f.write_str("BLOCK_STONE_STEP"), + Sound::BlockSuspiciousGravelBreak { .. } => { + f.write_str("BLOCK_SUSPICIOUS_GRAVEL_BREAK") + } + Sound::BlockSuspiciousGravelFall { .. } => f.write_str("BLOCK_SUSPICIOUS_GRAVEL_FALL"), + Sound::BlockSuspiciousGravelHit { .. } => f.write_str("BLOCK_SUSPICIOUS_GRAVEL_HIT"), + Sound::BlockSuspiciousGravelPlace { .. } => { + f.write_str("BLOCK_SUSPICIOUS_GRAVEL_PLACE") + } + Sound::BlockSuspiciousGravelStep { .. } => f.write_str("BLOCK_SUSPICIOUS_GRAVEL_STEP"), + Sound::BlockSuspiciousSandBreak { .. } => f.write_str("BLOCK_SUSPICIOUS_SAND_BREAK"), + Sound::BlockSuspiciousSandFall { .. } => f.write_str("BLOCK_SUSPICIOUS_SAND_FALL"), + Sound::BlockSuspiciousSandHit { .. } => f.write_str("BLOCK_SUSPICIOUS_SAND_HIT"), + Sound::BlockSuspiciousSandPlace { .. } => f.write_str("BLOCK_SUSPICIOUS_SAND_PLACE"), + Sound::BlockSuspiciousSandStep { .. } => f.write_str("BLOCK_SUSPICIOUS_SAND_STEP"), + Sound::BlockSweetBerryBushBreak { .. } => f.write_str("BLOCK_SWEET_BERRY_BUSH_BREAK"), + Sound::BlockSweetBerryBushPickBerries { .. } => { + f.write_str("BLOCK_SWEET_BERRY_BUSH_PICK_BERRIES") + } + Sound::BlockSweetBerryBushPlace { .. } => f.write_str("BLOCK_SWEET_BERRY_BUSH_PLACE"), + Sound::BlockTrialSpawnerAboutToSpawnItem { .. } => { + f.write_str("BLOCK_TRIAL_SPAWNER_ABOUT_TO_SPAWN_ITEM") + } + Sound::BlockTrialSpawnerAmbient { .. } => f.write_str("BLOCK_TRIAL_SPAWNER_AMBIENT"), + Sound::BlockTrialSpawnerAmbientOminous { .. } => { + f.write_str("BLOCK_TRIAL_SPAWNER_AMBIENT_OMINOUS") + } + Sound::BlockTrialSpawnerBreak { .. } => f.write_str("BLOCK_TRIAL_SPAWNER_BREAK"), + Sound::BlockTrialSpawnerCloseShutter { .. } => { + f.write_str("BLOCK_TRIAL_SPAWNER_CLOSE_SHUTTER") + } + Sound::BlockTrialSpawnerDetectPlayer { .. } => { + f.write_str("BLOCK_TRIAL_SPAWNER_DETECT_PLAYER") + } + Sound::BlockTrialSpawnerEjectItem { .. } => { + f.write_str("BLOCK_TRIAL_SPAWNER_EJECT_ITEM") + } + Sound::BlockTrialSpawnerFall { .. } => f.write_str("BLOCK_TRIAL_SPAWNER_FALL"), + Sound::BlockTrialSpawnerHit { .. } => f.write_str("BLOCK_TRIAL_SPAWNER_HIT"), + Sound::BlockTrialSpawnerOminousActivate { .. } => { + f.write_str("BLOCK_TRIAL_SPAWNER_OMINOUS_ACTIVATE") + } + Sound::BlockTrialSpawnerOpenShutter { .. } => { + f.write_str("BLOCK_TRIAL_SPAWNER_OPEN_SHUTTER") + } + Sound::BlockTrialSpawnerPlace { .. } => f.write_str("BLOCK_TRIAL_SPAWNER_PLACE"), + Sound::BlockTrialSpawnerSpawnItem { .. } => { + f.write_str("BLOCK_TRIAL_SPAWNER_SPAWN_ITEM") + } + Sound::BlockTrialSpawnerSpawnItemBegin { .. } => { + f.write_str("BLOCK_TRIAL_SPAWNER_SPAWN_ITEM_BEGIN") + } + Sound::BlockTrialSpawnerSpawnMob { .. } => f.write_str("BLOCK_TRIAL_SPAWNER_SPAWN_MOB"), + Sound::BlockTrialSpawnerStep { .. } => f.write_str("BLOCK_TRIAL_SPAWNER_STEP"), + Sound::BlockTripwireAttach { .. } => f.write_str("BLOCK_TRIPWIRE_ATTACH"), + Sound::BlockTripwireClickOff { .. } => f.write_str("BLOCK_TRIPWIRE_CLICK_OFF"), + Sound::BlockTripwireClickOn { .. } => f.write_str("BLOCK_TRIPWIRE_CLICK_ON"), + Sound::BlockTripwireDetach { .. } => f.write_str("BLOCK_TRIPWIRE_DETACH"), + Sound::BlockTuffBreak { .. } => f.write_str("BLOCK_TUFF_BREAK"), + Sound::BlockTuffBricksBreak { .. } => f.write_str("BLOCK_TUFF_BRICKS_BREAK"), + Sound::BlockTuffBricksFall { .. } => f.write_str("BLOCK_TUFF_BRICKS_FALL"), + Sound::BlockTuffBricksHit { .. } => f.write_str("BLOCK_TUFF_BRICKS_HIT"), + Sound::BlockTuffBricksPlace { .. } => f.write_str("BLOCK_TUFF_BRICKS_PLACE"), + Sound::BlockTuffBricksStep { .. } => f.write_str("BLOCK_TUFF_BRICKS_STEP"), + Sound::BlockTuffFall { .. } => f.write_str("BLOCK_TUFF_FALL"), + Sound::BlockTuffHit { .. } => f.write_str("BLOCK_TUFF_HIT"), + Sound::BlockTuffPlace { .. } => f.write_str("BLOCK_TUFF_PLACE"), + Sound::BlockTuffStep { .. } => f.write_str("BLOCK_TUFF_STEP"), + Sound::BlockVaultActivate { .. } => f.write_str("BLOCK_VAULT_ACTIVATE"), + Sound::BlockVaultAmbient { .. } => f.write_str("BLOCK_VAULT_AMBIENT"), + Sound::BlockVaultBreak { .. } => f.write_str("BLOCK_VAULT_BREAK"), + Sound::BlockVaultCloseShutter { .. } => f.write_str("BLOCK_VAULT_CLOSE_SHUTTER"), + Sound::BlockVaultDeactivate { .. } => f.write_str("BLOCK_VAULT_DEACTIVATE"), + Sound::BlockVaultEjectItem { .. } => f.write_str("BLOCK_VAULT_EJECT_ITEM"), + Sound::BlockVaultFall { .. } => f.write_str("BLOCK_VAULT_FALL"), + Sound::BlockVaultHit { .. } => f.write_str("BLOCK_VAULT_HIT"), + Sound::BlockVaultInsertItem { .. } => f.write_str("BLOCK_VAULT_INSERT_ITEM"), + Sound::BlockVaultInsertItemFail { .. } => f.write_str("BLOCK_VAULT_INSERT_ITEM_FAIL"), + Sound::BlockVaultOpenShutter { .. } => f.write_str("BLOCK_VAULT_OPEN_SHUTTER"), + Sound::BlockVaultPlace { .. } => f.write_str("BLOCK_VAULT_PLACE"), + Sound::BlockVaultRejectRewardedPlayer { .. } => { + f.write_str("BLOCK_VAULT_REJECT_REWARDED_PLAYER") + } + Sound::BlockVaultStep { .. } => f.write_str("BLOCK_VAULT_STEP"), + Sound::BlockVineBreak { .. } => f.write_str("BLOCK_VINE_BREAK"), + Sound::BlockVineFall { .. } => f.write_str("BLOCK_VINE_FALL"), + Sound::BlockVineHit { .. } => f.write_str("BLOCK_VINE_HIT"), + Sound::BlockVinePlace { .. } => f.write_str("BLOCK_VINE_PLACE"), + Sound::BlockVineStep { .. } => f.write_str("BLOCK_VINE_STEP"), + Sound::BlockWartBlockBreak { .. } => f.write_str("BLOCK_WART_BLOCK_BREAK"), + Sound::BlockWartBlockFall { .. } => f.write_str("BLOCK_WART_BLOCK_FALL"), + Sound::BlockWartBlockHit { .. } => f.write_str("BLOCK_WART_BLOCK_HIT"), + Sound::BlockWartBlockPlace { .. } => f.write_str("BLOCK_WART_BLOCK_PLACE"), + Sound::BlockWartBlockStep { .. } => f.write_str("BLOCK_WART_BLOCK_STEP"), + Sound::BlockWaterAmbient { .. } => f.write_str("BLOCK_WATER_AMBIENT"), + Sound::BlockWeepingVinesBreak { .. } => f.write_str("BLOCK_WEEPING_VINES_BREAK"), + Sound::BlockWeepingVinesFall { .. } => f.write_str("BLOCK_WEEPING_VINES_FALL"), + Sound::BlockWeepingVinesHit { .. } => f.write_str("BLOCK_WEEPING_VINES_HIT"), + Sound::BlockWeepingVinesPlace { .. } => f.write_str("BLOCK_WEEPING_VINES_PLACE"), + Sound::BlockWeepingVinesStep { .. } => f.write_str("BLOCK_WEEPING_VINES_STEP"), + Sound::BlockWetGrassBreak { .. } => f.write_str("BLOCK_WET_GRASS_BREAK"), + Sound::BlockWetGrassFall { .. } => f.write_str("BLOCK_WET_GRASS_FALL"), + Sound::BlockWetGrassHit { .. } => f.write_str("BLOCK_WET_GRASS_HIT"), + Sound::BlockWetGrassPlace { .. } => f.write_str("BLOCK_WET_GRASS_PLACE"), + Sound::BlockWetGrassStep { .. } => f.write_str("BLOCK_WET_GRASS_STEP"), + Sound::BlockWetSpongeBreak { .. } => f.write_str("BLOCK_WET_SPONGE_BREAK"), + Sound::BlockWetSpongeDries { .. } => f.write_str("BLOCK_WET_SPONGE_DRIES"), + Sound::BlockWetSpongeFall { .. } => f.write_str("BLOCK_WET_SPONGE_FALL"), + Sound::BlockWetSpongeHit { .. } => f.write_str("BLOCK_WET_SPONGE_HIT"), + Sound::BlockWetSpongePlace { .. } => f.write_str("BLOCK_WET_SPONGE_PLACE"), + Sound::BlockWetSpongeStep { .. } => f.write_str("BLOCK_WET_SPONGE_STEP"), + Sound::BlockWoodenButtonClickOff { .. } => f.write_str("BLOCK_WOODEN_BUTTON_CLICK_OFF"), + Sound::BlockWoodenButtonClickOn { .. } => f.write_str("BLOCK_WOODEN_BUTTON_CLICK_ON"), + Sound::BlockWoodenDoorClose { .. } => f.write_str("BLOCK_WOODEN_DOOR_CLOSE"), + Sound::BlockWoodenDoorOpen { .. } => f.write_str("BLOCK_WOODEN_DOOR_OPEN"), + Sound::BlockWoodenPressurePlateClickOff { .. } => { + f.write_str("BLOCK_WOODEN_PRESSURE_PLATE_CLICK_OFF") + } + Sound::BlockWoodenPressurePlateClickOn { .. } => { + f.write_str("BLOCK_WOODEN_PRESSURE_PLATE_CLICK_ON") + } + Sound::BlockWoodenTrapdoorClose { .. } => f.write_str("BLOCK_WOODEN_TRAPDOOR_CLOSE"), + Sound::BlockWoodenTrapdoorOpen { .. } => f.write_str("BLOCK_WOODEN_TRAPDOOR_OPEN"), + Sound::BlockWoodBreak { .. } => f.write_str("BLOCK_WOOD_BREAK"), + Sound::BlockWoodFall { .. } => f.write_str("BLOCK_WOOD_FALL"), + Sound::BlockWoodHit { .. } => f.write_str("BLOCK_WOOD_HIT"), + Sound::BlockWoodPlace { .. } => f.write_str("BLOCK_WOOD_PLACE"), + Sound::BlockWoodStep { .. } => f.write_str("BLOCK_WOOD_STEP"), + Sound::BlockWoolBreak { .. } => f.write_str("BLOCK_WOOL_BREAK"), + Sound::BlockWoolFall { .. } => f.write_str("BLOCK_WOOL_FALL"), + Sound::BlockWoolHit { .. } => f.write_str("BLOCK_WOOL_HIT"), + Sound::BlockWoolPlace { .. } => f.write_str("BLOCK_WOOL_PLACE"), + Sound::BlockWoolStep { .. } => f.write_str("BLOCK_WOOL_STEP"), + Sound::EnchantThornsHit { .. } => f.write_str("ENCHANT_THORNS_HIT"), + Sound::EntityAllayAmbientWithoutItem { .. } => { + f.write_str("ENTITY_ALLAY_AMBIENT_WITHOUT_ITEM") + } + Sound::EntityAllayAmbientWithItem { .. } => { + f.write_str("ENTITY_ALLAY_AMBIENT_WITH_ITEM") + } + Sound::EntityAllayDeath { .. } => f.write_str("ENTITY_ALLAY_DEATH"), + Sound::EntityAllayHurt { .. } => f.write_str("ENTITY_ALLAY_HURT"), + Sound::EntityAllayItemGiven { .. } => f.write_str("ENTITY_ALLAY_ITEM_GIVEN"), + Sound::EntityAllayItemTaken { .. } => f.write_str("ENTITY_ALLAY_ITEM_TAKEN"), + Sound::EntityAllayItemThrown { .. } => f.write_str("ENTITY_ALLAY_ITEM_THROWN"), + Sound::EntityArmadilloAmbient { .. } => f.write_str("ENTITY_ARMADILLO_AMBIENT"), + Sound::EntityArmadilloBrush { .. } => f.write_str("ENTITY_ARMADILLO_BRUSH"), + Sound::EntityArmadilloDeath { .. } => f.write_str("ENTITY_ARMADILLO_DEATH"), + Sound::EntityArmadilloEat { .. } => f.write_str("ENTITY_ARMADILLO_EAT"), + Sound::EntityArmadilloHurt { .. } => f.write_str("ENTITY_ARMADILLO_HURT"), + Sound::EntityArmadilloHurtReduced { .. } => { + f.write_str("ENTITY_ARMADILLO_HURT_REDUCED") + } + Sound::EntityArmadilloLand { .. } => f.write_str("ENTITY_ARMADILLO_LAND"), + Sound::EntityArmadilloPeek { .. } => f.write_str("ENTITY_ARMADILLO_PEEK"), + Sound::EntityArmadilloRoll { .. } => f.write_str("ENTITY_ARMADILLO_ROLL"), + Sound::EntityArmadilloScuteDrop { .. } => f.write_str("ENTITY_ARMADILLO_SCUTE_DROP"), + Sound::EntityArmadilloStep { .. } => f.write_str("ENTITY_ARMADILLO_STEP"), + Sound::EntityArmadilloUnrollFinish { .. } => { + f.write_str("ENTITY_ARMADILLO_UNROLL_FINISH") + } + Sound::EntityArmadilloUnrollStart { .. } => { + f.write_str("ENTITY_ARMADILLO_UNROLL_START") + } + Sound::EntityArmorStandBreak { .. } => f.write_str("ENTITY_ARMOR_STAND_BREAK"), + Sound::EntityArmorStandFall { .. } => f.write_str("ENTITY_ARMOR_STAND_FALL"), + Sound::EntityArmorStandHit { .. } => f.write_str("ENTITY_ARMOR_STAND_HIT"), + Sound::EntityArmorStandPlace { .. } => f.write_str("ENTITY_ARMOR_STAND_PLACE"), + Sound::EntityArrowHit { .. } => f.write_str("ENTITY_ARROW_HIT"), + Sound::EntityArrowHitPlayer { .. } => f.write_str("ENTITY_ARROW_HIT_PLAYER"), + Sound::EntityArrowShoot { .. } => f.write_str("ENTITY_ARROW_SHOOT"), + Sound::EntityAxolotlAttack { .. } => f.write_str("ENTITY_AXOLOTL_ATTACK"), + Sound::EntityAxolotlDeath { .. } => f.write_str("ENTITY_AXOLOTL_DEATH"), + Sound::EntityAxolotlHurt { .. } => f.write_str("ENTITY_AXOLOTL_HURT"), + Sound::EntityAxolotlIdleAir { .. } => f.write_str("ENTITY_AXOLOTL_IDLE_AIR"), + Sound::EntityAxolotlIdleWater { .. } => f.write_str("ENTITY_AXOLOTL_IDLE_WATER"), + Sound::EntityAxolotlSplash { .. } => f.write_str("ENTITY_AXOLOTL_SPLASH"), + Sound::EntityAxolotlSwim { .. } => f.write_str("ENTITY_AXOLOTL_SWIM"), + Sound::EntityBatAmbient { .. } => f.write_str("ENTITY_BAT_AMBIENT"), + Sound::EntityBatDeath { .. } => f.write_str("ENTITY_BAT_DEATH"), + Sound::EntityBatHurt { .. } => f.write_str("ENTITY_BAT_HURT"), + Sound::EntityBatLoop { .. } => f.write_str("ENTITY_BAT_LOOP"), + Sound::EntityBatTakeoff { .. } => f.write_str("ENTITY_BAT_TAKEOFF"), + Sound::EntityBeeDeath { .. } => f.write_str("ENTITY_BEE_DEATH"), + Sound::EntityBeeHurt { .. } => f.write_str("ENTITY_BEE_HURT"), + Sound::EntityBeeLoop { .. } => f.write_str("ENTITY_BEE_LOOP"), + Sound::EntityBeeLoopAggressive { .. } => f.write_str("ENTITY_BEE_LOOP_AGGRESSIVE"), + Sound::EntityBeePollinate { .. } => f.write_str("ENTITY_BEE_POLLINATE"), + Sound::EntityBeeSting { .. } => f.write_str("ENTITY_BEE_STING"), + Sound::EntityBlazeAmbient { .. } => f.write_str("ENTITY_BLAZE_AMBIENT"), + Sound::EntityBlazeBurn { .. } => f.write_str("ENTITY_BLAZE_BURN"), + Sound::EntityBlazeDeath { .. } => f.write_str("ENTITY_BLAZE_DEATH"), + Sound::EntityBlazeHurt { .. } => f.write_str("ENTITY_BLAZE_HURT"), + Sound::EntityBlazeShoot { .. } => f.write_str("ENTITY_BLAZE_SHOOT"), + Sound::EntityBoatPaddleLand { .. } => f.write_str("ENTITY_BOAT_PADDLE_LAND"), + Sound::EntityBoatPaddleWater { .. } => f.write_str("ENTITY_BOAT_PADDLE_WATER"), + Sound::EntityBoggedAmbient { .. } => f.write_str("ENTITY_BOGGED_AMBIENT"), + Sound::EntityBoggedDeath { .. } => f.write_str("ENTITY_BOGGED_DEATH"), + Sound::EntityBoggedHurt { .. } => f.write_str("ENTITY_BOGGED_HURT"), + Sound::EntityBoggedShear { .. } => f.write_str("ENTITY_BOGGED_SHEAR"), + Sound::EntityBoggedStep { .. } => f.write_str("ENTITY_BOGGED_STEP"), + Sound::EntityBreezeCharge { .. } => f.write_str("ENTITY_BREEZE_CHARGE"), + Sound::EntityBreezeDeath { .. } => f.write_str("ENTITY_BREEZE_DEATH"), + Sound::EntityBreezeDeflect { .. } => f.write_str("ENTITY_BREEZE_DEFLECT"), + Sound::EntityBreezeHurt { .. } => f.write_str("ENTITY_BREEZE_HURT"), + Sound::EntityBreezeIdleAir { .. } => f.write_str("ENTITY_BREEZE_IDLE_AIR"), + Sound::EntityBreezeIdleGround { .. } => f.write_str("ENTITY_BREEZE_IDLE_GROUND"), + Sound::EntityBreezeInhale { .. } => f.write_str("ENTITY_BREEZE_INHALE"), + Sound::EntityBreezeJump { .. } => f.write_str("ENTITY_BREEZE_JUMP"), + Sound::EntityBreezeLand { .. } => f.write_str("ENTITY_BREEZE_LAND"), + Sound::EntityBreezeShoot { .. } => f.write_str("ENTITY_BREEZE_SHOOT"), + Sound::EntityBreezeSlide { .. } => f.write_str("ENTITY_BREEZE_SLIDE"), + Sound::EntityBreezeWhirl { .. } => f.write_str("ENTITY_BREEZE_WHIRL"), + Sound::EntityBreezeWindBurst { .. } => f.write_str("ENTITY_BREEZE_WIND_BURST"), + Sound::EntityCamelAmbient { .. } => f.write_str("ENTITY_CAMEL_AMBIENT"), + Sound::EntityCamelDash { .. } => f.write_str("ENTITY_CAMEL_DASH"), + Sound::EntityCamelDashReady { .. } => f.write_str("ENTITY_CAMEL_DASH_READY"), + Sound::EntityCamelDeath { .. } => f.write_str("ENTITY_CAMEL_DEATH"), + Sound::EntityCamelEat { .. } => f.write_str("ENTITY_CAMEL_EAT"), + Sound::EntityCamelHurt { .. } => f.write_str("ENTITY_CAMEL_HURT"), + Sound::EntityCamelSaddle { .. } => f.write_str("ENTITY_CAMEL_SADDLE"), + Sound::EntityCamelSit { .. } => f.write_str("ENTITY_CAMEL_SIT"), + Sound::EntityCamelStand { .. } => f.write_str("ENTITY_CAMEL_STAND"), + Sound::EntityCamelStep { .. } => f.write_str("ENTITY_CAMEL_STEP"), + Sound::EntityCamelStepSand { .. } => f.write_str("ENTITY_CAMEL_STEP_SAND"), + Sound::EntityCatAmbient { .. } => f.write_str("ENTITY_CAT_AMBIENT"), + Sound::EntityCatBegForFood { .. } => f.write_str("ENTITY_CAT_BEG_FOR_FOOD"), + Sound::EntityCatDeath { .. } => f.write_str("ENTITY_CAT_DEATH"), + Sound::EntityCatEat { .. } => f.write_str("ENTITY_CAT_EAT"), + Sound::EntityCatHiss { .. } => f.write_str("ENTITY_CAT_HISS"), + Sound::EntityCatHurt { .. } => f.write_str("ENTITY_CAT_HURT"), + Sound::EntityCatPurr { .. } => f.write_str("ENTITY_CAT_PURR"), + Sound::EntityCatPurreow { .. } => f.write_str("ENTITY_CAT_PURREOW"), + Sound::EntityCatStrayAmbient { .. } => f.write_str("ENTITY_CAT_STRAY_AMBIENT"), + Sound::EntityChickenAmbient { .. } => f.write_str("ENTITY_CHICKEN_AMBIENT"), + Sound::EntityChickenDeath { .. } => f.write_str("ENTITY_CHICKEN_DEATH"), + Sound::EntityChickenEgg { .. } => f.write_str("ENTITY_CHICKEN_EGG"), + Sound::EntityChickenHurt { .. } => f.write_str("ENTITY_CHICKEN_HURT"), + Sound::EntityChickenStep { .. } => f.write_str("ENTITY_CHICKEN_STEP"), + Sound::EntityCodAmbient { .. } => f.write_str("ENTITY_COD_AMBIENT"), + Sound::EntityCodDeath { .. } => f.write_str("ENTITY_COD_DEATH"), + Sound::EntityCodFlop { .. } => f.write_str("ENTITY_COD_FLOP"), + Sound::EntityCodHurt { .. } => f.write_str("ENTITY_COD_HURT"), + Sound::EntityCowAmbient { .. } => f.write_str("ENTITY_COW_AMBIENT"), + Sound::EntityCowDeath { .. } => f.write_str("ENTITY_COW_DEATH"), + Sound::EntityCowHurt { .. } => f.write_str("ENTITY_COW_HURT"), + Sound::EntityCowMilk { .. } => f.write_str("ENTITY_COW_MILK"), + Sound::EntityCowStep { .. } => f.write_str("ENTITY_COW_STEP"), + Sound::EntityCreeperDeath { .. } => f.write_str("ENTITY_CREEPER_DEATH"), + Sound::EntityCreeperHurt { .. } => f.write_str("ENTITY_CREEPER_HURT"), + Sound::EntityCreeperPrimed { .. } => f.write_str("ENTITY_CREEPER_PRIMED"), + Sound::EntityDolphinAmbient { .. } => f.write_str("ENTITY_DOLPHIN_AMBIENT"), + Sound::EntityDolphinAmbientWater { .. } => f.write_str("ENTITY_DOLPHIN_AMBIENT_WATER"), + Sound::EntityDolphinAttack { .. } => f.write_str("ENTITY_DOLPHIN_ATTACK"), + Sound::EntityDolphinDeath { .. } => f.write_str("ENTITY_DOLPHIN_DEATH"), + Sound::EntityDolphinEat { .. } => f.write_str("ENTITY_DOLPHIN_EAT"), + Sound::EntityDolphinHurt { .. } => f.write_str("ENTITY_DOLPHIN_HURT"), + Sound::EntityDolphinJump { .. } => f.write_str("ENTITY_DOLPHIN_JUMP"), + Sound::EntityDolphinPlay { .. } => f.write_str("ENTITY_DOLPHIN_PLAY"), + Sound::EntityDolphinSplash { .. } => f.write_str("ENTITY_DOLPHIN_SPLASH"), + Sound::EntityDolphinSwim { .. } => f.write_str("ENTITY_DOLPHIN_SWIM"), + Sound::EntityDonkeyAmbient { .. } => f.write_str("ENTITY_DONKEY_AMBIENT"), + Sound::EntityDonkeyAngry { .. } => f.write_str("ENTITY_DONKEY_ANGRY"), + Sound::EntityDonkeyChest { .. } => f.write_str("ENTITY_DONKEY_CHEST"), + Sound::EntityDonkeyDeath { .. } => f.write_str("ENTITY_DONKEY_DEATH"), + Sound::EntityDonkeyEat { .. } => f.write_str("ENTITY_DONKEY_EAT"), + Sound::EntityDonkeyHurt { .. } => f.write_str("ENTITY_DONKEY_HURT"), + Sound::EntityDonkeyJump { .. } => f.write_str("ENTITY_DONKEY_JUMP"), + Sound::EntityDragonFireballExplode { .. } => { + f.write_str("ENTITY_DRAGON_FIREBALL_EXPLODE") + } + Sound::EntityDrownedAmbient { .. } => f.write_str("ENTITY_DROWNED_AMBIENT"), + Sound::EntityDrownedAmbientWater { .. } => f.write_str("ENTITY_DROWNED_AMBIENT_WATER"), + Sound::EntityDrownedDeath { .. } => f.write_str("ENTITY_DROWNED_DEATH"), + Sound::EntityDrownedDeathWater { .. } => f.write_str("ENTITY_DROWNED_DEATH_WATER"), + Sound::EntityDrownedHurt { .. } => f.write_str("ENTITY_DROWNED_HURT"), + Sound::EntityDrownedHurtWater { .. } => f.write_str("ENTITY_DROWNED_HURT_WATER"), + Sound::EntityDrownedShoot { .. } => f.write_str("ENTITY_DROWNED_SHOOT"), + Sound::EntityDrownedStep { .. } => f.write_str("ENTITY_DROWNED_STEP"), + Sound::EntityDrownedSwim { .. } => f.write_str("ENTITY_DROWNED_SWIM"), + Sound::EntityEggThrow { .. } => f.write_str("ENTITY_EGG_THROW"), + Sound::EntityElderGuardianAmbient { .. } => { + f.write_str("ENTITY_ELDER_GUARDIAN_AMBIENT") + } + Sound::EntityElderGuardianAmbientLand { .. } => { + f.write_str("ENTITY_ELDER_GUARDIAN_AMBIENT_LAND") + } + Sound::EntityElderGuardianCurse { .. } => f.write_str("ENTITY_ELDER_GUARDIAN_CURSE"), + Sound::EntityElderGuardianDeath { .. } => f.write_str("ENTITY_ELDER_GUARDIAN_DEATH"), + Sound::EntityElderGuardianDeathLand { .. } => { + f.write_str("ENTITY_ELDER_GUARDIAN_DEATH_LAND") + } + Sound::EntityElderGuardianFlop { .. } => f.write_str("ENTITY_ELDER_GUARDIAN_FLOP"), + Sound::EntityElderGuardianHurt { .. } => f.write_str("ENTITY_ELDER_GUARDIAN_HURT"), + Sound::EntityElderGuardianHurtLand { .. } => { + f.write_str("ENTITY_ELDER_GUARDIAN_HURT_LAND") + } + Sound::EntityEndermanAmbient { .. } => f.write_str("ENTITY_ENDERMAN_AMBIENT"), + Sound::EntityEndermanDeath { .. } => f.write_str("ENTITY_ENDERMAN_DEATH"), + Sound::EntityEndermanHurt { .. } => f.write_str("ENTITY_ENDERMAN_HURT"), + Sound::EntityEndermanScream { .. } => f.write_str("ENTITY_ENDERMAN_SCREAM"), + Sound::EntityEndermanStare { .. } => f.write_str("ENTITY_ENDERMAN_STARE"), + Sound::EntityEndermanTeleport { .. } => f.write_str("ENTITY_ENDERMAN_TELEPORT"), + Sound::EntityEndermiteAmbient { .. } => f.write_str("ENTITY_ENDERMITE_AMBIENT"), + Sound::EntityEndermiteDeath { .. } => f.write_str("ENTITY_ENDERMITE_DEATH"), + Sound::EntityEndermiteHurt { .. } => f.write_str("ENTITY_ENDERMITE_HURT"), + Sound::EntityEndermiteStep { .. } => f.write_str("ENTITY_ENDERMITE_STEP"), + Sound::EntityEnderDragonAmbient { .. } => f.write_str("ENTITY_ENDER_DRAGON_AMBIENT"), + Sound::EntityEnderDragonDeath { .. } => f.write_str("ENTITY_ENDER_DRAGON_DEATH"), + Sound::EntityEnderDragonFlap { .. } => f.write_str("ENTITY_ENDER_DRAGON_FLAP"), + Sound::EntityEnderDragonGrowl { .. } => f.write_str("ENTITY_ENDER_DRAGON_GROWL"), + Sound::EntityEnderDragonHurt { .. } => f.write_str("ENTITY_ENDER_DRAGON_HURT"), + Sound::EntityEnderDragonShoot { .. } => f.write_str("ENTITY_ENDER_DRAGON_SHOOT"), + Sound::EntityEnderEyeDeath { .. } => f.write_str("ENTITY_ENDER_EYE_DEATH"), + Sound::EntityEnderEyeLaunch { .. } => f.write_str("ENTITY_ENDER_EYE_LAUNCH"), + Sound::EntityEnderPearlThrow { .. } => f.write_str("ENTITY_ENDER_PEARL_THROW"), + Sound::EntityEvokerAmbient { .. } => f.write_str("ENTITY_EVOKER_AMBIENT"), + Sound::EntityEvokerCastSpell { .. } => f.write_str("ENTITY_EVOKER_CAST_SPELL"), + Sound::EntityEvokerCelebrate { .. } => f.write_str("ENTITY_EVOKER_CELEBRATE"), + Sound::EntityEvokerDeath { .. } => f.write_str("ENTITY_EVOKER_DEATH"), + Sound::EntityEvokerFangsAttack { .. } => f.write_str("ENTITY_EVOKER_FANGS_ATTACK"), + Sound::EntityEvokerHurt { .. } => f.write_str("ENTITY_EVOKER_HURT"), + Sound::EntityEvokerPrepareAttack { .. } => f.write_str("ENTITY_EVOKER_PREPARE_ATTACK"), + Sound::EntityEvokerPrepareSummon { .. } => f.write_str("ENTITY_EVOKER_PREPARE_SUMMON"), + Sound::EntityEvokerPrepareWololo { .. } => f.write_str("ENTITY_EVOKER_PREPARE_WOLOLO"), + Sound::EntityExperienceBottleThrow { .. } => { + f.write_str("ENTITY_EXPERIENCE_BOTTLE_THROW") + } + Sound::EntityExperienceOrbPickup { .. } => f.write_str("ENTITY_EXPERIENCE_ORB_PICKUP"), + Sound::EntityFireworkRocketBlast { .. } => f.write_str("ENTITY_FIREWORK_ROCKET_BLAST"), + Sound::EntityFireworkRocketBlastFar { .. } => { + f.write_str("ENTITY_FIREWORK_ROCKET_BLAST_FAR") + } + Sound::EntityFireworkRocketLargeBlast { .. } => { + f.write_str("ENTITY_FIREWORK_ROCKET_LARGE_BLAST") + } + Sound::EntityFireworkRocketLargeBlastFar { .. } => { + f.write_str("ENTITY_FIREWORK_ROCKET_LARGE_BLAST_FAR") + } + Sound::EntityFireworkRocketLaunch { .. } => { + f.write_str("ENTITY_FIREWORK_ROCKET_LAUNCH") + } + Sound::EntityFireworkRocketShoot { .. } => f.write_str("ENTITY_FIREWORK_ROCKET_SHOOT"), + Sound::EntityFireworkRocketTwinkle { .. } => { + f.write_str("ENTITY_FIREWORK_ROCKET_TWINKLE") + } + Sound::EntityFireworkRocketTwinkleFar { .. } => { + f.write_str("ENTITY_FIREWORK_ROCKET_TWINKLE_FAR") + } + Sound::EntityFishingBobberRetrieve { .. } => { + f.write_str("ENTITY_FISHING_BOBBER_RETRIEVE") + } + Sound::EntityFishingBobberSplash { .. } => f.write_str("ENTITY_FISHING_BOBBER_SPLASH"), + Sound::EntityFishingBobberThrow { .. } => f.write_str("ENTITY_FISHING_BOBBER_THROW"), + Sound::EntityFishSwim { .. } => f.write_str("ENTITY_FISH_SWIM"), + Sound::EntityFoxAggro { .. } => f.write_str("ENTITY_FOX_AGGRO"), + Sound::EntityFoxAmbient { .. } => f.write_str("ENTITY_FOX_AMBIENT"), + Sound::EntityFoxBite { .. } => f.write_str("ENTITY_FOX_BITE"), + Sound::EntityFoxDeath { .. } => f.write_str("ENTITY_FOX_DEATH"), + Sound::EntityFoxEat { .. } => f.write_str("ENTITY_FOX_EAT"), + Sound::EntityFoxHurt { .. } => f.write_str("ENTITY_FOX_HURT"), + Sound::EntityFoxScreech { .. } => f.write_str("ENTITY_FOX_SCREECH"), + Sound::EntityFoxSleep { .. } => f.write_str("ENTITY_FOX_SLEEP"), + Sound::EntityFoxSniff { .. } => f.write_str("ENTITY_FOX_SNIFF"), + Sound::EntityFoxSpit { .. } => f.write_str("ENTITY_FOX_SPIT"), + Sound::EntityFoxTeleport { .. } => f.write_str("ENTITY_FOX_TELEPORT"), + Sound::EntityFrogAmbient { .. } => f.write_str("ENTITY_FROG_AMBIENT"), + Sound::EntityFrogDeath { .. } => f.write_str("ENTITY_FROG_DEATH"), + Sound::EntityFrogEat { .. } => f.write_str("ENTITY_FROG_EAT"), + Sound::EntityFrogHurt { .. } => f.write_str("ENTITY_FROG_HURT"), + Sound::EntityFrogLaySpawn { .. } => f.write_str("ENTITY_FROG_LAY_SPAWN"), + Sound::EntityFrogLongJump { .. } => f.write_str("ENTITY_FROG_LONG_JUMP"), + Sound::EntityFrogStep { .. } => f.write_str("ENTITY_FROG_STEP"), + Sound::EntityFrogTongue { .. } => f.write_str("ENTITY_FROG_TONGUE"), + Sound::EntityGenericBigFall { .. } => f.write_str("ENTITY_GENERIC_BIG_FALL"), + Sound::EntityGenericBurn { .. } => f.write_str("ENTITY_GENERIC_BURN"), + Sound::EntityGenericDeath { .. } => f.write_str("ENTITY_GENERIC_DEATH"), + Sound::EntityGenericDrink { .. } => f.write_str("ENTITY_GENERIC_DRINK"), + Sound::EntityGenericEat { .. } => f.write_str("ENTITY_GENERIC_EAT"), + Sound::EntityGenericExplode { .. } => f.write_str("ENTITY_GENERIC_EXPLODE"), + Sound::EntityGenericExtinguishFire { .. } => { + f.write_str("ENTITY_GENERIC_EXTINGUISH_FIRE") + } + Sound::EntityGenericHurt { .. } => f.write_str("ENTITY_GENERIC_HURT"), + Sound::EntityGenericSmallFall { .. } => f.write_str("ENTITY_GENERIC_SMALL_FALL"), + Sound::EntityGenericSplash { .. } => f.write_str("ENTITY_GENERIC_SPLASH"), + Sound::EntityGenericSwim { .. } => f.write_str("ENTITY_GENERIC_SWIM"), + Sound::EntityGhastAmbient { .. } => f.write_str("ENTITY_GHAST_AMBIENT"), + Sound::EntityGhastDeath { .. } => f.write_str("ENTITY_GHAST_DEATH"), + Sound::EntityGhastHurt { .. } => f.write_str("ENTITY_GHAST_HURT"), + Sound::EntityGhastScream { .. } => f.write_str("ENTITY_GHAST_SCREAM"), + Sound::EntityGhastShoot { .. } => f.write_str("ENTITY_GHAST_SHOOT"), + Sound::EntityGhastWarn { .. } => f.write_str("ENTITY_GHAST_WARN"), + Sound::EntityGlowItemFrameAddItem { .. } => { + f.write_str("ENTITY_GLOW_ITEM_FRAME_ADD_ITEM") + } + Sound::EntityGlowItemFrameBreak { .. } => f.write_str("ENTITY_GLOW_ITEM_FRAME_BREAK"), + Sound::EntityGlowItemFramePlace { .. } => f.write_str("ENTITY_GLOW_ITEM_FRAME_PLACE"), + Sound::EntityGlowItemFrameRemoveItem { .. } => { + f.write_str("ENTITY_GLOW_ITEM_FRAME_REMOVE_ITEM") + } + Sound::EntityGlowItemFrameRotateItem { .. } => { + f.write_str("ENTITY_GLOW_ITEM_FRAME_ROTATE_ITEM") + } + Sound::EntityGlowSquidAmbient { .. } => f.write_str("ENTITY_GLOW_SQUID_AMBIENT"), + Sound::EntityGlowSquidDeath { .. } => f.write_str("ENTITY_GLOW_SQUID_DEATH"), + Sound::EntityGlowSquidHurt { .. } => f.write_str("ENTITY_GLOW_SQUID_HURT"), + Sound::EntityGlowSquidSquirt { .. } => f.write_str("ENTITY_GLOW_SQUID_SQUIRT"), + Sound::EntityGoatAmbient { .. } => f.write_str("ENTITY_GOAT_AMBIENT"), + Sound::EntityGoatDeath { .. } => f.write_str("ENTITY_GOAT_DEATH"), + Sound::EntityGoatEat { .. } => f.write_str("ENTITY_GOAT_EAT"), + Sound::EntityGoatHornBreak { .. } => f.write_str("ENTITY_GOAT_HORN_BREAK"), + Sound::EntityGoatHurt { .. } => f.write_str("ENTITY_GOAT_HURT"), + Sound::EntityGoatLongJump { .. } => f.write_str("ENTITY_GOAT_LONG_JUMP"), + Sound::EntityGoatMilk { .. } => f.write_str("ENTITY_GOAT_MILK"), + Sound::EntityGoatPrepareRam { .. } => f.write_str("ENTITY_GOAT_PREPARE_RAM"), + Sound::EntityGoatRamImpact { .. } => f.write_str("ENTITY_GOAT_RAM_IMPACT"), + Sound::EntityGoatScreamingAmbient { .. } => { + f.write_str("ENTITY_GOAT_SCREAMING_AMBIENT") + } + Sound::EntityGoatScreamingDeath { .. } => f.write_str("ENTITY_GOAT_SCREAMING_DEATH"), + Sound::EntityGoatScreamingEat { .. } => f.write_str("ENTITY_GOAT_SCREAMING_EAT"), + Sound::EntityGoatScreamingHornBreak { .. } => { + f.write_str("ENTITY_GOAT_SCREAMING_HORN_BREAK") + } + Sound::EntityGoatScreamingHurt { .. } => f.write_str("ENTITY_GOAT_SCREAMING_HURT"), + Sound::EntityGoatScreamingLongJump { .. } => { + f.write_str("ENTITY_GOAT_SCREAMING_LONG_JUMP") + } + Sound::EntityGoatScreamingMilk { .. } => f.write_str("ENTITY_GOAT_SCREAMING_MILK"), + Sound::EntityGoatScreamingPrepareRam { .. } => { + f.write_str("ENTITY_GOAT_SCREAMING_PREPARE_RAM") + } + Sound::EntityGoatScreamingRamImpact { .. } => { + f.write_str("ENTITY_GOAT_SCREAMING_RAM_IMPACT") + } + Sound::EntityGoatStep { .. } => f.write_str("ENTITY_GOAT_STEP"), + Sound::EntityGuardianAmbient { .. } => f.write_str("ENTITY_GUARDIAN_AMBIENT"), + Sound::EntityGuardianAmbientLand { .. } => f.write_str("ENTITY_GUARDIAN_AMBIENT_LAND"), + Sound::EntityGuardianAttack { .. } => f.write_str("ENTITY_GUARDIAN_ATTACK"), + Sound::EntityGuardianDeath { .. } => f.write_str("ENTITY_GUARDIAN_DEATH"), + Sound::EntityGuardianDeathLand { .. } => f.write_str("ENTITY_GUARDIAN_DEATH_LAND"), + Sound::EntityGuardianFlop { .. } => f.write_str("ENTITY_GUARDIAN_FLOP"), + Sound::EntityGuardianHurt { .. } => f.write_str("ENTITY_GUARDIAN_HURT"), + Sound::EntityGuardianHurtLand { .. } => f.write_str("ENTITY_GUARDIAN_HURT_LAND"), + Sound::EntityHoglinAmbient { .. } => f.write_str("ENTITY_HOGLIN_AMBIENT"), + Sound::EntityHoglinAngry { .. } => f.write_str("ENTITY_HOGLIN_ANGRY"), + Sound::EntityHoglinAttack { .. } => f.write_str("ENTITY_HOGLIN_ATTACK"), + Sound::EntityHoglinConvertedToZombified { .. } => { + f.write_str("ENTITY_HOGLIN_CONVERTED_TO_ZOMBIFIED") + } + Sound::EntityHoglinDeath { .. } => f.write_str("ENTITY_HOGLIN_DEATH"), + Sound::EntityHoglinHurt { .. } => f.write_str("ENTITY_HOGLIN_HURT"), + Sound::EntityHoglinRetreat { .. } => f.write_str("ENTITY_HOGLIN_RETREAT"), + Sound::EntityHoglinStep { .. } => f.write_str("ENTITY_HOGLIN_STEP"), + Sound::EntityHorseAmbient { .. } => f.write_str("ENTITY_HORSE_AMBIENT"), + Sound::EntityHorseAngry { .. } => f.write_str("ENTITY_HORSE_ANGRY"), + Sound::EntityHorseArmor { .. } => f.write_str("ENTITY_HORSE_ARMOR"), + Sound::EntityHorseBreathe { .. } => f.write_str("ENTITY_HORSE_BREATHE"), + Sound::EntityHorseDeath { .. } => f.write_str("ENTITY_HORSE_DEATH"), + Sound::EntityHorseEat { .. } => f.write_str("ENTITY_HORSE_EAT"), + Sound::EntityHorseGallop { .. } => f.write_str("ENTITY_HORSE_GALLOP"), + Sound::EntityHorseHurt { .. } => f.write_str("ENTITY_HORSE_HURT"), + Sound::EntityHorseJump { .. } => f.write_str("ENTITY_HORSE_JUMP"), + Sound::EntityHorseLand { .. } => f.write_str("ENTITY_HORSE_LAND"), + Sound::EntityHorseSaddle { .. } => f.write_str("ENTITY_HORSE_SADDLE"), + Sound::EntityHorseStep { .. } => f.write_str("ENTITY_HORSE_STEP"), + Sound::EntityHorseStepWood { .. } => f.write_str("ENTITY_HORSE_STEP_WOOD"), + Sound::EntityHostileBigFall { .. } => f.write_str("ENTITY_HOSTILE_BIG_FALL"), + Sound::EntityHostileDeath { .. } => f.write_str("ENTITY_HOSTILE_DEATH"), + Sound::EntityHostileHurt { .. } => f.write_str("ENTITY_HOSTILE_HURT"), + Sound::EntityHostileSmallFall { .. } => f.write_str("ENTITY_HOSTILE_SMALL_FALL"), + Sound::EntityHostileSplash { .. } => f.write_str("ENTITY_HOSTILE_SPLASH"), + Sound::EntityHostileSwim { .. } => f.write_str("ENTITY_HOSTILE_SWIM"), + Sound::EntityHuskAmbient { .. } => f.write_str("ENTITY_HUSK_AMBIENT"), + Sound::EntityHuskConvertedToZombie { .. } => { + f.write_str("ENTITY_HUSK_CONVERTED_TO_ZOMBIE") + } + Sound::EntityHuskDeath { .. } => f.write_str("ENTITY_HUSK_DEATH"), + Sound::EntityHuskHurt { .. } => f.write_str("ENTITY_HUSK_HURT"), + Sound::EntityHuskStep { .. } => f.write_str("ENTITY_HUSK_STEP"), + Sound::EntityIllusionerAmbient { .. } => f.write_str("ENTITY_ILLUSIONER_AMBIENT"), + Sound::EntityIllusionerCastSpell { .. } => f.write_str("ENTITY_ILLUSIONER_CAST_SPELL"), + Sound::EntityIllusionerDeath { .. } => f.write_str("ENTITY_ILLUSIONER_DEATH"), + Sound::EntityIllusionerHurt { .. } => f.write_str("ENTITY_ILLUSIONER_HURT"), + Sound::EntityIllusionerMirrorMove { .. } => { + f.write_str("ENTITY_ILLUSIONER_MIRROR_MOVE") + } + Sound::EntityIllusionerPrepareBlindness { .. } => { + f.write_str("ENTITY_ILLUSIONER_PREPARE_BLINDNESS") + } + Sound::EntityIllusionerPrepareMirror { .. } => { + f.write_str("ENTITY_ILLUSIONER_PREPARE_MIRROR") + } + Sound::EntityIronGolemAttack { .. } => f.write_str("ENTITY_IRON_GOLEM_ATTACK"), + Sound::EntityIronGolemDamage { .. } => f.write_str("ENTITY_IRON_GOLEM_DAMAGE"), + Sound::EntityIronGolemDeath { .. } => f.write_str("ENTITY_IRON_GOLEM_DEATH"), + Sound::EntityIronGolemHurt { .. } => f.write_str("ENTITY_IRON_GOLEM_HURT"), + Sound::EntityIronGolemRepair { .. } => f.write_str("ENTITY_IRON_GOLEM_REPAIR"), + Sound::EntityIronGolemStep { .. } => f.write_str("ENTITY_IRON_GOLEM_STEP"), + Sound::EntityItemBreak { .. } => f.write_str("ENTITY_ITEM_BREAK"), + Sound::EntityItemFrameAddItem { .. } => f.write_str("ENTITY_ITEM_FRAME_ADD_ITEM"), + Sound::EntityItemFrameBreak { .. } => f.write_str("ENTITY_ITEM_FRAME_BREAK"), + Sound::EntityItemFramePlace { .. } => f.write_str("ENTITY_ITEM_FRAME_PLACE"), + Sound::EntityItemFrameRemoveItem { .. } => f.write_str("ENTITY_ITEM_FRAME_REMOVE_ITEM"), + Sound::EntityItemFrameRotateItem { .. } => f.write_str("ENTITY_ITEM_FRAME_ROTATE_ITEM"), + Sound::EntityItemPickup { .. } => f.write_str("ENTITY_ITEM_PICKUP"), + Sound::EntityLeashKnotBreak { .. } => f.write_str("ENTITY_LEASH_KNOT_BREAK"), + Sound::EntityLeashKnotPlace { .. } => f.write_str("ENTITY_LEASH_KNOT_PLACE"), + Sound::EntityLightningBoltImpact { .. } => f.write_str("ENTITY_LIGHTNING_BOLT_IMPACT"), + Sound::EntityLightningBoltThunder { .. } => { + f.write_str("ENTITY_LIGHTNING_BOLT_THUNDER") + } + Sound::EntityLingeringPotionThrow { .. } => { + f.write_str("ENTITY_LINGERING_POTION_THROW") + } + Sound::EntityLlamaAmbient { .. } => f.write_str("ENTITY_LLAMA_AMBIENT"), + Sound::EntityLlamaAngry { .. } => f.write_str("ENTITY_LLAMA_ANGRY"), + Sound::EntityLlamaChest { .. } => f.write_str("ENTITY_LLAMA_CHEST"), + Sound::EntityLlamaDeath { .. } => f.write_str("ENTITY_LLAMA_DEATH"), + Sound::EntityLlamaEat { .. } => f.write_str("ENTITY_LLAMA_EAT"), + Sound::EntityLlamaHurt { .. } => f.write_str("ENTITY_LLAMA_HURT"), + Sound::EntityLlamaSpit { .. } => f.write_str("ENTITY_LLAMA_SPIT"), + Sound::EntityLlamaStep { .. } => f.write_str("ENTITY_LLAMA_STEP"), + Sound::EntityLlamaSwag { .. } => f.write_str("ENTITY_LLAMA_SWAG"), + Sound::EntityMagmaCubeDeath { .. } => f.write_str("ENTITY_MAGMA_CUBE_DEATH"), + Sound::EntityMagmaCubeDeathSmall { .. } => f.write_str("ENTITY_MAGMA_CUBE_DEATH_SMALL"), + Sound::EntityMagmaCubeHurt { .. } => f.write_str("ENTITY_MAGMA_CUBE_HURT"), + Sound::EntityMagmaCubeHurtSmall { .. } => f.write_str("ENTITY_MAGMA_CUBE_HURT_SMALL"), + Sound::EntityMagmaCubeJump { .. } => f.write_str("ENTITY_MAGMA_CUBE_JUMP"), + Sound::EntityMagmaCubeSquish { .. } => f.write_str("ENTITY_MAGMA_CUBE_SQUISH"), + Sound::EntityMagmaCubeSquishSmall { .. } => { + f.write_str("ENTITY_MAGMA_CUBE_SQUISH_SMALL") + } + Sound::EntityMinecartInside { .. } => f.write_str("ENTITY_MINECART_INSIDE"), + Sound::EntityMinecartInsideUnderwater { .. } => { + f.write_str("ENTITY_MINECART_INSIDE_UNDERWATER") + } + Sound::EntityMinecartRiding { .. } => f.write_str("ENTITY_MINECART_RIDING"), + Sound::EntityMooshroomConvert { .. } => f.write_str("ENTITY_MOOSHROOM_CONVERT"), + Sound::EntityMooshroomEat { .. } => f.write_str("ENTITY_MOOSHROOM_EAT"), + Sound::EntityMooshroomMilk { .. } => f.write_str("ENTITY_MOOSHROOM_MILK"), + Sound::EntityMooshroomShear { .. } => f.write_str("ENTITY_MOOSHROOM_SHEAR"), + Sound::EntityMooshroomSuspiciousMilk { .. } => { + f.write_str("ENTITY_MOOSHROOM_SUSPICIOUS_MILK") + } + Sound::EntityMuleAmbient { .. } => f.write_str("ENTITY_MULE_AMBIENT"), + Sound::EntityMuleAngry { .. } => f.write_str("ENTITY_MULE_ANGRY"), + Sound::EntityMuleChest { .. } => f.write_str("ENTITY_MULE_CHEST"), + Sound::EntityMuleDeath { .. } => f.write_str("ENTITY_MULE_DEATH"), + Sound::EntityMuleEat { .. } => f.write_str("ENTITY_MULE_EAT"), + Sound::EntityMuleHurt { .. } => f.write_str("ENTITY_MULE_HURT"), + Sound::EntityMuleJump { .. } => f.write_str("ENTITY_MULE_JUMP"), + Sound::EntityOcelotAmbient { .. } => f.write_str("ENTITY_OCELOT_AMBIENT"), + Sound::EntityOcelotDeath { .. } => f.write_str("ENTITY_OCELOT_DEATH"), + Sound::EntityOcelotHurt { .. } => f.write_str("ENTITY_OCELOT_HURT"), + Sound::EntityPaintingBreak { .. } => f.write_str("ENTITY_PAINTING_BREAK"), + Sound::EntityPaintingPlace { .. } => f.write_str("ENTITY_PAINTING_PLACE"), + Sound::EntityPandaAggressiveAmbient { .. } => { + f.write_str("ENTITY_PANDA_AGGRESSIVE_AMBIENT") + } + Sound::EntityPandaAmbient { .. } => f.write_str("ENTITY_PANDA_AMBIENT"), + Sound::EntityPandaBite { .. } => f.write_str("ENTITY_PANDA_BITE"), + Sound::EntityPandaCantBreed { .. } => f.write_str("ENTITY_PANDA_CANT_BREED"), + Sound::EntityPandaDeath { .. } => f.write_str("ENTITY_PANDA_DEATH"), + Sound::EntityPandaEat { .. } => f.write_str("ENTITY_PANDA_EAT"), + Sound::EntityPandaHurt { .. } => f.write_str("ENTITY_PANDA_HURT"), + Sound::EntityPandaPreSneeze { .. } => f.write_str("ENTITY_PANDA_PRE_SNEEZE"), + Sound::EntityPandaSneeze { .. } => f.write_str("ENTITY_PANDA_SNEEZE"), + Sound::EntityPandaStep { .. } => f.write_str("ENTITY_PANDA_STEP"), + Sound::EntityPandaWorriedAmbient { .. } => f.write_str("ENTITY_PANDA_WORRIED_AMBIENT"), + Sound::EntityParrotAmbient { .. } => f.write_str("ENTITY_PARROT_AMBIENT"), + Sound::EntityParrotDeath { .. } => f.write_str("ENTITY_PARROT_DEATH"), + Sound::EntityParrotEat { .. } => f.write_str("ENTITY_PARROT_EAT"), + Sound::EntityParrotFly { .. } => f.write_str("ENTITY_PARROT_FLY"), + Sound::EntityParrotHurt { .. } => f.write_str("ENTITY_PARROT_HURT"), + Sound::EntityParrotImitateBlaze { .. } => f.write_str("ENTITY_PARROT_IMITATE_BLAZE"), + Sound::EntityParrotImitateBogged { .. } => f.write_str("ENTITY_PARROT_IMITATE_BOGGED"), + Sound::EntityParrotImitateBreeze { .. } => f.write_str("ENTITY_PARROT_IMITATE_BREEZE"), + Sound::EntityParrotImitateCreeper { .. } => { + f.write_str("ENTITY_PARROT_IMITATE_CREEPER") + } + Sound::EntityParrotImitateDrowned { .. } => { + f.write_str("ENTITY_PARROT_IMITATE_DROWNED") + } + Sound::EntityParrotImitateElderGuardian { .. } => { + f.write_str("ENTITY_PARROT_IMITATE_ELDER_GUARDIAN") + } + Sound::EntityParrotImitateEndermite { .. } => { + f.write_str("ENTITY_PARROT_IMITATE_ENDERMITE") + } + Sound::EntityParrotImitateEnderDragon { .. } => { + f.write_str("ENTITY_PARROT_IMITATE_ENDER_DRAGON") + } + Sound::EntityParrotImitateEvoker { .. } => f.write_str("ENTITY_PARROT_IMITATE_EVOKER"), + Sound::EntityParrotImitateGhast { .. } => f.write_str("ENTITY_PARROT_IMITATE_GHAST"), + Sound::EntityParrotImitateGuardian { .. } => { + f.write_str("ENTITY_PARROT_IMITATE_GUARDIAN") + } + Sound::EntityParrotImitateHoglin { .. } => f.write_str("ENTITY_PARROT_IMITATE_HOGLIN"), + Sound::EntityParrotImitateHusk { .. } => f.write_str("ENTITY_PARROT_IMITATE_HUSK"), + Sound::EntityParrotImitateIllusioner { .. } => { + f.write_str("ENTITY_PARROT_IMITATE_ILLUSIONER") + } + Sound::EntityParrotImitateMagmaCube { .. } => { + f.write_str("ENTITY_PARROT_IMITATE_MAGMA_CUBE") + } + Sound::EntityParrotImitatePhantom { .. } => { + f.write_str("ENTITY_PARROT_IMITATE_PHANTOM") + } + Sound::EntityParrotImitatePiglin { .. } => f.write_str("ENTITY_PARROT_IMITATE_PIGLIN"), + Sound::EntityParrotImitatePiglinBrute { .. } => { + f.write_str("ENTITY_PARROT_IMITATE_PIGLIN_BRUTE") + } + Sound::EntityParrotImitatePillager { .. } => { + f.write_str("ENTITY_PARROT_IMITATE_PILLAGER") + } + Sound::EntityParrotImitateRavager { .. } => { + f.write_str("ENTITY_PARROT_IMITATE_RAVAGER") + } + Sound::EntityParrotImitateShulker { .. } => { + f.write_str("ENTITY_PARROT_IMITATE_SHULKER") + } + Sound::EntityParrotImitateSilverfish { .. } => { + f.write_str("ENTITY_PARROT_IMITATE_SILVERFISH") + } + Sound::EntityParrotImitateSkeleton { .. } => { + f.write_str("ENTITY_PARROT_IMITATE_SKELETON") + } + Sound::EntityParrotImitateSlime { .. } => f.write_str("ENTITY_PARROT_IMITATE_SLIME"), + Sound::EntityParrotImitateSpider { .. } => f.write_str("ENTITY_PARROT_IMITATE_SPIDER"), + Sound::EntityParrotImitateStray { .. } => f.write_str("ENTITY_PARROT_IMITATE_STRAY"), + Sound::EntityParrotImitateVex { .. } => f.write_str("ENTITY_PARROT_IMITATE_VEX"), + Sound::EntityParrotImitateVindicator { .. } => { + f.write_str("ENTITY_PARROT_IMITATE_VINDICATOR") + } + Sound::EntityParrotImitateWarden { .. } => f.write_str("ENTITY_PARROT_IMITATE_WARDEN"), + Sound::EntityParrotImitateWitch { .. } => f.write_str("ENTITY_PARROT_IMITATE_WITCH"), + Sound::EntityParrotImitateWither { .. } => f.write_str("ENTITY_PARROT_IMITATE_WITHER"), + Sound::EntityParrotImitateWitherSkeleton { .. } => { + f.write_str("ENTITY_PARROT_IMITATE_WITHER_SKELETON") + } + Sound::EntityParrotImitateZoglin { .. } => f.write_str("ENTITY_PARROT_IMITATE_ZOGLIN"), + Sound::EntityParrotImitateZombie { .. } => f.write_str("ENTITY_PARROT_IMITATE_ZOMBIE"), + Sound::EntityParrotImitateZombieVillager { .. } => { + f.write_str("ENTITY_PARROT_IMITATE_ZOMBIE_VILLAGER") + } + Sound::EntityParrotStep { .. } => f.write_str("ENTITY_PARROT_STEP"), + Sound::EntityPhantomAmbient { .. } => f.write_str("ENTITY_PHANTOM_AMBIENT"), + Sound::EntityPhantomBite { .. } => f.write_str("ENTITY_PHANTOM_BITE"), + Sound::EntityPhantomDeath { .. } => f.write_str("ENTITY_PHANTOM_DEATH"), + Sound::EntityPhantomFlap { .. } => f.write_str("ENTITY_PHANTOM_FLAP"), + Sound::EntityPhantomHurt { .. } => f.write_str("ENTITY_PHANTOM_HURT"), + Sound::EntityPhantomSwoop { .. } => f.write_str("ENTITY_PHANTOM_SWOOP"), + Sound::EntityPiglinAdmiringItem { .. } => f.write_str("ENTITY_PIGLIN_ADMIRING_ITEM"), + Sound::EntityPiglinAmbient { .. } => f.write_str("ENTITY_PIGLIN_AMBIENT"), + Sound::EntityPiglinAngry { .. } => f.write_str("ENTITY_PIGLIN_ANGRY"), + Sound::EntityPiglinBruteAmbient { .. } => f.write_str("ENTITY_PIGLIN_BRUTE_AMBIENT"), + Sound::EntityPiglinBruteAngry { .. } => f.write_str("ENTITY_PIGLIN_BRUTE_ANGRY"), + Sound::EntityPiglinBruteConvertedToZombified { .. } => { + f.write_str("ENTITY_PIGLIN_BRUTE_CONVERTED_TO_ZOMBIFIED") + } + Sound::EntityPiglinBruteDeath { .. } => f.write_str("ENTITY_PIGLIN_BRUTE_DEATH"), + Sound::EntityPiglinBruteHurt { .. } => f.write_str("ENTITY_PIGLIN_BRUTE_HURT"), + Sound::EntityPiglinBruteStep { .. } => f.write_str("ENTITY_PIGLIN_BRUTE_STEP"), + Sound::EntityPiglinCelebrate { .. } => f.write_str("ENTITY_PIGLIN_CELEBRATE"), + Sound::EntityPiglinConvertedToZombified { .. } => { + f.write_str("ENTITY_PIGLIN_CONVERTED_TO_ZOMBIFIED") + } + Sound::EntityPiglinDeath { .. } => f.write_str("ENTITY_PIGLIN_DEATH"), + Sound::EntityPiglinHurt { .. } => f.write_str("ENTITY_PIGLIN_HURT"), + Sound::EntityPiglinJealous { .. } => f.write_str("ENTITY_PIGLIN_JEALOUS"), + Sound::EntityPiglinRetreat { .. } => f.write_str("ENTITY_PIGLIN_RETREAT"), + Sound::EntityPiglinStep { .. } => f.write_str("ENTITY_PIGLIN_STEP"), + Sound::EntityPigAmbient { .. } => f.write_str("ENTITY_PIG_AMBIENT"), + Sound::EntityPigDeath { .. } => f.write_str("ENTITY_PIG_DEATH"), + Sound::EntityPigHurt { .. } => f.write_str("ENTITY_PIG_HURT"), + Sound::EntityPigSaddle { .. } => f.write_str("ENTITY_PIG_SADDLE"), + Sound::EntityPigStep { .. } => f.write_str("ENTITY_PIG_STEP"), + Sound::EntityPillagerAmbient { .. } => f.write_str("ENTITY_PILLAGER_AMBIENT"), + Sound::EntityPillagerCelebrate { .. } => f.write_str("ENTITY_PILLAGER_CELEBRATE"), + Sound::EntityPillagerDeath { .. } => f.write_str("ENTITY_PILLAGER_DEATH"), + Sound::EntityPillagerHurt { .. } => f.write_str("ENTITY_PILLAGER_HURT"), + Sound::EntityPlayerAttackCrit { .. } => f.write_str("ENTITY_PLAYER_ATTACK_CRIT"), + Sound::EntityPlayerAttackKnockback { .. } => { + f.write_str("ENTITY_PLAYER_ATTACK_KNOCKBACK") + } + Sound::EntityPlayerAttackNodamage { .. } => { + f.write_str("ENTITY_PLAYER_ATTACK_NODAMAGE") + } + Sound::EntityPlayerAttackStrong { .. } => f.write_str("ENTITY_PLAYER_ATTACK_STRONG"), + Sound::EntityPlayerAttackSweep { .. } => f.write_str("ENTITY_PLAYER_ATTACK_SWEEP"), + Sound::EntityPlayerAttackWeak { .. } => f.write_str("ENTITY_PLAYER_ATTACK_WEAK"), + Sound::EntityPlayerBigFall { .. } => f.write_str("ENTITY_PLAYER_BIG_FALL"), + Sound::EntityPlayerBreath { .. } => f.write_str("ENTITY_PLAYER_BREATH"), + Sound::EntityPlayerBurp { .. } => f.write_str("ENTITY_PLAYER_BURP"), + Sound::EntityPlayerDeath { .. } => f.write_str("ENTITY_PLAYER_DEATH"), + Sound::EntityPlayerHurt { .. } => f.write_str("ENTITY_PLAYER_HURT"), + Sound::EntityPlayerHurtDrown { .. } => f.write_str("ENTITY_PLAYER_HURT_DROWN"), + Sound::EntityPlayerHurtFreeze { .. } => f.write_str("ENTITY_PLAYER_HURT_FREEZE"), + Sound::EntityPlayerHurtOnFire { .. } => f.write_str("ENTITY_PLAYER_HURT_ON_FIRE"), + Sound::EntityPlayerHurtSweetBerryBush { .. } => { + f.write_str("ENTITY_PLAYER_HURT_SWEET_BERRY_BUSH") + } + Sound::EntityPlayerLevelup { .. } => f.write_str("ENTITY_PLAYER_LEVELUP"), + Sound::EntityPlayerSmallFall { .. } => f.write_str("ENTITY_PLAYER_SMALL_FALL"), + Sound::EntityPlayerSplash { .. } => f.write_str("ENTITY_PLAYER_SPLASH"), + Sound::EntityPlayerSplashHighSpeed { .. } => { + f.write_str("ENTITY_PLAYER_SPLASH_HIGH_SPEED") + } + Sound::EntityPlayerSwim { .. } => f.write_str("ENTITY_PLAYER_SWIM"), + Sound::EntityPlayerTeleport { .. } => f.write_str("ENTITY_PLAYER_TELEPORT"), + Sound::EntityPolarBearAmbient { .. } => f.write_str("ENTITY_POLAR_BEAR_AMBIENT"), + Sound::EntityPolarBearAmbientBaby { .. } => { + f.write_str("ENTITY_POLAR_BEAR_AMBIENT_BABY") + } + Sound::EntityPolarBearDeath { .. } => f.write_str("ENTITY_POLAR_BEAR_DEATH"), + Sound::EntityPolarBearHurt { .. } => f.write_str("ENTITY_POLAR_BEAR_HURT"), + Sound::EntityPolarBearStep { .. } => f.write_str("ENTITY_POLAR_BEAR_STEP"), + Sound::EntityPolarBearWarning { .. } => f.write_str("ENTITY_POLAR_BEAR_WARNING"), + Sound::EntityPufferFishAmbient { .. } => f.write_str("ENTITY_PUFFER_FISH_AMBIENT"), + Sound::EntityPufferFishBlowOut { .. } => f.write_str("ENTITY_PUFFER_FISH_BLOW_OUT"), + Sound::EntityPufferFishBlowUp { .. } => f.write_str("ENTITY_PUFFER_FISH_BLOW_UP"), + Sound::EntityPufferFishDeath { .. } => f.write_str("ENTITY_PUFFER_FISH_DEATH"), + Sound::EntityPufferFishFlop { .. } => f.write_str("ENTITY_PUFFER_FISH_FLOP"), + Sound::EntityPufferFishHurt { .. } => f.write_str("ENTITY_PUFFER_FISH_HURT"), + Sound::EntityPufferFishSting { .. } => f.write_str("ENTITY_PUFFER_FISH_STING"), + Sound::EntityRabbitAmbient { .. } => f.write_str("ENTITY_RABBIT_AMBIENT"), + Sound::EntityRabbitAttack { .. } => f.write_str("ENTITY_RABBIT_ATTACK"), + Sound::EntityRabbitDeath { .. } => f.write_str("ENTITY_RABBIT_DEATH"), + Sound::EntityRabbitHurt { .. } => f.write_str("ENTITY_RABBIT_HURT"), + Sound::EntityRabbitJump { .. } => f.write_str("ENTITY_RABBIT_JUMP"), + Sound::EntityRavagerAmbient { .. } => f.write_str("ENTITY_RAVAGER_AMBIENT"), + Sound::EntityRavagerAttack { .. } => f.write_str("ENTITY_RAVAGER_ATTACK"), + Sound::EntityRavagerCelebrate { .. } => f.write_str("ENTITY_RAVAGER_CELEBRATE"), + Sound::EntityRavagerDeath { .. } => f.write_str("ENTITY_RAVAGER_DEATH"), + Sound::EntityRavagerHurt { .. } => f.write_str("ENTITY_RAVAGER_HURT"), + Sound::EntityRavagerRoar { .. } => f.write_str("ENTITY_RAVAGER_ROAR"), + Sound::EntityRavagerStep { .. } => f.write_str("ENTITY_RAVAGER_STEP"), + Sound::EntityRavagerStunned { .. } => f.write_str("ENTITY_RAVAGER_STUNNED"), + Sound::EntitySalmonAmbient { .. } => f.write_str("ENTITY_SALMON_AMBIENT"), + Sound::EntitySalmonDeath { .. } => f.write_str("ENTITY_SALMON_DEATH"), + Sound::EntitySalmonFlop { .. } => f.write_str("ENTITY_SALMON_FLOP"), + Sound::EntitySalmonHurt { .. } => f.write_str("ENTITY_SALMON_HURT"), + Sound::EntitySheepAmbient { .. } => f.write_str("ENTITY_SHEEP_AMBIENT"), + Sound::EntitySheepDeath { .. } => f.write_str("ENTITY_SHEEP_DEATH"), + Sound::EntitySheepHurt { .. } => f.write_str("ENTITY_SHEEP_HURT"), + Sound::EntitySheepShear { .. } => f.write_str("ENTITY_SHEEP_SHEAR"), + Sound::EntitySheepStep { .. } => f.write_str("ENTITY_SHEEP_STEP"), + Sound::EntityShulkerAmbient { .. } => f.write_str("ENTITY_SHULKER_AMBIENT"), + Sound::EntityShulkerBulletHit { .. } => f.write_str("ENTITY_SHULKER_BULLET_HIT"), + Sound::EntityShulkerBulletHurt { .. } => f.write_str("ENTITY_SHULKER_BULLET_HURT"), + Sound::EntityShulkerClose { .. } => f.write_str("ENTITY_SHULKER_CLOSE"), + Sound::EntityShulkerDeath { .. } => f.write_str("ENTITY_SHULKER_DEATH"), + Sound::EntityShulkerHurt { .. } => f.write_str("ENTITY_SHULKER_HURT"), + Sound::EntityShulkerHurtClosed { .. } => f.write_str("ENTITY_SHULKER_HURT_CLOSED"), + Sound::EntityShulkerOpen { .. } => f.write_str("ENTITY_SHULKER_OPEN"), + Sound::EntityShulkerShoot { .. } => f.write_str("ENTITY_SHULKER_SHOOT"), + Sound::EntityShulkerTeleport { .. } => f.write_str("ENTITY_SHULKER_TELEPORT"), + Sound::EntitySilverfishAmbient { .. } => f.write_str("ENTITY_SILVERFISH_AMBIENT"), + Sound::EntitySilverfishDeath { .. } => f.write_str("ENTITY_SILVERFISH_DEATH"), + Sound::EntitySilverfishHurt { .. } => f.write_str("ENTITY_SILVERFISH_HURT"), + Sound::EntitySilverfishStep { .. } => f.write_str("ENTITY_SILVERFISH_STEP"), + Sound::EntitySkeletonAmbient { .. } => f.write_str("ENTITY_SKELETON_AMBIENT"), + Sound::EntitySkeletonConvertedToStray { .. } => { + f.write_str("ENTITY_SKELETON_CONVERTED_TO_STRAY") + } + Sound::EntitySkeletonDeath { .. } => f.write_str("ENTITY_SKELETON_DEATH"), + Sound::EntitySkeletonHorseAmbient { .. } => { + f.write_str("ENTITY_SKELETON_HORSE_AMBIENT") + } + Sound::EntitySkeletonHorseAmbientWater { .. } => { + f.write_str("ENTITY_SKELETON_HORSE_AMBIENT_WATER") + } + Sound::EntitySkeletonHorseDeath { .. } => f.write_str("ENTITY_SKELETON_HORSE_DEATH"), + Sound::EntitySkeletonHorseGallopWater { .. } => { + f.write_str("ENTITY_SKELETON_HORSE_GALLOP_WATER") + } + Sound::EntitySkeletonHorseHurt { .. } => f.write_str("ENTITY_SKELETON_HORSE_HURT"), + Sound::EntitySkeletonHorseJumpWater { .. } => { + f.write_str("ENTITY_SKELETON_HORSE_JUMP_WATER") + } + Sound::EntitySkeletonHorseStepWater { .. } => { + f.write_str("ENTITY_SKELETON_HORSE_STEP_WATER") + } + Sound::EntitySkeletonHorseSwim { .. } => f.write_str("ENTITY_SKELETON_HORSE_SWIM"), + Sound::EntitySkeletonHurt { .. } => f.write_str("ENTITY_SKELETON_HURT"), + Sound::EntitySkeletonShoot { .. } => f.write_str("ENTITY_SKELETON_SHOOT"), + Sound::EntitySkeletonStep { .. } => f.write_str("ENTITY_SKELETON_STEP"), + Sound::EntitySlimeAttack { .. } => f.write_str("ENTITY_SLIME_ATTACK"), + Sound::EntitySlimeDeath { .. } => f.write_str("ENTITY_SLIME_DEATH"), + Sound::EntitySlimeDeathSmall { .. } => f.write_str("ENTITY_SLIME_DEATH_SMALL"), + Sound::EntitySlimeHurt { .. } => f.write_str("ENTITY_SLIME_HURT"), + Sound::EntitySlimeHurtSmall { .. } => f.write_str("ENTITY_SLIME_HURT_SMALL"), + Sound::EntitySlimeJump { .. } => f.write_str("ENTITY_SLIME_JUMP"), + Sound::EntitySlimeJumpSmall { .. } => f.write_str("ENTITY_SLIME_JUMP_SMALL"), + Sound::EntitySlimeSquish { .. } => f.write_str("ENTITY_SLIME_SQUISH"), + Sound::EntitySlimeSquishSmall { .. } => f.write_str("ENTITY_SLIME_SQUISH_SMALL"), + Sound::EntitySnifferDeath { .. } => f.write_str("ENTITY_SNIFFER_DEATH"), + Sound::EntitySnifferDigging { .. } => f.write_str("ENTITY_SNIFFER_DIGGING"), + Sound::EntitySnifferDiggingStop { .. } => f.write_str("ENTITY_SNIFFER_DIGGING_STOP"), + Sound::EntitySnifferDropSeed { .. } => f.write_str("ENTITY_SNIFFER_DROP_SEED"), + Sound::EntitySnifferEat { .. } => f.write_str("ENTITY_SNIFFER_EAT"), + Sound::EntitySnifferHappy { .. } => f.write_str("ENTITY_SNIFFER_HAPPY"), + Sound::EntitySnifferHurt { .. } => f.write_str("ENTITY_SNIFFER_HURT"), + Sound::EntitySnifferIdle { .. } => f.write_str("ENTITY_SNIFFER_IDLE"), + Sound::EntitySnifferScenting { .. } => f.write_str("ENTITY_SNIFFER_SCENTING"), + Sound::EntitySnifferSearching { .. } => f.write_str("ENTITY_SNIFFER_SEARCHING"), + Sound::EntitySnifferSniffing { .. } => f.write_str("ENTITY_SNIFFER_SNIFFING"), + Sound::EntitySnifferStep { .. } => f.write_str("ENTITY_SNIFFER_STEP"), + Sound::EntitySnowballThrow { .. } => f.write_str("ENTITY_SNOWBALL_THROW"), + Sound::EntitySnowGolemAmbient { .. } => f.write_str("ENTITY_SNOW_GOLEM_AMBIENT"), + Sound::EntitySnowGolemDeath { .. } => f.write_str("ENTITY_SNOW_GOLEM_DEATH"), + Sound::EntitySnowGolemHurt { .. } => f.write_str("ENTITY_SNOW_GOLEM_HURT"), + Sound::EntitySnowGolemShear { .. } => f.write_str("ENTITY_SNOW_GOLEM_SHEAR"), + Sound::EntitySnowGolemShoot { .. } => f.write_str("ENTITY_SNOW_GOLEM_SHOOT"), + Sound::EntitySpiderAmbient { .. } => f.write_str("ENTITY_SPIDER_AMBIENT"), + Sound::EntitySpiderDeath { .. } => f.write_str("ENTITY_SPIDER_DEATH"), + Sound::EntitySpiderHurt { .. } => f.write_str("ENTITY_SPIDER_HURT"), + Sound::EntitySpiderStep { .. } => f.write_str("ENTITY_SPIDER_STEP"), + Sound::EntitySplashPotionBreak { .. } => f.write_str("ENTITY_SPLASH_POTION_BREAK"), + Sound::EntitySplashPotionThrow { .. } => f.write_str("ENTITY_SPLASH_POTION_THROW"), + Sound::EntitySquidAmbient { .. } => f.write_str("ENTITY_SQUID_AMBIENT"), + Sound::EntitySquidDeath { .. } => f.write_str("ENTITY_SQUID_DEATH"), + Sound::EntitySquidHurt { .. } => f.write_str("ENTITY_SQUID_HURT"), + Sound::EntitySquidSquirt { .. } => f.write_str("ENTITY_SQUID_SQUIRT"), + Sound::EntityStrayAmbient { .. } => f.write_str("ENTITY_STRAY_AMBIENT"), + Sound::EntityStrayDeath { .. } => f.write_str("ENTITY_STRAY_DEATH"), + Sound::EntityStrayHurt { .. } => f.write_str("ENTITY_STRAY_HURT"), + Sound::EntityStrayStep { .. } => f.write_str("ENTITY_STRAY_STEP"), + Sound::EntityStriderAmbient { .. } => f.write_str("ENTITY_STRIDER_AMBIENT"), + Sound::EntityStriderDeath { .. } => f.write_str("ENTITY_STRIDER_DEATH"), + Sound::EntityStriderEat { .. } => f.write_str("ENTITY_STRIDER_EAT"), + Sound::EntityStriderHappy { .. } => f.write_str("ENTITY_STRIDER_HAPPY"), + Sound::EntityStriderHurt { .. } => f.write_str("ENTITY_STRIDER_HURT"), + Sound::EntityStriderRetreat { .. } => f.write_str("ENTITY_STRIDER_RETREAT"), + Sound::EntityStriderSaddle { .. } => f.write_str("ENTITY_STRIDER_SADDLE"), + Sound::EntityStriderStep { .. } => f.write_str("ENTITY_STRIDER_STEP"), + Sound::EntityStriderStepLava { .. } => f.write_str("ENTITY_STRIDER_STEP_LAVA"), + Sound::EntityTadpoleDeath { .. } => f.write_str("ENTITY_TADPOLE_DEATH"), + Sound::EntityTadpoleFlop { .. } => f.write_str("ENTITY_TADPOLE_FLOP"), + Sound::EntityTadpoleGrowUp { .. } => f.write_str("ENTITY_TADPOLE_GROW_UP"), + Sound::EntityTadpoleHurt { .. } => f.write_str("ENTITY_TADPOLE_HURT"), + Sound::EntityTntPrimed { .. } => f.write_str("ENTITY_TNT_PRIMED"), + Sound::EntityTropicalFishAmbient { .. } => f.write_str("ENTITY_TROPICAL_FISH_AMBIENT"), + Sound::EntityTropicalFishDeath { .. } => f.write_str("ENTITY_TROPICAL_FISH_DEATH"), + Sound::EntityTropicalFishFlop { .. } => f.write_str("ENTITY_TROPICAL_FISH_FLOP"), + Sound::EntityTropicalFishHurt { .. } => f.write_str("ENTITY_TROPICAL_FISH_HURT"), + Sound::EntityTurtleAmbientLand { .. } => f.write_str("ENTITY_TURTLE_AMBIENT_LAND"), + Sound::EntityTurtleDeath { .. } => f.write_str("ENTITY_TURTLE_DEATH"), + Sound::EntityTurtleDeathBaby { .. } => f.write_str("ENTITY_TURTLE_DEATH_BABY"), + Sound::EntityTurtleEggBreak { .. } => f.write_str("ENTITY_TURTLE_EGG_BREAK"), + Sound::EntityTurtleEggCrack { .. } => f.write_str("ENTITY_TURTLE_EGG_CRACK"), + Sound::EntityTurtleEggHatch { .. } => f.write_str("ENTITY_TURTLE_EGG_HATCH"), + Sound::EntityTurtleHurt { .. } => f.write_str("ENTITY_TURTLE_HURT"), + Sound::EntityTurtleHurtBaby { .. } => f.write_str("ENTITY_TURTLE_HURT_BABY"), + Sound::EntityTurtleLayEgg { .. } => f.write_str("ENTITY_TURTLE_LAY_EGG"), + Sound::EntityTurtleShamble { .. } => f.write_str("ENTITY_TURTLE_SHAMBLE"), + Sound::EntityTurtleShambleBaby { .. } => f.write_str("ENTITY_TURTLE_SHAMBLE_BABY"), + Sound::EntityTurtleSwim { .. } => f.write_str("ENTITY_TURTLE_SWIM"), + Sound::EntityVexAmbient { .. } => f.write_str("ENTITY_VEX_AMBIENT"), + Sound::EntityVexCharge { .. } => f.write_str("ENTITY_VEX_CHARGE"), + Sound::EntityVexDeath { .. } => f.write_str("ENTITY_VEX_DEATH"), + Sound::EntityVexHurt { .. } => f.write_str("ENTITY_VEX_HURT"), + Sound::EntityVillagerAmbient { .. } => f.write_str("ENTITY_VILLAGER_AMBIENT"), + Sound::EntityVillagerCelebrate { .. } => f.write_str("ENTITY_VILLAGER_CELEBRATE"), + Sound::EntityVillagerDeath { .. } => f.write_str("ENTITY_VILLAGER_DEATH"), + Sound::EntityVillagerHurt { .. } => f.write_str("ENTITY_VILLAGER_HURT"), + Sound::EntityVillagerNo { .. } => f.write_str("ENTITY_VILLAGER_NO"), + Sound::EntityVillagerTrade { .. } => f.write_str("ENTITY_VILLAGER_TRADE"), + Sound::EntityVillagerWorkArmorer { .. } => f.write_str("ENTITY_VILLAGER_WORK_ARMORER"), + Sound::EntityVillagerWorkButcher { .. } => f.write_str("ENTITY_VILLAGER_WORK_BUTCHER"), + Sound::EntityVillagerWorkCartographer { .. } => { + f.write_str("ENTITY_VILLAGER_WORK_CARTOGRAPHER") + } + Sound::EntityVillagerWorkCleric { .. } => f.write_str("ENTITY_VILLAGER_WORK_CLERIC"), + Sound::EntityVillagerWorkFarmer { .. } => f.write_str("ENTITY_VILLAGER_WORK_FARMER"), + Sound::EntityVillagerWorkFisherman { .. } => { + f.write_str("ENTITY_VILLAGER_WORK_FISHERMAN") + } + Sound::EntityVillagerWorkFletcher { .. } => { + f.write_str("ENTITY_VILLAGER_WORK_FLETCHER") + } + Sound::EntityVillagerWorkLeatherworker { .. } => { + f.write_str("ENTITY_VILLAGER_WORK_LEATHERWORKER") + } + Sound::EntityVillagerWorkLibrarian { .. } => { + f.write_str("ENTITY_VILLAGER_WORK_LIBRARIAN") + } + Sound::EntityVillagerWorkMason { .. } => f.write_str("ENTITY_VILLAGER_WORK_MASON"), + Sound::EntityVillagerWorkShepherd { .. } => { + f.write_str("ENTITY_VILLAGER_WORK_SHEPHERD") + } + Sound::EntityVillagerWorkToolsmith { .. } => { + f.write_str("ENTITY_VILLAGER_WORK_TOOLSMITH") + } + Sound::EntityVillagerWorkWeaponsmith { .. } => { + f.write_str("ENTITY_VILLAGER_WORK_WEAPONSMITH") + } + Sound::EntityVillagerYes { .. } => f.write_str("ENTITY_VILLAGER_YES"), + Sound::EntityVindicatorAmbient { .. } => f.write_str("ENTITY_VINDICATOR_AMBIENT"), + Sound::EntityVindicatorCelebrate { .. } => f.write_str("ENTITY_VINDICATOR_CELEBRATE"), + Sound::EntityVindicatorDeath { .. } => f.write_str("ENTITY_VINDICATOR_DEATH"), + Sound::EntityVindicatorHurt { .. } => f.write_str("ENTITY_VINDICATOR_HURT"), + Sound::EntityWanderingTraderAmbient { .. } => { + f.write_str("ENTITY_WANDERING_TRADER_AMBIENT") + } + Sound::EntityWanderingTraderDeath { .. } => { + f.write_str("ENTITY_WANDERING_TRADER_DEATH") + } + Sound::EntityWanderingTraderDisappeared { .. } => { + f.write_str("ENTITY_WANDERING_TRADER_DISAPPEARED") + } + Sound::EntityWanderingTraderDrinkMilk { .. } => { + f.write_str("ENTITY_WANDERING_TRADER_DRINK_MILK") + } + Sound::EntityWanderingTraderDrinkPotion { .. } => { + f.write_str("ENTITY_WANDERING_TRADER_DRINK_POTION") + } + Sound::EntityWanderingTraderHurt { .. } => f.write_str("ENTITY_WANDERING_TRADER_HURT"), + Sound::EntityWanderingTraderNo { .. } => f.write_str("ENTITY_WANDERING_TRADER_NO"), + Sound::EntityWanderingTraderReappeared { .. } => { + f.write_str("ENTITY_WANDERING_TRADER_REAPPEARED") + } + Sound::EntityWanderingTraderTrade { .. } => { + f.write_str("ENTITY_WANDERING_TRADER_TRADE") + } + Sound::EntityWanderingTraderYes { .. } => f.write_str("ENTITY_WANDERING_TRADER_YES"), + Sound::EntityWardenAgitated { .. } => f.write_str("ENTITY_WARDEN_AGITATED"), + Sound::EntityWardenAmbient { .. } => f.write_str("ENTITY_WARDEN_AMBIENT"), + Sound::EntityWardenAngry { .. } => f.write_str("ENTITY_WARDEN_ANGRY"), + Sound::EntityWardenAttackImpact { .. } => f.write_str("ENTITY_WARDEN_ATTACK_IMPACT"), + Sound::EntityWardenDeath { .. } => f.write_str("ENTITY_WARDEN_DEATH"), + Sound::EntityWardenDig { .. } => f.write_str("ENTITY_WARDEN_DIG"), + Sound::EntityWardenEmerge { .. } => f.write_str("ENTITY_WARDEN_EMERGE"), + Sound::EntityWardenHeartbeat { .. } => f.write_str("ENTITY_WARDEN_HEARTBEAT"), + Sound::EntityWardenHurt { .. } => f.write_str("ENTITY_WARDEN_HURT"), + Sound::EntityWardenListening { .. } => f.write_str("ENTITY_WARDEN_LISTENING"), + Sound::EntityWardenListeningAngry { .. } => { + f.write_str("ENTITY_WARDEN_LISTENING_ANGRY") + } + Sound::EntityWardenNearbyClose { .. } => f.write_str("ENTITY_WARDEN_NEARBY_CLOSE"), + Sound::EntityWardenNearbyCloser { .. } => f.write_str("ENTITY_WARDEN_NEARBY_CLOSER"), + Sound::EntityWardenNearbyClosest { .. } => f.write_str("ENTITY_WARDEN_NEARBY_CLOSEST"), + Sound::EntityWardenRoar { .. } => f.write_str("ENTITY_WARDEN_ROAR"), + Sound::EntityWardenSniff { .. } => f.write_str("ENTITY_WARDEN_SNIFF"), + Sound::EntityWardenSonicBoom { .. } => f.write_str("ENTITY_WARDEN_SONIC_BOOM"), + Sound::EntityWardenSonicCharge { .. } => f.write_str("ENTITY_WARDEN_SONIC_CHARGE"), + Sound::EntityWardenStep { .. } => f.write_str("ENTITY_WARDEN_STEP"), + Sound::EntityWardenTendrilClicks { .. } => f.write_str("ENTITY_WARDEN_TENDRIL_CLICKS"), + Sound::EntityWindChargeThrow { .. } => f.write_str("ENTITY_WIND_CHARGE_THROW"), + Sound::EntityWindChargeWindBurst { .. } => f.write_str("ENTITY_WIND_CHARGE_WIND_BURST"), + Sound::EntityWitchAmbient { .. } => f.write_str("ENTITY_WITCH_AMBIENT"), + Sound::EntityWitchCelebrate { .. } => f.write_str("ENTITY_WITCH_CELEBRATE"), + Sound::EntityWitchDeath { .. } => f.write_str("ENTITY_WITCH_DEATH"), + Sound::EntityWitchDrink { .. } => f.write_str("ENTITY_WITCH_DRINK"), + Sound::EntityWitchHurt { .. } => f.write_str("ENTITY_WITCH_HURT"), + Sound::EntityWitchThrow { .. } => f.write_str("ENTITY_WITCH_THROW"), + Sound::EntityWitherAmbient { .. } => f.write_str("ENTITY_WITHER_AMBIENT"), + Sound::EntityWitherBreakBlock { .. } => f.write_str("ENTITY_WITHER_BREAK_BLOCK"), + Sound::EntityWitherDeath { .. } => f.write_str("ENTITY_WITHER_DEATH"), + Sound::EntityWitherHurt { .. } => f.write_str("ENTITY_WITHER_HURT"), + Sound::EntityWitherShoot { .. } => f.write_str("ENTITY_WITHER_SHOOT"), + Sound::EntityWitherSkeletonAmbient { .. } => { + f.write_str("ENTITY_WITHER_SKELETON_AMBIENT") + } + Sound::EntityWitherSkeletonDeath { .. } => f.write_str("ENTITY_WITHER_SKELETON_DEATH"), + Sound::EntityWitherSkeletonHurt { .. } => f.write_str("ENTITY_WITHER_SKELETON_HURT"), + Sound::EntityWitherSkeletonStep { .. } => f.write_str("ENTITY_WITHER_SKELETON_STEP"), + Sound::EntityWitherSpawn { .. } => f.write_str("ENTITY_WITHER_SPAWN"), + Sound::EntityWolfAmbient { .. } => f.write_str("ENTITY_WOLF_AMBIENT"), + Sound::EntityWolfDeath { .. } => f.write_str("ENTITY_WOLF_DEATH"), + Sound::EntityWolfGrowl { .. } => f.write_str("ENTITY_WOLF_GROWL"), + Sound::EntityWolfHowl { .. } => f.write_str("ENTITY_WOLF_HOWL"), + Sound::EntityWolfHurt { .. } => f.write_str("ENTITY_WOLF_HURT"), + Sound::EntityWolfPant { .. } => f.write_str("ENTITY_WOLF_PANT"), + Sound::EntityWolfShake { .. } => f.write_str("ENTITY_WOLF_SHAKE"), + Sound::EntityWolfStep { .. } => f.write_str("ENTITY_WOLF_STEP"), + Sound::EntityWolfWhine { .. } => f.write_str("ENTITY_WOLF_WHINE"), + Sound::EntityZoglinAmbient { .. } => f.write_str("ENTITY_ZOGLIN_AMBIENT"), + Sound::EntityZoglinAngry { .. } => f.write_str("ENTITY_ZOGLIN_ANGRY"), + Sound::EntityZoglinAttack { .. } => f.write_str("ENTITY_ZOGLIN_ATTACK"), + Sound::EntityZoglinDeath { .. } => f.write_str("ENTITY_ZOGLIN_DEATH"), + Sound::EntityZoglinHurt { .. } => f.write_str("ENTITY_ZOGLIN_HURT"), + Sound::EntityZoglinStep { .. } => f.write_str("ENTITY_ZOGLIN_STEP"), + Sound::EntityZombieAmbient { .. } => f.write_str("ENTITY_ZOMBIE_AMBIENT"), + Sound::EntityZombieAttackIronDoor { .. } => { + f.write_str("ENTITY_ZOMBIE_ATTACK_IRON_DOOR") + } + Sound::EntityZombieAttackWoodenDoor { .. } => { + f.write_str("ENTITY_ZOMBIE_ATTACK_WOODEN_DOOR") + } + Sound::EntityZombieBreakWoodenDoor { .. } => { + f.write_str("ENTITY_ZOMBIE_BREAK_WOODEN_DOOR") + } + Sound::EntityZombieConvertedToDrowned { .. } => { + f.write_str("ENTITY_ZOMBIE_CONVERTED_TO_DROWNED") + } + Sound::EntityZombieDeath { .. } => f.write_str("ENTITY_ZOMBIE_DEATH"), + Sound::EntityZombieDestroyEgg { .. } => f.write_str("ENTITY_ZOMBIE_DESTROY_EGG"), + Sound::EntityZombieHorseAmbient { .. } => f.write_str("ENTITY_ZOMBIE_HORSE_AMBIENT"), + Sound::EntityZombieHorseDeath { .. } => f.write_str("ENTITY_ZOMBIE_HORSE_DEATH"), + Sound::EntityZombieHorseHurt { .. } => f.write_str("ENTITY_ZOMBIE_HORSE_HURT"), + Sound::EntityZombieHurt { .. } => f.write_str("ENTITY_ZOMBIE_HURT"), + Sound::EntityZombieInfect { .. } => f.write_str("ENTITY_ZOMBIE_INFECT"), + Sound::EntityZombieStep { .. } => f.write_str("ENTITY_ZOMBIE_STEP"), + Sound::EntityZombieVillagerAmbient { .. } => { + f.write_str("ENTITY_ZOMBIE_VILLAGER_AMBIENT") + } + Sound::EntityZombieVillagerConverted { .. } => { + f.write_str("ENTITY_ZOMBIE_VILLAGER_CONVERTED") + } + Sound::EntityZombieVillagerCure { .. } => f.write_str("ENTITY_ZOMBIE_VILLAGER_CURE"), + Sound::EntityZombieVillagerDeath { .. } => f.write_str("ENTITY_ZOMBIE_VILLAGER_DEATH"), + Sound::EntityZombieVillagerHurt { .. } => f.write_str("ENTITY_ZOMBIE_VILLAGER_HURT"), + Sound::EntityZombieVillagerStep { .. } => f.write_str("ENTITY_ZOMBIE_VILLAGER_STEP"), + Sound::EntityZombifiedPiglinAmbient { .. } => { + f.write_str("ENTITY_ZOMBIFIED_PIGLIN_AMBIENT") + } + Sound::EntityZombifiedPiglinAngry { .. } => { + f.write_str("ENTITY_ZOMBIFIED_PIGLIN_ANGRY") + } + Sound::EntityZombifiedPiglinDeath { .. } => { + f.write_str("ENTITY_ZOMBIFIED_PIGLIN_DEATH") + } + Sound::EntityZombifiedPiglinHurt { .. } => f.write_str("ENTITY_ZOMBIFIED_PIGLIN_HURT"), + Sound::EventMobEffectBadOmen { .. } => f.write_str("EVENT_MOB_EFFECT_BAD_OMEN"), + Sound::EventMobEffectRaidOmen { .. } => f.write_str("EVENT_MOB_EFFECT_RAID_OMEN"), + Sound::EventMobEffectTrialOmen { .. } => f.write_str("EVENT_MOB_EFFECT_TRIAL_OMEN"), + Sound::EventRaidHorn { .. } => f.write_str("EVENT_RAID_HORN"), + Sound::IntentionallyEmpty { .. } => f.write_str("INTENTIONALLY_EMPTY"), + Sound::ItemArmorEquipChain { .. } => f.write_str("ITEM_ARMOR_EQUIP_CHAIN"), + Sound::ItemArmorEquipDiamond { .. } => f.write_str("ITEM_ARMOR_EQUIP_DIAMOND"), + Sound::ItemArmorEquipElytra { .. } => f.write_str("ITEM_ARMOR_EQUIP_ELYTRA"), + Sound::ItemArmorEquipGeneric { .. } => f.write_str("ITEM_ARMOR_EQUIP_GENERIC"), + Sound::ItemArmorEquipGold { .. } => f.write_str("ITEM_ARMOR_EQUIP_GOLD"), + Sound::ItemArmorEquipIron { .. } => f.write_str("ITEM_ARMOR_EQUIP_IRON"), + Sound::ItemArmorEquipLeather { .. } => f.write_str("ITEM_ARMOR_EQUIP_LEATHER"), + Sound::ItemArmorEquipNetherite { .. } => f.write_str("ITEM_ARMOR_EQUIP_NETHERITE"), + Sound::ItemArmorEquipTurtle { .. } => f.write_str("ITEM_ARMOR_EQUIP_TURTLE"), + Sound::ItemArmorEquipWolf { .. } => f.write_str("ITEM_ARMOR_EQUIP_WOLF"), + Sound::ItemArmorUnequipWolf { .. } => f.write_str("ITEM_ARMOR_UNEQUIP_WOLF"), + Sound::ItemAxeScrape { .. } => f.write_str("ITEM_AXE_SCRAPE"), + Sound::ItemAxeStrip { .. } => f.write_str("ITEM_AXE_STRIP"), + Sound::ItemAxeWaxOff { .. } => f.write_str("ITEM_AXE_WAX_OFF"), + Sound::ItemBoneMealUse { .. } => f.write_str("ITEM_BONE_MEAL_USE"), + Sound::ItemBookPageTurn { .. } => f.write_str("ITEM_BOOK_PAGE_TURN"), + Sound::ItemBookPut { .. } => f.write_str("ITEM_BOOK_PUT"), + Sound::ItemBottleEmpty { .. } => f.write_str("ITEM_BOTTLE_EMPTY"), + Sound::ItemBottleFill { .. } => f.write_str("ITEM_BOTTLE_FILL"), + Sound::ItemBottleFillDragonbreath { .. } => { + f.write_str("ITEM_BOTTLE_FILL_DRAGONBREATH") + } + Sound::ItemBrushBrushingGeneric { .. } => f.write_str("ITEM_BRUSH_BRUSHING_GENERIC"), + Sound::ItemBrushBrushingGravel { .. } => f.write_str("ITEM_BRUSH_BRUSHING_GRAVEL"), + Sound::ItemBrushBrushingGravelComplete { .. } => { + f.write_str("ITEM_BRUSH_BRUSHING_GRAVEL_COMPLETE") + } + Sound::ItemBrushBrushingSand { .. } => f.write_str("ITEM_BRUSH_BRUSHING_SAND"), + Sound::ItemBrushBrushingSandComplete { .. } => { + f.write_str("ITEM_BRUSH_BRUSHING_SAND_COMPLETE") + } + Sound::ItemBucketEmpty { .. } => f.write_str("ITEM_BUCKET_EMPTY"), + Sound::ItemBucketEmptyAxolotl { .. } => f.write_str("ITEM_BUCKET_EMPTY_AXOLOTL"), + Sound::ItemBucketEmptyFish { .. } => f.write_str("ITEM_BUCKET_EMPTY_FISH"), + Sound::ItemBucketEmptyLava { .. } => f.write_str("ITEM_BUCKET_EMPTY_LAVA"), + Sound::ItemBucketEmptyPowderSnow { .. } => f.write_str("ITEM_BUCKET_EMPTY_POWDER_SNOW"), + Sound::ItemBucketEmptyTadpole { .. } => f.write_str("ITEM_BUCKET_EMPTY_TADPOLE"), + Sound::ItemBucketFill { .. } => f.write_str("ITEM_BUCKET_FILL"), + Sound::ItemBucketFillAxolotl { .. } => f.write_str("ITEM_BUCKET_FILL_AXOLOTL"), + Sound::ItemBucketFillFish { .. } => f.write_str("ITEM_BUCKET_FILL_FISH"), + Sound::ItemBucketFillLava { .. } => f.write_str("ITEM_BUCKET_FILL_LAVA"), + Sound::ItemBucketFillPowderSnow { .. } => f.write_str("ITEM_BUCKET_FILL_POWDER_SNOW"), + Sound::ItemBucketFillTadpole { .. } => f.write_str("ITEM_BUCKET_FILL_TADPOLE"), + Sound::ItemBundleDropContents { .. } => f.write_str("ITEM_BUNDLE_DROP_CONTENTS"), + Sound::ItemBundleInsert { .. } => f.write_str("ITEM_BUNDLE_INSERT"), + Sound::ItemBundleRemoveOne { .. } => f.write_str("ITEM_BUNDLE_REMOVE_ONE"), + Sound::ItemChorusFruitTeleport { .. } => f.write_str("ITEM_CHORUS_FRUIT_TELEPORT"), + Sound::ItemCropPlant { .. } => f.write_str("ITEM_CROP_PLANT"), + Sound::ItemCrossbowHit { .. } => f.write_str("ITEM_CROSSBOW_HIT"), + Sound::ItemCrossbowLoadingEnd { .. } => f.write_str("ITEM_CROSSBOW_LOADING_END"), + Sound::ItemCrossbowLoadingMiddle { .. } => f.write_str("ITEM_CROSSBOW_LOADING_MIDDLE"), + Sound::ItemCrossbowLoadingStart { .. } => f.write_str("ITEM_CROSSBOW_LOADING_START"), + Sound::ItemCrossbowQuickCharge1 { .. } => f.write_str("ITEM_CROSSBOW_QUICK_CHARGE_1"), + Sound::ItemCrossbowQuickCharge2 { .. } => f.write_str("ITEM_CROSSBOW_QUICK_CHARGE_2"), + Sound::ItemCrossbowQuickCharge3 { .. } => f.write_str("ITEM_CROSSBOW_QUICK_CHARGE_3"), + Sound::ItemCrossbowShoot { .. } => f.write_str("ITEM_CROSSBOW_SHOOT"), + Sound::ItemDyeUse { .. } => f.write_str("ITEM_DYE_USE"), + Sound::ItemElytraFlying { .. } => f.write_str("ITEM_ELYTRA_FLYING"), + Sound::ItemFirechargeUse { .. } => f.write_str("ITEM_FIRECHARGE_USE"), + Sound::ItemFlintandsteelUse { .. } => f.write_str("ITEM_FLINTANDSTEEL_USE"), + Sound::ItemGlowInkSacUse { .. } => f.write_str("ITEM_GLOW_INK_SAC_USE"), + Sound::ItemGoatHornPlay { .. } => f.write_str("ITEM_GOAT_HORN_PLAY"), + Sound::ItemGoatHornSound0 { .. } => f.write_str("ITEM_GOAT_HORN_SOUND_0"), + Sound::ItemGoatHornSound1 { .. } => f.write_str("ITEM_GOAT_HORN_SOUND_1"), + Sound::ItemGoatHornSound2 { .. } => f.write_str("ITEM_GOAT_HORN_SOUND_2"), + Sound::ItemGoatHornSound3 { .. } => f.write_str("ITEM_GOAT_HORN_SOUND_3"), + Sound::ItemGoatHornSound4 { .. } => f.write_str("ITEM_GOAT_HORN_SOUND_4"), + Sound::ItemGoatHornSound5 { .. } => f.write_str("ITEM_GOAT_HORN_SOUND_5"), + Sound::ItemGoatHornSound6 { .. } => f.write_str("ITEM_GOAT_HORN_SOUND_6"), + Sound::ItemGoatHornSound7 { .. } => f.write_str("ITEM_GOAT_HORN_SOUND_7"), + Sound::ItemHoeTill { .. } => f.write_str("ITEM_HOE_TILL"), + Sound::ItemHoneycombWaxOn { .. } => f.write_str("ITEM_HONEYCOMB_WAX_ON"), + Sound::ItemHoneyBottleDrink { .. } => f.write_str("ITEM_HONEY_BOTTLE_DRINK"), + Sound::ItemInkSacUse { .. } => f.write_str("ITEM_INK_SAC_USE"), + Sound::ItemLodestoneCompassLock { .. } => f.write_str("ITEM_LODESTONE_COMPASS_LOCK"), + Sound::ItemMaceSmashAir { .. } => f.write_str("ITEM_MACE_SMASH_AIR"), + Sound::ItemMaceSmashGround { .. } => f.write_str("ITEM_MACE_SMASH_GROUND"), + Sound::ItemMaceSmashGroundHeavy { .. } => f.write_str("ITEM_MACE_SMASH_GROUND_HEAVY"), + Sound::ItemNetherWartPlant { .. } => f.write_str("ITEM_NETHER_WART_PLANT"), + Sound::ItemOminousBottleDispose { .. } => f.write_str("ITEM_OMINOUS_BOTTLE_DISPOSE"), + Sound::ItemShieldBlock { .. } => f.write_str("ITEM_SHIELD_BLOCK"), + Sound::ItemShieldBreak { .. } => f.write_str("ITEM_SHIELD_BREAK"), + Sound::ItemShovelFlatten { .. } => f.write_str("ITEM_SHOVEL_FLATTEN"), + Sound::ItemSpyglassStopUsing { .. } => f.write_str("ITEM_SPYGLASS_STOP_USING"), + Sound::ItemSpyglassUse { .. } => f.write_str("ITEM_SPYGLASS_USE"), + Sound::ItemTotemUse { .. } => f.write_str("ITEM_TOTEM_USE"), + Sound::ItemTridentHit { .. } => f.write_str("ITEM_TRIDENT_HIT"), + Sound::ItemTridentHitGround { .. } => f.write_str("ITEM_TRIDENT_HIT_GROUND"), + Sound::ItemTridentReturn { .. } => f.write_str("ITEM_TRIDENT_RETURN"), + Sound::ItemTridentRiptide1 { .. } => f.write_str("ITEM_TRIDENT_RIPTIDE_1"), + Sound::ItemTridentRiptide2 { .. } => f.write_str("ITEM_TRIDENT_RIPTIDE_2"), + Sound::ItemTridentRiptide3 { .. } => f.write_str("ITEM_TRIDENT_RIPTIDE_3"), + Sound::ItemTridentThrow { .. } => f.write_str("ITEM_TRIDENT_THROW"), + Sound::ItemTridentThunder { .. } => f.write_str("ITEM_TRIDENT_THUNDER"), + Sound::ItemWolfArmorBreak { .. } => f.write_str("ITEM_WOLF_ARMOR_BREAK"), + Sound::ItemWolfArmorCrack { .. } => f.write_str("ITEM_WOLF_ARMOR_CRACK"), + Sound::ItemWolfArmorDamage { .. } => f.write_str("ITEM_WOLF_ARMOR_DAMAGE"), + Sound::ItemWolfArmorRepair { .. } => f.write_str("ITEM_WOLF_ARMOR_REPAIR"), + Sound::MusicCreative { .. } => f.write_str("MUSIC_CREATIVE"), + Sound::MusicCredits { .. } => f.write_str("MUSIC_CREDITS"), + Sound::MusicDisc11 { .. } => f.write_str("MUSIC_DISC_11"), + Sound::MusicDisc13 { .. } => f.write_str("MUSIC_DISC_13"), + Sound::MusicDisc5 { .. } => f.write_str("MUSIC_DISC_5"), + Sound::MusicDiscBlocks { .. } => f.write_str("MUSIC_DISC_BLOCKS"), + Sound::MusicDiscCat { .. } => f.write_str("MUSIC_DISC_CAT"), + Sound::MusicDiscChirp { .. } => f.write_str("MUSIC_DISC_CHIRP"), + Sound::MusicDiscCreator { .. } => f.write_str("MUSIC_DISC_CREATOR"), + Sound::MusicDiscCreatorMusicBox { .. } => f.write_str("MUSIC_DISC_CREATOR_MUSIC_BOX"), + Sound::MusicDiscFar { .. } => f.write_str("MUSIC_DISC_FAR"), + Sound::MusicDiscMall { .. } => f.write_str("MUSIC_DISC_MALL"), + Sound::MusicDiscMellohi { .. } => f.write_str("MUSIC_DISC_MELLOHI"), + Sound::MusicDiscOtherside { .. } => f.write_str("MUSIC_DISC_OTHERSIDE"), + Sound::MusicDiscPigstep { .. } => f.write_str("MUSIC_DISC_PIGSTEP"), + Sound::MusicDiscPrecipice { .. } => f.write_str("MUSIC_DISC_PRECIPICE"), + Sound::MusicDiscRelic { .. } => f.write_str("MUSIC_DISC_RELIC"), + Sound::MusicDiscStal { .. } => f.write_str("MUSIC_DISC_STAL"), + Sound::MusicDiscStrad { .. } => f.write_str("MUSIC_DISC_STRAD"), + Sound::MusicDiscWait { .. } => f.write_str("MUSIC_DISC_WAIT"), + Sound::MusicDiscWard { .. } => f.write_str("MUSIC_DISC_WARD"), + Sound::MusicDragon { .. } => f.write_str("MUSIC_DRAGON"), + Sound::MusicEnd { .. } => f.write_str("MUSIC_END"), + Sound::MusicGame { .. } => f.write_str("MUSIC_GAME"), + Sound::MusicMenu { .. } => f.write_str("MUSIC_MENU"), + Sound::MusicNetherBasaltDeltas { .. } => f.write_str("MUSIC_NETHER_BASALT_DELTAS"), + Sound::MusicNetherCrimsonForest { .. } => f.write_str("MUSIC_NETHER_CRIMSON_FOREST"), + Sound::MusicNetherNetherWastes { .. } => f.write_str("MUSIC_NETHER_NETHER_WASTES"), + Sound::MusicNetherSoulSandValley { .. } => f.write_str("MUSIC_NETHER_SOUL_SAND_VALLEY"), + Sound::MusicNetherWarpedForest { .. } => f.write_str("MUSIC_NETHER_WARPED_FOREST"), + Sound::MusicOverworldBadlands { .. } => f.write_str("MUSIC_OVERWORLD_BADLANDS"), + Sound::MusicOverworldBambooJungle { .. } => { + f.write_str("MUSIC_OVERWORLD_BAMBOO_JUNGLE") + } + Sound::MusicOverworldCherryGrove { .. } => f.write_str("MUSIC_OVERWORLD_CHERRY_GROVE"), + Sound::MusicOverworldDeepDark { .. } => f.write_str("MUSIC_OVERWORLD_DEEP_DARK"), + Sound::MusicOverworldDesert { .. } => f.write_str("MUSIC_OVERWORLD_DESERT"), + Sound::MusicOverworldDripstoneCaves { .. } => { + f.write_str("MUSIC_OVERWORLD_DRIPSTONE_CAVES") + } + Sound::MusicOverworldFlowerForest { .. } => { + f.write_str("MUSIC_OVERWORLD_FLOWER_FOREST") + } + Sound::MusicOverworldForest { .. } => f.write_str("MUSIC_OVERWORLD_FOREST"), + Sound::MusicOverworldFrozenPeaks { .. } => f.write_str("MUSIC_OVERWORLD_FROZEN_PEAKS"), + Sound::MusicOverworldGrove { .. } => f.write_str("MUSIC_OVERWORLD_GROVE"), + Sound::MusicOverworldJaggedPeaks { .. } => f.write_str("MUSIC_OVERWORLD_JAGGED_PEAKS"), + Sound::MusicOverworldJungle { .. } => f.write_str("MUSIC_OVERWORLD_JUNGLE"), + Sound::MusicOverworldLushCaves { .. } => f.write_str("MUSIC_OVERWORLD_LUSH_CAVES"), + Sound::MusicOverworldMeadow { .. } => f.write_str("MUSIC_OVERWORLD_MEADOW"), + Sound::MusicOverworldOldGrowthTaiga { .. } => { + f.write_str("MUSIC_OVERWORLD_OLD_GROWTH_TAIGA") + } + Sound::MusicOverworldSnowySlopes { .. } => f.write_str("MUSIC_OVERWORLD_SNOWY_SLOPES"), + Sound::MusicOverworldSparseJungle { .. } => { + f.write_str("MUSIC_OVERWORLD_SPARSE_JUNGLE") + } + Sound::MusicOverworldStonyPeaks { .. } => f.write_str("MUSIC_OVERWORLD_STONY_PEAKS"), + Sound::MusicOverworldSwamp { .. } => f.write_str("MUSIC_OVERWORLD_SWAMP"), + Sound::MusicUnderWater { .. } => f.write_str("MUSIC_UNDER_WATER"), + Sound::ParticleSoulEscape { .. } => f.write_str("PARTICLE_SOUL_ESCAPE"), + Sound::UiButtonClick { .. } => f.write_str("UI_BUTTON_CLICK"), + Sound::UiCartographyTableTakeResult { .. } => { + f.write_str("UI_CARTOGRAPHY_TABLE_TAKE_RESULT") + } + Sound::UiLoomSelectPattern { .. } => f.write_str("UI_LOOM_SELECT_PATTERN"), + Sound::UiLoomTakeResult { .. } => f.write_str("UI_LOOM_TAKE_RESULT"), + Sound::UiStonecutterSelectRecipe { .. } => f.write_str("UI_STONECUTTER_SELECT_RECIPE"), + Sound::UiStonecutterTakeResult { .. } => f.write_str("UI_STONECUTTER_TAKE_RESULT"), + Sound::UiToastChallengeComplete { .. } => f.write_str("UI_TOAST_CHALLENGE_COMPLETE"), + Sound::UiToastIn { .. } => f.write_str("UI_TOAST_IN"), + Sound::UiToastOut { .. } => f.write_str("UI_TOAST_OUT"), + Sound::WeatherRain { .. } => f.write_str("WEATHER_RAIN"), + Sound::WeatherRainAbove { .. } => f.write_str("WEATHER_RAIN_ABOVE"), + } + } +} +impl<'mc> std::ops::Deref for Sound<'mc> { + type Target = SoundStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + Sound::AmbientBasaltDeltasAdditions { inner } => inner, + Sound::AmbientBasaltDeltasLoop { inner } => inner, + Sound::AmbientBasaltDeltasMood { inner } => inner, + Sound::AmbientCave { inner } => inner, + Sound::AmbientCrimsonForestAdditions { inner } => inner, + Sound::AmbientCrimsonForestLoop { inner } => inner, + Sound::AmbientCrimsonForestMood { inner } => inner, + Sound::AmbientNetherWastesAdditions { inner } => inner, + Sound::AmbientNetherWastesLoop { inner } => inner, + Sound::AmbientNetherWastesMood { inner } => inner, + Sound::AmbientSoulSandValleyAdditions { inner } => inner, + Sound::AmbientSoulSandValleyLoop { inner } => inner, + Sound::AmbientSoulSandValleyMood { inner } => inner, + Sound::AmbientUnderwaterEnter { inner } => inner, + Sound::AmbientUnderwaterExit { inner } => inner, + Sound::AmbientUnderwaterLoop { inner } => inner, + Sound::AmbientUnderwaterLoopAdditions { inner } => inner, + Sound::AmbientUnderwaterLoopAdditionsRare { inner } => inner, + Sound::AmbientUnderwaterLoopAdditionsUltraRare { inner } => inner, + Sound::AmbientWarpedForestAdditions { inner } => inner, + Sound::AmbientWarpedForestLoop { inner } => inner, + Sound::AmbientWarpedForestMood { inner } => inner, + Sound::BlockAmethystBlockBreak { inner } => inner, + Sound::BlockAmethystBlockChime { inner } => inner, + Sound::BlockAmethystBlockFall { inner } => inner, + Sound::BlockAmethystBlockHit { inner } => inner, + Sound::BlockAmethystBlockPlace { inner } => inner, + Sound::BlockAmethystBlockResonate { inner } => inner, + Sound::BlockAmethystBlockStep { inner } => inner, + Sound::BlockAmethystClusterBreak { inner } => inner, + Sound::BlockAmethystClusterFall { inner } => inner, + Sound::BlockAmethystClusterHit { inner } => inner, + Sound::BlockAmethystClusterPlace { inner } => inner, + Sound::BlockAmethystClusterStep { inner } => inner, + Sound::BlockAncientDebrisBreak { inner } => inner, + Sound::BlockAncientDebrisFall { inner } => inner, + Sound::BlockAncientDebrisHit { inner } => inner, + Sound::BlockAncientDebrisPlace { inner } => inner, + Sound::BlockAncientDebrisStep { inner } => inner, + Sound::BlockAnvilBreak { inner } => inner, + Sound::BlockAnvilDestroy { inner } => inner, + Sound::BlockAnvilFall { inner } => inner, + Sound::BlockAnvilHit { inner } => inner, + Sound::BlockAnvilLand { inner } => inner, + Sound::BlockAnvilPlace { inner } => inner, + Sound::BlockAnvilStep { inner } => inner, + Sound::BlockAnvilUse { inner } => inner, + Sound::BlockAzaleaBreak { inner } => inner, + Sound::BlockAzaleaFall { inner } => inner, + Sound::BlockAzaleaHit { inner } => inner, + Sound::BlockAzaleaLeavesBreak { inner } => inner, + Sound::BlockAzaleaLeavesFall { inner } => inner, + Sound::BlockAzaleaLeavesHit { inner } => inner, + Sound::BlockAzaleaLeavesPlace { inner } => inner, + Sound::BlockAzaleaLeavesStep { inner } => inner, + Sound::BlockAzaleaPlace { inner } => inner, + Sound::BlockAzaleaStep { inner } => inner, + Sound::BlockBambooBreak { inner } => inner, + Sound::BlockBambooFall { inner } => inner, + Sound::BlockBambooHit { inner } => inner, + Sound::BlockBambooPlace { inner } => inner, + Sound::BlockBambooSaplingBreak { inner } => inner, + Sound::BlockBambooSaplingHit { inner } => inner, + Sound::BlockBambooSaplingPlace { inner } => inner, + Sound::BlockBambooStep { inner } => inner, + Sound::BlockBambooWoodBreak { inner } => inner, + Sound::BlockBambooWoodButtonClickOff { inner } => inner, + Sound::BlockBambooWoodButtonClickOn { inner } => inner, + Sound::BlockBambooWoodDoorClose { inner } => inner, + Sound::BlockBambooWoodDoorOpen { inner } => inner, + Sound::BlockBambooWoodFall { inner } => inner, + Sound::BlockBambooWoodFenceGateClose { inner } => inner, + Sound::BlockBambooWoodFenceGateOpen { inner } => inner, + Sound::BlockBambooWoodHangingSignBreak { inner } => inner, + Sound::BlockBambooWoodHangingSignFall { inner } => inner, + Sound::BlockBambooWoodHangingSignHit { inner } => inner, + Sound::BlockBambooWoodHangingSignPlace { inner } => inner, + Sound::BlockBambooWoodHangingSignStep { inner } => inner, + Sound::BlockBambooWoodHit { inner } => inner, + Sound::BlockBambooWoodPlace { inner } => inner, + Sound::BlockBambooWoodPressurePlateClickOff { inner } => inner, + Sound::BlockBambooWoodPressurePlateClickOn { inner } => inner, + Sound::BlockBambooWoodStep { inner } => inner, + Sound::BlockBambooWoodTrapdoorClose { inner } => inner, + Sound::BlockBambooWoodTrapdoorOpen { inner } => inner, + Sound::BlockBarrelClose { inner } => inner, + Sound::BlockBarrelOpen { inner } => inner, + Sound::BlockBasaltBreak { inner } => inner, + Sound::BlockBasaltFall { inner } => inner, + Sound::BlockBasaltHit { inner } => inner, + Sound::BlockBasaltPlace { inner } => inner, + Sound::BlockBasaltStep { inner } => inner, + Sound::BlockBeaconActivate { inner } => inner, + Sound::BlockBeaconAmbient { inner } => inner, + Sound::BlockBeaconDeactivate { inner } => inner, + Sound::BlockBeaconPowerSelect { inner } => inner, + Sound::BlockBeehiveDrip { inner } => inner, + Sound::BlockBeehiveEnter { inner } => inner, + Sound::BlockBeehiveExit { inner } => inner, + Sound::BlockBeehiveShear { inner } => inner, + Sound::BlockBeehiveWork { inner } => inner, + Sound::BlockBellResonate { inner } => inner, + Sound::BlockBellUse { inner } => inner, + Sound::BlockBigDripleafBreak { inner } => inner, + Sound::BlockBigDripleafFall { inner } => inner, + Sound::BlockBigDripleafHit { inner } => inner, + Sound::BlockBigDripleafPlace { inner } => inner, + Sound::BlockBigDripleafStep { inner } => inner, + Sound::BlockBigDripleafTiltDown { inner } => inner, + Sound::BlockBigDripleafTiltUp { inner } => inner, + Sound::BlockBlastfurnaceFireCrackle { inner } => inner, + Sound::BlockBoneBlockBreak { inner } => inner, + Sound::BlockBoneBlockFall { inner } => inner, + Sound::BlockBoneBlockHit { inner } => inner, + Sound::BlockBoneBlockPlace { inner } => inner, + Sound::BlockBoneBlockStep { inner } => inner, + Sound::BlockBrewingStandBrew { inner } => inner, + Sound::BlockBubbleColumnBubblePop { inner } => inner, + Sound::BlockBubbleColumnUpwardsAmbient { inner } => inner, + Sound::BlockBubbleColumnUpwardsInside { inner } => inner, + Sound::BlockBubbleColumnWhirlpoolAmbient { inner } => inner, + Sound::BlockBubbleColumnWhirlpoolInside { inner } => inner, + Sound::BlockCakeAddCandle { inner } => inner, + Sound::BlockCalciteBreak { inner } => inner, + Sound::BlockCalciteFall { inner } => inner, + Sound::BlockCalciteHit { inner } => inner, + Sound::BlockCalcitePlace { inner } => inner, + Sound::BlockCalciteStep { inner } => inner, + Sound::BlockCampfireCrackle { inner } => inner, + Sound::BlockCandleAmbient { inner } => inner, + Sound::BlockCandleBreak { inner } => inner, + Sound::BlockCandleExtinguish { inner } => inner, + Sound::BlockCandleFall { inner } => inner, + Sound::BlockCandleHit { inner } => inner, + Sound::BlockCandlePlace { inner } => inner, + Sound::BlockCandleStep { inner } => inner, + Sound::BlockCaveVinesBreak { inner } => inner, + Sound::BlockCaveVinesFall { inner } => inner, + Sound::BlockCaveVinesHit { inner } => inner, + Sound::BlockCaveVinesPickBerries { inner } => inner, + Sound::BlockCaveVinesPlace { inner } => inner, + Sound::BlockCaveVinesStep { inner } => inner, + Sound::BlockChainBreak { inner } => inner, + Sound::BlockChainFall { inner } => inner, + Sound::BlockChainHit { inner } => inner, + Sound::BlockChainPlace { inner } => inner, + Sound::BlockChainStep { inner } => inner, + Sound::BlockCherryLeavesBreak { inner } => inner, + Sound::BlockCherryLeavesFall { inner } => inner, + Sound::BlockCherryLeavesHit { inner } => inner, + Sound::BlockCherryLeavesPlace { inner } => inner, + Sound::BlockCherryLeavesStep { inner } => inner, + Sound::BlockCherrySaplingBreak { inner } => inner, + Sound::BlockCherrySaplingFall { inner } => inner, + Sound::BlockCherrySaplingHit { inner } => inner, + Sound::BlockCherrySaplingPlace { inner } => inner, + Sound::BlockCherrySaplingStep { inner } => inner, + Sound::BlockCherryWoodBreak { inner } => inner, + Sound::BlockCherryWoodButtonClickOff { inner } => inner, + Sound::BlockCherryWoodButtonClickOn { inner } => inner, + Sound::BlockCherryWoodDoorClose { inner } => inner, + Sound::BlockCherryWoodDoorOpen { inner } => inner, + Sound::BlockCherryWoodFall { inner } => inner, + Sound::BlockCherryWoodFenceGateClose { inner } => inner, + Sound::BlockCherryWoodFenceGateOpen { inner } => inner, + Sound::BlockCherryWoodHangingSignBreak { inner } => inner, + Sound::BlockCherryWoodHangingSignFall { inner } => inner, + Sound::BlockCherryWoodHangingSignHit { inner } => inner, + Sound::BlockCherryWoodHangingSignPlace { inner } => inner, + Sound::BlockCherryWoodHangingSignStep { inner } => inner, + Sound::BlockCherryWoodHit { inner } => inner, + Sound::BlockCherryWoodPlace { inner } => inner, + Sound::BlockCherryWoodPressurePlateClickOff { inner } => inner, + Sound::BlockCherryWoodPressurePlateClickOn { inner } => inner, + Sound::BlockCherryWoodStep { inner } => inner, + Sound::BlockCherryWoodTrapdoorClose { inner } => inner, + Sound::BlockCherryWoodTrapdoorOpen { inner } => inner, + Sound::BlockChestClose { inner } => inner, + Sound::BlockChestLocked { inner } => inner, + Sound::BlockChestOpen { inner } => inner, + Sound::BlockChiseledBookshelfBreak { inner } => inner, + Sound::BlockChiseledBookshelfFall { inner } => inner, + Sound::BlockChiseledBookshelfHit { inner } => inner, + Sound::BlockChiseledBookshelfInsert { inner } => inner, + Sound::BlockChiseledBookshelfInsertEnchanted { inner } => inner, + Sound::BlockChiseledBookshelfPickup { inner } => inner, + Sound::BlockChiseledBookshelfPickupEnchanted { inner } => inner, + Sound::BlockChiseledBookshelfPlace { inner } => inner, + Sound::BlockChiseledBookshelfStep { inner } => inner, + Sound::BlockChorusFlowerDeath { inner } => inner, + Sound::BlockChorusFlowerGrow { inner } => inner, + Sound::BlockCobwebBreak { inner } => inner, + Sound::BlockCobwebFall { inner } => inner, + Sound::BlockCobwebHit { inner } => inner, + Sound::BlockCobwebPlace { inner } => inner, + Sound::BlockCobwebStep { inner } => inner, + Sound::BlockComparatorClick { inner } => inner, + Sound::BlockComposterEmpty { inner } => inner, + Sound::BlockComposterFill { inner } => inner, + Sound::BlockComposterFillSuccess { inner } => inner, + Sound::BlockComposterReady { inner } => inner, + Sound::BlockConduitActivate { inner } => inner, + Sound::BlockConduitAmbient { inner } => inner, + Sound::BlockConduitAmbientShort { inner } => inner, + Sound::BlockConduitAttackTarget { inner } => inner, + Sound::BlockConduitDeactivate { inner } => inner, + Sound::BlockCopperBreak { inner } => inner, + Sound::BlockCopperBulbBreak { inner } => inner, + Sound::BlockCopperBulbFall { inner } => inner, + Sound::BlockCopperBulbHit { inner } => inner, + Sound::BlockCopperBulbPlace { inner } => inner, + Sound::BlockCopperBulbStep { inner } => inner, + Sound::BlockCopperBulbTurnOff { inner } => inner, + Sound::BlockCopperBulbTurnOn { inner } => inner, + Sound::BlockCopperDoorClose { inner } => inner, + Sound::BlockCopperDoorOpen { inner } => inner, + Sound::BlockCopperFall { inner } => inner, + Sound::BlockCopperGrateBreak { inner } => inner, + Sound::BlockCopperGrateFall { inner } => inner, + Sound::BlockCopperGrateHit { inner } => inner, + Sound::BlockCopperGratePlace { inner } => inner, + Sound::BlockCopperGrateStep { inner } => inner, + Sound::BlockCopperHit { inner } => inner, + Sound::BlockCopperPlace { inner } => inner, + Sound::BlockCopperStep { inner } => inner, + Sound::BlockCopperTrapdoorClose { inner } => inner, + Sound::BlockCopperTrapdoorOpen { inner } => inner, + Sound::BlockCoralBlockBreak { inner } => inner, + Sound::BlockCoralBlockFall { inner } => inner, + Sound::BlockCoralBlockHit { inner } => inner, + Sound::BlockCoralBlockPlace { inner } => inner, + Sound::BlockCoralBlockStep { inner } => inner, + Sound::BlockCrafterCraft { inner } => inner, + Sound::BlockCrafterFail { inner } => inner, + Sound::BlockCropBreak { inner } => inner, + Sound::BlockDecoratedPotBreak { inner } => inner, + Sound::BlockDecoratedPotFall { inner } => inner, + Sound::BlockDecoratedPotHit { inner } => inner, + Sound::BlockDecoratedPotInsert { inner } => inner, + Sound::BlockDecoratedPotInsertFail { inner } => inner, + Sound::BlockDecoratedPotPlace { inner } => inner, + Sound::BlockDecoratedPotShatter { inner } => inner, + Sound::BlockDecoratedPotStep { inner } => inner, + Sound::BlockDeepslateBreak { inner } => inner, + Sound::BlockDeepslateBricksBreak { inner } => inner, + Sound::BlockDeepslateBricksFall { inner } => inner, + Sound::BlockDeepslateBricksHit { inner } => inner, + Sound::BlockDeepslateBricksPlace { inner } => inner, + Sound::BlockDeepslateBricksStep { inner } => inner, + Sound::BlockDeepslateFall { inner } => inner, + Sound::BlockDeepslateHit { inner } => inner, + Sound::BlockDeepslatePlace { inner } => inner, + Sound::BlockDeepslateStep { inner } => inner, + Sound::BlockDeepslateTilesBreak { inner } => inner, + Sound::BlockDeepslateTilesFall { inner } => inner, + Sound::BlockDeepslateTilesHit { inner } => inner, + Sound::BlockDeepslateTilesPlace { inner } => inner, + Sound::BlockDeepslateTilesStep { inner } => inner, + Sound::BlockDispenserDispense { inner } => inner, + Sound::BlockDispenserFail { inner } => inner, + Sound::BlockDispenserLaunch { inner } => inner, + Sound::BlockDripstoneBlockBreak { inner } => inner, + Sound::BlockDripstoneBlockFall { inner } => inner, + Sound::BlockDripstoneBlockHit { inner } => inner, + Sound::BlockDripstoneBlockPlace { inner } => inner, + Sound::BlockDripstoneBlockStep { inner } => inner, + Sound::BlockEnchantmentTableUse { inner } => inner, + Sound::BlockEnderChestClose { inner } => inner, + Sound::BlockEnderChestOpen { inner } => inner, + Sound::BlockEndGatewaySpawn { inner } => inner, + Sound::BlockEndPortalFrameFill { inner } => inner, + Sound::BlockEndPortalSpawn { inner } => inner, + Sound::BlockFenceGateClose { inner } => inner, + Sound::BlockFenceGateOpen { inner } => inner, + Sound::BlockFireAmbient { inner } => inner, + Sound::BlockFireExtinguish { inner } => inner, + Sound::BlockFloweringAzaleaBreak { inner } => inner, + Sound::BlockFloweringAzaleaFall { inner } => inner, + Sound::BlockFloweringAzaleaHit { inner } => inner, + Sound::BlockFloweringAzaleaPlace { inner } => inner, + Sound::BlockFloweringAzaleaStep { inner } => inner, + Sound::BlockFroglightBreak { inner } => inner, + Sound::BlockFroglightFall { inner } => inner, + Sound::BlockFroglightHit { inner } => inner, + Sound::BlockFroglightPlace { inner } => inner, + Sound::BlockFroglightStep { inner } => inner, + Sound::BlockFrogspawnBreak { inner } => inner, + Sound::BlockFrogspawnFall { inner } => inner, + Sound::BlockFrogspawnHatch { inner } => inner, + Sound::BlockFrogspawnHit { inner } => inner, + Sound::BlockFrogspawnPlace { inner } => inner, + Sound::BlockFrogspawnStep { inner } => inner, + Sound::BlockFungusBreak { inner } => inner, + Sound::BlockFungusFall { inner } => inner, + Sound::BlockFungusHit { inner } => inner, + Sound::BlockFungusPlace { inner } => inner, + Sound::BlockFungusStep { inner } => inner, + Sound::BlockFurnaceFireCrackle { inner } => inner, + Sound::BlockGildedBlackstoneBreak { inner } => inner, + Sound::BlockGildedBlackstoneFall { inner } => inner, + Sound::BlockGildedBlackstoneHit { inner } => inner, + Sound::BlockGildedBlackstonePlace { inner } => inner, + Sound::BlockGildedBlackstoneStep { inner } => inner, + Sound::BlockGlassBreak { inner } => inner, + Sound::BlockGlassFall { inner } => inner, + Sound::BlockGlassHit { inner } => inner, + Sound::BlockGlassPlace { inner } => inner, + Sound::BlockGlassStep { inner } => inner, + Sound::BlockGrassBreak { inner } => inner, + Sound::BlockGrassFall { inner } => inner, + Sound::BlockGrassHit { inner } => inner, + Sound::BlockGrassPlace { inner } => inner, + Sound::BlockGrassStep { inner } => inner, + Sound::BlockGravelBreak { inner } => inner, + Sound::BlockGravelFall { inner } => inner, + Sound::BlockGravelHit { inner } => inner, + Sound::BlockGravelPlace { inner } => inner, + Sound::BlockGravelStep { inner } => inner, + Sound::BlockGrindstoneUse { inner } => inner, + Sound::BlockGrowingPlantCrop { inner } => inner, + Sound::BlockHangingRootsBreak { inner } => inner, + Sound::BlockHangingRootsFall { inner } => inner, + Sound::BlockHangingRootsHit { inner } => inner, + Sound::BlockHangingRootsPlace { inner } => inner, + Sound::BlockHangingRootsStep { inner } => inner, + Sound::BlockHangingSignBreak { inner } => inner, + Sound::BlockHangingSignFall { inner } => inner, + Sound::BlockHangingSignHit { inner } => inner, + Sound::BlockHangingSignPlace { inner } => inner, + Sound::BlockHangingSignStep { inner } => inner, + Sound::BlockHangingSignWaxedInteractFail { inner } => inner, + Sound::BlockHeavyCoreBreak { inner } => inner, + Sound::BlockHeavyCoreFall { inner } => inner, + Sound::BlockHeavyCoreHit { inner } => inner, + Sound::BlockHeavyCorePlace { inner } => inner, + Sound::BlockHeavyCoreStep { inner } => inner, + Sound::BlockHoneyBlockBreak { inner } => inner, + Sound::BlockHoneyBlockFall { inner } => inner, + Sound::BlockHoneyBlockHit { inner } => inner, + Sound::BlockHoneyBlockPlace { inner } => inner, + Sound::BlockHoneyBlockSlide { inner } => inner, + Sound::BlockHoneyBlockStep { inner } => inner, + Sound::BlockIronDoorClose { inner } => inner, + Sound::BlockIronDoorOpen { inner } => inner, + Sound::BlockIronTrapdoorClose { inner } => inner, + Sound::BlockIronTrapdoorOpen { inner } => inner, + Sound::BlockLadderBreak { inner } => inner, + Sound::BlockLadderFall { inner } => inner, + Sound::BlockLadderHit { inner } => inner, + Sound::BlockLadderPlace { inner } => inner, + Sound::BlockLadderStep { inner } => inner, + Sound::BlockLanternBreak { inner } => inner, + Sound::BlockLanternFall { inner } => inner, + Sound::BlockLanternHit { inner } => inner, + Sound::BlockLanternPlace { inner } => inner, + Sound::BlockLanternStep { inner } => inner, + Sound::BlockLargeAmethystBudBreak { inner } => inner, + Sound::BlockLargeAmethystBudPlace { inner } => inner, + Sound::BlockLavaAmbient { inner } => inner, + Sound::BlockLavaExtinguish { inner } => inner, + Sound::BlockLavaPop { inner } => inner, + Sound::BlockLeverClick { inner } => inner, + Sound::BlockLilyPadPlace { inner } => inner, + Sound::BlockLodestoneBreak { inner } => inner, + Sound::BlockLodestoneFall { inner } => inner, + Sound::BlockLodestoneHit { inner } => inner, + Sound::BlockLodestonePlace { inner } => inner, + Sound::BlockLodestoneStep { inner } => inner, + Sound::BlockMangroveRootsBreak { inner } => inner, + Sound::BlockMangroveRootsFall { inner } => inner, + Sound::BlockMangroveRootsHit { inner } => inner, + Sound::BlockMangroveRootsPlace { inner } => inner, + Sound::BlockMangroveRootsStep { inner } => inner, + Sound::BlockMediumAmethystBudBreak { inner } => inner, + Sound::BlockMediumAmethystBudPlace { inner } => inner, + Sound::BlockMetalBreak { inner } => inner, + Sound::BlockMetalFall { inner } => inner, + Sound::BlockMetalHit { inner } => inner, + Sound::BlockMetalPlace { inner } => inner, + Sound::BlockMetalPressurePlateClickOff { inner } => inner, + Sound::BlockMetalPressurePlateClickOn { inner } => inner, + Sound::BlockMetalStep { inner } => inner, + Sound::BlockMossBreak { inner } => inner, + Sound::BlockMossCarpetBreak { inner } => inner, + Sound::BlockMossCarpetFall { inner } => inner, + Sound::BlockMossCarpetHit { inner } => inner, + Sound::BlockMossCarpetPlace { inner } => inner, + Sound::BlockMossCarpetStep { inner } => inner, + Sound::BlockMossFall { inner } => inner, + Sound::BlockMossHit { inner } => inner, + Sound::BlockMossPlace { inner } => inner, + Sound::BlockMossStep { inner } => inner, + Sound::BlockMuddyMangroveRootsBreak { inner } => inner, + Sound::BlockMuddyMangroveRootsFall { inner } => inner, + Sound::BlockMuddyMangroveRootsHit { inner } => inner, + Sound::BlockMuddyMangroveRootsPlace { inner } => inner, + Sound::BlockMuddyMangroveRootsStep { inner } => inner, + Sound::BlockMudBreak { inner } => inner, + Sound::BlockMudBricksBreak { inner } => inner, + Sound::BlockMudBricksFall { inner } => inner, + Sound::BlockMudBricksHit { inner } => inner, + Sound::BlockMudBricksPlace { inner } => inner, + Sound::BlockMudBricksStep { inner } => inner, + Sound::BlockMudFall { inner } => inner, + Sound::BlockMudHit { inner } => inner, + Sound::BlockMudPlace { inner } => inner, + Sound::BlockMudStep { inner } => inner, + Sound::BlockNetheriteBlockBreak { inner } => inner, + Sound::BlockNetheriteBlockFall { inner } => inner, + Sound::BlockNetheriteBlockHit { inner } => inner, + Sound::BlockNetheriteBlockPlace { inner } => inner, + Sound::BlockNetheriteBlockStep { inner } => inner, + Sound::BlockNetherrackBreak { inner } => inner, + Sound::BlockNetherrackFall { inner } => inner, + Sound::BlockNetherrackHit { inner } => inner, + Sound::BlockNetherrackPlace { inner } => inner, + Sound::BlockNetherrackStep { inner } => inner, + Sound::BlockNetherBricksBreak { inner } => inner, + Sound::BlockNetherBricksFall { inner } => inner, + Sound::BlockNetherBricksHit { inner } => inner, + Sound::BlockNetherBricksPlace { inner } => inner, + Sound::BlockNetherBricksStep { inner } => inner, + Sound::BlockNetherGoldOreBreak { inner } => inner, + Sound::BlockNetherGoldOreFall { inner } => inner, + Sound::BlockNetherGoldOreHit { inner } => inner, + Sound::BlockNetherGoldOrePlace { inner } => inner, + Sound::BlockNetherGoldOreStep { inner } => inner, + Sound::BlockNetherOreBreak { inner } => inner, + Sound::BlockNetherOreFall { inner } => inner, + Sound::BlockNetherOreHit { inner } => inner, + Sound::BlockNetherOrePlace { inner } => inner, + Sound::BlockNetherOreStep { inner } => inner, + Sound::BlockNetherSproutsBreak { inner } => inner, + Sound::BlockNetherSproutsFall { inner } => inner, + Sound::BlockNetherSproutsHit { inner } => inner, + Sound::BlockNetherSproutsPlace { inner } => inner, + Sound::BlockNetherSproutsStep { inner } => inner, + Sound::BlockNetherWartBreak { inner } => inner, + Sound::BlockNetherWoodBreak { inner } => inner, + Sound::BlockNetherWoodButtonClickOff { inner } => inner, + Sound::BlockNetherWoodButtonClickOn { inner } => inner, + Sound::BlockNetherWoodDoorClose { inner } => inner, + Sound::BlockNetherWoodDoorOpen { inner } => inner, + Sound::BlockNetherWoodFall { inner } => inner, + Sound::BlockNetherWoodFenceGateClose { inner } => inner, + Sound::BlockNetherWoodFenceGateOpen { inner } => inner, + Sound::BlockNetherWoodHangingSignBreak { inner } => inner, + Sound::BlockNetherWoodHangingSignFall { inner } => inner, + Sound::BlockNetherWoodHangingSignHit { inner } => inner, + Sound::BlockNetherWoodHangingSignPlace { inner } => inner, + Sound::BlockNetherWoodHangingSignStep { inner } => inner, + Sound::BlockNetherWoodHit { inner } => inner, + Sound::BlockNetherWoodPlace { inner } => inner, + Sound::BlockNetherWoodPressurePlateClickOff { inner } => inner, + Sound::BlockNetherWoodPressurePlateClickOn { inner } => inner, + Sound::BlockNetherWoodStep { inner } => inner, + Sound::BlockNetherWoodTrapdoorClose { inner } => inner, + Sound::BlockNetherWoodTrapdoorOpen { inner } => inner, + Sound::BlockNoteBlockBanjo { inner } => inner, + Sound::BlockNoteBlockBasedrum { inner } => inner, + Sound::BlockNoteBlockBass { inner } => inner, + Sound::BlockNoteBlockBell { inner } => inner, + Sound::BlockNoteBlockBit { inner } => inner, + Sound::BlockNoteBlockChime { inner } => inner, + Sound::BlockNoteBlockCowBell { inner } => inner, + Sound::BlockNoteBlockDidgeridoo { inner } => inner, + Sound::BlockNoteBlockFlute { inner } => inner, + Sound::BlockNoteBlockGuitar { inner } => inner, + Sound::BlockNoteBlockHarp { inner } => inner, + Sound::BlockNoteBlockHat { inner } => inner, + Sound::BlockNoteBlockImitateCreeper { inner } => inner, + Sound::BlockNoteBlockImitateEnderDragon { inner } => inner, + Sound::BlockNoteBlockImitatePiglin { inner } => inner, + Sound::BlockNoteBlockImitateSkeleton { inner } => inner, + Sound::BlockNoteBlockImitateWitherSkeleton { inner } => inner, + Sound::BlockNoteBlockImitateZombie { inner } => inner, + Sound::BlockNoteBlockIronXylophone { inner } => inner, + Sound::BlockNoteBlockPling { inner } => inner, + Sound::BlockNoteBlockSnare { inner } => inner, + Sound::BlockNoteBlockXylophone { inner } => inner, + Sound::BlockNyliumBreak { inner } => inner, + Sound::BlockNyliumFall { inner } => inner, + Sound::BlockNyliumHit { inner } => inner, + Sound::BlockNyliumPlace { inner } => inner, + Sound::BlockNyliumStep { inner } => inner, + Sound::BlockPackedMudBreak { inner } => inner, + Sound::BlockPackedMudFall { inner } => inner, + Sound::BlockPackedMudHit { inner } => inner, + Sound::BlockPackedMudPlace { inner } => inner, + Sound::BlockPackedMudStep { inner } => inner, + Sound::BlockPinkPetalsBreak { inner } => inner, + Sound::BlockPinkPetalsFall { inner } => inner, + Sound::BlockPinkPetalsHit { inner } => inner, + Sound::BlockPinkPetalsPlace { inner } => inner, + Sound::BlockPinkPetalsStep { inner } => inner, + Sound::BlockPistonContract { inner } => inner, + Sound::BlockPistonExtend { inner } => inner, + Sound::BlockPointedDripstoneBreak { inner } => inner, + Sound::BlockPointedDripstoneDripLava { inner } => inner, + Sound::BlockPointedDripstoneDripLavaIntoCauldron { inner } => inner, + Sound::BlockPointedDripstoneDripWater { inner } => inner, + Sound::BlockPointedDripstoneDripWaterIntoCauldron { inner } => inner, + Sound::BlockPointedDripstoneFall { inner } => inner, + Sound::BlockPointedDripstoneHit { inner } => inner, + Sound::BlockPointedDripstoneLand { inner } => inner, + Sound::BlockPointedDripstonePlace { inner } => inner, + Sound::BlockPointedDripstoneStep { inner } => inner, + Sound::BlockPolishedDeepslateBreak { inner } => inner, + Sound::BlockPolishedDeepslateFall { inner } => inner, + Sound::BlockPolishedDeepslateHit { inner } => inner, + Sound::BlockPolishedDeepslatePlace { inner } => inner, + Sound::BlockPolishedDeepslateStep { inner } => inner, + Sound::BlockPolishedTuffBreak { inner } => inner, + Sound::BlockPolishedTuffFall { inner } => inner, + Sound::BlockPolishedTuffHit { inner } => inner, + Sound::BlockPolishedTuffPlace { inner } => inner, + Sound::BlockPolishedTuffStep { inner } => inner, + Sound::BlockPortalAmbient { inner } => inner, + Sound::BlockPortalTravel { inner } => inner, + Sound::BlockPortalTrigger { inner } => inner, + Sound::BlockPowderSnowBreak { inner } => inner, + Sound::BlockPowderSnowFall { inner } => inner, + Sound::BlockPowderSnowHit { inner } => inner, + Sound::BlockPowderSnowPlace { inner } => inner, + Sound::BlockPowderSnowStep { inner } => inner, + Sound::BlockPumpkinCarve { inner } => inner, + Sound::BlockRedstoneTorchBurnout { inner } => inner, + Sound::BlockRespawnAnchorAmbient { inner } => inner, + Sound::BlockRespawnAnchorCharge { inner } => inner, + Sound::BlockRespawnAnchorDeplete { inner } => inner, + Sound::BlockRespawnAnchorSetSpawn { inner } => inner, + Sound::BlockRootedDirtBreak { inner } => inner, + Sound::BlockRootedDirtFall { inner } => inner, + Sound::BlockRootedDirtHit { inner } => inner, + Sound::BlockRootedDirtPlace { inner } => inner, + Sound::BlockRootedDirtStep { inner } => inner, + Sound::BlockRootsBreak { inner } => inner, + Sound::BlockRootsFall { inner } => inner, + Sound::BlockRootsHit { inner } => inner, + Sound::BlockRootsPlace { inner } => inner, + Sound::BlockRootsStep { inner } => inner, + Sound::BlockSandBreak { inner } => inner, + Sound::BlockSandFall { inner } => inner, + Sound::BlockSandHit { inner } => inner, + Sound::BlockSandPlace { inner } => inner, + Sound::BlockSandStep { inner } => inner, + Sound::BlockScaffoldingBreak { inner } => inner, + Sound::BlockScaffoldingFall { inner } => inner, + Sound::BlockScaffoldingHit { inner } => inner, + Sound::BlockScaffoldingPlace { inner } => inner, + Sound::BlockScaffoldingStep { inner } => inner, + Sound::BlockSculkBreak { inner } => inner, + Sound::BlockSculkCatalystBloom { inner } => inner, + Sound::BlockSculkCatalystBreak { inner } => inner, + Sound::BlockSculkCatalystFall { inner } => inner, + Sound::BlockSculkCatalystHit { inner } => inner, + Sound::BlockSculkCatalystPlace { inner } => inner, + Sound::BlockSculkCatalystStep { inner } => inner, + Sound::BlockSculkCharge { inner } => inner, + Sound::BlockSculkFall { inner } => inner, + Sound::BlockSculkHit { inner } => inner, + Sound::BlockSculkPlace { inner } => inner, + Sound::BlockSculkSensorBreak { inner } => inner, + Sound::BlockSculkSensorClicking { inner } => inner, + Sound::BlockSculkSensorClickingStop { inner } => inner, + Sound::BlockSculkSensorFall { inner } => inner, + Sound::BlockSculkSensorHit { inner } => inner, + Sound::BlockSculkSensorPlace { inner } => inner, + Sound::BlockSculkSensorStep { inner } => inner, + Sound::BlockSculkShriekerBreak { inner } => inner, + Sound::BlockSculkShriekerFall { inner } => inner, + Sound::BlockSculkShriekerHit { inner } => inner, + Sound::BlockSculkShriekerPlace { inner } => inner, + Sound::BlockSculkShriekerShriek { inner } => inner, + Sound::BlockSculkShriekerStep { inner } => inner, + Sound::BlockSculkSpread { inner } => inner, + Sound::BlockSculkStep { inner } => inner, + Sound::BlockSculkVeinBreak { inner } => inner, + Sound::BlockSculkVeinFall { inner } => inner, + Sound::BlockSculkVeinHit { inner } => inner, + Sound::BlockSculkVeinPlace { inner } => inner, + Sound::BlockSculkVeinStep { inner } => inner, + Sound::BlockShroomlightBreak { inner } => inner, + Sound::BlockShroomlightFall { inner } => inner, + Sound::BlockShroomlightHit { inner } => inner, + Sound::BlockShroomlightPlace { inner } => inner, + Sound::BlockShroomlightStep { inner } => inner, + Sound::BlockShulkerBoxClose { inner } => inner, + Sound::BlockShulkerBoxOpen { inner } => inner, + Sound::BlockSignWaxedInteractFail { inner } => inner, + Sound::BlockSlimeBlockBreak { inner } => inner, + Sound::BlockSlimeBlockFall { inner } => inner, + Sound::BlockSlimeBlockHit { inner } => inner, + Sound::BlockSlimeBlockPlace { inner } => inner, + Sound::BlockSlimeBlockStep { inner } => inner, + Sound::BlockSmallAmethystBudBreak { inner } => inner, + Sound::BlockSmallAmethystBudPlace { inner } => inner, + Sound::BlockSmallDripleafBreak { inner } => inner, + Sound::BlockSmallDripleafFall { inner } => inner, + Sound::BlockSmallDripleafHit { inner } => inner, + Sound::BlockSmallDripleafPlace { inner } => inner, + Sound::BlockSmallDripleafStep { inner } => inner, + Sound::BlockSmithingTableUse { inner } => inner, + Sound::BlockSmokerSmoke { inner } => inner, + Sound::BlockSnifferEggCrack { inner } => inner, + Sound::BlockSnifferEggHatch { inner } => inner, + Sound::BlockSnifferEggPlop { inner } => inner, + Sound::BlockSnowBreak { inner } => inner, + Sound::BlockSnowFall { inner } => inner, + Sound::BlockSnowHit { inner } => inner, + Sound::BlockSnowPlace { inner } => inner, + Sound::BlockSnowStep { inner } => inner, + Sound::BlockSoulSandBreak { inner } => inner, + Sound::BlockSoulSandFall { inner } => inner, + Sound::BlockSoulSandHit { inner } => inner, + Sound::BlockSoulSandPlace { inner } => inner, + Sound::BlockSoulSandStep { inner } => inner, + Sound::BlockSoulSoilBreak { inner } => inner, + Sound::BlockSoulSoilFall { inner } => inner, + Sound::BlockSoulSoilHit { inner } => inner, + Sound::BlockSoulSoilPlace { inner } => inner, + Sound::BlockSoulSoilStep { inner } => inner, + Sound::BlockSpongeAbsorb { inner } => inner, + Sound::BlockSpongeBreak { inner } => inner, + Sound::BlockSpongeFall { inner } => inner, + Sound::BlockSpongeHit { inner } => inner, + Sound::BlockSpongePlace { inner } => inner, + Sound::BlockSpongeStep { inner } => inner, + Sound::BlockSporeBlossomBreak { inner } => inner, + Sound::BlockSporeBlossomFall { inner } => inner, + Sound::BlockSporeBlossomHit { inner } => inner, + Sound::BlockSporeBlossomPlace { inner } => inner, + Sound::BlockSporeBlossomStep { inner } => inner, + Sound::BlockStemBreak { inner } => inner, + Sound::BlockStemFall { inner } => inner, + Sound::BlockStemHit { inner } => inner, + Sound::BlockStemPlace { inner } => inner, + Sound::BlockStemStep { inner } => inner, + Sound::BlockStoneBreak { inner } => inner, + Sound::BlockStoneButtonClickOff { inner } => inner, + Sound::BlockStoneButtonClickOn { inner } => inner, + Sound::BlockStoneFall { inner } => inner, + Sound::BlockStoneHit { inner } => inner, + Sound::BlockStonePlace { inner } => inner, + Sound::BlockStonePressurePlateClickOff { inner } => inner, + Sound::BlockStonePressurePlateClickOn { inner } => inner, + Sound::BlockStoneStep { inner } => inner, + Sound::BlockSuspiciousGravelBreak { inner } => inner, + Sound::BlockSuspiciousGravelFall { inner } => inner, + Sound::BlockSuspiciousGravelHit { inner } => inner, + Sound::BlockSuspiciousGravelPlace { inner } => inner, + Sound::BlockSuspiciousGravelStep { inner } => inner, + Sound::BlockSuspiciousSandBreak { inner } => inner, + Sound::BlockSuspiciousSandFall { inner } => inner, + Sound::BlockSuspiciousSandHit { inner } => inner, + Sound::BlockSuspiciousSandPlace { inner } => inner, + Sound::BlockSuspiciousSandStep { inner } => inner, + Sound::BlockSweetBerryBushBreak { inner } => inner, + Sound::BlockSweetBerryBushPickBerries { inner } => inner, + Sound::BlockSweetBerryBushPlace { inner } => inner, + Sound::BlockTrialSpawnerAboutToSpawnItem { inner } => inner, + Sound::BlockTrialSpawnerAmbient { inner } => inner, + Sound::BlockTrialSpawnerAmbientOminous { inner } => inner, + Sound::BlockTrialSpawnerBreak { inner } => inner, + Sound::BlockTrialSpawnerCloseShutter { inner } => inner, + Sound::BlockTrialSpawnerDetectPlayer { inner } => inner, + Sound::BlockTrialSpawnerEjectItem { inner } => inner, + Sound::BlockTrialSpawnerFall { inner } => inner, + Sound::BlockTrialSpawnerHit { inner } => inner, + Sound::BlockTrialSpawnerOminousActivate { inner } => inner, + Sound::BlockTrialSpawnerOpenShutter { inner } => inner, + Sound::BlockTrialSpawnerPlace { inner } => inner, + Sound::BlockTrialSpawnerSpawnItem { inner } => inner, + Sound::BlockTrialSpawnerSpawnItemBegin { inner } => inner, + Sound::BlockTrialSpawnerSpawnMob { inner } => inner, + Sound::BlockTrialSpawnerStep { inner } => inner, + Sound::BlockTripwireAttach { inner } => inner, + Sound::BlockTripwireClickOff { inner } => inner, + Sound::BlockTripwireClickOn { inner } => inner, + Sound::BlockTripwireDetach { inner } => inner, + Sound::BlockTuffBreak { inner } => inner, + Sound::BlockTuffBricksBreak { inner } => inner, + Sound::BlockTuffBricksFall { inner } => inner, + Sound::BlockTuffBricksHit { inner } => inner, + Sound::BlockTuffBricksPlace { inner } => inner, + Sound::BlockTuffBricksStep { inner } => inner, + Sound::BlockTuffFall { inner } => inner, + Sound::BlockTuffHit { inner } => inner, + Sound::BlockTuffPlace { inner } => inner, + Sound::BlockTuffStep { inner } => inner, + Sound::BlockVaultActivate { inner } => inner, + Sound::BlockVaultAmbient { inner } => inner, + Sound::BlockVaultBreak { inner } => inner, + Sound::BlockVaultCloseShutter { inner } => inner, + Sound::BlockVaultDeactivate { inner } => inner, + Sound::BlockVaultEjectItem { inner } => inner, + Sound::BlockVaultFall { inner } => inner, + Sound::BlockVaultHit { inner } => inner, + Sound::BlockVaultInsertItem { inner } => inner, + Sound::BlockVaultInsertItemFail { inner } => inner, + Sound::BlockVaultOpenShutter { inner } => inner, + Sound::BlockVaultPlace { inner } => inner, + Sound::BlockVaultRejectRewardedPlayer { inner } => inner, + Sound::BlockVaultStep { inner } => inner, + Sound::BlockVineBreak { inner } => inner, + Sound::BlockVineFall { inner } => inner, + Sound::BlockVineHit { inner } => inner, + Sound::BlockVinePlace { inner } => inner, + Sound::BlockVineStep { inner } => inner, + Sound::BlockWartBlockBreak { inner } => inner, + Sound::BlockWartBlockFall { inner } => inner, + Sound::BlockWartBlockHit { inner } => inner, + Sound::BlockWartBlockPlace { inner } => inner, + Sound::BlockWartBlockStep { inner } => inner, + Sound::BlockWaterAmbient { inner } => inner, + Sound::BlockWeepingVinesBreak { inner } => inner, + Sound::BlockWeepingVinesFall { inner } => inner, + Sound::BlockWeepingVinesHit { inner } => inner, + Sound::BlockWeepingVinesPlace { inner } => inner, + Sound::BlockWeepingVinesStep { inner } => inner, + Sound::BlockWetGrassBreak { inner } => inner, + Sound::BlockWetGrassFall { inner } => inner, + Sound::BlockWetGrassHit { inner } => inner, + Sound::BlockWetGrassPlace { inner } => inner, + Sound::BlockWetGrassStep { inner } => inner, + Sound::BlockWetSpongeBreak { inner } => inner, + Sound::BlockWetSpongeDries { inner } => inner, + Sound::BlockWetSpongeFall { inner } => inner, + Sound::BlockWetSpongeHit { inner } => inner, + Sound::BlockWetSpongePlace { inner } => inner, + Sound::BlockWetSpongeStep { inner } => inner, + Sound::BlockWoodenButtonClickOff { inner } => inner, + Sound::BlockWoodenButtonClickOn { inner } => inner, + Sound::BlockWoodenDoorClose { inner } => inner, + Sound::BlockWoodenDoorOpen { inner } => inner, + Sound::BlockWoodenPressurePlateClickOff { inner } => inner, + Sound::BlockWoodenPressurePlateClickOn { inner } => inner, + Sound::BlockWoodenTrapdoorClose { inner } => inner, + Sound::BlockWoodenTrapdoorOpen { inner } => inner, + Sound::BlockWoodBreak { inner } => inner, + Sound::BlockWoodFall { inner } => inner, + Sound::BlockWoodHit { inner } => inner, + Sound::BlockWoodPlace { inner } => inner, + Sound::BlockWoodStep { inner } => inner, + Sound::BlockWoolBreak { inner } => inner, + Sound::BlockWoolFall { inner } => inner, + Sound::BlockWoolHit { inner } => inner, + Sound::BlockWoolPlace { inner } => inner, + Sound::BlockWoolStep { inner } => inner, + Sound::EnchantThornsHit { inner } => inner, + Sound::EntityAllayAmbientWithoutItem { inner } => inner, + Sound::EntityAllayAmbientWithItem { inner } => inner, + Sound::EntityAllayDeath { inner } => inner, + Sound::EntityAllayHurt { inner } => inner, + Sound::EntityAllayItemGiven { inner } => inner, + Sound::EntityAllayItemTaken { inner } => inner, + Sound::EntityAllayItemThrown { inner } => inner, + Sound::EntityArmadilloAmbient { inner } => inner, + Sound::EntityArmadilloBrush { inner } => inner, + Sound::EntityArmadilloDeath { inner } => inner, + Sound::EntityArmadilloEat { inner } => inner, + Sound::EntityArmadilloHurt { inner } => inner, + Sound::EntityArmadilloHurtReduced { inner } => inner, + Sound::EntityArmadilloLand { inner } => inner, + Sound::EntityArmadilloPeek { inner } => inner, + Sound::EntityArmadilloRoll { inner } => inner, + Sound::EntityArmadilloScuteDrop { inner } => inner, + Sound::EntityArmadilloStep { inner } => inner, + Sound::EntityArmadilloUnrollFinish { inner } => inner, + Sound::EntityArmadilloUnrollStart { inner } => inner, + Sound::EntityArmorStandBreak { inner } => inner, + Sound::EntityArmorStandFall { inner } => inner, + Sound::EntityArmorStandHit { inner } => inner, + Sound::EntityArmorStandPlace { inner } => inner, + Sound::EntityArrowHit { inner } => inner, + Sound::EntityArrowHitPlayer { inner } => inner, + Sound::EntityArrowShoot { inner } => inner, + Sound::EntityAxolotlAttack { inner } => inner, + Sound::EntityAxolotlDeath { inner } => inner, + Sound::EntityAxolotlHurt { inner } => inner, + Sound::EntityAxolotlIdleAir { inner } => inner, + Sound::EntityAxolotlIdleWater { inner } => inner, + Sound::EntityAxolotlSplash { inner } => inner, + Sound::EntityAxolotlSwim { inner } => inner, + Sound::EntityBatAmbient { inner } => inner, + Sound::EntityBatDeath { inner } => inner, + Sound::EntityBatHurt { inner } => inner, + Sound::EntityBatLoop { inner } => inner, + Sound::EntityBatTakeoff { inner } => inner, + Sound::EntityBeeDeath { inner } => inner, + Sound::EntityBeeHurt { inner } => inner, + Sound::EntityBeeLoop { inner } => inner, + Sound::EntityBeeLoopAggressive { inner } => inner, + Sound::EntityBeePollinate { inner } => inner, + Sound::EntityBeeSting { inner } => inner, + Sound::EntityBlazeAmbient { inner } => inner, + Sound::EntityBlazeBurn { inner } => inner, + Sound::EntityBlazeDeath { inner } => inner, + Sound::EntityBlazeHurt { inner } => inner, + Sound::EntityBlazeShoot { inner } => inner, + Sound::EntityBoatPaddleLand { inner } => inner, + Sound::EntityBoatPaddleWater { inner } => inner, + Sound::EntityBoggedAmbient { inner } => inner, + Sound::EntityBoggedDeath { inner } => inner, + Sound::EntityBoggedHurt { inner } => inner, + Sound::EntityBoggedShear { inner } => inner, + Sound::EntityBoggedStep { inner } => inner, + Sound::EntityBreezeCharge { inner } => inner, + Sound::EntityBreezeDeath { inner } => inner, + Sound::EntityBreezeDeflect { inner } => inner, + Sound::EntityBreezeHurt { inner } => inner, + Sound::EntityBreezeIdleAir { inner } => inner, + Sound::EntityBreezeIdleGround { inner } => inner, + Sound::EntityBreezeInhale { inner } => inner, + Sound::EntityBreezeJump { inner } => inner, + Sound::EntityBreezeLand { inner } => inner, + Sound::EntityBreezeShoot { inner } => inner, + Sound::EntityBreezeSlide { inner } => inner, + Sound::EntityBreezeWhirl { inner } => inner, + Sound::EntityBreezeWindBurst { inner } => inner, + Sound::EntityCamelAmbient { inner } => inner, + Sound::EntityCamelDash { inner } => inner, + Sound::EntityCamelDashReady { inner } => inner, + Sound::EntityCamelDeath { inner } => inner, + Sound::EntityCamelEat { inner } => inner, + Sound::EntityCamelHurt { inner } => inner, + Sound::EntityCamelSaddle { inner } => inner, + Sound::EntityCamelSit { inner } => inner, + Sound::EntityCamelStand { inner } => inner, + Sound::EntityCamelStep { inner } => inner, + Sound::EntityCamelStepSand { inner } => inner, + Sound::EntityCatAmbient { inner } => inner, + Sound::EntityCatBegForFood { inner } => inner, + Sound::EntityCatDeath { inner } => inner, + Sound::EntityCatEat { inner } => inner, + Sound::EntityCatHiss { inner } => inner, + Sound::EntityCatHurt { inner } => inner, + Sound::EntityCatPurr { inner } => inner, + Sound::EntityCatPurreow { inner } => inner, + Sound::EntityCatStrayAmbient { inner } => inner, + Sound::EntityChickenAmbient { inner } => inner, + Sound::EntityChickenDeath { inner } => inner, + Sound::EntityChickenEgg { inner } => inner, + Sound::EntityChickenHurt { inner } => inner, + Sound::EntityChickenStep { inner } => inner, + Sound::EntityCodAmbient { inner } => inner, + Sound::EntityCodDeath { inner } => inner, + Sound::EntityCodFlop { inner } => inner, + Sound::EntityCodHurt { inner } => inner, + Sound::EntityCowAmbient { inner } => inner, + Sound::EntityCowDeath { inner } => inner, + Sound::EntityCowHurt { inner } => inner, + Sound::EntityCowMilk { inner } => inner, + Sound::EntityCowStep { inner } => inner, + Sound::EntityCreeperDeath { inner } => inner, + Sound::EntityCreeperHurt { inner } => inner, + Sound::EntityCreeperPrimed { inner } => inner, + Sound::EntityDolphinAmbient { inner } => inner, + Sound::EntityDolphinAmbientWater { inner } => inner, + Sound::EntityDolphinAttack { inner } => inner, + Sound::EntityDolphinDeath { inner } => inner, + Sound::EntityDolphinEat { inner } => inner, + Sound::EntityDolphinHurt { inner } => inner, + Sound::EntityDolphinJump { inner } => inner, + Sound::EntityDolphinPlay { inner } => inner, + Sound::EntityDolphinSplash { inner } => inner, + Sound::EntityDolphinSwim { inner } => inner, + Sound::EntityDonkeyAmbient { inner } => inner, + Sound::EntityDonkeyAngry { inner } => inner, + Sound::EntityDonkeyChest { inner } => inner, + Sound::EntityDonkeyDeath { inner } => inner, + Sound::EntityDonkeyEat { inner } => inner, + Sound::EntityDonkeyHurt { inner } => inner, + Sound::EntityDonkeyJump { inner } => inner, + Sound::EntityDragonFireballExplode { inner } => inner, + Sound::EntityDrownedAmbient { inner } => inner, + Sound::EntityDrownedAmbientWater { inner } => inner, + Sound::EntityDrownedDeath { inner } => inner, + Sound::EntityDrownedDeathWater { inner } => inner, + Sound::EntityDrownedHurt { inner } => inner, + Sound::EntityDrownedHurtWater { inner } => inner, + Sound::EntityDrownedShoot { inner } => inner, + Sound::EntityDrownedStep { inner } => inner, + Sound::EntityDrownedSwim { inner } => inner, + Sound::EntityEggThrow { inner } => inner, + Sound::EntityElderGuardianAmbient { inner } => inner, + Sound::EntityElderGuardianAmbientLand { inner } => inner, + Sound::EntityElderGuardianCurse { inner } => inner, + Sound::EntityElderGuardianDeath { inner } => inner, + Sound::EntityElderGuardianDeathLand { inner } => inner, + Sound::EntityElderGuardianFlop { inner } => inner, + Sound::EntityElderGuardianHurt { inner } => inner, + Sound::EntityElderGuardianHurtLand { inner } => inner, + Sound::EntityEndermanAmbient { inner } => inner, + Sound::EntityEndermanDeath { inner } => inner, + Sound::EntityEndermanHurt { inner } => inner, + Sound::EntityEndermanScream { inner } => inner, + Sound::EntityEndermanStare { inner } => inner, + Sound::EntityEndermanTeleport { inner } => inner, + Sound::EntityEndermiteAmbient { inner } => inner, + Sound::EntityEndermiteDeath { inner } => inner, + Sound::EntityEndermiteHurt { inner } => inner, + Sound::EntityEndermiteStep { inner } => inner, + Sound::EntityEnderDragonAmbient { inner } => inner, + Sound::EntityEnderDragonDeath { inner } => inner, + Sound::EntityEnderDragonFlap { inner } => inner, + Sound::EntityEnderDragonGrowl { inner } => inner, + Sound::EntityEnderDragonHurt { inner } => inner, + Sound::EntityEnderDragonShoot { inner } => inner, + Sound::EntityEnderEyeDeath { inner } => inner, + Sound::EntityEnderEyeLaunch { inner } => inner, + Sound::EntityEnderPearlThrow { inner } => inner, + Sound::EntityEvokerAmbient { inner } => inner, + Sound::EntityEvokerCastSpell { inner } => inner, + Sound::EntityEvokerCelebrate { inner } => inner, + Sound::EntityEvokerDeath { inner } => inner, + Sound::EntityEvokerFangsAttack { inner } => inner, + Sound::EntityEvokerHurt { inner } => inner, + Sound::EntityEvokerPrepareAttack { inner } => inner, + Sound::EntityEvokerPrepareSummon { inner } => inner, + Sound::EntityEvokerPrepareWololo { inner } => inner, + Sound::EntityExperienceBottleThrow { inner } => inner, + Sound::EntityExperienceOrbPickup { inner } => inner, + Sound::EntityFireworkRocketBlast { inner } => inner, + Sound::EntityFireworkRocketBlastFar { inner } => inner, + Sound::EntityFireworkRocketLargeBlast { inner } => inner, + Sound::EntityFireworkRocketLargeBlastFar { inner } => inner, + Sound::EntityFireworkRocketLaunch { inner } => inner, + Sound::EntityFireworkRocketShoot { inner } => inner, + Sound::EntityFireworkRocketTwinkle { inner } => inner, + Sound::EntityFireworkRocketTwinkleFar { inner } => inner, + Sound::EntityFishingBobberRetrieve { inner } => inner, + Sound::EntityFishingBobberSplash { inner } => inner, + Sound::EntityFishingBobberThrow { inner } => inner, + Sound::EntityFishSwim { inner } => inner, + Sound::EntityFoxAggro { inner } => inner, + Sound::EntityFoxAmbient { inner } => inner, + Sound::EntityFoxBite { inner } => inner, + Sound::EntityFoxDeath { inner } => inner, + Sound::EntityFoxEat { inner } => inner, + Sound::EntityFoxHurt { inner } => inner, + Sound::EntityFoxScreech { inner } => inner, + Sound::EntityFoxSleep { inner } => inner, + Sound::EntityFoxSniff { inner } => inner, + Sound::EntityFoxSpit { inner } => inner, + Sound::EntityFoxTeleport { inner } => inner, + Sound::EntityFrogAmbient { inner } => inner, + Sound::EntityFrogDeath { inner } => inner, + Sound::EntityFrogEat { inner } => inner, + Sound::EntityFrogHurt { inner } => inner, + Sound::EntityFrogLaySpawn { inner } => inner, + Sound::EntityFrogLongJump { inner } => inner, + Sound::EntityFrogStep { inner } => inner, + Sound::EntityFrogTongue { inner } => inner, + Sound::EntityGenericBigFall { inner } => inner, + Sound::EntityGenericBurn { inner } => inner, + Sound::EntityGenericDeath { inner } => inner, + Sound::EntityGenericDrink { inner } => inner, + Sound::EntityGenericEat { inner } => inner, + Sound::EntityGenericExplode { inner } => inner, + Sound::EntityGenericExtinguishFire { inner } => inner, + Sound::EntityGenericHurt { inner } => inner, + Sound::EntityGenericSmallFall { inner } => inner, + Sound::EntityGenericSplash { inner } => inner, + Sound::EntityGenericSwim { inner } => inner, + Sound::EntityGhastAmbient { inner } => inner, + Sound::EntityGhastDeath { inner } => inner, + Sound::EntityGhastHurt { inner } => inner, + Sound::EntityGhastScream { inner } => inner, + Sound::EntityGhastShoot { inner } => inner, + Sound::EntityGhastWarn { inner } => inner, + Sound::EntityGlowItemFrameAddItem { inner } => inner, + Sound::EntityGlowItemFrameBreak { inner } => inner, + Sound::EntityGlowItemFramePlace { inner } => inner, + Sound::EntityGlowItemFrameRemoveItem { inner } => inner, + Sound::EntityGlowItemFrameRotateItem { inner } => inner, + Sound::EntityGlowSquidAmbient { inner } => inner, + Sound::EntityGlowSquidDeath { inner } => inner, + Sound::EntityGlowSquidHurt { inner } => inner, + Sound::EntityGlowSquidSquirt { inner } => inner, + Sound::EntityGoatAmbient { inner } => inner, + Sound::EntityGoatDeath { inner } => inner, + Sound::EntityGoatEat { inner } => inner, + Sound::EntityGoatHornBreak { inner } => inner, + Sound::EntityGoatHurt { inner } => inner, + Sound::EntityGoatLongJump { inner } => inner, + Sound::EntityGoatMilk { inner } => inner, + Sound::EntityGoatPrepareRam { inner } => inner, + Sound::EntityGoatRamImpact { inner } => inner, + Sound::EntityGoatScreamingAmbient { inner } => inner, + Sound::EntityGoatScreamingDeath { inner } => inner, + Sound::EntityGoatScreamingEat { inner } => inner, + Sound::EntityGoatScreamingHornBreak { inner } => inner, + Sound::EntityGoatScreamingHurt { inner } => inner, + Sound::EntityGoatScreamingLongJump { inner } => inner, + Sound::EntityGoatScreamingMilk { inner } => inner, + Sound::EntityGoatScreamingPrepareRam { inner } => inner, + Sound::EntityGoatScreamingRamImpact { inner } => inner, + Sound::EntityGoatStep { inner } => inner, + Sound::EntityGuardianAmbient { inner } => inner, + Sound::EntityGuardianAmbientLand { inner } => inner, + Sound::EntityGuardianAttack { inner } => inner, + Sound::EntityGuardianDeath { inner } => inner, + Sound::EntityGuardianDeathLand { inner } => inner, + Sound::EntityGuardianFlop { inner } => inner, + Sound::EntityGuardianHurt { inner } => inner, + Sound::EntityGuardianHurtLand { inner } => inner, + Sound::EntityHoglinAmbient { inner } => inner, + Sound::EntityHoglinAngry { inner } => inner, + Sound::EntityHoglinAttack { inner } => inner, + Sound::EntityHoglinConvertedToZombified { inner } => inner, + Sound::EntityHoglinDeath { inner } => inner, + Sound::EntityHoglinHurt { inner } => inner, + Sound::EntityHoglinRetreat { inner } => inner, + Sound::EntityHoglinStep { inner } => inner, + Sound::EntityHorseAmbient { inner } => inner, + Sound::EntityHorseAngry { inner } => inner, + Sound::EntityHorseArmor { inner } => inner, + Sound::EntityHorseBreathe { inner } => inner, + Sound::EntityHorseDeath { inner } => inner, + Sound::EntityHorseEat { inner } => inner, + Sound::EntityHorseGallop { inner } => inner, + Sound::EntityHorseHurt { inner } => inner, + Sound::EntityHorseJump { inner } => inner, + Sound::EntityHorseLand { inner } => inner, + Sound::EntityHorseSaddle { inner } => inner, + Sound::EntityHorseStep { inner } => inner, + Sound::EntityHorseStepWood { inner } => inner, + Sound::EntityHostileBigFall { inner } => inner, + Sound::EntityHostileDeath { inner } => inner, + Sound::EntityHostileHurt { inner } => inner, + Sound::EntityHostileSmallFall { inner } => inner, + Sound::EntityHostileSplash { inner } => inner, + Sound::EntityHostileSwim { inner } => inner, + Sound::EntityHuskAmbient { inner } => inner, + Sound::EntityHuskConvertedToZombie { inner } => inner, + Sound::EntityHuskDeath { inner } => inner, + Sound::EntityHuskHurt { inner } => inner, + Sound::EntityHuskStep { inner } => inner, + Sound::EntityIllusionerAmbient { inner } => inner, + Sound::EntityIllusionerCastSpell { inner } => inner, + Sound::EntityIllusionerDeath { inner } => inner, + Sound::EntityIllusionerHurt { inner } => inner, + Sound::EntityIllusionerMirrorMove { inner } => inner, + Sound::EntityIllusionerPrepareBlindness { inner } => inner, + Sound::EntityIllusionerPrepareMirror { inner } => inner, + Sound::EntityIronGolemAttack { inner } => inner, + Sound::EntityIronGolemDamage { inner } => inner, + Sound::EntityIronGolemDeath { inner } => inner, + Sound::EntityIronGolemHurt { inner } => inner, + Sound::EntityIronGolemRepair { inner } => inner, + Sound::EntityIronGolemStep { inner } => inner, + Sound::EntityItemBreak { inner } => inner, + Sound::EntityItemFrameAddItem { inner } => inner, + Sound::EntityItemFrameBreak { inner } => inner, + Sound::EntityItemFramePlace { inner } => inner, + Sound::EntityItemFrameRemoveItem { inner } => inner, + Sound::EntityItemFrameRotateItem { inner } => inner, + Sound::EntityItemPickup { inner } => inner, + Sound::EntityLeashKnotBreak { inner } => inner, + Sound::EntityLeashKnotPlace { inner } => inner, + Sound::EntityLightningBoltImpact { inner } => inner, + Sound::EntityLightningBoltThunder { inner } => inner, + Sound::EntityLingeringPotionThrow { inner } => inner, + Sound::EntityLlamaAmbient { inner } => inner, + Sound::EntityLlamaAngry { inner } => inner, + Sound::EntityLlamaChest { inner } => inner, + Sound::EntityLlamaDeath { inner } => inner, + Sound::EntityLlamaEat { inner } => inner, + Sound::EntityLlamaHurt { inner } => inner, + Sound::EntityLlamaSpit { inner } => inner, + Sound::EntityLlamaStep { inner } => inner, + Sound::EntityLlamaSwag { inner } => inner, + Sound::EntityMagmaCubeDeath { inner } => inner, + Sound::EntityMagmaCubeDeathSmall { inner } => inner, + Sound::EntityMagmaCubeHurt { inner } => inner, + Sound::EntityMagmaCubeHurtSmall { inner } => inner, + Sound::EntityMagmaCubeJump { inner } => inner, + Sound::EntityMagmaCubeSquish { inner } => inner, + Sound::EntityMagmaCubeSquishSmall { inner } => inner, + Sound::EntityMinecartInside { inner } => inner, + Sound::EntityMinecartInsideUnderwater { inner } => inner, + Sound::EntityMinecartRiding { inner } => inner, + Sound::EntityMooshroomConvert { inner } => inner, + Sound::EntityMooshroomEat { inner } => inner, + Sound::EntityMooshroomMilk { inner } => inner, + Sound::EntityMooshroomShear { inner } => inner, + Sound::EntityMooshroomSuspiciousMilk { inner } => inner, + Sound::EntityMuleAmbient { inner } => inner, + Sound::EntityMuleAngry { inner } => inner, + Sound::EntityMuleChest { inner } => inner, + Sound::EntityMuleDeath { inner } => inner, + Sound::EntityMuleEat { inner } => inner, + Sound::EntityMuleHurt { inner } => inner, + Sound::EntityMuleJump { inner } => inner, + Sound::EntityOcelotAmbient { inner } => inner, + Sound::EntityOcelotDeath { inner } => inner, + Sound::EntityOcelotHurt { inner } => inner, + Sound::EntityPaintingBreak { inner } => inner, + Sound::EntityPaintingPlace { inner } => inner, + Sound::EntityPandaAggressiveAmbient { inner } => inner, + Sound::EntityPandaAmbient { inner } => inner, + Sound::EntityPandaBite { inner } => inner, + Sound::EntityPandaCantBreed { inner } => inner, + Sound::EntityPandaDeath { inner } => inner, + Sound::EntityPandaEat { inner } => inner, + Sound::EntityPandaHurt { inner } => inner, + Sound::EntityPandaPreSneeze { inner } => inner, + Sound::EntityPandaSneeze { inner } => inner, + Sound::EntityPandaStep { inner } => inner, + Sound::EntityPandaWorriedAmbient { inner } => inner, + Sound::EntityParrotAmbient { inner } => inner, + Sound::EntityParrotDeath { inner } => inner, + Sound::EntityParrotEat { inner } => inner, + Sound::EntityParrotFly { inner } => inner, + Sound::EntityParrotHurt { inner } => inner, + Sound::EntityParrotImitateBlaze { inner } => inner, + Sound::EntityParrotImitateBogged { inner } => inner, + Sound::EntityParrotImitateBreeze { inner } => inner, + Sound::EntityParrotImitateCreeper { inner } => inner, + Sound::EntityParrotImitateDrowned { inner } => inner, + Sound::EntityParrotImitateElderGuardian { inner } => inner, + Sound::EntityParrotImitateEndermite { inner } => inner, + Sound::EntityParrotImitateEnderDragon { inner } => inner, + Sound::EntityParrotImitateEvoker { inner } => inner, + Sound::EntityParrotImitateGhast { inner } => inner, + Sound::EntityParrotImitateGuardian { inner } => inner, + Sound::EntityParrotImitateHoglin { inner } => inner, + Sound::EntityParrotImitateHusk { inner } => inner, + Sound::EntityParrotImitateIllusioner { inner } => inner, + Sound::EntityParrotImitateMagmaCube { inner } => inner, + Sound::EntityParrotImitatePhantom { inner } => inner, + Sound::EntityParrotImitatePiglin { inner } => inner, + Sound::EntityParrotImitatePiglinBrute { inner } => inner, + Sound::EntityParrotImitatePillager { inner } => inner, + Sound::EntityParrotImitateRavager { inner } => inner, + Sound::EntityParrotImitateShulker { inner } => inner, + Sound::EntityParrotImitateSilverfish { inner } => inner, + Sound::EntityParrotImitateSkeleton { inner } => inner, + Sound::EntityParrotImitateSlime { inner } => inner, + Sound::EntityParrotImitateSpider { inner } => inner, + Sound::EntityParrotImitateStray { inner } => inner, + Sound::EntityParrotImitateVex { inner } => inner, + Sound::EntityParrotImitateVindicator { inner } => inner, + Sound::EntityParrotImitateWarden { inner } => inner, + Sound::EntityParrotImitateWitch { inner } => inner, + Sound::EntityParrotImitateWither { inner } => inner, + Sound::EntityParrotImitateWitherSkeleton { inner } => inner, + Sound::EntityParrotImitateZoglin { inner } => inner, + Sound::EntityParrotImitateZombie { inner } => inner, + Sound::EntityParrotImitateZombieVillager { inner } => inner, + Sound::EntityParrotStep { inner } => inner, + Sound::EntityPhantomAmbient { inner } => inner, + Sound::EntityPhantomBite { inner } => inner, + Sound::EntityPhantomDeath { inner } => inner, + Sound::EntityPhantomFlap { inner } => inner, + Sound::EntityPhantomHurt { inner } => inner, + Sound::EntityPhantomSwoop { inner } => inner, + Sound::EntityPiglinAdmiringItem { inner } => inner, + Sound::EntityPiglinAmbient { inner } => inner, + Sound::EntityPiglinAngry { inner } => inner, + Sound::EntityPiglinBruteAmbient { inner } => inner, + Sound::EntityPiglinBruteAngry { inner } => inner, + Sound::EntityPiglinBruteConvertedToZombified { inner } => inner, + Sound::EntityPiglinBruteDeath { inner } => inner, + Sound::EntityPiglinBruteHurt { inner } => inner, + Sound::EntityPiglinBruteStep { inner } => inner, + Sound::EntityPiglinCelebrate { inner } => inner, + Sound::EntityPiglinConvertedToZombified { inner } => inner, + Sound::EntityPiglinDeath { inner } => inner, + Sound::EntityPiglinHurt { inner } => inner, + Sound::EntityPiglinJealous { inner } => inner, + Sound::EntityPiglinRetreat { inner } => inner, + Sound::EntityPiglinStep { inner } => inner, + Sound::EntityPigAmbient { inner } => inner, + Sound::EntityPigDeath { inner } => inner, + Sound::EntityPigHurt { inner } => inner, + Sound::EntityPigSaddle { inner } => inner, + Sound::EntityPigStep { inner } => inner, + Sound::EntityPillagerAmbient { inner } => inner, + Sound::EntityPillagerCelebrate { inner } => inner, + Sound::EntityPillagerDeath { inner } => inner, + Sound::EntityPillagerHurt { inner } => inner, + Sound::EntityPlayerAttackCrit { inner } => inner, + Sound::EntityPlayerAttackKnockback { inner } => inner, + Sound::EntityPlayerAttackNodamage { inner } => inner, + Sound::EntityPlayerAttackStrong { inner } => inner, + Sound::EntityPlayerAttackSweep { inner } => inner, + Sound::EntityPlayerAttackWeak { inner } => inner, + Sound::EntityPlayerBigFall { inner } => inner, + Sound::EntityPlayerBreath { inner } => inner, + Sound::EntityPlayerBurp { inner } => inner, + Sound::EntityPlayerDeath { inner } => inner, + Sound::EntityPlayerHurt { inner } => inner, + Sound::EntityPlayerHurtDrown { inner } => inner, + Sound::EntityPlayerHurtFreeze { inner } => inner, + Sound::EntityPlayerHurtOnFire { inner } => inner, + Sound::EntityPlayerHurtSweetBerryBush { inner } => inner, + Sound::EntityPlayerLevelup { inner } => inner, + Sound::EntityPlayerSmallFall { inner } => inner, + Sound::EntityPlayerSplash { inner } => inner, + Sound::EntityPlayerSplashHighSpeed { inner } => inner, + Sound::EntityPlayerSwim { inner } => inner, + Sound::EntityPlayerTeleport { inner } => inner, + Sound::EntityPolarBearAmbient { inner } => inner, + Sound::EntityPolarBearAmbientBaby { inner } => inner, + Sound::EntityPolarBearDeath { inner } => inner, + Sound::EntityPolarBearHurt { inner } => inner, + Sound::EntityPolarBearStep { inner } => inner, + Sound::EntityPolarBearWarning { inner } => inner, + Sound::EntityPufferFishAmbient { inner } => inner, + Sound::EntityPufferFishBlowOut { inner } => inner, + Sound::EntityPufferFishBlowUp { inner } => inner, + Sound::EntityPufferFishDeath { inner } => inner, + Sound::EntityPufferFishFlop { inner } => inner, + Sound::EntityPufferFishHurt { inner } => inner, + Sound::EntityPufferFishSting { inner } => inner, + Sound::EntityRabbitAmbient { inner } => inner, + Sound::EntityRabbitAttack { inner } => inner, + Sound::EntityRabbitDeath { inner } => inner, + Sound::EntityRabbitHurt { inner } => inner, + Sound::EntityRabbitJump { inner } => inner, + Sound::EntityRavagerAmbient { inner } => inner, + Sound::EntityRavagerAttack { inner } => inner, + Sound::EntityRavagerCelebrate { inner } => inner, + Sound::EntityRavagerDeath { inner } => inner, + Sound::EntityRavagerHurt { inner } => inner, + Sound::EntityRavagerRoar { inner } => inner, + Sound::EntityRavagerStep { inner } => inner, + Sound::EntityRavagerStunned { inner } => inner, + Sound::EntitySalmonAmbient { inner } => inner, + Sound::EntitySalmonDeath { inner } => inner, + Sound::EntitySalmonFlop { inner } => inner, + Sound::EntitySalmonHurt { inner } => inner, + Sound::EntitySheepAmbient { inner } => inner, + Sound::EntitySheepDeath { inner } => inner, + Sound::EntitySheepHurt { inner } => inner, + Sound::EntitySheepShear { inner } => inner, + Sound::EntitySheepStep { inner } => inner, + Sound::EntityShulkerAmbient { inner } => inner, + Sound::EntityShulkerBulletHit { inner } => inner, + Sound::EntityShulkerBulletHurt { inner } => inner, + Sound::EntityShulkerClose { inner } => inner, + Sound::EntityShulkerDeath { inner } => inner, + Sound::EntityShulkerHurt { inner } => inner, + Sound::EntityShulkerHurtClosed { inner } => inner, + Sound::EntityShulkerOpen { inner } => inner, + Sound::EntityShulkerShoot { inner } => inner, + Sound::EntityShulkerTeleport { inner } => inner, + Sound::EntitySilverfishAmbient { inner } => inner, + Sound::EntitySilverfishDeath { inner } => inner, + Sound::EntitySilverfishHurt { inner } => inner, + Sound::EntitySilverfishStep { inner } => inner, + Sound::EntitySkeletonAmbient { inner } => inner, + Sound::EntitySkeletonConvertedToStray { inner } => inner, + Sound::EntitySkeletonDeath { inner } => inner, + Sound::EntitySkeletonHorseAmbient { inner } => inner, + Sound::EntitySkeletonHorseAmbientWater { inner } => inner, + Sound::EntitySkeletonHorseDeath { inner } => inner, + Sound::EntitySkeletonHorseGallopWater { inner } => inner, + Sound::EntitySkeletonHorseHurt { inner } => inner, + Sound::EntitySkeletonHorseJumpWater { inner } => inner, + Sound::EntitySkeletonHorseStepWater { inner } => inner, + Sound::EntitySkeletonHorseSwim { inner } => inner, + Sound::EntitySkeletonHurt { inner } => inner, + Sound::EntitySkeletonShoot { inner } => inner, + Sound::EntitySkeletonStep { inner } => inner, + Sound::EntitySlimeAttack { inner } => inner, + Sound::EntitySlimeDeath { inner } => inner, + Sound::EntitySlimeDeathSmall { inner } => inner, + Sound::EntitySlimeHurt { inner } => inner, + Sound::EntitySlimeHurtSmall { inner } => inner, + Sound::EntitySlimeJump { inner } => inner, + Sound::EntitySlimeJumpSmall { inner } => inner, + Sound::EntitySlimeSquish { inner } => inner, + Sound::EntitySlimeSquishSmall { inner } => inner, + Sound::EntitySnifferDeath { inner } => inner, + Sound::EntitySnifferDigging { inner } => inner, + Sound::EntitySnifferDiggingStop { inner } => inner, + Sound::EntitySnifferDropSeed { inner } => inner, + Sound::EntitySnifferEat { inner } => inner, + Sound::EntitySnifferHappy { inner } => inner, + Sound::EntitySnifferHurt { inner } => inner, + Sound::EntitySnifferIdle { inner } => inner, + Sound::EntitySnifferScenting { inner } => inner, + Sound::EntitySnifferSearching { inner } => inner, + Sound::EntitySnifferSniffing { inner } => inner, + Sound::EntitySnifferStep { inner } => inner, + Sound::EntitySnowballThrow { inner } => inner, + Sound::EntitySnowGolemAmbient { inner } => inner, + Sound::EntitySnowGolemDeath { inner } => inner, + Sound::EntitySnowGolemHurt { inner } => inner, + Sound::EntitySnowGolemShear { inner } => inner, + Sound::EntitySnowGolemShoot { inner } => inner, + Sound::EntitySpiderAmbient { inner } => inner, + Sound::EntitySpiderDeath { inner } => inner, + Sound::EntitySpiderHurt { inner } => inner, + Sound::EntitySpiderStep { inner } => inner, + Sound::EntitySplashPotionBreak { inner } => inner, + Sound::EntitySplashPotionThrow { inner } => inner, + Sound::EntitySquidAmbient { inner } => inner, + Sound::EntitySquidDeath { inner } => inner, + Sound::EntitySquidHurt { inner } => inner, + Sound::EntitySquidSquirt { inner } => inner, + Sound::EntityStrayAmbient { inner } => inner, + Sound::EntityStrayDeath { inner } => inner, + Sound::EntityStrayHurt { inner } => inner, + Sound::EntityStrayStep { inner } => inner, + Sound::EntityStriderAmbient { inner } => inner, + Sound::EntityStriderDeath { inner } => inner, + Sound::EntityStriderEat { inner } => inner, + Sound::EntityStriderHappy { inner } => inner, + Sound::EntityStriderHurt { inner } => inner, + Sound::EntityStriderRetreat { inner } => inner, + Sound::EntityStriderSaddle { inner } => inner, + Sound::EntityStriderStep { inner } => inner, + Sound::EntityStriderStepLava { inner } => inner, + Sound::EntityTadpoleDeath { inner } => inner, + Sound::EntityTadpoleFlop { inner } => inner, + Sound::EntityTadpoleGrowUp { inner } => inner, + Sound::EntityTadpoleHurt { inner } => inner, + Sound::EntityTntPrimed { inner } => inner, + Sound::EntityTropicalFishAmbient { inner } => inner, + Sound::EntityTropicalFishDeath { inner } => inner, + Sound::EntityTropicalFishFlop { inner } => inner, + Sound::EntityTropicalFishHurt { inner } => inner, + Sound::EntityTurtleAmbientLand { inner } => inner, + Sound::EntityTurtleDeath { inner } => inner, + Sound::EntityTurtleDeathBaby { inner } => inner, + Sound::EntityTurtleEggBreak { inner } => inner, + Sound::EntityTurtleEggCrack { inner } => inner, + Sound::EntityTurtleEggHatch { inner } => inner, + Sound::EntityTurtleHurt { inner } => inner, + Sound::EntityTurtleHurtBaby { inner } => inner, + Sound::EntityTurtleLayEgg { inner } => inner, + Sound::EntityTurtleShamble { inner } => inner, + Sound::EntityTurtleShambleBaby { inner } => inner, + Sound::EntityTurtleSwim { inner } => inner, + Sound::EntityVexAmbient { inner } => inner, + Sound::EntityVexCharge { inner } => inner, + Sound::EntityVexDeath { inner } => inner, + Sound::EntityVexHurt { inner } => inner, + Sound::EntityVillagerAmbient { inner } => inner, + Sound::EntityVillagerCelebrate { inner } => inner, + Sound::EntityVillagerDeath { inner } => inner, + Sound::EntityVillagerHurt { inner } => inner, + Sound::EntityVillagerNo { inner } => inner, + Sound::EntityVillagerTrade { inner } => inner, + Sound::EntityVillagerWorkArmorer { inner } => inner, + Sound::EntityVillagerWorkButcher { inner } => inner, + Sound::EntityVillagerWorkCartographer { inner } => inner, + Sound::EntityVillagerWorkCleric { inner } => inner, + Sound::EntityVillagerWorkFarmer { inner } => inner, + Sound::EntityVillagerWorkFisherman { inner } => inner, + Sound::EntityVillagerWorkFletcher { inner } => inner, + Sound::EntityVillagerWorkLeatherworker { inner } => inner, + Sound::EntityVillagerWorkLibrarian { inner } => inner, + Sound::EntityVillagerWorkMason { inner } => inner, + Sound::EntityVillagerWorkShepherd { inner } => inner, + Sound::EntityVillagerWorkToolsmith { inner } => inner, + Sound::EntityVillagerWorkWeaponsmith { inner } => inner, + Sound::EntityVillagerYes { inner } => inner, + Sound::EntityVindicatorAmbient { inner } => inner, + Sound::EntityVindicatorCelebrate { inner } => inner, + Sound::EntityVindicatorDeath { inner } => inner, + Sound::EntityVindicatorHurt { inner } => inner, + Sound::EntityWanderingTraderAmbient { inner } => inner, + Sound::EntityWanderingTraderDeath { inner } => inner, + Sound::EntityWanderingTraderDisappeared { inner } => inner, + Sound::EntityWanderingTraderDrinkMilk { inner } => inner, + Sound::EntityWanderingTraderDrinkPotion { inner } => inner, + Sound::EntityWanderingTraderHurt { inner } => inner, + Sound::EntityWanderingTraderNo { inner } => inner, + Sound::EntityWanderingTraderReappeared { inner } => inner, + Sound::EntityWanderingTraderTrade { inner } => inner, + Sound::EntityWanderingTraderYes { inner } => inner, + Sound::EntityWardenAgitated { inner } => inner, + Sound::EntityWardenAmbient { inner } => inner, + Sound::EntityWardenAngry { inner } => inner, + Sound::EntityWardenAttackImpact { inner } => inner, + Sound::EntityWardenDeath { inner } => inner, + Sound::EntityWardenDig { inner } => inner, + Sound::EntityWardenEmerge { inner } => inner, + Sound::EntityWardenHeartbeat { inner } => inner, + Sound::EntityWardenHurt { inner } => inner, + Sound::EntityWardenListening { inner } => inner, + Sound::EntityWardenListeningAngry { inner } => inner, + Sound::EntityWardenNearbyClose { inner } => inner, + Sound::EntityWardenNearbyCloser { inner } => inner, + Sound::EntityWardenNearbyClosest { inner } => inner, + Sound::EntityWardenRoar { inner } => inner, + Sound::EntityWardenSniff { inner } => inner, + Sound::EntityWardenSonicBoom { inner } => inner, + Sound::EntityWardenSonicCharge { inner } => inner, + Sound::EntityWardenStep { inner } => inner, + Sound::EntityWardenTendrilClicks { inner } => inner, + Sound::EntityWindChargeThrow { inner } => inner, + Sound::EntityWindChargeWindBurst { inner } => inner, + Sound::EntityWitchAmbient { inner } => inner, + Sound::EntityWitchCelebrate { inner } => inner, + Sound::EntityWitchDeath { inner } => inner, + Sound::EntityWitchDrink { inner } => inner, + Sound::EntityWitchHurt { inner } => inner, + Sound::EntityWitchThrow { inner } => inner, + Sound::EntityWitherAmbient { inner } => inner, + Sound::EntityWitherBreakBlock { inner } => inner, + Sound::EntityWitherDeath { inner } => inner, + Sound::EntityWitherHurt { inner } => inner, + Sound::EntityWitherShoot { inner } => inner, + Sound::EntityWitherSkeletonAmbient { inner } => inner, + Sound::EntityWitherSkeletonDeath { inner } => inner, + Sound::EntityWitherSkeletonHurt { inner } => inner, + Sound::EntityWitherSkeletonStep { inner } => inner, + Sound::EntityWitherSpawn { inner } => inner, + Sound::EntityWolfAmbient { inner } => inner, + Sound::EntityWolfDeath { inner } => inner, + Sound::EntityWolfGrowl { inner } => inner, + Sound::EntityWolfHowl { inner } => inner, + Sound::EntityWolfHurt { inner } => inner, + Sound::EntityWolfPant { inner } => inner, + Sound::EntityWolfShake { inner } => inner, + Sound::EntityWolfStep { inner } => inner, + Sound::EntityWolfWhine { inner } => inner, + Sound::EntityZoglinAmbient { inner } => inner, + Sound::EntityZoglinAngry { inner } => inner, + Sound::EntityZoglinAttack { inner } => inner, + Sound::EntityZoglinDeath { inner } => inner, + Sound::EntityZoglinHurt { inner } => inner, + Sound::EntityZoglinStep { inner } => inner, + Sound::EntityZombieAmbient { inner } => inner, + Sound::EntityZombieAttackIronDoor { inner } => inner, + Sound::EntityZombieAttackWoodenDoor { inner } => inner, + Sound::EntityZombieBreakWoodenDoor { inner } => inner, + Sound::EntityZombieConvertedToDrowned { inner } => inner, + Sound::EntityZombieDeath { inner } => inner, + Sound::EntityZombieDestroyEgg { inner } => inner, + Sound::EntityZombieHorseAmbient { inner } => inner, + Sound::EntityZombieHorseDeath { inner } => inner, + Sound::EntityZombieHorseHurt { inner } => inner, + Sound::EntityZombieHurt { inner } => inner, + Sound::EntityZombieInfect { inner } => inner, + Sound::EntityZombieStep { inner } => inner, + Sound::EntityZombieVillagerAmbient { inner } => inner, + Sound::EntityZombieVillagerConverted { inner } => inner, + Sound::EntityZombieVillagerCure { inner } => inner, + Sound::EntityZombieVillagerDeath { inner } => inner, + Sound::EntityZombieVillagerHurt { inner } => inner, + Sound::EntityZombieVillagerStep { inner } => inner, + Sound::EntityZombifiedPiglinAmbient { inner } => inner, + Sound::EntityZombifiedPiglinAngry { inner } => inner, + Sound::EntityZombifiedPiglinDeath { inner } => inner, + Sound::EntityZombifiedPiglinHurt { inner } => inner, + Sound::EventMobEffectBadOmen { inner } => inner, + Sound::EventMobEffectRaidOmen { inner } => inner, + Sound::EventMobEffectTrialOmen { inner } => inner, + Sound::EventRaidHorn { inner } => inner, + Sound::IntentionallyEmpty { inner } => inner, + Sound::ItemArmorEquipChain { inner } => inner, + Sound::ItemArmorEquipDiamond { inner } => inner, + Sound::ItemArmorEquipElytra { inner } => inner, + Sound::ItemArmorEquipGeneric { inner } => inner, + Sound::ItemArmorEquipGold { inner } => inner, + Sound::ItemArmorEquipIron { inner } => inner, + Sound::ItemArmorEquipLeather { inner } => inner, + Sound::ItemArmorEquipNetherite { inner } => inner, + Sound::ItemArmorEquipTurtle { inner } => inner, + Sound::ItemArmorEquipWolf { inner } => inner, + Sound::ItemArmorUnequipWolf { inner } => inner, + Sound::ItemAxeScrape { inner } => inner, + Sound::ItemAxeStrip { inner } => inner, + Sound::ItemAxeWaxOff { inner } => inner, + Sound::ItemBoneMealUse { inner } => inner, + Sound::ItemBookPageTurn { inner } => inner, + Sound::ItemBookPut { inner } => inner, + Sound::ItemBottleEmpty { inner } => inner, + Sound::ItemBottleFill { inner } => inner, + Sound::ItemBottleFillDragonbreath { inner } => inner, + Sound::ItemBrushBrushingGeneric { inner } => inner, + Sound::ItemBrushBrushingGravel { inner } => inner, + Sound::ItemBrushBrushingGravelComplete { inner } => inner, + Sound::ItemBrushBrushingSand { inner } => inner, + Sound::ItemBrushBrushingSandComplete { inner } => inner, + Sound::ItemBucketEmpty { inner } => inner, + Sound::ItemBucketEmptyAxolotl { inner } => inner, + Sound::ItemBucketEmptyFish { inner } => inner, + Sound::ItemBucketEmptyLava { inner } => inner, + Sound::ItemBucketEmptyPowderSnow { inner } => inner, + Sound::ItemBucketEmptyTadpole { inner } => inner, + Sound::ItemBucketFill { inner } => inner, + Sound::ItemBucketFillAxolotl { inner } => inner, + Sound::ItemBucketFillFish { inner } => inner, + Sound::ItemBucketFillLava { inner } => inner, + Sound::ItemBucketFillPowderSnow { inner } => inner, + Sound::ItemBucketFillTadpole { inner } => inner, + Sound::ItemBundleDropContents { inner } => inner, + Sound::ItemBundleInsert { inner } => inner, + Sound::ItemBundleRemoveOne { inner } => inner, + Sound::ItemChorusFruitTeleport { inner } => inner, + Sound::ItemCropPlant { inner } => inner, + Sound::ItemCrossbowHit { inner } => inner, + Sound::ItemCrossbowLoadingEnd { inner } => inner, + Sound::ItemCrossbowLoadingMiddle { inner } => inner, + Sound::ItemCrossbowLoadingStart { inner } => inner, + Sound::ItemCrossbowQuickCharge1 { inner } => inner, + Sound::ItemCrossbowQuickCharge2 { inner } => inner, + Sound::ItemCrossbowQuickCharge3 { inner } => inner, + Sound::ItemCrossbowShoot { inner } => inner, + Sound::ItemDyeUse { inner } => inner, + Sound::ItemElytraFlying { inner } => inner, + Sound::ItemFirechargeUse { inner } => inner, + Sound::ItemFlintandsteelUse { inner } => inner, + Sound::ItemGlowInkSacUse { inner } => inner, + Sound::ItemGoatHornPlay { inner } => inner, + Sound::ItemGoatHornSound0 { inner } => inner, + Sound::ItemGoatHornSound1 { inner } => inner, + Sound::ItemGoatHornSound2 { inner } => inner, + Sound::ItemGoatHornSound3 { inner } => inner, + Sound::ItemGoatHornSound4 { inner } => inner, + Sound::ItemGoatHornSound5 { inner } => inner, + Sound::ItemGoatHornSound6 { inner } => inner, + Sound::ItemGoatHornSound7 { inner } => inner, + Sound::ItemHoeTill { inner } => inner, + Sound::ItemHoneycombWaxOn { inner } => inner, + Sound::ItemHoneyBottleDrink { inner } => inner, + Sound::ItemInkSacUse { inner } => inner, + Sound::ItemLodestoneCompassLock { inner } => inner, + Sound::ItemMaceSmashAir { inner } => inner, + Sound::ItemMaceSmashGround { inner } => inner, + Sound::ItemMaceSmashGroundHeavy { inner } => inner, + Sound::ItemNetherWartPlant { inner } => inner, + Sound::ItemOminousBottleDispose { inner } => inner, + Sound::ItemShieldBlock { inner } => inner, + Sound::ItemShieldBreak { inner } => inner, + Sound::ItemShovelFlatten { inner } => inner, + Sound::ItemSpyglassStopUsing { inner } => inner, + Sound::ItemSpyglassUse { inner } => inner, + Sound::ItemTotemUse { inner } => inner, + Sound::ItemTridentHit { inner } => inner, + Sound::ItemTridentHitGround { inner } => inner, + Sound::ItemTridentReturn { inner } => inner, + Sound::ItemTridentRiptide1 { inner } => inner, + Sound::ItemTridentRiptide2 { inner } => inner, + Sound::ItemTridentRiptide3 { inner } => inner, + Sound::ItemTridentThrow { inner } => inner, + Sound::ItemTridentThunder { inner } => inner, + Sound::ItemWolfArmorBreak { inner } => inner, + Sound::ItemWolfArmorCrack { inner } => inner, + Sound::ItemWolfArmorDamage { inner } => inner, + Sound::ItemWolfArmorRepair { inner } => inner, + Sound::MusicCreative { inner } => inner, + Sound::MusicCredits { inner } => inner, + Sound::MusicDisc11 { inner } => inner, + Sound::MusicDisc13 { inner } => inner, + Sound::MusicDisc5 { inner } => inner, + Sound::MusicDiscBlocks { inner } => inner, + Sound::MusicDiscCat { inner } => inner, + Sound::MusicDiscChirp { inner } => inner, + Sound::MusicDiscCreator { inner } => inner, + Sound::MusicDiscCreatorMusicBox { inner } => inner, + Sound::MusicDiscFar { inner } => inner, + Sound::MusicDiscMall { inner } => inner, + Sound::MusicDiscMellohi { inner } => inner, + Sound::MusicDiscOtherside { inner } => inner, + Sound::MusicDiscPigstep { inner } => inner, + Sound::MusicDiscPrecipice { inner } => inner, + Sound::MusicDiscRelic { inner } => inner, + Sound::MusicDiscStal { inner } => inner, + Sound::MusicDiscStrad { inner } => inner, + Sound::MusicDiscWait { inner } => inner, + Sound::MusicDiscWard { inner } => inner, + Sound::MusicDragon { inner } => inner, + Sound::MusicEnd { inner } => inner, + Sound::MusicGame { inner } => inner, + Sound::MusicMenu { inner } => inner, + Sound::MusicNetherBasaltDeltas { inner } => inner, + Sound::MusicNetherCrimsonForest { inner } => inner, + Sound::MusicNetherNetherWastes { inner } => inner, + Sound::MusicNetherSoulSandValley { inner } => inner, + Sound::MusicNetherWarpedForest { inner } => inner, + Sound::MusicOverworldBadlands { inner } => inner, + Sound::MusicOverworldBambooJungle { inner } => inner, + Sound::MusicOverworldCherryGrove { inner } => inner, + Sound::MusicOverworldDeepDark { inner } => inner, + Sound::MusicOverworldDesert { inner } => inner, + Sound::MusicOverworldDripstoneCaves { inner } => inner, + Sound::MusicOverworldFlowerForest { inner } => inner, + Sound::MusicOverworldForest { inner } => inner, + Sound::MusicOverworldFrozenPeaks { inner } => inner, + Sound::MusicOverworldGrove { inner } => inner, + Sound::MusicOverworldJaggedPeaks { inner } => inner, + Sound::MusicOverworldJungle { inner } => inner, + Sound::MusicOverworldLushCaves { inner } => inner, + Sound::MusicOverworldMeadow { inner } => inner, + Sound::MusicOverworldOldGrowthTaiga { inner } => inner, + Sound::MusicOverworldSnowySlopes { inner } => inner, + Sound::MusicOverworldSparseJungle { inner } => inner, + Sound::MusicOverworldStonyPeaks { inner } => inner, + Sound::MusicOverworldSwamp { inner } => inner, + Sound::MusicUnderWater { inner } => inner, + Sound::ParticleSoulEscape { inner } => inner, + Sound::UiButtonClick { inner } => inner, + Sound::UiCartographyTableTakeResult { inner } => inner, + Sound::UiLoomSelectPattern { inner } => inner, + Sound::UiLoomTakeResult { inner } => inner, + Sound::UiStonecutterSelectRecipe { inner } => inner, + Sound::UiStonecutterTakeResult { inner } => inner, + Sound::UiToastChallengeComplete { inner } => inner, + Sound::UiToastIn { inner } => inner, + Sound::UiToastOut { inner } => inner, + Sound::WeatherRain { inner } => inner, + Sound::WeatherRainAbove { inner } => inner, + } + } +} + +impl<'mc> Sound<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/Sound"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/Sound;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "AMBIENT_BASALT_DELTAS_ADDITIONS" => Ok(Sound::AmbientBasaltDeltasAdditions { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_BASALT_DELTAS_LOOP" => Ok(Sound::AmbientBasaltDeltasLoop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_BASALT_DELTAS_MOOD" => Ok(Sound::AmbientBasaltDeltasMood { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_CAVE" => Ok(Sound::AmbientCave { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_CRIMSON_FOREST_ADDITIONS" => Ok(Sound::AmbientCrimsonForestAdditions { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_CRIMSON_FOREST_LOOP" => Ok(Sound::AmbientCrimsonForestLoop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_CRIMSON_FOREST_MOOD" => Ok(Sound::AmbientCrimsonForestMood { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_NETHER_WASTES_ADDITIONS" => Ok(Sound::AmbientNetherWastesAdditions { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_NETHER_WASTES_LOOP" => Ok(Sound::AmbientNetherWastesLoop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_NETHER_WASTES_MOOD" => Ok(Sound::AmbientNetherWastesMood { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_SOUL_SAND_VALLEY_ADDITIONS" => Ok(Sound::AmbientSoulSandValleyAdditions { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_SOUL_SAND_VALLEY_LOOP" => Ok(Sound::AmbientSoulSandValleyLoop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_SOUL_SAND_VALLEY_MOOD" => Ok(Sound::AmbientSoulSandValleyMood { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_UNDERWATER_ENTER" => Ok(Sound::AmbientUnderwaterEnter { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_UNDERWATER_EXIT" => Ok(Sound::AmbientUnderwaterExit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_UNDERWATER_LOOP" => Ok(Sound::AmbientUnderwaterLoop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_UNDERWATER_LOOP_ADDITIONS" => Ok(Sound::AmbientUnderwaterLoopAdditions { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_UNDERWATER_LOOP_ADDITIONS_RARE" => { + Ok(Sound::AmbientUnderwaterLoopAdditionsRare { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "AMBIENT_UNDERWATER_LOOP_ADDITIONS_ULTRA_RARE" => { + Ok(Sound::AmbientUnderwaterLoopAdditionsUltraRare { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "AMBIENT_WARPED_FOREST_ADDITIONS" => Ok(Sound::AmbientWarpedForestAdditions { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_WARPED_FOREST_LOOP" => Ok(Sound::AmbientWarpedForestLoop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_WARPED_FOREST_MOOD" => Ok(Sound::AmbientWarpedForestMood { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AMETHYST_BLOCK_BREAK" => Ok(Sound::BlockAmethystBlockBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AMETHYST_BLOCK_CHIME" => Ok(Sound::BlockAmethystBlockChime { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AMETHYST_BLOCK_FALL" => Ok(Sound::BlockAmethystBlockFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AMETHYST_BLOCK_HIT" => Ok(Sound::BlockAmethystBlockHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AMETHYST_BLOCK_PLACE" => Ok(Sound::BlockAmethystBlockPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AMETHYST_BLOCK_RESONATE" => Ok(Sound::BlockAmethystBlockResonate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AMETHYST_BLOCK_STEP" => Ok(Sound::BlockAmethystBlockStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AMETHYST_CLUSTER_BREAK" => Ok(Sound::BlockAmethystClusterBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AMETHYST_CLUSTER_FALL" => Ok(Sound::BlockAmethystClusterFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AMETHYST_CLUSTER_HIT" => Ok(Sound::BlockAmethystClusterHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AMETHYST_CLUSTER_PLACE" => Ok(Sound::BlockAmethystClusterPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AMETHYST_CLUSTER_STEP" => Ok(Sound::BlockAmethystClusterStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANCIENT_DEBRIS_BREAK" => Ok(Sound::BlockAncientDebrisBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANCIENT_DEBRIS_FALL" => Ok(Sound::BlockAncientDebrisFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANCIENT_DEBRIS_HIT" => Ok(Sound::BlockAncientDebrisHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANCIENT_DEBRIS_PLACE" => Ok(Sound::BlockAncientDebrisPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANCIENT_DEBRIS_STEP" => Ok(Sound::BlockAncientDebrisStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANVIL_BREAK" => Ok(Sound::BlockAnvilBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANVIL_DESTROY" => Ok(Sound::BlockAnvilDestroy { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANVIL_FALL" => Ok(Sound::BlockAnvilFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANVIL_HIT" => Ok(Sound::BlockAnvilHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANVIL_LAND" => Ok(Sound::BlockAnvilLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANVIL_PLACE" => Ok(Sound::BlockAnvilPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANVIL_STEP" => Ok(Sound::BlockAnvilStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANVIL_USE" => Ok(Sound::BlockAnvilUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AZALEA_BREAK" => Ok(Sound::BlockAzaleaBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AZALEA_FALL" => Ok(Sound::BlockAzaleaFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AZALEA_HIT" => Ok(Sound::BlockAzaleaHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AZALEA_LEAVES_BREAK" => Ok(Sound::BlockAzaleaLeavesBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AZALEA_LEAVES_FALL" => Ok(Sound::BlockAzaleaLeavesFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AZALEA_LEAVES_HIT" => Ok(Sound::BlockAzaleaLeavesHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AZALEA_LEAVES_PLACE" => Ok(Sound::BlockAzaleaLeavesPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AZALEA_LEAVES_STEP" => Ok(Sound::BlockAzaleaLeavesStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AZALEA_PLACE" => Ok(Sound::BlockAzaleaPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AZALEA_STEP" => Ok(Sound::BlockAzaleaStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_BREAK" => Ok(Sound::BlockBambooBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_FALL" => Ok(Sound::BlockBambooFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_HIT" => Ok(Sound::BlockBambooHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_PLACE" => Ok(Sound::BlockBambooPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_SAPLING_BREAK" => Ok(Sound::BlockBambooSaplingBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_SAPLING_HIT" => Ok(Sound::BlockBambooSaplingHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_SAPLING_PLACE" => Ok(Sound::BlockBambooSaplingPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_STEP" => Ok(Sound::BlockBambooStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_BREAK" => Ok(Sound::BlockBambooWoodBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_BUTTON_CLICK_OFF" => Ok(Sound::BlockBambooWoodButtonClickOff { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_BUTTON_CLICK_ON" => Ok(Sound::BlockBambooWoodButtonClickOn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_DOOR_CLOSE" => Ok(Sound::BlockBambooWoodDoorClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_DOOR_OPEN" => Ok(Sound::BlockBambooWoodDoorOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_FALL" => Ok(Sound::BlockBambooWoodFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_FENCE_GATE_CLOSE" => Ok(Sound::BlockBambooWoodFenceGateClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_FENCE_GATE_OPEN" => Ok(Sound::BlockBambooWoodFenceGateOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_HANGING_SIGN_BREAK" => Ok(Sound::BlockBambooWoodHangingSignBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_HANGING_SIGN_FALL" => Ok(Sound::BlockBambooWoodHangingSignFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_HANGING_SIGN_HIT" => Ok(Sound::BlockBambooWoodHangingSignHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_HANGING_SIGN_PLACE" => Ok(Sound::BlockBambooWoodHangingSignPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_HANGING_SIGN_STEP" => Ok(Sound::BlockBambooWoodHangingSignStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_HIT" => Ok(Sound::BlockBambooWoodHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_PLACE" => Ok(Sound::BlockBambooWoodPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_PRESSURE_PLATE_CLICK_OFF" => { + Ok(Sound::BlockBambooWoodPressurePlateClickOff { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_BAMBOO_WOOD_PRESSURE_PLATE_CLICK_ON" => { + Ok(Sound::BlockBambooWoodPressurePlateClickOn { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_BAMBOO_WOOD_STEP" => Ok(Sound::BlockBambooWoodStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_TRAPDOOR_CLOSE" => Ok(Sound::BlockBambooWoodTrapdoorClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_TRAPDOOR_OPEN" => Ok(Sound::BlockBambooWoodTrapdoorOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BARREL_CLOSE" => Ok(Sound::BlockBarrelClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BARREL_OPEN" => Ok(Sound::BlockBarrelOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BASALT_BREAK" => Ok(Sound::BlockBasaltBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BASALT_FALL" => Ok(Sound::BlockBasaltFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BASALT_HIT" => Ok(Sound::BlockBasaltHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BASALT_PLACE" => Ok(Sound::BlockBasaltPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BASALT_STEP" => Ok(Sound::BlockBasaltStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BEACON_ACTIVATE" => Ok(Sound::BlockBeaconActivate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BEACON_AMBIENT" => Ok(Sound::BlockBeaconAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BEACON_DEACTIVATE" => Ok(Sound::BlockBeaconDeactivate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BEACON_POWER_SELECT" => Ok(Sound::BlockBeaconPowerSelect { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BEEHIVE_DRIP" => Ok(Sound::BlockBeehiveDrip { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BEEHIVE_ENTER" => Ok(Sound::BlockBeehiveEnter { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BEEHIVE_EXIT" => Ok(Sound::BlockBeehiveExit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BEEHIVE_SHEAR" => Ok(Sound::BlockBeehiveShear { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BEEHIVE_WORK" => Ok(Sound::BlockBeehiveWork { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BELL_RESONATE" => Ok(Sound::BlockBellResonate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BELL_USE" => Ok(Sound::BlockBellUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BIG_DRIPLEAF_BREAK" => Ok(Sound::BlockBigDripleafBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BIG_DRIPLEAF_FALL" => Ok(Sound::BlockBigDripleafFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BIG_DRIPLEAF_HIT" => Ok(Sound::BlockBigDripleafHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BIG_DRIPLEAF_PLACE" => Ok(Sound::BlockBigDripleafPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BIG_DRIPLEAF_STEP" => Ok(Sound::BlockBigDripleafStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BIG_DRIPLEAF_TILT_DOWN" => Ok(Sound::BlockBigDripleafTiltDown { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BIG_DRIPLEAF_TILT_UP" => Ok(Sound::BlockBigDripleafTiltUp { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BLASTFURNACE_FIRE_CRACKLE" => Ok(Sound::BlockBlastfurnaceFireCrackle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BONE_BLOCK_BREAK" => Ok(Sound::BlockBoneBlockBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BONE_BLOCK_FALL" => Ok(Sound::BlockBoneBlockFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BONE_BLOCK_HIT" => Ok(Sound::BlockBoneBlockHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BONE_BLOCK_PLACE" => Ok(Sound::BlockBoneBlockPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BONE_BLOCK_STEP" => Ok(Sound::BlockBoneBlockStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BREWING_STAND_BREW" => Ok(Sound::BlockBrewingStandBrew { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BUBBLE_COLUMN_BUBBLE_POP" => Ok(Sound::BlockBubbleColumnBubblePop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BUBBLE_COLUMN_UPWARDS_AMBIENT" => Ok(Sound::BlockBubbleColumnUpwardsAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BUBBLE_COLUMN_UPWARDS_INSIDE" => Ok(Sound::BlockBubbleColumnUpwardsInside { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BUBBLE_COLUMN_WHIRLPOOL_AMBIENT" => { + Ok(Sound::BlockBubbleColumnWhirlpoolAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_BUBBLE_COLUMN_WHIRLPOOL_INSIDE" => Ok(Sound::BlockBubbleColumnWhirlpoolInside { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CAKE_ADD_CANDLE" => Ok(Sound::BlockCakeAddCandle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CALCITE_BREAK" => Ok(Sound::BlockCalciteBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CALCITE_FALL" => Ok(Sound::BlockCalciteFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CALCITE_HIT" => Ok(Sound::BlockCalciteHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CALCITE_PLACE" => Ok(Sound::BlockCalcitePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CALCITE_STEP" => Ok(Sound::BlockCalciteStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CAMPFIRE_CRACKLE" => Ok(Sound::BlockCampfireCrackle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CANDLE_AMBIENT" => Ok(Sound::BlockCandleAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CANDLE_BREAK" => Ok(Sound::BlockCandleBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CANDLE_EXTINGUISH" => Ok(Sound::BlockCandleExtinguish { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CANDLE_FALL" => Ok(Sound::BlockCandleFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CANDLE_HIT" => Ok(Sound::BlockCandleHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CANDLE_PLACE" => Ok(Sound::BlockCandlePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CANDLE_STEP" => Ok(Sound::BlockCandleStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CAVE_VINES_BREAK" => Ok(Sound::BlockCaveVinesBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CAVE_VINES_FALL" => Ok(Sound::BlockCaveVinesFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CAVE_VINES_HIT" => Ok(Sound::BlockCaveVinesHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CAVE_VINES_PICK_BERRIES" => Ok(Sound::BlockCaveVinesPickBerries { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CAVE_VINES_PLACE" => Ok(Sound::BlockCaveVinesPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CAVE_VINES_STEP" => Ok(Sound::BlockCaveVinesStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHAIN_BREAK" => Ok(Sound::BlockChainBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHAIN_FALL" => Ok(Sound::BlockChainFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHAIN_HIT" => Ok(Sound::BlockChainHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHAIN_PLACE" => Ok(Sound::BlockChainPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHAIN_STEP" => Ok(Sound::BlockChainStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_LEAVES_BREAK" => Ok(Sound::BlockCherryLeavesBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_LEAVES_FALL" => Ok(Sound::BlockCherryLeavesFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_LEAVES_HIT" => Ok(Sound::BlockCherryLeavesHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_LEAVES_PLACE" => Ok(Sound::BlockCherryLeavesPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_LEAVES_STEP" => Ok(Sound::BlockCherryLeavesStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_SAPLING_BREAK" => Ok(Sound::BlockCherrySaplingBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_SAPLING_FALL" => Ok(Sound::BlockCherrySaplingFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_SAPLING_HIT" => Ok(Sound::BlockCherrySaplingHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_SAPLING_PLACE" => Ok(Sound::BlockCherrySaplingPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_SAPLING_STEP" => Ok(Sound::BlockCherrySaplingStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_BREAK" => Ok(Sound::BlockCherryWoodBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_BUTTON_CLICK_OFF" => Ok(Sound::BlockCherryWoodButtonClickOff { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_BUTTON_CLICK_ON" => Ok(Sound::BlockCherryWoodButtonClickOn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_DOOR_CLOSE" => Ok(Sound::BlockCherryWoodDoorClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_DOOR_OPEN" => Ok(Sound::BlockCherryWoodDoorOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_FALL" => Ok(Sound::BlockCherryWoodFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_FENCE_GATE_CLOSE" => Ok(Sound::BlockCherryWoodFenceGateClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_FENCE_GATE_OPEN" => Ok(Sound::BlockCherryWoodFenceGateOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_HANGING_SIGN_BREAK" => Ok(Sound::BlockCherryWoodHangingSignBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_HANGING_SIGN_FALL" => Ok(Sound::BlockCherryWoodHangingSignFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_HANGING_SIGN_HIT" => Ok(Sound::BlockCherryWoodHangingSignHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_HANGING_SIGN_PLACE" => Ok(Sound::BlockCherryWoodHangingSignPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_HANGING_SIGN_STEP" => Ok(Sound::BlockCherryWoodHangingSignStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_HIT" => Ok(Sound::BlockCherryWoodHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_PLACE" => Ok(Sound::BlockCherryWoodPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_PRESSURE_PLATE_CLICK_OFF" => { + Ok(Sound::BlockCherryWoodPressurePlateClickOff { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_CHERRY_WOOD_PRESSURE_PLATE_CLICK_ON" => { + Ok(Sound::BlockCherryWoodPressurePlateClickOn { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_CHERRY_WOOD_STEP" => Ok(Sound::BlockCherryWoodStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_TRAPDOOR_CLOSE" => Ok(Sound::BlockCherryWoodTrapdoorClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_TRAPDOOR_OPEN" => Ok(Sound::BlockCherryWoodTrapdoorOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHEST_CLOSE" => Ok(Sound::BlockChestClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHEST_LOCKED" => Ok(Sound::BlockChestLocked { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHEST_OPEN" => Ok(Sound::BlockChestOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHISELED_BOOKSHELF_BREAK" => Ok(Sound::BlockChiseledBookshelfBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHISELED_BOOKSHELF_FALL" => Ok(Sound::BlockChiseledBookshelfFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHISELED_BOOKSHELF_HIT" => Ok(Sound::BlockChiseledBookshelfHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHISELED_BOOKSHELF_INSERT" => Ok(Sound::BlockChiseledBookshelfInsert { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHISELED_BOOKSHELF_INSERT_ENCHANTED" => { + Ok(Sound::BlockChiseledBookshelfInsertEnchanted { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_CHISELED_BOOKSHELF_PICKUP" => Ok(Sound::BlockChiseledBookshelfPickup { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHISELED_BOOKSHELF_PICKUP_ENCHANTED" => { + Ok(Sound::BlockChiseledBookshelfPickupEnchanted { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_CHISELED_BOOKSHELF_PLACE" => Ok(Sound::BlockChiseledBookshelfPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHISELED_BOOKSHELF_STEP" => Ok(Sound::BlockChiseledBookshelfStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHORUS_FLOWER_DEATH" => Ok(Sound::BlockChorusFlowerDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHORUS_FLOWER_GROW" => Ok(Sound::BlockChorusFlowerGrow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COBWEB_BREAK" => Ok(Sound::BlockCobwebBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COBWEB_FALL" => Ok(Sound::BlockCobwebFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COBWEB_HIT" => Ok(Sound::BlockCobwebHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COBWEB_PLACE" => Ok(Sound::BlockCobwebPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COBWEB_STEP" => Ok(Sound::BlockCobwebStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COMPARATOR_CLICK" => Ok(Sound::BlockComparatorClick { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COMPOSTER_EMPTY" => Ok(Sound::BlockComposterEmpty { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COMPOSTER_FILL" => Ok(Sound::BlockComposterFill { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COMPOSTER_FILL_SUCCESS" => Ok(Sound::BlockComposterFillSuccess { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COMPOSTER_READY" => Ok(Sound::BlockComposterReady { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CONDUIT_ACTIVATE" => Ok(Sound::BlockConduitActivate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CONDUIT_AMBIENT" => Ok(Sound::BlockConduitAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CONDUIT_AMBIENT_SHORT" => Ok(Sound::BlockConduitAmbientShort { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CONDUIT_ATTACK_TARGET" => Ok(Sound::BlockConduitAttackTarget { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CONDUIT_DEACTIVATE" => Ok(Sound::BlockConduitDeactivate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_BREAK" => Ok(Sound::BlockCopperBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_BULB_BREAK" => Ok(Sound::BlockCopperBulbBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_BULB_FALL" => Ok(Sound::BlockCopperBulbFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_BULB_HIT" => Ok(Sound::BlockCopperBulbHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_BULB_PLACE" => Ok(Sound::BlockCopperBulbPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_BULB_STEP" => Ok(Sound::BlockCopperBulbStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_BULB_TURN_OFF" => Ok(Sound::BlockCopperBulbTurnOff { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_BULB_TURN_ON" => Ok(Sound::BlockCopperBulbTurnOn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_DOOR_CLOSE" => Ok(Sound::BlockCopperDoorClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_DOOR_OPEN" => Ok(Sound::BlockCopperDoorOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_FALL" => Ok(Sound::BlockCopperFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_GRATE_BREAK" => Ok(Sound::BlockCopperGrateBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_GRATE_FALL" => Ok(Sound::BlockCopperGrateFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_GRATE_HIT" => Ok(Sound::BlockCopperGrateHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_GRATE_PLACE" => Ok(Sound::BlockCopperGratePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_GRATE_STEP" => Ok(Sound::BlockCopperGrateStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_HIT" => Ok(Sound::BlockCopperHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_PLACE" => Ok(Sound::BlockCopperPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_STEP" => Ok(Sound::BlockCopperStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_TRAPDOOR_CLOSE" => Ok(Sound::BlockCopperTrapdoorClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_TRAPDOOR_OPEN" => Ok(Sound::BlockCopperTrapdoorOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CORAL_BLOCK_BREAK" => Ok(Sound::BlockCoralBlockBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CORAL_BLOCK_FALL" => Ok(Sound::BlockCoralBlockFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CORAL_BLOCK_HIT" => Ok(Sound::BlockCoralBlockHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CORAL_BLOCK_PLACE" => Ok(Sound::BlockCoralBlockPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CORAL_BLOCK_STEP" => Ok(Sound::BlockCoralBlockStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CRAFTER_CRAFT" => Ok(Sound::BlockCrafterCraft { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CRAFTER_FAIL" => Ok(Sound::BlockCrafterFail { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CROP_BREAK" => Ok(Sound::BlockCropBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DECORATED_POT_BREAK" => Ok(Sound::BlockDecoratedPotBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DECORATED_POT_FALL" => Ok(Sound::BlockDecoratedPotFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DECORATED_POT_HIT" => Ok(Sound::BlockDecoratedPotHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DECORATED_POT_INSERT" => Ok(Sound::BlockDecoratedPotInsert { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DECORATED_POT_INSERT_FAIL" => Ok(Sound::BlockDecoratedPotInsertFail { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DECORATED_POT_PLACE" => Ok(Sound::BlockDecoratedPotPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DECORATED_POT_SHATTER" => Ok(Sound::BlockDecoratedPotShatter { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DECORATED_POT_STEP" => Ok(Sound::BlockDecoratedPotStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_BREAK" => Ok(Sound::BlockDeepslateBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_BRICKS_BREAK" => Ok(Sound::BlockDeepslateBricksBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_BRICKS_FALL" => Ok(Sound::BlockDeepslateBricksFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_BRICKS_HIT" => Ok(Sound::BlockDeepslateBricksHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_BRICKS_PLACE" => Ok(Sound::BlockDeepslateBricksPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_BRICKS_STEP" => Ok(Sound::BlockDeepslateBricksStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_FALL" => Ok(Sound::BlockDeepslateFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_HIT" => Ok(Sound::BlockDeepslateHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_PLACE" => Ok(Sound::BlockDeepslatePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_STEP" => Ok(Sound::BlockDeepslateStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_TILES_BREAK" => Ok(Sound::BlockDeepslateTilesBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_TILES_FALL" => Ok(Sound::BlockDeepslateTilesFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_TILES_HIT" => Ok(Sound::BlockDeepslateTilesHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_TILES_PLACE" => Ok(Sound::BlockDeepslateTilesPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_TILES_STEP" => Ok(Sound::BlockDeepslateTilesStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DISPENSER_DISPENSE" => Ok(Sound::BlockDispenserDispense { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DISPENSER_FAIL" => Ok(Sound::BlockDispenserFail { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DISPENSER_LAUNCH" => Ok(Sound::BlockDispenserLaunch { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DRIPSTONE_BLOCK_BREAK" => Ok(Sound::BlockDripstoneBlockBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DRIPSTONE_BLOCK_FALL" => Ok(Sound::BlockDripstoneBlockFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DRIPSTONE_BLOCK_HIT" => Ok(Sound::BlockDripstoneBlockHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DRIPSTONE_BLOCK_PLACE" => Ok(Sound::BlockDripstoneBlockPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DRIPSTONE_BLOCK_STEP" => Ok(Sound::BlockDripstoneBlockStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ENCHANTMENT_TABLE_USE" => Ok(Sound::BlockEnchantmentTableUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ENDER_CHEST_CLOSE" => Ok(Sound::BlockEnderChestClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ENDER_CHEST_OPEN" => Ok(Sound::BlockEnderChestOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_END_GATEWAY_SPAWN" => Ok(Sound::BlockEndGatewaySpawn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_END_PORTAL_FRAME_FILL" => Ok(Sound::BlockEndPortalFrameFill { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_END_PORTAL_SPAWN" => Ok(Sound::BlockEndPortalSpawn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FENCE_GATE_CLOSE" => Ok(Sound::BlockFenceGateClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FENCE_GATE_OPEN" => Ok(Sound::BlockFenceGateOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FIRE_AMBIENT" => Ok(Sound::BlockFireAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FIRE_EXTINGUISH" => Ok(Sound::BlockFireExtinguish { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FLOWERING_AZALEA_BREAK" => Ok(Sound::BlockFloweringAzaleaBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FLOWERING_AZALEA_FALL" => Ok(Sound::BlockFloweringAzaleaFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FLOWERING_AZALEA_HIT" => Ok(Sound::BlockFloweringAzaleaHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FLOWERING_AZALEA_PLACE" => Ok(Sound::BlockFloweringAzaleaPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FLOWERING_AZALEA_STEP" => Ok(Sound::BlockFloweringAzaleaStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FROGLIGHT_BREAK" => Ok(Sound::BlockFroglightBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FROGLIGHT_FALL" => Ok(Sound::BlockFroglightFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FROGLIGHT_HIT" => Ok(Sound::BlockFroglightHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FROGLIGHT_PLACE" => Ok(Sound::BlockFroglightPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FROGLIGHT_STEP" => Ok(Sound::BlockFroglightStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FROGSPAWN_BREAK" => Ok(Sound::BlockFrogspawnBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FROGSPAWN_FALL" => Ok(Sound::BlockFrogspawnFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FROGSPAWN_HATCH" => Ok(Sound::BlockFrogspawnHatch { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FROGSPAWN_HIT" => Ok(Sound::BlockFrogspawnHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FROGSPAWN_PLACE" => Ok(Sound::BlockFrogspawnPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FROGSPAWN_STEP" => Ok(Sound::BlockFrogspawnStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FUNGUS_BREAK" => Ok(Sound::BlockFungusBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FUNGUS_FALL" => Ok(Sound::BlockFungusFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FUNGUS_HIT" => Ok(Sound::BlockFungusHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FUNGUS_PLACE" => Ok(Sound::BlockFungusPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FUNGUS_STEP" => Ok(Sound::BlockFungusStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FURNACE_FIRE_CRACKLE" => Ok(Sound::BlockFurnaceFireCrackle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GILDED_BLACKSTONE_BREAK" => Ok(Sound::BlockGildedBlackstoneBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GILDED_BLACKSTONE_FALL" => Ok(Sound::BlockGildedBlackstoneFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GILDED_BLACKSTONE_HIT" => Ok(Sound::BlockGildedBlackstoneHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GILDED_BLACKSTONE_PLACE" => Ok(Sound::BlockGildedBlackstonePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GILDED_BLACKSTONE_STEP" => Ok(Sound::BlockGildedBlackstoneStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GLASS_BREAK" => Ok(Sound::BlockGlassBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GLASS_FALL" => Ok(Sound::BlockGlassFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GLASS_HIT" => Ok(Sound::BlockGlassHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GLASS_PLACE" => Ok(Sound::BlockGlassPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GLASS_STEP" => Ok(Sound::BlockGlassStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GRASS_BREAK" => Ok(Sound::BlockGrassBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GRASS_FALL" => Ok(Sound::BlockGrassFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GRASS_HIT" => Ok(Sound::BlockGrassHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GRASS_PLACE" => Ok(Sound::BlockGrassPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GRASS_STEP" => Ok(Sound::BlockGrassStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GRAVEL_BREAK" => Ok(Sound::BlockGravelBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GRAVEL_FALL" => Ok(Sound::BlockGravelFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GRAVEL_HIT" => Ok(Sound::BlockGravelHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GRAVEL_PLACE" => Ok(Sound::BlockGravelPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GRAVEL_STEP" => Ok(Sound::BlockGravelStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GRINDSTONE_USE" => Ok(Sound::BlockGrindstoneUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GROWING_PLANT_CROP" => Ok(Sound::BlockGrowingPlantCrop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HANGING_ROOTS_BREAK" => Ok(Sound::BlockHangingRootsBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HANGING_ROOTS_FALL" => Ok(Sound::BlockHangingRootsFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HANGING_ROOTS_HIT" => Ok(Sound::BlockHangingRootsHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HANGING_ROOTS_PLACE" => Ok(Sound::BlockHangingRootsPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HANGING_ROOTS_STEP" => Ok(Sound::BlockHangingRootsStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HANGING_SIGN_BREAK" => Ok(Sound::BlockHangingSignBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HANGING_SIGN_FALL" => Ok(Sound::BlockHangingSignFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HANGING_SIGN_HIT" => Ok(Sound::BlockHangingSignHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HANGING_SIGN_PLACE" => Ok(Sound::BlockHangingSignPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HANGING_SIGN_STEP" => Ok(Sound::BlockHangingSignStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HANGING_SIGN_WAXED_INTERACT_FAIL" => { + Ok(Sound::BlockHangingSignWaxedInteractFail { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_HEAVY_CORE_BREAK" => Ok(Sound::BlockHeavyCoreBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HEAVY_CORE_FALL" => Ok(Sound::BlockHeavyCoreFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HEAVY_CORE_HIT" => Ok(Sound::BlockHeavyCoreHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HEAVY_CORE_PLACE" => Ok(Sound::BlockHeavyCorePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HEAVY_CORE_STEP" => Ok(Sound::BlockHeavyCoreStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HONEY_BLOCK_BREAK" => Ok(Sound::BlockHoneyBlockBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HONEY_BLOCK_FALL" => Ok(Sound::BlockHoneyBlockFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HONEY_BLOCK_HIT" => Ok(Sound::BlockHoneyBlockHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HONEY_BLOCK_PLACE" => Ok(Sound::BlockHoneyBlockPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HONEY_BLOCK_SLIDE" => Ok(Sound::BlockHoneyBlockSlide { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HONEY_BLOCK_STEP" => Ok(Sound::BlockHoneyBlockStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_IRON_DOOR_CLOSE" => Ok(Sound::BlockIronDoorClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_IRON_DOOR_OPEN" => Ok(Sound::BlockIronDoorOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_IRON_TRAPDOOR_CLOSE" => Ok(Sound::BlockIronTrapdoorClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_IRON_TRAPDOOR_OPEN" => Ok(Sound::BlockIronTrapdoorOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LADDER_BREAK" => Ok(Sound::BlockLadderBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LADDER_FALL" => Ok(Sound::BlockLadderFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LADDER_HIT" => Ok(Sound::BlockLadderHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LADDER_PLACE" => Ok(Sound::BlockLadderPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LADDER_STEP" => Ok(Sound::BlockLadderStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LANTERN_BREAK" => Ok(Sound::BlockLanternBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LANTERN_FALL" => Ok(Sound::BlockLanternFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LANTERN_HIT" => Ok(Sound::BlockLanternHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LANTERN_PLACE" => Ok(Sound::BlockLanternPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LANTERN_STEP" => Ok(Sound::BlockLanternStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LARGE_AMETHYST_BUD_BREAK" => Ok(Sound::BlockLargeAmethystBudBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LARGE_AMETHYST_BUD_PLACE" => Ok(Sound::BlockLargeAmethystBudPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LAVA_AMBIENT" => Ok(Sound::BlockLavaAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LAVA_EXTINGUISH" => Ok(Sound::BlockLavaExtinguish { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LAVA_POP" => Ok(Sound::BlockLavaPop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LEVER_CLICK" => Ok(Sound::BlockLeverClick { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LILY_PAD_PLACE" => Ok(Sound::BlockLilyPadPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LODESTONE_BREAK" => Ok(Sound::BlockLodestoneBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LODESTONE_FALL" => Ok(Sound::BlockLodestoneFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LODESTONE_HIT" => Ok(Sound::BlockLodestoneHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LODESTONE_PLACE" => Ok(Sound::BlockLodestonePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LODESTONE_STEP" => Ok(Sound::BlockLodestoneStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MANGROVE_ROOTS_BREAK" => Ok(Sound::BlockMangroveRootsBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MANGROVE_ROOTS_FALL" => Ok(Sound::BlockMangroveRootsFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MANGROVE_ROOTS_HIT" => Ok(Sound::BlockMangroveRootsHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MANGROVE_ROOTS_PLACE" => Ok(Sound::BlockMangroveRootsPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MANGROVE_ROOTS_STEP" => Ok(Sound::BlockMangroveRootsStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MEDIUM_AMETHYST_BUD_BREAK" => Ok(Sound::BlockMediumAmethystBudBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MEDIUM_AMETHYST_BUD_PLACE" => Ok(Sound::BlockMediumAmethystBudPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_METAL_BREAK" => Ok(Sound::BlockMetalBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_METAL_FALL" => Ok(Sound::BlockMetalFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_METAL_HIT" => Ok(Sound::BlockMetalHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_METAL_PLACE" => Ok(Sound::BlockMetalPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_METAL_PRESSURE_PLATE_CLICK_OFF" => Ok(Sound::BlockMetalPressurePlateClickOff { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_METAL_PRESSURE_PLATE_CLICK_ON" => Ok(Sound::BlockMetalPressurePlateClickOn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_METAL_STEP" => Ok(Sound::BlockMetalStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MOSS_BREAK" => Ok(Sound::BlockMossBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MOSS_CARPET_BREAK" => Ok(Sound::BlockMossCarpetBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MOSS_CARPET_FALL" => Ok(Sound::BlockMossCarpetFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MOSS_CARPET_HIT" => Ok(Sound::BlockMossCarpetHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MOSS_CARPET_PLACE" => Ok(Sound::BlockMossCarpetPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MOSS_CARPET_STEP" => Ok(Sound::BlockMossCarpetStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MOSS_FALL" => Ok(Sound::BlockMossFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MOSS_HIT" => Ok(Sound::BlockMossHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MOSS_PLACE" => Ok(Sound::BlockMossPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MOSS_STEP" => Ok(Sound::BlockMossStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUDDY_MANGROVE_ROOTS_BREAK" => Ok(Sound::BlockMuddyMangroveRootsBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUDDY_MANGROVE_ROOTS_FALL" => Ok(Sound::BlockMuddyMangroveRootsFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUDDY_MANGROVE_ROOTS_HIT" => Ok(Sound::BlockMuddyMangroveRootsHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUDDY_MANGROVE_ROOTS_PLACE" => Ok(Sound::BlockMuddyMangroveRootsPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUDDY_MANGROVE_ROOTS_STEP" => Ok(Sound::BlockMuddyMangroveRootsStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUD_BREAK" => Ok(Sound::BlockMudBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUD_BRICKS_BREAK" => Ok(Sound::BlockMudBricksBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUD_BRICKS_FALL" => Ok(Sound::BlockMudBricksFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUD_BRICKS_HIT" => Ok(Sound::BlockMudBricksHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUD_BRICKS_PLACE" => Ok(Sound::BlockMudBricksPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUD_BRICKS_STEP" => Ok(Sound::BlockMudBricksStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUD_FALL" => Ok(Sound::BlockMudFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUD_HIT" => Ok(Sound::BlockMudHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUD_PLACE" => Ok(Sound::BlockMudPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUD_STEP" => Ok(Sound::BlockMudStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHERITE_BLOCK_BREAK" => Ok(Sound::BlockNetheriteBlockBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHERITE_BLOCK_FALL" => Ok(Sound::BlockNetheriteBlockFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHERITE_BLOCK_HIT" => Ok(Sound::BlockNetheriteBlockHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHERITE_BLOCK_PLACE" => Ok(Sound::BlockNetheriteBlockPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHERITE_BLOCK_STEP" => Ok(Sound::BlockNetheriteBlockStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHERRACK_BREAK" => Ok(Sound::BlockNetherrackBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHERRACK_FALL" => Ok(Sound::BlockNetherrackFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHERRACK_HIT" => Ok(Sound::BlockNetherrackHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHERRACK_PLACE" => Ok(Sound::BlockNetherrackPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHERRACK_STEP" => Ok(Sound::BlockNetherrackStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_BRICKS_BREAK" => Ok(Sound::BlockNetherBricksBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_BRICKS_FALL" => Ok(Sound::BlockNetherBricksFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_BRICKS_HIT" => Ok(Sound::BlockNetherBricksHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_BRICKS_PLACE" => Ok(Sound::BlockNetherBricksPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_BRICKS_STEP" => Ok(Sound::BlockNetherBricksStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_GOLD_ORE_BREAK" => Ok(Sound::BlockNetherGoldOreBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_GOLD_ORE_FALL" => Ok(Sound::BlockNetherGoldOreFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_GOLD_ORE_HIT" => Ok(Sound::BlockNetherGoldOreHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_GOLD_ORE_PLACE" => Ok(Sound::BlockNetherGoldOrePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_GOLD_ORE_STEP" => Ok(Sound::BlockNetherGoldOreStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_ORE_BREAK" => Ok(Sound::BlockNetherOreBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_ORE_FALL" => Ok(Sound::BlockNetherOreFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_ORE_HIT" => Ok(Sound::BlockNetherOreHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_ORE_PLACE" => Ok(Sound::BlockNetherOrePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_ORE_STEP" => Ok(Sound::BlockNetherOreStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_SPROUTS_BREAK" => Ok(Sound::BlockNetherSproutsBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_SPROUTS_FALL" => Ok(Sound::BlockNetherSproutsFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_SPROUTS_HIT" => Ok(Sound::BlockNetherSproutsHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_SPROUTS_PLACE" => Ok(Sound::BlockNetherSproutsPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_SPROUTS_STEP" => Ok(Sound::BlockNetherSproutsStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WART_BREAK" => Ok(Sound::BlockNetherWartBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_BREAK" => Ok(Sound::BlockNetherWoodBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_BUTTON_CLICK_OFF" => Ok(Sound::BlockNetherWoodButtonClickOff { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_BUTTON_CLICK_ON" => Ok(Sound::BlockNetherWoodButtonClickOn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_DOOR_CLOSE" => Ok(Sound::BlockNetherWoodDoorClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_DOOR_OPEN" => Ok(Sound::BlockNetherWoodDoorOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_FALL" => Ok(Sound::BlockNetherWoodFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_FENCE_GATE_CLOSE" => Ok(Sound::BlockNetherWoodFenceGateClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_FENCE_GATE_OPEN" => Ok(Sound::BlockNetherWoodFenceGateOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_HANGING_SIGN_BREAK" => Ok(Sound::BlockNetherWoodHangingSignBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_HANGING_SIGN_FALL" => Ok(Sound::BlockNetherWoodHangingSignFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_HANGING_SIGN_HIT" => Ok(Sound::BlockNetherWoodHangingSignHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_HANGING_SIGN_PLACE" => Ok(Sound::BlockNetherWoodHangingSignPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_HANGING_SIGN_STEP" => Ok(Sound::BlockNetherWoodHangingSignStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_HIT" => Ok(Sound::BlockNetherWoodHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_PLACE" => Ok(Sound::BlockNetherWoodPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_PRESSURE_PLATE_CLICK_OFF" => { + Ok(Sound::BlockNetherWoodPressurePlateClickOff { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_NETHER_WOOD_PRESSURE_PLATE_CLICK_ON" => { + Ok(Sound::BlockNetherWoodPressurePlateClickOn { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_NETHER_WOOD_STEP" => Ok(Sound::BlockNetherWoodStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_TRAPDOOR_CLOSE" => Ok(Sound::BlockNetherWoodTrapdoorClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_TRAPDOOR_OPEN" => Ok(Sound::BlockNetherWoodTrapdoorOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_BANJO" => Ok(Sound::BlockNoteBlockBanjo { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_BASEDRUM" => Ok(Sound::BlockNoteBlockBasedrum { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_BASS" => Ok(Sound::BlockNoteBlockBass { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_BELL" => Ok(Sound::BlockNoteBlockBell { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_BIT" => Ok(Sound::BlockNoteBlockBit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_CHIME" => Ok(Sound::BlockNoteBlockChime { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_COW_BELL" => Ok(Sound::BlockNoteBlockCowBell { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_DIDGERIDOO" => Ok(Sound::BlockNoteBlockDidgeridoo { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_FLUTE" => Ok(Sound::BlockNoteBlockFlute { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_GUITAR" => Ok(Sound::BlockNoteBlockGuitar { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_HARP" => Ok(Sound::BlockNoteBlockHarp { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_HAT" => Ok(Sound::BlockNoteBlockHat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_IMITATE_CREEPER" => Ok(Sound::BlockNoteBlockImitateCreeper { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_IMITATE_ENDER_DRAGON" => { + Ok(Sound::BlockNoteBlockImitateEnderDragon { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_NOTE_BLOCK_IMITATE_PIGLIN" => Ok(Sound::BlockNoteBlockImitatePiglin { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_IMITATE_SKELETON" => Ok(Sound::BlockNoteBlockImitateSkeleton { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_IMITATE_WITHER_SKELETON" => { + Ok(Sound::BlockNoteBlockImitateWitherSkeleton { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_NOTE_BLOCK_IMITATE_ZOMBIE" => Ok(Sound::BlockNoteBlockImitateZombie { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_IRON_XYLOPHONE" => Ok(Sound::BlockNoteBlockIronXylophone { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_PLING" => Ok(Sound::BlockNoteBlockPling { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_SNARE" => Ok(Sound::BlockNoteBlockSnare { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_XYLOPHONE" => Ok(Sound::BlockNoteBlockXylophone { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NYLIUM_BREAK" => Ok(Sound::BlockNyliumBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NYLIUM_FALL" => Ok(Sound::BlockNyliumFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NYLIUM_HIT" => Ok(Sound::BlockNyliumHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NYLIUM_PLACE" => Ok(Sound::BlockNyliumPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NYLIUM_STEP" => Ok(Sound::BlockNyliumStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PACKED_MUD_BREAK" => Ok(Sound::BlockPackedMudBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PACKED_MUD_FALL" => Ok(Sound::BlockPackedMudFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PACKED_MUD_HIT" => Ok(Sound::BlockPackedMudHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PACKED_MUD_PLACE" => Ok(Sound::BlockPackedMudPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PACKED_MUD_STEP" => Ok(Sound::BlockPackedMudStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PINK_PETALS_BREAK" => Ok(Sound::BlockPinkPetalsBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PINK_PETALS_FALL" => Ok(Sound::BlockPinkPetalsFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PINK_PETALS_HIT" => Ok(Sound::BlockPinkPetalsHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PINK_PETALS_PLACE" => Ok(Sound::BlockPinkPetalsPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PINK_PETALS_STEP" => Ok(Sound::BlockPinkPetalsStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PISTON_CONTRACT" => Ok(Sound::BlockPistonContract { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PISTON_EXTEND" => Ok(Sound::BlockPistonExtend { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POINTED_DRIPSTONE_BREAK" => Ok(Sound::BlockPointedDripstoneBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POINTED_DRIPSTONE_DRIP_LAVA" => Ok(Sound::BlockPointedDripstoneDripLava { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POINTED_DRIPSTONE_DRIP_LAVA_INTO_CAULDRON" => { + Ok(Sound::BlockPointedDripstoneDripLavaIntoCauldron { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_POINTED_DRIPSTONE_DRIP_WATER" => Ok(Sound::BlockPointedDripstoneDripWater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POINTED_DRIPSTONE_DRIP_WATER_INTO_CAULDRON" => { + Ok(Sound::BlockPointedDripstoneDripWaterIntoCauldron { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_POINTED_DRIPSTONE_FALL" => Ok(Sound::BlockPointedDripstoneFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POINTED_DRIPSTONE_HIT" => Ok(Sound::BlockPointedDripstoneHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POINTED_DRIPSTONE_LAND" => Ok(Sound::BlockPointedDripstoneLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POINTED_DRIPSTONE_PLACE" => Ok(Sound::BlockPointedDripstonePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POINTED_DRIPSTONE_STEP" => Ok(Sound::BlockPointedDripstoneStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POLISHED_DEEPSLATE_BREAK" => Ok(Sound::BlockPolishedDeepslateBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POLISHED_DEEPSLATE_FALL" => Ok(Sound::BlockPolishedDeepslateFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POLISHED_DEEPSLATE_HIT" => Ok(Sound::BlockPolishedDeepslateHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POLISHED_DEEPSLATE_PLACE" => Ok(Sound::BlockPolishedDeepslatePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POLISHED_DEEPSLATE_STEP" => Ok(Sound::BlockPolishedDeepslateStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POLISHED_TUFF_BREAK" => Ok(Sound::BlockPolishedTuffBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POLISHED_TUFF_FALL" => Ok(Sound::BlockPolishedTuffFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POLISHED_TUFF_HIT" => Ok(Sound::BlockPolishedTuffHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POLISHED_TUFF_PLACE" => Ok(Sound::BlockPolishedTuffPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POLISHED_TUFF_STEP" => Ok(Sound::BlockPolishedTuffStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PORTAL_AMBIENT" => Ok(Sound::BlockPortalAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PORTAL_TRAVEL" => Ok(Sound::BlockPortalTravel { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PORTAL_TRIGGER" => Ok(Sound::BlockPortalTrigger { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POWDER_SNOW_BREAK" => Ok(Sound::BlockPowderSnowBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POWDER_SNOW_FALL" => Ok(Sound::BlockPowderSnowFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POWDER_SNOW_HIT" => Ok(Sound::BlockPowderSnowHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POWDER_SNOW_PLACE" => Ok(Sound::BlockPowderSnowPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POWDER_SNOW_STEP" => Ok(Sound::BlockPowderSnowStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PUMPKIN_CARVE" => Ok(Sound::BlockPumpkinCarve { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_REDSTONE_TORCH_BURNOUT" => Ok(Sound::BlockRedstoneTorchBurnout { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_RESPAWN_ANCHOR_AMBIENT" => Ok(Sound::BlockRespawnAnchorAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_RESPAWN_ANCHOR_CHARGE" => Ok(Sound::BlockRespawnAnchorCharge { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_RESPAWN_ANCHOR_DEPLETE" => Ok(Sound::BlockRespawnAnchorDeplete { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_RESPAWN_ANCHOR_SET_SPAWN" => Ok(Sound::BlockRespawnAnchorSetSpawn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ROOTED_DIRT_BREAK" => Ok(Sound::BlockRootedDirtBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ROOTED_DIRT_FALL" => Ok(Sound::BlockRootedDirtFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ROOTED_DIRT_HIT" => Ok(Sound::BlockRootedDirtHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ROOTED_DIRT_PLACE" => Ok(Sound::BlockRootedDirtPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ROOTED_DIRT_STEP" => Ok(Sound::BlockRootedDirtStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ROOTS_BREAK" => Ok(Sound::BlockRootsBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ROOTS_FALL" => Ok(Sound::BlockRootsFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ROOTS_HIT" => Ok(Sound::BlockRootsHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ROOTS_PLACE" => Ok(Sound::BlockRootsPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ROOTS_STEP" => Ok(Sound::BlockRootsStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SAND_BREAK" => Ok(Sound::BlockSandBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SAND_FALL" => Ok(Sound::BlockSandFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SAND_HIT" => Ok(Sound::BlockSandHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SAND_PLACE" => Ok(Sound::BlockSandPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SAND_STEP" => Ok(Sound::BlockSandStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCAFFOLDING_BREAK" => Ok(Sound::BlockScaffoldingBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCAFFOLDING_FALL" => Ok(Sound::BlockScaffoldingFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCAFFOLDING_HIT" => Ok(Sound::BlockScaffoldingHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCAFFOLDING_PLACE" => Ok(Sound::BlockScaffoldingPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCAFFOLDING_STEP" => Ok(Sound::BlockScaffoldingStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_BREAK" => Ok(Sound::BlockSculkBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_CATALYST_BLOOM" => Ok(Sound::BlockSculkCatalystBloom { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_CATALYST_BREAK" => Ok(Sound::BlockSculkCatalystBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_CATALYST_FALL" => Ok(Sound::BlockSculkCatalystFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_CATALYST_HIT" => Ok(Sound::BlockSculkCatalystHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_CATALYST_PLACE" => Ok(Sound::BlockSculkCatalystPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_CATALYST_STEP" => Ok(Sound::BlockSculkCatalystStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_CHARGE" => Ok(Sound::BlockSculkCharge { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_FALL" => Ok(Sound::BlockSculkFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_HIT" => Ok(Sound::BlockSculkHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_PLACE" => Ok(Sound::BlockSculkPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SENSOR_BREAK" => Ok(Sound::BlockSculkSensorBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SENSOR_CLICKING" => Ok(Sound::BlockSculkSensorClicking { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SENSOR_CLICKING_STOP" => Ok(Sound::BlockSculkSensorClickingStop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SENSOR_FALL" => Ok(Sound::BlockSculkSensorFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SENSOR_HIT" => Ok(Sound::BlockSculkSensorHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SENSOR_PLACE" => Ok(Sound::BlockSculkSensorPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SENSOR_STEP" => Ok(Sound::BlockSculkSensorStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SHRIEKER_BREAK" => Ok(Sound::BlockSculkShriekerBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SHRIEKER_FALL" => Ok(Sound::BlockSculkShriekerFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SHRIEKER_HIT" => Ok(Sound::BlockSculkShriekerHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SHRIEKER_PLACE" => Ok(Sound::BlockSculkShriekerPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SHRIEKER_SHRIEK" => Ok(Sound::BlockSculkShriekerShriek { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SHRIEKER_STEP" => Ok(Sound::BlockSculkShriekerStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SPREAD" => Ok(Sound::BlockSculkSpread { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_STEP" => Ok(Sound::BlockSculkStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_VEIN_BREAK" => Ok(Sound::BlockSculkVeinBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_VEIN_FALL" => Ok(Sound::BlockSculkVeinFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_VEIN_HIT" => Ok(Sound::BlockSculkVeinHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_VEIN_PLACE" => Ok(Sound::BlockSculkVeinPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_VEIN_STEP" => Ok(Sound::BlockSculkVeinStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SHROOMLIGHT_BREAK" => Ok(Sound::BlockShroomlightBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SHROOMLIGHT_FALL" => Ok(Sound::BlockShroomlightFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SHROOMLIGHT_HIT" => Ok(Sound::BlockShroomlightHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SHROOMLIGHT_PLACE" => Ok(Sound::BlockShroomlightPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SHROOMLIGHT_STEP" => Ok(Sound::BlockShroomlightStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SHULKER_BOX_CLOSE" => Ok(Sound::BlockShulkerBoxClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SHULKER_BOX_OPEN" => Ok(Sound::BlockShulkerBoxOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SIGN_WAXED_INTERACT_FAIL" => Ok(Sound::BlockSignWaxedInteractFail { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SLIME_BLOCK_BREAK" => Ok(Sound::BlockSlimeBlockBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SLIME_BLOCK_FALL" => Ok(Sound::BlockSlimeBlockFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SLIME_BLOCK_HIT" => Ok(Sound::BlockSlimeBlockHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SLIME_BLOCK_PLACE" => Ok(Sound::BlockSlimeBlockPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SLIME_BLOCK_STEP" => Ok(Sound::BlockSlimeBlockStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SMALL_AMETHYST_BUD_BREAK" => Ok(Sound::BlockSmallAmethystBudBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SMALL_AMETHYST_BUD_PLACE" => Ok(Sound::BlockSmallAmethystBudPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SMALL_DRIPLEAF_BREAK" => Ok(Sound::BlockSmallDripleafBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SMALL_DRIPLEAF_FALL" => Ok(Sound::BlockSmallDripleafFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SMALL_DRIPLEAF_HIT" => Ok(Sound::BlockSmallDripleafHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SMALL_DRIPLEAF_PLACE" => Ok(Sound::BlockSmallDripleafPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SMALL_DRIPLEAF_STEP" => Ok(Sound::BlockSmallDripleafStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SMITHING_TABLE_USE" => Ok(Sound::BlockSmithingTableUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SMOKER_SMOKE" => Ok(Sound::BlockSmokerSmoke { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SNIFFER_EGG_CRACK" => Ok(Sound::BlockSnifferEggCrack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SNIFFER_EGG_HATCH" => Ok(Sound::BlockSnifferEggHatch { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SNIFFER_EGG_PLOP" => Ok(Sound::BlockSnifferEggPlop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SNOW_BREAK" => Ok(Sound::BlockSnowBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SNOW_FALL" => Ok(Sound::BlockSnowFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SNOW_HIT" => Ok(Sound::BlockSnowHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SNOW_PLACE" => Ok(Sound::BlockSnowPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SNOW_STEP" => Ok(Sound::BlockSnowStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SOUL_SAND_BREAK" => Ok(Sound::BlockSoulSandBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SOUL_SAND_FALL" => Ok(Sound::BlockSoulSandFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SOUL_SAND_HIT" => Ok(Sound::BlockSoulSandHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SOUL_SAND_PLACE" => Ok(Sound::BlockSoulSandPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SOUL_SAND_STEP" => Ok(Sound::BlockSoulSandStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SOUL_SOIL_BREAK" => Ok(Sound::BlockSoulSoilBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SOUL_SOIL_FALL" => Ok(Sound::BlockSoulSoilFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SOUL_SOIL_HIT" => Ok(Sound::BlockSoulSoilHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SOUL_SOIL_PLACE" => Ok(Sound::BlockSoulSoilPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SOUL_SOIL_STEP" => Ok(Sound::BlockSoulSoilStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SPONGE_ABSORB" => Ok(Sound::BlockSpongeAbsorb { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SPONGE_BREAK" => Ok(Sound::BlockSpongeBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SPONGE_FALL" => Ok(Sound::BlockSpongeFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SPONGE_HIT" => Ok(Sound::BlockSpongeHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SPONGE_PLACE" => Ok(Sound::BlockSpongePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SPONGE_STEP" => Ok(Sound::BlockSpongeStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SPORE_BLOSSOM_BREAK" => Ok(Sound::BlockSporeBlossomBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SPORE_BLOSSOM_FALL" => Ok(Sound::BlockSporeBlossomFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SPORE_BLOSSOM_HIT" => Ok(Sound::BlockSporeBlossomHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SPORE_BLOSSOM_PLACE" => Ok(Sound::BlockSporeBlossomPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SPORE_BLOSSOM_STEP" => Ok(Sound::BlockSporeBlossomStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STEM_BREAK" => Ok(Sound::BlockStemBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STEM_FALL" => Ok(Sound::BlockStemFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STEM_HIT" => Ok(Sound::BlockStemHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STEM_PLACE" => Ok(Sound::BlockStemPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STEM_STEP" => Ok(Sound::BlockStemStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STONE_BREAK" => Ok(Sound::BlockStoneBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STONE_BUTTON_CLICK_OFF" => Ok(Sound::BlockStoneButtonClickOff { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STONE_BUTTON_CLICK_ON" => Ok(Sound::BlockStoneButtonClickOn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STONE_FALL" => Ok(Sound::BlockStoneFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STONE_HIT" => Ok(Sound::BlockStoneHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STONE_PLACE" => Ok(Sound::BlockStonePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STONE_PRESSURE_PLATE_CLICK_OFF" => Ok(Sound::BlockStonePressurePlateClickOff { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STONE_PRESSURE_PLATE_CLICK_ON" => Ok(Sound::BlockStonePressurePlateClickOn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STONE_STEP" => Ok(Sound::BlockStoneStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SUSPICIOUS_GRAVEL_BREAK" => Ok(Sound::BlockSuspiciousGravelBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SUSPICIOUS_GRAVEL_FALL" => Ok(Sound::BlockSuspiciousGravelFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SUSPICIOUS_GRAVEL_HIT" => Ok(Sound::BlockSuspiciousGravelHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SUSPICIOUS_GRAVEL_PLACE" => Ok(Sound::BlockSuspiciousGravelPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SUSPICIOUS_GRAVEL_STEP" => Ok(Sound::BlockSuspiciousGravelStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SUSPICIOUS_SAND_BREAK" => Ok(Sound::BlockSuspiciousSandBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SUSPICIOUS_SAND_FALL" => Ok(Sound::BlockSuspiciousSandFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SUSPICIOUS_SAND_HIT" => Ok(Sound::BlockSuspiciousSandHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SUSPICIOUS_SAND_PLACE" => Ok(Sound::BlockSuspiciousSandPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SUSPICIOUS_SAND_STEP" => Ok(Sound::BlockSuspiciousSandStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SWEET_BERRY_BUSH_BREAK" => Ok(Sound::BlockSweetBerryBushBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SWEET_BERRY_BUSH_PICK_BERRIES" => Ok(Sound::BlockSweetBerryBushPickBerries { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SWEET_BERRY_BUSH_PLACE" => Ok(Sound::BlockSweetBerryBushPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_ABOUT_TO_SPAWN_ITEM" => { + Ok(Sound::BlockTrialSpawnerAboutToSpawnItem { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_TRIAL_SPAWNER_AMBIENT" => Ok(Sound::BlockTrialSpawnerAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_AMBIENT_OMINOUS" => Ok(Sound::BlockTrialSpawnerAmbientOminous { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_BREAK" => Ok(Sound::BlockTrialSpawnerBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_CLOSE_SHUTTER" => Ok(Sound::BlockTrialSpawnerCloseShutter { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_DETECT_PLAYER" => Ok(Sound::BlockTrialSpawnerDetectPlayer { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_EJECT_ITEM" => Ok(Sound::BlockTrialSpawnerEjectItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_FALL" => Ok(Sound::BlockTrialSpawnerFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_HIT" => Ok(Sound::BlockTrialSpawnerHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_OMINOUS_ACTIVATE" => Ok(Sound::BlockTrialSpawnerOminousActivate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_OPEN_SHUTTER" => Ok(Sound::BlockTrialSpawnerOpenShutter { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_PLACE" => Ok(Sound::BlockTrialSpawnerPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_SPAWN_ITEM" => Ok(Sound::BlockTrialSpawnerSpawnItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_SPAWN_ITEM_BEGIN" => Ok(Sound::BlockTrialSpawnerSpawnItemBegin { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_SPAWN_MOB" => Ok(Sound::BlockTrialSpawnerSpawnMob { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_STEP" => Ok(Sound::BlockTrialSpawnerStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIPWIRE_ATTACH" => Ok(Sound::BlockTripwireAttach { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIPWIRE_CLICK_OFF" => Ok(Sound::BlockTripwireClickOff { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIPWIRE_CLICK_ON" => Ok(Sound::BlockTripwireClickOn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIPWIRE_DETACH" => Ok(Sound::BlockTripwireDetach { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TUFF_BREAK" => Ok(Sound::BlockTuffBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TUFF_BRICKS_BREAK" => Ok(Sound::BlockTuffBricksBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TUFF_BRICKS_FALL" => Ok(Sound::BlockTuffBricksFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TUFF_BRICKS_HIT" => Ok(Sound::BlockTuffBricksHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TUFF_BRICKS_PLACE" => Ok(Sound::BlockTuffBricksPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TUFF_BRICKS_STEP" => Ok(Sound::BlockTuffBricksStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TUFF_FALL" => Ok(Sound::BlockTuffFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TUFF_HIT" => Ok(Sound::BlockTuffHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TUFF_PLACE" => Ok(Sound::BlockTuffPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TUFF_STEP" => Ok(Sound::BlockTuffStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_ACTIVATE" => Ok(Sound::BlockVaultActivate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_AMBIENT" => Ok(Sound::BlockVaultAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_BREAK" => Ok(Sound::BlockVaultBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_CLOSE_SHUTTER" => Ok(Sound::BlockVaultCloseShutter { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_DEACTIVATE" => Ok(Sound::BlockVaultDeactivate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_EJECT_ITEM" => Ok(Sound::BlockVaultEjectItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_FALL" => Ok(Sound::BlockVaultFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_HIT" => Ok(Sound::BlockVaultHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_INSERT_ITEM" => Ok(Sound::BlockVaultInsertItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_INSERT_ITEM_FAIL" => Ok(Sound::BlockVaultInsertItemFail { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_OPEN_SHUTTER" => Ok(Sound::BlockVaultOpenShutter { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_PLACE" => Ok(Sound::BlockVaultPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_REJECT_REWARDED_PLAYER" => Ok(Sound::BlockVaultRejectRewardedPlayer { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_STEP" => Ok(Sound::BlockVaultStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VINE_BREAK" => Ok(Sound::BlockVineBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VINE_FALL" => Ok(Sound::BlockVineFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VINE_HIT" => Ok(Sound::BlockVineHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VINE_PLACE" => Ok(Sound::BlockVinePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VINE_STEP" => Ok(Sound::BlockVineStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WART_BLOCK_BREAK" => Ok(Sound::BlockWartBlockBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WART_BLOCK_FALL" => Ok(Sound::BlockWartBlockFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WART_BLOCK_HIT" => Ok(Sound::BlockWartBlockHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WART_BLOCK_PLACE" => Ok(Sound::BlockWartBlockPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WART_BLOCK_STEP" => Ok(Sound::BlockWartBlockStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WATER_AMBIENT" => Ok(Sound::BlockWaterAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WEEPING_VINES_BREAK" => Ok(Sound::BlockWeepingVinesBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WEEPING_VINES_FALL" => Ok(Sound::BlockWeepingVinesFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WEEPING_VINES_HIT" => Ok(Sound::BlockWeepingVinesHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WEEPING_VINES_PLACE" => Ok(Sound::BlockWeepingVinesPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WEEPING_VINES_STEP" => Ok(Sound::BlockWeepingVinesStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WET_GRASS_BREAK" => Ok(Sound::BlockWetGrassBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WET_GRASS_FALL" => Ok(Sound::BlockWetGrassFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WET_GRASS_HIT" => Ok(Sound::BlockWetGrassHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WET_GRASS_PLACE" => Ok(Sound::BlockWetGrassPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WET_GRASS_STEP" => Ok(Sound::BlockWetGrassStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WET_SPONGE_BREAK" => Ok(Sound::BlockWetSpongeBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WET_SPONGE_DRIES" => Ok(Sound::BlockWetSpongeDries { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WET_SPONGE_FALL" => Ok(Sound::BlockWetSpongeFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WET_SPONGE_HIT" => Ok(Sound::BlockWetSpongeHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WET_SPONGE_PLACE" => Ok(Sound::BlockWetSpongePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WET_SPONGE_STEP" => Ok(Sound::BlockWetSpongeStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOODEN_BUTTON_CLICK_OFF" => Ok(Sound::BlockWoodenButtonClickOff { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOODEN_BUTTON_CLICK_ON" => Ok(Sound::BlockWoodenButtonClickOn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOODEN_DOOR_CLOSE" => Ok(Sound::BlockWoodenDoorClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOODEN_DOOR_OPEN" => Ok(Sound::BlockWoodenDoorOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOODEN_PRESSURE_PLATE_CLICK_OFF" => { + Ok(Sound::BlockWoodenPressurePlateClickOff { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_WOODEN_PRESSURE_PLATE_CLICK_ON" => Ok(Sound::BlockWoodenPressurePlateClickOn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOODEN_TRAPDOOR_CLOSE" => Ok(Sound::BlockWoodenTrapdoorClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOODEN_TRAPDOOR_OPEN" => Ok(Sound::BlockWoodenTrapdoorOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOOD_BREAK" => Ok(Sound::BlockWoodBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOOD_FALL" => Ok(Sound::BlockWoodFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOOD_HIT" => Ok(Sound::BlockWoodHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOOD_PLACE" => Ok(Sound::BlockWoodPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOOD_STEP" => Ok(Sound::BlockWoodStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOOL_BREAK" => Ok(Sound::BlockWoolBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOOL_FALL" => Ok(Sound::BlockWoolFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOOL_HIT" => Ok(Sound::BlockWoolHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOOL_PLACE" => Ok(Sound::BlockWoolPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOOL_STEP" => Ok(Sound::BlockWoolStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENCHANT_THORNS_HIT" => Ok(Sound::EnchantThornsHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ALLAY_AMBIENT_WITHOUT_ITEM" => Ok(Sound::EntityAllayAmbientWithoutItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ALLAY_AMBIENT_WITH_ITEM" => Ok(Sound::EntityAllayAmbientWithItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ALLAY_DEATH" => Ok(Sound::EntityAllayDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ALLAY_HURT" => Ok(Sound::EntityAllayHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ALLAY_ITEM_GIVEN" => Ok(Sound::EntityAllayItemGiven { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ALLAY_ITEM_TAKEN" => Ok(Sound::EntityAllayItemTaken { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ALLAY_ITEM_THROWN" => Ok(Sound::EntityAllayItemThrown { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_AMBIENT" => Ok(Sound::EntityArmadilloAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_BRUSH" => Ok(Sound::EntityArmadilloBrush { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_DEATH" => Ok(Sound::EntityArmadilloDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_EAT" => Ok(Sound::EntityArmadilloEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_HURT" => Ok(Sound::EntityArmadilloHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_HURT_REDUCED" => Ok(Sound::EntityArmadilloHurtReduced { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_LAND" => Ok(Sound::EntityArmadilloLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_PEEK" => Ok(Sound::EntityArmadilloPeek { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_ROLL" => Ok(Sound::EntityArmadilloRoll { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_SCUTE_DROP" => Ok(Sound::EntityArmadilloScuteDrop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_STEP" => Ok(Sound::EntityArmadilloStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_UNROLL_FINISH" => Ok(Sound::EntityArmadilloUnrollFinish { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_UNROLL_START" => Ok(Sound::EntityArmadilloUnrollStart { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMOR_STAND_BREAK" => Ok(Sound::EntityArmorStandBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMOR_STAND_FALL" => Ok(Sound::EntityArmorStandFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMOR_STAND_HIT" => Ok(Sound::EntityArmorStandHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMOR_STAND_PLACE" => Ok(Sound::EntityArmorStandPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARROW_HIT" => Ok(Sound::EntityArrowHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARROW_HIT_PLAYER" => Ok(Sound::EntityArrowHitPlayer { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARROW_SHOOT" => Ok(Sound::EntityArrowShoot { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_AXOLOTL_ATTACK" => Ok(Sound::EntityAxolotlAttack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_AXOLOTL_DEATH" => Ok(Sound::EntityAxolotlDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_AXOLOTL_HURT" => Ok(Sound::EntityAxolotlHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_AXOLOTL_IDLE_AIR" => Ok(Sound::EntityAxolotlIdleAir { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_AXOLOTL_IDLE_WATER" => Ok(Sound::EntityAxolotlIdleWater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_AXOLOTL_SPLASH" => Ok(Sound::EntityAxolotlSplash { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_AXOLOTL_SWIM" => Ok(Sound::EntityAxolotlSwim { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BAT_AMBIENT" => Ok(Sound::EntityBatAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BAT_DEATH" => Ok(Sound::EntityBatDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BAT_HURT" => Ok(Sound::EntityBatHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BAT_LOOP" => Ok(Sound::EntityBatLoop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BAT_TAKEOFF" => Ok(Sound::EntityBatTakeoff { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BEE_DEATH" => Ok(Sound::EntityBeeDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BEE_HURT" => Ok(Sound::EntityBeeHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BEE_LOOP" => Ok(Sound::EntityBeeLoop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BEE_LOOP_AGGRESSIVE" => Ok(Sound::EntityBeeLoopAggressive { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BEE_POLLINATE" => Ok(Sound::EntityBeePollinate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BEE_STING" => Ok(Sound::EntityBeeSting { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BLAZE_AMBIENT" => Ok(Sound::EntityBlazeAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BLAZE_BURN" => Ok(Sound::EntityBlazeBurn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BLAZE_DEATH" => Ok(Sound::EntityBlazeDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BLAZE_HURT" => Ok(Sound::EntityBlazeHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BLAZE_SHOOT" => Ok(Sound::EntityBlazeShoot { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BOAT_PADDLE_LAND" => Ok(Sound::EntityBoatPaddleLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BOAT_PADDLE_WATER" => Ok(Sound::EntityBoatPaddleWater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BOGGED_AMBIENT" => Ok(Sound::EntityBoggedAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BOGGED_DEATH" => Ok(Sound::EntityBoggedDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BOGGED_HURT" => Ok(Sound::EntityBoggedHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BOGGED_SHEAR" => Ok(Sound::EntityBoggedShear { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BOGGED_STEP" => Ok(Sound::EntityBoggedStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_CHARGE" => Ok(Sound::EntityBreezeCharge { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_DEATH" => Ok(Sound::EntityBreezeDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_DEFLECT" => Ok(Sound::EntityBreezeDeflect { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_HURT" => Ok(Sound::EntityBreezeHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_IDLE_AIR" => Ok(Sound::EntityBreezeIdleAir { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_IDLE_GROUND" => Ok(Sound::EntityBreezeIdleGround { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_INHALE" => Ok(Sound::EntityBreezeInhale { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_JUMP" => Ok(Sound::EntityBreezeJump { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_LAND" => Ok(Sound::EntityBreezeLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_SHOOT" => Ok(Sound::EntityBreezeShoot { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_SLIDE" => Ok(Sound::EntityBreezeSlide { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_WHIRL" => Ok(Sound::EntityBreezeWhirl { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_WIND_BURST" => Ok(Sound::EntityBreezeWindBurst { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAMEL_AMBIENT" => Ok(Sound::EntityCamelAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAMEL_DASH" => Ok(Sound::EntityCamelDash { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAMEL_DASH_READY" => Ok(Sound::EntityCamelDashReady { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAMEL_DEATH" => Ok(Sound::EntityCamelDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAMEL_EAT" => Ok(Sound::EntityCamelEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAMEL_HURT" => Ok(Sound::EntityCamelHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAMEL_SADDLE" => Ok(Sound::EntityCamelSaddle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAMEL_SIT" => Ok(Sound::EntityCamelSit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAMEL_STAND" => Ok(Sound::EntityCamelStand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAMEL_STEP" => Ok(Sound::EntityCamelStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAMEL_STEP_SAND" => Ok(Sound::EntityCamelStepSand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAT_AMBIENT" => Ok(Sound::EntityCatAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAT_BEG_FOR_FOOD" => Ok(Sound::EntityCatBegForFood { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAT_DEATH" => Ok(Sound::EntityCatDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAT_EAT" => Ok(Sound::EntityCatEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAT_HISS" => Ok(Sound::EntityCatHiss { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAT_HURT" => Ok(Sound::EntityCatHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAT_PURR" => Ok(Sound::EntityCatPurr { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAT_PURREOW" => Ok(Sound::EntityCatPurreow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAT_STRAY_AMBIENT" => Ok(Sound::EntityCatStrayAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CHICKEN_AMBIENT" => Ok(Sound::EntityChickenAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CHICKEN_DEATH" => Ok(Sound::EntityChickenDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CHICKEN_EGG" => Ok(Sound::EntityChickenEgg { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CHICKEN_HURT" => Ok(Sound::EntityChickenHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CHICKEN_STEP" => Ok(Sound::EntityChickenStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_COD_AMBIENT" => Ok(Sound::EntityCodAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_COD_DEATH" => Ok(Sound::EntityCodDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_COD_FLOP" => Ok(Sound::EntityCodFlop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_COD_HURT" => Ok(Sound::EntityCodHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_COW_AMBIENT" => Ok(Sound::EntityCowAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_COW_DEATH" => Ok(Sound::EntityCowDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_COW_HURT" => Ok(Sound::EntityCowHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_COW_MILK" => Ok(Sound::EntityCowMilk { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_COW_STEP" => Ok(Sound::EntityCowStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CREEPER_DEATH" => Ok(Sound::EntityCreeperDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CREEPER_HURT" => Ok(Sound::EntityCreeperHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CREEPER_PRIMED" => Ok(Sound::EntityCreeperPrimed { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DOLPHIN_AMBIENT" => Ok(Sound::EntityDolphinAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DOLPHIN_AMBIENT_WATER" => Ok(Sound::EntityDolphinAmbientWater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DOLPHIN_ATTACK" => Ok(Sound::EntityDolphinAttack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DOLPHIN_DEATH" => Ok(Sound::EntityDolphinDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DOLPHIN_EAT" => Ok(Sound::EntityDolphinEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DOLPHIN_HURT" => Ok(Sound::EntityDolphinHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DOLPHIN_JUMP" => Ok(Sound::EntityDolphinJump { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DOLPHIN_PLAY" => Ok(Sound::EntityDolphinPlay { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DOLPHIN_SPLASH" => Ok(Sound::EntityDolphinSplash { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DOLPHIN_SWIM" => Ok(Sound::EntityDolphinSwim { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DONKEY_AMBIENT" => Ok(Sound::EntityDonkeyAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DONKEY_ANGRY" => Ok(Sound::EntityDonkeyAngry { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DONKEY_CHEST" => Ok(Sound::EntityDonkeyChest { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DONKEY_DEATH" => Ok(Sound::EntityDonkeyDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DONKEY_EAT" => Ok(Sound::EntityDonkeyEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DONKEY_HURT" => Ok(Sound::EntityDonkeyHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DONKEY_JUMP" => Ok(Sound::EntityDonkeyJump { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DRAGON_FIREBALL_EXPLODE" => Ok(Sound::EntityDragonFireballExplode { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DROWNED_AMBIENT" => Ok(Sound::EntityDrownedAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DROWNED_AMBIENT_WATER" => Ok(Sound::EntityDrownedAmbientWater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DROWNED_DEATH" => Ok(Sound::EntityDrownedDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DROWNED_DEATH_WATER" => Ok(Sound::EntityDrownedDeathWater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DROWNED_HURT" => Ok(Sound::EntityDrownedHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DROWNED_HURT_WATER" => Ok(Sound::EntityDrownedHurtWater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DROWNED_SHOOT" => Ok(Sound::EntityDrownedShoot { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DROWNED_STEP" => Ok(Sound::EntityDrownedStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DROWNED_SWIM" => Ok(Sound::EntityDrownedSwim { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_EGG_THROW" => Ok(Sound::EntityEggThrow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ELDER_GUARDIAN_AMBIENT" => Ok(Sound::EntityElderGuardianAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ELDER_GUARDIAN_AMBIENT_LAND" => Ok(Sound::EntityElderGuardianAmbientLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ELDER_GUARDIAN_CURSE" => Ok(Sound::EntityElderGuardianCurse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ELDER_GUARDIAN_DEATH" => Ok(Sound::EntityElderGuardianDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ELDER_GUARDIAN_DEATH_LAND" => Ok(Sound::EntityElderGuardianDeathLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ELDER_GUARDIAN_FLOP" => Ok(Sound::EntityElderGuardianFlop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ELDER_GUARDIAN_HURT" => Ok(Sound::EntityElderGuardianHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ELDER_GUARDIAN_HURT_LAND" => Ok(Sound::EntityElderGuardianHurtLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDERMAN_AMBIENT" => Ok(Sound::EntityEndermanAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDERMAN_DEATH" => Ok(Sound::EntityEndermanDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDERMAN_HURT" => Ok(Sound::EntityEndermanHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDERMAN_SCREAM" => Ok(Sound::EntityEndermanScream { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDERMAN_STARE" => Ok(Sound::EntityEndermanStare { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDERMAN_TELEPORT" => Ok(Sound::EntityEndermanTeleport { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDERMITE_AMBIENT" => Ok(Sound::EntityEndermiteAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDERMITE_DEATH" => Ok(Sound::EntityEndermiteDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDERMITE_HURT" => Ok(Sound::EntityEndermiteHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDERMITE_STEP" => Ok(Sound::EntityEndermiteStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDER_DRAGON_AMBIENT" => Ok(Sound::EntityEnderDragonAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDER_DRAGON_DEATH" => Ok(Sound::EntityEnderDragonDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDER_DRAGON_FLAP" => Ok(Sound::EntityEnderDragonFlap { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDER_DRAGON_GROWL" => Ok(Sound::EntityEnderDragonGrowl { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDER_DRAGON_HURT" => Ok(Sound::EntityEnderDragonHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDER_DRAGON_SHOOT" => Ok(Sound::EntityEnderDragonShoot { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDER_EYE_DEATH" => Ok(Sound::EntityEnderEyeDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDER_EYE_LAUNCH" => Ok(Sound::EntityEnderEyeLaunch { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDER_PEARL_THROW" => Ok(Sound::EntityEnderPearlThrow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_EVOKER_AMBIENT" => Ok(Sound::EntityEvokerAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_EVOKER_CAST_SPELL" => Ok(Sound::EntityEvokerCastSpell { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_EVOKER_CELEBRATE" => Ok(Sound::EntityEvokerCelebrate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_EVOKER_DEATH" => Ok(Sound::EntityEvokerDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_EVOKER_FANGS_ATTACK" => Ok(Sound::EntityEvokerFangsAttack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_EVOKER_HURT" => Ok(Sound::EntityEvokerHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_EVOKER_PREPARE_ATTACK" => Ok(Sound::EntityEvokerPrepareAttack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_EVOKER_PREPARE_SUMMON" => Ok(Sound::EntityEvokerPrepareSummon { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_EVOKER_PREPARE_WOLOLO" => Ok(Sound::EntityEvokerPrepareWololo { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_EXPERIENCE_BOTTLE_THROW" => Ok(Sound::EntityExperienceBottleThrow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_EXPERIENCE_ORB_PICKUP" => Ok(Sound::EntityExperienceOrbPickup { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FIREWORK_ROCKET_BLAST" => Ok(Sound::EntityFireworkRocketBlast { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FIREWORK_ROCKET_BLAST_FAR" => Ok(Sound::EntityFireworkRocketBlastFar { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FIREWORK_ROCKET_LARGE_BLAST" => Ok(Sound::EntityFireworkRocketLargeBlast { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FIREWORK_ROCKET_LARGE_BLAST_FAR" => { + Ok(Sound::EntityFireworkRocketLargeBlastFar { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "ENTITY_FIREWORK_ROCKET_LAUNCH" => Ok(Sound::EntityFireworkRocketLaunch { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FIREWORK_ROCKET_SHOOT" => Ok(Sound::EntityFireworkRocketShoot { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FIREWORK_ROCKET_TWINKLE" => Ok(Sound::EntityFireworkRocketTwinkle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FIREWORK_ROCKET_TWINKLE_FAR" => Ok(Sound::EntityFireworkRocketTwinkleFar { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FISHING_BOBBER_RETRIEVE" => Ok(Sound::EntityFishingBobberRetrieve { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FISHING_BOBBER_SPLASH" => Ok(Sound::EntityFishingBobberSplash { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FISHING_BOBBER_THROW" => Ok(Sound::EntityFishingBobberThrow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FISH_SWIM" => Ok(Sound::EntityFishSwim { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FOX_AGGRO" => Ok(Sound::EntityFoxAggro { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FOX_AMBIENT" => Ok(Sound::EntityFoxAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FOX_BITE" => Ok(Sound::EntityFoxBite { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FOX_DEATH" => Ok(Sound::EntityFoxDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FOX_EAT" => Ok(Sound::EntityFoxEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FOX_HURT" => Ok(Sound::EntityFoxHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FOX_SCREECH" => Ok(Sound::EntityFoxScreech { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FOX_SLEEP" => Ok(Sound::EntityFoxSleep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FOX_SNIFF" => Ok(Sound::EntityFoxSniff { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FOX_SPIT" => Ok(Sound::EntityFoxSpit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FOX_TELEPORT" => Ok(Sound::EntityFoxTeleport { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FROG_AMBIENT" => Ok(Sound::EntityFrogAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FROG_DEATH" => Ok(Sound::EntityFrogDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FROG_EAT" => Ok(Sound::EntityFrogEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FROG_HURT" => Ok(Sound::EntityFrogHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FROG_LAY_SPAWN" => Ok(Sound::EntityFrogLaySpawn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FROG_LONG_JUMP" => Ok(Sound::EntityFrogLongJump { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FROG_STEP" => Ok(Sound::EntityFrogStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FROG_TONGUE" => Ok(Sound::EntityFrogTongue { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GENERIC_BIG_FALL" => Ok(Sound::EntityGenericBigFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GENERIC_BURN" => Ok(Sound::EntityGenericBurn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GENERIC_DEATH" => Ok(Sound::EntityGenericDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GENERIC_DRINK" => Ok(Sound::EntityGenericDrink { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GENERIC_EAT" => Ok(Sound::EntityGenericEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GENERIC_EXPLODE" => Ok(Sound::EntityGenericExplode { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GENERIC_EXTINGUISH_FIRE" => Ok(Sound::EntityGenericExtinguishFire { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GENERIC_HURT" => Ok(Sound::EntityGenericHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GENERIC_SMALL_FALL" => Ok(Sound::EntityGenericSmallFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GENERIC_SPLASH" => Ok(Sound::EntityGenericSplash { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GENERIC_SWIM" => Ok(Sound::EntityGenericSwim { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GHAST_AMBIENT" => Ok(Sound::EntityGhastAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GHAST_DEATH" => Ok(Sound::EntityGhastDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GHAST_HURT" => Ok(Sound::EntityGhastHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GHAST_SCREAM" => Ok(Sound::EntityGhastScream { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GHAST_SHOOT" => Ok(Sound::EntityGhastShoot { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GHAST_WARN" => Ok(Sound::EntityGhastWarn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GLOW_ITEM_FRAME_ADD_ITEM" => Ok(Sound::EntityGlowItemFrameAddItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GLOW_ITEM_FRAME_BREAK" => Ok(Sound::EntityGlowItemFrameBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GLOW_ITEM_FRAME_PLACE" => Ok(Sound::EntityGlowItemFramePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GLOW_ITEM_FRAME_REMOVE_ITEM" => Ok(Sound::EntityGlowItemFrameRemoveItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GLOW_ITEM_FRAME_ROTATE_ITEM" => Ok(Sound::EntityGlowItemFrameRotateItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GLOW_SQUID_AMBIENT" => Ok(Sound::EntityGlowSquidAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GLOW_SQUID_DEATH" => Ok(Sound::EntityGlowSquidDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GLOW_SQUID_HURT" => Ok(Sound::EntityGlowSquidHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GLOW_SQUID_SQUIRT" => Ok(Sound::EntityGlowSquidSquirt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_AMBIENT" => Ok(Sound::EntityGoatAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_DEATH" => Ok(Sound::EntityGoatDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_EAT" => Ok(Sound::EntityGoatEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_HORN_BREAK" => Ok(Sound::EntityGoatHornBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_HURT" => Ok(Sound::EntityGoatHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_LONG_JUMP" => Ok(Sound::EntityGoatLongJump { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_MILK" => Ok(Sound::EntityGoatMilk { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_PREPARE_RAM" => Ok(Sound::EntityGoatPrepareRam { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_RAM_IMPACT" => Ok(Sound::EntityGoatRamImpact { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_SCREAMING_AMBIENT" => Ok(Sound::EntityGoatScreamingAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_SCREAMING_DEATH" => Ok(Sound::EntityGoatScreamingDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_SCREAMING_EAT" => Ok(Sound::EntityGoatScreamingEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_SCREAMING_HORN_BREAK" => Ok(Sound::EntityGoatScreamingHornBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_SCREAMING_HURT" => Ok(Sound::EntityGoatScreamingHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_SCREAMING_LONG_JUMP" => Ok(Sound::EntityGoatScreamingLongJump { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_SCREAMING_MILK" => Ok(Sound::EntityGoatScreamingMilk { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_SCREAMING_PREPARE_RAM" => Ok(Sound::EntityGoatScreamingPrepareRam { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_SCREAMING_RAM_IMPACT" => Ok(Sound::EntityGoatScreamingRamImpact { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_STEP" => Ok(Sound::EntityGoatStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GUARDIAN_AMBIENT" => Ok(Sound::EntityGuardianAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GUARDIAN_AMBIENT_LAND" => Ok(Sound::EntityGuardianAmbientLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GUARDIAN_ATTACK" => Ok(Sound::EntityGuardianAttack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GUARDIAN_DEATH" => Ok(Sound::EntityGuardianDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GUARDIAN_DEATH_LAND" => Ok(Sound::EntityGuardianDeathLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GUARDIAN_FLOP" => Ok(Sound::EntityGuardianFlop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GUARDIAN_HURT" => Ok(Sound::EntityGuardianHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GUARDIAN_HURT_LAND" => Ok(Sound::EntityGuardianHurtLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOGLIN_AMBIENT" => Ok(Sound::EntityHoglinAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOGLIN_ANGRY" => Ok(Sound::EntityHoglinAngry { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOGLIN_ATTACK" => Ok(Sound::EntityHoglinAttack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOGLIN_CONVERTED_TO_ZOMBIFIED" => Ok(Sound::EntityHoglinConvertedToZombified { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOGLIN_DEATH" => Ok(Sound::EntityHoglinDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOGLIN_HURT" => Ok(Sound::EntityHoglinHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOGLIN_RETREAT" => Ok(Sound::EntityHoglinRetreat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOGLIN_STEP" => Ok(Sound::EntityHoglinStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_AMBIENT" => Ok(Sound::EntityHorseAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_ANGRY" => Ok(Sound::EntityHorseAngry { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_ARMOR" => Ok(Sound::EntityHorseArmor { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_BREATHE" => Ok(Sound::EntityHorseBreathe { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_DEATH" => Ok(Sound::EntityHorseDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_EAT" => Ok(Sound::EntityHorseEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_GALLOP" => Ok(Sound::EntityHorseGallop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_HURT" => Ok(Sound::EntityHorseHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_JUMP" => Ok(Sound::EntityHorseJump { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_LAND" => Ok(Sound::EntityHorseLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_SADDLE" => Ok(Sound::EntityHorseSaddle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_STEP" => Ok(Sound::EntityHorseStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_STEP_WOOD" => Ok(Sound::EntityHorseStepWood { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOSTILE_BIG_FALL" => Ok(Sound::EntityHostileBigFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOSTILE_DEATH" => Ok(Sound::EntityHostileDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOSTILE_HURT" => Ok(Sound::EntityHostileHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOSTILE_SMALL_FALL" => Ok(Sound::EntityHostileSmallFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOSTILE_SPLASH" => Ok(Sound::EntityHostileSplash { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOSTILE_SWIM" => Ok(Sound::EntityHostileSwim { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HUSK_AMBIENT" => Ok(Sound::EntityHuskAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HUSK_CONVERTED_TO_ZOMBIE" => Ok(Sound::EntityHuskConvertedToZombie { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HUSK_DEATH" => Ok(Sound::EntityHuskDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HUSK_HURT" => Ok(Sound::EntityHuskHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HUSK_STEP" => Ok(Sound::EntityHuskStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ILLUSIONER_AMBIENT" => Ok(Sound::EntityIllusionerAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ILLUSIONER_CAST_SPELL" => Ok(Sound::EntityIllusionerCastSpell { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ILLUSIONER_DEATH" => Ok(Sound::EntityIllusionerDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ILLUSIONER_HURT" => Ok(Sound::EntityIllusionerHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ILLUSIONER_MIRROR_MOVE" => Ok(Sound::EntityIllusionerMirrorMove { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ILLUSIONER_PREPARE_BLINDNESS" => Ok(Sound::EntityIllusionerPrepareBlindness { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ILLUSIONER_PREPARE_MIRROR" => Ok(Sound::EntityIllusionerPrepareMirror { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_IRON_GOLEM_ATTACK" => Ok(Sound::EntityIronGolemAttack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_IRON_GOLEM_DAMAGE" => Ok(Sound::EntityIronGolemDamage { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_IRON_GOLEM_DEATH" => Ok(Sound::EntityIronGolemDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_IRON_GOLEM_HURT" => Ok(Sound::EntityIronGolemHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_IRON_GOLEM_REPAIR" => Ok(Sound::EntityIronGolemRepair { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_IRON_GOLEM_STEP" => Ok(Sound::EntityIronGolemStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ITEM_BREAK" => Ok(Sound::EntityItemBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ITEM_FRAME_ADD_ITEM" => Ok(Sound::EntityItemFrameAddItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ITEM_FRAME_BREAK" => Ok(Sound::EntityItemFrameBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ITEM_FRAME_PLACE" => Ok(Sound::EntityItemFramePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ITEM_FRAME_REMOVE_ITEM" => Ok(Sound::EntityItemFrameRemoveItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ITEM_FRAME_ROTATE_ITEM" => Ok(Sound::EntityItemFrameRotateItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ITEM_PICKUP" => Ok(Sound::EntityItemPickup { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LEASH_KNOT_BREAK" => Ok(Sound::EntityLeashKnotBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LEASH_KNOT_PLACE" => Ok(Sound::EntityLeashKnotPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LIGHTNING_BOLT_IMPACT" => Ok(Sound::EntityLightningBoltImpact { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LIGHTNING_BOLT_THUNDER" => Ok(Sound::EntityLightningBoltThunder { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LINGERING_POTION_THROW" => Ok(Sound::EntityLingeringPotionThrow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LLAMA_AMBIENT" => Ok(Sound::EntityLlamaAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LLAMA_ANGRY" => Ok(Sound::EntityLlamaAngry { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LLAMA_CHEST" => Ok(Sound::EntityLlamaChest { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LLAMA_DEATH" => Ok(Sound::EntityLlamaDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LLAMA_EAT" => Ok(Sound::EntityLlamaEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LLAMA_HURT" => Ok(Sound::EntityLlamaHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LLAMA_SPIT" => Ok(Sound::EntityLlamaSpit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LLAMA_STEP" => Ok(Sound::EntityLlamaStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LLAMA_SWAG" => Ok(Sound::EntityLlamaSwag { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MAGMA_CUBE_DEATH" => Ok(Sound::EntityMagmaCubeDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MAGMA_CUBE_DEATH_SMALL" => Ok(Sound::EntityMagmaCubeDeathSmall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MAGMA_CUBE_HURT" => Ok(Sound::EntityMagmaCubeHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MAGMA_CUBE_HURT_SMALL" => Ok(Sound::EntityMagmaCubeHurtSmall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MAGMA_CUBE_JUMP" => Ok(Sound::EntityMagmaCubeJump { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MAGMA_CUBE_SQUISH" => Ok(Sound::EntityMagmaCubeSquish { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MAGMA_CUBE_SQUISH_SMALL" => Ok(Sound::EntityMagmaCubeSquishSmall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MINECART_INSIDE" => Ok(Sound::EntityMinecartInside { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MINECART_INSIDE_UNDERWATER" => Ok(Sound::EntityMinecartInsideUnderwater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MINECART_RIDING" => Ok(Sound::EntityMinecartRiding { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MOOSHROOM_CONVERT" => Ok(Sound::EntityMooshroomConvert { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MOOSHROOM_EAT" => Ok(Sound::EntityMooshroomEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MOOSHROOM_MILK" => Ok(Sound::EntityMooshroomMilk { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MOOSHROOM_SHEAR" => Ok(Sound::EntityMooshroomShear { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MOOSHROOM_SUSPICIOUS_MILK" => Ok(Sound::EntityMooshroomSuspiciousMilk { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MULE_AMBIENT" => Ok(Sound::EntityMuleAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MULE_ANGRY" => Ok(Sound::EntityMuleAngry { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MULE_CHEST" => Ok(Sound::EntityMuleChest { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MULE_DEATH" => Ok(Sound::EntityMuleDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MULE_EAT" => Ok(Sound::EntityMuleEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MULE_HURT" => Ok(Sound::EntityMuleHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MULE_JUMP" => Ok(Sound::EntityMuleJump { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_OCELOT_AMBIENT" => Ok(Sound::EntityOcelotAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_OCELOT_DEATH" => Ok(Sound::EntityOcelotDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_OCELOT_HURT" => Ok(Sound::EntityOcelotHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PAINTING_BREAK" => Ok(Sound::EntityPaintingBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PAINTING_PLACE" => Ok(Sound::EntityPaintingPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PANDA_AGGRESSIVE_AMBIENT" => Ok(Sound::EntityPandaAggressiveAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PANDA_AMBIENT" => Ok(Sound::EntityPandaAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PANDA_BITE" => Ok(Sound::EntityPandaBite { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PANDA_CANT_BREED" => Ok(Sound::EntityPandaCantBreed { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PANDA_DEATH" => Ok(Sound::EntityPandaDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PANDA_EAT" => Ok(Sound::EntityPandaEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PANDA_HURT" => Ok(Sound::EntityPandaHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PANDA_PRE_SNEEZE" => Ok(Sound::EntityPandaPreSneeze { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PANDA_SNEEZE" => Ok(Sound::EntityPandaSneeze { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PANDA_STEP" => Ok(Sound::EntityPandaStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PANDA_WORRIED_AMBIENT" => Ok(Sound::EntityPandaWorriedAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_AMBIENT" => Ok(Sound::EntityParrotAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_DEATH" => Ok(Sound::EntityParrotDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_EAT" => Ok(Sound::EntityParrotEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_FLY" => Ok(Sound::EntityParrotFly { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_HURT" => Ok(Sound::EntityParrotHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_BLAZE" => Ok(Sound::EntityParrotImitateBlaze { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_BOGGED" => Ok(Sound::EntityParrotImitateBogged { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_BREEZE" => Ok(Sound::EntityParrotImitateBreeze { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_CREEPER" => Ok(Sound::EntityParrotImitateCreeper { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_DROWNED" => Ok(Sound::EntityParrotImitateDrowned { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_ELDER_GUARDIAN" => Ok(Sound::EntityParrotImitateElderGuardian { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_ENDERMITE" => Ok(Sound::EntityParrotImitateEndermite { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_ENDER_DRAGON" => Ok(Sound::EntityParrotImitateEnderDragon { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_EVOKER" => Ok(Sound::EntityParrotImitateEvoker { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_GHAST" => Ok(Sound::EntityParrotImitateGhast { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_GUARDIAN" => Ok(Sound::EntityParrotImitateGuardian { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_HOGLIN" => Ok(Sound::EntityParrotImitateHoglin { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_HUSK" => Ok(Sound::EntityParrotImitateHusk { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_ILLUSIONER" => Ok(Sound::EntityParrotImitateIllusioner { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_MAGMA_CUBE" => Ok(Sound::EntityParrotImitateMagmaCube { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_PHANTOM" => Ok(Sound::EntityParrotImitatePhantom { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_PIGLIN" => Ok(Sound::EntityParrotImitatePiglin { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_PIGLIN_BRUTE" => Ok(Sound::EntityParrotImitatePiglinBrute { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_PILLAGER" => Ok(Sound::EntityParrotImitatePillager { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_RAVAGER" => Ok(Sound::EntityParrotImitateRavager { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_SHULKER" => Ok(Sound::EntityParrotImitateShulker { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_SILVERFISH" => Ok(Sound::EntityParrotImitateSilverfish { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_SKELETON" => Ok(Sound::EntityParrotImitateSkeleton { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_SLIME" => Ok(Sound::EntityParrotImitateSlime { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_SPIDER" => Ok(Sound::EntityParrotImitateSpider { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_STRAY" => Ok(Sound::EntityParrotImitateStray { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_VEX" => Ok(Sound::EntityParrotImitateVex { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_VINDICATOR" => Ok(Sound::EntityParrotImitateVindicator { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_WARDEN" => Ok(Sound::EntityParrotImitateWarden { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_WITCH" => Ok(Sound::EntityParrotImitateWitch { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_WITHER" => Ok(Sound::EntityParrotImitateWither { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_WITHER_SKELETON" => { + Ok(Sound::EntityParrotImitateWitherSkeleton { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "ENTITY_PARROT_IMITATE_ZOGLIN" => Ok(Sound::EntityParrotImitateZoglin { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_ZOMBIE" => Ok(Sound::EntityParrotImitateZombie { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_ZOMBIE_VILLAGER" => { + Ok(Sound::EntityParrotImitateZombieVillager { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "ENTITY_PARROT_STEP" => Ok(Sound::EntityParrotStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PHANTOM_AMBIENT" => Ok(Sound::EntityPhantomAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PHANTOM_BITE" => Ok(Sound::EntityPhantomBite { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PHANTOM_DEATH" => Ok(Sound::EntityPhantomDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PHANTOM_FLAP" => Ok(Sound::EntityPhantomFlap { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PHANTOM_HURT" => Ok(Sound::EntityPhantomHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PHANTOM_SWOOP" => Ok(Sound::EntityPhantomSwoop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_ADMIRING_ITEM" => Ok(Sound::EntityPiglinAdmiringItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_AMBIENT" => Ok(Sound::EntityPiglinAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_ANGRY" => Ok(Sound::EntityPiglinAngry { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_BRUTE_AMBIENT" => Ok(Sound::EntityPiglinBruteAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_BRUTE_ANGRY" => Ok(Sound::EntityPiglinBruteAngry { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_BRUTE_CONVERTED_TO_ZOMBIFIED" => { + Ok(Sound::EntityPiglinBruteConvertedToZombified { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "ENTITY_PIGLIN_BRUTE_DEATH" => Ok(Sound::EntityPiglinBruteDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_BRUTE_HURT" => Ok(Sound::EntityPiglinBruteHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_BRUTE_STEP" => Ok(Sound::EntityPiglinBruteStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_CELEBRATE" => Ok(Sound::EntityPiglinCelebrate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_CONVERTED_TO_ZOMBIFIED" => Ok(Sound::EntityPiglinConvertedToZombified { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_DEATH" => Ok(Sound::EntityPiglinDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_HURT" => Ok(Sound::EntityPiglinHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_JEALOUS" => Ok(Sound::EntityPiglinJealous { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_RETREAT" => Ok(Sound::EntityPiglinRetreat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_STEP" => Ok(Sound::EntityPiglinStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIG_AMBIENT" => Ok(Sound::EntityPigAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIG_DEATH" => Ok(Sound::EntityPigDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIG_HURT" => Ok(Sound::EntityPigHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIG_SADDLE" => Ok(Sound::EntityPigSaddle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIG_STEP" => Ok(Sound::EntityPigStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PILLAGER_AMBIENT" => Ok(Sound::EntityPillagerAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PILLAGER_CELEBRATE" => Ok(Sound::EntityPillagerCelebrate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PILLAGER_DEATH" => Ok(Sound::EntityPillagerDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PILLAGER_HURT" => Ok(Sound::EntityPillagerHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_ATTACK_CRIT" => Ok(Sound::EntityPlayerAttackCrit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_ATTACK_KNOCKBACK" => Ok(Sound::EntityPlayerAttackKnockback { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_ATTACK_NODAMAGE" => Ok(Sound::EntityPlayerAttackNodamage { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_ATTACK_STRONG" => Ok(Sound::EntityPlayerAttackStrong { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_ATTACK_SWEEP" => Ok(Sound::EntityPlayerAttackSweep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_ATTACK_WEAK" => Ok(Sound::EntityPlayerAttackWeak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_BIG_FALL" => Ok(Sound::EntityPlayerBigFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_BREATH" => Ok(Sound::EntityPlayerBreath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_BURP" => Ok(Sound::EntityPlayerBurp { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_DEATH" => Ok(Sound::EntityPlayerDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_HURT" => Ok(Sound::EntityPlayerHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_HURT_DROWN" => Ok(Sound::EntityPlayerHurtDrown { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_HURT_FREEZE" => Ok(Sound::EntityPlayerHurtFreeze { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_HURT_ON_FIRE" => Ok(Sound::EntityPlayerHurtOnFire { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_HURT_SWEET_BERRY_BUSH" => Ok(Sound::EntityPlayerHurtSweetBerryBush { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_LEVELUP" => Ok(Sound::EntityPlayerLevelup { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_SMALL_FALL" => Ok(Sound::EntityPlayerSmallFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_SPLASH" => Ok(Sound::EntityPlayerSplash { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_SPLASH_HIGH_SPEED" => Ok(Sound::EntityPlayerSplashHighSpeed { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_SWIM" => Ok(Sound::EntityPlayerSwim { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_TELEPORT" => Ok(Sound::EntityPlayerTeleport { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_POLAR_BEAR_AMBIENT" => Ok(Sound::EntityPolarBearAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_POLAR_BEAR_AMBIENT_BABY" => Ok(Sound::EntityPolarBearAmbientBaby { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_POLAR_BEAR_DEATH" => Ok(Sound::EntityPolarBearDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_POLAR_BEAR_HURT" => Ok(Sound::EntityPolarBearHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_POLAR_BEAR_STEP" => Ok(Sound::EntityPolarBearStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_POLAR_BEAR_WARNING" => Ok(Sound::EntityPolarBearWarning { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PUFFER_FISH_AMBIENT" => Ok(Sound::EntityPufferFishAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PUFFER_FISH_BLOW_OUT" => Ok(Sound::EntityPufferFishBlowOut { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PUFFER_FISH_BLOW_UP" => Ok(Sound::EntityPufferFishBlowUp { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PUFFER_FISH_DEATH" => Ok(Sound::EntityPufferFishDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PUFFER_FISH_FLOP" => Ok(Sound::EntityPufferFishFlop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PUFFER_FISH_HURT" => Ok(Sound::EntityPufferFishHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PUFFER_FISH_STING" => Ok(Sound::EntityPufferFishSting { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RABBIT_AMBIENT" => Ok(Sound::EntityRabbitAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RABBIT_ATTACK" => Ok(Sound::EntityRabbitAttack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RABBIT_DEATH" => Ok(Sound::EntityRabbitDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RABBIT_HURT" => Ok(Sound::EntityRabbitHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RABBIT_JUMP" => Ok(Sound::EntityRabbitJump { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RAVAGER_AMBIENT" => Ok(Sound::EntityRavagerAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RAVAGER_ATTACK" => Ok(Sound::EntityRavagerAttack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RAVAGER_CELEBRATE" => Ok(Sound::EntityRavagerCelebrate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RAVAGER_DEATH" => Ok(Sound::EntityRavagerDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RAVAGER_HURT" => Ok(Sound::EntityRavagerHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RAVAGER_ROAR" => Ok(Sound::EntityRavagerRoar { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RAVAGER_STEP" => Ok(Sound::EntityRavagerStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RAVAGER_STUNNED" => Ok(Sound::EntityRavagerStunned { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SALMON_AMBIENT" => Ok(Sound::EntitySalmonAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SALMON_DEATH" => Ok(Sound::EntitySalmonDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SALMON_FLOP" => Ok(Sound::EntitySalmonFlop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SALMON_HURT" => Ok(Sound::EntitySalmonHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHEEP_AMBIENT" => Ok(Sound::EntitySheepAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHEEP_DEATH" => Ok(Sound::EntitySheepDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHEEP_HURT" => Ok(Sound::EntitySheepHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHEEP_SHEAR" => Ok(Sound::EntitySheepShear { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHEEP_STEP" => Ok(Sound::EntitySheepStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHULKER_AMBIENT" => Ok(Sound::EntityShulkerAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHULKER_BULLET_HIT" => Ok(Sound::EntityShulkerBulletHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHULKER_BULLET_HURT" => Ok(Sound::EntityShulkerBulletHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHULKER_CLOSE" => Ok(Sound::EntityShulkerClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHULKER_DEATH" => Ok(Sound::EntityShulkerDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHULKER_HURT" => Ok(Sound::EntityShulkerHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHULKER_HURT_CLOSED" => Ok(Sound::EntityShulkerHurtClosed { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHULKER_OPEN" => Ok(Sound::EntityShulkerOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHULKER_SHOOT" => Ok(Sound::EntityShulkerShoot { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHULKER_TELEPORT" => Ok(Sound::EntityShulkerTeleport { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SILVERFISH_AMBIENT" => Ok(Sound::EntitySilverfishAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SILVERFISH_DEATH" => Ok(Sound::EntitySilverfishDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SILVERFISH_HURT" => Ok(Sound::EntitySilverfishHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SILVERFISH_STEP" => Ok(Sound::EntitySilverfishStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_AMBIENT" => Ok(Sound::EntitySkeletonAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_CONVERTED_TO_STRAY" => Ok(Sound::EntitySkeletonConvertedToStray { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_DEATH" => Ok(Sound::EntitySkeletonDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_HORSE_AMBIENT" => Ok(Sound::EntitySkeletonHorseAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_HORSE_AMBIENT_WATER" => Ok(Sound::EntitySkeletonHorseAmbientWater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_HORSE_DEATH" => Ok(Sound::EntitySkeletonHorseDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_HORSE_GALLOP_WATER" => Ok(Sound::EntitySkeletonHorseGallopWater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_HORSE_HURT" => Ok(Sound::EntitySkeletonHorseHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_HORSE_JUMP_WATER" => Ok(Sound::EntitySkeletonHorseJumpWater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_HORSE_STEP_WATER" => Ok(Sound::EntitySkeletonHorseStepWater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_HORSE_SWIM" => Ok(Sound::EntitySkeletonHorseSwim { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_HURT" => Ok(Sound::EntitySkeletonHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_SHOOT" => Ok(Sound::EntitySkeletonShoot { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_STEP" => Ok(Sound::EntitySkeletonStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SLIME_ATTACK" => Ok(Sound::EntitySlimeAttack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SLIME_DEATH" => Ok(Sound::EntitySlimeDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SLIME_DEATH_SMALL" => Ok(Sound::EntitySlimeDeathSmall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SLIME_HURT" => Ok(Sound::EntitySlimeHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SLIME_HURT_SMALL" => Ok(Sound::EntitySlimeHurtSmall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SLIME_JUMP" => Ok(Sound::EntitySlimeJump { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SLIME_JUMP_SMALL" => Ok(Sound::EntitySlimeJumpSmall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SLIME_SQUISH" => Ok(Sound::EntitySlimeSquish { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SLIME_SQUISH_SMALL" => Ok(Sound::EntitySlimeSquishSmall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNIFFER_DEATH" => Ok(Sound::EntitySnifferDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNIFFER_DIGGING" => Ok(Sound::EntitySnifferDigging { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNIFFER_DIGGING_STOP" => Ok(Sound::EntitySnifferDiggingStop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNIFFER_DROP_SEED" => Ok(Sound::EntitySnifferDropSeed { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNIFFER_EAT" => Ok(Sound::EntitySnifferEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNIFFER_HAPPY" => Ok(Sound::EntitySnifferHappy { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNIFFER_HURT" => Ok(Sound::EntitySnifferHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNIFFER_IDLE" => Ok(Sound::EntitySnifferIdle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNIFFER_SCENTING" => Ok(Sound::EntitySnifferScenting { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNIFFER_SEARCHING" => Ok(Sound::EntitySnifferSearching { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNIFFER_SNIFFING" => Ok(Sound::EntitySnifferSniffing { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNIFFER_STEP" => Ok(Sound::EntitySnifferStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNOWBALL_THROW" => Ok(Sound::EntitySnowballThrow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNOW_GOLEM_AMBIENT" => Ok(Sound::EntitySnowGolemAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNOW_GOLEM_DEATH" => Ok(Sound::EntitySnowGolemDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNOW_GOLEM_HURT" => Ok(Sound::EntitySnowGolemHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNOW_GOLEM_SHEAR" => Ok(Sound::EntitySnowGolemShear { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNOW_GOLEM_SHOOT" => Ok(Sound::EntitySnowGolemShoot { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SPIDER_AMBIENT" => Ok(Sound::EntitySpiderAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SPIDER_DEATH" => Ok(Sound::EntitySpiderDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SPIDER_HURT" => Ok(Sound::EntitySpiderHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SPIDER_STEP" => Ok(Sound::EntitySpiderStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SPLASH_POTION_BREAK" => Ok(Sound::EntitySplashPotionBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SPLASH_POTION_THROW" => Ok(Sound::EntitySplashPotionThrow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SQUID_AMBIENT" => Ok(Sound::EntitySquidAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SQUID_DEATH" => Ok(Sound::EntitySquidDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SQUID_HURT" => Ok(Sound::EntitySquidHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SQUID_SQUIRT" => Ok(Sound::EntitySquidSquirt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRAY_AMBIENT" => Ok(Sound::EntityStrayAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRAY_DEATH" => Ok(Sound::EntityStrayDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRAY_HURT" => Ok(Sound::EntityStrayHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRAY_STEP" => Ok(Sound::EntityStrayStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRIDER_AMBIENT" => Ok(Sound::EntityStriderAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRIDER_DEATH" => Ok(Sound::EntityStriderDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRIDER_EAT" => Ok(Sound::EntityStriderEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRIDER_HAPPY" => Ok(Sound::EntityStriderHappy { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRIDER_HURT" => Ok(Sound::EntityStriderHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRIDER_RETREAT" => Ok(Sound::EntityStriderRetreat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRIDER_SADDLE" => Ok(Sound::EntityStriderSaddle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRIDER_STEP" => Ok(Sound::EntityStriderStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRIDER_STEP_LAVA" => Ok(Sound::EntityStriderStepLava { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TADPOLE_DEATH" => Ok(Sound::EntityTadpoleDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TADPOLE_FLOP" => Ok(Sound::EntityTadpoleFlop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TADPOLE_GROW_UP" => Ok(Sound::EntityTadpoleGrowUp { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TADPOLE_HURT" => Ok(Sound::EntityTadpoleHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TNT_PRIMED" => Ok(Sound::EntityTntPrimed { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TROPICAL_FISH_AMBIENT" => Ok(Sound::EntityTropicalFishAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TROPICAL_FISH_DEATH" => Ok(Sound::EntityTropicalFishDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TROPICAL_FISH_FLOP" => Ok(Sound::EntityTropicalFishFlop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TROPICAL_FISH_HURT" => Ok(Sound::EntityTropicalFishHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TURTLE_AMBIENT_LAND" => Ok(Sound::EntityTurtleAmbientLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TURTLE_DEATH" => Ok(Sound::EntityTurtleDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TURTLE_DEATH_BABY" => Ok(Sound::EntityTurtleDeathBaby { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TURTLE_EGG_BREAK" => Ok(Sound::EntityTurtleEggBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TURTLE_EGG_CRACK" => Ok(Sound::EntityTurtleEggCrack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TURTLE_EGG_HATCH" => Ok(Sound::EntityTurtleEggHatch { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TURTLE_HURT" => Ok(Sound::EntityTurtleHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TURTLE_HURT_BABY" => Ok(Sound::EntityTurtleHurtBaby { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TURTLE_LAY_EGG" => Ok(Sound::EntityTurtleLayEgg { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TURTLE_SHAMBLE" => Ok(Sound::EntityTurtleShamble { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TURTLE_SHAMBLE_BABY" => Ok(Sound::EntityTurtleShambleBaby { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TURTLE_SWIM" => Ok(Sound::EntityTurtleSwim { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VEX_AMBIENT" => Ok(Sound::EntityVexAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VEX_CHARGE" => Ok(Sound::EntityVexCharge { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VEX_DEATH" => Ok(Sound::EntityVexDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VEX_HURT" => Ok(Sound::EntityVexHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_AMBIENT" => Ok(Sound::EntityVillagerAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_CELEBRATE" => Ok(Sound::EntityVillagerCelebrate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_DEATH" => Ok(Sound::EntityVillagerDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_HURT" => Ok(Sound::EntityVillagerHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_NO" => Ok(Sound::EntityVillagerNo { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_TRADE" => Ok(Sound::EntityVillagerTrade { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_ARMORER" => Ok(Sound::EntityVillagerWorkArmorer { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_BUTCHER" => Ok(Sound::EntityVillagerWorkButcher { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_CARTOGRAPHER" => Ok(Sound::EntityVillagerWorkCartographer { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_CLERIC" => Ok(Sound::EntityVillagerWorkCleric { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_FARMER" => Ok(Sound::EntityVillagerWorkFarmer { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_FISHERMAN" => Ok(Sound::EntityVillagerWorkFisherman { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_FLETCHER" => Ok(Sound::EntityVillagerWorkFletcher { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_LEATHERWORKER" => Ok(Sound::EntityVillagerWorkLeatherworker { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_LIBRARIAN" => Ok(Sound::EntityVillagerWorkLibrarian { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_MASON" => Ok(Sound::EntityVillagerWorkMason { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_SHEPHERD" => Ok(Sound::EntityVillagerWorkShepherd { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_TOOLSMITH" => Ok(Sound::EntityVillagerWorkToolsmith { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_WEAPONSMITH" => Ok(Sound::EntityVillagerWorkWeaponsmith { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_YES" => Ok(Sound::EntityVillagerYes { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VINDICATOR_AMBIENT" => Ok(Sound::EntityVindicatorAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VINDICATOR_CELEBRATE" => Ok(Sound::EntityVindicatorCelebrate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VINDICATOR_DEATH" => Ok(Sound::EntityVindicatorDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VINDICATOR_HURT" => Ok(Sound::EntityVindicatorHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WANDERING_TRADER_AMBIENT" => Ok(Sound::EntityWanderingTraderAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WANDERING_TRADER_DEATH" => Ok(Sound::EntityWanderingTraderDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WANDERING_TRADER_DISAPPEARED" => Ok(Sound::EntityWanderingTraderDisappeared { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WANDERING_TRADER_DRINK_MILK" => Ok(Sound::EntityWanderingTraderDrinkMilk { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WANDERING_TRADER_DRINK_POTION" => Ok(Sound::EntityWanderingTraderDrinkPotion { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WANDERING_TRADER_HURT" => Ok(Sound::EntityWanderingTraderHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WANDERING_TRADER_NO" => Ok(Sound::EntityWanderingTraderNo { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WANDERING_TRADER_REAPPEARED" => Ok(Sound::EntityWanderingTraderReappeared { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WANDERING_TRADER_TRADE" => Ok(Sound::EntityWanderingTraderTrade { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WANDERING_TRADER_YES" => Ok(Sound::EntityWanderingTraderYes { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_AGITATED" => Ok(Sound::EntityWardenAgitated { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_AMBIENT" => Ok(Sound::EntityWardenAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_ANGRY" => Ok(Sound::EntityWardenAngry { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_ATTACK_IMPACT" => Ok(Sound::EntityWardenAttackImpact { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_DEATH" => Ok(Sound::EntityWardenDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_DIG" => Ok(Sound::EntityWardenDig { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_EMERGE" => Ok(Sound::EntityWardenEmerge { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_HEARTBEAT" => Ok(Sound::EntityWardenHeartbeat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_HURT" => Ok(Sound::EntityWardenHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_LISTENING" => Ok(Sound::EntityWardenListening { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_LISTENING_ANGRY" => Ok(Sound::EntityWardenListeningAngry { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_NEARBY_CLOSE" => Ok(Sound::EntityWardenNearbyClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_NEARBY_CLOSER" => Ok(Sound::EntityWardenNearbyCloser { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_NEARBY_CLOSEST" => Ok(Sound::EntityWardenNearbyClosest { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_ROAR" => Ok(Sound::EntityWardenRoar { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_SNIFF" => Ok(Sound::EntityWardenSniff { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_SONIC_BOOM" => Ok(Sound::EntityWardenSonicBoom { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_SONIC_CHARGE" => Ok(Sound::EntityWardenSonicCharge { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_STEP" => Ok(Sound::EntityWardenStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_TENDRIL_CLICKS" => Ok(Sound::EntityWardenTendrilClicks { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WIND_CHARGE_THROW" => Ok(Sound::EntityWindChargeThrow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WIND_CHARGE_WIND_BURST" => Ok(Sound::EntityWindChargeWindBurst { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITCH_AMBIENT" => Ok(Sound::EntityWitchAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITCH_CELEBRATE" => Ok(Sound::EntityWitchCelebrate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITCH_DEATH" => Ok(Sound::EntityWitchDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITCH_DRINK" => Ok(Sound::EntityWitchDrink { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITCH_HURT" => Ok(Sound::EntityWitchHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITCH_THROW" => Ok(Sound::EntityWitchThrow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITHER_AMBIENT" => Ok(Sound::EntityWitherAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITHER_BREAK_BLOCK" => Ok(Sound::EntityWitherBreakBlock { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITHER_DEATH" => Ok(Sound::EntityWitherDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITHER_HURT" => Ok(Sound::EntityWitherHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITHER_SHOOT" => Ok(Sound::EntityWitherShoot { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITHER_SKELETON_AMBIENT" => Ok(Sound::EntityWitherSkeletonAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITHER_SKELETON_DEATH" => Ok(Sound::EntityWitherSkeletonDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITHER_SKELETON_HURT" => Ok(Sound::EntityWitherSkeletonHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITHER_SKELETON_STEP" => Ok(Sound::EntityWitherSkeletonStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITHER_SPAWN" => Ok(Sound::EntityWitherSpawn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WOLF_AMBIENT" => Ok(Sound::EntityWolfAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WOLF_DEATH" => Ok(Sound::EntityWolfDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WOLF_GROWL" => Ok(Sound::EntityWolfGrowl { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WOLF_HOWL" => Ok(Sound::EntityWolfHowl { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WOLF_HURT" => Ok(Sound::EntityWolfHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WOLF_PANT" => Ok(Sound::EntityWolfPant { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WOLF_SHAKE" => Ok(Sound::EntityWolfShake { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WOLF_STEP" => Ok(Sound::EntityWolfStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WOLF_WHINE" => Ok(Sound::EntityWolfWhine { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOGLIN_AMBIENT" => Ok(Sound::EntityZoglinAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOGLIN_ANGRY" => Ok(Sound::EntityZoglinAngry { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOGLIN_ATTACK" => Ok(Sound::EntityZoglinAttack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOGLIN_DEATH" => Ok(Sound::EntityZoglinDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOGLIN_HURT" => Ok(Sound::EntityZoglinHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOGLIN_STEP" => Ok(Sound::EntityZoglinStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_AMBIENT" => Ok(Sound::EntityZombieAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_ATTACK_IRON_DOOR" => Ok(Sound::EntityZombieAttackIronDoor { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_ATTACK_WOODEN_DOOR" => Ok(Sound::EntityZombieAttackWoodenDoor { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_BREAK_WOODEN_DOOR" => Ok(Sound::EntityZombieBreakWoodenDoor { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_CONVERTED_TO_DROWNED" => Ok(Sound::EntityZombieConvertedToDrowned { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_DEATH" => Ok(Sound::EntityZombieDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_DESTROY_EGG" => Ok(Sound::EntityZombieDestroyEgg { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_HORSE_AMBIENT" => Ok(Sound::EntityZombieHorseAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_HORSE_DEATH" => Ok(Sound::EntityZombieHorseDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_HORSE_HURT" => Ok(Sound::EntityZombieHorseHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_HURT" => Ok(Sound::EntityZombieHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_INFECT" => Ok(Sound::EntityZombieInfect { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_STEP" => Ok(Sound::EntityZombieStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_VILLAGER_AMBIENT" => Ok(Sound::EntityZombieVillagerAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_VILLAGER_CONVERTED" => Ok(Sound::EntityZombieVillagerConverted { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_VILLAGER_CURE" => Ok(Sound::EntityZombieVillagerCure { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_VILLAGER_DEATH" => Ok(Sound::EntityZombieVillagerDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_VILLAGER_HURT" => Ok(Sound::EntityZombieVillagerHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_VILLAGER_STEP" => Ok(Sound::EntityZombieVillagerStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIFIED_PIGLIN_AMBIENT" => Ok(Sound::EntityZombifiedPiglinAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIFIED_PIGLIN_ANGRY" => Ok(Sound::EntityZombifiedPiglinAngry { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIFIED_PIGLIN_DEATH" => Ok(Sound::EntityZombifiedPiglinDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIFIED_PIGLIN_HURT" => Ok(Sound::EntityZombifiedPiglinHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "EVENT_MOB_EFFECT_BAD_OMEN" => Ok(Sound::EventMobEffectBadOmen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "EVENT_MOB_EFFECT_RAID_OMEN" => Ok(Sound::EventMobEffectRaidOmen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "EVENT_MOB_EFFECT_TRIAL_OMEN" => Ok(Sound::EventMobEffectTrialOmen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "EVENT_RAID_HORN" => Ok(Sound::EventRaidHorn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "INTENTIONALLY_EMPTY" => Ok(Sound::IntentionallyEmpty { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_ARMOR_EQUIP_CHAIN" => Ok(Sound::ItemArmorEquipChain { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_ARMOR_EQUIP_DIAMOND" => Ok(Sound::ItemArmorEquipDiamond { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_ARMOR_EQUIP_ELYTRA" => Ok(Sound::ItemArmorEquipElytra { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_ARMOR_EQUIP_GENERIC" => Ok(Sound::ItemArmorEquipGeneric { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_ARMOR_EQUIP_GOLD" => Ok(Sound::ItemArmorEquipGold { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_ARMOR_EQUIP_IRON" => Ok(Sound::ItemArmorEquipIron { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_ARMOR_EQUIP_LEATHER" => Ok(Sound::ItemArmorEquipLeather { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_ARMOR_EQUIP_NETHERITE" => Ok(Sound::ItemArmorEquipNetherite { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_ARMOR_EQUIP_TURTLE" => Ok(Sound::ItemArmorEquipTurtle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_ARMOR_EQUIP_WOLF" => Ok(Sound::ItemArmorEquipWolf { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_ARMOR_UNEQUIP_WOLF" => Ok(Sound::ItemArmorUnequipWolf { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_AXE_SCRAPE" => Ok(Sound::ItemAxeScrape { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_AXE_STRIP" => Ok(Sound::ItemAxeStrip { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_AXE_WAX_OFF" => Ok(Sound::ItemAxeWaxOff { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BONE_MEAL_USE" => Ok(Sound::ItemBoneMealUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BOOK_PAGE_TURN" => Ok(Sound::ItemBookPageTurn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BOOK_PUT" => Ok(Sound::ItemBookPut { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BOTTLE_EMPTY" => Ok(Sound::ItemBottleEmpty { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BOTTLE_FILL" => Ok(Sound::ItemBottleFill { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BOTTLE_FILL_DRAGONBREATH" => Ok(Sound::ItemBottleFillDragonbreath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BRUSH_BRUSHING_GENERIC" => Ok(Sound::ItemBrushBrushingGeneric { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BRUSH_BRUSHING_GRAVEL" => Ok(Sound::ItemBrushBrushingGravel { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BRUSH_BRUSHING_GRAVEL_COMPLETE" => Ok(Sound::ItemBrushBrushingGravelComplete { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BRUSH_BRUSHING_SAND" => Ok(Sound::ItemBrushBrushingSand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BRUSH_BRUSHING_SAND_COMPLETE" => Ok(Sound::ItemBrushBrushingSandComplete { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUCKET_EMPTY" => Ok(Sound::ItemBucketEmpty { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUCKET_EMPTY_AXOLOTL" => Ok(Sound::ItemBucketEmptyAxolotl { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUCKET_EMPTY_FISH" => Ok(Sound::ItemBucketEmptyFish { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUCKET_EMPTY_LAVA" => Ok(Sound::ItemBucketEmptyLava { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUCKET_EMPTY_POWDER_SNOW" => Ok(Sound::ItemBucketEmptyPowderSnow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUCKET_EMPTY_TADPOLE" => Ok(Sound::ItemBucketEmptyTadpole { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUCKET_FILL" => Ok(Sound::ItemBucketFill { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUCKET_FILL_AXOLOTL" => Ok(Sound::ItemBucketFillAxolotl { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUCKET_FILL_FISH" => Ok(Sound::ItemBucketFillFish { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUCKET_FILL_LAVA" => Ok(Sound::ItemBucketFillLava { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUCKET_FILL_POWDER_SNOW" => Ok(Sound::ItemBucketFillPowderSnow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUCKET_FILL_TADPOLE" => Ok(Sound::ItemBucketFillTadpole { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUNDLE_DROP_CONTENTS" => Ok(Sound::ItemBundleDropContents { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUNDLE_INSERT" => Ok(Sound::ItemBundleInsert { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUNDLE_REMOVE_ONE" => Ok(Sound::ItemBundleRemoveOne { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_CHORUS_FRUIT_TELEPORT" => Ok(Sound::ItemChorusFruitTeleport { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_CROP_PLANT" => Ok(Sound::ItemCropPlant { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_CROSSBOW_HIT" => Ok(Sound::ItemCrossbowHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_CROSSBOW_LOADING_END" => Ok(Sound::ItemCrossbowLoadingEnd { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_CROSSBOW_LOADING_MIDDLE" => Ok(Sound::ItemCrossbowLoadingMiddle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_CROSSBOW_LOADING_START" => Ok(Sound::ItemCrossbowLoadingStart { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_CROSSBOW_QUICK_CHARGE_1" => Ok(Sound::ItemCrossbowQuickCharge1 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_CROSSBOW_QUICK_CHARGE_2" => Ok(Sound::ItemCrossbowQuickCharge2 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_CROSSBOW_QUICK_CHARGE_3" => Ok(Sound::ItemCrossbowQuickCharge3 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_CROSSBOW_SHOOT" => Ok(Sound::ItemCrossbowShoot { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_DYE_USE" => Ok(Sound::ItemDyeUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_ELYTRA_FLYING" => Ok(Sound::ItemElytraFlying { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_FIRECHARGE_USE" => Ok(Sound::ItemFirechargeUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_FLINTANDSTEEL_USE" => Ok(Sound::ItemFlintandsteelUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_GLOW_INK_SAC_USE" => Ok(Sound::ItemGlowInkSacUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_GOAT_HORN_PLAY" => Ok(Sound::ItemGoatHornPlay { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_GOAT_HORN_SOUND_0" => Ok(Sound::ItemGoatHornSound0 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_GOAT_HORN_SOUND_1" => Ok(Sound::ItemGoatHornSound1 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_GOAT_HORN_SOUND_2" => Ok(Sound::ItemGoatHornSound2 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_GOAT_HORN_SOUND_3" => Ok(Sound::ItemGoatHornSound3 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_GOAT_HORN_SOUND_4" => Ok(Sound::ItemGoatHornSound4 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_GOAT_HORN_SOUND_5" => Ok(Sound::ItemGoatHornSound5 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_GOAT_HORN_SOUND_6" => Ok(Sound::ItemGoatHornSound6 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_GOAT_HORN_SOUND_7" => Ok(Sound::ItemGoatHornSound7 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_HOE_TILL" => Ok(Sound::ItemHoeTill { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_HONEYCOMB_WAX_ON" => Ok(Sound::ItemHoneycombWaxOn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_HONEY_BOTTLE_DRINK" => Ok(Sound::ItemHoneyBottleDrink { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_INK_SAC_USE" => Ok(Sound::ItemInkSacUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_LODESTONE_COMPASS_LOCK" => Ok(Sound::ItemLodestoneCompassLock { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_MACE_SMASH_AIR" => Ok(Sound::ItemMaceSmashAir { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_MACE_SMASH_GROUND" => Ok(Sound::ItemMaceSmashGround { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_MACE_SMASH_GROUND_HEAVY" => Ok(Sound::ItemMaceSmashGroundHeavy { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_NETHER_WART_PLANT" => Ok(Sound::ItemNetherWartPlant { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_OMINOUS_BOTTLE_DISPOSE" => Ok(Sound::ItemOminousBottleDispose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_SHIELD_BLOCK" => Ok(Sound::ItemShieldBlock { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_SHIELD_BREAK" => Ok(Sound::ItemShieldBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_SHOVEL_FLATTEN" => Ok(Sound::ItemShovelFlatten { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_SPYGLASS_STOP_USING" => Ok(Sound::ItemSpyglassStopUsing { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_SPYGLASS_USE" => Ok(Sound::ItemSpyglassUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_TOTEM_USE" => Ok(Sound::ItemTotemUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_TRIDENT_HIT" => Ok(Sound::ItemTridentHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_TRIDENT_HIT_GROUND" => Ok(Sound::ItemTridentHitGround { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_TRIDENT_RETURN" => Ok(Sound::ItemTridentReturn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_TRIDENT_RIPTIDE_1" => Ok(Sound::ItemTridentRiptide1 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_TRIDENT_RIPTIDE_2" => Ok(Sound::ItemTridentRiptide2 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_TRIDENT_RIPTIDE_3" => Ok(Sound::ItemTridentRiptide3 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_TRIDENT_THROW" => Ok(Sound::ItemTridentThrow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_TRIDENT_THUNDER" => Ok(Sound::ItemTridentThunder { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_WOLF_ARMOR_BREAK" => Ok(Sound::ItemWolfArmorBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_WOLF_ARMOR_CRACK" => Ok(Sound::ItemWolfArmorCrack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_WOLF_ARMOR_DAMAGE" => Ok(Sound::ItemWolfArmorDamage { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_WOLF_ARMOR_REPAIR" => Ok(Sound::ItemWolfArmorRepair { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_CREATIVE" => Ok(Sound::MusicCreative { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_CREDITS" => Ok(Sound::MusicCredits { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_11" => Ok(Sound::MusicDisc11 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_13" => Ok(Sound::MusicDisc13 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_5" => Ok(Sound::MusicDisc5 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_BLOCKS" => Ok(Sound::MusicDiscBlocks { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_CAT" => Ok(Sound::MusicDiscCat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_CHIRP" => Ok(Sound::MusicDiscChirp { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_CREATOR" => Ok(Sound::MusicDiscCreator { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_CREATOR_MUSIC_BOX" => Ok(Sound::MusicDiscCreatorMusicBox { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_FAR" => Ok(Sound::MusicDiscFar { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_MALL" => Ok(Sound::MusicDiscMall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_MELLOHI" => Ok(Sound::MusicDiscMellohi { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_OTHERSIDE" => Ok(Sound::MusicDiscOtherside { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_PIGSTEP" => Ok(Sound::MusicDiscPigstep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_PRECIPICE" => Ok(Sound::MusicDiscPrecipice { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_RELIC" => Ok(Sound::MusicDiscRelic { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_STAL" => Ok(Sound::MusicDiscStal { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_STRAD" => Ok(Sound::MusicDiscStrad { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_WAIT" => Ok(Sound::MusicDiscWait { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_WARD" => Ok(Sound::MusicDiscWard { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DRAGON" => Ok(Sound::MusicDragon { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_END" => Ok(Sound::MusicEnd { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_GAME" => Ok(Sound::MusicGame { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_MENU" => Ok(Sound::MusicMenu { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_NETHER_BASALT_DELTAS" => Ok(Sound::MusicNetherBasaltDeltas { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_NETHER_CRIMSON_FOREST" => Ok(Sound::MusicNetherCrimsonForest { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_NETHER_NETHER_WASTES" => Ok(Sound::MusicNetherNetherWastes { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_NETHER_SOUL_SAND_VALLEY" => Ok(Sound::MusicNetherSoulSandValley { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_NETHER_WARPED_FOREST" => Ok(Sound::MusicNetherWarpedForest { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_BADLANDS" => Ok(Sound::MusicOverworldBadlands { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_BAMBOO_JUNGLE" => Ok(Sound::MusicOverworldBambooJungle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_CHERRY_GROVE" => Ok(Sound::MusicOverworldCherryGrove { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_DEEP_DARK" => Ok(Sound::MusicOverworldDeepDark { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_DESERT" => Ok(Sound::MusicOverworldDesert { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_DRIPSTONE_CAVES" => Ok(Sound::MusicOverworldDripstoneCaves { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_FLOWER_FOREST" => Ok(Sound::MusicOverworldFlowerForest { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_FOREST" => Ok(Sound::MusicOverworldForest { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_FROZEN_PEAKS" => Ok(Sound::MusicOverworldFrozenPeaks { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_GROVE" => Ok(Sound::MusicOverworldGrove { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_JAGGED_PEAKS" => Ok(Sound::MusicOverworldJaggedPeaks { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_JUNGLE" => Ok(Sound::MusicOverworldJungle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_LUSH_CAVES" => Ok(Sound::MusicOverworldLushCaves { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_MEADOW" => Ok(Sound::MusicOverworldMeadow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_OLD_GROWTH_TAIGA" => Ok(Sound::MusicOverworldOldGrowthTaiga { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_SNOWY_SLOPES" => Ok(Sound::MusicOverworldSnowySlopes { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_SPARSE_JUNGLE" => Ok(Sound::MusicOverworldSparseJungle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_STONY_PEAKS" => Ok(Sound::MusicOverworldStonyPeaks { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_SWAMP" => Ok(Sound::MusicOverworldSwamp { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_UNDER_WATER" => Ok(Sound::MusicUnderWater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "PARTICLE_SOUL_ESCAPE" => Ok(Sound::ParticleSoulEscape { + inner: SoundStruct::from_raw(env, obj)?, + }), + "UI_BUTTON_CLICK" => Ok(Sound::UiButtonClick { + inner: SoundStruct::from_raw(env, obj)?, + }), + "UI_CARTOGRAPHY_TABLE_TAKE_RESULT" => Ok(Sound::UiCartographyTableTakeResult { + inner: SoundStruct::from_raw(env, obj)?, + }), + "UI_LOOM_SELECT_PATTERN" => Ok(Sound::UiLoomSelectPattern { + inner: SoundStruct::from_raw(env, obj)?, + }), + "UI_LOOM_TAKE_RESULT" => Ok(Sound::UiLoomTakeResult { + inner: SoundStruct::from_raw(env, obj)?, + }), + "UI_STONECUTTER_SELECT_RECIPE" => Ok(Sound::UiStonecutterSelectRecipe { + inner: SoundStruct::from_raw(env, obj)?, + }), + "UI_STONECUTTER_TAKE_RESULT" => Ok(Sound::UiStonecutterTakeResult { + inner: SoundStruct::from_raw(env, obj)?, + }), + "UI_TOAST_CHALLENGE_COMPLETE" => Ok(Sound::UiToastChallengeComplete { + inner: SoundStruct::from_raw(env, obj)?, + }), + "UI_TOAST_IN" => Ok(Sound::UiToastIn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "UI_TOAST_OUT" => Ok(Sound::UiToastOut { + inner: SoundStruct::from_raw(env, obj)?, + }), + "WEATHER_RAIN" => Ok(Sound::WeatherRain { + inner: SoundStruct::from_raw(env, obj)?, + }), + "WEATHER_RAIN_ABOVE" => Ok(Sound::WeatherRainAbove { + inner: SoundStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct SoundStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Sound<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::AmbientBasaltDeltasAdditions { inner } => inner.0.clone(), + Self::AmbientBasaltDeltasLoop { inner } => inner.0.clone(), + Self::AmbientBasaltDeltasMood { inner } => inner.0.clone(), + Self::AmbientCave { inner } => inner.0.clone(), + Self::AmbientCrimsonForestAdditions { inner } => inner.0.clone(), + Self::AmbientCrimsonForestLoop { inner } => inner.0.clone(), + Self::AmbientCrimsonForestMood { inner } => inner.0.clone(), + Self::AmbientNetherWastesAdditions { inner } => inner.0.clone(), + Self::AmbientNetherWastesLoop { inner } => inner.0.clone(), + Self::AmbientNetherWastesMood { inner } => inner.0.clone(), + Self::AmbientSoulSandValleyAdditions { inner } => inner.0.clone(), + Self::AmbientSoulSandValleyLoop { inner } => inner.0.clone(), + Self::AmbientSoulSandValleyMood { inner } => inner.0.clone(), + Self::AmbientUnderwaterEnter { inner } => inner.0.clone(), + Self::AmbientUnderwaterExit { inner } => inner.0.clone(), + Self::AmbientUnderwaterLoop { inner } => inner.0.clone(), + Self::AmbientUnderwaterLoopAdditions { inner } => inner.0.clone(), + Self::AmbientUnderwaterLoopAdditionsRare { inner } => inner.0.clone(), + Self::AmbientUnderwaterLoopAdditionsUltraRare { inner } => inner.0.clone(), + Self::AmbientWarpedForestAdditions { inner } => inner.0.clone(), + Self::AmbientWarpedForestLoop { inner } => inner.0.clone(), + Self::AmbientWarpedForestMood { inner } => inner.0.clone(), + Self::BlockAmethystBlockBreak { inner } => inner.0.clone(), + Self::BlockAmethystBlockChime { inner } => inner.0.clone(), + Self::BlockAmethystBlockFall { inner } => inner.0.clone(), + Self::BlockAmethystBlockHit { inner } => inner.0.clone(), + Self::BlockAmethystBlockPlace { inner } => inner.0.clone(), + Self::BlockAmethystBlockResonate { inner } => inner.0.clone(), + Self::BlockAmethystBlockStep { inner } => inner.0.clone(), + Self::BlockAmethystClusterBreak { inner } => inner.0.clone(), + Self::BlockAmethystClusterFall { inner } => inner.0.clone(), + Self::BlockAmethystClusterHit { inner } => inner.0.clone(), + Self::BlockAmethystClusterPlace { inner } => inner.0.clone(), + Self::BlockAmethystClusterStep { inner } => inner.0.clone(), + Self::BlockAncientDebrisBreak { inner } => inner.0.clone(), + Self::BlockAncientDebrisFall { inner } => inner.0.clone(), + Self::BlockAncientDebrisHit { inner } => inner.0.clone(), + Self::BlockAncientDebrisPlace { inner } => inner.0.clone(), + Self::BlockAncientDebrisStep { inner } => inner.0.clone(), + Self::BlockAnvilBreak { inner } => inner.0.clone(), + Self::BlockAnvilDestroy { inner } => inner.0.clone(), + Self::BlockAnvilFall { inner } => inner.0.clone(), + Self::BlockAnvilHit { inner } => inner.0.clone(), + Self::BlockAnvilLand { inner } => inner.0.clone(), + Self::BlockAnvilPlace { inner } => inner.0.clone(), + Self::BlockAnvilStep { inner } => inner.0.clone(), + Self::BlockAnvilUse { inner } => inner.0.clone(), + Self::BlockAzaleaBreak { inner } => inner.0.clone(), + Self::BlockAzaleaFall { inner } => inner.0.clone(), + Self::BlockAzaleaHit { inner } => inner.0.clone(), + Self::BlockAzaleaLeavesBreak { inner } => inner.0.clone(), + Self::BlockAzaleaLeavesFall { inner } => inner.0.clone(), + Self::BlockAzaleaLeavesHit { inner } => inner.0.clone(), + Self::BlockAzaleaLeavesPlace { inner } => inner.0.clone(), + Self::BlockAzaleaLeavesStep { inner } => inner.0.clone(), + Self::BlockAzaleaPlace { inner } => inner.0.clone(), + Self::BlockAzaleaStep { inner } => inner.0.clone(), + Self::BlockBambooBreak { inner } => inner.0.clone(), + Self::BlockBambooFall { inner } => inner.0.clone(), + Self::BlockBambooHit { inner } => inner.0.clone(), + Self::BlockBambooPlace { inner } => inner.0.clone(), + Self::BlockBambooSaplingBreak { inner } => inner.0.clone(), + Self::BlockBambooSaplingHit { inner } => inner.0.clone(), + Self::BlockBambooSaplingPlace { inner } => inner.0.clone(), + Self::BlockBambooStep { inner } => inner.0.clone(), + Self::BlockBambooWoodBreak { inner } => inner.0.clone(), + Self::BlockBambooWoodButtonClickOff { inner } => inner.0.clone(), + Self::BlockBambooWoodButtonClickOn { inner } => inner.0.clone(), + Self::BlockBambooWoodDoorClose { inner } => inner.0.clone(), + Self::BlockBambooWoodDoorOpen { inner } => inner.0.clone(), + Self::BlockBambooWoodFall { inner } => inner.0.clone(), + Self::BlockBambooWoodFenceGateClose { inner } => inner.0.clone(), + Self::BlockBambooWoodFenceGateOpen { inner } => inner.0.clone(), + Self::BlockBambooWoodHangingSignBreak { inner } => inner.0.clone(), + Self::BlockBambooWoodHangingSignFall { inner } => inner.0.clone(), + Self::BlockBambooWoodHangingSignHit { inner } => inner.0.clone(), + Self::BlockBambooWoodHangingSignPlace { inner } => inner.0.clone(), + Self::BlockBambooWoodHangingSignStep { inner } => inner.0.clone(), + Self::BlockBambooWoodHit { inner } => inner.0.clone(), + Self::BlockBambooWoodPlace { inner } => inner.0.clone(), + Self::BlockBambooWoodPressurePlateClickOff { inner } => inner.0.clone(), + Self::BlockBambooWoodPressurePlateClickOn { inner } => inner.0.clone(), + Self::BlockBambooWoodStep { inner } => inner.0.clone(), + Self::BlockBambooWoodTrapdoorClose { inner } => inner.0.clone(), + Self::BlockBambooWoodTrapdoorOpen { inner } => inner.0.clone(), + Self::BlockBarrelClose { inner } => inner.0.clone(), + Self::BlockBarrelOpen { inner } => inner.0.clone(), + Self::BlockBasaltBreak { inner } => inner.0.clone(), + Self::BlockBasaltFall { inner } => inner.0.clone(), + Self::BlockBasaltHit { inner } => inner.0.clone(), + Self::BlockBasaltPlace { inner } => inner.0.clone(), + Self::BlockBasaltStep { inner } => inner.0.clone(), + Self::BlockBeaconActivate { inner } => inner.0.clone(), + Self::BlockBeaconAmbient { inner } => inner.0.clone(), + Self::BlockBeaconDeactivate { inner } => inner.0.clone(), + Self::BlockBeaconPowerSelect { inner } => inner.0.clone(), + Self::BlockBeehiveDrip { inner } => inner.0.clone(), + Self::BlockBeehiveEnter { inner } => inner.0.clone(), + Self::BlockBeehiveExit { inner } => inner.0.clone(), + Self::BlockBeehiveShear { inner } => inner.0.clone(), + Self::BlockBeehiveWork { inner } => inner.0.clone(), + Self::BlockBellResonate { inner } => inner.0.clone(), + Self::BlockBellUse { inner } => inner.0.clone(), + Self::BlockBigDripleafBreak { inner } => inner.0.clone(), + Self::BlockBigDripleafFall { inner } => inner.0.clone(), + Self::BlockBigDripleafHit { inner } => inner.0.clone(), + Self::BlockBigDripleafPlace { inner } => inner.0.clone(), + Self::BlockBigDripleafStep { inner } => inner.0.clone(), + Self::BlockBigDripleafTiltDown { inner } => inner.0.clone(), + Self::BlockBigDripleafTiltUp { inner } => inner.0.clone(), + Self::BlockBlastfurnaceFireCrackle { inner } => inner.0.clone(), + Self::BlockBoneBlockBreak { inner } => inner.0.clone(), + Self::BlockBoneBlockFall { inner } => inner.0.clone(), + Self::BlockBoneBlockHit { inner } => inner.0.clone(), + Self::BlockBoneBlockPlace { inner } => inner.0.clone(), + Self::BlockBoneBlockStep { inner } => inner.0.clone(), + Self::BlockBrewingStandBrew { inner } => inner.0.clone(), + Self::BlockBubbleColumnBubblePop { inner } => inner.0.clone(), + Self::BlockBubbleColumnUpwardsAmbient { inner } => inner.0.clone(), + Self::BlockBubbleColumnUpwardsInside { inner } => inner.0.clone(), + Self::BlockBubbleColumnWhirlpoolAmbient { inner } => inner.0.clone(), + Self::BlockBubbleColumnWhirlpoolInside { inner } => inner.0.clone(), + Self::BlockCakeAddCandle { inner } => inner.0.clone(), + Self::BlockCalciteBreak { inner } => inner.0.clone(), + Self::BlockCalciteFall { inner } => inner.0.clone(), + Self::BlockCalciteHit { inner } => inner.0.clone(), + Self::BlockCalcitePlace { inner } => inner.0.clone(), + Self::BlockCalciteStep { inner } => inner.0.clone(), + Self::BlockCampfireCrackle { inner } => inner.0.clone(), + Self::BlockCandleAmbient { inner } => inner.0.clone(), + Self::BlockCandleBreak { inner } => inner.0.clone(), + Self::BlockCandleExtinguish { inner } => inner.0.clone(), + Self::BlockCandleFall { inner } => inner.0.clone(), + Self::BlockCandleHit { inner } => inner.0.clone(), + Self::BlockCandlePlace { inner } => inner.0.clone(), + Self::BlockCandleStep { inner } => inner.0.clone(), + Self::BlockCaveVinesBreak { inner } => inner.0.clone(), + Self::BlockCaveVinesFall { inner } => inner.0.clone(), + Self::BlockCaveVinesHit { inner } => inner.0.clone(), + Self::BlockCaveVinesPickBerries { inner } => inner.0.clone(), + Self::BlockCaveVinesPlace { inner } => inner.0.clone(), + Self::BlockCaveVinesStep { inner } => inner.0.clone(), + Self::BlockChainBreak { inner } => inner.0.clone(), + Self::BlockChainFall { inner } => inner.0.clone(), + Self::BlockChainHit { inner } => inner.0.clone(), + Self::BlockChainPlace { inner } => inner.0.clone(), + Self::BlockChainStep { inner } => inner.0.clone(), + Self::BlockCherryLeavesBreak { inner } => inner.0.clone(), + Self::BlockCherryLeavesFall { inner } => inner.0.clone(), + Self::BlockCherryLeavesHit { inner } => inner.0.clone(), + Self::BlockCherryLeavesPlace { inner } => inner.0.clone(), + Self::BlockCherryLeavesStep { inner } => inner.0.clone(), + Self::BlockCherrySaplingBreak { inner } => inner.0.clone(), + Self::BlockCherrySaplingFall { inner } => inner.0.clone(), + Self::BlockCherrySaplingHit { inner } => inner.0.clone(), + Self::BlockCherrySaplingPlace { inner } => inner.0.clone(), + Self::BlockCherrySaplingStep { inner } => inner.0.clone(), + Self::BlockCherryWoodBreak { inner } => inner.0.clone(), + Self::BlockCherryWoodButtonClickOff { inner } => inner.0.clone(), + Self::BlockCherryWoodButtonClickOn { inner } => inner.0.clone(), + Self::BlockCherryWoodDoorClose { inner } => inner.0.clone(), + Self::BlockCherryWoodDoorOpen { inner } => inner.0.clone(), + Self::BlockCherryWoodFall { inner } => inner.0.clone(), + Self::BlockCherryWoodFenceGateClose { inner } => inner.0.clone(), + Self::BlockCherryWoodFenceGateOpen { inner } => inner.0.clone(), + Self::BlockCherryWoodHangingSignBreak { inner } => inner.0.clone(), + Self::BlockCherryWoodHangingSignFall { inner } => inner.0.clone(), + Self::BlockCherryWoodHangingSignHit { inner } => inner.0.clone(), + Self::BlockCherryWoodHangingSignPlace { inner } => inner.0.clone(), + Self::BlockCherryWoodHangingSignStep { inner } => inner.0.clone(), + Self::BlockCherryWoodHit { inner } => inner.0.clone(), + Self::BlockCherryWoodPlace { inner } => inner.0.clone(), + Self::BlockCherryWoodPressurePlateClickOff { inner } => inner.0.clone(), + Self::BlockCherryWoodPressurePlateClickOn { inner } => inner.0.clone(), + Self::BlockCherryWoodStep { inner } => inner.0.clone(), + Self::BlockCherryWoodTrapdoorClose { inner } => inner.0.clone(), + Self::BlockCherryWoodTrapdoorOpen { inner } => inner.0.clone(), + Self::BlockChestClose { inner } => inner.0.clone(), + Self::BlockChestLocked { inner } => inner.0.clone(), + Self::BlockChestOpen { inner } => inner.0.clone(), + Self::BlockChiseledBookshelfBreak { inner } => inner.0.clone(), + Self::BlockChiseledBookshelfFall { inner } => inner.0.clone(), + Self::BlockChiseledBookshelfHit { inner } => inner.0.clone(), + Self::BlockChiseledBookshelfInsert { inner } => inner.0.clone(), + Self::BlockChiseledBookshelfInsertEnchanted { inner } => inner.0.clone(), + Self::BlockChiseledBookshelfPickup { inner } => inner.0.clone(), + Self::BlockChiseledBookshelfPickupEnchanted { inner } => inner.0.clone(), + Self::BlockChiseledBookshelfPlace { inner } => inner.0.clone(), + Self::BlockChiseledBookshelfStep { inner } => inner.0.clone(), + Self::BlockChorusFlowerDeath { inner } => inner.0.clone(), + Self::BlockChorusFlowerGrow { inner } => inner.0.clone(), + Self::BlockCobwebBreak { inner } => inner.0.clone(), + Self::BlockCobwebFall { inner } => inner.0.clone(), + Self::BlockCobwebHit { inner } => inner.0.clone(), + Self::BlockCobwebPlace { inner } => inner.0.clone(), + Self::BlockCobwebStep { inner } => inner.0.clone(), + Self::BlockComparatorClick { inner } => inner.0.clone(), + Self::BlockComposterEmpty { inner } => inner.0.clone(), + Self::BlockComposterFill { inner } => inner.0.clone(), + Self::BlockComposterFillSuccess { inner } => inner.0.clone(), + Self::BlockComposterReady { inner } => inner.0.clone(), + Self::BlockConduitActivate { inner } => inner.0.clone(), + Self::BlockConduitAmbient { inner } => inner.0.clone(), + Self::BlockConduitAmbientShort { inner } => inner.0.clone(), + Self::BlockConduitAttackTarget { inner } => inner.0.clone(), + Self::BlockConduitDeactivate { inner } => inner.0.clone(), + Self::BlockCopperBreak { inner } => inner.0.clone(), + Self::BlockCopperBulbBreak { inner } => inner.0.clone(), + Self::BlockCopperBulbFall { inner } => inner.0.clone(), + Self::BlockCopperBulbHit { inner } => inner.0.clone(), + Self::BlockCopperBulbPlace { inner } => inner.0.clone(), + Self::BlockCopperBulbStep { inner } => inner.0.clone(), + Self::BlockCopperBulbTurnOff { inner } => inner.0.clone(), + Self::BlockCopperBulbTurnOn { inner } => inner.0.clone(), + Self::BlockCopperDoorClose { inner } => inner.0.clone(), + Self::BlockCopperDoorOpen { inner } => inner.0.clone(), + Self::BlockCopperFall { inner } => inner.0.clone(), + Self::BlockCopperGrateBreak { inner } => inner.0.clone(), + Self::BlockCopperGrateFall { inner } => inner.0.clone(), + Self::BlockCopperGrateHit { inner } => inner.0.clone(), + Self::BlockCopperGratePlace { inner } => inner.0.clone(), + Self::BlockCopperGrateStep { inner } => inner.0.clone(), + Self::BlockCopperHit { inner } => inner.0.clone(), + Self::BlockCopperPlace { inner } => inner.0.clone(), + Self::BlockCopperStep { inner } => inner.0.clone(), + Self::BlockCopperTrapdoorClose { inner } => inner.0.clone(), + Self::BlockCopperTrapdoorOpen { inner } => inner.0.clone(), + Self::BlockCoralBlockBreak { inner } => inner.0.clone(), + Self::BlockCoralBlockFall { inner } => inner.0.clone(), + Self::BlockCoralBlockHit { inner } => inner.0.clone(), + Self::BlockCoralBlockPlace { inner } => inner.0.clone(), + Self::BlockCoralBlockStep { inner } => inner.0.clone(), + Self::BlockCrafterCraft { inner } => inner.0.clone(), + Self::BlockCrafterFail { inner } => inner.0.clone(), + Self::BlockCropBreak { inner } => inner.0.clone(), + Self::BlockDecoratedPotBreak { inner } => inner.0.clone(), + Self::BlockDecoratedPotFall { inner } => inner.0.clone(), + Self::BlockDecoratedPotHit { inner } => inner.0.clone(), + Self::BlockDecoratedPotInsert { inner } => inner.0.clone(), + Self::BlockDecoratedPotInsertFail { inner } => inner.0.clone(), + Self::BlockDecoratedPotPlace { inner } => inner.0.clone(), + Self::BlockDecoratedPotShatter { inner } => inner.0.clone(), + Self::BlockDecoratedPotStep { inner } => inner.0.clone(), + Self::BlockDeepslateBreak { inner } => inner.0.clone(), + Self::BlockDeepslateBricksBreak { inner } => inner.0.clone(), + Self::BlockDeepslateBricksFall { inner } => inner.0.clone(), + Self::BlockDeepslateBricksHit { inner } => inner.0.clone(), + Self::BlockDeepslateBricksPlace { inner } => inner.0.clone(), + Self::BlockDeepslateBricksStep { inner } => inner.0.clone(), + Self::BlockDeepslateFall { inner } => inner.0.clone(), + Self::BlockDeepslateHit { inner } => inner.0.clone(), + Self::BlockDeepslatePlace { inner } => inner.0.clone(), + Self::BlockDeepslateStep { inner } => inner.0.clone(), + Self::BlockDeepslateTilesBreak { inner } => inner.0.clone(), + Self::BlockDeepslateTilesFall { inner } => inner.0.clone(), + Self::BlockDeepslateTilesHit { inner } => inner.0.clone(), + Self::BlockDeepslateTilesPlace { inner } => inner.0.clone(), + Self::BlockDeepslateTilesStep { inner } => inner.0.clone(), + Self::BlockDispenserDispense { inner } => inner.0.clone(), + Self::BlockDispenserFail { inner } => inner.0.clone(), + Self::BlockDispenserLaunch { inner } => inner.0.clone(), + Self::BlockDripstoneBlockBreak { inner } => inner.0.clone(), + Self::BlockDripstoneBlockFall { inner } => inner.0.clone(), + Self::BlockDripstoneBlockHit { inner } => inner.0.clone(), + Self::BlockDripstoneBlockPlace { inner } => inner.0.clone(), + Self::BlockDripstoneBlockStep { inner } => inner.0.clone(), + Self::BlockEnchantmentTableUse { inner } => inner.0.clone(), + Self::BlockEnderChestClose { inner } => inner.0.clone(), + Self::BlockEnderChestOpen { inner } => inner.0.clone(), + Self::BlockEndGatewaySpawn { inner } => inner.0.clone(), + Self::BlockEndPortalFrameFill { inner } => inner.0.clone(), + Self::BlockEndPortalSpawn { inner } => inner.0.clone(), + Self::BlockFenceGateClose { inner } => inner.0.clone(), + Self::BlockFenceGateOpen { inner } => inner.0.clone(), + Self::BlockFireAmbient { inner } => inner.0.clone(), + Self::BlockFireExtinguish { inner } => inner.0.clone(), + Self::BlockFloweringAzaleaBreak { inner } => inner.0.clone(), + Self::BlockFloweringAzaleaFall { inner } => inner.0.clone(), + Self::BlockFloweringAzaleaHit { inner } => inner.0.clone(), + Self::BlockFloweringAzaleaPlace { inner } => inner.0.clone(), + Self::BlockFloweringAzaleaStep { inner } => inner.0.clone(), + Self::BlockFroglightBreak { inner } => inner.0.clone(), + Self::BlockFroglightFall { inner } => inner.0.clone(), + Self::BlockFroglightHit { inner } => inner.0.clone(), + Self::BlockFroglightPlace { inner } => inner.0.clone(), + Self::BlockFroglightStep { inner } => inner.0.clone(), + Self::BlockFrogspawnBreak { inner } => inner.0.clone(), + Self::BlockFrogspawnFall { inner } => inner.0.clone(), + Self::BlockFrogspawnHatch { inner } => inner.0.clone(), + Self::BlockFrogspawnHit { inner } => inner.0.clone(), + Self::BlockFrogspawnPlace { inner } => inner.0.clone(), + Self::BlockFrogspawnStep { inner } => inner.0.clone(), + Self::BlockFungusBreak { inner } => inner.0.clone(), + Self::BlockFungusFall { inner } => inner.0.clone(), + Self::BlockFungusHit { inner } => inner.0.clone(), + Self::BlockFungusPlace { inner } => inner.0.clone(), + Self::BlockFungusStep { inner } => inner.0.clone(), + Self::BlockFurnaceFireCrackle { inner } => inner.0.clone(), + Self::BlockGildedBlackstoneBreak { inner } => inner.0.clone(), + Self::BlockGildedBlackstoneFall { inner } => inner.0.clone(), + Self::BlockGildedBlackstoneHit { inner } => inner.0.clone(), + Self::BlockGildedBlackstonePlace { inner } => inner.0.clone(), + Self::BlockGildedBlackstoneStep { inner } => inner.0.clone(), + Self::BlockGlassBreak { inner } => inner.0.clone(), + Self::BlockGlassFall { inner } => inner.0.clone(), + Self::BlockGlassHit { inner } => inner.0.clone(), + Self::BlockGlassPlace { inner } => inner.0.clone(), + Self::BlockGlassStep { inner } => inner.0.clone(), + Self::BlockGrassBreak { inner } => inner.0.clone(), + Self::BlockGrassFall { inner } => inner.0.clone(), + Self::BlockGrassHit { inner } => inner.0.clone(), + Self::BlockGrassPlace { inner } => inner.0.clone(), + Self::BlockGrassStep { inner } => inner.0.clone(), + Self::BlockGravelBreak { inner } => inner.0.clone(), + Self::BlockGravelFall { inner } => inner.0.clone(), + Self::BlockGravelHit { inner } => inner.0.clone(), + Self::BlockGravelPlace { inner } => inner.0.clone(), + Self::BlockGravelStep { inner } => inner.0.clone(), + Self::BlockGrindstoneUse { inner } => inner.0.clone(), + Self::BlockGrowingPlantCrop { inner } => inner.0.clone(), + Self::BlockHangingRootsBreak { inner } => inner.0.clone(), + Self::BlockHangingRootsFall { inner } => inner.0.clone(), + Self::BlockHangingRootsHit { inner } => inner.0.clone(), + Self::BlockHangingRootsPlace { inner } => inner.0.clone(), + Self::BlockHangingRootsStep { inner } => inner.0.clone(), + Self::BlockHangingSignBreak { inner } => inner.0.clone(), + Self::BlockHangingSignFall { inner } => inner.0.clone(), + Self::BlockHangingSignHit { inner } => inner.0.clone(), + Self::BlockHangingSignPlace { inner } => inner.0.clone(), + Self::BlockHangingSignStep { inner } => inner.0.clone(), + Self::BlockHangingSignWaxedInteractFail { inner } => inner.0.clone(), + Self::BlockHeavyCoreBreak { inner } => inner.0.clone(), + Self::BlockHeavyCoreFall { inner } => inner.0.clone(), + Self::BlockHeavyCoreHit { inner } => inner.0.clone(), + Self::BlockHeavyCorePlace { inner } => inner.0.clone(), + Self::BlockHeavyCoreStep { inner } => inner.0.clone(), + Self::BlockHoneyBlockBreak { inner } => inner.0.clone(), + Self::BlockHoneyBlockFall { inner } => inner.0.clone(), + Self::BlockHoneyBlockHit { inner } => inner.0.clone(), + Self::BlockHoneyBlockPlace { inner } => inner.0.clone(), + Self::BlockHoneyBlockSlide { inner } => inner.0.clone(), + Self::BlockHoneyBlockStep { inner } => inner.0.clone(), + Self::BlockIronDoorClose { inner } => inner.0.clone(), + Self::BlockIronDoorOpen { inner } => inner.0.clone(), + Self::BlockIronTrapdoorClose { inner } => inner.0.clone(), + Self::BlockIronTrapdoorOpen { inner } => inner.0.clone(), + Self::BlockLadderBreak { inner } => inner.0.clone(), + Self::BlockLadderFall { inner } => inner.0.clone(), + Self::BlockLadderHit { inner } => inner.0.clone(), + Self::BlockLadderPlace { inner } => inner.0.clone(), + Self::BlockLadderStep { inner } => inner.0.clone(), + Self::BlockLanternBreak { inner } => inner.0.clone(), + Self::BlockLanternFall { inner } => inner.0.clone(), + Self::BlockLanternHit { inner } => inner.0.clone(), + Self::BlockLanternPlace { inner } => inner.0.clone(), + Self::BlockLanternStep { inner } => inner.0.clone(), + Self::BlockLargeAmethystBudBreak { inner } => inner.0.clone(), + Self::BlockLargeAmethystBudPlace { inner } => inner.0.clone(), + Self::BlockLavaAmbient { inner } => inner.0.clone(), + Self::BlockLavaExtinguish { inner } => inner.0.clone(), + Self::BlockLavaPop { inner } => inner.0.clone(), + Self::BlockLeverClick { inner } => inner.0.clone(), + Self::BlockLilyPadPlace { inner } => inner.0.clone(), + Self::BlockLodestoneBreak { inner } => inner.0.clone(), + Self::BlockLodestoneFall { inner } => inner.0.clone(), + Self::BlockLodestoneHit { inner } => inner.0.clone(), + Self::BlockLodestonePlace { inner } => inner.0.clone(), + Self::BlockLodestoneStep { inner } => inner.0.clone(), + Self::BlockMangroveRootsBreak { inner } => inner.0.clone(), + Self::BlockMangroveRootsFall { inner } => inner.0.clone(), + Self::BlockMangroveRootsHit { inner } => inner.0.clone(), + Self::BlockMangroveRootsPlace { inner } => inner.0.clone(), + Self::BlockMangroveRootsStep { inner } => inner.0.clone(), + Self::BlockMediumAmethystBudBreak { inner } => inner.0.clone(), + Self::BlockMediumAmethystBudPlace { inner } => inner.0.clone(), + Self::BlockMetalBreak { inner } => inner.0.clone(), + Self::BlockMetalFall { inner } => inner.0.clone(), + Self::BlockMetalHit { inner } => inner.0.clone(), + Self::BlockMetalPlace { inner } => inner.0.clone(), + Self::BlockMetalPressurePlateClickOff { inner } => inner.0.clone(), + Self::BlockMetalPressurePlateClickOn { inner } => inner.0.clone(), + Self::BlockMetalStep { inner } => inner.0.clone(), + Self::BlockMossBreak { inner } => inner.0.clone(), + Self::BlockMossCarpetBreak { inner } => inner.0.clone(), + Self::BlockMossCarpetFall { inner } => inner.0.clone(), + Self::BlockMossCarpetHit { inner } => inner.0.clone(), + Self::BlockMossCarpetPlace { inner } => inner.0.clone(), + Self::BlockMossCarpetStep { inner } => inner.0.clone(), + Self::BlockMossFall { inner } => inner.0.clone(), + Self::BlockMossHit { inner } => inner.0.clone(), + Self::BlockMossPlace { inner } => inner.0.clone(), + Self::BlockMossStep { inner } => inner.0.clone(), + Self::BlockMuddyMangroveRootsBreak { inner } => inner.0.clone(), + Self::BlockMuddyMangroveRootsFall { inner } => inner.0.clone(), + Self::BlockMuddyMangroveRootsHit { inner } => inner.0.clone(), + Self::BlockMuddyMangroveRootsPlace { inner } => inner.0.clone(), + Self::BlockMuddyMangroveRootsStep { inner } => inner.0.clone(), + Self::BlockMudBreak { inner } => inner.0.clone(), + Self::BlockMudBricksBreak { inner } => inner.0.clone(), + Self::BlockMudBricksFall { inner } => inner.0.clone(), + Self::BlockMudBricksHit { inner } => inner.0.clone(), + Self::BlockMudBricksPlace { inner } => inner.0.clone(), + Self::BlockMudBricksStep { inner } => inner.0.clone(), + Self::BlockMudFall { inner } => inner.0.clone(), + Self::BlockMudHit { inner } => inner.0.clone(), + Self::BlockMudPlace { inner } => inner.0.clone(), + Self::BlockMudStep { inner } => inner.0.clone(), + Self::BlockNetheriteBlockBreak { inner } => inner.0.clone(), + Self::BlockNetheriteBlockFall { inner } => inner.0.clone(), + Self::BlockNetheriteBlockHit { inner } => inner.0.clone(), + Self::BlockNetheriteBlockPlace { inner } => inner.0.clone(), + Self::BlockNetheriteBlockStep { inner } => inner.0.clone(), + Self::BlockNetherrackBreak { inner } => inner.0.clone(), + Self::BlockNetherrackFall { inner } => inner.0.clone(), + Self::BlockNetherrackHit { inner } => inner.0.clone(), + Self::BlockNetherrackPlace { inner } => inner.0.clone(), + Self::BlockNetherrackStep { inner } => inner.0.clone(), + Self::BlockNetherBricksBreak { inner } => inner.0.clone(), + Self::BlockNetherBricksFall { inner } => inner.0.clone(), + Self::BlockNetherBricksHit { inner } => inner.0.clone(), + Self::BlockNetherBricksPlace { inner } => inner.0.clone(), + Self::BlockNetherBricksStep { inner } => inner.0.clone(), + Self::BlockNetherGoldOreBreak { inner } => inner.0.clone(), + Self::BlockNetherGoldOreFall { inner } => inner.0.clone(), + Self::BlockNetherGoldOreHit { inner } => inner.0.clone(), + Self::BlockNetherGoldOrePlace { inner } => inner.0.clone(), + Self::BlockNetherGoldOreStep { inner } => inner.0.clone(), + Self::BlockNetherOreBreak { inner } => inner.0.clone(), + Self::BlockNetherOreFall { inner } => inner.0.clone(), + Self::BlockNetherOreHit { inner } => inner.0.clone(), + Self::BlockNetherOrePlace { inner } => inner.0.clone(), + Self::BlockNetherOreStep { inner } => inner.0.clone(), + Self::BlockNetherSproutsBreak { inner } => inner.0.clone(), + Self::BlockNetherSproutsFall { inner } => inner.0.clone(), + Self::BlockNetherSproutsHit { inner } => inner.0.clone(), + Self::BlockNetherSproutsPlace { inner } => inner.0.clone(), + Self::BlockNetherSproutsStep { inner } => inner.0.clone(), + Self::BlockNetherWartBreak { inner } => inner.0.clone(), + Self::BlockNetherWoodBreak { inner } => inner.0.clone(), + Self::BlockNetherWoodButtonClickOff { inner } => inner.0.clone(), + Self::BlockNetherWoodButtonClickOn { inner } => inner.0.clone(), + Self::BlockNetherWoodDoorClose { inner } => inner.0.clone(), + Self::BlockNetherWoodDoorOpen { inner } => inner.0.clone(), + Self::BlockNetherWoodFall { inner } => inner.0.clone(), + Self::BlockNetherWoodFenceGateClose { inner } => inner.0.clone(), + Self::BlockNetherWoodFenceGateOpen { inner } => inner.0.clone(), + Self::BlockNetherWoodHangingSignBreak { inner } => inner.0.clone(), + Self::BlockNetherWoodHangingSignFall { inner } => inner.0.clone(), + Self::BlockNetherWoodHangingSignHit { inner } => inner.0.clone(), + Self::BlockNetherWoodHangingSignPlace { inner } => inner.0.clone(), + Self::BlockNetherWoodHangingSignStep { inner } => inner.0.clone(), + Self::BlockNetherWoodHit { inner } => inner.0.clone(), + Self::BlockNetherWoodPlace { inner } => inner.0.clone(), + Self::BlockNetherWoodPressurePlateClickOff { inner } => inner.0.clone(), + Self::BlockNetherWoodPressurePlateClickOn { inner } => inner.0.clone(), + Self::BlockNetherWoodStep { inner } => inner.0.clone(), + Self::BlockNetherWoodTrapdoorClose { inner } => inner.0.clone(), + Self::BlockNetherWoodTrapdoorOpen { inner } => inner.0.clone(), + Self::BlockNoteBlockBanjo { inner } => inner.0.clone(), + Self::BlockNoteBlockBasedrum { inner } => inner.0.clone(), + Self::BlockNoteBlockBass { inner } => inner.0.clone(), + Self::BlockNoteBlockBell { inner } => inner.0.clone(), + Self::BlockNoteBlockBit { inner } => inner.0.clone(), + Self::BlockNoteBlockChime { inner } => inner.0.clone(), + Self::BlockNoteBlockCowBell { inner } => inner.0.clone(), + Self::BlockNoteBlockDidgeridoo { inner } => inner.0.clone(), + Self::BlockNoteBlockFlute { inner } => inner.0.clone(), + Self::BlockNoteBlockGuitar { inner } => inner.0.clone(), + Self::BlockNoteBlockHarp { inner } => inner.0.clone(), + Self::BlockNoteBlockHat { inner } => inner.0.clone(), + Self::BlockNoteBlockImitateCreeper { inner } => inner.0.clone(), + Self::BlockNoteBlockImitateEnderDragon { inner } => inner.0.clone(), + Self::BlockNoteBlockImitatePiglin { inner } => inner.0.clone(), + Self::BlockNoteBlockImitateSkeleton { inner } => inner.0.clone(), + Self::BlockNoteBlockImitateWitherSkeleton { inner } => inner.0.clone(), + Self::BlockNoteBlockImitateZombie { inner } => inner.0.clone(), + Self::BlockNoteBlockIronXylophone { inner } => inner.0.clone(), + Self::BlockNoteBlockPling { inner } => inner.0.clone(), + Self::BlockNoteBlockSnare { inner } => inner.0.clone(), + Self::BlockNoteBlockXylophone { inner } => inner.0.clone(), + Self::BlockNyliumBreak { inner } => inner.0.clone(), + Self::BlockNyliumFall { inner } => inner.0.clone(), + Self::BlockNyliumHit { inner } => inner.0.clone(), + Self::BlockNyliumPlace { inner } => inner.0.clone(), + Self::BlockNyliumStep { inner } => inner.0.clone(), + Self::BlockPackedMudBreak { inner } => inner.0.clone(), + Self::BlockPackedMudFall { inner } => inner.0.clone(), + Self::BlockPackedMudHit { inner } => inner.0.clone(), + Self::BlockPackedMudPlace { inner } => inner.0.clone(), + Self::BlockPackedMudStep { inner } => inner.0.clone(), + Self::BlockPinkPetalsBreak { inner } => inner.0.clone(), + Self::BlockPinkPetalsFall { inner } => inner.0.clone(), + Self::BlockPinkPetalsHit { inner } => inner.0.clone(), + Self::BlockPinkPetalsPlace { inner } => inner.0.clone(), + Self::BlockPinkPetalsStep { inner } => inner.0.clone(), + Self::BlockPistonContract { inner } => inner.0.clone(), + Self::BlockPistonExtend { inner } => inner.0.clone(), + Self::BlockPointedDripstoneBreak { inner } => inner.0.clone(), + Self::BlockPointedDripstoneDripLava { inner } => inner.0.clone(), + Self::BlockPointedDripstoneDripLavaIntoCauldron { inner } => inner.0.clone(), + Self::BlockPointedDripstoneDripWater { inner } => inner.0.clone(), + Self::BlockPointedDripstoneDripWaterIntoCauldron { inner } => inner.0.clone(), + Self::BlockPointedDripstoneFall { inner } => inner.0.clone(), + Self::BlockPointedDripstoneHit { inner } => inner.0.clone(), + Self::BlockPointedDripstoneLand { inner } => inner.0.clone(), + Self::BlockPointedDripstonePlace { inner } => inner.0.clone(), + Self::BlockPointedDripstoneStep { inner } => inner.0.clone(), + Self::BlockPolishedDeepslateBreak { inner } => inner.0.clone(), + Self::BlockPolishedDeepslateFall { inner } => inner.0.clone(), + Self::BlockPolishedDeepslateHit { inner } => inner.0.clone(), + Self::BlockPolishedDeepslatePlace { inner } => inner.0.clone(), + Self::BlockPolishedDeepslateStep { inner } => inner.0.clone(), + Self::BlockPolishedTuffBreak { inner } => inner.0.clone(), + Self::BlockPolishedTuffFall { inner } => inner.0.clone(), + Self::BlockPolishedTuffHit { inner } => inner.0.clone(), + Self::BlockPolishedTuffPlace { inner } => inner.0.clone(), + Self::BlockPolishedTuffStep { inner } => inner.0.clone(), + Self::BlockPortalAmbient { inner } => inner.0.clone(), + Self::BlockPortalTravel { inner } => inner.0.clone(), + Self::BlockPortalTrigger { inner } => inner.0.clone(), + Self::BlockPowderSnowBreak { inner } => inner.0.clone(), + Self::BlockPowderSnowFall { inner } => inner.0.clone(), + Self::BlockPowderSnowHit { inner } => inner.0.clone(), + Self::BlockPowderSnowPlace { inner } => inner.0.clone(), + Self::BlockPowderSnowStep { inner } => inner.0.clone(), + Self::BlockPumpkinCarve { inner } => inner.0.clone(), + Self::BlockRedstoneTorchBurnout { inner } => inner.0.clone(), + Self::BlockRespawnAnchorAmbient { inner } => inner.0.clone(), + Self::BlockRespawnAnchorCharge { inner } => inner.0.clone(), + Self::BlockRespawnAnchorDeplete { inner } => inner.0.clone(), + Self::BlockRespawnAnchorSetSpawn { inner } => inner.0.clone(), + Self::BlockRootedDirtBreak { inner } => inner.0.clone(), + Self::BlockRootedDirtFall { inner } => inner.0.clone(), + Self::BlockRootedDirtHit { inner } => inner.0.clone(), + Self::BlockRootedDirtPlace { inner } => inner.0.clone(), + Self::BlockRootedDirtStep { inner } => inner.0.clone(), + Self::BlockRootsBreak { inner } => inner.0.clone(), + Self::BlockRootsFall { inner } => inner.0.clone(), + Self::BlockRootsHit { inner } => inner.0.clone(), + Self::BlockRootsPlace { inner } => inner.0.clone(), + Self::BlockRootsStep { inner } => inner.0.clone(), + Self::BlockSandBreak { inner } => inner.0.clone(), + Self::BlockSandFall { inner } => inner.0.clone(), + Self::BlockSandHit { inner } => inner.0.clone(), + Self::BlockSandPlace { inner } => inner.0.clone(), + Self::BlockSandStep { inner } => inner.0.clone(), + Self::BlockScaffoldingBreak { inner } => inner.0.clone(), + Self::BlockScaffoldingFall { inner } => inner.0.clone(), + Self::BlockScaffoldingHit { inner } => inner.0.clone(), + Self::BlockScaffoldingPlace { inner } => inner.0.clone(), + Self::BlockScaffoldingStep { inner } => inner.0.clone(), + Self::BlockSculkBreak { inner } => inner.0.clone(), + Self::BlockSculkCatalystBloom { inner } => inner.0.clone(), + Self::BlockSculkCatalystBreak { inner } => inner.0.clone(), + Self::BlockSculkCatalystFall { inner } => inner.0.clone(), + Self::BlockSculkCatalystHit { inner } => inner.0.clone(), + Self::BlockSculkCatalystPlace { inner } => inner.0.clone(), + Self::BlockSculkCatalystStep { inner } => inner.0.clone(), + Self::BlockSculkCharge { inner } => inner.0.clone(), + Self::BlockSculkFall { inner } => inner.0.clone(), + Self::BlockSculkHit { inner } => inner.0.clone(), + Self::BlockSculkPlace { inner } => inner.0.clone(), + Self::BlockSculkSensorBreak { inner } => inner.0.clone(), + Self::BlockSculkSensorClicking { inner } => inner.0.clone(), + Self::BlockSculkSensorClickingStop { inner } => inner.0.clone(), + Self::BlockSculkSensorFall { inner } => inner.0.clone(), + Self::BlockSculkSensorHit { inner } => inner.0.clone(), + Self::BlockSculkSensorPlace { inner } => inner.0.clone(), + Self::BlockSculkSensorStep { inner } => inner.0.clone(), + Self::BlockSculkShriekerBreak { inner } => inner.0.clone(), + Self::BlockSculkShriekerFall { inner } => inner.0.clone(), + Self::BlockSculkShriekerHit { inner } => inner.0.clone(), + Self::BlockSculkShriekerPlace { inner } => inner.0.clone(), + Self::BlockSculkShriekerShriek { inner } => inner.0.clone(), + Self::BlockSculkShriekerStep { inner } => inner.0.clone(), + Self::BlockSculkSpread { inner } => inner.0.clone(), + Self::BlockSculkStep { inner } => inner.0.clone(), + Self::BlockSculkVeinBreak { inner } => inner.0.clone(), + Self::BlockSculkVeinFall { inner } => inner.0.clone(), + Self::BlockSculkVeinHit { inner } => inner.0.clone(), + Self::BlockSculkVeinPlace { inner } => inner.0.clone(), + Self::BlockSculkVeinStep { inner } => inner.0.clone(), + Self::BlockShroomlightBreak { inner } => inner.0.clone(), + Self::BlockShroomlightFall { inner } => inner.0.clone(), + Self::BlockShroomlightHit { inner } => inner.0.clone(), + Self::BlockShroomlightPlace { inner } => inner.0.clone(), + Self::BlockShroomlightStep { inner } => inner.0.clone(), + Self::BlockShulkerBoxClose { inner } => inner.0.clone(), + Self::BlockShulkerBoxOpen { inner } => inner.0.clone(), + Self::BlockSignWaxedInteractFail { inner } => inner.0.clone(), + Self::BlockSlimeBlockBreak { inner } => inner.0.clone(), + Self::BlockSlimeBlockFall { inner } => inner.0.clone(), + Self::BlockSlimeBlockHit { inner } => inner.0.clone(), + Self::BlockSlimeBlockPlace { inner } => inner.0.clone(), + Self::BlockSlimeBlockStep { inner } => inner.0.clone(), + Self::BlockSmallAmethystBudBreak { inner } => inner.0.clone(), + Self::BlockSmallAmethystBudPlace { inner } => inner.0.clone(), + Self::BlockSmallDripleafBreak { inner } => inner.0.clone(), + Self::BlockSmallDripleafFall { inner } => inner.0.clone(), + Self::BlockSmallDripleafHit { inner } => inner.0.clone(), + Self::BlockSmallDripleafPlace { inner } => inner.0.clone(), + Self::BlockSmallDripleafStep { inner } => inner.0.clone(), + Self::BlockSmithingTableUse { inner } => inner.0.clone(), + Self::BlockSmokerSmoke { inner } => inner.0.clone(), + Self::BlockSnifferEggCrack { inner } => inner.0.clone(), + Self::BlockSnifferEggHatch { inner } => inner.0.clone(), + Self::BlockSnifferEggPlop { inner } => inner.0.clone(), + Self::BlockSnowBreak { inner } => inner.0.clone(), + Self::BlockSnowFall { inner } => inner.0.clone(), + Self::BlockSnowHit { inner } => inner.0.clone(), + Self::BlockSnowPlace { inner } => inner.0.clone(), + Self::BlockSnowStep { inner } => inner.0.clone(), + Self::BlockSoulSandBreak { inner } => inner.0.clone(), + Self::BlockSoulSandFall { inner } => inner.0.clone(), + Self::BlockSoulSandHit { inner } => inner.0.clone(), + Self::BlockSoulSandPlace { inner } => inner.0.clone(), + Self::BlockSoulSandStep { inner } => inner.0.clone(), + Self::BlockSoulSoilBreak { inner } => inner.0.clone(), + Self::BlockSoulSoilFall { inner } => inner.0.clone(), + Self::BlockSoulSoilHit { inner } => inner.0.clone(), + Self::BlockSoulSoilPlace { inner } => inner.0.clone(), + Self::BlockSoulSoilStep { inner } => inner.0.clone(), + Self::BlockSpongeAbsorb { inner } => inner.0.clone(), + Self::BlockSpongeBreak { inner } => inner.0.clone(), + Self::BlockSpongeFall { inner } => inner.0.clone(), + Self::BlockSpongeHit { inner } => inner.0.clone(), + Self::BlockSpongePlace { inner } => inner.0.clone(), + Self::BlockSpongeStep { inner } => inner.0.clone(), + Self::BlockSporeBlossomBreak { inner } => inner.0.clone(), + Self::BlockSporeBlossomFall { inner } => inner.0.clone(), + Self::BlockSporeBlossomHit { inner } => inner.0.clone(), + Self::BlockSporeBlossomPlace { inner } => inner.0.clone(), + Self::BlockSporeBlossomStep { inner } => inner.0.clone(), + Self::BlockStemBreak { inner } => inner.0.clone(), + Self::BlockStemFall { inner } => inner.0.clone(), + Self::BlockStemHit { inner } => inner.0.clone(), + Self::BlockStemPlace { inner } => inner.0.clone(), + Self::BlockStemStep { inner } => inner.0.clone(), + Self::BlockStoneBreak { inner } => inner.0.clone(), + Self::BlockStoneButtonClickOff { inner } => inner.0.clone(), + Self::BlockStoneButtonClickOn { inner } => inner.0.clone(), + Self::BlockStoneFall { inner } => inner.0.clone(), + Self::BlockStoneHit { inner } => inner.0.clone(), + Self::BlockStonePlace { inner } => inner.0.clone(), + Self::BlockStonePressurePlateClickOff { inner } => inner.0.clone(), + Self::BlockStonePressurePlateClickOn { inner } => inner.0.clone(), + Self::BlockStoneStep { inner } => inner.0.clone(), + Self::BlockSuspiciousGravelBreak { inner } => inner.0.clone(), + Self::BlockSuspiciousGravelFall { inner } => inner.0.clone(), + Self::BlockSuspiciousGravelHit { inner } => inner.0.clone(), + Self::BlockSuspiciousGravelPlace { inner } => inner.0.clone(), + Self::BlockSuspiciousGravelStep { inner } => inner.0.clone(), + Self::BlockSuspiciousSandBreak { inner } => inner.0.clone(), + Self::BlockSuspiciousSandFall { inner } => inner.0.clone(), + Self::BlockSuspiciousSandHit { inner } => inner.0.clone(), + Self::BlockSuspiciousSandPlace { inner } => inner.0.clone(), + Self::BlockSuspiciousSandStep { inner } => inner.0.clone(), + Self::BlockSweetBerryBushBreak { inner } => inner.0.clone(), + Self::BlockSweetBerryBushPickBerries { inner } => inner.0.clone(), + Self::BlockSweetBerryBushPlace { inner } => inner.0.clone(), + Self::BlockTrialSpawnerAboutToSpawnItem { inner } => inner.0.clone(), + Self::BlockTrialSpawnerAmbient { inner } => inner.0.clone(), + Self::BlockTrialSpawnerAmbientOminous { inner } => inner.0.clone(), + Self::BlockTrialSpawnerBreak { inner } => inner.0.clone(), + Self::BlockTrialSpawnerCloseShutter { inner } => inner.0.clone(), + Self::BlockTrialSpawnerDetectPlayer { inner } => inner.0.clone(), + Self::BlockTrialSpawnerEjectItem { inner } => inner.0.clone(), + Self::BlockTrialSpawnerFall { inner } => inner.0.clone(), + Self::BlockTrialSpawnerHit { inner } => inner.0.clone(), + Self::BlockTrialSpawnerOminousActivate { inner } => inner.0.clone(), + Self::BlockTrialSpawnerOpenShutter { inner } => inner.0.clone(), + Self::BlockTrialSpawnerPlace { inner } => inner.0.clone(), + Self::BlockTrialSpawnerSpawnItem { inner } => inner.0.clone(), + Self::BlockTrialSpawnerSpawnItemBegin { inner } => inner.0.clone(), + Self::BlockTrialSpawnerSpawnMob { inner } => inner.0.clone(), + Self::BlockTrialSpawnerStep { inner } => inner.0.clone(), + Self::BlockTripwireAttach { inner } => inner.0.clone(), + Self::BlockTripwireClickOff { inner } => inner.0.clone(), + Self::BlockTripwireClickOn { inner } => inner.0.clone(), + Self::BlockTripwireDetach { inner } => inner.0.clone(), + Self::BlockTuffBreak { inner } => inner.0.clone(), + Self::BlockTuffBricksBreak { inner } => inner.0.clone(), + Self::BlockTuffBricksFall { inner } => inner.0.clone(), + Self::BlockTuffBricksHit { inner } => inner.0.clone(), + Self::BlockTuffBricksPlace { inner } => inner.0.clone(), + Self::BlockTuffBricksStep { inner } => inner.0.clone(), + Self::BlockTuffFall { inner } => inner.0.clone(), + Self::BlockTuffHit { inner } => inner.0.clone(), + Self::BlockTuffPlace { inner } => inner.0.clone(), + Self::BlockTuffStep { inner } => inner.0.clone(), + Self::BlockVaultActivate { inner } => inner.0.clone(), + Self::BlockVaultAmbient { inner } => inner.0.clone(), + Self::BlockVaultBreak { inner } => inner.0.clone(), + Self::BlockVaultCloseShutter { inner } => inner.0.clone(), + Self::BlockVaultDeactivate { inner } => inner.0.clone(), + Self::BlockVaultEjectItem { inner } => inner.0.clone(), + Self::BlockVaultFall { inner } => inner.0.clone(), + Self::BlockVaultHit { inner } => inner.0.clone(), + Self::BlockVaultInsertItem { inner } => inner.0.clone(), + Self::BlockVaultInsertItemFail { inner } => inner.0.clone(), + Self::BlockVaultOpenShutter { inner } => inner.0.clone(), + Self::BlockVaultPlace { inner } => inner.0.clone(), + Self::BlockVaultRejectRewardedPlayer { inner } => inner.0.clone(), + Self::BlockVaultStep { inner } => inner.0.clone(), + Self::BlockVineBreak { inner } => inner.0.clone(), + Self::BlockVineFall { inner } => inner.0.clone(), + Self::BlockVineHit { inner } => inner.0.clone(), + Self::BlockVinePlace { inner } => inner.0.clone(), + Self::BlockVineStep { inner } => inner.0.clone(), + Self::BlockWartBlockBreak { inner } => inner.0.clone(), + Self::BlockWartBlockFall { inner } => inner.0.clone(), + Self::BlockWartBlockHit { inner } => inner.0.clone(), + Self::BlockWartBlockPlace { inner } => inner.0.clone(), + Self::BlockWartBlockStep { inner } => inner.0.clone(), + Self::BlockWaterAmbient { inner } => inner.0.clone(), + Self::BlockWeepingVinesBreak { inner } => inner.0.clone(), + Self::BlockWeepingVinesFall { inner } => inner.0.clone(), + Self::BlockWeepingVinesHit { inner } => inner.0.clone(), + Self::BlockWeepingVinesPlace { inner } => inner.0.clone(), + Self::BlockWeepingVinesStep { inner } => inner.0.clone(), + Self::BlockWetGrassBreak { inner } => inner.0.clone(), + Self::BlockWetGrassFall { inner } => inner.0.clone(), + Self::BlockWetGrassHit { inner } => inner.0.clone(), + Self::BlockWetGrassPlace { inner } => inner.0.clone(), + Self::BlockWetGrassStep { inner } => inner.0.clone(), + Self::BlockWetSpongeBreak { inner } => inner.0.clone(), + Self::BlockWetSpongeDries { inner } => inner.0.clone(), + Self::BlockWetSpongeFall { inner } => inner.0.clone(), + Self::BlockWetSpongeHit { inner } => inner.0.clone(), + Self::BlockWetSpongePlace { inner } => inner.0.clone(), + Self::BlockWetSpongeStep { inner } => inner.0.clone(), + Self::BlockWoodenButtonClickOff { inner } => inner.0.clone(), + Self::BlockWoodenButtonClickOn { inner } => inner.0.clone(), + Self::BlockWoodenDoorClose { inner } => inner.0.clone(), + Self::BlockWoodenDoorOpen { inner } => inner.0.clone(), + Self::BlockWoodenPressurePlateClickOff { inner } => inner.0.clone(), + Self::BlockWoodenPressurePlateClickOn { inner } => inner.0.clone(), + Self::BlockWoodenTrapdoorClose { inner } => inner.0.clone(), + Self::BlockWoodenTrapdoorOpen { inner } => inner.0.clone(), + Self::BlockWoodBreak { inner } => inner.0.clone(), + Self::BlockWoodFall { inner } => inner.0.clone(), + Self::BlockWoodHit { inner } => inner.0.clone(), + Self::BlockWoodPlace { inner } => inner.0.clone(), + Self::BlockWoodStep { inner } => inner.0.clone(), + Self::BlockWoolBreak { inner } => inner.0.clone(), + Self::BlockWoolFall { inner } => inner.0.clone(), + Self::BlockWoolHit { inner } => inner.0.clone(), + Self::BlockWoolPlace { inner } => inner.0.clone(), + Self::BlockWoolStep { inner } => inner.0.clone(), + Self::EnchantThornsHit { inner } => inner.0.clone(), + Self::EntityAllayAmbientWithoutItem { inner } => inner.0.clone(), + Self::EntityAllayAmbientWithItem { inner } => inner.0.clone(), + Self::EntityAllayDeath { inner } => inner.0.clone(), + Self::EntityAllayHurt { inner } => inner.0.clone(), + Self::EntityAllayItemGiven { inner } => inner.0.clone(), + Self::EntityAllayItemTaken { inner } => inner.0.clone(), + Self::EntityAllayItemThrown { inner } => inner.0.clone(), + Self::EntityArmadilloAmbient { inner } => inner.0.clone(), + Self::EntityArmadilloBrush { inner } => inner.0.clone(), + Self::EntityArmadilloDeath { inner } => inner.0.clone(), + Self::EntityArmadilloEat { inner } => inner.0.clone(), + Self::EntityArmadilloHurt { inner } => inner.0.clone(), + Self::EntityArmadilloHurtReduced { inner } => inner.0.clone(), + Self::EntityArmadilloLand { inner } => inner.0.clone(), + Self::EntityArmadilloPeek { inner } => inner.0.clone(), + Self::EntityArmadilloRoll { inner } => inner.0.clone(), + Self::EntityArmadilloScuteDrop { inner } => inner.0.clone(), + Self::EntityArmadilloStep { inner } => inner.0.clone(), + Self::EntityArmadilloUnrollFinish { inner } => inner.0.clone(), + Self::EntityArmadilloUnrollStart { inner } => inner.0.clone(), + Self::EntityArmorStandBreak { inner } => inner.0.clone(), + Self::EntityArmorStandFall { inner } => inner.0.clone(), + Self::EntityArmorStandHit { inner } => inner.0.clone(), + Self::EntityArmorStandPlace { inner } => inner.0.clone(), + Self::EntityArrowHit { inner } => inner.0.clone(), + Self::EntityArrowHitPlayer { inner } => inner.0.clone(), + Self::EntityArrowShoot { inner } => inner.0.clone(), + Self::EntityAxolotlAttack { inner } => inner.0.clone(), + Self::EntityAxolotlDeath { inner } => inner.0.clone(), + Self::EntityAxolotlHurt { inner } => inner.0.clone(), + Self::EntityAxolotlIdleAir { inner } => inner.0.clone(), + Self::EntityAxolotlIdleWater { inner } => inner.0.clone(), + Self::EntityAxolotlSplash { inner } => inner.0.clone(), + Self::EntityAxolotlSwim { inner } => inner.0.clone(), + Self::EntityBatAmbient { inner } => inner.0.clone(), + Self::EntityBatDeath { inner } => inner.0.clone(), + Self::EntityBatHurt { inner } => inner.0.clone(), + Self::EntityBatLoop { inner } => inner.0.clone(), + Self::EntityBatTakeoff { inner } => inner.0.clone(), + Self::EntityBeeDeath { inner } => inner.0.clone(), + Self::EntityBeeHurt { inner } => inner.0.clone(), + Self::EntityBeeLoop { inner } => inner.0.clone(), + Self::EntityBeeLoopAggressive { inner } => inner.0.clone(), + Self::EntityBeePollinate { inner } => inner.0.clone(), + Self::EntityBeeSting { inner } => inner.0.clone(), + Self::EntityBlazeAmbient { inner } => inner.0.clone(), + Self::EntityBlazeBurn { inner } => inner.0.clone(), + Self::EntityBlazeDeath { inner } => inner.0.clone(), + Self::EntityBlazeHurt { inner } => inner.0.clone(), + Self::EntityBlazeShoot { inner } => inner.0.clone(), + Self::EntityBoatPaddleLand { inner } => inner.0.clone(), + Self::EntityBoatPaddleWater { inner } => inner.0.clone(), + Self::EntityBoggedAmbient { inner } => inner.0.clone(), + Self::EntityBoggedDeath { inner } => inner.0.clone(), + Self::EntityBoggedHurt { inner } => inner.0.clone(), + Self::EntityBoggedShear { inner } => inner.0.clone(), + Self::EntityBoggedStep { inner } => inner.0.clone(), + Self::EntityBreezeCharge { inner } => inner.0.clone(), + Self::EntityBreezeDeath { inner } => inner.0.clone(), + Self::EntityBreezeDeflect { inner } => inner.0.clone(), + Self::EntityBreezeHurt { inner } => inner.0.clone(), + Self::EntityBreezeIdleAir { inner } => inner.0.clone(), + Self::EntityBreezeIdleGround { inner } => inner.0.clone(), + Self::EntityBreezeInhale { inner } => inner.0.clone(), + Self::EntityBreezeJump { inner } => inner.0.clone(), + Self::EntityBreezeLand { inner } => inner.0.clone(), + Self::EntityBreezeShoot { inner } => inner.0.clone(), + Self::EntityBreezeSlide { inner } => inner.0.clone(), + Self::EntityBreezeWhirl { inner } => inner.0.clone(), + Self::EntityBreezeWindBurst { inner } => inner.0.clone(), + Self::EntityCamelAmbient { inner } => inner.0.clone(), + Self::EntityCamelDash { inner } => inner.0.clone(), + Self::EntityCamelDashReady { inner } => inner.0.clone(), + Self::EntityCamelDeath { inner } => inner.0.clone(), + Self::EntityCamelEat { inner } => inner.0.clone(), + Self::EntityCamelHurt { inner } => inner.0.clone(), + Self::EntityCamelSaddle { inner } => inner.0.clone(), + Self::EntityCamelSit { inner } => inner.0.clone(), + Self::EntityCamelStand { inner } => inner.0.clone(), + Self::EntityCamelStep { inner } => inner.0.clone(), + Self::EntityCamelStepSand { inner } => inner.0.clone(), + Self::EntityCatAmbient { inner } => inner.0.clone(), + Self::EntityCatBegForFood { inner } => inner.0.clone(), + Self::EntityCatDeath { inner } => inner.0.clone(), + Self::EntityCatEat { inner } => inner.0.clone(), + Self::EntityCatHiss { inner } => inner.0.clone(), + Self::EntityCatHurt { inner } => inner.0.clone(), + Self::EntityCatPurr { inner } => inner.0.clone(), + Self::EntityCatPurreow { inner } => inner.0.clone(), + Self::EntityCatStrayAmbient { inner } => inner.0.clone(), + Self::EntityChickenAmbient { inner } => inner.0.clone(), + Self::EntityChickenDeath { inner } => inner.0.clone(), + Self::EntityChickenEgg { inner } => inner.0.clone(), + Self::EntityChickenHurt { inner } => inner.0.clone(), + Self::EntityChickenStep { inner } => inner.0.clone(), + Self::EntityCodAmbient { inner } => inner.0.clone(), + Self::EntityCodDeath { inner } => inner.0.clone(), + Self::EntityCodFlop { inner } => inner.0.clone(), + Self::EntityCodHurt { inner } => inner.0.clone(), + Self::EntityCowAmbient { inner } => inner.0.clone(), + Self::EntityCowDeath { inner } => inner.0.clone(), + Self::EntityCowHurt { inner } => inner.0.clone(), + Self::EntityCowMilk { inner } => inner.0.clone(), + Self::EntityCowStep { inner } => inner.0.clone(), + Self::EntityCreeperDeath { inner } => inner.0.clone(), + Self::EntityCreeperHurt { inner } => inner.0.clone(), + Self::EntityCreeperPrimed { inner } => inner.0.clone(), + Self::EntityDolphinAmbient { inner } => inner.0.clone(), + Self::EntityDolphinAmbientWater { inner } => inner.0.clone(), + Self::EntityDolphinAttack { inner } => inner.0.clone(), + Self::EntityDolphinDeath { inner } => inner.0.clone(), + Self::EntityDolphinEat { inner } => inner.0.clone(), + Self::EntityDolphinHurt { inner } => inner.0.clone(), + Self::EntityDolphinJump { inner } => inner.0.clone(), + Self::EntityDolphinPlay { inner } => inner.0.clone(), + Self::EntityDolphinSplash { inner } => inner.0.clone(), + Self::EntityDolphinSwim { inner } => inner.0.clone(), + Self::EntityDonkeyAmbient { inner } => inner.0.clone(), + Self::EntityDonkeyAngry { inner } => inner.0.clone(), + Self::EntityDonkeyChest { inner } => inner.0.clone(), + Self::EntityDonkeyDeath { inner } => inner.0.clone(), + Self::EntityDonkeyEat { inner } => inner.0.clone(), + Self::EntityDonkeyHurt { inner } => inner.0.clone(), + Self::EntityDonkeyJump { inner } => inner.0.clone(), + Self::EntityDragonFireballExplode { inner } => inner.0.clone(), + Self::EntityDrownedAmbient { inner } => inner.0.clone(), + Self::EntityDrownedAmbientWater { inner } => inner.0.clone(), + Self::EntityDrownedDeath { inner } => inner.0.clone(), + Self::EntityDrownedDeathWater { inner } => inner.0.clone(), + Self::EntityDrownedHurt { inner } => inner.0.clone(), + Self::EntityDrownedHurtWater { inner } => inner.0.clone(), + Self::EntityDrownedShoot { inner } => inner.0.clone(), + Self::EntityDrownedStep { inner } => inner.0.clone(), + Self::EntityDrownedSwim { inner } => inner.0.clone(), + Self::EntityEggThrow { inner } => inner.0.clone(), + Self::EntityElderGuardianAmbient { inner } => inner.0.clone(), + Self::EntityElderGuardianAmbientLand { inner } => inner.0.clone(), + Self::EntityElderGuardianCurse { inner } => inner.0.clone(), + Self::EntityElderGuardianDeath { inner } => inner.0.clone(), + Self::EntityElderGuardianDeathLand { inner } => inner.0.clone(), + Self::EntityElderGuardianFlop { inner } => inner.0.clone(), + Self::EntityElderGuardianHurt { inner } => inner.0.clone(), + Self::EntityElderGuardianHurtLand { inner } => inner.0.clone(), + Self::EntityEndermanAmbient { inner } => inner.0.clone(), + Self::EntityEndermanDeath { inner } => inner.0.clone(), + Self::EntityEndermanHurt { inner } => inner.0.clone(), + Self::EntityEndermanScream { inner } => inner.0.clone(), + Self::EntityEndermanStare { inner } => inner.0.clone(), + Self::EntityEndermanTeleport { inner } => inner.0.clone(), + Self::EntityEndermiteAmbient { inner } => inner.0.clone(), + Self::EntityEndermiteDeath { inner } => inner.0.clone(), + Self::EntityEndermiteHurt { inner } => inner.0.clone(), + Self::EntityEndermiteStep { inner } => inner.0.clone(), + Self::EntityEnderDragonAmbient { inner } => inner.0.clone(), + Self::EntityEnderDragonDeath { inner } => inner.0.clone(), + Self::EntityEnderDragonFlap { inner } => inner.0.clone(), + Self::EntityEnderDragonGrowl { inner } => inner.0.clone(), + Self::EntityEnderDragonHurt { inner } => inner.0.clone(), + Self::EntityEnderDragonShoot { inner } => inner.0.clone(), + Self::EntityEnderEyeDeath { inner } => inner.0.clone(), + Self::EntityEnderEyeLaunch { inner } => inner.0.clone(), + Self::EntityEnderPearlThrow { inner } => inner.0.clone(), + Self::EntityEvokerAmbient { inner } => inner.0.clone(), + Self::EntityEvokerCastSpell { inner } => inner.0.clone(), + Self::EntityEvokerCelebrate { inner } => inner.0.clone(), + Self::EntityEvokerDeath { inner } => inner.0.clone(), + Self::EntityEvokerFangsAttack { inner } => inner.0.clone(), + Self::EntityEvokerHurt { inner } => inner.0.clone(), + Self::EntityEvokerPrepareAttack { inner } => inner.0.clone(), + Self::EntityEvokerPrepareSummon { inner } => inner.0.clone(), + Self::EntityEvokerPrepareWololo { inner } => inner.0.clone(), + Self::EntityExperienceBottleThrow { inner } => inner.0.clone(), + Self::EntityExperienceOrbPickup { inner } => inner.0.clone(), + Self::EntityFireworkRocketBlast { inner } => inner.0.clone(), + Self::EntityFireworkRocketBlastFar { inner } => inner.0.clone(), + Self::EntityFireworkRocketLargeBlast { inner } => inner.0.clone(), + Self::EntityFireworkRocketLargeBlastFar { inner } => inner.0.clone(), + Self::EntityFireworkRocketLaunch { inner } => inner.0.clone(), + Self::EntityFireworkRocketShoot { inner } => inner.0.clone(), + Self::EntityFireworkRocketTwinkle { inner } => inner.0.clone(), + Self::EntityFireworkRocketTwinkleFar { inner } => inner.0.clone(), + Self::EntityFishingBobberRetrieve { inner } => inner.0.clone(), + Self::EntityFishingBobberSplash { inner } => inner.0.clone(), + Self::EntityFishingBobberThrow { inner } => inner.0.clone(), + Self::EntityFishSwim { inner } => inner.0.clone(), + Self::EntityFoxAggro { inner } => inner.0.clone(), + Self::EntityFoxAmbient { inner } => inner.0.clone(), + Self::EntityFoxBite { inner } => inner.0.clone(), + Self::EntityFoxDeath { inner } => inner.0.clone(), + Self::EntityFoxEat { inner } => inner.0.clone(), + Self::EntityFoxHurt { inner } => inner.0.clone(), + Self::EntityFoxScreech { inner } => inner.0.clone(), + Self::EntityFoxSleep { inner } => inner.0.clone(), + Self::EntityFoxSniff { inner } => inner.0.clone(), + Self::EntityFoxSpit { inner } => inner.0.clone(), + Self::EntityFoxTeleport { inner } => inner.0.clone(), + Self::EntityFrogAmbient { inner } => inner.0.clone(), + Self::EntityFrogDeath { inner } => inner.0.clone(), + Self::EntityFrogEat { inner } => inner.0.clone(), + Self::EntityFrogHurt { inner } => inner.0.clone(), + Self::EntityFrogLaySpawn { inner } => inner.0.clone(), + Self::EntityFrogLongJump { inner } => inner.0.clone(), + Self::EntityFrogStep { inner } => inner.0.clone(), + Self::EntityFrogTongue { inner } => inner.0.clone(), + Self::EntityGenericBigFall { inner } => inner.0.clone(), + Self::EntityGenericBurn { inner } => inner.0.clone(), + Self::EntityGenericDeath { inner } => inner.0.clone(), + Self::EntityGenericDrink { inner } => inner.0.clone(), + Self::EntityGenericEat { inner } => inner.0.clone(), + Self::EntityGenericExplode { inner } => inner.0.clone(), + Self::EntityGenericExtinguishFire { inner } => inner.0.clone(), + Self::EntityGenericHurt { inner } => inner.0.clone(), + Self::EntityGenericSmallFall { inner } => inner.0.clone(), + Self::EntityGenericSplash { inner } => inner.0.clone(), + Self::EntityGenericSwim { inner } => inner.0.clone(), + Self::EntityGhastAmbient { inner } => inner.0.clone(), + Self::EntityGhastDeath { inner } => inner.0.clone(), + Self::EntityGhastHurt { inner } => inner.0.clone(), + Self::EntityGhastScream { inner } => inner.0.clone(), + Self::EntityGhastShoot { inner } => inner.0.clone(), + Self::EntityGhastWarn { inner } => inner.0.clone(), + Self::EntityGlowItemFrameAddItem { inner } => inner.0.clone(), + Self::EntityGlowItemFrameBreak { inner } => inner.0.clone(), + Self::EntityGlowItemFramePlace { inner } => inner.0.clone(), + Self::EntityGlowItemFrameRemoveItem { inner } => inner.0.clone(), + Self::EntityGlowItemFrameRotateItem { inner } => inner.0.clone(), + Self::EntityGlowSquidAmbient { inner } => inner.0.clone(), + Self::EntityGlowSquidDeath { inner } => inner.0.clone(), + Self::EntityGlowSquidHurt { inner } => inner.0.clone(), + Self::EntityGlowSquidSquirt { inner } => inner.0.clone(), + Self::EntityGoatAmbient { inner } => inner.0.clone(), + Self::EntityGoatDeath { inner } => inner.0.clone(), + Self::EntityGoatEat { inner } => inner.0.clone(), + Self::EntityGoatHornBreak { inner } => inner.0.clone(), + Self::EntityGoatHurt { inner } => inner.0.clone(), + Self::EntityGoatLongJump { inner } => inner.0.clone(), + Self::EntityGoatMilk { inner } => inner.0.clone(), + Self::EntityGoatPrepareRam { inner } => inner.0.clone(), + Self::EntityGoatRamImpact { inner } => inner.0.clone(), + Self::EntityGoatScreamingAmbient { inner } => inner.0.clone(), + Self::EntityGoatScreamingDeath { inner } => inner.0.clone(), + Self::EntityGoatScreamingEat { inner } => inner.0.clone(), + Self::EntityGoatScreamingHornBreak { inner } => inner.0.clone(), + Self::EntityGoatScreamingHurt { inner } => inner.0.clone(), + Self::EntityGoatScreamingLongJump { inner } => inner.0.clone(), + Self::EntityGoatScreamingMilk { inner } => inner.0.clone(), + Self::EntityGoatScreamingPrepareRam { inner } => inner.0.clone(), + Self::EntityGoatScreamingRamImpact { inner } => inner.0.clone(), + Self::EntityGoatStep { inner } => inner.0.clone(), + Self::EntityGuardianAmbient { inner } => inner.0.clone(), + Self::EntityGuardianAmbientLand { inner } => inner.0.clone(), + Self::EntityGuardianAttack { inner } => inner.0.clone(), + Self::EntityGuardianDeath { inner } => inner.0.clone(), + Self::EntityGuardianDeathLand { inner } => inner.0.clone(), + Self::EntityGuardianFlop { inner } => inner.0.clone(), + Self::EntityGuardianHurt { inner } => inner.0.clone(), + Self::EntityGuardianHurtLand { inner } => inner.0.clone(), + Self::EntityHoglinAmbient { inner } => inner.0.clone(), + Self::EntityHoglinAngry { inner } => inner.0.clone(), + Self::EntityHoglinAttack { inner } => inner.0.clone(), + Self::EntityHoglinConvertedToZombified { inner } => inner.0.clone(), + Self::EntityHoglinDeath { inner } => inner.0.clone(), + Self::EntityHoglinHurt { inner } => inner.0.clone(), + Self::EntityHoglinRetreat { inner } => inner.0.clone(), + Self::EntityHoglinStep { inner } => inner.0.clone(), + Self::EntityHorseAmbient { inner } => inner.0.clone(), + Self::EntityHorseAngry { inner } => inner.0.clone(), + Self::EntityHorseArmor { inner } => inner.0.clone(), + Self::EntityHorseBreathe { inner } => inner.0.clone(), + Self::EntityHorseDeath { inner } => inner.0.clone(), + Self::EntityHorseEat { inner } => inner.0.clone(), + Self::EntityHorseGallop { inner } => inner.0.clone(), + Self::EntityHorseHurt { inner } => inner.0.clone(), + Self::EntityHorseJump { inner } => inner.0.clone(), + Self::EntityHorseLand { inner } => inner.0.clone(), + Self::EntityHorseSaddle { inner } => inner.0.clone(), + Self::EntityHorseStep { inner } => inner.0.clone(), + Self::EntityHorseStepWood { inner } => inner.0.clone(), + Self::EntityHostileBigFall { inner } => inner.0.clone(), + Self::EntityHostileDeath { inner } => inner.0.clone(), + Self::EntityHostileHurt { inner } => inner.0.clone(), + Self::EntityHostileSmallFall { inner } => inner.0.clone(), + Self::EntityHostileSplash { inner } => inner.0.clone(), + Self::EntityHostileSwim { inner } => inner.0.clone(), + Self::EntityHuskAmbient { inner } => inner.0.clone(), + Self::EntityHuskConvertedToZombie { inner } => inner.0.clone(), + Self::EntityHuskDeath { inner } => inner.0.clone(), + Self::EntityHuskHurt { inner } => inner.0.clone(), + Self::EntityHuskStep { inner } => inner.0.clone(), + Self::EntityIllusionerAmbient { inner } => inner.0.clone(), + Self::EntityIllusionerCastSpell { inner } => inner.0.clone(), + Self::EntityIllusionerDeath { inner } => inner.0.clone(), + Self::EntityIllusionerHurt { inner } => inner.0.clone(), + Self::EntityIllusionerMirrorMove { inner } => inner.0.clone(), + Self::EntityIllusionerPrepareBlindness { inner } => inner.0.clone(), + Self::EntityIllusionerPrepareMirror { inner } => inner.0.clone(), + Self::EntityIronGolemAttack { inner } => inner.0.clone(), + Self::EntityIronGolemDamage { inner } => inner.0.clone(), + Self::EntityIronGolemDeath { inner } => inner.0.clone(), + Self::EntityIronGolemHurt { inner } => inner.0.clone(), + Self::EntityIronGolemRepair { inner } => inner.0.clone(), + Self::EntityIronGolemStep { inner } => inner.0.clone(), + Self::EntityItemBreak { inner } => inner.0.clone(), + Self::EntityItemFrameAddItem { inner } => inner.0.clone(), + Self::EntityItemFrameBreak { inner } => inner.0.clone(), + Self::EntityItemFramePlace { inner } => inner.0.clone(), + Self::EntityItemFrameRemoveItem { inner } => inner.0.clone(), + Self::EntityItemFrameRotateItem { inner } => inner.0.clone(), + Self::EntityItemPickup { inner } => inner.0.clone(), + Self::EntityLeashKnotBreak { inner } => inner.0.clone(), + Self::EntityLeashKnotPlace { inner } => inner.0.clone(), + Self::EntityLightningBoltImpact { inner } => inner.0.clone(), + Self::EntityLightningBoltThunder { inner } => inner.0.clone(), + Self::EntityLingeringPotionThrow { inner } => inner.0.clone(), + Self::EntityLlamaAmbient { inner } => inner.0.clone(), + Self::EntityLlamaAngry { inner } => inner.0.clone(), + Self::EntityLlamaChest { inner } => inner.0.clone(), + Self::EntityLlamaDeath { inner } => inner.0.clone(), + Self::EntityLlamaEat { inner } => inner.0.clone(), + Self::EntityLlamaHurt { inner } => inner.0.clone(), + Self::EntityLlamaSpit { inner } => inner.0.clone(), + Self::EntityLlamaStep { inner } => inner.0.clone(), + Self::EntityLlamaSwag { inner } => inner.0.clone(), + Self::EntityMagmaCubeDeath { inner } => inner.0.clone(), + Self::EntityMagmaCubeDeathSmall { inner } => inner.0.clone(), + Self::EntityMagmaCubeHurt { inner } => inner.0.clone(), + Self::EntityMagmaCubeHurtSmall { inner } => inner.0.clone(), + Self::EntityMagmaCubeJump { inner } => inner.0.clone(), + Self::EntityMagmaCubeSquish { inner } => inner.0.clone(), + Self::EntityMagmaCubeSquishSmall { inner } => inner.0.clone(), + Self::EntityMinecartInside { inner } => inner.0.clone(), + Self::EntityMinecartInsideUnderwater { inner } => inner.0.clone(), + Self::EntityMinecartRiding { inner } => inner.0.clone(), + Self::EntityMooshroomConvert { inner } => inner.0.clone(), + Self::EntityMooshroomEat { inner } => inner.0.clone(), + Self::EntityMooshroomMilk { inner } => inner.0.clone(), + Self::EntityMooshroomShear { inner } => inner.0.clone(), + Self::EntityMooshroomSuspiciousMilk { inner } => inner.0.clone(), + Self::EntityMuleAmbient { inner } => inner.0.clone(), + Self::EntityMuleAngry { inner } => inner.0.clone(), + Self::EntityMuleChest { inner } => inner.0.clone(), + Self::EntityMuleDeath { inner } => inner.0.clone(), + Self::EntityMuleEat { inner } => inner.0.clone(), + Self::EntityMuleHurt { inner } => inner.0.clone(), + Self::EntityMuleJump { inner } => inner.0.clone(), + Self::EntityOcelotAmbient { inner } => inner.0.clone(), + Self::EntityOcelotDeath { inner } => inner.0.clone(), + Self::EntityOcelotHurt { inner } => inner.0.clone(), + Self::EntityPaintingBreak { inner } => inner.0.clone(), + Self::EntityPaintingPlace { inner } => inner.0.clone(), + Self::EntityPandaAggressiveAmbient { inner } => inner.0.clone(), + Self::EntityPandaAmbient { inner } => inner.0.clone(), + Self::EntityPandaBite { inner } => inner.0.clone(), + Self::EntityPandaCantBreed { inner } => inner.0.clone(), + Self::EntityPandaDeath { inner } => inner.0.clone(), + Self::EntityPandaEat { inner } => inner.0.clone(), + Self::EntityPandaHurt { inner } => inner.0.clone(), + Self::EntityPandaPreSneeze { inner } => inner.0.clone(), + Self::EntityPandaSneeze { inner } => inner.0.clone(), + Self::EntityPandaStep { inner } => inner.0.clone(), + Self::EntityPandaWorriedAmbient { inner } => inner.0.clone(), + Self::EntityParrotAmbient { inner } => inner.0.clone(), + Self::EntityParrotDeath { inner } => inner.0.clone(), + Self::EntityParrotEat { inner } => inner.0.clone(), + Self::EntityParrotFly { inner } => inner.0.clone(), + Self::EntityParrotHurt { inner } => inner.0.clone(), + Self::EntityParrotImitateBlaze { inner } => inner.0.clone(), + Self::EntityParrotImitateBogged { inner } => inner.0.clone(), + Self::EntityParrotImitateBreeze { inner } => inner.0.clone(), + Self::EntityParrotImitateCreeper { inner } => inner.0.clone(), + Self::EntityParrotImitateDrowned { inner } => inner.0.clone(), + Self::EntityParrotImitateElderGuardian { inner } => inner.0.clone(), + Self::EntityParrotImitateEndermite { inner } => inner.0.clone(), + Self::EntityParrotImitateEnderDragon { inner } => inner.0.clone(), + Self::EntityParrotImitateEvoker { inner } => inner.0.clone(), + Self::EntityParrotImitateGhast { inner } => inner.0.clone(), + Self::EntityParrotImitateGuardian { inner } => inner.0.clone(), + Self::EntityParrotImitateHoglin { inner } => inner.0.clone(), + Self::EntityParrotImitateHusk { inner } => inner.0.clone(), + Self::EntityParrotImitateIllusioner { inner } => inner.0.clone(), + Self::EntityParrotImitateMagmaCube { inner } => inner.0.clone(), + Self::EntityParrotImitatePhantom { inner } => inner.0.clone(), + Self::EntityParrotImitatePiglin { inner } => inner.0.clone(), + Self::EntityParrotImitatePiglinBrute { inner } => inner.0.clone(), + Self::EntityParrotImitatePillager { inner } => inner.0.clone(), + Self::EntityParrotImitateRavager { inner } => inner.0.clone(), + Self::EntityParrotImitateShulker { inner } => inner.0.clone(), + Self::EntityParrotImitateSilverfish { inner } => inner.0.clone(), + Self::EntityParrotImitateSkeleton { inner } => inner.0.clone(), + Self::EntityParrotImitateSlime { inner } => inner.0.clone(), + Self::EntityParrotImitateSpider { inner } => inner.0.clone(), + Self::EntityParrotImitateStray { inner } => inner.0.clone(), + Self::EntityParrotImitateVex { inner } => inner.0.clone(), + Self::EntityParrotImitateVindicator { inner } => inner.0.clone(), + Self::EntityParrotImitateWarden { inner } => inner.0.clone(), + Self::EntityParrotImitateWitch { inner } => inner.0.clone(), + Self::EntityParrotImitateWither { inner } => inner.0.clone(), + Self::EntityParrotImitateWitherSkeleton { inner } => inner.0.clone(), + Self::EntityParrotImitateZoglin { inner } => inner.0.clone(), + Self::EntityParrotImitateZombie { inner } => inner.0.clone(), + Self::EntityParrotImitateZombieVillager { inner } => inner.0.clone(), + Self::EntityParrotStep { inner } => inner.0.clone(), + Self::EntityPhantomAmbient { inner } => inner.0.clone(), + Self::EntityPhantomBite { inner } => inner.0.clone(), + Self::EntityPhantomDeath { inner } => inner.0.clone(), + Self::EntityPhantomFlap { inner } => inner.0.clone(), + Self::EntityPhantomHurt { inner } => inner.0.clone(), + Self::EntityPhantomSwoop { inner } => inner.0.clone(), + Self::EntityPiglinAdmiringItem { inner } => inner.0.clone(), + Self::EntityPiglinAmbient { inner } => inner.0.clone(), + Self::EntityPiglinAngry { inner } => inner.0.clone(), + Self::EntityPiglinBruteAmbient { inner } => inner.0.clone(), + Self::EntityPiglinBruteAngry { inner } => inner.0.clone(), + Self::EntityPiglinBruteConvertedToZombified { inner } => inner.0.clone(), + Self::EntityPiglinBruteDeath { inner } => inner.0.clone(), + Self::EntityPiglinBruteHurt { inner } => inner.0.clone(), + Self::EntityPiglinBruteStep { inner } => inner.0.clone(), + Self::EntityPiglinCelebrate { inner } => inner.0.clone(), + Self::EntityPiglinConvertedToZombified { inner } => inner.0.clone(), + Self::EntityPiglinDeath { inner } => inner.0.clone(), + Self::EntityPiglinHurt { inner } => inner.0.clone(), + Self::EntityPiglinJealous { inner } => inner.0.clone(), + Self::EntityPiglinRetreat { inner } => inner.0.clone(), + Self::EntityPiglinStep { inner } => inner.0.clone(), + Self::EntityPigAmbient { inner } => inner.0.clone(), + Self::EntityPigDeath { inner } => inner.0.clone(), + Self::EntityPigHurt { inner } => inner.0.clone(), + Self::EntityPigSaddle { inner } => inner.0.clone(), + Self::EntityPigStep { inner } => inner.0.clone(), + Self::EntityPillagerAmbient { inner } => inner.0.clone(), + Self::EntityPillagerCelebrate { inner } => inner.0.clone(), + Self::EntityPillagerDeath { inner } => inner.0.clone(), + Self::EntityPillagerHurt { inner } => inner.0.clone(), + Self::EntityPlayerAttackCrit { inner } => inner.0.clone(), + Self::EntityPlayerAttackKnockback { inner } => inner.0.clone(), + Self::EntityPlayerAttackNodamage { inner } => inner.0.clone(), + Self::EntityPlayerAttackStrong { inner } => inner.0.clone(), + Self::EntityPlayerAttackSweep { inner } => inner.0.clone(), + Self::EntityPlayerAttackWeak { inner } => inner.0.clone(), + Self::EntityPlayerBigFall { inner } => inner.0.clone(), + Self::EntityPlayerBreath { inner } => inner.0.clone(), + Self::EntityPlayerBurp { inner } => inner.0.clone(), + Self::EntityPlayerDeath { inner } => inner.0.clone(), + Self::EntityPlayerHurt { inner } => inner.0.clone(), + Self::EntityPlayerHurtDrown { inner } => inner.0.clone(), + Self::EntityPlayerHurtFreeze { inner } => inner.0.clone(), + Self::EntityPlayerHurtOnFire { inner } => inner.0.clone(), + Self::EntityPlayerHurtSweetBerryBush { inner } => inner.0.clone(), + Self::EntityPlayerLevelup { inner } => inner.0.clone(), + Self::EntityPlayerSmallFall { inner } => inner.0.clone(), + Self::EntityPlayerSplash { inner } => inner.0.clone(), + Self::EntityPlayerSplashHighSpeed { inner } => inner.0.clone(), + Self::EntityPlayerSwim { inner } => inner.0.clone(), + Self::EntityPlayerTeleport { inner } => inner.0.clone(), + Self::EntityPolarBearAmbient { inner } => inner.0.clone(), + Self::EntityPolarBearAmbientBaby { inner } => inner.0.clone(), + Self::EntityPolarBearDeath { inner } => inner.0.clone(), + Self::EntityPolarBearHurt { inner } => inner.0.clone(), + Self::EntityPolarBearStep { inner } => inner.0.clone(), + Self::EntityPolarBearWarning { inner } => inner.0.clone(), + Self::EntityPufferFishAmbient { inner } => inner.0.clone(), + Self::EntityPufferFishBlowOut { inner } => inner.0.clone(), + Self::EntityPufferFishBlowUp { inner } => inner.0.clone(), + Self::EntityPufferFishDeath { inner } => inner.0.clone(), + Self::EntityPufferFishFlop { inner } => inner.0.clone(), + Self::EntityPufferFishHurt { inner } => inner.0.clone(), + Self::EntityPufferFishSting { inner } => inner.0.clone(), + Self::EntityRabbitAmbient { inner } => inner.0.clone(), + Self::EntityRabbitAttack { inner } => inner.0.clone(), + Self::EntityRabbitDeath { inner } => inner.0.clone(), + Self::EntityRabbitHurt { inner } => inner.0.clone(), + Self::EntityRabbitJump { inner } => inner.0.clone(), + Self::EntityRavagerAmbient { inner } => inner.0.clone(), + Self::EntityRavagerAttack { inner } => inner.0.clone(), + Self::EntityRavagerCelebrate { inner } => inner.0.clone(), + Self::EntityRavagerDeath { inner } => inner.0.clone(), + Self::EntityRavagerHurt { inner } => inner.0.clone(), + Self::EntityRavagerRoar { inner } => inner.0.clone(), + Self::EntityRavagerStep { inner } => inner.0.clone(), + Self::EntityRavagerStunned { inner } => inner.0.clone(), + Self::EntitySalmonAmbient { inner } => inner.0.clone(), + Self::EntitySalmonDeath { inner } => inner.0.clone(), + Self::EntitySalmonFlop { inner } => inner.0.clone(), + Self::EntitySalmonHurt { inner } => inner.0.clone(), + Self::EntitySheepAmbient { inner } => inner.0.clone(), + Self::EntitySheepDeath { inner } => inner.0.clone(), + Self::EntitySheepHurt { inner } => inner.0.clone(), + Self::EntitySheepShear { inner } => inner.0.clone(), + Self::EntitySheepStep { inner } => inner.0.clone(), + Self::EntityShulkerAmbient { inner } => inner.0.clone(), + Self::EntityShulkerBulletHit { inner } => inner.0.clone(), + Self::EntityShulkerBulletHurt { inner } => inner.0.clone(), + Self::EntityShulkerClose { inner } => inner.0.clone(), + Self::EntityShulkerDeath { inner } => inner.0.clone(), + Self::EntityShulkerHurt { inner } => inner.0.clone(), + Self::EntityShulkerHurtClosed { inner } => inner.0.clone(), + Self::EntityShulkerOpen { inner } => inner.0.clone(), + Self::EntityShulkerShoot { inner } => inner.0.clone(), + Self::EntityShulkerTeleport { inner } => inner.0.clone(), + Self::EntitySilverfishAmbient { inner } => inner.0.clone(), + Self::EntitySilverfishDeath { inner } => inner.0.clone(), + Self::EntitySilverfishHurt { inner } => inner.0.clone(), + Self::EntitySilverfishStep { inner } => inner.0.clone(), + Self::EntitySkeletonAmbient { inner } => inner.0.clone(), + Self::EntitySkeletonConvertedToStray { inner } => inner.0.clone(), + Self::EntitySkeletonDeath { inner } => inner.0.clone(), + Self::EntitySkeletonHorseAmbient { inner } => inner.0.clone(), + Self::EntitySkeletonHorseAmbientWater { inner } => inner.0.clone(), + Self::EntitySkeletonHorseDeath { inner } => inner.0.clone(), + Self::EntitySkeletonHorseGallopWater { inner } => inner.0.clone(), + Self::EntitySkeletonHorseHurt { inner } => inner.0.clone(), + Self::EntitySkeletonHorseJumpWater { inner } => inner.0.clone(), + Self::EntitySkeletonHorseStepWater { inner } => inner.0.clone(), + Self::EntitySkeletonHorseSwim { inner } => inner.0.clone(), + Self::EntitySkeletonHurt { inner } => inner.0.clone(), + Self::EntitySkeletonShoot { inner } => inner.0.clone(), + Self::EntitySkeletonStep { inner } => inner.0.clone(), + Self::EntitySlimeAttack { inner } => inner.0.clone(), + Self::EntitySlimeDeath { inner } => inner.0.clone(), + Self::EntitySlimeDeathSmall { inner } => inner.0.clone(), + Self::EntitySlimeHurt { inner } => inner.0.clone(), + Self::EntitySlimeHurtSmall { inner } => inner.0.clone(), + Self::EntitySlimeJump { inner } => inner.0.clone(), + Self::EntitySlimeJumpSmall { inner } => inner.0.clone(), + Self::EntitySlimeSquish { inner } => inner.0.clone(), + Self::EntitySlimeSquishSmall { inner } => inner.0.clone(), + Self::EntitySnifferDeath { inner } => inner.0.clone(), + Self::EntitySnifferDigging { inner } => inner.0.clone(), + Self::EntitySnifferDiggingStop { inner } => inner.0.clone(), + Self::EntitySnifferDropSeed { inner } => inner.0.clone(), + Self::EntitySnifferEat { inner } => inner.0.clone(), + Self::EntitySnifferHappy { inner } => inner.0.clone(), + Self::EntitySnifferHurt { inner } => inner.0.clone(), + Self::EntitySnifferIdle { inner } => inner.0.clone(), + Self::EntitySnifferScenting { inner } => inner.0.clone(), + Self::EntitySnifferSearching { inner } => inner.0.clone(), + Self::EntitySnifferSniffing { inner } => inner.0.clone(), + Self::EntitySnifferStep { inner } => inner.0.clone(), + Self::EntitySnowballThrow { inner } => inner.0.clone(), + Self::EntitySnowGolemAmbient { inner } => inner.0.clone(), + Self::EntitySnowGolemDeath { inner } => inner.0.clone(), + Self::EntitySnowGolemHurt { inner } => inner.0.clone(), + Self::EntitySnowGolemShear { inner } => inner.0.clone(), + Self::EntitySnowGolemShoot { inner } => inner.0.clone(), + Self::EntitySpiderAmbient { inner } => inner.0.clone(), + Self::EntitySpiderDeath { inner } => inner.0.clone(), + Self::EntitySpiderHurt { inner } => inner.0.clone(), + Self::EntitySpiderStep { inner } => inner.0.clone(), + Self::EntitySplashPotionBreak { inner } => inner.0.clone(), + Self::EntitySplashPotionThrow { inner } => inner.0.clone(), + Self::EntitySquidAmbient { inner } => inner.0.clone(), + Self::EntitySquidDeath { inner } => inner.0.clone(), + Self::EntitySquidHurt { inner } => inner.0.clone(), + Self::EntitySquidSquirt { inner } => inner.0.clone(), + Self::EntityStrayAmbient { inner } => inner.0.clone(), + Self::EntityStrayDeath { inner } => inner.0.clone(), + Self::EntityStrayHurt { inner } => inner.0.clone(), + Self::EntityStrayStep { inner } => inner.0.clone(), + Self::EntityStriderAmbient { inner } => inner.0.clone(), + Self::EntityStriderDeath { inner } => inner.0.clone(), + Self::EntityStriderEat { inner } => inner.0.clone(), + Self::EntityStriderHappy { inner } => inner.0.clone(), + Self::EntityStriderHurt { inner } => inner.0.clone(), + Self::EntityStriderRetreat { inner } => inner.0.clone(), + Self::EntityStriderSaddle { inner } => inner.0.clone(), + Self::EntityStriderStep { inner } => inner.0.clone(), + Self::EntityStriderStepLava { inner } => inner.0.clone(), + Self::EntityTadpoleDeath { inner } => inner.0.clone(), + Self::EntityTadpoleFlop { inner } => inner.0.clone(), + Self::EntityTadpoleGrowUp { inner } => inner.0.clone(), + Self::EntityTadpoleHurt { inner } => inner.0.clone(), + Self::EntityTntPrimed { inner } => inner.0.clone(), + Self::EntityTropicalFishAmbient { inner } => inner.0.clone(), + Self::EntityTropicalFishDeath { inner } => inner.0.clone(), + Self::EntityTropicalFishFlop { inner } => inner.0.clone(), + Self::EntityTropicalFishHurt { inner } => inner.0.clone(), + Self::EntityTurtleAmbientLand { inner } => inner.0.clone(), + Self::EntityTurtleDeath { inner } => inner.0.clone(), + Self::EntityTurtleDeathBaby { inner } => inner.0.clone(), + Self::EntityTurtleEggBreak { inner } => inner.0.clone(), + Self::EntityTurtleEggCrack { inner } => inner.0.clone(), + Self::EntityTurtleEggHatch { inner } => inner.0.clone(), + Self::EntityTurtleHurt { inner } => inner.0.clone(), + Self::EntityTurtleHurtBaby { inner } => inner.0.clone(), + Self::EntityTurtleLayEgg { inner } => inner.0.clone(), + Self::EntityTurtleShamble { inner } => inner.0.clone(), + Self::EntityTurtleShambleBaby { inner } => inner.0.clone(), + Self::EntityTurtleSwim { inner } => inner.0.clone(), + Self::EntityVexAmbient { inner } => inner.0.clone(), + Self::EntityVexCharge { inner } => inner.0.clone(), + Self::EntityVexDeath { inner } => inner.0.clone(), + Self::EntityVexHurt { inner } => inner.0.clone(), + Self::EntityVillagerAmbient { inner } => inner.0.clone(), + Self::EntityVillagerCelebrate { inner } => inner.0.clone(), + Self::EntityVillagerDeath { inner } => inner.0.clone(), + Self::EntityVillagerHurt { inner } => inner.0.clone(), + Self::EntityVillagerNo { inner } => inner.0.clone(), + Self::EntityVillagerTrade { inner } => inner.0.clone(), + Self::EntityVillagerWorkArmorer { inner } => inner.0.clone(), + Self::EntityVillagerWorkButcher { inner } => inner.0.clone(), + Self::EntityVillagerWorkCartographer { inner } => inner.0.clone(), + Self::EntityVillagerWorkCleric { inner } => inner.0.clone(), + Self::EntityVillagerWorkFarmer { inner } => inner.0.clone(), + Self::EntityVillagerWorkFisherman { inner } => inner.0.clone(), + Self::EntityVillagerWorkFletcher { inner } => inner.0.clone(), + Self::EntityVillagerWorkLeatherworker { inner } => inner.0.clone(), + Self::EntityVillagerWorkLibrarian { inner } => inner.0.clone(), + Self::EntityVillagerWorkMason { inner } => inner.0.clone(), + Self::EntityVillagerWorkShepherd { inner } => inner.0.clone(), + Self::EntityVillagerWorkToolsmith { inner } => inner.0.clone(), + Self::EntityVillagerWorkWeaponsmith { inner } => inner.0.clone(), + Self::EntityVillagerYes { inner } => inner.0.clone(), + Self::EntityVindicatorAmbient { inner } => inner.0.clone(), + Self::EntityVindicatorCelebrate { inner } => inner.0.clone(), + Self::EntityVindicatorDeath { inner } => inner.0.clone(), + Self::EntityVindicatorHurt { inner } => inner.0.clone(), + Self::EntityWanderingTraderAmbient { inner } => inner.0.clone(), + Self::EntityWanderingTraderDeath { inner } => inner.0.clone(), + Self::EntityWanderingTraderDisappeared { inner } => inner.0.clone(), + Self::EntityWanderingTraderDrinkMilk { inner } => inner.0.clone(), + Self::EntityWanderingTraderDrinkPotion { inner } => inner.0.clone(), + Self::EntityWanderingTraderHurt { inner } => inner.0.clone(), + Self::EntityWanderingTraderNo { inner } => inner.0.clone(), + Self::EntityWanderingTraderReappeared { inner } => inner.0.clone(), + Self::EntityWanderingTraderTrade { inner } => inner.0.clone(), + Self::EntityWanderingTraderYes { inner } => inner.0.clone(), + Self::EntityWardenAgitated { inner } => inner.0.clone(), + Self::EntityWardenAmbient { inner } => inner.0.clone(), + Self::EntityWardenAngry { inner } => inner.0.clone(), + Self::EntityWardenAttackImpact { inner } => inner.0.clone(), + Self::EntityWardenDeath { inner } => inner.0.clone(), + Self::EntityWardenDig { inner } => inner.0.clone(), + Self::EntityWardenEmerge { inner } => inner.0.clone(), + Self::EntityWardenHeartbeat { inner } => inner.0.clone(), + Self::EntityWardenHurt { inner } => inner.0.clone(), + Self::EntityWardenListening { inner } => inner.0.clone(), + Self::EntityWardenListeningAngry { inner } => inner.0.clone(), + Self::EntityWardenNearbyClose { inner } => inner.0.clone(), + Self::EntityWardenNearbyCloser { inner } => inner.0.clone(), + Self::EntityWardenNearbyClosest { inner } => inner.0.clone(), + Self::EntityWardenRoar { inner } => inner.0.clone(), + Self::EntityWardenSniff { inner } => inner.0.clone(), + Self::EntityWardenSonicBoom { inner } => inner.0.clone(), + Self::EntityWardenSonicCharge { inner } => inner.0.clone(), + Self::EntityWardenStep { inner } => inner.0.clone(), + Self::EntityWardenTendrilClicks { inner } => inner.0.clone(), + Self::EntityWindChargeThrow { inner } => inner.0.clone(), + Self::EntityWindChargeWindBurst { inner } => inner.0.clone(), + Self::EntityWitchAmbient { inner } => inner.0.clone(), + Self::EntityWitchCelebrate { inner } => inner.0.clone(), + Self::EntityWitchDeath { inner } => inner.0.clone(), + Self::EntityWitchDrink { inner } => inner.0.clone(), + Self::EntityWitchHurt { inner } => inner.0.clone(), + Self::EntityWitchThrow { inner } => inner.0.clone(), + Self::EntityWitherAmbient { inner } => inner.0.clone(), + Self::EntityWitherBreakBlock { inner } => inner.0.clone(), + Self::EntityWitherDeath { inner } => inner.0.clone(), + Self::EntityWitherHurt { inner } => inner.0.clone(), + Self::EntityWitherShoot { inner } => inner.0.clone(), + Self::EntityWitherSkeletonAmbient { inner } => inner.0.clone(), + Self::EntityWitherSkeletonDeath { inner } => inner.0.clone(), + Self::EntityWitherSkeletonHurt { inner } => inner.0.clone(), + Self::EntityWitherSkeletonStep { inner } => inner.0.clone(), + Self::EntityWitherSpawn { inner } => inner.0.clone(), + Self::EntityWolfAmbient { inner } => inner.0.clone(), + Self::EntityWolfDeath { inner } => inner.0.clone(), + Self::EntityWolfGrowl { inner } => inner.0.clone(), + Self::EntityWolfHowl { inner } => inner.0.clone(), + Self::EntityWolfHurt { inner } => inner.0.clone(), + Self::EntityWolfPant { inner } => inner.0.clone(), + Self::EntityWolfShake { inner } => inner.0.clone(), + Self::EntityWolfStep { inner } => inner.0.clone(), + Self::EntityWolfWhine { inner } => inner.0.clone(), + Self::EntityZoglinAmbient { inner } => inner.0.clone(), + Self::EntityZoglinAngry { inner } => inner.0.clone(), + Self::EntityZoglinAttack { inner } => inner.0.clone(), + Self::EntityZoglinDeath { inner } => inner.0.clone(), + Self::EntityZoglinHurt { inner } => inner.0.clone(), + Self::EntityZoglinStep { inner } => inner.0.clone(), + Self::EntityZombieAmbient { inner } => inner.0.clone(), + Self::EntityZombieAttackIronDoor { inner } => inner.0.clone(), + Self::EntityZombieAttackWoodenDoor { inner } => inner.0.clone(), + Self::EntityZombieBreakWoodenDoor { inner } => inner.0.clone(), + Self::EntityZombieConvertedToDrowned { inner } => inner.0.clone(), + Self::EntityZombieDeath { inner } => inner.0.clone(), + Self::EntityZombieDestroyEgg { inner } => inner.0.clone(), + Self::EntityZombieHorseAmbient { inner } => inner.0.clone(), + Self::EntityZombieHorseDeath { inner } => inner.0.clone(), + Self::EntityZombieHorseHurt { inner } => inner.0.clone(), + Self::EntityZombieHurt { inner } => inner.0.clone(), + Self::EntityZombieInfect { inner } => inner.0.clone(), + Self::EntityZombieStep { inner } => inner.0.clone(), + Self::EntityZombieVillagerAmbient { inner } => inner.0.clone(), + Self::EntityZombieVillagerConverted { inner } => inner.0.clone(), + Self::EntityZombieVillagerCure { inner } => inner.0.clone(), + Self::EntityZombieVillagerDeath { inner } => inner.0.clone(), + Self::EntityZombieVillagerHurt { inner } => inner.0.clone(), + Self::EntityZombieVillagerStep { inner } => inner.0.clone(), + Self::EntityZombifiedPiglinAmbient { inner } => inner.0.clone(), + Self::EntityZombifiedPiglinAngry { inner } => inner.0.clone(), + Self::EntityZombifiedPiglinDeath { inner } => inner.0.clone(), + Self::EntityZombifiedPiglinHurt { inner } => inner.0.clone(), + Self::EventMobEffectBadOmen { inner } => inner.0.clone(), + Self::EventMobEffectRaidOmen { inner } => inner.0.clone(), + Self::EventMobEffectTrialOmen { inner } => inner.0.clone(), + Self::EventRaidHorn { inner } => inner.0.clone(), + Self::IntentionallyEmpty { inner } => inner.0.clone(), + Self::ItemArmorEquipChain { inner } => inner.0.clone(), + Self::ItemArmorEquipDiamond { inner } => inner.0.clone(), + Self::ItemArmorEquipElytra { inner } => inner.0.clone(), + Self::ItemArmorEquipGeneric { inner } => inner.0.clone(), + Self::ItemArmorEquipGold { inner } => inner.0.clone(), + Self::ItemArmorEquipIron { inner } => inner.0.clone(), + Self::ItemArmorEquipLeather { inner } => inner.0.clone(), + Self::ItemArmorEquipNetherite { inner } => inner.0.clone(), + Self::ItemArmorEquipTurtle { inner } => inner.0.clone(), + Self::ItemArmorEquipWolf { inner } => inner.0.clone(), + Self::ItemArmorUnequipWolf { inner } => inner.0.clone(), + Self::ItemAxeScrape { inner } => inner.0.clone(), + Self::ItemAxeStrip { inner } => inner.0.clone(), + Self::ItemAxeWaxOff { inner } => inner.0.clone(), + Self::ItemBoneMealUse { inner } => inner.0.clone(), + Self::ItemBookPageTurn { inner } => inner.0.clone(), + Self::ItemBookPut { inner } => inner.0.clone(), + Self::ItemBottleEmpty { inner } => inner.0.clone(), + Self::ItemBottleFill { inner } => inner.0.clone(), + Self::ItemBottleFillDragonbreath { inner } => inner.0.clone(), + Self::ItemBrushBrushingGeneric { inner } => inner.0.clone(), + Self::ItemBrushBrushingGravel { inner } => inner.0.clone(), + Self::ItemBrushBrushingGravelComplete { inner } => inner.0.clone(), + Self::ItemBrushBrushingSand { inner } => inner.0.clone(), + Self::ItemBrushBrushingSandComplete { inner } => inner.0.clone(), + Self::ItemBucketEmpty { inner } => inner.0.clone(), + Self::ItemBucketEmptyAxolotl { inner } => inner.0.clone(), + Self::ItemBucketEmptyFish { inner } => inner.0.clone(), + Self::ItemBucketEmptyLava { inner } => inner.0.clone(), + Self::ItemBucketEmptyPowderSnow { inner } => inner.0.clone(), + Self::ItemBucketEmptyTadpole { inner } => inner.0.clone(), + Self::ItemBucketFill { inner } => inner.0.clone(), + Self::ItemBucketFillAxolotl { inner } => inner.0.clone(), + Self::ItemBucketFillFish { inner } => inner.0.clone(), + Self::ItemBucketFillLava { inner } => inner.0.clone(), + Self::ItemBucketFillPowderSnow { inner } => inner.0.clone(), + Self::ItemBucketFillTadpole { inner } => inner.0.clone(), + Self::ItemBundleDropContents { inner } => inner.0.clone(), + Self::ItemBundleInsert { inner } => inner.0.clone(), + Self::ItemBundleRemoveOne { inner } => inner.0.clone(), + Self::ItemChorusFruitTeleport { inner } => inner.0.clone(), + Self::ItemCropPlant { inner } => inner.0.clone(), + Self::ItemCrossbowHit { inner } => inner.0.clone(), + Self::ItemCrossbowLoadingEnd { inner } => inner.0.clone(), + Self::ItemCrossbowLoadingMiddle { inner } => inner.0.clone(), + Self::ItemCrossbowLoadingStart { inner } => inner.0.clone(), + Self::ItemCrossbowQuickCharge1 { inner } => inner.0.clone(), + Self::ItemCrossbowQuickCharge2 { inner } => inner.0.clone(), + Self::ItemCrossbowQuickCharge3 { inner } => inner.0.clone(), + Self::ItemCrossbowShoot { inner } => inner.0.clone(), + Self::ItemDyeUse { inner } => inner.0.clone(), + Self::ItemElytraFlying { inner } => inner.0.clone(), + Self::ItemFirechargeUse { inner } => inner.0.clone(), + Self::ItemFlintandsteelUse { inner } => inner.0.clone(), + Self::ItemGlowInkSacUse { inner } => inner.0.clone(), + Self::ItemGoatHornPlay { inner } => inner.0.clone(), + Self::ItemGoatHornSound0 { inner } => inner.0.clone(), + Self::ItemGoatHornSound1 { inner } => inner.0.clone(), + Self::ItemGoatHornSound2 { inner } => inner.0.clone(), + Self::ItemGoatHornSound3 { inner } => inner.0.clone(), + Self::ItemGoatHornSound4 { inner } => inner.0.clone(), + Self::ItemGoatHornSound5 { inner } => inner.0.clone(), + Self::ItemGoatHornSound6 { inner } => inner.0.clone(), + Self::ItemGoatHornSound7 { inner } => inner.0.clone(), + Self::ItemHoeTill { inner } => inner.0.clone(), + Self::ItemHoneycombWaxOn { inner } => inner.0.clone(), + Self::ItemHoneyBottleDrink { inner } => inner.0.clone(), + Self::ItemInkSacUse { inner } => inner.0.clone(), + Self::ItemLodestoneCompassLock { inner } => inner.0.clone(), + Self::ItemMaceSmashAir { inner } => inner.0.clone(), + Self::ItemMaceSmashGround { inner } => inner.0.clone(), + Self::ItemMaceSmashGroundHeavy { inner } => inner.0.clone(), + Self::ItemNetherWartPlant { inner } => inner.0.clone(), + Self::ItemOminousBottleDispose { inner } => inner.0.clone(), + Self::ItemShieldBlock { inner } => inner.0.clone(), + Self::ItemShieldBreak { inner } => inner.0.clone(), + Self::ItemShovelFlatten { inner } => inner.0.clone(), + Self::ItemSpyglassStopUsing { inner } => inner.0.clone(), + Self::ItemSpyglassUse { inner } => inner.0.clone(), + Self::ItemTotemUse { inner } => inner.0.clone(), + Self::ItemTridentHit { inner } => inner.0.clone(), + Self::ItemTridentHitGround { inner } => inner.0.clone(), + Self::ItemTridentReturn { inner } => inner.0.clone(), + Self::ItemTridentRiptide1 { inner } => inner.0.clone(), + Self::ItemTridentRiptide2 { inner } => inner.0.clone(), + Self::ItemTridentRiptide3 { inner } => inner.0.clone(), + Self::ItemTridentThrow { inner } => inner.0.clone(), + Self::ItemTridentThunder { inner } => inner.0.clone(), + Self::ItemWolfArmorBreak { inner } => inner.0.clone(), + Self::ItemWolfArmorCrack { inner } => inner.0.clone(), + Self::ItemWolfArmorDamage { inner } => inner.0.clone(), + Self::ItemWolfArmorRepair { inner } => inner.0.clone(), + Self::MusicCreative { inner } => inner.0.clone(), + Self::MusicCredits { inner } => inner.0.clone(), + Self::MusicDisc11 { inner } => inner.0.clone(), + Self::MusicDisc13 { inner } => inner.0.clone(), + Self::MusicDisc5 { inner } => inner.0.clone(), + Self::MusicDiscBlocks { inner } => inner.0.clone(), + Self::MusicDiscCat { inner } => inner.0.clone(), + Self::MusicDiscChirp { inner } => inner.0.clone(), + Self::MusicDiscCreator { inner } => inner.0.clone(), + Self::MusicDiscCreatorMusicBox { inner } => inner.0.clone(), + Self::MusicDiscFar { inner } => inner.0.clone(), + Self::MusicDiscMall { inner } => inner.0.clone(), + Self::MusicDiscMellohi { inner } => inner.0.clone(), + Self::MusicDiscOtherside { inner } => inner.0.clone(), + Self::MusicDiscPigstep { inner } => inner.0.clone(), + Self::MusicDiscPrecipice { inner } => inner.0.clone(), + Self::MusicDiscRelic { inner } => inner.0.clone(), + Self::MusicDiscStal { inner } => inner.0.clone(), + Self::MusicDiscStrad { inner } => inner.0.clone(), + Self::MusicDiscWait { inner } => inner.0.clone(), + Self::MusicDiscWard { inner } => inner.0.clone(), + Self::MusicDragon { inner } => inner.0.clone(), + Self::MusicEnd { inner } => inner.0.clone(), + Self::MusicGame { inner } => inner.0.clone(), + Self::MusicMenu { inner } => inner.0.clone(), + Self::MusicNetherBasaltDeltas { inner } => inner.0.clone(), + Self::MusicNetherCrimsonForest { inner } => inner.0.clone(), + Self::MusicNetherNetherWastes { inner } => inner.0.clone(), + Self::MusicNetherSoulSandValley { inner } => inner.0.clone(), + Self::MusicNetherWarpedForest { inner } => inner.0.clone(), + Self::MusicOverworldBadlands { inner } => inner.0.clone(), + Self::MusicOverworldBambooJungle { inner } => inner.0.clone(), + Self::MusicOverworldCherryGrove { inner } => inner.0.clone(), + Self::MusicOverworldDeepDark { inner } => inner.0.clone(), + Self::MusicOverworldDesert { inner } => inner.0.clone(), + Self::MusicOverworldDripstoneCaves { inner } => inner.0.clone(), + Self::MusicOverworldFlowerForest { inner } => inner.0.clone(), + Self::MusicOverworldForest { inner } => inner.0.clone(), + Self::MusicOverworldFrozenPeaks { inner } => inner.0.clone(), + Self::MusicOverworldGrove { inner } => inner.0.clone(), + Self::MusicOverworldJaggedPeaks { inner } => inner.0.clone(), + Self::MusicOverworldJungle { inner } => inner.0.clone(), + Self::MusicOverworldLushCaves { inner } => inner.0.clone(), + Self::MusicOverworldMeadow { inner } => inner.0.clone(), + Self::MusicOverworldOldGrowthTaiga { inner } => inner.0.clone(), + Self::MusicOverworldSnowySlopes { inner } => inner.0.clone(), + Self::MusicOverworldSparseJungle { inner } => inner.0.clone(), + Self::MusicOverworldStonyPeaks { inner } => inner.0.clone(), + Self::MusicOverworldSwamp { inner } => inner.0.clone(), + Self::MusicUnderWater { inner } => inner.0.clone(), + Self::ParticleSoulEscape { inner } => inner.0.clone(), + Self::UiButtonClick { inner } => inner.0.clone(), + Self::UiCartographyTableTakeResult { inner } => inner.0.clone(), + Self::UiLoomSelectPattern { inner } => inner.0.clone(), + Self::UiLoomTakeResult { inner } => inner.0.clone(), + Self::UiStonecutterSelectRecipe { inner } => inner.0.clone(), + Self::UiStonecutterTakeResult { inner } => inner.0.clone(), + Self::UiToastChallengeComplete { inner } => inner.0.clone(), + Self::UiToastIn { inner } => inner.0.clone(), + Self::UiToastOut { inner } => inner.0.clone(), + Self::WeatherRain { inner } => inner.0.clone(), + Self::WeatherRainAbove { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::AmbientBasaltDeltasAdditions { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AmbientBasaltDeltasLoop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AmbientBasaltDeltasMood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AmbientCave { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AmbientCrimsonForestAdditions { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AmbientCrimsonForestLoop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AmbientCrimsonForestMood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AmbientNetherWastesAdditions { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AmbientNetherWastesLoop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AmbientNetherWastesMood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AmbientSoulSandValleyAdditions { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AmbientSoulSandValleyLoop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AmbientSoulSandValleyMood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AmbientUnderwaterEnter { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AmbientUnderwaterExit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AmbientUnderwaterLoop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AmbientUnderwaterLoopAdditions { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AmbientUnderwaterLoopAdditionsRare { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AmbientUnderwaterLoopAdditionsUltraRare { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AmbientWarpedForestAdditions { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AmbientWarpedForestLoop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AmbientWarpedForestMood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAmethystBlockBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAmethystBlockChime { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAmethystBlockFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAmethystBlockHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAmethystBlockPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAmethystBlockResonate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAmethystBlockStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAmethystClusterBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAmethystClusterFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAmethystClusterHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAmethystClusterPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAmethystClusterStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAncientDebrisBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAncientDebrisFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAncientDebrisHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAncientDebrisPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAncientDebrisStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAnvilBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAnvilDestroy { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAnvilFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAnvilHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAnvilLand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAnvilPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAnvilStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAnvilUse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAzaleaBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAzaleaFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAzaleaHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAzaleaLeavesBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAzaleaLeavesFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAzaleaLeavesHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAzaleaLeavesPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAzaleaLeavesStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAzaleaPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockAzaleaStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooSaplingBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooSaplingHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooSaplingPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooWoodBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooWoodButtonClickOff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooWoodButtonClickOn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooWoodDoorClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooWoodDoorOpen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooWoodFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooWoodFenceGateClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooWoodFenceGateOpen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooWoodHangingSignBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooWoodHangingSignFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooWoodHangingSignHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooWoodHangingSignPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooWoodHangingSignStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooWoodHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooWoodPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooWoodPressurePlateClickOff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooWoodPressurePlateClickOn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooWoodStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooWoodTrapdoorClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBambooWoodTrapdoorOpen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBarrelClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBarrelOpen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBasaltBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBasaltFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBasaltHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBasaltPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBasaltStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBeaconActivate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBeaconAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBeaconDeactivate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBeaconPowerSelect { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBeehiveDrip { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBeehiveEnter { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBeehiveExit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBeehiveShear { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBeehiveWork { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBellResonate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBellUse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBigDripleafBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBigDripleafFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBigDripleafHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBigDripleafPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBigDripleafStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBigDripleafTiltDown { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBigDripleafTiltUp { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBlastfurnaceFireCrackle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBoneBlockBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBoneBlockFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBoneBlockHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBoneBlockPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBoneBlockStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBrewingStandBrew { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBubbleColumnBubblePop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBubbleColumnUpwardsAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBubbleColumnUpwardsInside { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBubbleColumnWhirlpoolAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockBubbleColumnWhirlpoolInside { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCakeAddCandle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCalciteBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCalciteFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCalciteHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCalcitePlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCalciteStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCampfireCrackle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCandleAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCandleBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCandleExtinguish { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCandleFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCandleHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCandlePlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCandleStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCaveVinesBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCaveVinesFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCaveVinesHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCaveVinesPickBerries { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCaveVinesPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCaveVinesStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockChainBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockChainFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockChainHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockChainPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockChainStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryLeavesBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryLeavesFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryLeavesHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryLeavesPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryLeavesStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherrySaplingBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherrySaplingFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherrySaplingHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherrySaplingPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherrySaplingStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryWoodBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryWoodButtonClickOff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryWoodButtonClickOn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryWoodDoorClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryWoodDoorOpen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryWoodFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryWoodFenceGateClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryWoodFenceGateOpen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryWoodHangingSignBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryWoodHangingSignFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryWoodHangingSignHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryWoodHangingSignPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryWoodHangingSignStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryWoodHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryWoodPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryWoodPressurePlateClickOff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryWoodPressurePlateClickOn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryWoodStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryWoodTrapdoorClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCherryWoodTrapdoorOpen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockChestClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockChestLocked { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockChestOpen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockChiseledBookshelfBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockChiseledBookshelfFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockChiseledBookshelfHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockChiseledBookshelfInsert { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockChiseledBookshelfInsertEnchanted { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockChiseledBookshelfPickup { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockChiseledBookshelfPickupEnchanted { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockChiseledBookshelfPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockChiseledBookshelfStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockChorusFlowerDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockChorusFlowerGrow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCobwebBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCobwebFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCobwebHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCobwebPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCobwebStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockComparatorClick { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockComposterEmpty { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockComposterFill { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockComposterFillSuccess { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockComposterReady { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockConduitActivate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockConduitAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockConduitAmbientShort { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockConduitAttackTarget { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockConduitDeactivate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCopperBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCopperBulbBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCopperBulbFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCopperBulbHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCopperBulbPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCopperBulbStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCopperBulbTurnOff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCopperBulbTurnOn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCopperDoorClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCopperDoorOpen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCopperFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCopperGrateBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCopperGrateFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCopperGrateHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCopperGratePlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCopperGrateStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCopperHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCopperPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCopperStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCopperTrapdoorClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCopperTrapdoorOpen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCoralBlockBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCoralBlockFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCoralBlockHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCoralBlockPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCoralBlockStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCrafterCraft { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCrafterFail { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockCropBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDecoratedPotBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDecoratedPotFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDecoratedPotHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDecoratedPotInsert { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDecoratedPotInsertFail { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDecoratedPotPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDecoratedPotShatter { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDecoratedPotStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDeepslateBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDeepslateBricksBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDeepslateBricksFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDeepslateBricksHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDeepslateBricksPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDeepslateBricksStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDeepslateFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDeepslateHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDeepslatePlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDeepslateStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDeepslateTilesBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDeepslateTilesFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDeepslateTilesHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDeepslateTilesPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDeepslateTilesStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDispenserDispense { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDispenserFail { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDispenserLaunch { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDripstoneBlockBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDripstoneBlockFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDripstoneBlockHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDripstoneBlockPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockDripstoneBlockStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockEnchantmentTableUse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockEnderChestClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockEnderChestOpen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockEndGatewaySpawn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockEndPortalFrameFill { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockEndPortalSpawn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFenceGateClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFenceGateOpen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFireAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFireExtinguish { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFloweringAzaleaBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFloweringAzaleaFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFloweringAzaleaHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFloweringAzaleaPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFloweringAzaleaStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFroglightBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFroglightFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFroglightHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFroglightPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFroglightStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFrogspawnBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFrogspawnFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFrogspawnHatch { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFrogspawnHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFrogspawnPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFrogspawnStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFungusBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFungusFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFungusHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFungusPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFungusStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockFurnaceFireCrackle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockGildedBlackstoneBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockGildedBlackstoneFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockGildedBlackstoneHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockGildedBlackstonePlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockGildedBlackstoneStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockGlassBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockGlassFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockGlassHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockGlassPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockGlassStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockGrassBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockGrassFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockGrassHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockGrassPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockGrassStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockGravelBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockGravelFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockGravelHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockGravelPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockGravelStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockGrindstoneUse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockGrowingPlantCrop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockHangingRootsBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockHangingRootsFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockHangingRootsHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockHangingRootsPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockHangingRootsStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockHangingSignBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockHangingSignFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockHangingSignHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockHangingSignPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockHangingSignStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockHangingSignWaxedInteractFail { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockHeavyCoreBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockHeavyCoreFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockHeavyCoreHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockHeavyCorePlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockHeavyCoreStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockHoneyBlockBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockHoneyBlockFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockHoneyBlockHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockHoneyBlockPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockHoneyBlockSlide { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockHoneyBlockStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockIronDoorClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockIronDoorOpen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockIronTrapdoorClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockIronTrapdoorOpen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockLadderBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockLadderFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockLadderHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockLadderPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockLadderStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockLanternBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockLanternFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockLanternHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockLanternPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockLanternStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockLargeAmethystBudBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockLargeAmethystBudPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockLavaAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockLavaExtinguish { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockLavaPop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockLeverClick { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockLilyPadPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockLodestoneBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockLodestoneFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockLodestoneHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockLodestonePlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockLodestoneStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMangroveRootsBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMangroveRootsFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMangroveRootsHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMangroveRootsPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMangroveRootsStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMediumAmethystBudBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMediumAmethystBudPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMetalBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMetalFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMetalHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMetalPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMetalPressurePlateClickOff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMetalPressurePlateClickOn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMetalStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMossBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMossCarpetBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMossCarpetFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMossCarpetHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMossCarpetPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMossCarpetStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMossFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMossHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMossPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMossStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMuddyMangroveRootsBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMuddyMangroveRootsFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMuddyMangroveRootsHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMuddyMangroveRootsPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMuddyMangroveRootsStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMudBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMudBricksBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMudBricksFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMudBricksHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMudBricksPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMudBricksStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMudFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMudHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMudPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMudStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetheriteBlockBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetheriteBlockFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetheriteBlockHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetheriteBlockPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetheriteBlockStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherrackBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherrackFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherrackHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherrackPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherrackStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherBricksBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherBricksFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherBricksHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherBricksPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherBricksStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherGoldOreBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherGoldOreFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherGoldOreHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherGoldOrePlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherGoldOreStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherOreBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherOreFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherOreHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherOrePlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherOreStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherSproutsBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherSproutsFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherSproutsHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherSproutsPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherSproutsStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherWartBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherWoodBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherWoodButtonClickOff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherWoodButtonClickOn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherWoodDoorClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherWoodDoorOpen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherWoodFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherWoodFenceGateClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherWoodFenceGateOpen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherWoodHangingSignBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherWoodHangingSignFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherWoodHangingSignHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherWoodHangingSignPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherWoodHangingSignStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherWoodHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherWoodPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherWoodPressurePlateClickOff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherWoodPressurePlateClickOn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherWoodStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherWoodTrapdoorClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNetherWoodTrapdoorOpen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNoteBlockBanjo { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNoteBlockBasedrum { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNoteBlockBass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNoteBlockBell { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNoteBlockBit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNoteBlockChime { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNoteBlockCowBell { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNoteBlockDidgeridoo { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNoteBlockFlute { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNoteBlockGuitar { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNoteBlockHarp { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNoteBlockHat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNoteBlockImitateCreeper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNoteBlockImitateEnderDragon { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNoteBlockImitatePiglin { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNoteBlockImitateSkeleton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNoteBlockImitateWitherSkeleton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNoteBlockImitateZombie { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNoteBlockIronXylophone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNoteBlockPling { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNoteBlockSnare { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNoteBlockXylophone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNyliumBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNyliumFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNyliumHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNyliumPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockNyliumStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPackedMudBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPackedMudFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPackedMudHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPackedMudPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPackedMudStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPinkPetalsBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPinkPetalsFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPinkPetalsHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPinkPetalsPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPinkPetalsStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPistonContract { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPistonExtend { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPointedDripstoneBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPointedDripstoneDripLava { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPointedDripstoneDripLavaIntoCauldron { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPointedDripstoneDripWater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPointedDripstoneDripWaterIntoCauldron { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPointedDripstoneFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPointedDripstoneHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPointedDripstoneLand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPointedDripstonePlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPointedDripstoneStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPolishedDeepslateBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPolishedDeepslateFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPolishedDeepslateHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPolishedDeepslatePlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPolishedDeepslateStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPolishedTuffBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPolishedTuffFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPolishedTuffHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPolishedTuffPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPolishedTuffStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPortalAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPortalTravel { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPortalTrigger { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPowderSnowBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPowderSnowFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPowderSnowHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPowderSnowPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPowderSnowStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockPumpkinCarve { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockRedstoneTorchBurnout { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockRespawnAnchorAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockRespawnAnchorCharge { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockRespawnAnchorDeplete { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockRespawnAnchorSetSpawn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockRootedDirtBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockRootedDirtFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockRootedDirtHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockRootedDirtPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockRootedDirtStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockRootsBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockRootsFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockRootsHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockRootsPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockRootsStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSandBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSandFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSandHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSandPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSandStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockScaffoldingBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockScaffoldingFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockScaffoldingHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockScaffoldingPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockScaffoldingStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkCatalystBloom { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkCatalystBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkCatalystFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkCatalystHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkCatalystPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkCatalystStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkCharge { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkSensorBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkSensorClicking { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkSensorClickingStop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkSensorFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkSensorHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkSensorPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkSensorStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkShriekerBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkShriekerFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkShriekerHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkShriekerPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkShriekerShriek { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkShriekerStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkSpread { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkVeinBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkVeinFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkVeinHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkVeinPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSculkVeinStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockShroomlightBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockShroomlightFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockShroomlightHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockShroomlightPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockShroomlightStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockShulkerBoxClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockShulkerBoxOpen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSignWaxedInteractFail { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSlimeBlockBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSlimeBlockFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSlimeBlockHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSlimeBlockPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSlimeBlockStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSmallAmethystBudBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSmallAmethystBudPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSmallDripleafBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSmallDripleafFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSmallDripleafHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSmallDripleafPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSmallDripleafStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSmithingTableUse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSmokerSmoke { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSnifferEggCrack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSnifferEggHatch { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSnifferEggPlop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSnowBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSnowFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSnowHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSnowPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSnowStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSoulSandBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSoulSandFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSoulSandHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSoulSandPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSoulSandStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSoulSoilBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSoulSoilFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSoulSoilHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSoulSoilPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSoulSoilStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSpongeAbsorb { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSpongeBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSpongeFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSpongeHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSpongePlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSpongeStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSporeBlossomBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSporeBlossomFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSporeBlossomHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSporeBlossomPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSporeBlossomStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockStemBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockStemFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockStemHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockStemPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockStemStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockStoneBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockStoneButtonClickOff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockStoneButtonClickOn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockStoneFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockStoneHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockStonePlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockStonePressurePlateClickOff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockStonePressurePlateClickOn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockStoneStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSuspiciousGravelBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSuspiciousGravelFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSuspiciousGravelHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSuspiciousGravelPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSuspiciousGravelStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSuspiciousSandBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSuspiciousSandFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSuspiciousSandHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSuspiciousSandPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSuspiciousSandStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSweetBerryBushBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSweetBerryBushPickBerries { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockSweetBerryBushPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTrialSpawnerAboutToSpawnItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTrialSpawnerAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTrialSpawnerAmbientOminous { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTrialSpawnerBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTrialSpawnerCloseShutter { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTrialSpawnerDetectPlayer { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTrialSpawnerEjectItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTrialSpawnerFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTrialSpawnerHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTrialSpawnerOminousActivate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTrialSpawnerOpenShutter { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTrialSpawnerPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTrialSpawnerSpawnItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTrialSpawnerSpawnItemBegin { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTrialSpawnerSpawnMob { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTrialSpawnerStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTripwireAttach { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTripwireClickOff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTripwireClickOn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTripwireDetach { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTuffBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTuffBricksBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTuffBricksFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTuffBricksHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTuffBricksPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTuffBricksStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTuffFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTuffHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTuffPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockTuffStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockVaultActivate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockVaultAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockVaultBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockVaultCloseShutter { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockVaultDeactivate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockVaultEjectItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockVaultFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockVaultHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockVaultInsertItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockVaultInsertItemFail { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockVaultOpenShutter { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockVaultPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockVaultRejectRewardedPlayer { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockVaultStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockVineBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockVineFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockVineHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockVinePlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockVineStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWartBlockBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWartBlockFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWartBlockHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWartBlockPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWartBlockStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWaterAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWeepingVinesBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWeepingVinesFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWeepingVinesHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWeepingVinesPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWeepingVinesStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWetGrassBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWetGrassFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWetGrassHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWetGrassPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWetGrassStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWetSpongeBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWetSpongeDries { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWetSpongeFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWetSpongeHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWetSpongePlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWetSpongeStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWoodenButtonClickOff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWoodenButtonClickOn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWoodenDoorClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWoodenDoorOpen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWoodenPressurePlateClickOff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWoodenPressurePlateClickOn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWoodenTrapdoorClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWoodenTrapdoorOpen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWoodBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWoodFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWoodHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWoodPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWoodStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWoolBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWoolFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWoolHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWoolPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockWoolStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnchantThornsHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityAllayAmbientWithoutItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityAllayAmbientWithItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityAllayDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityAllayHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityAllayItemGiven { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityAllayItemTaken { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityAllayItemThrown { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityArmadilloAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityArmadilloBrush { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityArmadilloDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityArmadilloEat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityArmadilloHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityArmadilloHurtReduced { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityArmadilloLand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityArmadilloPeek { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityArmadilloRoll { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityArmadilloScuteDrop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityArmadilloStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityArmadilloUnrollFinish { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityArmadilloUnrollStart { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityArmorStandBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityArmorStandFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityArmorStandHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityArmorStandPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityArrowHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityArrowHitPlayer { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityArrowShoot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityAxolotlAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityAxolotlDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityAxolotlHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityAxolotlIdleAir { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityAxolotlIdleWater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityAxolotlSplash { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityAxolotlSwim { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBatAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBatDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBatHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBatLoop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBatTakeoff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBeeDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBeeHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBeeLoop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBeeLoopAggressive { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBeePollinate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBeeSting { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBlazeAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBlazeBurn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBlazeDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBlazeHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBlazeShoot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBoatPaddleLand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBoatPaddleWater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBoggedAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBoggedDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBoggedHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBoggedShear { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBoggedStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBreezeCharge { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBreezeDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBreezeDeflect { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBreezeHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBreezeIdleAir { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBreezeIdleGround { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBreezeInhale { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBreezeJump { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBreezeLand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBreezeShoot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBreezeSlide { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBreezeWhirl { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityBreezeWindBurst { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCamelAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCamelDash { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCamelDashReady { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCamelDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCamelEat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCamelHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCamelSaddle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCamelSit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCamelStand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCamelStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCamelStepSand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCatAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCatBegForFood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCatDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCatEat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCatHiss { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCatHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCatPurr { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCatPurreow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCatStrayAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityChickenAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityChickenDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityChickenEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityChickenHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityChickenStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCodAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCodDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCodFlop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCodHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCowAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCowDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCowHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCowMilk { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCowStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCreeperDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCreeperHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityCreeperPrimed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDolphinAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDolphinAmbientWater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDolphinAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDolphinDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDolphinEat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDolphinHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDolphinJump { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDolphinPlay { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDolphinSplash { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDolphinSwim { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDonkeyAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDonkeyAngry { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDonkeyChest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDonkeyDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDonkeyEat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDonkeyHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDonkeyJump { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDragonFireballExplode { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDrownedAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDrownedAmbientWater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDrownedDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDrownedDeathWater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDrownedHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDrownedHurtWater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDrownedShoot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDrownedStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDrownedSwim { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEggThrow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityElderGuardianAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityElderGuardianAmbientLand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityElderGuardianCurse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityElderGuardianDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityElderGuardianDeathLand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityElderGuardianFlop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityElderGuardianHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityElderGuardianHurtLand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEndermanAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEndermanDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEndermanHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEndermanScream { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEndermanStare { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEndermanTeleport { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEndermiteAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEndermiteDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEndermiteHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEndermiteStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEnderDragonAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEnderDragonDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEnderDragonFlap { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEnderDragonGrowl { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEnderDragonHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEnderDragonShoot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEnderEyeDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEnderEyeLaunch { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEnderPearlThrow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEvokerAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEvokerCastSpell { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEvokerCelebrate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEvokerDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEvokerFangsAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEvokerHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEvokerPrepareAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEvokerPrepareSummon { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEvokerPrepareWololo { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityExperienceBottleThrow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityExperienceOrbPickup { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFireworkRocketBlast { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFireworkRocketBlastFar { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFireworkRocketLargeBlast { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFireworkRocketLargeBlastFar { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFireworkRocketLaunch { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFireworkRocketShoot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFireworkRocketTwinkle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFireworkRocketTwinkleFar { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFishingBobberRetrieve { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFishingBobberSplash { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFishingBobberThrow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFishSwim { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFoxAggro { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFoxAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFoxBite { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFoxDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFoxEat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFoxHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFoxScreech { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFoxSleep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFoxSniff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFoxSpit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFoxTeleport { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFrogAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFrogDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFrogEat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFrogHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFrogLaySpawn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFrogLongJump { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFrogStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityFrogTongue { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGenericBigFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGenericBurn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGenericDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGenericDrink { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGenericEat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGenericExplode { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGenericExtinguishFire { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGenericHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGenericSmallFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGenericSplash { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGenericSwim { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGhastAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGhastDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGhastHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGhastScream { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGhastShoot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGhastWarn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGlowItemFrameAddItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGlowItemFrameBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGlowItemFramePlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGlowItemFrameRemoveItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGlowItemFrameRotateItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGlowSquidAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGlowSquidDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGlowSquidHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGlowSquidSquirt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGoatAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGoatDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGoatEat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGoatHornBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGoatHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGoatLongJump { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGoatMilk { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGoatPrepareRam { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGoatRamImpact { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGoatScreamingAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGoatScreamingDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGoatScreamingEat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGoatScreamingHornBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGoatScreamingHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGoatScreamingLongJump { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGoatScreamingMilk { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGoatScreamingPrepareRam { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGoatScreamingRamImpact { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGoatStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGuardianAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGuardianAmbientLand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGuardianAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGuardianDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGuardianDeathLand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGuardianFlop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGuardianHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityGuardianHurtLand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHoglinAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHoglinAngry { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHoglinAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHoglinConvertedToZombified { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHoglinDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHoglinHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHoglinRetreat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHoglinStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHorseAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHorseAngry { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHorseArmor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHorseBreathe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHorseDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHorseEat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHorseGallop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHorseHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHorseJump { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHorseLand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHorseSaddle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHorseStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHorseStepWood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHostileBigFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHostileDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHostileHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHostileSmallFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHostileSplash { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHostileSwim { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHuskAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHuskConvertedToZombie { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHuskDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHuskHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityHuskStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityIllusionerAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityIllusionerCastSpell { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityIllusionerDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityIllusionerHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityIllusionerMirrorMove { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityIllusionerPrepareBlindness { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityIllusionerPrepareMirror { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityIronGolemAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityIronGolemDamage { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityIronGolemDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityIronGolemHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityIronGolemRepair { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityIronGolemStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityItemBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityItemFrameAddItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityItemFrameBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityItemFramePlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityItemFrameRemoveItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityItemFrameRotateItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityItemPickup { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityLeashKnotBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityLeashKnotPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityLightningBoltImpact { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityLightningBoltThunder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityLingeringPotionThrow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityLlamaAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityLlamaAngry { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityLlamaChest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityLlamaDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityLlamaEat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityLlamaHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityLlamaSpit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityLlamaStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityLlamaSwag { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityMagmaCubeDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityMagmaCubeDeathSmall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityMagmaCubeHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityMagmaCubeHurtSmall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityMagmaCubeJump { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityMagmaCubeSquish { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityMagmaCubeSquishSmall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityMinecartInside { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityMinecartInsideUnderwater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityMinecartRiding { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityMooshroomConvert { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityMooshroomEat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityMooshroomMilk { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityMooshroomShear { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityMooshroomSuspiciousMilk { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityMuleAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityMuleAngry { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityMuleChest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityMuleDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityMuleEat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityMuleHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityMuleJump { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityOcelotAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityOcelotDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityOcelotHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPaintingBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPaintingPlace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPandaAggressiveAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPandaAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPandaBite { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPandaCantBreed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPandaDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPandaEat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPandaHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPandaPreSneeze { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPandaSneeze { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPandaStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPandaWorriedAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotEat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotFly { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateBlaze { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateBogged { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateBreeze { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateCreeper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateDrowned { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateElderGuardian { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateEndermite { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateEnderDragon { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateEvoker { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateGhast { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateGuardian { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateHoglin { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateHusk { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateIllusioner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateMagmaCube { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitatePhantom { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitatePiglin { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitatePiglinBrute { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitatePillager { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateRavager { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateShulker { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateSilverfish { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateSkeleton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateSlime { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateSpider { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateStray { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateVex { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateVindicator { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateWarden { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateWitch { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateWither { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateWitherSkeleton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateZoglin { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateZombie { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotImitateZombieVillager { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityParrotStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPhantomAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPhantomBite { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPhantomDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPhantomFlap { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPhantomHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPhantomSwoop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPiglinAdmiringItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPiglinAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPiglinAngry { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPiglinBruteAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPiglinBruteAngry { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPiglinBruteConvertedToZombified { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPiglinBruteDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPiglinBruteHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPiglinBruteStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPiglinCelebrate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPiglinConvertedToZombified { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPiglinDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPiglinHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPiglinJealous { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPiglinRetreat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPiglinStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPigAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPigDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPigHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPigSaddle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPigStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPillagerAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPillagerCelebrate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPillagerDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPillagerHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPlayerAttackCrit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPlayerAttackKnockback { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPlayerAttackNodamage { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPlayerAttackStrong { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPlayerAttackSweep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPlayerAttackWeak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPlayerBigFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPlayerBreath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPlayerBurp { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPlayerDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPlayerHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPlayerHurtDrown { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPlayerHurtFreeze { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPlayerHurtOnFire { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPlayerHurtSweetBerryBush { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPlayerLevelup { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPlayerSmallFall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPlayerSplash { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPlayerSplashHighSpeed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPlayerSwim { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPlayerTeleport { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPolarBearAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPolarBearAmbientBaby { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPolarBearDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPolarBearHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPolarBearStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPolarBearWarning { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPufferFishAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPufferFishBlowOut { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPufferFishBlowUp { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPufferFishDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPufferFishFlop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPufferFishHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPufferFishSting { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityRabbitAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityRabbitAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityRabbitDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityRabbitHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityRabbitJump { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityRavagerAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityRavagerAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityRavagerCelebrate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityRavagerDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityRavagerHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityRavagerRoar { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityRavagerStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityRavagerStunned { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySalmonAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySalmonDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySalmonFlop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySalmonHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySheepAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySheepDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySheepHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySheepShear { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySheepStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityShulkerAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityShulkerBulletHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityShulkerBulletHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityShulkerClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityShulkerDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityShulkerHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityShulkerHurtClosed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityShulkerOpen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityShulkerShoot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityShulkerTeleport { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySilverfishAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySilverfishDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySilverfishHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySilverfishStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySkeletonAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySkeletonConvertedToStray { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySkeletonDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySkeletonHorseAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySkeletonHorseAmbientWater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySkeletonHorseDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySkeletonHorseGallopWater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySkeletonHorseHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySkeletonHorseJumpWater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySkeletonHorseStepWater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySkeletonHorseSwim { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySkeletonHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySkeletonShoot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySkeletonStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySlimeAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySlimeDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySlimeDeathSmall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySlimeHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySlimeHurtSmall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySlimeJump { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySlimeJumpSmall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySlimeSquish { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySlimeSquishSmall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySnifferDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySnifferDigging { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySnifferDiggingStop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySnifferDropSeed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySnifferEat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySnifferHappy { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySnifferHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySnifferIdle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySnifferScenting { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySnifferSearching { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySnifferSniffing { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySnifferStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySnowballThrow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySnowGolemAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySnowGolemDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySnowGolemHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySnowGolemShear { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySnowGolemShoot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySpiderAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySpiderDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySpiderHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySpiderStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySplashPotionBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySplashPotionThrow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySquidAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySquidDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySquidHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntitySquidSquirt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityStrayAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityStrayDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityStrayHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityStrayStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityStriderAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityStriderDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityStriderEat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityStriderHappy { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityStriderHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityStriderRetreat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityStriderSaddle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityStriderStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityStriderStepLava { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityTadpoleDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityTadpoleFlop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityTadpoleGrowUp { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityTadpoleHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityTntPrimed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityTropicalFishAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityTropicalFishDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityTropicalFishFlop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityTropicalFishHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityTurtleAmbientLand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityTurtleDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityTurtleDeathBaby { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityTurtleEggBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityTurtleEggCrack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityTurtleEggHatch { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityTurtleHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityTurtleHurtBaby { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityTurtleLayEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityTurtleShamble { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityTurtleShambleBaby { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityTurtleSwim { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVexAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVexCharge { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVexDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVexHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVillagerAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVillagerCelebrate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVillagerDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVillagerHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVillagerNo { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVillagerTrade { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVillagerWorkArmorer { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVillagerWorkButcher { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVillagerWorkCartographer { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVillagerWorkCleric { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVillagerWorkFarmer { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVillagerWorkFisherman { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVillagerWorkFletcher { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVillagerWorkLeatherworker { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVillagerWorkLibrarian { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVillagerWorkMason { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVillagerWorkShepherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVillagerWorkToolsmith { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVillagerWorkWeaponsmith { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVillagerYes { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVindicatorAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVindicatorCelebrate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVindicatorDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityVindicatorHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWanderingTraderAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWanderingTraderDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWanderingTraderDisappeared { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWanderingTraderDrinkMilk { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWanderingTraderDrinkPotion { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWanderingTraderHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWanderingTraderNo { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWanderingTraderReappeared { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWanderingTraderTrade { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWanderingTraderYes { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWardenAgitated { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWardenAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWardenAngry { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWardenAttackImpact { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWardenDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWardenDig { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWardenEmerge { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWardenHeartbeat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWardenHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWardenListening { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWardenListeningAngry { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWardenNearbyClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWardenNearbyCloser { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWardenNearbyClosest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWardenRoar { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWardenSniff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWardenSonicBoom { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWardenSonicCharge { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWardenStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWardenTendrilClicks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWindChargeThrow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWindChargeWindBurst { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWitchAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWitchCelebrate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWitchDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWitchDrink { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWitchHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWitchThrow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWitherAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWitherBreakBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWitherDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWitherHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWitherShoot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWitherSkeletonAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWitherSkeletonDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWitherSkeletonHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWitherSkeletonStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWitherSpawn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWolfAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWolfDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWolfGrowl { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWolfHowl { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWolfHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWolfPant { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWolfShake { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWolfStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityWolfWhine { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZoglinAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZoglinAngry { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZoglinAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZoglinDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZoglinHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZoglinStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZombieAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZombieAttackIronDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZombieAttackWoodenDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZombieBreakWoodenDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZombieConvertedToDrowned { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZombieDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZombieDestroyEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZombieHorseAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZombieHorseDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZombieHorseHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZombieHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZombieInfect { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZombieStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZombieVillagerAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZombieVillagerConverted { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZombieVillagerCure { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZombieVillagerDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZombieVillagerHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZombieVillagerStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZombifiedPiglinAmbient { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZombifiedPiglinAngry { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZombifiedPiglinDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityZombifiedPiglinHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EventMobEffectBadOmen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EventMobEffectRaidOmen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EventMobEffectTrialOmen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EventRaidHorn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IntentionallyEmpty { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemArmorEquipChain { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemArmorEquipDiamond { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemArmorEquipElytra { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemArmorEquipGeneric { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemArmorEquipGold { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemArmorEquipIron { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemArmorEquipLeather { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemArmorEquipNetherite { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemArmorEquipTurtle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemArmorEquipWolf { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemArmorUnequipWolf { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemAxeScrape { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemAxeStrip { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemAxeWaxOff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBoneMealUse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBookPageTurn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBookPut { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBottleEmpty { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBottleFill { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBottleFillDragonbreath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBrushBrushingGeneric { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBrushBrushingGravel { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBrushBrushingGravelComplete { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBrushBrushingSand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBrushBrushingSandComplete { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBucketEmpty { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBucketEmptyAxolotl { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBucketEmptyFish { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBucketEmptyLava { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBucketEmptyPowderSnow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBucketEmptyTadpole { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBucketFill { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBucketFillAxolotl { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBucketFillFish { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBucketFillLava { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBucketFillPowderSnow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBucketFillTadpole { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBundleDropContents { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBundleInsert { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemBundleRemoveOne { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemChorusFruitTeleport { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemCropPlant { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemCrossbowHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemCrossbowLoadingEnd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemCrossbowLoadingMiddle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemCrossbowLoadingStart { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemCrossbowQuickCharge1 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemCrossbowQuickCharge2 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemCrossbowQuickCharge3 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemCrossbowShoot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemDyeUse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemElytraFlying { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemFirechargeUse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemFlintandsteelUse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemGlowInkSacUse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemGoatHornPlay { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemGoatHornSound0 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemGoatHornSound1 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemGoatHornSound2 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemGoatHornSound3 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemGoatHornSound4 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemGoatHornSound5 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemGoatHornSound6 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemGoatHornSound7 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemHoeTill { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemHoneycombWaxOn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemHoneyBottleDrink { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemInkSacUse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemLodestoneCompassLock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemMaceSmashAir { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemMaceSmashGround { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemMaceSmashGroundHeavy { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemNetherWartPlant { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemOminousBottleDispose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemShieldBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemShieldBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemShovelFlatten { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemSpyglassStopUsing { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemSpyglassUse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemTotemUse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemTridentHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemTridentHitGround { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemTridentReturn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemTridentRiptide1 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemTridentRiptide2 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemTridentRiptide3 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemTridentThrow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemTridentThunder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemWolfArmorBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemWolfArmorCrack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemWolfArmorDamage { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemWolfArmorRepair { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicCreative { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicCredits { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDisc11 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDisc13 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDisc5 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscBlocks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscCat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscChirp { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscCreator { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscCreatorMusicBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscFar { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscMall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscMellohi { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscOtherside { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscPigstep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscPrecipice { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscRelic { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscStal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscStrad { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscWait { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscWard { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDragon { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicEnd { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::MusicGame { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicMenu { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicNetherBasaltDeltas { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicNetherCrimsonForest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicNetherNetherWastes { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicNetherSoulSandValley { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicNetherWarpedForest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicOverworldBadlands { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicOverworldBambooJungle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicOverworldCherryGrove { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicOverworldDeepDark { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicOverworldDesert { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicOverworldDripstoneCaves { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicOverworldFlowerForest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicOverworldForest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicOverworldFrozenPeaks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicOverworldGrove { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicOverworldJaggedPeaks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicOverworldJungle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicOverworldLushCaves { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicOverworldMeadow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicOverworldOldGrowthTaiga { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicOverworldSnowySlopes { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicOverworldSparseJungle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicOverworldStonyPeaks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicOverworldSwamp { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicUnderWater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ParticleSoulEscape { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::UiButtonClick { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::UiCartographyTableTakeResult { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::UiLoomSelectPattern { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::UiLoomTakeResult { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::UiStonecutterSelectRecipe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::UiStonecutterTakeResult { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::UiToastChallengeComplete { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::UiToastIn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::UiToastOut { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WeatherRain { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WeatherRainAbove { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for Sound<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Sound from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Sound")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Sound object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "AMBIENT_BASALT_DELTAS_ADDITIONS" => Ok(Sound::AmbientBasaltDeltasAdditions { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_BASALT_DELTAS_LOOP" => Ok(Sound::AmbientBasaltDeltasLoop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_BASALT_DELTAS_MOOD" => Ok(Sound::AmbientBasaltDeltasMood { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_CAVE" => Ok(Sound::AmbientCave { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_CRIMSON_FOREST_ADDITIONS" => Ok(Sound::AmbientCrimsonForestAdditions { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_CRIMSON_FOREST_LOOP" => Ok(Sound::AmbientCrimsonForestLoop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_CRIMSON_FOREST_MOOD" => Ok(Sound::AmbientCrimsonForestMood { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_NETHER_WASTES_ADDITIONS" => Ok(Sound::AmbientNetherWastesAdditions { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_NETHER_WASTES_LOOP" => Ok(Sound::AmbientNetherWastesLoop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_NETHER_WASTES_MOOD" => Ok(Sound::AmbientNetherWastesMood { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_SOUL_SAND_VALLEY_ADDITIONS" => Ok(Sound::AmbientSoulSandValleyAdditions { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_SOUL_SAND_VALLEY_LOOP" => Ok(Sound::AmbientSoulSandValleyLoop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_SOUL_SAND_VALLEY_MOOD" => Ok(Sound::AmbientSoulSandValleyMood { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_UNDERWATER_ENTER" => Ok(Sound::AmbientUnderwaterEnter { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_UNDERWATER_EXIT" => Ok(Sound::AmbientUnderwaterExit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_UNDERWATER_LOOP" => Ok(Sound::AmbientUnderwaterLoop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_UNDERWATER_LOOP_ADDITIONS" => Ok(Sound::AmbientUnderwaterLoopAdditions { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_UNDERWATER_LOOP_ADDITIONS_RARE" => { + Ok(Sound::AmbientUnderwaterLoopAdditionsRare { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "AMBIENT_UNDERWATER_LOOP_ADDITIONS_ULTRA_RARE" => { + Ok(Sound::AmbientUnderwaterLoopAdditionsUltraRare { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "AMBIENT_WARPED_FOREST_ADDITIONS" => Ok(Sound::AmbientWarpedForestAdditions { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_WARPED_FOREST_LOOP" => Ok(Sound::AmbientWarpedForestLoop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "AMBIENT_WARPED_FOREST_MOOD" => Ok(Sound::AmbientWarpedForestMood { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AMETHYST_BLOCK_BREAK" => Ok(Sound::BlockAmethystBlockBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AMETHYST_BLOCK_CHIME" => Ok(Sound::BlockAmethystBlockChime { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AMETHYST_BLOCK_FALL" => Ok(Sound::BlockAmethystBlockFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AMETHYST_BLOCK_HIT" => Ok(Sound::BlockAmethystBlockHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AMETHYST_BLOCK_PLACE" => Ok(Sound::BlockAmethystBlockPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AMETHYST_BLOCK_RESONATE" => Ok(Sound::BlockAmethystBlockResonate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AMETHYST_BLOCK_STEP" => Ok(Sound::BlockAmethystBlockStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AMETHYST_CLUSTER_BREAK" => Ok(Sound::BlockAmethystClusterBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AMETHYST_CLUSTER_FALL" => Ok(Sound::BlockAmethystClusterFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AMETHYST_CLUSTER_HIT" => Ok(Sound::BlockAmethystClusterHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AMETHYST_CLUSTER_PLACE" => Ok(Sound::BlockAmethystClusterPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AMETHYST_CLUSTER_STEP" => Ok(Sound::BlockAmethystClusterStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANCIENT_DEBRIS_BREAK" => Ok(Sound::BlockAncientDebrisBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANCIENT_DEBRIS_FALL" => Ok(Sound::BlockAncientDebrisFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANCIENT_DEBRIS_HIT" => Ok(Sound::BlockAncientDebrisHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANCIENT_DEBRIS_PLACE" => Ok(Sound::BlockAncientDebrisPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANCIENT_DEBRIS_STEP" => Ok(Sound::BlockAncientDebrisStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANVIL_BREAK" => Ok(Sound::BlockAnvilBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANVIL_DESTROY" => Ok(Sound::BlockAnvilDestroy { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANVIL_FALL" => Ok(Sound::BlockAnvilFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANVIL_HIT" => Ok(Sound::BlockAnvilHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANVIL_LAND" => Ok(Sound::BlockAnvilLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANVIL_PLACE" => Ok(Sound::BlockAnvilPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANVIL_STEP" => Ok(Sound::BlockAnvilStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ANVIL_USE" => Ok(Sound::BlockAnvilUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AZALEA_BREAK" => Ok(Sound::BlockAzaleaBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AZALEA_FALL" => Ok(Sound::BlockAzaleaFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AZALEA_HIT" => Ok(Sound::BlockAzaleaHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AZALEA_LEAVES_BREAK" => Ok(Sound::BlockAzaleaLeavesBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AZALEA_LEAVES_FALL" => Ok(Sound::BlockAzaleaLeavesFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AZALEA_LEAVES_HIT" => Ok(Sound::BlockAzaleaLeavesHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AZALEA_LEAVES_PLACE" => Ok(Sound::BlockAzaleaLeavesPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AZALEA_LEAVES_STEP" => Ok(Sound::BlockAzaleaLeavesStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AZALEA_PLACE" => Ok(Sound::BlockAzaleaPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_AZALEA_STEP" => Ok(Sound::BlockAzaleaStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_BREAK" => Ok(Sound::BlockBambooBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_FALL" => Ok(Sound::BlockBambooFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_HIT" => Ok(Sound::BlockBambooHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_PLACE" => Ok(Sound::BlockBambooPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_SAPLING_BREAK" => Ok(Sound::BlockBambooSaplingBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_SAPLING_HIT" => Ok(Sound::BlockBambooSaplingHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_SAPLING_PLACE" => Ok(Sound::BlockBambooSaplingPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_STEP" => Ok(Sound::BlockBambooStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_BREAK" => Ok(Sound::BlockBambooWoodBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_BUTTON_CLICK_OFF" => Ok(Sound::BlockBambooWoodButtonClickOff { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_BUTTON_CLICK_ON" => Ok(Sound::BlockBambooWoodButtonClickOn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_DOOR_CLOSE" => Ok(Sound::BlockBambooWoodDoorClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_DOOR_OPEN" => Ok(Sound::BlockBambooWoodDoorOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_FALL" => Ok(Sound::BlockBambooWoodFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_FENCE_GATE_CLOSE" => Ok(Sound::BlockBambooWoodFenceGateClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_FENCE_GATE_OPEN" => Ok(Sound::BlockBambooWoodFenceGateOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_HANGING_SIGN_BREAK" => { + Ok(Sound::BlockBambooWoodHangingSignBreak { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_BAMBOO_WOOD_HANGING_SIGN_FALL" => { + Ok(Sound::BlockBambooWoodHangingSignFall { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_BAMBOO_WOOD_HANGING_SIGN_HIT" => Ok(Sound::BlockBambooWoodHangingSignHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_HANGING_SIGN_PLACE" => { + Ok(Sound::BlockBambooWoodHangingSignPlace { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_BAMBOO_WOOD_HANGING_SIGN_STEP" => { + Ok(Sound::BlockBambooWoodHangingSignStep { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_BAMBOO_WOOD_HIT" => Ok(Sound::BlockBambooWoodHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_PLACE" => Ok(Sound::BlockBambooWoodPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_PRESSURE_PLATE_CLICK_OFF" => { + Ok(Sound::BlockBambooWoodPressurePlateClickOff { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_BAMBOO_WOOD_PRESSURE_PLATE_CLICK_ON" => { + Ok(Sound::BlockBambooWoodPressurePlateClickOn { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_BAMBOO_WOOD_STEP" => Ok(Sound::BlockBambooWoodStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_TRAPDOOR_CLOSE" => Ok(Sound::BlockBambooWoodTrapdoorClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BAMBOO_WOOD_TRAPDOOR_OPEN" => Ok(Sound::BlockBambooWoodTrapdoorOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BARREL_CLOSE" => Ok(Sound::BlockBarrelClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BARREL_OPEN" => Ok(Sound::BlockBarrelOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BASALT_BREAK" => Ok(Sound::BlockBasaltBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BASALT_FALL" => Ok(Sound::BlockBasaltFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BASALT_HIT" => Ok(Sound::BlockBasaltHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BASALT_PLACE" => Ok(Sound::BlockBasaltPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BASALT_STEP" => Ok(Sound::BlockBasaltStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BEACON_ACTIVATE" => Ok(Sound::BlockBeaconActivate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BEACON_AMBIENT" => Ok(Sound::BlockBeaconAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BEACON_DEACTIVATE" => Ok(Sound::BlockBeaconDeactivate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BEACON_POWER_SELECT" => Ok(Sound::BlockBeaconPowerSelect { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BEEHIVE_DRIP" => Ok(Sound::BlockBeehiveDrip { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BEEHIVE_ENTER" => Ok(Sound::BlockBeehiveEnter { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BEEHIVE_EXIT" => Ok(Sound::BlockBeehiveExit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BEEHIVE_SHEAR" => Ok(Sound::BlockBeehiveShear { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BEEHIVE_WORK" => Ok(Sound::BlockBeehiveWork { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BELL_RESONATE" => Ok(Sound::BlockBellResonate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BELL_USE" => Ok(Sound::BlockBellUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BIG_DRIPLEAF_BREAK" => Ok(Sound::BlockBigDripleafBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BIG_DRIPLEAF_FALL" => Ok(Sound::BlockBigDripleafFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BIG_DRIPLEAF_HIT" => Ok(Sound::BlockBigDripleafHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BIG_DRIPLEAF_PLACE" => Ok(Sound::BlockBigDripleafPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BIG_DRIPLEAF_STEP" => Ok(Sound::BlockBigDripleafStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BIG_DRIPLEAF_TILT_DOWN" => Ok(Sound::BlockBigDripleafTiltDown { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BIG_DRIPLEAF_TILT_UP" => Ok(Sound::BlockBigDripleafTiltUp { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BLASTFURNACE_FIRE_CRACKLE" => Ok(Sound::BlockBlastfurnaceFireCrackle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BONE_BLOCK_BREAK" => Ok(Sound::BlockBoneBlockBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BONE_BLOCK_FALL" => Ok(Sound::BlockBoneBlockFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BONE_BLOCK_HIT" => Ok(Sound::BlockBoneBlockHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BONE_BLOCK_PLACE" => Ok(Sound::BlockBoneBlockPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BONE_BLOCK_STEP" => Ok(Sound::BlockBoneBlockStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BREWING_STAND_BREW" => Ok(Sound::BlockBrewingStandBrew { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BUBBLE_COLUMN_BUBBLE_POP" => Ok(Sound::BlockBubbleColumnBubblePop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BUBBLE_COLUMN_UPWARDS_AMBIENT" => { + Ok(Sound::BlockBubbleColumnUpwardsAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_BUBBLE_COLUMN_UPWARDS_INSIDE" => Ok(Sound::BlockBubbleColumnUpwardsInside { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_BUBBLE_COLUMN_WHIRLPOOL_AMBIENT" => { + Ok(Sound::BlockBubbleColumnWhirlpoolAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_BUBBLE_COLUMN_WHIRLPOOL_INSIDE" => { + Ok(Sound::BlockBubbleColumnWhirlpoolInside { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_CAKE_ADD_CANDLE" => Ok(Sound::BlockCakeAddCandle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CALCITE_BREAK" => Ok(Sound::BlockCalciteBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CALCITE_FALL" => Ok(Sound::BlockCalciteFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CALCITE_HIT" => Ok(Sound::BlockCalciteHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CALCITE_PLACE" => Ok(Sound::BlockCalcitePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CALCITE_STEP" => Ok(Sound::BlockCalciteStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CAMPFIRE_CRACKLE" => Ok(Sound::BlockCampfireCrackle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CANDLE_AMBIENT" => Ok(Sound::BlockCandleAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CANDLE_BREAK" => Ok(Sound::BlockCandleBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CANDLE_EXTINGUISH" => Ok(Sound::BlockCandleExtinguish { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CANDLE_FALL" => Ok(Sound::BlockCandleFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CANDLE_HIT" => Ok(Sound::BlockCandleHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CANDLE_PLACE" => Ok(Sound::BlockCandlePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CANDLE_STEP" => Ok(Sound::BlockCandleStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CAVE_VINES_BREAK" => Ok(Sound::BlockCaveVinesBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CAVE_VINES_FALL" => Ok(Sound::BlockCaveVinesFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CAVE_VINES_HIT" => Ok(Sound::BlockCaveVinesHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CAVE_VINES_PICK_BERRIES" => Ok(Sound::BlockCaveVinesPickBerries { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CAVE_VINES_PLACE" => Ok(Sound::BlockCaveVinesPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CAVE_VINES_STEP" => Ok(Sound::BlockCaveVinesStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHAIN_BREAK" => Ok(Sound::BlockChainBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHAIN_FALL" => Ok(Sound::BlockChainFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHAIN_HIT" => Ok(Sound::BlockChainHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHAIN_PLACE" => Ok(Sound::BlockChainPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHAIN_STEP" => Ok(Sound::BlockChainStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_LEAVES_BREAK" => Ok(Sound::BlockCherryLeavesBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_LEAVES_FALL" => Ok(Sound::BlockCherryLeavesFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_LEAVES_HIT" => Ok(Sound::BlockCherryLeavesHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_LEAVES_PLACE" => Ok(Sound::BlockCherryLeavesPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_LEAVES_STEP" => Ok(Sound::BlockCherryLeavesStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_SAPLING_BREAK" => Ok(Sound::BlockCherrySaplingBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_SAPLING_FALL" => Ok(Sound::BlockCherrySaplingFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_SAPLING_HIT" => Ok(Sound::BlockCherrySaplingHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_SAPLING_PLACE" => Ok(Sound::BlockCherrySaplingPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_SAPLING_STEP" => Ok(Sound::BlockCherrySaplingStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_BREAK" => Ok(Sound::BlockCherryWoodBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_BUTTON_CLICK_OFF" => Ok(Sound::BlockCherryWoodButtonClickOff { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_BUTTON_CLICK_ON" => Ok(Sound::BlockCherryWoodButtonClickOn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_DOOR_CLOSE" => Ok(Sound::BlockCherryWoodDoorClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_DOOR_OPEN" => Ok(Sound::BlockCherryWoodDoorOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_FALL" => Ok(Sound::BlockCherryWoodFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_FENCE_GATE_CLOSE" => Ok(Sound::BlockCherryWoodFenceGateClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_FENCE_GATE_OPEN" => Ok(Sound::BlockCherryWoodFenceGateOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_HANGING_SIGN_BREAK" => { + Ok(Sound::BlockCherryWoodHangingSignBreak { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_CHERRY_WOOD_HANGING_SIGN_FALL" => { + Ok(Sound::BlockCherryWoodHangingSignFall { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_CHERRY_WOOD_HANGING_SIGN_HIT" => Ok(Sound::BlockCherryWoodHangingSignHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_HANGING_SIGN_PLACE" => { + Ok(Sound::BlockCherryWoodHangingSignPlace { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_CHERRY_WOOD_HANGING_SIGN_STEP" => { + Ok(Sound::BlockCherryWoodHangingSignStep { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_CHERRY_WOOD_HIT" => Ok(Sound::BlockCherryWoodHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_PLACE" => Ok(Sound::BlockCherryWoodPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_PRESSURE_PLATE_CLICK_OFF" => { + Ok(Sound::BlockCherryWoodPressurePlateClickOff { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_CHERRY_WOOD_PRESSURE_PLATE_CLICK_ON" => { + Ok(Sound::BlockCherryWoodPressurePlateClickOn { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_CHERRY_WOOD_STEP" => Ok(Sound::BlockCherryWoodStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_TRAPDOOR_CLOSE" => Ok(Sound::BlockCherryWoodTrapdoorClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHERRY_WOOD_TRAPDOOR_OPEN" => Ok(Sound::BlockCherryWoodTrapdoorOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHEST_CLOSE" => Ok(Sound::BlockChestClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHEST_LOCKED" => Ok(Sound::BlockChestLocked { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHEST_OPEN" => Ok(Sound::BlockChestOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHISELED_BOOKSHELF_BREAK" => Ok(Sound::BlockChiseledBookshelfBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHISELED_BOOKSHELF_FALL" => Ok(Sound::BlockChiseledBookshelfFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHISELED_BOOKSHELF_HIT" => Ok(Sound::BlockChiseledBookshelfHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHISELED_BOOKSHELF_INSERT" => Ok(Sound::BlockChiseledBookshelfInsert { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHISELED_BOOKSHELF_INSERT_ENCHANTED" => { + Ok(Sound::BlockChiseledBookshelfInsertEnchanted { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_CHISELED_BOOKSHELF_PICKUP" => Ok(Sound::BlockChiseledBookshelfPickup { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHISELED_BOOKSHELF_PICKUP_ENCHANTED" => { + Ok(Sound::BlockChiseledBookshelfPickupEnchanted { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_CHISELED_BOOKSHELF_PLACE" => Ok(Sound::BlockChiseledBookshelfPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHISELED_BOOKSHELF_STEP" => Ok(Sound::BlockChiseledBookshelfStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHORUS_FLOWER_DEATH" => Ok(Sound::BlockChorusFlowerDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CHORUS_FLOWER_GROW" => Ok(Sound::BlockChorusFlowerGrow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COBWEB_BREAK" => Ok(Sound::BlockCobwebBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COBWEB_FALL" => Ok(Sound::BlockCobwebFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COBWEB_HIT" => Ok(Sound::BlockCobwebHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COBWEB_PLACE" => Ok(Sound::BlockCobwebPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COBWEB_STEP" => Ok(Sound::BlockCobwebStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COMPARATOR_CLICK" => Ok(Sound::BlockComparatorClick { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COMPOSTER_EMPTY" => Ok(Sound::BlockComposterEmpty { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COMPOSTER_FILL" => Ok(Sound::BlockComposterFill { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COMPOSTER_FILL_SUCCESS" => Ok(Sound::BlockComposterFillSuccess { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COMPOSTER_READY" => Ok(Sound::BlockComposterReady { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CONDUIT_ACTIVATE" => Ok(Sound::BlockConduitActivate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CONDUIT_AMBIENT" => Ok(Sound::BlockConduitAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CONDUIT_AMBIENT_SHORT" => Ok(Sound::BlockConduitAmbientShort { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CONDUIT_ATTACK_TARGET" => Ok(Sound::BlockConduitAttackTarget { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CONDUIT_DEACTIVATE" => Ok(Sound::BlockConduitDeactivate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_BREAK" => Ok(Sound::BlockCopperBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_BULB_BREAK" => Ok(Sound::BlockCopperBulbBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_BULB_FALL" => Ok(Sound::BlockCopperBulbFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_BULB_HIT" => Ok(Sound::BlockCopperBulbHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_BULB_PLACE" => Ok(Sound::BlockCopperBulbPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_BULB_STEP" => Ok(Sound::BlockCopperBulbStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_BULB_TURN_OFF" => Ok(Sound::BlockCopperBulbTurnOff { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_BULB_TURN_ON" => Ok(Sound::BlockCopperBulbTurnOn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_DOOR_CLOSE" => Ok(Sound::BlockCopperDoorClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_DOOR_OPEN" => Ok(Sound::BlockCopperDoorOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_FALL" => Ok(Sound::BlockCopperFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_GRATE_BREAK" => Ok(Sound::BlockCopperGrateBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_GRATE_FALL" => Ok(Sound::BlockCopperGrateFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_GRATE_HIT" => Ok(Sound::BlockCopperGrateHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_GRATE_PLACE" => Ok(Sound::BlockCopperGratePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_GRATE_STEP" => Ok(Sound::BlockCopperGrateStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_HIT" => Ok(Sound::BlockCopperHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_PLACE" => Ok(Sound::BlockCopperPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_STEP" => Ok(Sound::BlockCopperStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_TRAPDOOR_CLOSE" => Ok(Sound::BlockCopperTrapdoorClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_COPPER_TRAPDOOR_OPEN" => Ok(Sound::BlockCopperTrapdoorOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CORAL_BLOCK_BREAK" => Ok(Sound::BlockCoralBlockBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CORAL_BLOCK_FALL" => Ok(Sound::BlockCoralBlockFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CORAL_BLOCK_HIT" => Ok(Sound::BlockCoralBlockHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CORAL_BLOCK_PLACE" => Ok(Sound::BlockCoralBlockPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CORAL_BLOCK_STEP" => Ok(Sound::BlockCoralBlockStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CRAFTER_CRAFT" => Ok(Sound::BlockCrafterCraft { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CRAFTER_FAIL" => Ok(Sound::BlockCrafterFail { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_CROP_BREAK" => Ok(Sound::BlockCropBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DECORATED_POT_BREAK" => Ok(Sound::BlockDecoratedPotBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DECORATED_POT_FALL" => Ok(Sound::BlockDecoratedPotFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DECORATED_POT_HIT" => Ok(Sound::BlockDecoratedPotHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DECORATED_POT_INSERT" => Ok(Sound::BlockDecoratedPotInsert { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DECORATED_POT_INSERT_FAIL" => Ok(Sound::BlockDecoratedPotInsertFail { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DECORATED_POT_PLACE" => Ok(Sound::BlockDecoratedPotPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DECORATED_POT_SHATTER" => Ok(Sound::BlockDecoratedPotShatter { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DECORATED_POT_STEP" => Ok(Sound::BlockDecoratedPotStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_BREAK" => Ok(Sound::BlockDeepslateBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_BRICKS_BREAK" => Ok(Sound::BlockDeepslateBricksBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_BRICKS_FALL" => Ok(Sound::BlockDeepslateBricksFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_BRICKS_HIT" => Ok(Sound::BlockDeepslateBricksHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_BRICKS_PLACE" => Ok(Sound::BlockDeepslateBricksPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_BRICKS_STEP" => Ok(Sound::BlockDeepslateBricksStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_FALL" => Ok(Sound::BlockDeepslateFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_HIT" => Ok(Sound::BlockDeepslateHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_PLACE" => Ok(Sound::BlockDeepslatePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_STEP" => Ok(Sound::BlockDeepslateStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_TILES_BREAK" => Ok(Sound::BlockDeepslateTilesBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_TILES_FALL" => Ok(Sound::BlockDeepslateTilesFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_TILES_HIT" => Ok(Sound::BlockDeepslateTilesHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_TILES_PLACE" => Ok(Sound::BlockDeepslateTilesPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DEEPSLATE_TILES_STEP" => Ok(Sound::BlockDeepslateTilesStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DISPENSER_DISPENSE" => Ok(Sound::BlockDispenserDispense { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DISPENSER_FAIL" => Ok(Sound::BlockDispenserFail { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DISPENSER_LAUNCH" => Ok(Sound::BlockDispenserLaunch { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DRIPSTONE_BLOCK_BREAK" => Ok(Sound::BlockDripstoneBlockBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DRIPSTONE_BLOCK_FALL" => Ok(Sound::BlockDripstoneBlockFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DRIPSTONE_BLOCK_HIT" => Ok(Sound::BlockDripstoneBlockHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DRIPSTONE_BLOCK_PLACE" => Ok(Sound::BlockDripstoneBlockPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_DRIPSTONE_BLOCK_STEP" => Ok(Sound::BlockDripstoneBlockStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ENCHANTMENT_TABLE_USE" => Ok(Sound::BlockEnchantmentTableUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ENDER_CHEST_CLOSE" => Ok(Sound::BlockEnderChestClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ENDER_CHEST_OPEN" => Ok(Sound::BlockEnderChestOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_END_GATEWAY_SPAWN" => Ok(Sound::BlockEndGatewaySpawn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_END_PORTAL_FRAME_FILL" => Ok(Sound::BlockEndPortalFrameFill { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_END_PORTAL_SPAWN" => Ok(Sound::BlockEndPortalSpawn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FENCE_GATE_CLOSE" => Ok(Sound::BlockFenceGateClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FENCE_GATE_OPEN" => Ok(Sound::BlockFenceGateOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FIRE_AMBIENT" => Ok(Sound::BlockFireAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FIRE_EXTINGUISH" => Ok(Sound::BlockFireExtinguish { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FLOWERING_AZALEA_BREAK" => Ok(Sound::BlockFloweringAzaleaBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FLOWERING_AZALEA_FALL" => Ok(Sound::BlockFloweringAzaleaFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FLOWERING_AZALEA_HIT" => Ok(Sound::BlockFloweringAzaleaHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FLOWERING_AZALEA_PLACE" => Ok(Sound::BlockFloweringAzaleaPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FLOWERING_AZALEA_STEP" => Ok(Sound::BlockFloweringAzaleaStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FROGLIGHT_BREAK" => Ok(Sound::BlockFroglightBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FROGLIGHT_FALL" => Ok(Sound::BlockFroglightFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FROGLIGHT_HIT" => Ok(Sound::BlockFroglightHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FROGLIGHT_PLACE" => Ok(Sound::BlockFroglightPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FROGLIGHT_STEP" => Ok(Sound::BlockFroglightStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FROGSPAWN_BREAK" => Ok(Sound::BlockFrogspawnBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FROGSPAWN_FALL" => Ok(Sound::BlockFrogspawnFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FROGSPAWN_HATCH" => Ok(Sound::BlockFrogspawnHatch { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FROGSPAWN_HIT" => Ok(Sound::BlockFrogspawnHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FROGSPAWN_PLACE" => Ok(Sound::BlockFrogspawnPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FROGSPAWN_STEP" => Ok(Sound::BlockFrogspawnStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FUNGUS_BREAK" => Ok(Sound::BlockFungusBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FUNGUS_FALL" => Ok(Sound::BlockFungusFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FUNGUS_HIT" => Ok(Sound::BlockFungusHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FUNGUS_PLACE" => Ok(Sound::BlockFungusPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FUNGUS_STEP" => Ok(Sound::BlockFungusStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_FURNACE_FIRE_CRACKLE" => Ok(Sound::BlockFurnaceFireCrackle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GILDED_BLACKSTONE_BREAK" => Ok(Sound::BlockGildedBlackstoneBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GILDED_BLACKSTONE_FALL" => Ok(Sound::BlockGildedBlackstoneFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GILDED_BLACKSTONE_HIT" => Ok(Sound::BlockGildedBlackstoneHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GILDED_BLACKSTONE_PLACE" => Ok(Sound::BlockGildedBlackstonePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GILDED_BLACKSTONE_STEP" => Ok(Sound::BlockGildedBlackstoneStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GLASS_BREAK" => Ok(Sound::BlockGlassBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GLASS_FALL" => Ok(Sound::BlockGlassFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GLASS_HIT" => Ok(Sound::BlockGlassHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GLASS_PLACE" => Ok(Sound::BlockGlassPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GLASS_STEP" => Ok(Sound::BlockGlassStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GRASS_BREAK" => Ok(Sound::BlockGrassBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GRASS_FALL" => Ok(Sound::BlockGrassFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GRASS_HIT" => Ok(Sound::BlockGrassHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GRASS_PLACE" => Ok(Sound::BlockGrassPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GRASS_STEP" => Ok(Sound::BlockGrassStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GRAVEL_BREAK" => Ok(Sound::BlockGravelBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GRAVEL_FALL" => Ok(Sound::BlockGravelFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GRAVEL_HIT" => Ok(Sound::BlockGravelHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GRAVEL_PLACE" => Ok(Sound::BlockGravelPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GRAVEL_STEP" => Ok(Sound::BlockGravelStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GRINDSTONE_USE" => Ok(Sound::BlockGrindstoneUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_GROWING_PLANT_CROP" => Ok(Sound::BlockGrowingPlantCrop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HANGING_ROOTS_BREAK" => Ok(Sound::BlockHangingRootsBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HANGING_ROOTS_FALL" => Ok(Sound::BlockHangingRootsFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HANGING_ROOTS_HIT" => Ok(Sound::BlockHangingRootsHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HANGING_ROOTS_PLACE" => Ok(Sound::BlockHangingRootsPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HANGING_ROOTS_STEP" => Ok(Sound::BlockHangingRootsStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HANGING_SIGN_BREAK" => Ok(Sound::BlockHangingSignBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HANGING_SIGN_FALL" => Ok(Sound::BlockHangingSignFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HANGING_SIGN_HIT" => Ok(Sound::BlockHangingSignHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HANGING_SIGN_PLACE" => Ok(Sound::BlockHangingSignPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HANGING_SIGN_STEP" => Ok(Sound::BlockHangingSignStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HANGING_SIGN_WAXED_INTERACT_FAIL" => { + Ok(Sound::BlockHangingSignWaxedInteractFail { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_HEAVY_CORE_BREAK" => Ok(Sound::BlockHeavyCoreBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HEAVY_CORE_FALL" => Ok(Sound::BlockHeavyCoreFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HEAVY_CORE_HIT" => Ok(Sound::BlockHeavyCoreHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HEAVY_CORE_PLACE" => Ok(Sound::BlockHeavyCorePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HEAVY_CORE_STEP" => Ok(Sound::BlockHeavyCoreStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HONEY_BLOCK_BREAK" => Ok(Sound::BlockHoneyBlockBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HONEY_BLOCK_FALL" => Ok(Sound::BlockHoneyBlockFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HONEY_BLOCK_HIT" => Ok(Sound::BlockHoneyBlockHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HONEY_BLOCK_PLACE" => Ok(Sound::BlockHoneyBlockPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HONEY_BLOCK_SLIDE" => Ok(Sound::BlockHoneyBlockSlide { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_HONEY_BLOCK_STEP" => Ok(Sound::BlockHoneyBlockStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_IRON_DOOR_CLOSE" => Ok(Sound::BlockIronDoorClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_IRON_DOOR_OPEN" => Ok(Sound::BlockIronDoorOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_IRON_TRAPDOOR_CLOSE" => Ok(Sound::BlockIronTrapdoorClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_IRON_TRAPDOOR_OPEN" => Ok(Sound::BlockIronTrapdoorOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LADDER_BREAK" => Ok(Sound::BlockLadderBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LADDER_FALL" => Ok(Sound::BlockLadderFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LADDER_HIT" => Ok(Sound::BlockLadderHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LADDER_PLACE" => Ok(Sound::BlockLadderPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LADDER_STEP" => Ok(Sound::BlockLadderStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LANTERN_BREAK" => Ok(Sound::BlockLanternBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LANTERN_FALL" => Ok(Sound::BlockLanternFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LANTERN_HIT" => Ok(Sound::BlockLanternHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LANTERN_PLACE" => Ok(Sound::BlockLanternPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LANTERN_STEP" => Ok(Sound::BlockLanternStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LARGE_AMETHYST_BUD_BREAK" => Ok(Sound::BlockLargeAmethystBudBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LARGE_AMETHYST_BUD_PLACE" => Ok(Sound::BlockLargeAmethystBudPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LAVA_AMBIENT" => Ok(Sound::BlockLavaAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LAVA_EXTINGUISH" => Ok(Sound::BlockLavaExtinguish { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LAVA_POP" => Ok(Sound::BlockLavaPop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LEVER_CLICK" => Ok(Sound::BlockLeverClick { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LILY_PAD_PLACE" => Ok(Sound::BlockLilyPadPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LODESTONE_BREAK" => Ok(Sound::BlockLodestoneBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LODESTONE_FALL" => Ok(Sound::BlockLodestoneFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LODESTONE_HIT" => Ok(Sound::BlockLodestoneHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LODESTONE_PLACE" => Ok(Sound::BlockLodestonePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_LODESTONE_STEP" => Ok(Sound::BlockLodestoneStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MANGROVE_ROOTS_BREAK" => Ok(Sound::BlockMangroveRootsBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MANGROVE_ROOTS_FALL" => Ok(Sound::BlockMangroveRootsFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MANGROVE_ROOTS_HIT" => Ok(Sound::BlockMangroveRootsHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MANGROVE_ROOTS_PLACE" => Ok(Sound::BlockMangroveRootsPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MANGROVE_ROOTS_STEP" => Ok(Sound::BlockMangroveRootsStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MEDIUM_AMETHYST_BUD_BREAK" => Ok(Sound::BlockMediumAmethystBudBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MEDIUM_AMETHYST_BUD_PLACE" => Ok(Sound::BlockMediumAmethystBudPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_METAL_BREAK" => Ok(Sound::BlockMetalBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_METAL_FALL" => Ok(Sound::BlockMetalFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_METAL_HIT" => Ok(Sound::BlockMetalHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_METAL_PLACE" => Ok(Sound::BlockMetalPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_METAL_PRESSURE_PLATE_CLICK_OFF" => { + Ok(Sound::BlockMetalPressurePlateClickOff { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_METAL_PRESSURE_PLATE_CLICK_ON" => { + Ok(Sound::BlockMetalPressurePlateClickOn { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_METAL_STEP" => Ok(Sound::BlockMetalStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MOSS_BREAK" => Ok(Sound::BlockMossBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MOSS_CARPET_BREAK" => Ok(Sound::BlockMossCarpetBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MOSS_CARPET_FALL" => Ok(Sound::BlockMossCarpetFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MOSS_CARPET_HIT" => Ok(Sound::BlockMossCarpetHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MOSS_CARPET_PLACE" => Ok(Sound::BlockMossCarpetPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MOSS_CARPET_STEP" => Ok(Sound::BlockMossCarpetStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MOSS_FALL" => Ok(Sound::BlockMossFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MOSS_HIT" => Ok(Sound::BlockMossHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MOSS_PLACE" => Ok(Sound::BlockMossPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MOSS_STEP" => Ok(Sound::BlockMossStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUDDY_MANGROVE_ROOTS_BREAK" => Ok(Sound::BlockMuddyMangroveRootsBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUDDY_MANGROVE_ROOTS_FALL" => Ok(Sound::BlockMuddyMangroveRootsFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUDDY_MANGROVE_ROOTS_HIT" => Ok(Sound::BlockMuddyMangroveRootsHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUDDY_MANGROVE_ROOTS_PLACE" => Ok(Sound::BlockMuddyMangroveRootsPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUDDY_MANGROVE_ROOTS_STEP" => Ok(Sound::BlockMuddyMangroveRootsStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUD_BREAK" => Ok(Sound::BlockMudBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUD_BRICKS_BREAK" => Ok(Sound::BlockMudBricksBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUD_BRICKS_FALL" => Ok(Sound::BlockMudBricksFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUD_BRICKS_HIT" => Ok(Sound::BlockMudBricksHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUD_BRICKS_PLACE" => Ok(Sound::BlockMudBricksPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUD_BRICKS_STEP" => Ok(Sound::BlockMudBricksStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUD_FALL" => Ok(Sound::BlockMudFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUD_HIT" => Ok(Sound::BlockMudHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUD_PLACE" => Ok(Sound::BlockMudPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_MUD_STEP" => Ok(Sound::BlockMudStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHERITE_BLOCK_BREAK" => Ok(Sound::BlockNetheriteBlockBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHERITE_BLOCK_FALL" => Ok(Sound::BlockNetheriteBlockFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHERITE_BLOCK_HIT" => Ok(Sound::BlockNetheriteBlockHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHERITE_BLOCK_PLACE" => Ok(Sound::BlockNetheriteBlockPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHERITE_BLOCK_STEP" => Ok(Sound::BlockNetheriteBlockStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHERRACK_BREAK" => Ok(Sound::BlockNetherrackBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHERRACK_FALL" => Ok(Sound::BlockNetherrackFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHERRACK_HIT" => Ok(Sound::BlockNetherrackHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHERRACK_PLACE" => Ok(Sound::BlockNetherrackPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHERRACK_STEP" => Ok(Sound::BlockNetherrackStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_BRICKS_BREAK" => Ok(Sound::BlockNetherBricksBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_BRICKS_FALL" => Ok(Sound::BlockNetherBricksFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_BRICKS_HIT" => Ok(Sound::BlockNetherBricksHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_BRICKS_PLACE" => Ok(Sound::BlockNetherBricksPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_BRICKS_STEP" => Ok(Sound::BlockNetherBricksStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_GOLD_ORE_BREAK" => Ok(Sound::BlockNetherGoldOreBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_GOLD_ORE_FALL" => Ok(Sound::BlockNetherGoldOreFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_GOLD_ORE_HIT" => Ok(Sound::BlockNetherGoldOreHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_GOLD_ORE_PLACE" => Ok(Sound::BlockNetherGoldOrePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_GOLD_ORE_STEP" => Ok(Sound::BlockNetherGoldOreStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_ORE_BREAK" => Ok(Sound::BlockNetherOreBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_ORE_FALL" => Ok(Sound::BlockNetherOreFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_ORE_HIT" => Ok(Sound::BlockNetherOreHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_ORE_PLACE" => Ok(Sound::BlockNetherOrePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_ORE_STEP" => Ok(Sound::BlockNetherOreStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_SPROUTS_BREAK" => Ok(Sound::BlockNetherSproutsBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_SPROUTS_FALL" => Ok(Sound::BlockNetherSproutsFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_SPROUTS_HIT" => Ok(Sound::BlockNetherSproutsHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_SPROUTS_PLACE" => Ok(Sound::BlockNetherSproutsPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_SPROUTS_STEP" => Ok(Sound::BlockNetherSproutsStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WART_BREAK" => Ok(Sound::BlockNetherWartBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_BREAK" => Ok(Sound::BlockNetherWoodBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_BUTTON_CLICK_OFF" => Ok(Sound::BlockNetherWoodButtonClickOff { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_BUTTON_CLICK_ON" => Ok(Sound::BlockNetherWoodButtonClickOn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_DOOR_CLOSE" => Ok(Sound::BlockNetherWoodDoorClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_DOOR_OPEN" => Ok(Sound::BlockNetherWoodDoorOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_FALL" => Ok(Sound::BlockNetherWoodFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_FENCE_GATE_CLOSE" => Ok(Sound::BlockNetherWoodFenceGateClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_FENCE_GATE_OPEN" => Ok(Sound::BlockNetherWoodFenceGateOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_HANGING_SIGN_BREAK" => { + Ok(Sound::BlockNetherWoodHangingSignBreak { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_NETHER_WOOD_HANGING_SIGN_FALL" => { + Ok(Sound::BlockNetherWoodHangingSignFall { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_NETHER_WOOD_HANGING_SIGN_HIT" => Ok(Sound::BlockNetherWoodHangingSignHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_HANGING_SIGN_PLACE" => { + Ok(Sound::BlockNetherWoodHangingSignPlace { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_NETHER_WOOD_HANGING_SIGN_STEP" => { + Ok(Sound::BlockNetherWoodHangingSignStep { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_NETHER_WOOD_HIT" => Ok(Sound::BlockNetherWoodHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_PLACE" => Ok(Sound::BlockNetherWoodPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_PRESSURE_PLATE_CLICK_OFF" => { + Ok(Sound::BlockNetherWoodPressurePlateClickOff { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_NETHER_WOOD_PRESSURE_PLATE_CLICK_ON" => { + Ok(Sound::BlockNetherWoodPressurePlateClickOn { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_NETHER_WOOD_STEP" => Ok(Sound::BlockNetherWoodStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_TRAPDOOR_CLOSE" => Ok(Sound::BlockNetherWoodTrapdoorClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NETHER_WOOD_TRAPDOOR_OPEN" => Ok(Sound::BlockNetherWoodTrapdoorOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_BANJO" => Ok(Sound::BlockNoteBlockBanjo { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_BASEDRUM" => Ok(Sound::BlockNoteBlockBasedrum { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_BASS" => Ok(Sound::BlockNoteBlockBass { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_BELL" => Ok(Sound::BlockNoteBlockBell { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_BIT" => Ok(Sound::BlockNoteBlockBit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_CHIME" => Ok(Sound::BlockNoteBlockChime { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_COW_BELL" => Ok(Sound::BlockNoteBlockCowBell { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_DIDGERIDOO" => Ok(Sound::BlockNoteBlockDidgeridoo { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_FLUTE" => Ok(Sound::BlockNoteBlockFlute { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_GUITAR" => Ok(Sound::BlockNoteBlockGuitar { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_HARP" => Ok(Sound::BlockNoteBlockHarp { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_HAT" => Ok(Sound::BlockNoteBlockHat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_IMITATE_CREEPER" => Ok(Sound::BlockNoteBlockImitateCreeper { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_IMITATE_ENDER_DRAGON" => { + Ok(Sound::BlockNoteBlockImitateEnderDragon { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_NOTE_BLOCK_IMITATE_PIGLIN" => Ok(Sound::BlockNoteBlockImitatePiglin { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_IMITATE_SKELETON" => Ok(Sound::BlockNoteBlockImitateSkeleton { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_IMITATE_WITHER_SKELETON" => { + Ok(Sound::BlockNoteBlockImitateWitherSkeleton { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_NOTE_BLOCK_IMITATE_ZOMBIE" => Ok(Sound::BlockNoteBlockImitateZombie { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_IRON_XYLOPHONE" => Ok(Sound::BlockNoteBlockIronXylophone { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_PLING" => Ok(Sound::BlockNoteBlockPling { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_SNARE" => Ok(Sound::BlockNoteBlockSnare { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NOTE_BLOCK_XYLOPHONE" => Ok(Sound::BlockNoteBlockXylophone { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NYLIUM_BREAK" => Ok(Sound::BlockNyliumBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NYLIUM_FALL" => Ok(Sound::BlockNyliumFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NYLIUM_HIT" => Ok(Sound::BlockNyliumHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NYLIUM_PLACE" => Ok(Sound::BlockNyliumPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_NYLIUM_STEP" => Ok(Sound::BlockNyliumStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PACKED_MUD_BREAK" => Ok(Sound::BlockPackedMudBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PACKED_MUD_FALL" => Ok(Sound::BlockPackedMudFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PACKED_MUD_HIT" => Ok(Sound::BlockPackedMudHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PACKED_MUD_PLACE" => Ok(Sound::BlockPackedMudPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PACKED_MUD_STEP" => Ok(Sound::BlockPackedMudStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PINK_PETALS_BREAK" => Ok(Sound::BlockPinkPetalsBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PINK_PETALS_FALL" => Ok(Sound::BlockPinkPetalsFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PINK_PETALS_HIT" => Ok(Sound::BlockPinkPetalsHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PINK_PETALS_PLACE" => Ok(Sound::BlockPinkPetalsPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PINK_PETALS_STEP" => Ok(Sound::BlockPinkPetalsStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PISTON_CONTRACT" => Ok(Sound::BlockPistonContract { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PISTON_EXTEND" => Ok(Sound::BlockPistonExtend { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POINTED_DRIPSTONE_BREAK" => Ok(Sound::BlockPointedDripstoneBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POINTED_DRIPSTONE_DRIP_LAVA" => Ok(Sound::BlockPointedDripstoneDripLava { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POINTED_DRIPSTONE_DRIP_LAVA_INTO_CAULDRON" => { + Ok(Sound::BlockPointedDripstoneDripLavaIntoCauldron { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_POINTED_DRIPSTONE_DRIP_WATER" => Ok(Sound::BlockPointedDripstoneDripWater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POINTED_DRIPSTONE_DRIP_WATER_INTO_CAULDRON" => { + Ok(Sound::BlockPointedDripstoneDripWaterIntoCauldron { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_POINTED_DRIPSTONE_FALL" => Ok(Sound::BlockPointedDripstoneFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POINTED_DRIPSTONE_HIT" => Ok(Sound::BlockPointedDripstoneHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POINTED_DRIPSTONE_LAND" => Ok(Sound::BlockPointedDripstoneLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POINTED_DRIPSTONE_PLACE" => Ok(Sound::BlockPointedDripstonePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POINTED_DRIPSTONE_STEP" => Ok(Sound::BlockPointedDripstoneStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POLISHED_DEEPSLATE_BREAK" => Ok(Sound::BlockPolishedDeepslateBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POLISHED_DEEPSLATE_FALL" => Ok(Sound::BlockPolishedDeepslateFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POLISHED_DEEPSLATE_HIT" => Ok(Sound::BlockPolishedDeepslateHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POLISHED_DEEPSLATE_PLACE" => Ok(Sound::BlockPolishedDeepslatePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POLISHED_DEEPSLATE_STEP" => Ok(Sound::BlockPolishedDeepslateStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POLISHED_TUFF_BREAK" => Ok(Sound::BlockPolishedTuffBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POLISHED_TUFF_FALL" => Ok(Sound::BlockPolishedTuffFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POLISHED_TUFF_HIT" => Ok(Sound::BlockPolishedTuffHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POLISHED_TUFF_PLACE" => Ok(Sound::BlockPolishedTuffPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POLISHED_TUFF_STEP" => Ok(Sound::BlockPolishedTuffStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PORTAL_AMBIENT" => Ok(Sound::BlockPortalAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PORTAL_TRAVEL" => Ok(Sound::BlockPortalTravel { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PORTAL_TRIGGER" => Ok(Sound::BlockPortalTrigger { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POWDER_SNOW_BREAK" => Ok(Sound::BlockPowderSnowBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POWDER_SNOW_FALL" => Ok(Sound::BlockPowderSnowFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POWDER_SNOW_HIT" => Ok(Sound::BlockPowderSnowHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POWDER_SNOW_PLACE" => Ok(Sound::BlockPowderSnowPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_POWDER_SNOW_STEP" => Ok(Sound::BlockPowderSnowStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_PUMPKIN_CARVE" => Ok(Sound::BlockPumpkinCarve { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_REDSTONE_TORCH_BURNOUT" => Ok(Sound::BlockRedstoneTorchBurnout { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_RESPAWN_ANCHOR_AMBIENT" => Ok(Sound::BlockRespawnAnchorAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_RESPAWN_ANCHOR_CHARGE" => Ok(Sound::BlockRespawnAnchorCharge { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_RESPAWN_ANCHOR_DEPLETE" => Ok(Sound::BlockRespawnAnchorDeplete { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_RESPAWN_ANCHOR_SET_SPAWN" => Ok(Sound::BlockRespawnAnchorSetSpawn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ROOTED_DIRT_BREAK" => Ok(Sound::BlockRootedDirtBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ROOTED_DIRT_FALL" => Ok(Sound::BlockRootedDirtFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ROOTED_DIRT_HIT" => Ok(Sound::BlockRootedDirtHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ROOTED_DIRT_PLACE" => Ok(Sound::BlockRootedDirtPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ROOTED_DIRT_STEP" => Ok(Sound::BlockRootedDirtStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ROOTS_BREAK" => Ok(Sound::BlockRootsBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ROOTS_FALL" => Ok(Sound::BlockRootsFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ROOTS_HIT" => Ok(Sound::BlockRootsHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ROOTS_PLACE" => Ok(Sound::BlockRootsPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_ROOTS_STEP" => Ok(Sound::BlockRootsStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SAND_BREAK" => Ok(Sound::BlockSandBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SAND_FALL" => Ok(Sound::BlockSandFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SAND_HIT" => Ok(Sound::BlockSandHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SAND_PLACE" => Ok(Sound::BlockSandPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SAND_STEP" => Ok(Sound::BlockSandStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCAFFOLDING_BREAK" => Ok(Sound::BlockScaffoldingBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCAFFOLDING_FALL" => Ok(Sound::BlockScaffoldingFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCAFFOLDING_HIT" => Ok(Sound::BlockScaffoldingHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCAFFOLDING_PLACE" => Ok(Sound::BlockScaffoldingPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCAFFOLDING_STEP" => Ok(Sound::BlockScaffoldingStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_BREAK" => Ok(Sound::BlockSculkBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_CATALYST_BLOOM" => Ok(Sound::BlockSculkCatalystBloom { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_CATALYST_BREAK" => Ok(Sound::BlockSculkCatalystBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_CATALYST_FALL" => Ok(Sound::BlockSculkCatalystFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_CATALYST_HIT" => Ok(Sound::BlockSculkCatalystHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_CATALYST_PLACE" => Ok(Sound::BlockSculkCatalystPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_CATALYST_STEP" => Ok(Sound::BlockSculkCatalystStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_CHARGE" => Ok(Sound::BlockSculkCharge { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_FALL" => Ok(Sound::BlockSculkFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_HIT" => Ok(Sound::BlockSculkHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_PLACE" => Ok(Sound::BlockSculkPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SENSOR_BREAK" => Ok(Sound::BlockSculkSensorBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SENSOR_CLICKING" => Ok(Sound::BlockSculkSensorClicking { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SENSOR_CLICKING_STOP" => Ok(Sound::BlockSculkSensorClickingStop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SENSOR_FALL" => Ok(Sound::BlockSculkSensorFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SENSOR_HIT" => Ok(Sound::BlockSculkSensorHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SENSOR_PLACE" => Ok(Sound::BlockSculkSensorPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SENSOR_STEP" => Ok(Sound::BlockSculkSensorStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SHRIEKER_BREAK" => Ok(Sound::BlockSculkShriekerBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SHRIEKER_FALL" => Ok(Sound::BlockSculkShriekerFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SHRIEKER_HIT" => Ok(Sound::BlockSculkShriekerHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SHRIEKER_PLACE" => Ok(Sound::BlockSculkShriekerPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SHRIEKER_SHRIEK" => Ok(Sound::BlockSculkShriekerShriek { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SHRIEKER_STEP" => Ok(Sound::BlockSculkShriekerStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_SPREAD" => Ok(Sound::BlockSculkSpread { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_STEP" => Ok(Sound::BlockSculkStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_VEIN_BREAK" => Ok(Sound::BlockSculkVeinBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_VEIN_FALL" => Ok(Sound::BlockSculkVeinFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_VEIN_HIT" => Ok(Sound::BlockSculkVeinHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_VEIN_PLACE" => Ok(Sound::BlockSculkVeinPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SCULK_VEIN_STEP" => Ok(Sound::BlockSculkVeinStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SHROOMLIGHT_BREAK" => Ok(Sound::BlockShroomlightBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SHROOMLIGHT_FALL" => Ok(Sound::BlockShroomlightFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SHROOMLIGHT_HIT" => Ok(Sound::BlockShroomlightHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SHROOMLIGHT_PLACE" => Ok(Sound::BlockShroomlightPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SHROOMLIGHT_STEP" => Ok(Sound::BlockShroomlightStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SHULKER_BOX_CLOSE" => Ok(Sound::BlockShulkerBoxClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SHULKER_BOX_OPEN" => Ok(Sound::BlockShulkerBoxOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SIGN_WAXED_INTERACT_FAIL" => Ok(Sound::BlockSignWaxedInteractFail { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SLIME_BLOCK_BREAK" => Ok(Sound::BlockSlimeBlockBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SLIME_BLOCK_FALL" => Ok(Sound::BlockSlimeBlockFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SLIME_BLOCK_HIT" => Ok(Sound::BlockSlimeBlockHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SLIME_BLOCK_PLACE" => Ok(Sound::BlockSlimeBlockPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SLIME_BLOCK_STEP" => Ok(Sound::BlockSlimeBlockStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SMALL_AMETHYST_BUD_BREAK" => Ok(Sound::BlockSmallAmethystBudBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SMALL_AMETHYST_BUD_PLACE" => Ok(Sound::BlockSmallAmethystBudPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SMALL_DRIPLEAF_BREAK" => Ok(Sound::BlockSmallDripleafBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SMALL_DRIPLEAF_FALL" => Ok(Sound::BlockSmallDripleafFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SMALL_DRIPLEAF_HIT" => Ok(Sound::BlockSmallDripleafHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SMALL_DRIPLEAF_PLACE" => Ok(Sound::BlockSmallDripleafPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SMALL_DRIPLEAF_STEP" => Ok(Sound::BlockSmallDripleafStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SMITHING_TABLE_USE" => Ok(Sound::BlockSmithingTableUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SMOKER_SMOKE" => Ok(Sound::BlockSmokerSmoke { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SNIFFER_EGG_CRACK" => Ok(Sound::BlockSnifferEggCrack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SNIFFER_EGG_HATCH" => Ok(Sound::BlockSnifferEggHatch { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SNIFFER_EGG_PLOP" => Ok(Sound::BlockSnifferEggPlop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SNOW_BREAK" => Ok(Sound::BlockSnowBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SNOW_FALL" => Ok(Sound::BlockSnowFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SNOW_HIT" => Ok(Sound::BlockSnowHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SNOW_PLACE" => Ok(Sound::BlockSnowPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SNOW_STEP" => Ok(Sound::BlockSnowStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SOUL_SAND_BREAK" => Ok(Sound::BlockSoulSandBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SOUL_SAND_FALL" => Ok(Sound::BlockSoulSandFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SOUL_SAND_HIT" => Ok(Sound::BlockSoulSandHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SOUL_SAND_PLACE" => Ok(Sound::BlockSoulSandPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SOUL_SAND_STEP" => Ok(Sound::BlockSoulSandStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SOUL_SOIL_BREAK" => Ok(Sound::BlockSoulSoilBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SOUL_SOIL_FALL" => Ok(Sound::BlockSoulSoilFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SOUL_SOIL_HIT" => Ok(Sound::BlockSoulSoilHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SOUL_SOIL_PLACE" => Ok(Sound::BlockSoulSoilPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SOUL_SOIL_STEP" => Ok(Sound::BlockSoulSoilStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SPONGE_ABSORB" => Ok(Sound::BlockSpongeAbsorb { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SPONGE_BREAK" => Ok(Sound::BlockSpongeBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SPONGE_FALL" => Ok(Sound::BlockSpongeFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SPONGE_HIT" => Ok(Sound::BlockSpongeHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SPONGE_PLACE" => Ok(Sound::BlockSpongePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SPONGE_STEP" => Ok(Sound::BlockSpongeStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SPORE_BLOSSOM_BREAK" => Ok(Sound::BlockSporeBlossomBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SPORE_BLOSSOM_FALL" => Ok(Sound::BlockSporeBlossomFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SPORE_BLOSSOM_HIT" => Ok(Sound::BlockSporeBlossomHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SPORE_BLOSSOM_PLACE" => Ok(Sound::BlockSporeBlossomPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SPORE_BLOSSOM_STEP" => Ok(Sound::BlockSporeBlossomStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STEM_BREAK" => Ok(Sound::BlockStemBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STEM_FALL" => Ok(Sound::BlockStemFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STEM_HIT" => Ok(Sound::BlockStemHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STEM_PLACE" => Ok(Sound::BlockStemPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STEM_STEP" => Ok(Sound::BlockStemStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STONE_BREAK" => Ok(Sound::BlockStoneBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STONE_BUTTON_CLICK_OFF" => Ok(Sound::BlockStoneButtonClickOff { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STONE_BUTTON_CLICK_ON" => Ok(Sound::BlockStoneButtonClickOn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STONE_FALL" => Ok(Sound::BlockStoneFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STONE_HIT" => Ok(Sound::BlockStoneHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STONE_PLACE" => Ok(Sound::BlockStonePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_STONE_PRESSURE_PLATE_CLICK_OFF" => { + Ok(Sound::BlockStonePressurePlateClickOff { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_STONE_PRESSURE_PLATE_CLICK_ON" => { + Ok(Sound::BlockStonePressurePlateClickOn { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_STONE_STEP" => Ok(Sound::BlockStoneStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SUSPICIOUS_GRAVEL_BREAK" => Ok(Sound::BlockSuspiciousGravelBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SUSPICIOUS_GRAVEL_FALL" => Ok(Sound::BlockSuspiciousGravelFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SUSPICIOUS_GRAVEL_HIT" => Ok(Sound::BlockSuspiciousGravelHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SUSPICIOUS_GRAVEL_PLACE" => Ok(Sound::BlockSuspiciousGravelPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SUSPICIOUS_GRAVEL_STEP" => Ok(Sound::BlockSuspiciousGravelStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SUSPICIOUS_SAND_BREAK" => Ok(Sound::BlockSuspiciousSandBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SUSPICIOUS_SAND_FALL" => Ok(Sound::BlockSuspiciousSandFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SUSPICIOUS_SAND_HIT" => Ok(Sound::BlockSuspiciousSandHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SUSPICIOUS_SAND_PLACE" => Ok(Sound::BlockSuspiciousSandPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SUSPICIOUS_SAND_STEP" => Ok(Sound::BlockSuspiciousSandStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SWEET_BERRY_BUSH_BREAK" => Ok(Sound::BlockSweetBerryBushBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_SWEET_BERRY_BUSH_PICK_BERRIES" => { + Ok(Sound::BlockSweetBerryBushPickBerries { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_SWEET_BERRY_BUSH_PLACE" => Ok(Sound::BlockSweetBerryBushPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_ABOUT_TO_SPAWN_ITEM" => { + Ok(Sound::BlockTrialSpawnerAboutToSpawnItem { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_TRIAL_SPAWNER_AMBIENT" => Ok(Sound::BlockTrialSpawnerAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_AMBIENT_OMINOUS" => { + Ok(Sound::BlockTrialSpawnerAmbientOminous { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_TRIAL_SPAWNER_BREAK" => Ok(Sound::BlockTrialSpawnerBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_CLOSE_SHUTTER" => Ok(Sound::BlockTrialSpawnerCloseShutter { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_DETECT_PLAYER" => Ok(Sound::BlockTrialSpawnerDetectPlayer { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_EJECT_ITEM" => Ok(Sound::BlockTrialSpawnerEjectItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_FALL" => Ok(Sound::BlockTrialSpawnerFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_HIT" => Ok(Sound::BlockTrialSpawnerHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_OMINOUS_ACTIVATE" => { + Ok(Sound::BlockTrialSpawnerOminousActivate { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_TRIAL_SPAWNER_OPEN_SHUTTER" => Ok(Sound::BlockTrialSpawnerOpenShutter { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_PLACE" => Ok(Sound::BlockTrialSpawnerPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_SPAWN_ITEM" => Ok(Sound::BlockTrialSpawnerSpawnItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_SPAWN_ITEM_BEGIN" => { + Ok(Sound::BlockTrialSpawnerSpawnItemBegin { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_TRIAL_SPAWNER_SPAWN_MOB" => Ok(Sound::BlockTrialSpawnerSpawnMob { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIAL_SPAWNER_STEP" => Ok(Sound::BlockTrialSpawnerStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIPWIRE_ATTACH" => Ok(Sound::BlockTripwireAttach { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIPWIRE_CLICK_OFF" => Ok(Sound::BlockTripwireClickOff { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIPWIRE_CLICK_ON" => Ok(Sound::BlockTripwireClickOn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TRIPWIRE_DETACH" => Ok(Sound::BlockTripwireDetach { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TUFF_BREAK" => Ok(Sound::BlockTuffBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TUFF_BRICKS_BREAK" => Ok(Sound::BlockTuffBricksBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TUFF_BRICKS_FALL" => Ok(Sound::BlockTuffBricksFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TUFF_BRICKS_HIT" => Ok(Sound::BlockTuffBricksHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TUFF_BRICKS_PLACE" => Ok(Sound::BlockTuffBricksPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TUFF_BRICKS_STEP" => Ok(Sound::BlockTuffBricksStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TUFF_FALL" => Ok(Sound::BlockTuffFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TUFF_HIT" => Ok(Sound::BlockTuffHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TUFF_PLACE" => Ok(Sound::BlockTuffPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_TUFF_STEP" => Ok(Sound::BlockTuffStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_ACTIVATE" => Ok(Sound::BlockVaultActivate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_AMBIENT" => Ok(Sound::BlockVaultAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_BREAK" => Ok(Sound::BlockVaultBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_CLOSE_SHUTTER" => Ok(Sound::BlockVaultCloseShutter { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_DEACTIVATE" => Ok(Sound::BlockVaultDeactivate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_EJECT_ITEM" => Ok(Sound::BlockVaultEjectItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_FALL" => Ok(Sound::BlockVaultFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_HIT" => Ok(Sound::BlockVaultHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_INSERT_ITEM" => Ok(Sound::BlockVaultInsertItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_INSERT_ITEM_FAIL" => Ok(Sound::BlockVaultInsertItemFail { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_OPEN_SHUTTER" => Ok(Sound::BlockVaultOpenShutter { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_PLACE" => Ok(Sound::BlockVaultPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_REJECT_REWARDED_PLAYER" => Ok(Sound::BlockVaultRejectRewardedPlayer { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VAULT_STEP" => Ok(Sound::BlockVaultStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VINE_BREAK" => Ok(Sound::BlockVineBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VINE_FALL" => Ok(Sound::BlockVineFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VINE_HIT" => Ok(Sound::BlockVineHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VINE_PLACE" => Ok(Sound::BlockVinePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_VINE_STEP" => Ok(Sound::BlockVineStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WART_BLOCK_BREAK" => Ok(Sound::BlockWartBlockBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WART_BLOCK_FALL" => Ok(Sound::BlockWartBlockFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WART_BLOCK_HIT" => Ok(Sound::BlockWartBlockHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WART_BLOCK_PLACE" => Ok(Sound::BlockWartBlockPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WART_BLOCK_STEP" => Ok(Sound::BlockWartBlockStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WATER_AMBIENT" => Ok(Sound::BlockWaterAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WEEPING_VINES_BREAK" => Ok(Sound::BlockWeepingVinesBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WEEPING_VINES_FALL" => Ok(Sound::BlockWeepingVinesFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WEEPING_VINES_HIT" => Ok(Sound::BlockWeepingVinesHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WEEPING_VINES_PLACE" => Ok(Sound::BlockWeepingVinesPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WEEPING_VINES_STEP" => Ok(Sound::BlockWeepingVinesStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WET_GRASS_BREAK" => Ok(Sound::BlockWetGrassBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WET_GRASS_FALL" => Ok(Sound::BlockWetGrassFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WET_GRASS_HIT" => Ok(Sound::BlockWetGrassHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WET_GRASS_PLACE" => Ok(Sound::BlockWetGrassPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WET_GRASS_STEP" => Ok(Sound::BlockWetGrassStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WET_SPONGE_BREAK" => Ok(Sound::BlockWetSpongeBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WET_SPONGE_DRIES" => Ok(Sound::BlockWetSpongeDries { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WET_SPONGE_FALL" => Ok(Sound::BlockWetSpongeFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WET_SPONGE_HIT" => Ok(Sound::BlockWetSpongeHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WET_SPONGE_PLACE" => Ok(Sound::BlockWetSpongePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WET_SPONGE_STEP" => Ok(Sound::BlockWetSpongeStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOODEN_BUTTON_CLICK_OFF" => Ok(Sound::BlockWoodenButtonClickOff { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOODEN_BUTTON_CLICK_ON" => Ok(Sound::BlockWoodenButtonClickOn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOODEN_DOOR_CLOSE" => Ok(Sound::BlockWoodenDoorClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOODEN_DOOR_OPEN" => Ok(Sound::BlockWoodenDoorOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOODEN_PRESSURE_PLATE_CLICK_OFF" => { + Ok(Sound::BlockWoodenPressurePlateClickOff { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_WOODEN_PRESSURE_PLATE_CLICK_ON" => { + Ok(Sound::BlockWoodenPressurePlateClickOn { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "BLOCK_WOODEN_TRAPDOOR_CLOSE" => Ok(Sound::BlockWoodenTrapdoorClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOODEN_TRAPDOOR_OPEN" => Ok(Sound::BlockWoodenTrapdoorOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOOD_BREAK" => Ok(Sound::BlockWoodBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOOD_FALL" => Ok(Sound::BlockWoodFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOOD_HIT" => Ok(Sound::BlockWoodHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOOD_PLACE" => Ok(Sound::BlockWoodPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOOD_STEP" => Ok(Sound::BlockWoodStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOOL_BREAK" => Ok(Sound::BlockWoolBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOOL_FALL" => Ok(Sound::BlockWoolFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOOL_HIT" => Ok(Sound::BlockWoolHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOOL_PLACE" => Ok(Sound::BlockWoolPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "BLOCK_WOOL_STEP" => Ok(Sound::BlockWoolStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENCHANT_THORNS_HIT" => Ok(Sound::EnchantThornsHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ALLAY_AMBIENT_WITHOUT_ITEM" => Ok(Sound::EntityAllayAmbientWithoutItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ALLAY_AMBIENT_WITH_ITEM" => Ok(Sound::EntityAllayAmbientWithItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ALLAY_DEATH" => Ok(Sound::EntityAllayDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ALLAY_HURT" => Ok(Sound::EntityAllayHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ALLAY_ITEM_GIVEN" => Ok(Sound::EntityAllayItemGiven { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ALLAY_ITEM_TAKEN" => Ok(Sound::EntityAllayItemTaken { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ALLAY_ITEM_THROWN" => Ok(Sound::EntityAllayItemThrown { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_AMBIENT" => Ok(Sound::EntityArmadilloAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_BRUSH" => Ok(Sound::EntityArmadilloBrush { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_DEATH" => Ok(Sound::EntityArmadilloDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_EAT" => Ok(Sound::EntityArmadilloEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_HURT" => Ok(Sound::EntityArmadilloHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_HURT_REDUCED" => Ok(Sound::EntityArmadilloHurtReduced { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_LAND" => Ok(Sound::EntityArmadilloLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_PEEK" => Ok(Sound::EntityArmadilloPeek { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_ROLL" => Ok(Sound::EntityArmadilloRoll { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_SCUTE_DROP" => Ok(Sound::EntityArmadilloScuteDrop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_STEP" => Ok(Sound::EntityArmadilloStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_UNROLL_FINISH" => Ok(Sound::EntityArmadilloUnrollFinish { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMADILLO_UNROLL_START" => Ok(Sound::EntityArmadilloUnrollStart { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMOR_STAND_BREAK" => Ok(Sound::EntityArmorStandBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMOR_STAND_FALL" => Ok(Sound::EntityArmorStandFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMOR_STAND_HIT" => Ok(Sound::EntityArmorStandHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARMOR_STAND_PLACE" => Ok(Sound::EntityArmorStandPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARROW_HIT" => Ok(Sound::EntityArrowHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARROW_HIT_PLAYER" => Ok(Sound::EntityArrowHitPlayer { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ARROW_SHOOT" => Ok(Sound::EntityArrowShoot { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_AXOLOTL_ATTACK" => Ok(Sound::EntityAxolotlAttack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_AXOLOTL_DEATH" => Ok(Sound::EntityAxolotlDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_AXOLOTL_HURT" => Ok(Sound::EntityAxolotlHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_AXOLOTL_IDLE_AIR" => Ok(Sound::EntityAxolotlIdleAir { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_AXOLOTL_IDLE_WATER" => Ok(Sound::EntityAxolotlIdleWater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_AXOLOTL_SPLASH" => Ok(Sound::EntityAxolotlSplash { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_AXOLOTL_SWIM" => Ok(Sound::EntityAxolotlSwim { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BAT_AMBIENT" => Ok(Sound::EntityBatAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BAT_DEATH" => Ok(Sound::EntityBatDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BAT_HURT" => Ok(Sound::EntityBatHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BAT_LOOP" => Ok(Sound::EntityBatLoop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BAT_TAKEOFF" => Ok(Sound::EntityBatTakeoff { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BEE_DEATH" => Ok(Sound::EntityBeeDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BEE_HURT" => Ok(Sound::EntityBeeHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BEE_LOOP" => Ok(Sound::EntityBeeLoop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BEE_LOOP_AGGRESSIVE" => Ok(Sound::EntityBeeLoopAggressive { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BEE_POLLINATE" => Ok(Sound::EntityBeePollinate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BEE_STING" => Ok(Sound::EntityBeeSting { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BLAZE_AMBIENT" => Ok(Sound::EntityBlazeAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BLAZE_BURN" => Ok(Sound::EntityBlazeBurn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BLAZE_DEATH" => Ok(Sound::EntityBlazeDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BLAZE_HURT" => Ok(Sound::EntityBlazeHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BLAZE_SHOOT" => Ok(Sound::EntityBlazeShoot { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BOAT_PADDLE_LAND" => Ok(Sound::EntityBoatPaddleLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BOAT_PADDLE_WATER" => Ok(Sound::EntityBoatPaddleWater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BOGGED_AMBIENT" => Ok(Sound::EntityBoggedAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BOGGED_DEATH" => Ok(Sound::EntityBoggedDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BOGGED_HURT" => Ok(Sound::EntityBoggedHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BOGGED_SHEAR" => Ok(Sound::EntityBoggedShear { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BOGGED_STEP" => Ok(Sound::EntityBoggedStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_CHARGE" => Ok(Sound::EntityBreezeCharge { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_DEATH" => Ok(Sound::EntityBreezeDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_DEFLECT" => Ok(Sound::EntityBreezeDeflect { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_HURT" => Ok(Sound::EntityBreezeHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_IDLE_AIR" => Ok(Sound::EntityBreezeIdleAir { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_IDLE_GROUND" => Ok(Sound::EntityBreezeIdleGround { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_INHALE" => Ok(Sound::EntityBreezeInhale { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_JUMP" => Ok(Sound::EntityBreezeJump { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_LAND" => Ok(Sound::EntityBreezeLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_SHOOT" => Ok(Sound::EntityBreezeShoot { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_SLIDE" => Ok(Sound::EntityBreezeSlide { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_WHIRL" => Ok(Sound::EntityBreezeWhirl { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_BREEZE_WIND_BURST" => Ok(Sound::EntityBreezeWindBurst { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAMEL_AMBIENT" => Ok(Sound::EntityCamelAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAMEL_DASH" => Ok(Sound::EntityCamelDash { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAMEL_DASH_READY" => Ok(Sound::EntityCamelDashReady { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAMEL_DEATH" => Ok(Sound::EntityCamelDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAMEL_EAT" => Ok(Sound::EntityCamelEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAMEL_HURT" => Ok(Sound::EntityCamelHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAMEL_SADDLE" => Ok(Sound::EntityCamelSaddle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAMEL_SIT" => Ok(Sound::EntityCamelSit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAMEL_STAND" => Ok(Sound::EntityCamelStand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAMEL_STEP" => Ok(Sound::EntityCamelStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAMEL_STEP_SAND" => Ok(Sound::EntityCamelStepSand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAT_AMBIENT" => Ok(Sound::EntityCatAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAT_BEG_FOR_FOOD" => Ok(Sound::EntityCatBegForFood { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAT_DEATH" => Ok(Sound::EntityCatDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAT_EAT" => Ok(Sound::EntityCatEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAT_HISS" => Ok(Sound::EntityCatHiss { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAT_HURT" => Ok(Sound::EntityCatHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAT_PURR" => Ok(Sound::EntityCatPurr { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAT_PURREOW" => Ok(Sound::EntityCatPurreow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CAT_STRAY_AMBIENT" => Ok(Sound::EntityCatStrayAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CHICKEN_AMBIENT" => Ok(Sound::EntityChickenAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CHICKEN_DEATH" => Ok(Sound::EntityChickenDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CHICKEN_EGG" => Ok(Sound::EntityChickenEgg { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CHICKEN_HURT" => Ok(Sound::EntityChickenHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CHICKEN_STEP" => Ok(Sound::EntityChickenStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_COD_AMBIENT" => Ok(Sound::EntityCodAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_COD_DEATH" => Ok(Sound::EntityCodDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_COD_FLOP" => Ok(Sound::EntityCodFlop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_COD_HURT" => Ok(Sound::EntityCodHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_COW_AMBIENT" => Ok(Sound::EntityCowAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_COW_DEATH" => Ok(Sound::EntityCowDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_COW_HURT" => Ok(Sound::EntityCowHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_COW_MILK" => Ok(Sound::EntityCowMilk { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_COW_STEP" => Ok(Sound::EntityCowStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CREEPER_DEATH" => Ok(Sound::EntityCreeperDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CREEPER_HURT" => Ok(Sound::EntityCreeperHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_CREEPER_PRIMED" => Ok(Sound::EntityCreeperPrimed { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DOLPHIN_AMBIENT" => Ok(Sound::EntityDolphinAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DOLPHIN_AMBIENT_WATER" => Ok(Sound::EntityDolphinAmbientWater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DOLPHIN_ATTACK" => Ok(Sound::EntityDolphinAttack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DOLPHIN_DEATH" => Ok(Sound::EntityDolphinDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DOLPHIN_EAT" => Ok(Sound::EntityDolphinEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DOLPHIN_HURT" => Ok(Sound::EntityDolphinHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DOLPHIN_JUMP" => Ok(Sound::EntityDolphinJump { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DOLPHIN_PLAY" => Ok(Sound::EntityDolphinPlay { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DOLPHIN_SPLASH" => Ok(Sound::EntityDolphinSplash { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DOLPHIN_SWIM" => Ok(Sound::EntityDolphinSwim { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DONKEY_AMBIENT" => Ok(Sound::EntityDonkeyAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DONKEY_ANGRY" => Ok(Sound::EntityDonkeyAngry { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DONKEY_CHEST" => Ok(Sound::EntityDonkeyChest { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DONKEY_DEATH" => Ok(Sound::EntityDonkeyDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DONKEY_EAT" => Ok(Sound::EntityDonkeyEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DONKEY_HURT" => Ok(Sound::EntityDonkeyHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DONKEY_JUMP" => Ok(Sound::EntityDonkeyJump { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DRAGON_FIREBALL_EXPLODE" => Ok(Sound::EntityDragonFireballExplode { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DROWNED_AMBIENT" => Ok(Sound::EntityDrownedAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DROWNED_AMBIENT_WATER" => Ok(Sound::EntityDrownedAmbientWater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DROWNED_DEATH" => Ok(Sound::EntityDrownedDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DROWNED_DEATH_WATER" => Ok(Sound::EntityDrownedDeathWater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DROWNED_HURT" => Ok(Sound::EntityDrownedHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DROWNED_HURT_WATER" => Ok(Sound::EntityDrownedHurtWater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DROWNED_SHOOT" => Ok(Sound::EntityDrownedShoot { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DROWNED_STEP" => Ok(Sound::EntityDrownedStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_DROWNED_SWIM" => Ok(Sound::EntityDrownedSwim { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_EGG_THROW" => Ok(Sound::EntityEggThrow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ELDER_GUARDIAN_AMBIENT" => Ok(Sound::EntityElderGuardianAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ELDER_GUARDIAN_AMBIENT_LAND" => Ok(Sound::EntityElderGuardianAmbientLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ELDER_GUARDIAN_CURSE" => Ok(Sound::EntityElderGuardianCurse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ELDER_GUARDIAN_DEATH" => Ok(Sound::EntityElderGuardianDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ELDER_GUARDIAN_DEATH_LAND" => Ok(Sound::EntityElderGuardianDeathLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ELDER_GUARDIAN_FLOP" => Ok(Sound::EntityElderGuardianFlop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ELDER_GUARDIAN_HURT" => Ok(Sound::EntityElderGuardianHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ELDER_GUARDIAN_HURT_LAND" => Ok(Sound::EntityElderGuardianHurtLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDERMAN_AMBIENT" => Ok(Sound::EntityEndermanAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDERMAN_DEATH" => Ok(Sound::EntityEndermanDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDERMAN_HURT" => Ok(Sound::EntityEndermanHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDERMAN_SCREAM" => Ok(Sound::EntityEndermanScream { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDERMAN_STARE" => Ok(Sound::EntityEndermanStare { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDERMAN_TELEPORT" => Ok(Sound::EntityEndermanTeleport { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDERMITE_AMBIENT" => Ok(Sound::EntityEndermiteAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDERMITE_DEATH" => Ok(Sound::EntityEndermiteDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDERMITE_HURT" => Ok(Sound::EntityEndermiteHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDERMITE_STEP" => Ok(Sound::EntityEndermiteStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDER_DRAGON_AMBIENT" => Ok(Sound::EntityEnderDragonAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDER_DRAGON_DEATH" => Ok(Sound::EntityEnderDragonDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDER_DRAGON_FLAP" => Ok(Sound::EntityEnderDragonFlap { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDER_DRAGON_GROWL" => Ok(Sound::EntityEnderDragonGrowl { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDER_DRAGON_HURT" => Ok(Sound::EntityEnderDragonHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDER_DRAGON_SHOOT" => Ok(Sound::EntityEnderDragonShoot { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDER_EYE_DEATH" => Ok(Sound::EntityEnderEyeDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDER_EYE_LAUNCH" => Ok(Sound::EntityEnderEyeLaunch { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ENDER_PEARL_THROW" => Ok(Sound::EntityEnderPearlThrow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_EVOKER_AMBIENT" => Ok(Sound::EntityEvokerAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_EVOKER_CAST_SPELL" => Ok(Sound::EntityEvokerCastSpell { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_EVOKER_CELEBRATE" => Ok(Sound::EntityEvokerCelebrate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_EVOKER_DEATH" => Ok(Sound::EntityEvokerDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_EVOKER_FANGS_ATTACK" => Ok(Sound::EntityEvokerFangsAttack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_EVOKER_HURT" => Ok(Sound::EntityEvokerHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_EVOKER_PREPARE_ATTACK" => Ok(Sound::EntityEvokerPrepareAttack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_EVOKER_PREPARE_SUMMON" => Ok(Sound::EntityEvokerPrepareSummon { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_EVOKER_PREPARE_WOLOLO" => Ok(Sound::EntityEvokerPrepareWololo { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_EXPERIENCE_BOTTLE_THROW" => Ok(Sound::EntityExperienceBottleThrow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_EXPERIENCE_ORB_PICKUP" => Ok(Sound::EntityExperienceOrbPickup { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FIREWORK_ROCKET_BLAST" => Ok(Sound::EntityFireworkRocketBlast { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FIREWORK_ROCKET_BLAST_FAR" => Ok(Sound::EntityFireworkRocketBlastFar { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FIREWORK_ROCKET_LARGE_BLAST" => Ok(Sound::EntityFireworkRocketLargeBlast { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FIREWORK_ROCKET_LARGE_BLAST_FAR" => { + Ok(Sound::EntityFireworkRocketLargeBlastFar { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "ENTITY_FIREWORK_ROCKET_LAUNCH" => Ok(Sound::EntityFireworkRocketLaunch { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FIREWORK_ROCKET_SHOOT" => Ok(Sound::EntityFireworkRocketShoot { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FIREWORK_ROCKET_TWINKLE" => Ok(Sound::EntityFireworkRocketTwinkle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FIREWORK_ROCKET_TWINKLE_FAR" => Ok(Sound::EntityFireworkRocketTwinkleFar { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FISHING_BOBBER_RETRIEVE" => Ok(Sound::EntityFishingBobberRetrieve { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FISHING_BOBBER_SPLASH" => Ok(Sound::EntityFishingBobberSplash { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FISHING_BOBBER_THROW" => Ok(Sound::EntityFishingBobberThrow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FISH_SWIM" => Ok(Sound::EntityFishSwim { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FOX_AGGRO" => Ok(Sound::EntityFoxAggro { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FOX_AMBIENT" => Ok(Sound::EntityFoxAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FOX_BITE" => Ok(Sound::EntityFoxBite { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FOX_DEATH" => Ok(Sound::EntityFoxDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FOX_EAT" => Ok(Sound::EntityFoxEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FOX_HURT" => Ok(Sound::EntityFoxHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FOX_SCREECH" => Ok(Sound::EntityFoxScreech { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FOX_SLEEP" => Ok(Sound::EntityFoxSleep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FOX_SNIFF" => Ok(Sound::EntityFoxSniff { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FOX_SPIT" => Ok(Sound::EntityFoxSpit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FOX_TELEPORT" => Ok(Sound::EntityFoxTeleport { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FROG_AMBIENT" => Ok(Sound::EntityFrogAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FROG_DEATH" => Ok(Sound::EntityFrogDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FROG_EAT" => Ok(Sound::EntityFrogEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FROG_HURT" => Ok(Sound::EntityFrogHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FROG_LAY_SPAWN" => Ok(Sound::EntityFrogLaySpawn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FROG_LONG_JUMP" => Ok(Sound::EntityFrogLongJump { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FROG_STEP" => Ok(Sound::EntityFrogStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_FROG_TONGUE" => Ok(Sound::EntityFrogTongue { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GENERIC_BIG_FALL" => Ok(Sound::EntityGenericBigFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GENERIC_BURN" => Ok(Sound::EntityGenericBurn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GENERIC_DEATH" => Ok(Sound::EntityGenericDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GENERIC_DRINK" => Ok(Sound::EntityGenericDrink { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GENERIC_EAT" => Ok(Sound::EntityGenericEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GENERIC_EXPLODE" => Ok(Sound::EntityGenericExplode { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GENERIC_EXTINGUISH_FIRE" => Ok(Sound::EntityGenericExtinguishFire { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GENERIC_HURT" => Ok(Sound::EntityGenericHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GENERIC_SMALL_FALL" => Ok(Sound::EntityGenericSmallFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GENERIC_SPLASH" => Ok(Sound::EntityGenericSplash { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GENERIC_SWIM" => Ok(Sound::EntityGenericSwim { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GHAST_AMBIENT" => Ok(Sound::EntityGhastAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GHAST_DEATH" => Ok(Sound::EntityGhastDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GHAST_HURT" => Ok(Sound::EntityGhastHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GHAST_SCREAM" => Ok(Sound::EntityGhastScream { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GHAST_SHOOT" => Ok(Sound::EntityGhastShoot { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GHAST_WARN" => Ok(Sound::EntityGhastWarn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GLOW_ITEM_FRAME_ADD_ITEM" => Ok(Sound::EntityGlowItemFrameAddItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GLOW_ITEM_FRAME_BREAK" => Ok(Sound::EntityGlowItemFrameBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GLOW_ITEM_FRAME_PLACE" => Ok(Sound::EntityGlowItemFramePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GLOW_ITEM_FRAME_REMOVE_ITEM" => Ok(Sound::EntityGlowItemFrameRemoveItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GLOW_ITEM_FRAME_ROTATE_ITEM" => Ok(Sound::EntityGlowItemFrameRotateItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GLOW_SQUID_AMBIENT" => Ok(Sound::EntityGlowSquidAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GLOW_SQUID_DEATH" => Ok(Sound::EntityGlowSquidDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GLOW_SQUID_HURT" => Ok(Sound::EntityGlowSquidHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GLOW_SQUID_SQUIRT" => Ok(Sound::EntityGlowSquidSquirt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_AMBIENT" => Ok(Sound::EntityGoatAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_DEATH" => Ok(Sound::EntityGoatDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_EAT" => Ok(Sound::EntityGoatEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_HORN_BREAK" => Ok(Sound::EntityGoatHornBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_HURT" => Ok(Sound::EntityGoatHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_LONG_JUMP" => Ok(Sound::EntityGoatLongJump { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_MILK" => Ok(Sound::EntityGoatMilk { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_PREPARE_RAM" => Ok(Sound::EntityGoatPrepareRam { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_RAM_IMPACT" => Ok(Sound::EntityGoatRamImpact { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_SCREAMING_AMBIENT" => Ok(Sound::EntityGoatScreamingAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_SCREAMING_DEATH" => Ok(Sound::EntityGoatScreamingDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_SCREAMING_EAT" => Ok(Sound::EntityGoatScreamingEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_SCREAMING_HORN_BREAK" => Ok(Sound::EntityGoatScreamingHornBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_SCREAMING_HURT" => Ok(Sound::EntityGoatScreamingHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_SCREAMING_LONG_JUMP" => Ok(Sound::EntityGoatScreamingLongJump { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_SCREAMING_MILK" => Ok(Sound::EntityGoatScreamingMilk { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_SCREAMING_PREPARE_RAM" => Ok(Sound::EntityGoatScreamingPrepareRam { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_SCREAMING_RAM_IMPACT" => Ok(Sound::EntityGoatScreamingRamImpact { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GOAT_STEP" => Ok(Sound::EntityGoatStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GUARDIAN_AMBIENT" => Ok(Sound::EntityGuardianAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GUARDIAN_AMBIENT_LAND" => Ok(Sound::EntityGuardianAmbientLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GUARDIAN_ATTACK" => Ok(Sound::EntityGuardianAttack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GUARDIAN_DEATH" => Ok(Sound::EntityGuardianDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GUARDIAN_DEATH_LAND" => Ok(Sound::EntityGuardianDeathLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GUARDIAN_FLOP" => Ok(Sound::EntityGuardianFlop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GUARDIAN_HURT" => Ok(Sound::EntityGuardianHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_GUARDIAN_HURT_LAND" => Ok(Sound::EntityGuardianHurtLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOGLIN_AMBIENT" => Ok(Sound::EntityHoglinAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOGLIN_ANGRY" => Ok(Sound::EntityHoglinAngry { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOGLIN_ATTACK" => Ok(Sound::EntityHoglinAttack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOGLIN_CONVERTED_TO_ZOMBIFIED" => { + Ok(Sound::EntityHoglinConvertedToZombified { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "ENTITY_HOGLIN_DEATH" => Ok(Sound::EntityHoglinDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOGLIN_HURT" => Ok(Sound::EntityHoglinHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOGLIN_RETREAT" => Ok(Sound::EntityHoglinRetreat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOGLIN_STEP" => Ok(Sound::EntityHoglinStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_AMBIENT" => Ok(Sound::EntityHorseAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_ANGRY" => Ok(Sound::EntityHorseAngry { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_ARMOR" => Ok(Sound::EntityHorseArmor { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_BREATHE" => Ok(Sound::EntityHorseBreathe { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_DEATH" => Ok(Sound::EntityHorseDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_EAT" => Ok(Sound::EntityHorseEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_GALLOP" => Ok(Sound::EntityHorseGallop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_HURT" => Ok(Sound::EntityHorseHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_JUMP" => Ok(Sound::EntityHorseJump { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_LAND" => Ok(Sound::EntityHorseLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_SADDLE" => Ok(Sound::EntityHorseSaddle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_STEP" => Ok(Sound::EntityHorseStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HORSE_STEP_WOOD" => Ok(Sound::EntityHorseStepWood { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOSTILE_BIG_FALL" => Ok(Sound::EntityHostileBigFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOSTILE_DEATH" => Ok(Sound::EntityHostileDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOSTILE_HURT" => Ok(Sound::EntityHostileHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOSTILE_SMALL_FALL" => Ok(Sound::EntityHostileSmallFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOSTILE_SPLASH" => Ok(Sound::EntityHostileSplash { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HOSTILE_SWIM" => Ok(Sound::EntityHostileSwim { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HUSK_AMBIENT" => Ok(Sound::EntityHuskAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HUSK_CONVERTED_TO_ZOMBIE" => Ok(Sound::EntityHuskConvertedToZombie { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HUSK_DEATH" => Ok(Sound::EntityHuskDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HUSK_HURT" => Ok(Sound::EntityHuskHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_HUSK_STEP" => Ok(Sound::EntityHuskStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ILLUSIONER_AMBIENT" => Ok(Sound::EntityIllusionerAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ILLUSIONER_CAST_SPELL" => Ok(Sound::EntityIllusionerCastSpell { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ILLUSIONER_DEATH" => Ok(Sound::EntityIllusionerDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ILLUSIONER_HURT" => Ok(Sound::EntityIllusionerHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ILLUSIONER_MIRROR_MOVE" => Ok(Sound::EntityIllusionerMirrorMove { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ILLUSIONER_PREPARE_BLINDNESS" => { + Ok(Sound::EntityIllusionerPrepareBlindness { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "ENTITY_ILLUSIONER_PREPARE_MIRROR" => Ok(Sound::EntityIllusionerPrepareMirror { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_IRON_GOLEM_ATTACK" => Ok(Sound::EntityIronGolemAttack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_IRON_GOLEM_DAMAGE" => Ok(Sound::EntityIronGolemDamage { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_IRON_GOLEM_DEATH" => Ok(Sound::EntityIronGolemDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_IRON_GOLEM_HURT" => Ok(Sound::EntityIronGolemHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_IRON_GOLEM_REPAIR" => Ok(Sound::EntityIronGolemRepair { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_IRON_GOLEM_STEP" => Ok(Sound::EntityIronGolemStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ITEM_BREAK" => Ok(Sound::EntityItemBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ITEM_FRAME_ADD_ITEM" => Ok(Sound::EntityItemFrameAddItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ITEM_FRAME_BREAK" => Ok(Sound::EntityItemFrameBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ITEM_FRAME_PLACE" => Ok(Sound::EntityItemFramePlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ITEM_FRAME_REMOVE_ITEM" => Ok(Sound::EntityItemFrameRemoveItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ITEM_FRAME_ROTATE_ITEM" => Ok(Sound::EntityItemFrameRotateItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ITEM_PICKUP" => Ok(Sound::EntityItemPickup { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LEASH_KNOT_BREAK" => Ok(Sound::EntityLeashKnotBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LEASH_KNOT_PLACE" => Ok(Sound::EntityLeashKnotPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LIGHTNING_BOLT_IMPACT" => Ok(Sound::EntityLightningBoltImpact { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LIGHTNING_BOLT_THUNDER" => Ok(Sound::EntityLightningBoltThunder { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LINGERING_POTION_THROW" => Ok(Sound::EntityLingeringPotionThrow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LLAMA_AMBIENT" => Ok(Sound::EntityLlamaAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LLAMA_ANGRY" => Ok(Sound::EntityLlamaAngry { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LLAMA_CHEST" => Ok(Sound::EntityLlamaChest { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LLAMA_DEATH" => Ok(Sound::EntityLlamaDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LLAMA_EAT" => Ok(Sound::EntityLlamaEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LLAMA_HURT" => Ok(Sound::EntityLlamaHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LLAMA_SPIT" => Ok(Sound::EntityLlamaSpit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LLAMA_STEP" => Ok(Sound::EntityLlamaStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_LLAMA_SWAG" => Ok(Sound::EntityLlamaSwag { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MAGMA_CUBE_DEATH" => Ok(Sound::EntityMagmaCubeDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MAGMA_CUBE_DEATH_SMALL" => Ok(Sound::EntityMagmaCubeDeathSmall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MAGMA_CUBE_HURT" => Ok(Sound::EntityMagmaCubeHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MAGMA_CUBE_HURT_SMALL" => Ok(Sound::EntityMagmaCubeHurtSmall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MAGMA_CUBE_JUMP" => Ok(Sound::EntityMagmaCubeJump { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MAGMA_CUBE_SQUISH" => Ok(Sound::EntityMagmaCubeSquish { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MAGMA_CUBE_SQUISH_SMALL" => Ok(Sound::EntityMagmaCubeSquishSmall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MINECART_INSIDE" => Ok(Sound::EntityMinecartInside { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MINECART_INSIDE_UNDERWATER" => Ok(Sound::EntityMinecartInsideUnderwater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MINECART_RIDING" => Ok(Sound::EntityMinecartRiding { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MOOSHROOM_CONVERT" => Ok(Sound::EntityMooshroomConvert { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MOOSHROOM_EAT" => Ok(Sound::EntityMooshroomEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MOOSHROOM_MILK" => Ok(Sound::EntityMooshroomMilk { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MOOSHROOM_SHEAR" => Ok(Sound::EntityMooshroomShear { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MOOSHROOM_SUSPICIOUS_MILK" => Ok(Sound::EntityMooshroomSuspiciousMilk { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MULE_AMBIENT" => Ok(Sound::EntityMuleAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MULE_ANGRY" => Ok(Sound::EntityMuleAngry { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MULE_CHEST" => Ok(Sound::EntityMuleChest { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MULE_DEATH" => Ok(Sound::EntityMuleDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MULE_EAT" => Ok(Sound::EntityMuleEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MULE_HURT" => Ok(Sound::EntityMuleHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_MULE_JUMP" => Ok(Sound::EntityMuleJump { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_OCELOT_AMBIENT" => Ok(Sound::EntityOcelotAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_OCELOT_DEATH" => Ok(Sound::EntityOcelotDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_OCELOT_HURT" => Ok(Sound::EntityOcelotHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PAINTING_BREAK" => Ok(Sound::EntityPaintingBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PAINTING_PLACE" => Ok(Sound::EntityPaintingPlace { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PANDA_AGGRESSIVE_AMBIENT" => Ok(Sound::EntityPandaAggressiveAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PANDA_AMBIENT" => Ok(Sound::EntityPandaAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PANDA_BITE" => Ok(Sound::EntityPandaBite { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PANDA_CANT_BREED" => Ok(Sound::EntityPandaCantBreed { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PANDA_DEATH" => Ok(Sound::EntityPandaDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PANDA_EAT" => Ok(Sound::EntityPandaEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PANDA_HURT" => Ok(Sound::EntityPandaHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PANDA_PRE_SNEEZE" => Ok(Sound::EntityPandaPreSneeze { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PANDA_SNEEZE" => Ok(Sound::EntityPandaSneeze { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PANDA_STEP" => Ok(Sound::EntityPandaStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PANDA_WORRIED_AMBIENT" => Ok(Sound::EntityPandaWorriedAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_AMBIENT" => Ok(Sound::EntityParrotAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_DEATH" => Ok(Sound::EntityParrotDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_EAT" => Ok(Sound::EntityParrotEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_FLY" => Ok(Sound::EntityParrotFly { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_HURT" => Ok(Sound::EntityParrotHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_BLAZE" => Ok(Sound::EntityParrotImitateBlaze { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_BOGGED" => Ok(Sound::EntityParrotImitateBogged { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_BREEZE" => Ok(Sound::EntityParrotImitateBreeze { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_CREEPER" => Ok(Sound::EntityParrotImitateCreeper { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_DROWNED" => Ok(Sound::EntityParrotImitateDrowned { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_ELDER_GUARDIAN" => { + Ok(Sound::EntityParrotImitateElderGuardian { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "ENTITY_PARROT_IMITATE_ENDERMITE" => Ok(Sound::EntityParrotImitateEndermite { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_ENDER_DRAGON" => Ok(Sound::EntityParrotImitateEnderDragon { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_EVOKER" => Ok(Sound::EntityParrotImitateEvoker { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_GHAST" => Ok(Sound::EntityParrotImitateGhast { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_GUARDIAN" => Ok(Sound::EntityParrotImitateGuardian { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_HOGLIN" => Ok(Sound::EntityParrotImitateHoglin { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_HUSK" => Ok(Sound::EntityParrotImitateHusk { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_ILLUSIONER" => Ok(Sound::EntityParrotImitateIllusioner { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_MAGMA_CUBE" => Ok(Sound::EntityParrotImitateMagmaCube { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_PHANTOM" => Ok(Sound::EntityParrotImitatePhantom { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_PIGLIN" => Ok(Sound::EntityParrotImitatePiglin { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_PIGLIN_BRUTE" => Ok(Sound::EntityParrotImitatePiglinBrute { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_PILLAGER" => Ok(Sound::EntityParrotImitatePillager { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_RAVAGER" => Ok(Sound::EntityParrotImitateRavager { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_SHULKER" => Ok(Sound::EntityParrotImitateShulker { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_SILVERFISH" => Ok(Sound::EntityParrotImitateSilverfish { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_SKELETON" => Ok(Sound::EntityParrotImitateSkeleton { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_SLIME" => Ok(Sound::EntityParrotImitateSlime { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_SPIDER" => Ok(Sound::EntityParrotImitateSpider { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_STRAY" => Ok(Sound::EntityParrotImitateStray { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_VEX" => Ok(Sound::EntityParrotImitateVex { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_VINDICATOR" => Ok(Sound::EntityParrotImitateVindicator { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_WARDEN" => Ok(Sound::EntityParrotImitateWarden { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_WITCH" => Ok(Sound::EntityParrotImitateWitch { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_WITHER" => Ok(Sound::EntityParrotImitateWither { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_WITHER_SKELETON" => { + Ok(Sound::EntityParrotImitateWitherSkeleton { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "ENTITY_PARROT_IMITATE_ZOGLIN" => Ok(Sound::EntityParrotImitateZoglin { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_ZOMBIE" => Ok(Sound::EntityParrotImitateZombie { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PARROT_IMITATE_ZOMBIE_VILLAGER" => { + Ok(Sound::EntityParrotImitateZombieVillager { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "ENTITY_PARROT_STEP" => Ok(Sound::EntityParrotStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PHANTOM_AMBIENT" => Ok(Sound::EntityPhantomAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PHANTOM_BITE" => Ok(Sound::EntityPhantomBite { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PHANTOM_DEATH" => Ok(Sound::EntityPhantomDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PHANTOM_FLAP" => Ok(Sound::EntityPhantomFlap { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PHANTOM_HURT" => Ok(Sound::EntityPhantomHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PHANTOM_SWOOP" => Ok(Sound::EntityPhantomSwoop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_ADMIRING_ITEM" => Ok(Sound::EntityPiglinAdmiringItem { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_AMBIENT" => Ok(Sound::EntityPiglinAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_ANGRY" => Ok(Sound::EntityPiglinAngry { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_BRUTE_AMBIENT" => Ok(Sound::EntityPiglinBruteAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_BRUTE_ANGRY" => Ok(Sound::EntityPiglinBruteAngry { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_BRUTE_CONVERTED_TO_ZOMBIFIED" => { + Ok(Sound::EntityPiglinBruteConvertedToZombified { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "ENTITY_PIGLIN_BRUTE_DEATH" => Ok(Sound::EntityPiglinBruteDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_BRUTE_HURT" => Ok(Sound::EntityPiglinBruteHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_BRUTE_STEP" => Ok(Sound::EntityPiglinBruteStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_CELEBRATE" => Ok(Sound::EntityPiglinCelebrate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_CONVERTED_TO_ZOMBIFIED" => { + Ok(Sound::EntityPiglinConvertedToZombified { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "ENTITY_PIGLIN_DEATH" => Ok(Sound::EntityPiglinDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_HURT" => Ok(Sound::EntityPiglinHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_JEALOUS" => Ok(Sound::EntityPiglinJealous { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_RETREAT" => Ok(Sound::EntityPiglinRetreat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIGLIN_STEP" => Ok(Sound::EntityPiglinStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIG_AMBIENT" => Ok(Sound::EntityPigAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIG_DEATH" => Ok(Sound::EntityPigDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIG_HURT" => Ok(Sound::EntityPigHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIG_SADDLE" => Ok(Sound::EntityPigSaddle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PIG_STEP" => Ok(Sound::EntityPigStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PILLAGER_AMBIENT" => Ok(Sound::EntityPillagerAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PILLAGER_CELEBRATE" => Ok(Sound::EntityPillagerCelebrate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PILLAGER_DEATH" => Ok(Sound::EntityPillagerDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PILLAGER_HURT" => Ok(Sound::EntityPillagerHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_ATTACK_CRIT" => Ok(Sound::EntityPlayerAttackCrit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_ATTACK_KNOCKBACK" => Ok(Sound::EntityPlayerAttackKnockback { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_ATTACK_NODAMAGE" => Ok(Sound::EntityPlayerAttackNodamage { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_ATTACK_STRONG" => Ok(Sound::EntityPlayerAttackStrong { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_ATTACK_SWEEP" => Ok(Sound::EntityPlayerAttackSweep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_ATTACK_WEAK" => Ok(Sound::EntityPlayerAttackWeak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_BIG_FALL" => Ok(Sound::EntityPlayerBigFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_BREATH" => Ok(Sound::EntityPlayerBreath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_BURP" => Ok(Sound::EntityPlayerBurp { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_DEATH" => Ok(Sound::EntityPlayerDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_HURT" => Ok(Sound::EntityPlayerHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_HURT_DROWN" => Ok(Sound::EntityPlayerHurtDrown { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_HURT_FREEZE" => Ok(Sound::EntityPlayerHurtFreeze { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_HURT_ON_FIRE" => Ok(Sound::EntityPlayerHurtOnFire { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_HURT_SWEET_BERRY_BUSH" => { + Ok(Sound::EntityPlayerHurtSweetBerryBush { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "ENTITY_PLAYER_LEVELUP" => Ok(Sound::EntityPlayerLevelup { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_SMALL_FALL" => Ok(Sound::EntityPlayerSmallFall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_SPLASH" => Ok(Sound::EntityPlayerSplash { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_SPLASH_HIGH_SPEED" => Ok(Sound::EntityPlayerSplashHighSpeed { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_SWIM" => Ok(Sound::EntityPlayerSwim { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PLAYER_TELEPORT" => Ok(Sound::EntityPlayerTeleport { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_POLAR_BEAR_AMBIENT" => Ok(Sound::EntityPolarBearAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_POLAR_BEAR_AMBIENT_BABY" => Ok(Sound::EntityPolarBearAmbientBaby { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_POLAR_BEAR_DEATH" => Ok(Sound::EntityPolarBearDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_POLAR_BEAR_HURT" => Ok(Sound::EntityPolarBearHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_POLAR_BEAR_STEP" => Ok(Sound::EntityPolarBearStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_POLAR_BEAR_WARNING" => Ok(Sound::EntityPolarBearWarning { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PUFFER_FISH_AMBIENT" => Ok(Sound::EntityPufferFishAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PUFFER_FISH_BLOW_OUT" => Ok(Sound::EntityPufferFishBlowOut { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PUFFER_FISH_BLOW_UP" => Ok(Sound::EntityPufferFishBlowUp { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PUFFER_FISH_DEATH" => Ok(Sound::EntityPufferFishDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PUFFER_FISH_FLOP" => Ok(Sound::EntityPufferFishFlop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PUFFER_FISH_HURT" => Ok(Sound::EntityPufferFishHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_PUFFER_FISH_STING" => Ok(Sound::EntityPufferFishSting { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RABBIT_AMBIENT" => Ok(Sound::EntityRabbitAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RABBIT_ATTACK" => Ok(Sound::EntityRabbitAttack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RABBIT_DEATH" => Ok(Sound::EntityRabbitDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RABBIT_HURT" => Ok(Sound::EntityRabbitHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RABBIT_JUMP" => Ok(Sound::EntityRabbitJump { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RAVAGER_AMBIENT" => Ok(Sound::EntityRavagerAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RAVAGER_ATTACK" => Ok(Sound::EntityRavagerAttack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RAVAGER_CELEBRATE" => Ok(Sound::EntityRavagerCelebrate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RAVAGER_DEATH" => Ok(Sound::EntityRavagerDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RAVAGER_HURT" => Ok(Sound::EntityRavagerHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RAVAGER_ROAR" => Ok(Sound::EntityRavagerRoar { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RAVAGER_STEP" => Ok(Sound::EntityRavagerStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_RAVAGER_STUNNED" => Ok(Sound::EntityRavagerStunned { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SALMON_AMBIENT" => Ok(Sound::EntitySalmonAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SALMON_DEATH" => Ok(Sound::EntitySalmonDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SALMON_FLOP" => Ok(Sound::EntitySalmonFlop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SALMON_HURT" => Ok(Sound::EntitySalmonHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHEEP_AMBIENT" => Ok(Sound::EntitySheepAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHEEP_DEATH" => Ok(Sound::EntitySheepDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHEEP_HURT" => Ok(Sound::EntitySheepHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHEEP_SHEAR" => Ok(Sound::EntitySheepShear { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHEEP_STEP" => Ok(Sound::EntitySheepStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHULKER_AMBIENT" => Ok(Sound::EntityShulkerAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHULKER_BULLET_HIT" => Ok(Sound::EntityShulkerBulletHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHULKER_BULLET_HURT" => Ok(Sound::EntityShulkerBulletHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHULKER_CLOSE" => Ok(Sound::EntityShulkerClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHULKER_DEATH" => Ok(Sound::EntityShulkerDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHULKER_HURT" => Ok(Sound::EntityShulkerHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHULKER_HURT_CLOSED" => Ok(Sound::EntityShulkerHurtClosed { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHULKER_OPEN" => Ok(Sound::EntityShulkerOpen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHULKER_SHOOT" => Ok(Sound::EntityShulkerShoot { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SHULKER_TELEPORT" => Ok(Sound::EntityShulkerTeleport { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SILVERFISH_AMBIENT" => Ok(Sound::EntitySilverfishAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SILVERFISH_DEATH" => Ok(Sound::EntitySilverfishDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SILVERFISH_HURT" => Ok(Sound::EntitySilverfishHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SILVERFISH_STEP" => Ok(Sound::EntitySilverfishStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_AMBIENT" => Ok(Sound::EntitySkeletonAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_CONVERTED_TO_STRAY" => Ok(Sound::EntitySkeletonConvertedToStray { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_DEATH" => Ok(Sound::EntitySkeletonDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_HORSE_AMBIENT" => Ok(Sound::EntitySkeletonHorseAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_HORSE_AMBIENT_WATER" => { + Ok(Sound::EntitySkeletonHorseAmbientWater { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "ENTITY_SKELETON_HORSE_DEATH" => Ok(Sound::EntitySkeletonHorseDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_HORSE_GALLOP_WATER" => Ok(Sound::EntitySkeletonHorseGallopWater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_HORSE_HURT" => Ok(Sound::EntitySkeletonHorseHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_HORSE_JUMP_WATER" => Ok(Sound::EntitySkeletonHorseJumpWater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_HORSE_STEP_WATER" => Ok(Sound::EntitySkeletonHorseStepWater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_HORSE_SWIM" => Ok(Sound::EntitySkeletonHorseSwim { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_HURT" => Ok(Sound::EntitySkeletonHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_SHOOT" => Ok(Sound::EntitySkeletonShoot { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SKELETON_STEP" => Ok(Sound::EntitySkeletonStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SLIME_ATTACK" => Ok(Sound::EntitySlimeAttack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SLIME_DEATH" => Ok(Sound::EntitySlimeDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SLIME_DEATH_SMALL" => Ok(Sound::EntitySlimeDeathSmall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SLIME_HURT" => Ok(Sound::EntitySlimeHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SLIME_HURT_SMALL" => Ok(Sound::EntitySlimeHurtSmall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SLIME_JUMP" => Ok(Sound::EntitySlimeJump { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SLIME_JUMP_SMALL" => Ok(Sound::EntitySlimeJumpSmall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SLIME_SQUISH" => Ok(Sound::EntitySlimeSquish { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SLIME_SQUISH_SMALL" => Ok(Sound::EntitySlimeSquishSmall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNIFFER_DEATH" => Ok(Sound::EntitySnifferDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNIFFER_DIGGING" => Ok(Sound::EntitySnifferDigging { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNIFFER_DIGGING_STOP" => Ok(Sound::EntitySnifferDiggingStop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNIFFER_DROP_SEED" => Ok(Sound::EntitySnifferDropSeed { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNIFFER_EAT" => Ok(Sound::EntitySnifferEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNIFFER_HAPPY" => Ok(Sound::EntitySnifferHappy { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNIFFER_HURT" => Ok(Sound::EntitySnifferHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNIFFER_IDLE" => Ok(Sound::EntitySnifferIdle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNIFFER_SCENTING" => Ok(Sound::EntitySnifferScenting { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNIFFER_SEARCHING" => Ok(Sound::EntitySnifferSearching { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNIFFER_SNIFFING" => Ok(Sound::EntitySnifferSniffing { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNIFFER_STEP" => Ok(Sound::EntitySnifferStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNOWBALL_THROW" => Ok(Sound::EntitySnowballThrow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNOW_GOLEM_AMBIENT" => Ok(Sound::EntitySnowGolemAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNOW_GOLEM_DEATH" => Ok(Sound::EntitySnowGolemDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNOW_GOLEM_HURT" => Ok(Sound::EntitySnowGolemHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNOW_GOLEM_SHEAR" => Ok(Sound::EntitySnowGolemShear { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SNOW_GOLEM_SHOOT" => Ok(Sound::EntitySnowGolemShoot { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SPIDER_AMBIENT" => Ok(Sound::EntitySpiderAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SPIDER_DEATH" => Ok(Sound::EntitySpiderDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SPIDER_HURT" => Ok(Sound::EntitySpiderHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SPIDER_STEP" => Ok(Sound::EntitySpiderStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SPLASH_POTION_BREAK" => Ok(Sound::EntitySplashPotionBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SPLASH_POTION_THROW" => Ok(Sound::EntitySplashPotionThrow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SQUID_AMBIENT" => Ok(Sound::EntitySquidAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SQUID_DEATH" => Ok(Sound::EntitySquidDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SQUID_HURT" => Ok(Sound::EntitySquidHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_SQUID_SQUIRT" => Ok(Sound::EntitySquidSquirt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRAY_AMBIENT" => Ok(Sound::EntityStrayAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRAY_DEATH" => Ok(Sound::EntityStrayDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRAY_HURT" => Ok(Sound::EntityStrayHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRAY_STEP" => Ok(Sound::EntityStrayStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRIDER_AMBIENT" => Ok(Sound::EntityStriderAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRIDER_DEATH" => Ok(Sound::EntityStriderDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRIDER_EAT" => Ok(Sound::EntityStriderEat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRIDER_HAPPY" => Ok(Sound::EntityStriderHappy { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRIDER_HURT" => Ok(Sound::EntityStriderHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRIDER_RETREAT" => Ok(Sound::EntityStriderRetreat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRIDER_SADDLE" => Ok(Sound::EntityStriderSaddle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRIDER_STEP" => Ok(Sound::EntityStriderStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_STRIDER_STEP_LAVA" => Ok(Sound::EntityStriderStepLava { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TADPOLE_DEATH" => Ok(Sound::EntityTadpoleDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TADPOLE_FLOP" => Ok(Sound::EntityTadpoleFlop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TADPOLE_GROW_UP" => Ok(Sound::EntityTadpoleGrowUp { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TADPOLE_HURT" => Ok(Sound::EntityTadpoleHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TNT_PRIMED" => Ok(Sound::EntityTntPrimed { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TROPICAL_FISH_AMBIENT" => Ok(Sound::EntityTropicalFishAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TROPICAL_FISH_DEATH" => Ok(Sound::EntityTropicalFishDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TROPICAL_FISH_FLOP" => Ok(Sound::EntityTropicalFishFlop { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TROPICAL_FISH_HURT" => Ok(Sound::EntityTropicalFishHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TURTLE_AMBIENT_LAND" => Ok(Sound::EntityTurtleAmbientLand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TURTLE_DEATH" => Ok(Sound::EntityTurtleDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TURTLE_DEATH_BABY" => Ok(Sound::EntityTurtleDeathBaby { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TURTLE_EGG_BREAK" => Ok(Sound::EntityTurtleEggBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TURTLE_EGG_CRACK" => Ok(Sound::EntityTurtleEggCrack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TURTLE_EGG_HATCH" => Ok(Sound::EntityTurtleEggHatch { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TURTLE_HURT" => Ok(Sound::EntityTurtleHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TURTLE_HURT_BABY" => Ok(Sound::EntityTurtleHurtBaby { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TURTLE_LAY_EGG" => Ok(Sound::EntityTurtleLayEgg { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TURTLE_SHAMBLE" => Ok(Sound::EntityTurtleShamble { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TURTLE_SHAMBLE_BABY" => Ok(Sound::EntityTurtleShambleBaby { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_TURTLE_SWIM" => Ok(Sound::EntityTurtleSwim { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VEX_AMBIENT" => Ok(Sound::EntityVexAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VEX_CHARGE" => Ok(Sound::EntityVexCharge { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VEX_DEATH" => Ok(Sound::EntityVexDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VEX_HURT" => Ok(Sound::EntityVexHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_AMBIENT" => Ok(Sound::EntityVillagerAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_CELEBRATE" => Ok(Sound::EntityVillagerCelebrate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_DEATH" => Ok(Sound::EntityVillagerDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_HURT" => Ok(Sound::EntityVillagerHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_NO" => Ok(Sound::EntityVillagerNo { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_TRADE" => Ok(Sound::EntityVillagerTrade { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_ARMORER" => Ok(Sound::EntityVillagerWorkArmorer { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_BUTCHER" => Ok(Sound::EntityVillagerWorkButcher { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_CARTOGRAPHER" => Ok(Sound::EntityVillagerWorkCartographer { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_CLERIC" => Ok(Sound::EntityVillagerWorkCleric { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_FARMER" => Ok(Sound::EntityVillagerWorkFarmer { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_FISHERMAN" => Ok(Sound::EntityVillagerWorkFisherman { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_FLETCHER" => Ok(Sound::EntityVillagerWorkFletcher { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_LEATHERWORKER" => { + Ok(Sound::EntityVillagerWorkLeatherworker { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "ENTITY_VILLAGER_WORK_LIBRARIAN" => Ok(Sound::EntityVillagerWorkLibrarian { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_MASON" => Ok(Sound::EntityVillagerWorkMason { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_SHEPHERD" => Ok(Sound::EntityVillagerWorkShepherd { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_TOOLSMITH" => Ok(Sound::EntityVillagerWorkToolsmith { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_WORK_WEAPONSMITH" => Ok(Sound::EntityVillagerWorkWeaponsmith { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VILLAGER_YES" => Ok(Sound::EntityVillagerYes { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VINDICATOR_AMBIENT" => Ok(Sound::EntityVindicatorAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VINDICATOR_CELEBRATE" => Ok(Sound::EntityVindicatorCelebrate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VINDICATOR_DEATH" => Ok(Sound::EntityVindicatorDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_VINDICATOR_HURT" => Ok(Sound::EntityVindicatorHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WANDERING_TRADER_AMBIENT" => Ok(Sound::EntityWanderingTraderAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WANDERING_TRADER_DEATH" => Ok(Sound::EntityWanderingTraderDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WANDERING_TRADER_DISAPPEARED" => { + Ok(Sound::EntityWanderingTraderDisappeared { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "ENTITY_WANDERING_TRADER_DRINK_MILK" => Ok(Sound::EntityWanderingTraderDrinkMilk { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WANDERING_TRADER_DRINK_POTION" => { + Ok(Sound::EntityWanderingTraderDrinkPotion { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "ENTITY_WANDERING_TRADER_HURT" => Ok(Sound::EntityWanderingTraderHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WANDERING_TRADER_NO" => Ok(Sound::EntityWanderingTraderNo { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WANDERING_TRADER_REAPPEARED" => { + Ok(Sound::EntityWanderingTraderReappeared { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "ENTITY_WANDERING_TRADER_TRADE" => Ok(Sound::EntityWanderingTraderTrade { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WANDERING_TRADER_YES" => Ok(Sound::EntityWanderingTraderYes { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_AGITATED" => Ok(Sound::EntityWardenAgitated { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_AMBIENT" => Ok(Sound::EntityWardenAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_ANGRY" => Ok(Sound::EntityWardenAngry { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_ATTACK_IMPACT" => Ok(Sound::EntityWardenAttackImpact { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_DEATH" => Ok(Sound::EntityWardenDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_DIG" => Ok(Sound::EntityWardenDig { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_EMERGE" => Ok(Sound::EntityWardenEmerge { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_HEARTBEAT" => Ok(Sound::EntityWardenHeartbeat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_HURT" => Ok(Sound::EntityWardenHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_LISTENING" => Ok(Sound::EntityWardenListening { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_LISTENING_ANGRY" => Ok(Sound::EntityWardenListeningAngry { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_NEARBY_CLOSE" => Ok(Sound::EntityWardenNearbyClose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_NEARBY_CLOSER" => Ok(Sound::EntityWardenNearbyCloser { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_NEARBY_CLOSEST" => Ok(Sound::EntityWardenNearbyClosest { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_ROAR" => Ok(Sound::EntityWardenRoar { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_SNIFF" => Ok(Sound::EntityWardenSniff { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_SONIC_BOOM" => Ok(Sound::EntityWardenSonicBoom { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_SONIC_CHARGE" => Ok(Sound::EntityWardenSonicCharge { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_STEP" => Ok(Sound::EntityWardenStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WARDEN_TENDRIL_CLICKS" => Ok(Sound::EntityWardenTendrilClicks { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WIND_CHARGE_THROW" => Ok(Sound::EntityWindChargeThrow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WIND_CHARGE_WIND_BURST" => Ok(Sound::EntityWindChargeWindBurst { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITCH_AMBIENT" => Ok(Sound::EntityWitchAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITCH_CELEBRATE" => Ok(Sound::EntityWitchCelebrate { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITCH_DEATH" => Ok(Sound::EntityWitchDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITCH_DRINK" => Ok(Sound::EntityWitchDrink { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITCH_HURT" => Ok(Sound::EntityWitchHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITCH_THROW" => Ok(Sound::EntityWitchThrow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITHER_AMBIENT" => Ok(Sound::EntityWitherAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITHER_BREAK_BLOCK" => Ok(Sound::EntityWitherBreakBlock { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITHER_DEATH" => Ok(Sound::EntityWitherDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITHER_HURT" => Ok(Sound::EntityWitherHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITHER_SHOOT" => Ok(Sound::EntityWitherShoot { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITHER_SKELETON_AMBIENT" => Ok(Sound::EntityWitherSkeletonAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITHER_SKELETON_DEATH" => Ok(Sound::EntityWitherSkeletonDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITHER_SKELETON_HURT" => Ok(Sound::EntityWitherSkeletonHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITHER_SKELETON_STEP" => Ok(Sound::EntityWitherSkeletonStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WITHER_SPAWN" => Ok(Sound::EntityWitherSpawn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WOLF_AMBIENT" => Ok(Sound::EntityWolfAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WOLF_DEATH" => Ok(Sound::EntityWolfDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WOLF_GROWL" => Ok(Sound::EntityWolfGrowl { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WOLF_HOWL" => Ok(Sound::EntityWolfHowl { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WOLF_HURT" => Ok(Sound::EntityWolfHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WOLF_PANT" => Ok(Sound::EntityWolfPant { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WOLF_SHAKE" => Ok(Sound::EntityWolfShake { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WOLF_STEP" => Ok(Sound::EntityWolfStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_WOLF_WHINE" => Ok(Sound::EntityWolfWhine { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOGLIN_AMBIENT" => Ok(Sound::EntityZoglinAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOGLIN_ANGRY" => Ok(Sound::EntityZoglinAngry { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOGLIN_ATTACK" => Ok(Sound::EntityZoglinAttack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOGLIN_DEATH" => Ok(Sound::EntityZoglinDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOGLIN_HURT" => Ok(Sound::EntityZoglinHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOGLIN_STEP" => Ok(Sound::EntityZoglinStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_AMBIENT" => Ok(Sound::EntityZombieAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_ATTACK_IRON_DOOR" => Ok(Sound::EntityZombieAttackIronDoor { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_ATTACK_WOODEN_DOOR" => Ok(Sound::EntityZombieAttackWoodenDoor { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_BREAK_WOODEN_DOOR" => Ok(Sound::EntityZombieBreakWoodenDoor { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_CONVERTED_TO_DROWNED" => Ok(Sound::EntityZombieConvertedToDrowned { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_DEATH" => Ok(Sound::EntityZombieDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_DESTROY_EGG" => Ok(Sound::EntityZombieDestroyEgg { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_HORSE_AMBIENT" => Ok(Sound::EntityZombieHorseAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_HORSE_DEATH" => Ok(Sound::EntityZombieHorseDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_HORSE_HURT" => Ok(Sound::EntityZombieHorseHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_HURT" => Ok(Sound::EntityZombieHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_INFECT" => Ok(Sound::EntityZombieInfect { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_STEP" => Ok(Sound::EntityZombieStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_VILLAGER_AMBIENT" => Ok(Sound::EntityZombieVillagerAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_VILLAGER_CONVERTED" => Ok(Sound::EntityZombieVillagerConverted { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_VILLAGER_CURE" => Ok(Sound::EntityZombieVillagerCure { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_VILLAGER_DEATH" => Ok(Sound::EntityZombieVillagerDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_VILLAGER_HURT" => Ok(Sound::EntityZombieVillagerHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIE_VILLAGER_STEP" => Ok(Sound::EntityZombieVillagerStep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIFIED_PIGLIN_AMBIENT" => Ok(Sound::EntityZombifiedPiglinAmbient { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIFIED_PIGLIN_ANGRY" => Ok(Sound::EntityZombifiedPiglinAngry { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIFIED_PIGLIN_DEATH" => Ok(Sound::EntityZombifiedPiglinDeath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ENTITY_ZOMBIFIED_PIGLIN_HURT" => Ok(Sound::EntityZombifiedPiglinHurt { + inner: SoundStruct::from_raw(env, obj)?, + }), + "EVENT_MOB_EFFECT_BAD_OMEN" => Ok(Sound::EventMobEffectBadOmen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "EVENT_MOB_EFFECT_RAID_OMEN" => Ok(Sound::EventMobEffectRaidOmen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "EVENT_MOB_EFFECT_TRIAL_OMEN" => Ok(Sound::EventMobEffectTrialOmen { + inner: SoundStruct::from_raw(env, obj)?, + }), + "EVENT_RAID_HORN" => Ok(Sound::EventRaidHorn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "INTENTIONALLY_EMPTY" => Ok(Sound::IntentionallyEmpty { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_ARMOR_EQUIP_CHAIN" => Ok(Sound::ItemArmorEquipChain { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_ARMOR_EQUIP_DIAMOND" => Ok(Sound::ItemArmorEquipDiamond { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_ARMOR_EQUIP_ELYTRA" => Ok(Sound::ItemArmorEquipElytra { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_ARMOR_EQUIP_GENERIC" => Ok(Sound::ItemArmorEquipGeneric { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_ARMOR_EQUIP_GOLD" => Ok(Sound::ItemArmorEquipGold { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_ARMOR_EQUIP_IRON" => Ok(Sound::ItemArmorEquipIron { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_ARMOR_EQUIP_LEATHER" => Ok(Sound::ItemArmorEquipLeather { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_ARMOR_EQUIP_NETHERITE" => Ok(Sound::ItemArmorEquipNetherite { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_ARMOR_EQUIP_TURTLE" => Ok(Sound::ItemArmorEquipTurtle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_ARMOR_EQUIP_WOLF" => Ok(Sound::ItemArmorEquipWolf { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_ARMOR_UNEQUIP_WOLF" => Ok(Sound::ItemArmorUnequipWolf { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_AXE_SCRAPE" => Ok(Sound::ItemAxeScrape { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_AXE_STRIP" => Ok(Sound::ItemAxeStrip { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_AXE_WAX_OFF" => Ok(Sound::ItemAxeWaxOff { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BONE_MEAL_USE" => Ok(Sound::ItemBoneMealUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BOOK_PAGE_TURN" => Ok(Sound::ItemBookPageTurn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BOOK_PUT" => Ok(Sound::ItemBookPut { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BOTTLE_EMPTY" => Ok(Sound::ItemBottleEmpty { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BOTTLE_FILL" => Ok(Sound::ItemBottleFill { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BOTTLE_FILL_DRAGONBREATH" => Ok(Sound::ItemBottleFillDragonbreath { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BRUSH_BRUSHING_GENERIC" => Ok(Sound::ItemBrushBrushingGeneric { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BRUSH_BRUSHING_GRAVEL" => Ok(Sound::ItemBrushBrushingGravel { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BRUSH_BRUSHING_GRAVEL_COMPLETE" => { + Ok(Sound::ItemBrushBrushingGravelComplete { + inner: SoundStruct::from_raw(env, obj)?, + }) + } + "ITEM_BRUSH_BRUSHING_SAND" => Ok(Sound::ItemBrushBrushingSand { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BRUSH_BRUSHING_SAND_COMPLETE" => Ok(Sound::ItemBrushBrushingSandComplete { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUCKET_EMPTY" => Ok(Sound::ItemBucketEmpty { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUCKET_EMPTY_AXOLOTL" => Ok(Sound::ItemBucketEmptyAxolotl { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUCKET_EMPTY_FISH" => Ok(Sound::ItemBucketEmptyFish { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUCKET_EMPTY_LAVA" => Ok(Sound::ItemBucketEmptyLava { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUCKET_EMPTY_POWDER_SNOW" => Ok(Sound::ItemBucketEmptyPowderSnow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUCKET_EMPTY_TADPOLE" => Ok(Sound::ItemBucketEmptyTadpole { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUCKET_FILL" => Ok(Sound::ItemBucketFill { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUCKET_FILL_AXOLOTL" => Ok(Sound::ItemBucketFillAxolotl { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUCKET_FILL_FISH" => Ok(Sound::ItemBucketFillFish { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUCKET_FILL_LAVA" => Ok(Sound::ItemBucketFillLava { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUCKET_FILL_POWDER_SNOW" => Ok(Sound::ItemBucketFillPowderSnow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUCKET_FILL_TADPOLE" => Ok(Sound::ItemBucketFillTadpole { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUNDLE_DROP_CONTENTS" => Ok(Sound::ItemBundleDropContents { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUNDLE_INSERT" => Ok(Sound::ItemBundleInsert { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_BUNDLE_REMOVE_ONE" => Ok(Sound::ItemBundleRemoveOne { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_CHORUS_FRUIT_TELEPORT" => Ok(Sound::ItemChorusFruitTeleport { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_CROP_PLANT" => Ok(Sound::ItemCropPlant { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_CROSSBOW_HIT" => Ok(Sound::ItemCrossbowHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_CROSSBOW_LOADING_END" => Ok(Sound::ItemCrossbowLoadingEnd { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_CROSSBOW_LOADING_MIDDLE" => Ok(Sound::ItemCrossbowLoadingMiddle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_CROSSBOW_LOADING_START" => Ok(Sound::ItemCrossbowLoadingStart { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_CROSSBOW_QUICK_CHARGE_1" => Ok(Sound::ItemCrossbowQuickCharge1 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_CROSSBOW_QUICK_CHARGE_2" => Ok(Sound::ItemCrossbowQuickCharge2 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_CROSSBOW_QUICK_CHARGE_3" => Ok(Sound::ItemCrossbowQuickCharge3 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_CROSSBOW_SHOOT" => Ok(Sound::ItemCrossbowShoot { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_DYE_USE" => Ok(Sound::ItemDyeUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_ELYTRA_FLYING" => Ok(Sound::ItemElytraFlying { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_FIRECHARGE_USE" => Ok(Sound::ItemFirechargeUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_FLINTANDSTEEL_USE" => Ok(Sound::ItemFlintandsteelUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_GLOW_INK_SAC_USE" => Ok(Sound::ItemGlowInkSacUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_GOAT_HORN_PLAY" => Ok(Sound::ItemGoatHornPlay { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_GOAT_HORN_SOUND_0" => Ok(Sound::ItemGoatHornSound0 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_GOAT_HORN_SOUND_1" => Ok(Sound::ItemGoatHornSound1 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_GOAT_HORN_SOUND_2" => Ok(Sound::ItemGoatHornSound2 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_GOAT_HORN_SOUND_3" => Ok(Sound::ItemGoatHornSound3 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_GOAT_HORN_SOUND_4" => Ok(Sound::ItemGoatHornSound4 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_GOAT_HORN_SOUND_5" => Ok(Sound::ItemGoatHornSound5 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_GOAT_HORN_SOUND_6" => Ok(Sound::ItemGoatHornSound6 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_GOAT_HORN_SOUND_7" => Ok(Sound::ItemGoatHornSound7 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_HOE_TILL" => Ok(Sound::ItemHoeTill { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_HONEYCOMB_WAX_ON" => Ok(Sound::ItemHoneycombWaxOn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_HONEY_BOTTLE_DRINK" => Ok(Sound::ItemHoneyBottleDrink { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_INK_SAC_USE" => Ok(Sound::ItemInkSacUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_LODESTONE_COMPASS_LOCK" => Ok(Sound::ItemLodestoneCompassLock { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_MACE_SMASH_AIR" => Ok(Sound::ItemMaceSmashAir { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_MACE_SMASH_GROUND" => Ok(Sound::ItemMaceSmashGround { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_MACE_SMASH_GROUND_HEAVY" => Ok(Sound::ItemMaceSmashGroundHeavy { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_NETHER_WART_PLANT" => Ok(Sound::ItemNetherWartPlant { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_OMINOUS_BOTTLE_DISPOSE" => Ok(Sound::ItemOminousBottleDispose { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_SHIELD_BLOCK" => Ok(Sound::ItemShieldBlock { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_SHIELD_BREAK" => Ok(Sound::ItemShieldBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_SHOVEL_FLATTEN" => Ok(Sound::ItemShovelFlatten { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_SPYGLASS_STOP_USING" => Ok(Sound::ItemSpyglassStopUsing { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_SPYGLASS_USE" => Ok(Sound::ItemSpyglassUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_TOTEM_USE" => Ok(Sound::ItemTotemUse { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_TRIDENT_HIT" => Ok(Sound::ItemTridentHit { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_TRIDENT_HIT_GROUND" => Ok(Sound::ItemTridentHitGround { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_TRIDENT_RETURN" => Ok(Sound::ItemTridentReturn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_TRIDENT_RIPTIDE_1" => Ok(Sound::ItemTridentRiptide1 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_TRIDENT_RIPTIDE_2" => Ok(Sound::ItemTridentRiptide2 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_TRIDENT_RIPTIDE_3" => Ok(Sound::ItemTridentRiptide3 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_TRIDENT_THROW" => Ok(Sound::ItemTridentThrow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_TRIDENT_THUNDER" => Ok(Sound::ItemTridentThunder { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_WOLF_ARMOR_BREAK" => Ok(Sound::ItemWolfArmorBreak { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_WOLF_ARMOR_CRACK" => Ok(Sound::ItemWolfArmorCrack { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_WOLF_ARMOR_DAMAGE" => Ok(Sound::ItemWolfArmorDamage { + inner: SoundStruct::from_raw(env, obj)?, + }), + "ITEM_WOLF_ARMOR_REPAIR" => Ok(Sound::ItemWolfArmorRepair { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_CREATIVE" => Ok(Sound::MusicCreative { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_CREDITS" => Ok(Sound::MusicCredits { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_11" => Ok(Sound::MusicDisc11 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_13" => Ok(Sound::MusicDisc13 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_5" => Ok(Sound::MusicDisc5 { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_BLOCKS" => Ok(Sound::MusicDiscBlocks { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_CAT" => Ok(Sound::MusicDiscCat { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_CHIRP" => Ok(Sound::MusicDiscChirp { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_CREATOR" => Ok(Sound::MusicDiscCreator { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_CREATOR_MUSIC_BOX" => Ok(Sound::MusicDiscCreatorMusicBox { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_FAR" => Ok(Sound::MusicDiscFar { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_MALL" => Ok(Sound::MusicDiscMall { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_MELLOHI" => Ok(Sound::MusicDiscMellohi { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_OTHERSIDE" => Ok(Sound::MusicDiscOtherside { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_PIGSTEP" => Ok(Sound::MusicDiscPigstep { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_PRECIPICE" => Ok(Sound::MusicDiscPrecipice { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_RELIC" => Ok(Sound::MusicDiscRelic { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_STAL" => Ok(Sound::MusicDiscStal { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_STRAD" => Ok(Sound::MusicDiscStrad { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_WAIT" => Ok(Sound::MusicDiscWait { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_WARD" => Ok(Sound::MusicDiscWard { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_DRAGON" => Ok(Sound::MusicDragon { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_END" => Ok(Sound::MusicEnd { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_GAME" => Ok(Sound::MusicGame { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_MENU" => Ok(Sound::MusicMenu { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_NETHER_BASALT_DELTAS" => Ok(Sound::MusicNetherBasaltDeltas { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_NETHER_CRIMSON_FOREST" => Ok(Sound::MusicNetherCrimsonForest { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_NETHER_NETHER_WASTES" => Ok(Sound::MusicNetherNetherWastes { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_NETHER_SOUL_SAND_VALLEY" => Ok(Sound::MusicNetherSoulSandValley { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_NETHER_WARPED_FOREST" => Ok(Sound::MusicNetherWarpedForest { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_BADLANDS" => Ok(Sound::MusicOverworldBadlands { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_BAMBOO_JUNGLE" => Ok(Sound::MusicOverworldBambooJungle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_CHERRY_GROVE" => Ok(Sound::MusicOverworldCherryGrove { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_DEEP_DARK" => Ok(Sound::MusicOverworldDeepDark { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_DESERT" => Ok(Sound::MusicOverworldDesert { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_DRIPSTONE_CAVES" => Ok(Sound::MusicOverworldDripstoneCaves { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_FLOWER_FOREST" => Ok(Sound::MusicOverworldFlowerForest { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_FOREST" => Ok(Sound::MusicOverworldForest { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_FROZEN_PEAKS" => Ok(Sound::MusicOverworldFrozenPeaks { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_GROVE" => Ok(Sound::MusicOverworldGrove { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_JAGGED_PEAKS" => Ok(Sound::MusicOverworldJaggedPeaks { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_JUNGLE" => Ok(Sound::MusicOverworldJungle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_LUSH_CAVES" => Ok(Sound::MusicOverworldLushCaves { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_MEADOW" => Ok(Sound::MusicOverworldMeadow { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_OLD_GROWTH_TAIGA" => Ok(Sound::MusicOverworldOldGrowthTaiga { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_SNOWY_SLOPES" => Ok(Sound::MusicOverworldSnowySlopes { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_SPARSE_JUNGLE" => Ok(Sound::MusicOverworldSparseJungle { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_STONY_PEAKS" => Ok(Sound::MusicOverworldStonyPeaks { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_OVERWORLD_SWAMP" => Ok(Sound::MusicOverworldSwamp { + inner: SoundStruct::from_raw(env, obj)?, + }), + "MUSIC_UNDER_WATER" => Ok(Sound::MusicUnderWater { + inner: SoundStruct::from_raw(env, obj)?, + }), + "PARTICLE_SOUL_ESCAPE" => Ok(Sound::ParticleSoulEscape { + inner: SoundStruct::from_raw(env, obj)?, + }), + "UI_BUTTON_CLICK" => Ok(Sound::UiButtonClick { + inner: SoundStruct::from_raw(env, obj)?, + }), + "UI_CARTOGRAPHY_TABLE_TAKE_RESULT" => Ok(Sound::UiCartographyTableTakeResult { + inner: SoundStruct::from_raw(env, obj)?, + }), + "UI_LOOM_SELECT_PATTERN" => Ok(Sound::UiLoomSelectPattern { + inner: SoundStruct::from_raw(env, obj)?, + }), + "UI_LOOM_TAKE_RESULT" => Ok(Sound::UiLoomTakeResult { + inner: SoundStruct::from_raw(env, obj)?, + }), + "UI_STONECUTTER_SELECT_RECIPE" => Ok(Sound::UiStonecutterSelectRecipe { + inner: SoundStruct::from_raw(env, obj)?, + }), + "UI_STONECUTTER_TAKE_RESULT" => Ok(Sound::UiStonecutterTakeResult { + inner: SoundStruct::from_raw(env, obj)?, + }), + "UI_TOAST_CHALLENGE_COMPLETE" => Ok(Sound::UiToastChallengeComplete { + inner: SoundStruct::from_raw(env, obj)?, + }), + "UI_TOAST_IN" => Ok(Sound::UiToastIn { + inner: SoundStruct::from_raw(env, obj)?, + }), + "UI_TOAST_OUT" => Ok(Sound::UiToastOut { + inner: SoundStruct::from_raw(env, obj)?, + }), + "WEATHER_RAIN" => Ok(Sound::WeatherRain { + inner: SoundStruct::from_raw(env, obj)?, + }), + "WEATHER_RAIN_ABOVE" => Ok(Sound::WeatherRainAbove { + inner: SoundStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for SoundStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for SoundStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate SoundStruct from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Sound")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a SoundStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> SoundStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let cls = jni.find_class("org/bukkit/Sound"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::Sound::from_raw(&jni, obj) + } + + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +pub enum SandstoneType<'mc> { + Cracked { inner: SandstoneTypeStruct<'mc> }, + Glyphed { inner: SandstoneTypeStruct<'mc> }, + Smooth { inner: SandstoneTypeStruct<'mc> }, +} +impl<'mc> std::fmt::Display for SandstoneType<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + SandstoneType::Cracked { .. } => f.write_str("CRACKED"), + SandstoneType::Glyphed { .. } => f.write_str("GLYPHED"), + SandstoneType::Smooth { .. } => f.write_str("SMOOTH"), + } + } +} +impl<'mc> std::ops::Deref for SandstoneType<'mc> { + type Target = SandstoneTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + SandstoneType::Cracked { inner } => inner, + SandstoneType::Glyphed { inner } => inner, + SandstoneType::Smooth { inner } => inner, + } + } +} + +impl<'mc> SandstoneType<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/SandstoneType"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/SandstoneType;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "CRACKED" => Ok(SandstoneType::Cracked { + inner: SandstoneTypeStruct::from_raw(env, obj)?, + }), + "GLYPHED" => Ok(SandstoneType::Glyphed { + inner: SandstoneTypeStruct::from_raw(env, obj)?, + }), + "SMOOTH" => Ok(SandstoneType::Smooth { + inner: SandstoneTypeStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct SandstoneTypeStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for SandstoneType<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Cracked { inner } => inner.0.clone(), + Self::Glyphed { inner } => inner.0.clone(), + Self::Smooth { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Cracked { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Glyphed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Smooth { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for SandstoneType<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate SandstoneType from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/SandstoneType")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a SandstoneType object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "CRACKED" => Ok(SandstoneType::Cracked { + inner: SandstoneTypeStruct::from_raw(env, obj)?, + }), + "GLYPHED" => Ok(SandstoneType::Glyphed { + inner: SandstoneTypeStruct::from_raw(env, obj)?, + }), + "SMOOTH" => Ok(SandstoneType::Smooth { + inner: SandstoneTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for SandstoneTypeStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for SandstoneTypeStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate SandstoneTypeStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/SandstoneType")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a SandstoneTypeStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> SandstoneTypeStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/SandstoneType;"); + let cls = jni.find_class("org/bukkit/SandstoneType"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::SandstoneType::from_raw(&jni, obj) + } + #[deprecated] + /// Gets the associated data value representing this type of sandstone + pub fn data(&self) -> Result> { + let sig = String::from("()B"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.b()?) + } + #[deprecated] + /// Gets the type of sandstone with the given data value + pub fn get_by_data( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + data: i8, + ) -> Result>, Box> { + let sig = String::from("(B)Lorg/bukkit/SandstoneType;"); + let val_1 = jni::objects::JValueGen::Byte(data); + let cls = jni.find_class("org/bukkit/SandstoneType"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getByData", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::SandstoneType::from_raw(&jni, obj)?)) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct Registry<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Registry<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Registry<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Registry from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Registry")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Registry object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Registry<'mc> { + /// Get the object by its key. + pub fn get( + &self, + key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)LT;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(key.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "get", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) + } + /// Get the object by its key. + /// If there is no object with the given key, an exception will be thrown. + pub fn get_or_throw( + &self, + key: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)LT;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(key.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getOrThrow", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) + } + /// Attempts to match the registered object with the given key. + /// + /// This will attempt to find a reasonable match based on the provided input + /// and may do so through unspecified means. + pub fn get_match( + &self, + input: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;)LT;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(input.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "match", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct RegistrySimpleRegistry<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for RegistrySimpleRegistry<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for RegistrySimpleRegistry<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate RegistrySimpleRegistry from null object." + ) + .into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Registry/SimpleRegistry")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a RegistrySimpleRegistry object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> RegistrySimpleRegistry<'mc> { + pub fn get( + &self, + key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)LT;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(key.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "get", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) + } + + pub fn get_or_throw( + &self, + key: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)LT;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(key.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getOrThrow", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) + } + + pub fn iterator( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Iterator;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "iterator", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaIterator::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + #[deprecated] + + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/Class;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(unsafe { jni::objects::JClass::from_raw(res.as_jni().l) }) + } + /// Attempts to match the registered object with the given key. + /// + /// This will attempt to find a reasonable match based on the provided input + /// and may do so through unspecified means. + pub fn get_match( + &self, + input: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;)LT;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(input.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "match", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for RegistrySimpleRegistry<'mc> { + fn into(self) -> crate::Registry<'mc> { + crate::Registry::from_raw(&self.jni_ref(), self.1) + .expect("Error converting RegistrySimpleRegistry into crate::Registry") + } +} +pub enum Particle<'mc> { + Poof { inner: ParticleStruct<'mc> }, + Explosion { inner: ParticleStruct<'mc> }, + ExplosionEmitter { inner: ParticleStruct<'mc> }, + Firework { inner: ParticleStruct<'mc> }, + Bubble { inner: ParticleStruct<'mc> }, + Splash { inner: ParticleStruct<'mc> }, + Fishing { inner: ParticleStruct<'mc> }, + Underwater { inner: ParticleStruct<'mc> }, + Crit { inner: ParticleStruct<'mc> }, + EnchantedHit { inner: ParticleStruct<'mc> }, + Smoke { inner: ParticleStruct<'mc> }, + LargeSmoke { inner: ParticleStruct<'mc> }, + Effect { inner: ParticleStruct<'mc> }, + InstantEffect { inner: ParticleStruct<'mc> }, + EntityEffect { inner: ParticleStruct<'mc> }, + Witch { inner: ParticleStruct<'mc> }, + DrippingWater { inner: ParticleStruct<'mc> }, + DrippingLava { inner: ParticleStruct<'mc> }, + AngryVillager { inner: ParticleStruct<'mc> }, + HappyVillager { inner: ParticleStruct<'mc> }, + Mycelium { inner: ParticleStruct<'mc> }, + Note { inner: ParticleStruct<'mc> }, + Portal { inner: ParticleStruct<'mc> }, + Enchant { inner: ParticleStruct<'mc> }, + Flame { inner: ParticleStruct<'mc> }, + Lava { inner: ParticleStruct<'mc> }, + Cloud { inner: ParticleStruct<'mc> }, + Dust { inner: ParticleStruct<'mc> }, + ItemSnowball { inner: ParticleStruct<'mc> }, + ItemSlime { inner: ParticleStruct<'mc> }, + Heart { inner: ParticleStruct<'mc> }, + Item { inner: ParticleStruct<'mc> }, + Block { inner: ParticleStruct<'mc> }, + Rain { inner: ParticleStruct<'mc> }, + ElderGuardian { inner: ParticleStruct<'mc> }, + DragonBreath { inner: ParticleStruct<'mc> }, + EndRod { inner: ParticleStruct<'mc> }, + DamageIndicator { inner: ParticleStruct<'mc> }, + SweepAttack { inner: ParticleStruct<'mc> }, + FallingDust { inner: ParticleStruct<'mc> }, + TotemOfUndying { inner: ParticleStruct<'mc> }, + Spit { inner: ParticleStruct<'mc> }, + SquidInk { inner: ParticleStruct<'mc> }, + BubblePop { inner: ParticleStruct<'mc> }, + CurrentDown { inner: ParticleStruct<'mc> }, + BubbleColumnUp { inner: ParticleStruct<'mc> }, + Nautilus { inner: ParticleStruct<'mc> }, + Dolphin { inner: ParticleStruct<'mc> }, + Sneeze { inner: ParticleStruct<'mc> }, + CampfireCosySmoke { inner: ParticleStruct<'mc> }, + CampfireSignalSmoke { inner: ParticleStruct<'mc> }, + Composter { inner: ParticleStruct<'mc> }, + Flash { inner: ParticleStruct<'mc> }, + FallingLava { inner: ParticleStruct<'mc> }, + LandingLava { inner: ParticleStruct<'mc> }, + FallingWater { inner: ParticleStruct<'mc> }, + DrippingHoney { inner: ParticleStruct<'mc> }, + FallingHoney { inner: ParticleStruct<'mc> }, + LandingHoney { inner: ParticleStruct<'mc> }, + FallingNectar { inner: ParticleStruct<'mc> }, + SoulFireFlame { inner: ParticleStruct<'mc> }, + Ash { inner: ParticleStruct<'mc> }, + CrimsonSpore { inner: ParticleStruct<'mc> }, + WarpedSpore { inner: ParticleStruct<'mc> }, + Soul { inner: ParticleStruct<'mc> }, + DrippingObsidianTear { inner: ParticleStruct<'mc> }, + FallingObsidianTear { inner: ParticleStruct<'mc> }, + LandingObsidianTear { inner: ParticleStruct<'mc> }, + ReversePortal { inner: ParticleStruct<'mc> }, + WhiteAsh { inner: ParticleStruct<'mc> }, + DustColorTransition { inner: ParticleStruct<'mc> }, + Vibration { inner: ParticleStruct<'mc> }, + FallingSporeBlossom { inner: ParticleStruct<'mc> }, + SporeBlossomAir { inner: ParticleStruct<'mc> }, + SmallFlame { inner: ParticleStruct<'mc> }, + Snowflake { inner: ParticleStruct<'mc> }, + DrippingDripstoneLava { inner: ParticleStruct<'mc> }, + FallingDripstoneLava { inner: ParticleStruct<'mc> }, + DrippingDripstoneWater { inner: ParticleStruct<'mc> }, + FallingDripstoneWater { inner: ParticleStruct<'mc> }, + GlowSquidInk { inner: ParticleStruct<'mc> }, + Glow { inner: ParticleStruct<'mc> }, + WaxOn { inner: ParticleStruct<'mc> }, + WaxOff { inner: ParticleStruct<'mc> }, + ElectricSpark { inner: ParticleStruct<'mc> }, + Scrape { inner: ParticleStruct<'mc> }, + SonicBoom { inner: ParticleStruct<'mc> }, + SculkSoul { inner: ParticleStruct<'mc> }, + SculkCharge { inner: ParticleStruct<'mc> }, + SculkChargePop { inner: ParticleStruct<'mc> }, + Shriek { inner: ParticleStruct<'mc> }, + CherryLeaves { inner: ParticleStruct<'mc> }, + EggCrack { inner: ParticleStruct<'mc> }, + DustPlume { inner: ParticleStruct<'mc> }, + WhiteSmoke { inner: ParticleStruct<'mc> }, + Gust { inner: ParticleStruct<'mc> }, + SmallGust { inner: ParticleStruct<'mc> }, + GustEmitterLarge { inner: ParticleStruct<'mc> }, + GustEmitterSmall { inner: ParticleStruct<'mc> }, + TrialSpawnerDetection { inner: ParticleStruct<'mc> }, + TrialSpawnerDetectionOminous { inner: ParticleStruct<'mc> }, + VaultConnection { inner: ParticleStruct<'mc> }, + Infested { inner: ParticleStruct<'mc> }, + ItemCobweb { inner: ParticleStruct<'mc> }, + DustPillar { inner: ParticleStruct<'mc> }, + OminousSpawning { inner: ParticleStruct<'mc> }, + RaidOmen { inner: ParticleStruct<'mc> }, + TrialOmen { inner: ParticleStruct<'mc> }, + BlockMarker { inner: ParticleStruct<'mc> }, +} +impl<'mc> std::fmt::Display for Particle<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Particle::Poof { .. } => f.write_str("POOF"), + Particle::Explosion { .. } => f.write_str("EXPLOSION"), + Particle::ExplosionEmitter { .. } => f.write_str("EXPLOSION_EMITTER"), + Particle::Firework { .. } => f.write_str("FIREWORK"), + Particle::Bubble { .. } => f.write_str("BUBBLE"), + Particle::Splash { .. } => f.write_str("SPLASH"), + Particle::Fishing { .. } => f.write_str("FISHING"), + Particle::Underwater { .. } => f.write_str("UNDERWATER"), + Particle::Crit { .. } => f.write_str("CRIT"), + Particle::EnchantedHit { .. } => f.write_str("ENCHANTED_HIT"), + Particle::Smoke { .. } => f.write_str("SMOKE"), + Particle::LargeSmoke { .. } => f.write_str("LARGE_SMOKE"), + Particle::Effect { .. } => f.write_str("EFFECT"), + Particle::InstantEffect { .. } => f.write_str("INSTANT_EFFECT"), + Particle::EntityEffect { .. } => f.write_str("ENTITY_EFFECT"), + Particle::Witch { .. } => f.write_str("WITCH"), + Particle::DrippingWater { .. } => f.write_str("DRIPPING_WATER"), + Particle::DrippingLava { .. } => f.write_str("DRIPPING_LAVA"), + Particle::AngryVillager { .. } => f.write_str("ANGRY_VILLAGER"), + Particle::HappyVillager { .. } => f.write_str("HAPPY_VILLAGER"), + Particle::Mycelium { .. } => f.write_str("MYCELIUM"), + Particle::Note { .. } => f.write_str("NOTE"), + Particle::Portal { .. } => f.write_str("PORTAL"), + Particle::Enchant { .. } => f.write_str("ENCHANT"), + Particle::Flame { .. } => f.write_str("FLAME"), + Particle::Lava { .. } => f.write_str("LAVA"), + Particle::Cloud { .. } => f.write_str("CLOUD"), + Particle::Dust { .. } => f.write_str("DUST"), + Particle::ItemSnowball { .. } => f.write_str("ITEM_SNOWBALL"), + Particle::ItemSlime { .. } => f.write_str("ITEM_SLIME"), + Particle::Heart { .. } => f.write_str("HEART"), + Particle::Item { .. } => f.write_str("ITEM"), + Particle::Block { .. } => f.write_str("BLOCK"), + Particle::Rain { .. } => f.write_str("RAIN"), + Particle::ElderGuardian { .. } => f.write_str("ELDER_GUARDIAN"), + Particle::DragonBreath { .. } => f.write_str("DRAGON_BREATH"), + Particle::EndRod { .. } => f.write_str("END_ROD"), + Particle::DamageIndicator { .. } => f.write_str("DAMAGE_INDICATOR"), + Particle::SweepAttack { .. } => f.write_str("SWEEP_ATTACK"), + Particle::FallingDust { .. } => f.write_str("FALLING_DUST"), + Particle::TotemOfUndying { .. } => f.write_str("TOTEM_OF_UNDYING"), + Particle::Spit { .. } => f.write_str("SPIT"), + Particle::SquidInk { .. } => f.write_str("SQUID_INK"), + Particle::BubblePop { .. } => f.write_str("BUBBLE_POP"), + Particle::CurrentDown { .. } => f.write_str("CURRENT_DOWN"), + Particle::BubbleColumnUp { .. } => f.write_str("BUBBLE_COLUMN_UP"), + Particle::Nautilus { .. } => f.write_str("NAUTILUS"), + Particle::Dolphin { .. } => f.write_str("DOLPHIN"), + Particle::Sneeze { .. } => f.write_str("SNEEZE"), + Particle::CampfireCosySmoke { .. } => f.write_str("CAMPFIRE_COSY_SMOKE"), + Particle::CampfireSignalSmoke { .. } => f.write_str("CAMPFIRE_SIGNAL_SMOKE"), + Particle::Composter { .. } => f.write_str("COMPOSTER"), + Particle::Flash { .. } => f.write_str("FLASH"), + Particle::FallingLava { .. } => f.write_str("FALLING_LAVA"), + Particle::LandingLava { .. } => f.write_str("LANDING_LAVA"), + Particle::FallingWater { .. } => f.write_str("FALLING_WATER"), + Particle::DrippingHoney { .. } => f.write_str("DRIPPING_HONEY"), + Particle::FallingHoney { .. } => f.write_str("FALLING_HONEY"), + Particle::LandingHoney { .. } => f.write_str("LANDING_HONEY"), + Particle::FallingNectar { .. } => f.write_str("FALLING_NECTAR"), + Particle::SoulFireFlame { .. } => f.write_str("SOUL_FIRE_FLAME"), + Particle::Ash { .. } => f.write_str("ASH"), + Particle::CrimsonSpore { .. } => f.write_str("CRIMSON_SPORE"), + Particle::WarpedSpore { .. } => f.write_str("WARPED_SPORE"), + Particle::Soul { .. } => f.write_str("SOUL"), + Particle::DrippingObsidianTear { .. } => f.write_str("DRIPPING_OBSIDIAN_TEAR"), + Particle::FallingObsidianTear { .. } => f.write_str("FALLING_OBSIDIAN_TEAR"), + Particle::LandingObsidianTear { .. } => f.write_str("LANDING_OBSIDIAN_TEAR"), + Particle::ReversePortal { .. } => f.write_str("REVERSE_PORTAL"), + Particle::WhiteAsh { .. } => f.write_str("WHITE_ASH"), + Particle::DustColorTransition { .. } => f.write_str("DUST_COLOR_TRANSITION"), + Particle::Vibration { .. } => f.write_str("VIBRATION"), + Particle::FallingSporeBlossom { .. } => f.write_str("FALLING_SPORE_BLOSSOM"), + Particle::SporeBlossomAir { .. } => f.write_str("SPORE_BLOSSOM_AIR"), + Particle::SmallFlame { .. } => f.write_str("SMALL_FLAME"), + Particle::Snowflake { .. } => f.write_str("SNOWFLAKE"), + Particle::DrippingDripstoneLava { .. } => f.write_str("DRIPPING_DRIPSTONE_LAVA"), + Particle::FallingDripstoneLava { .. } => f.write_str("FALLING_DRIPSTONE_LAVA"), + Particle::DrippingDripstoneWater { .. } => f.write_str("DRIPPING_DRIPSTONE_WATER"), + Particle::FallingDripstoneWater { .. } => f.write_str("FALLING_DRIPSTONE_WATER"), + Particle::GlowSquidInk { .. } => f.write_str("GLOW_SQUID_INK"), + Particle::Glow { .. } => f.write_str("GLOW"), + Particle::WaxOn { .. } => f.write_str("WAX_ON"), + Particle::WaxOff { .. } => f.write_str("WAX_OFF"), + Particle::ElectricSpark { .. } => f.write_str("ELECTRIC_SPARK"), + Particle::Scrape { .. } => f.write_str("SCRAPE"), + Particle::SonicBoom { .. } => f.write_str("SONIC_BOOM"), + Particle::SculkSoul { .. } => f.write_str("SCULK_SOUL"), + Particle::SculkCharge { .. } => f.write_str("SCULK_CHARGE"), + Particle::SculkChargePop { .. } => f.write_str("SCULK_CHARGE_POP"), + Particle::Shriek { .. } => f.write_str("SHRIEK"), + Particle::CherryLeaves { .. } => f.write_str("CHERRY_LEAVES"), + Particle::EggCrack { .. } => f.write_str("EGG_CRACK"), + Particle::DustPlume { .. } => f.write_str("DUST_PLUME"), + Particle::WhiteSmoke { .. } => f.write_str("WHITE_SMOKE"), + Particle::Gust { .. } => f.write_str("GUST"), + Particle::SmallGust { .. } => f.write_str("SMALL_GUST"), + Particle::GustEmitterLarge { .. } => f.write_str("GUST_EMITTER_LARGE"), + Particle::GustEmitterSmall { .. } => f.write_str("GUST_EMITTER_SMALL"), + Particle::TrialSpawnerDetection { .. } => f.write_str("TRIAL_SPAWNER_DETECTION"), + Particle::TrialSpawnerDetectionOminous { .. } => { + f.write_str("TRIAL_SPAWNER_DETECTION_OMINOUS") + } + Particle::VaultConnection { .. } => f.write_str("VAULT_CONNECTION"), + Particle::Infested { .. } => f.write_str("INFESTED"), + Particle::ItemCobweb { .. } => f.write_str("ITEM_COBWEB"), + Particle::DustPillar { .. } => f.write_str("DUST_PILLAR"), + Particle::OminousSpawning { .. } => f.write_str("OMINOUS_SPAWNING"), + Particle::RaidOmen { .. } => f.write_str("RAID_OMEN"), + Particle::TrialOmen { .. } => f.write_str("TRIAL_OMEN"), + Particle::BlockMarker { .. } => f.write_str("BLOCK_MARKER"), + } + } +} +impl<'mc> std::ops::Deref for Particle<'mc> { + type Target = ParticleStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + Particle::Poof { inner } => inner, + Particle::Explosion { inner } => inner, + Particle::ExplosionEmitter { inner } => inner, + Particle::Firework { inner } => inner, + Particle::Bubble { inner } => inner, + Particle::Splash { inner } => inner, + Particle::Fishing { inner } => inner, + Particle::Underwater { inner } => inner, + Particle::Crit { inner } => inner, + Particle::EnchantedHit { inner } => inner, + Particle::Smoke { inner } => inner, + Particle::LargeSmoke { inner } => inner, + Particle::Effect { inner } => inner, + Particle::InstantEffect { inner } => inner, + Particle::EntityEffect { inner } => inner, + Particle::Witch { inner } => inner, + Particle::DrippingWater { inner } => inner, + Particle::DrippingLava { inner } => inner, + Particle::AngryVillager { inner } => inner, + Particle::HappyVillager { inner } => inner, + Particle::Mycelium { inner } => inner, + Particle::Note { inner } => inner, + Particle::Portal { inner } => inner, + Particle::Enchant { inner } => inner, + Particle::Flame { inner } => inner, + Particle::Lava { inner } => inner, + Particle::Cloud { inner } => inner, + Particle::Dust { inner } => inner, + Particle::ItemSnowball { inner } => inner, + Particle::ItemSlime { inner } => inner, + Particle::Heart { inner } => inner, + Particle::Item { inner } => inner, + Particle::Block { inner } => inner, + Particle::Rain { inner } => inner, + Particle::ElderGuardian { inner } => inner, + Particle::DragonBreath { inner } => inner, + Particle::EndRod { inner } => inner, + Particle::DamageIndicator { inner } => inner, + Particle::SweepAttack { inner } => inner, + Particle::FallingDust { inner } => inner, + Particle::TotemOfUndying { inner } => inner, + Particle::Spit { inner } => inner, + Particle::SquidInk { inner } => inner, + Particle::BubblePop { inner } => inner, + Particle::CurrentDown { inner } => inner, + Particle::BubbleColumnUp { inner } => inner, + Particle::Nautilus { inner } => inner, + Particle::Dolphin { inner } => inner, + Particle::Sneeze { inner } => inner, + Particle::CampfireCosySmoke { inner } => inner, + Particle::CampfireSignalSmoke { inner } => inner, + Particle::Composter { inner } => inner, + Particle::Flash { inner } => inner, + Particle::FallingLava { inner } => inner, + Particle::LandingLava { inner } => inner, + Particle::FallingWater { inner } => inner, + Particle::DrippingHoney { inner } => inner, + Particle::FallingHoney { inner } => inner, + Particle::LandingHoney { inner } => inner, + Particle::FallingNectar { inner } => inner, + Particle::SoulFireFlame { inner } => inner, + Particle::Ash { inner } => inner, + Particle::CrimsonSpore { inner } => inner, + Particle::WarpedSpore { inner } => inner, + Particle::Soul { inner } => inner, + Particle::DrippingObsidianTear { inner } => inner, + Particle::FallingObsidianTear { inner } => inner, + Particle::LandingObsidianTear { inner } => inner, + Particle::ReversePortal { inner } => inner, + Particle::WhiteAsh { inner } => inner, + Particle::DustColorTransition { inner } => inner, + Particle::Vibration { inner } => inner, + Particle::FallingSporeBlossom { inner } => inner, + Particle::SporeBlossomAir { inner } => inner, + Particle::SmallFlame { inner } => inner, + Particle::Snowflake { inner } => inner, + Particle::DrippingDripstoneLava { inner } => inner, + Particle::FallingDripstoneLava { inner } => inner, + Particle::DrippingDripstoneWater { inner } => inner, + Particle::FallingDripstoneWater { inner } => inner, + Particle::GlowSquidInk { inner } => inner, + Particle::Glow { inner } => inner, + Particle::WaxOn { inner } => inner, + Particle::WaxOff { inner } => inner, + Particle::ElectricSpark { inner } => inner, + Particle::Scrape { inner } => inner, + Particle::SonicBoom { inner } => inner, + Particle::SculkSoul { inner } => inner, + Particle::SculkCharge { inner } => inner, + Particle::SculkChargePop { inner } => inner, + Particle::Shriek { inner } => inner, + Particle::CherryLeaves { inner } => inner, + Particle::EggCrack { inner } => inner, + Particle::DustPlume { inner } => inner, + Particle::WhiteSmoke { inner } => inner, + Particle::Gust { inner } => inner, + Particle::SmallGust { inner } => inner, + Particle::GustEmitterLarge { inner } => inner, + Particle::GustEmitterSmall { inner } => inner, + Particle::TrialSpawnerDetection { inner } => inner, + Particle::TrialSpawnerDetectionOminous { inner } => inner, + Particle::VaultConnection { inner } => inner, + Particle::Infested { inner } => inner, + Particle::ItemCobweb { inner } => inner, + Particle::DustPillar { inner } => inner, + Particle::OminousSpawning { inner } => inner, + Particle::RaidOmen { inner } => inner, + Particle::TrialOmen { inner } => inner, + Particle::BlockMarker { inner } => inner, + } + } +} + +impl<'mc> Particle<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/Particle"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/Particle;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "POOF" => Ok(Particle::Poof { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "EXPLOSION" => Ok(Particle::Explosion { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "EXPLOSION_EMITTER" => Ok(Particle::ExplosionEmitter { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FIREWORK" => Ok(Particle::Firework { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "BUBBLE" => Ok(Particle::Bubble { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SPLASH" => Ok(Particle::Splash { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FISHING" => Ok(Particle::Fishing { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "UNDERWATER" => Ok(Particle::Underwater { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "CRIT" => Ok(Particle::Crit { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "ENCHANTED_HIT" => Ok(Particle::EnchantedHit { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SMOKE" => Ok(Particle::Smoke { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "LARGE_SMOKE" => Ok(Particle::LargeSmoke { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "EFFECT" => Ok(Particle::Effect { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "INSTANT_EFFECT" => Ok(Particle::InstantEffect { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "ENTITY_EFFECT" => Ok(Particle::EntityEffect { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "WITCH" => Ok(Particle::Witch { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DRIPPING_WATER" => Ok(Particle::DrippingWater { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DRIPPING_LAVA" => Ok(Particle::DrippingLava { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "ANGRY_VILLAGER" => Ok(Particle::AngryVillager { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "HAPPY_VILLAGER" => Ok(Particle::HappyVillager { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "MYCELIUM" => Ok(Particle::Mycelium { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "NOTE" => Ok(Particle::Note { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "PORTAL" => Ok(Particle::Portal { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "ENCHANT" => Ok(Particle::Enchant { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FLAME" => Ok(Particle::Flame { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "LAVA" => Ok(Particle::Lava { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "CLOUD" => Ok(Particle::Cloud { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DUST" => Ok(Particle::Dust { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "ITEM_SNOWBALL" => Ok(Particle::ItemSnowball { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "ITEM_SLIME" => Ok(Particle::ItemSlime { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "HEART" => Ok(Particle::Heart { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "ITEM" => Ok(Particle::Item { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "BLOCK" => Ok(Particle::Block { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "RAIN" => Ok(Particle::Rain { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "ELDER_GUARDIAN" => Ok(Particle::ElderGuardian { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DRAGON_BREATH" => Ok(Particle::DragonBreath { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "END_ROD" => Ok(Particle::EndRod { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DAMAGE_INDICATOR" => Ok(Particle::DamageIndicator { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SWEEP_ATTACK" => Ok(Particle::SweepAttack { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FALLING_DUST" => Ok(Particle::FallingDust { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "TOTEM_OF_UNDYING" => Ok(Particle::TotemOfUndying { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SPIT" => Ok(Particle::Spit { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SQUID_INK" => Ok(Particle::SquidInk { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "BUBBLE_POP" => Ok(Particle::BubblePop { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "CURRENT_DOWN" => Ok(Particle::CurrentDown { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "BUBBLE_COLUMN_UP" => Ok(Particle::BubbleColumnUp { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "NAUTILUS" => Ok(Particle::Nautilus { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DOLPHIN" => Ok(Particle::Dolphin { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SNEEZE" => Ok(Particle::Sneeze { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "CAMPFIRE_COSY_SMOKE" => Ok(Particle::CampfireCosySmoke { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "CAMPFIRE_SIGNAL_SMOKE" => Ok(Particle::CampfireSignalSmoke { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "COMPOSTER" => Ok(Particle::Composter { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FLASH" => Ok(Particle::Flash { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FALLING_LAVA" => Ok(Particle::FallingLava { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "LANDING_LAVA" => Ok(Particle::LandingLava { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FALLING_WATER" => Ok(Particle::FallingWater { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DRIPPING_HONEY" => Ok(Particle::DrippingHoney { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FALLING_HONEY" => Ok(Particle::FallingHoney { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "LANDING_HONEY" => Ok(Particle::LandingHoney { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FALLING_NECTAR" => Ok(Particle::FallingNectar { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SOUL_FIRE_FLAME" => Ok(Particle::SoulFireFlame { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "ASH" => Ok(Particle::Ash { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "CRIMSON_SPORE" => Ok(Particle::CrimsonSpore { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "WARPED_SPORE" => Ok(Particle::WarpedSpore { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SOUL" => Ok(Particle::Soul { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DRIPPING_OBSIDIAN_TEAR" => Ok(Particle::DrippingObsidianTear { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FALLING_OBSIDIAN_TEAR" => Ok(Particle::FallingObsidianTear { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "LANDING_OBSIDIAN_TEAR" => Ok(Particle::LandingObsidianTear { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "REVERSE_PORTAL" => Ok(Particle::ReversePortal { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "WHITE_ASH" => Ok(Particle::WhiteAsh { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DUST_COLOR_TRANSITION" => Ok(Particle::DustColorTransition { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "VIBRATION" => Ok(Particle::Vibration { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FALLING_SPORE_BLOSSOM" => Ok(Particle::FallingSporeBlossom { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SPORE_BLOSSOM_AIR" => Ok(Particle::SporeBlossomAir { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SMALL_FLAME" => Ok(Particle::SmallFlame { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SNOWFLAKE" => Ok(Particle::Snowflake { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DRIPPING_DRIPSTONE_LAVA" => Ok(Particle::DrippingDripstoneLava { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FALLING_DRIPSTONE_LAVA" => Ok(Particle::FallingDripstoneLava { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DRIPPING_DRIPSTONE_WATER" => Ok(Particle::DrippingDripstoneWater { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FALLING_DRIPSTONE_WATER" => Ok(Particle::FallingDripstoneWater { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "GLOW_SQUID_INK" => Ok(Particle::GlowSquidInk { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "GLOW" => Ok(Particle::Glow { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "WAX_ON" => Ok(Particle::WaxOn { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "WAX_OFF" => Ok(Particle::WaxOff { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "ELECTRIC_SPARK" => Ok(Particle::ElectricSpark { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SCRAPE" => Ok(Particle::Scrape { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SONIC_BOOM" => Ok(Particle::SonicBoom { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SCULK_SOUL" => Ok(Particle::SculkSoul { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SCULK_CHARGE" => Ok(Particle::SculkCharge { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SCULK_CHARGE_POP" => Ok(Particle::SculkChargePop { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SHRIEK" => Ok(Particle::Shriek { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "CHERRY_LEAVES" => Ok(Particle::CherryLeaves { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "EGG_CRACK" => Ok(Particle::EggCrack { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DUST_PLUME" => Ok(Particle::DustPlume { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "WHITE_SMOKE" => Ok(Particle::WhiteSmoke { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "GUST" => Ok(Particle::Gust { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SMALL_GUST" => Ok(Particle::SmallGust { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "GUST_EMITTER_LARGE" => Ok(Particle::GustEmitterLarge { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "GUST_EMITTER_SMALL" => Ok(Particle::GustEmitterSmall { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "TRIAL_SPAWNER_DETECTION" => Ok(Particle::TrialSpawnerDetection { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "TRIAL_SPAWNER_DETECTION_OMINOUS" => Ok(Particle::TrialSpawnerDetectionOminous { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "VAULT_CONNECTION" => Ok(Particle::VaultConnection { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "INFESTED" => Ok(Particle::Infested { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "ITEM_COBWEB" => Ok(Particle::ItemCobweb { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DUST_PILLAR" => Ok(Particle::DustPillar { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "OMINOUS_SPAWNING" => Ok(Particle::OminousSpawning { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "RAID_OMEN" => Ok(Particle::RaidOmen { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "TRIAL_OMEN" => Ok(Particle::TrialOmen { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "BLOCK_MARKER" => Ok(Particle::BlockMarker { + inner: ParticleStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct ParticleStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Particle<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Poof { inner } => inner.0.clone(), + Self::Explosion { inner } => inner.0.clone(), + Self::ExplosionEmitter { inner } => inner.0.clone(), + Self::Firework { inner } => inner.0.clone(), + Self::Bubble { inner } => inner.0.clone(), + Self::Splash { inner } => inner.0.clone(), + Self::Fishing { inner } => inner.0.clone(), + Self::Underwater { inner } => inner.0.clone(), + Self::Crit { inner } => inner.0.clone(), + Self::EnchantedHit { inner } => inner.0.clone(), + Self::Smoke { inner } => inner.0.clone(), + Self::LargeSmoke { inner } => inner.0.clone(), + Self::Effect { inner } => inner.0.clone(), + Self::InstantEffect { inner } => inner.0.clone(), + Self::EntityEffect { inner } => inner.0.clone(), + Self::Witch { inner } => inner.0.clone(), + Self::DrippingWater { inner } => inner.0.clone(), + Self::DrippingLava { inner } => inner.0.clone(), + Self::AngryVillager { inner } => inner.0.clone(), + Self::HappyVillager { inner } => inner.0.clone(), + Self::Mycelium { inner } => inner.0.clone(), + Self::Note { inner } => inner.0.clone(), + Self::Portal { inner } => inner.0.clone(), + Self::Enchant { inner } => inner.0.clone(), + Self::Flame { inner } => inner.0.clone(), + Self::Lava { inner } => inner.0.clone(), + Self::Cloud { inner } => inner.0.clone(), + Self::Dust { inner } => inner.0.clone(), + Self::ItemSnowball { inner } => inner.0.clone(), + Self::ItemSlime { inner } => inner.0.clone(), + Self::Heart { inner } => inner.0.clone(), + Self::Item { inner } => inner.0.clone(), + Self::Block { inner } => inner.0.clone(), + Self::Rain { inner } => inner.0.clone(), + Self::ElderGuardian { inner } => inner.0.clone(), + Self::DragonBreath { inner } => inner.0.clone(), + Self::EndRod { inner } => inner.0.clone(), + Self::DamageIndicator { inner } => inner.0.clone(), + Self::SweepAttack { inner } => inner.0.clone(), + Self::FallingDust { inner } => inner.0.clone(), + Self::TotemOfUndying { inner } => inner.0.clone(), + Self::Spit { inner } => inner.0.clone(), + Self::SquidInk { inner } => inner.0.clone(), + Self::BubblePop { inner } => inner.0.clone(), + Self::CurrentDown { inner } => inner.0.clone(), + Self::BubbleColumnUp { inner } => inner.0.clone(), + Self::Nautilus { inner } => inner.0.clone(), + Self::Dolphin { inner } => inner.0.clone(), + Self::Sneeze { inner } => inner.0.clone(), + Self::CampfireCosySmoke { inner } => inner.0.clone(), + Self::CampfireSignalSmoke { inner } => inner.0.clone(), + Self::Composter { inner } => inner.0.clone(), + Self::Flash { inner } => inner.0.clone(), + Self::FallingLava { inner } => inner.0.clone(), + Self::LandingLava { inner } => inner.0.clone(), + Self::FallingWater { inner } => inner.0.clone(), + Self::DrippingHoney { inner } => inner.0.clone(), + Self::FallingHoney { inner } => inner.0.clone(), + Self::LandingHoney { inner } => inner.0.clone(), + Self::FallingNectar { inner } => inner.0.clone(), + Self::SoulFireFlame { inner } => inner.0.clone(), + Self::Ash { inner } => inner.0.clone(), + Self::CrimsonSpore { inner } => inner.0.clone(), + Self::WarpedSpore { inner } => inner.0.clone(), + Self::Soul { inner } => inner.0.clone(), + Self::DrippingObsidianTear { inner } => inner.0.clone(), + Self::FallingObsidianTear { inner } => inner.0.clone(), + Self::LandingObsidianTear { inner } => inner.0.clone(), + Self::ReversePortal { inner } => inner.0.clone(), + Self::WhiteAsh { inner } => inner.0.clone(), + Self::DustColorTransition { inner } => inner.0.clone(), + Self::Vibration { inner } => inner.0.clone(), + Self::FallingSporeBlossom { inner } => inner.0.clone(), + Self::SporeBlossomAir { inner } => inner.0.clone(), + Self::SmallFlame { inner } => inner.0.clone(), + Self::Snowflake { inner } => inner.0.clone(), + Self::DrippingDripstoneLava { inner } => inner.0.clone(), + Self::FallingDripstoneLava { inner } => inner.0.clone(), + Self::DrippingDripstoneWater { inner } => inner.0.clone(), + Self::FallingDripstoneWater { inner } => inner.0.clone(), + Self::GlowSquidInk { inner } => inner.0.clone(), + Self::Glow { inner } => inner.0.clone(), + Self::WaxOn { inner } => inner.0.clone(), + Self::WaxOff { inner } => inner.0.clone(), + Self::ElectricSpark { inner } => inner.0.clone(), + Self::Scrape { inner } => inner.0.clone(), + Self::SonicBoom { inner } => inner.0.clone(), + Self::SculkSoul { inner } => inner.0.clone(), + Self::SculkCharge { inner } => inner.0.clone(), + Self::SculkChargePop { inner } => inner.0.clone(), + Self::Shriek { inner } => inner.0.clone(), + Self::CherryLeaves { inner } => inner.0.clone(), + Self::EggCrack { inner } => inner.0.clone(), + Self::DustPlume { inner } => inner.0.clone(), + Self::WhiteSmoke { inner } => inner.0.clone(), + Self::Gust { inner } => inner.0.clone(), + Self::SmallGust { inner } => inner.0.clone(), + Self::GustEmitterLarge { inner } => inner.0.clone(), + Self::GustEmitterSmall { inner } => inner.0.clone(), + Self::TrialSpawnerDetection { inner } => inner.0.clone(), + Self::TrialSpawnerDetectionOminous { inner } => inner.0.clone(), + Self::VaultConnection { inner } => inner.0.clone(), + Self::Infested { inner } => inner.0.clone(), + Self::ItemCobweb { inner } => inner.0.clone(), + Self::DustPillar { inner } => inner.0.clone(), + Self::OminousSpawning { inner } => inner.0.clone(), + Self::RaidOmen { inner } => inner.0.clone(), + Self::TrialOmen { inner } => inner.0.clone(), + Self::BlockMarker { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Poof { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Explosion { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ExplosionEmitter { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Firework { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Bubble { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Splash { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Fishing { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Underwater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Crit { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::EnchantedHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Smoke { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::LargeSmoke { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Effect { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::InstantEffect { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityEffect { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Witch { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DrippingWater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DrippingLava { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AngryVillager { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HappyVillager { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Mycelium { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Note { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Portal { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Enchant { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Flame { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Lava { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Cloud { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Dust { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ItemSnowball { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ItemSlime { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Heart { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Item { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Block { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Rain { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ElderGuardian { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DragonBreath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EndRod { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DamageIndicator { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SweepAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FallingDust { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TotemOfUndying { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Spit { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SquidInk { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BubblePop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CurrentDown { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BubbleColumnUp { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Nautilus { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Dolphin { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Sneeze { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CampfireCosySmoke { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CampfireSignalSmoke { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Composter { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Flash { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::FallingLava { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LandingLava { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FallingWater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DrippingHoney { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FallingHoney { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LandingHoney { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FallingNectar { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SoulFireFlame { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Ash { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CrimsonSpore { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WarpedSpore { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Soul { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DrippingObsidianTear { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FallingObsidianTear { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LandingObsidianTear { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ReversePortal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WhiteAsh { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DustColorTransition { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Vibration { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FallingSporeBlossom { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SporeBlossomAir { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SmallFlame { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Snowflake { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DrippingDripstoneLava { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FallingDripstoneLava { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DrippingDripstoneWater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FallingDripstoneWater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GlowSquidInk { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Glow { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::WaxOn { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::WaxOff { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ElectricSpark { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Scrape { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SonicBoom { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SculkSoul { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SculkCharge { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SculkChargePop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Shriek { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CherryLeaves { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EggCrack { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DustPlume { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WhiteSmoke { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Gust { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SmallGust { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GustEmitterLarge { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GustEmitterSmall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrialSpawnerDetection { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrialSpawnerDetectionOminous { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VaultConnection { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Infested { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ItemCobweb { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DustPillar { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OminousSpawning { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RaidOmen { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::TrialOmen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockMarker { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for Particle<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Particle from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Particle")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Particle object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "POOF" => Ok(Particle::Poof { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "EXPLOSION" => Ok(Particle::Explosion { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "EXPLOSION_EMITTER" => Ok(Particle::ExplosionEmitter { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FIREWORK" => Ok(Particle::Firework { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "BUBBLE" => Ok(Particle::Bubble { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SPLASH" => Ok(Particle::Splash { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FISHING" => Ok(Particle::Fishing { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "UNDERWATER" => Ok(Particle::Underwater { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "CRIT" => Ok(Particle::Crit { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "ENCHANTED_HIT" => Ok(Particle::EnchantedHit { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SMOKE" => Ok(Particle::Smoke { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "LARGE_SMOKE" => Ok(Particle::LargeSmoke { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "EFFECT" => Ok(Particle::Effect { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "INSTANT_EFFECT" => Ok(Particle::InstantEffect { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "ENTITY_EFFECT" => Ok(Particle::EntityEffect { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "WITCH" => Ok(Particle::Witch { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DRIPPING_WATER" => Ok(Particle::DrippingWater { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DRIPPING_LAVA" => Ok(Particle::DrippingLava { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "ANGRY_VILLAGER" => Ok(Particle::AngryVillager { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "HAPPY_VILLAGER" => Ok(Particle::HappyVillager { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "MYCELIUM" => Ok(Particle::Mycelium { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "NOTE" => Ok(Particle::Note { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "PORTAL" => Ok(Particle::Portal { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "ENCHANT" => Ok(Particle::Enchant { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FLAME" => Ok(Particle::Flame { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "LAVA" => Ok(Particle::Lava { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "CLOUD" => Ok(Particle::Cloud { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DUST" => Ok(Particle::Dust { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "ITEM_SNOWBALL" => Ok(Particle::ItemSnowball { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "ITEM_SLIME" => Ok(Particle::ItemSlime { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "HEART" => Ok(Particle::Heart { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "ITEM" => Ok(Particle::Item { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "BLOCK" => Ok(Particle::Block { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "RAIN" => Ok(Particle::Rain { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "ELDER_GUARDIAN" => Ok(Particle::ElderGuardian { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DRAGON_BREATH" => Ok(Particle::DragonBreath { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "END_ROD" => Ok(Particle::EndRod { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DAMAGE_INDICATOR" => Ok(Particle::DamageIndicator { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SWEEP_ATTACK" => Ok(Particle::SweepAttack { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FALLING_DUST" => Ok(Particle::FallingDust { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "TOTEM_OF_UNDYING" => Ok(Particle::TotemOfUndying { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SPIT" => Ok(Particle::Spit { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SQUID_INK" => Ok(Particle::SquidInk { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "BUBBLE_POP" => Ok(Particle::BubblePop { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "CURRENT_DOWN" => Ok(Particle::CurrentDown { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "BUBBLE_COLUMN_UP" => Ok(Particle::BubbleColumnUp { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "NAUTILUS" => Ok(Particle::Nautilus { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DOLPHIN" => Ok(Particle::Dolphin { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SNEEZE" => Ok(Particle::Sneeze { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "CAMPFIRE_COSY_SMOKE" => Ok(Particle::CampfireCosySmoke { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "CAMPFIRE_SIGNAL_SMOKE" => Ok(Particle::CampfireSignalSmoke { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "COMPOSTER" => Ok(Particle::Composter { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FLASH" => Ok(Particle::Flash { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FALLING_LAVA" => Ok(Particle::FallingLava { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "LANDING_LAVA" => Ok(Particle::LandingLava { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FALLING_WATER" => Ok(Particle::FallingWater { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DRIPPING_HONEY" => Ok(Particle::DrippingHoney { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FALLING_HONEY" => Ok(Particle::FallingHoney { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "LANDING_HONEY" => Ok(Particle::LandingHoney { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FALLING_NECTAR" => Ok(Particle::FallingNectar { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SOUL_FIRE_FLAME" => Ok(Particle::SoulFireFlame { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "ASH" => Ok(Particle::Ash { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "CRIMSON_SPORE" => Ok(Particle::CrimsonSpore { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "WARPED_SPORE" => Ok(Particle::WarpedSpore { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SOUL" => Ok(Particle::Soul { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DRIPPING_OBSIDIAN_TEAR" => Ok(Particle::DrippingObsidianTear { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FALLING_OBSIDIAN_TEAR" => Ok(Particle::FallingObsidianTear { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "LANDING_OBSIDIAN_TEAR" => Ok(Particle::LandingObsidianTear { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "REVERSE_PORTAL" => Ok(Particle::ReversePortal { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "WHITE_ASH" => Ok(Particle::WhiteAsh { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DUST_COLOR_TRANSITION" => Ok(Particle::DustColorTransition { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "VIBRATION" => Ok(Particle::Vibration { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FALLING_SPORE_BLOSSOM" => Ok(Particle::FallingSporeBlossom { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SPORE_BLOSSOM_AIR" => Ok(Particle::SporeBlossomAir { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SMALL_FLAME" => Ok(Particle::SmallFlame { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SNOWFLAKE" => Ok(Particle::Snowflake { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DRIPPING_DRIPSTONE_LAVA" => Ok(Particle::DrippingDripstoneLava { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FALLING_DRIPSTONE_LAVA" => Ok(Particle::FallingDripstoneLava { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DRIPPING_DRIPSTONE_WATER" => Ok(Particle::DrippingDripstoneWater { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "FALLING_DRIPSTONE_WATER" => Ok(Particle::FallingDripstoneWater { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "GLOW_SQUID_INK" => Ok(Particle::GlowSquidInk { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "GLOW" => Ok(Particle::Glow { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "WAX_ON" => Ok(Particle::WaxOn { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "WAX_OFF" => Ok(Particle::WaxOff { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "ELECTRIC_SPARK" => Ok(Particle::ElectricSpark { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SCRAPE" => Ok(Particle::Scrape { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SONIC_BOOM" => Ok(Particle::SonicBoom { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SCULK_SOUL" => Ok(Particle::SculkSoul { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SCULK_CHARGE" => Ok(Particle::SculkCharge { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SCULK_CHARGE_POP" => Ok(Particle::SculkChargePop { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SHRIEK" => Ok(Particle::Shriek { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "CHERRY_LEAVES" => Ok(Particle::CherryLeaves { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "EGG_CRACK" => Ok(Particle::EggCrack { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DUST_PLUME" => Ok(Particle::DustPlume { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "WHITE_SMOKE" => Ok(Particle::WhiteSmoke { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "GUST" => Ok(Particle::Gust { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "SMALL_GUST" => Ok(Particle::SmallGust { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "GUST_EMITTER_LARGE" => Ok(Particle::GustEmitterLarge { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "GUST_EMITTER_SMALL" => Ok(Particle::GustEmitterSmall { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "TRIAL_SPAWNER_DETECTION" => Ok(Particle::TrialSpawnerDetection { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "TRIAL_SPAWNER_DETECTION_OMINOUS" => Ok(Particle::TrialSpawnerDetectionOminous { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "VAULT_CONNECTION" => Ok(Particle::VaultConnection { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "INFESTED" => Ok(Particle::Infested { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "ITEM_COBWEB" => Ok(Particle::ItemCobweb { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "DUST_PILLAR" => Ok(Particle::DustPillar { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "OMINOUS_SPAWNING" => Ok(Particle::OminousSpawning { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "RAID_OMEN" => Ok(Particle::RaidOmen { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "TRIAL_OMEN" => Ok(Particle::TrialOmen { + inner: ParticleStruct::from_raw(env, obj)?, + }), + "BLOCK_MARKER" => Ok(Particle::BlockMarker { + inner: ParticleStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for ParticleStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for ParticleStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate ParticleStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Particle")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ParticleStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> ParticleStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Particle;"); + let cls = jni.find_class("org/bukkit/Particle"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::Particle::from_raw(&jni, obj) + } + + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct ParticleDustOptions<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ParticleDustOptions<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for ParticleDustOptions<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate ParticleDustOptions from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Particle/DustOptions")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ParticleDustOptions object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> ParticleDustOptions<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + color: impl Into>, + size: f32, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/Color;F)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(color.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Float(size); + let cls = jni.find_class("org/bukkit/Particle/DustOptions"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::ParticleDustOptions::from_raw(&jni, res) + } + /// The color of the particles to be displayed. + pub fn color(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Color;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Color::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Relative size of the particle. + pub fn size(&self) -> Result> { + let sig = String::from("()F"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct ParticleDustTransition<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ParticleDustTransition<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for ParticleDustTransition<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate ParticleDustTransition from null object." + ) + .into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Particle/DustTransition")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ParticleDustTransition object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> ParticleDustTransition<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + from_color: impl Into>, + to_color: impl Into>, + size: f32, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/Color;Lorg/bukkit/Color;F)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(from_color.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(to_color.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Float(size); + let cls = jni.find_class("org/bukkit/Particle/DustTransition"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::ParticleDustTransition::from_raw(&jni, res) + } + /// The final of the particles to be displayed. + pub fn to_color(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Color;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getToColor", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Color::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + // SUPER CLASS: org.bukkit.Particle.DustOptions ( ['getToColor']) + /// The color of the particles to be displayed. + pub fn color(&self) -> Result, Box> { + let temp_clone = crate::ParticleDustOptions::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::ParticleDustOptions = temp_clone.into(); + real.color() + } + /// Relative size of the particle. + pub fn size(&self) -> Result> { + let temp_clone = crate::ParticleDustOptions::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::ParticleDustOptions = temp_clone.into(); + real.size() + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for ParticleDustTransition<'mc> { + fn into(self) -> crate::ParticleDustOptions<'mc> { + crate::ParticleDustOptions::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ParticleDustTransition into crate::ParticleDustOptions") + } +} +#[repr(C)] +pub struct Note<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Note<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Note<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Note from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Note")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Note object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Note<'mc> { + /// Creates a new note. + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + octave: i32, + tone: std::option::Option>>, + sharped: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(octave); + args.push(val_1); + if let Some(a) = tone { + sig += "Lorg/bukkit/Note/Tone;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + if let Some(a) = sharped { + sig += "Z"; + let val_3 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_3); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/Note"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::Note::from_raw(&jni, res) + } + /// Creates a new note for a flat tone, such as A-flat. + pub fn flat( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + octave: i32, + tone: impl Into>, + ) -> Result, Box> { + let sig = String::from("(ILorg/bukkit/Note/Tone;)Lorg/bukkit/Note;"); + let val_1 = jni::objects::JValueGen::Int(octave); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(tone.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/Note"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "flat", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::Note::from_raw(&jni, obj) + } + /// Creates a new note for a sharp tone, such as A-sharp. + pub fn sharp( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + octave: i32, + tone: impl Into>, + ) -> Result, Box> { + let sig = String::from("(ILorg/bukkit/Note/Tone;)Lorg/bukkit/Note;"); + let val_1 = jni::objects::JValueGen::Int(octave); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(tone.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/Note"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "sharp", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::Note::from_raw(&jni, obj) + } + /// Creates a new note for a natural tone, such as A-natural. + pub fn natural( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + octave: i32, + tone: impl Into>, + ) -> Result, Box> { + let sig = String::from("(ILorg/bukkit/Note/Tone;)Lorg/bukkit/Note;"); + let val_1 = jni::objects::JValueGen::Int(octave); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(tone.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/Note"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "natural", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::Note::from_raw(&jni, obj) + } + + pub fn sharped(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Note;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "sharped", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Note::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn flattened(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Note;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "flattened", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Note::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + #[deprecated] + /// Returns the internal id of this note. + pub fn id(&self) -> Result> { + let sig = String::from("()B"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.b()?) + } + /// Returns the octave of this note. + pub fn octave(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getOctave", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Returns the tone of this note. + pub fn tone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Note/Tone;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NoteTone::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns if this note is sharped. + pub fn is_sharped(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSharped", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the pitch of this note. This is the value used with + /// {@link World#playSound} or the /playsound command. + pub fn pitch(&self) -> Result> { + let sig = String::from("()F"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPitch", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + + pub fn hash_code(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + + pub fn equals( + &self, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(Ljava/lang/Object;)Z"); + let val_1 = jni::objects::JValueGen::Object(obj); + let res = self.jni_ref().call_method( + &self.jni_object(), + "equals", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} + +impl<'mc> std::string::ToString for Note<'mc> { + fn to_string(&self) -> String { + match &self.internal_to_string() { + Ok(a) => a.clone(), + Err(err) => format!("Error calling Note.toString: {}", err), + } + } +} + +pub enum NoteTone<'mc> { + G { inner: NoteToneStruct<'mc> }, + A { inner: NoteToneStruct<'mc> }, + B { inner: NoteToneStruct<'mc> }, + C { inner: NoteToneStruct<'mc> }, + D { inner: NoteToneStruct<'mc> }, + E { inner: NoteToneStruct<'mc> }, + F { inner: NoteToneStruct<'mc> }, +} +impl<'mc> std::fmt::Display for NoteTone<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + NoteTone::G { .. } => f.write_str("G"), + NoteTone::A { .. } => f.write_str("A"), + NoteTone::B { .. } => f.write_str("B"), + NoteTone::C { .. } => f.write_str("C"), + NoteTone::D { .. } => f.write_str("D"), + NoteTone::E { .. } => f.write_str("E"), + NoteTone::F { .. } => f.write_str("F"), + } + } +} +impl<'mc> std::ops::Deref for NoteTone<'mc> { + type Target = NoteToneStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + NoteTone::G { inner } => inner, + NoteTone::A { inner } => inner, + NoteTone::B { inner } => inner, + NoteTone::C { inner } => inner, + NoteTone::D { inner } => inner, + NoteTone::E { inner } => inner, + NoteTone::F { inner } => inner, + } + } +} + +impl<'mc> NoteTone<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/Note/Tone"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/Note/Tone;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "G" => Ok(NoteTone::G { + inner: NoteToneStruct::from_raw(env, obj)?, + }), + "A" => Ok(NoteTone::A { + inner: NoteToneStruct::from_raw(env, obj)?, + }), + "B" => Ok(NoteTone::B { + inner: NoteToneStruct::from_raw(env, obj)?, + }), + "C" => Ok(NoteTone::C { + inner: NoteToneStruct::from_raw(env, obj)?, + }), + "D" => Ok(NoteTone::D { + inner: NoteToneStruct::from_raw(env, obj)?, + }), + "E" => Ok(NoteTone::E { + inner: NoteToneStruct::from_raw(env, obj)?, + }), + "F" => Ok(NoteTone::F { + inner: NoteToneStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct NoteToneStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for NoteTone<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::G { inner } => inner.0.clone(), + Self::A { inner } => inner.0.clone(), + Self::B { inner } => inner.0.clone(), + Self::C { inner } => inner.0.clone(), + Self::D { inner } => inner.0.clone(), + Self::E { inner } => inner.0.clone(), + Self::F { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::G { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::A { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::B { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::C { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::D { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::E { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::F { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for NoteTone<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate NoteTone from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Note/Tone")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a NoteTone object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "G" => Ok(NoteTone::G { + inner: NoteToneStruct::from_raw(env, obj)?, + }), + "A" => Ok(NoteTone::A { + inner: NoteToneStruct::from_raw(env, obj)?, + }), + "B" => Ok(NoteTone::B { + inner: NoteToneStruct::from_raw(env, obj)?, + }), + "C" => Ok(NoteTone::C { + inner: NoteToneStruct::from_raw(env, obj)?, + }), + "D" => Ok(NoteTone::D { + inner: NoteToneStruct::from_raw(env, obj)?, + }), + "E" => Ok(NoteTone::E { + inner: NoteToneStruct::from_raw(env, obj)?, + }), + "F" => Ok(NoteTone::F { + inner: NoteToneStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for NoteToneStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for NoteToneStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate NoteToneStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Note/Tone")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a NoteToneStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> NoteToneStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Note/Tone;"); + let cls = jni.find_class("org/bukkit/Note/Tone"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::NoteTone::from_raw(&jni, obj) + } + #[deprecated] + /// Returns the id of this tone. These method allows to return the sharped id of the tone. If the tone couldn't be sharped it always return the not sharped id of this tone. + pub fn get_id(&self, sharped: bool) -> Result> { + let sig = String::from("(Z)B"); + let val_1 = jni::objects::JValueGen::Bool(sharped.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getId", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.b()?) + } + /// Returns if this tone could be sharped. + pub fn is_sharpable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isSharpable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Returns if this tone id is the sharped id of the tone. + pub fn is_sharped(&self, id: i8) -> Result> { + let sig = String::from("(B)Z"); + let val_1 = jni::objects::JValueGen::Byte(id); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isSharped", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + #[deprecated] + /// Returns the tone to id. Also returning the semitones. + pub fn get_by_id( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + id: i8, + ) -> Result>, Box> { + let sig = String::from("(B)Lorg/bukkit/Note/Tone;"); + let val_1 = jni::objects::JValueGen::Byte(id); + let cls = jni.find_class("org/bukkit/Note/Tone"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getById", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::NoteTone::from_raw(&jni, obj)?)) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct NamespacedKey<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for NamespacedKey<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for NamespacedKey<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate NamespacedKey from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/NamespacedKey")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a NamespacedKey object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> NamespacedKey<'mc> { + /// Create a key in the plugin's namespace. + /// + /// Namespaces may only contain lowercase alphanumeric characters, periods, + /// underscores, and hyphens. + /// + /// Keys may only contain lowercase alphanumeric characters, periods, + /// underscores, hyphens, and forward slashes. + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + plugin: impl Into>, + key: impl Into, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/plugin/Plugin;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(key.into())?, + )); + args.push(val_2); + sig += ")V"; + let cls = jni.find_class("org/bukkit/NamespacedKey"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::NamespacedKey::from_raw(&jni, res) + } + + pub fn namespace(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getNamespace", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + + pub fn key(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + + pub fn hash_code(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + + pub fn equals( + &self, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(Ljava/lang/Object;)Z"); + let val_1 = jni::objects::JValueGen::Object(obj); + let res = self.jni_ref().call_method( + &self.jni_object(), + "equals", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + #[deprecated] + /// Return a new random key in the {@link #BUKKIT} namespace. + pub fn random_key( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let cls = jni.find_class("org/bukkit/NamespacedKey"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "randomKey", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::NamespacedKey::from_raw(&jni, obj) + } + /// Get a key in the Minecraft namespace. + pub fn minecraft( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + key: impl Into, + ) -> Result, Box> { + let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/NamespacedKey;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(key.into())?, + )); + let cls = jni.find_class("org/bukkit/NamespacedKey"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "minecraft", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::NamespacedKey::from_raw(&jni, obj) + } + /// Get a NamespacedKey from the supplied string with a default namespace if + /// a namespace is not defined. This is a utility method meant to fetch a + /// NamespacedKey from user input. Please note that casing does matter and + /// any instance of uppercase characters will be considered invalid. The + /// input contract is as follows: + ///
    +    /// fromString("foo", plugin) -{@literal >} "plugin:foo"
    +    /// fromString("foo:bar", plugin) -{@literal >} "foo:bar"
    +    /// fromString(":foo", null) -{@literal >} "minecraft:foo"
    +    /// fromString("foo", null) -{@literal >} "minecraft:foo"
    +    /// fromString("Foo", plugin) -{@literal >} null
    +    /// fromString(":Foo", plugin) -{@literal >} null
    +    /// fromString("foo:bar:bazz", plugin) -{@literal >} null
    +    /// fromString("", plugin) -{@literal >} null
    +    /// 
    + pub fn from_string( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + string: impl Into, + default_namespace: std::option::Option>>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(string.into())?, + )); + args.push(val_1); + if let Some(a) = default_namespace { + sig += "Lorg/bukkit/plugin/Plugin;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/NamespacedKey;"; + let cls = jni.find_class("org/bukkit/NamespacedKey"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "fromString", sig.as_str(), args); + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::NamespacedKey::from_raw(&jni, obj)?)) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} + +impl<'mc> std::string::ToString for NamespacedKey<'mc> { + fn to_string(&self) -> String { + match &self.internal_to_string() { + Ok(a) => a.clone(), + Err(err) => format!("Error calling NamespacedKey.toString: {}", err), + } + } +} + +pub enum Material<'mc> { + Air { inner: MaterialStruct<'mc> }, + Stone { inner: MaterialStruct<'mc> }, + Granite { inner: MaterialStruct<'mc> }, + PolishedGranite { inner: MaterialStruct<'mc> }, + Diorite { inner: MaterialStruct<'mc> }, + PolishedDiorite { inner: MaterialStruct<'mc> }, + Andesite { inner: MaterialStruct<'mc> }, + PolishedAndesite { inner: MaterialStruct<'mc> }, + Deepslate { inner: MaterialStruct<'mc> }, + CobbledDeepslate { inner: MaterialStruct<'mc> }, + PolishedDeepslate { inner: MaterialStruct<'mc> }, + Calcite { inner: MaterialStruct<'mc> }, + Tuff { inner: MaterialStruct<'mc> }, + TuffSlab { inner: MaterialStruct<'mc> }, + TuffStairs { inner: MaterialStruct<'mc> }, + TuffWall { inner: MaterialStruct<'mc> }, + ChiseledTuff { inner: MaterialStruct<'mc> }, + PolishedTuff { inner: MaterialStruct<'mc> }, + PolishedTuffSlab { inner: MaterialStruct<'mc> }, + PolishedTuffStairs { inner: MaterialStruct<'mc> }, + PolishedTuffWall { inner: MaterialStruct<'mc> }, + TuffBricks { inner: MaterialStruct<'mc> }, + TuffBrickSlab { inner: MaterialStruct<'mc> }, + TuffBrickStairs { inner: MaterialStruct<'mc> }, + TuffBrickWall { inner: MaterialStruct<'mc> }, + ChiseledTuffBricks { inner: MaterialStruct<'mc> }, + DripstoneBlock { inner: MaterialStruct<'mc> }, + GrassBlock { inner: MaterialStruct<'mc> }, + Dirt { inner: MaterialStruct<'mc> }, + CoarseDirt { inner: MaterialStruct<'mc> }, + Podzol { inner: MaterialStruct<'mc> }, + RootedDirt { inner: MaterialStruct<'mc> }, + Mud { inner: MaterialStruct<'mc> }, + CrimsonNylium { inner: MaterialStruct<'mc> }, + WarpedNylium { inner: MaterialStruct<'mc> }, + Cobblestone { inner: MaterialStruct<'mc> }, + OakPlanks { inner: MaterialStruct<'mc> }, + SprucePlanks { inner: MaterialStruct<'mc> }, + BirchPlanks { inner: MaterialStruct<'mc> }, + JunglePlanks { inner: MaterialStruct<'mc> }, + AcaciaPlanks { inner: MaterialStruct<'mc> }, + CherryPlanks { inner: MaterialStruct<'mc> }, + DarkOakPlanks { inner: MaterialStruct<'mc> }, + MangrovePlanks { inner: MaterialStruct<'mc> }, + BambooPlanks { inner: MaterialStruct<'mc> }, + CrimsonPlanks { inner: MaterialStruct<'mc> }, + WarpedPlanks { inner: MaterialStruct<'mc> }, + BambooMosaic { inner: MaterialStruct<'mc> }, + OakSapling { inner: MaterialStruct<'mc> }, + SpruceSapling { inner: MaterialStruct<'mc> }, + BirchSapling { inner: MaterialStruct<'mc> }, + JungleSapling { inner: MaterialStruct<'mc> }, + AcaciaSapling { inner: MaterialStruct<'mc> }, + CherrySapling { inner: MaterialStruct<'mc> }, + DarkOakSapling { inner: MaterialStruct<'mc> }, + MangrovePropagule { inner: MaterialStruct<'mc> }, + Bedrock { inner: MaterialStruct<'mc> }, + Sand { inner: MaterialStruct<'mc> }, + SuspiciousSand { inner: MaterialStruct<'mc> }, + SuspiciousGravel { inner: MaterialStruct<'mc> }, + RedSand { inner: MaterialStruct<'mc> }, + Gravel { inner: MaterialStruct<'mc> }, + CoalOre { inner: MaterialStruct<'mc> }, + DeepslateCoalOre { inner: MaterialStruct<'mc> }, + IronOre { inner: MaterialStruct<'mc> }, + DeepslateIronOre { inner: MaterialStruct<'mc> }, + CopperOre { inner: MaterialStruct<'mc> }, + DeepslateCopperOre { inner: MaterialStruct<'mc> }, + GoldOre { inner: MaterialStruct<'mc> }, + DeepslateGoldOre { inner: MaterialStruct<'mc> }, + RedstoneOre { inner: MaterialStruct<'mc> }, + DeepslateRedstoneOre { inner: MaterialStruct<'mc> }, + EmeraldOre { inner: MaterialStruct<'mc> }, + DeepslateEmeraldOre { inner: MaterialStruct<'mc> }, + LapisOre { inner: MaterialStruct<'mc> }, + DeepslateLapisOre { inner: MaterialStruct<'mc> }, + DiamondOre { inner: MaterialStruct<'mc> }, + DeepslateDiamondOre { inner: MaterialStruct<'mc> }, + NetherGoldOre { inner: MaterialStruct<'mc> }, + NetherQuartzOre { inner: MaterialStruct<'mc> }, + AncientDebris { inner: MaterialStruct<'mc> }, + CoalBlock { inner: MaterialStruct<'mc> }, + RawIronBlock { inner: MaterialStruct<'mc> }, + RawCopperBlock { inner: MaterialStruct<'mc> }, + RawGoldBlock { inner: MaterialStruct<'mc> }, + HeavyCore { inner: MaterialStruct<'mc> }, + AmethystBlock { inner: MaterialStruct<'mc> }, + BuddingAmethyst { inner: MaterialStruct<'mc> }, + IronBlock { inner: MaterialStruct<'mc> }, + CopperBlock { inner: MaterialStruct<'mc> }, + GoldBlock { inner: MaterialStruct<'mc> }, + DiamondBlock { inner: MaterialStruct<'mc> }, + NetheriteBlock { inner: MaterialStruct<'mc> }, + ExposedCopper { inner: MaterialStruct<'mc> }, + WeatheredCopper { inner: MaterialStruct<'mc> }, + OxidizedCopper { inner: MaterialStruct<'mc> }, + ChiseledCopper { inner: MaterialStruct<'mc> }, + ExposedChiseledCopper { inner: MaterialStruct<'mc> }, + WeatheredChiseledCopper { inner: MaterialStruct<'mc> }, + OxidizedChiseledCopper { inner: MaterialStruct<'mc> }, + CutCopper { inner: MaterialStruct<'mc> }, + ExposedCutCopper { inner: MaterialStruct<'mc> }, + WeatheredCutCopper { inner: MaterialStruct<'mc> }, + OxidizedCutCopper { inner: MaterialStruct<'mc> }, + CutCopperStairs { inner: MaterialStruct<'mc> }, + ExposedCutCopperStairs { inner: MaterialStruct<'mc> }, + WeatheredCutCopperStairs { inner: MaterialStruct<'mc> }, + OxidizedCutCopperStairs { inner: MaterialStruct<'mc> }, + CutCopperSlab { inner: MaterialStruct<'mc> }, + ExposedCutCopperSlab { inner: MaterialStruct<'mc> }, + WeatheredCutCopperSlab { inner: MaterialStruct<'mc> }, + OxidizedCutCopperSlab { inner: MaterialStruct<'mc> }, + WaxedCopperBlock { inner: MaterialStruct<'mc> }, + WaxedExposedCopper { inner: MaterialStruct<'mc> }, + WaxedWeatheredCopper { inner: MaterialStruct<'mc> }, + WaxedOxidizedCopper { inner: MaterialStruct<'mc> }, + WaxedChiseledCopper { inner: MaterialStruct<'mc> }, + WaxedExposedChiseledCopper { inner: MaterialStruct<'mc> }, + WaxedWeatheredChiseledCopper { inner: MaterialStruct<'mc> }, + WaxedOxidizedChiseledCopper { inner: MaterialStruct<'mc> }, + WaxedCutCopper { inner: MaterialStruct<'mc> }, + WaxedExposedCutCopper { inner: MaterialStruct<'mc> }, + WaxedWeatheredCutCopper { inner: MaterialStruct<'mc> }, + WaxedOxidizedCutCopper { inner: MaterialStruct<'mc> }, + WaxedCutCopperStairs { inner: MaterialStruct<'mc> }, + WaxedExposedCutCopperStairs { inner: MaterialStruct<'mc> }, + WaxedWeatheredCutCopperStairs { inner: MaterialStruct<'mc> }, + WaxedOxidizedCutCopperStairs { inner: MaterialStruct<'mc> }, + WaxedCutCopperSlab { inner: MaterialStruct<'mc> }, + WaxedExposedCutCopperSlab { inner: MaterialStruct<'mc> }, + WaxedWeatheredCutCopperSlab { inner: MaterialStruct<'mc> }, + WaxedOxidizedCutCopperSlab { inner: MaterialStruct<'mc> }, + OakLog { inner: MaterialStruct<'mc> }, + SpruceLog { inner: MaterialStruct<'mc> }, + BirchLog { inner: MaterialStruct<'mc> }, + JungleLog { inner: MaterialStruct<'mc> }, + AcaciaLog { inner: MaterialStruct<'mc> }, + CherryLog { inner: MaterialStruct<'mc> }, + DarkOakLog { inner: MaterialStruct<'mc> }, + MangroveLog { inner: MaterialStruct<'mc> }, + MangroveRoots { inner: MaterialStruct<'mc> }, + MuddyMangroveRoots { inner: MaterialStruct<'mc> }, + CrimsonStem { inner: MaterialStruct<'mc> }, + WarpedStem { inner: MaterialStruct<'mc> }, + BambooBlock { inner: MaterialStruct<'mc> }, + StrippedOakLog { inner: MaterialStruct<'mc> }, + StrippedSpruceLog { inner: MaterialStruct<'mc> }, + StrippedBirchLog { inner: MaterialStruct<'mc> }, + StrippedJungleLog { inner: MaterialStruct<'mc> }, + StrippedAcaciaLog { inner: MaterialStruct<'mc> }, + StrippedCherryLog { inner: MaterialStruct<'mc> }, + StrippedDarkOakLog { inner: MaterialStruct<'mc> }, + StrippedMangroveLog { inner: MaterialStruct<'mc> }, + StrippedCrimsonStem { inner: MaterialStruct<'mc> }, + StrippedWarpedStem { inner: MaterialStruct<'mc> }, + StrippedOakWood { inner: MaterialStruct<'mc> }, + StrippedSpruceWood { inner: MaterialStruct<'mc> }, + StrippedBirchWood { inner: MaterialStruct<'mc> }, + StrippedJungleWood { inner: MaterialStruct<'mc> }, + StrippedAcaciaWood { inner: MaterialStruct<'mc> }, + StrippedCherryWood { inner: MaterialStruct<'mc> }, + StrippedDarkOakWood { inner: MaterialStruct<'mc> }, + StrippedMangroveWood { inner: MaterialStruct<'mc> }, + StrippedCrimsonHyphae { inner: MaterialStruct<'mc> }, + StrippedWarpedHyphae { inner: MaterialStruct<'mc> }, + StrippedBambooBlock { inner: MaterialStruct<'mc> }, + OakWood { inner: MaterialStruct<'mc> }, + SpruceWood { inner: MaterialStruct<'mc> }, + BirchWood { inner: MaterialStruct<'mc> }, + JungleWood { inner: MaterialStruct<'mc> }, + AcaciaWood { inner: MaterialStruct<'mc> }, + CherryWood { inner: MaterialStruct<'mc> }, + DarkOakWood { inner: MaterialStruct<'mc> }, + MangroveWood { inner: MaterialStruct<'mc> }, + CrimsonHyphae { inner: MaterialStruct<'mc> }, + WarpedHyphae { inner: MaterialStruct<'mc> }, + OakLeaves { inner: MaterialStruct<'mc> }, + SpruceLeaves { inner: MaterialStruct<'mc> }, + BirchLeaves { inner: MaterialStruct<'mc> }, + JungleLeaves { inner: MaterialStruct<'mc> }, + AcaciaLeaves { inner: MaterialStruct<'mc> }, + CherryLeaves { inner: MaterialStruct<'mc> }, + DarkOakLeaves { inner: MaterialStruct<'mc> }, + MangroveLeaves { inner: MaterialStruct<'mc> }, + AzaleaLeaves { inner: MaterialStruct<'mc> }, + FloweringAzaleaLeaves { inner: MaterialStruct<'mc> }, + Sponge { inner: MaterialStruct<'mc> }, + WetSponge { inner: MaterialStruct<'mc> }, + Glass { inner: MaterialStruct<'mc> }, + TintedGlass { inner: MaterialStruct<'mc> }, + LapisBlock { inner: MaterialStruct<'mc> }, + Sandstone { inner: MaterialStruct<'mc> }, + ChiseledSandstone { inner: MaterialStruct<'mc> }, + CutSandstone { inner: MaterialStruct<'mc> }, + Cobweb { inner: MaterialStruct<'mc> }, + ShortGrass { inner: MaterialStruct<'mc> }, + Fern { inner: MaterialStruct<'mc> }, + Azalea { inner: MaterialStruct<'mc> }, + FloweringAzalea { inner: MaterialStruct<'mc> }, + DeadBush { inner: MaterialStruct<'mc> }, + Seagrass { inner: MaterialStruct<'mc> }, + SeaPickle { inner: MaterialStruct<'mc> }, + WhiteWool { inner: MaterialStruct<'mc> }, + OrangeWool { inner: MaterialStruct<'mc> }, + MagentaWool { inner: MaterialStruct<'mc> }, + LightBlueWool { inner: MaterialStruct<'mc> }, + YellowWool { inner: MaterialStruct<'mc> }, + LimeWool { inner: MaterialStruct<'mc> }, + PinkWool { inner: MaterialStruct<'mc> }, + GrayWool { inner: MaterialStruct<'mc> }, + LightGrayWool { inner: MaterialStruct<'mc> }, + CyanWool { inner: MaterialStruct<'mc> }, + PurpleWool { inner: MaterialStruct<'mc> }, + BlueWool { inner: MaterialStruct<'mc> }, + BrownWool { inner: MaterialStruct<'mc> }, + GreenWool { inner: MaterialStruct<'mc> }, + RedWool { inner: MaterialStruct<'mc> }, + BlackWool { inner: MaterialStruct<'mc> }, + Dandelion { inner: MaterialStruct<'mc> }, + Poppy { inner: MaterialStruct<'mc> }, + BlueOrchid { inner: MaterialStruct<'mc> }, + Allium { inner: MaterialStruct<'mc> }, + AzureBluet { inner: MaterialStruct<'mc> }, + RedTulip { inner: MaterialStruct<'mc> }, + OrangeTulip { inner: MaterialStruct<'mc> }, + WhiteTulip { inner: MaterialStruct<'mc> }, + PinkTulip { inner: MaterialStruct<'mc> }, + OxeyeDaisy { inner: MaterialStruct<'mc> }, + Cornflower { inner: MaterialStruct<'mc> }, + LilyOfTheValley { inner: MaterialStruct<'mc> }, + WitherRose { inner: MaterialStruct<'mc> }, + Torchflower { inner: MaterialStruct<'mc> }, + PitcherPlant { inner: MaterialStruct<'mc> }, + SporeBlossom { inner: MaterialStruct<'mc> }, + BrownMushroom { inner: MaterialStruct<'mc> }, + RedMushroom { inner: MaterialStruct<'mc> }, + CrimsonFungus { inner: MaterialStruct<'mc> }, + WarpedFungus { inner: MaterialStruct<'mc> }, + CrimsonRoots { inner: MaterialStruct<'mc> }, + WarpedRoots { inner: MaterialStruct<'mc> }, + NetherSprouts { inner: MaterialStruct<'mc> }, + WeepingVines { inner: MaterialStruct<'mc> }, + TwistingVines { inner: MaterialStruct<'mc> }, + SugarCane { inner: MaterialStruct<'mc> }, + Kelp { inner: MaterialStruct<'mc> }, + MossCarpet { inner: MaterialStruct<'mc> }, + PinkPetals { inner: MaterialStruct<'mc> }, + MossBlock { inner: MaterialStruct<'mc> }, + HangingRoots { inner: MaterialStruct<'mc> }, + BigDripleaf { inner: MaterialStruct<'mc> }, + SmallDripleaf { inner: MaterialStruct<'mc> }, + Bamboo { inner: MaterialStruct<'mc> }, + OakSlab { inner: MaterialStruct<'mc> }, + SpruceSlab { inner: MaterialStruct<'mc> }, + BirchSlab { inner: MaterialStruct<'mc> }, + JungleSlab { inner: MaterialStruct<'mc> }, + AcaciaSlab { inner: MaterialStruct<'mc> }, + CherrySlab { inner: MaterialStruct<'mc> }, + DarkOakSlab { inner: MaterialStruct<'mc> }, + MangroveSlab { inner: MaterialStruct<'mc> }, + BambooSlab { inner: MaterialStruct<'mc> }, + BambooMosaicSlab { inner: MaterialStruct<'mc> }, + CrimsonSlab { inner: MaterialStruct<'mc> }, + WarpedSlab { inner: MaterialStruct<'mc> }, + StoneSlab { inner: MaterialStruct<'mc> }, + SmoothStoneSlab { inner: MaterialStruct<'mc> }, + SandstoneSlab { inner: MaterialStruct<'mc> }, + CutSandstoneSlab { inner: MaterialStruct<'mc> }, + PetrifiedOakSlab { inner: MaterialStruct<'mc> }, + CobblestoneSlab { inner: MaterialStruct<'mc> }, + BrickSlab { inner: MaterialStruct<'mc> }, + StoneBrickSlab { inner: MaterialStruct<'mc> }, + MudBrickSlab { inner: MaterialStruct<'mc> }, + NetherBrickSlab { inner: MaterialStruct<'mc> }, + QuartzSlab { inner: MaterialStruct<'mc> }, + RedSandstoneSlab { inner: MaterialStruct<'mc> }, + CutRedSandstoneSlab { inner: MaterialStruct<'mc> }, + PurpurSlab { inner: MaterialStruct<'mc> }, + PrismarineSlab { inner: MaterialStruct<'mc> }, + PrismarineBrickSlab { inner: MaterialStruct<'mc> }, + DarkPrismarineSlab { inner: MaterialStruct<'mc> }, + SmoothQuartz { inner: MaterialStruct<'mc> }, + SmoothRedSandstone { inner: MaterialStruct<'mc> }, + SmoothSandstone { inner: MaterialStruct<'mc> }, + SmoothStone { inner: MaterialStruct<'mc> }, + Bricks { inner: MaterialStruct<'mc> }, + Bookshelf { inner: MaterialStruct<'mc> }, + ChiseledBookshelf { inner: MaterialStruct<'mc> }, + DecoratedPot { inner: MaterialStruct<'mc> }, + MossyCobblestone { inner: MaterialStruct<'mc> }, + Obsidian { inner: MaterialStruct<'mc> }, + Torch { inner: MaterialStruct<'mc> }, + EndRod { inner: MaterialStruct<'mc> }, + ChorusPlant { inner: MaterialStruct<'mc> }, + ChorusFlower { inner: MaterialStruct<'mc> }, + PurpurBlock { inner: MaterialStruct<'mc> }, + PurpurPillar { inner: MaterialStruct<'mc> }, + PurpurStairs { inner: MaterialStruct<'mc> }, + Spawner { inner: MaterialStruct<'mc> }, + Chest { inner: MaterialStruct<'mc> }, + CraftingTable { inner: MaterialStruct<'mc> }, + Farmland { inner: MaterialStruct<'mc> }, + Furnace { inner: MaterialStruct<'mc> }, + Ladder { inner: MaterialStruct<'mc> }, + CobblestoneStairs { inner: MaterialStruct<'mc> }, + Snow { inner: MaterialStruct<'mc> }, + Ice { inner: MaterialStruct<'mc> }, + SnowBlock { inner: MaterialStruct<'mc> }, + Cactus { inner: MaterialStruct<'mc> }, + Clay { inner: MaterialStruct<'mc> }, + Jukebox { inner: MaterialStruct<'mc> }, + OakFence { inner: MaterialStruct<'mc> }, + SpruceFence { inner: MaterialStruct<'mc> }, + BirchFence { inner: MaterialStruct<'mc> }, + JungleFence { inner: MaterialStruct<'mc> }, + AcaciaFence { inner: MaterialStruct<'mc> }, + CherryFence { inner: MaterialStruct<'mc> }, + DarkOakFence { inner: MaterialStruct<'mc> }, + MangroveFence { inner: MaterialStruct<'mc> }, + BambooFence { inner: MaterialStruct<'mc> }, + CrimsonFence { inner: MaterialStruct<'mc> }, + WarpedFence { inner: MaterialStruct<'mc> }, + Pumpkin { inner: MaterialStruct<'mc> }, + CarvedPumpkin { inner: MaterialStruct<'mc> }, + JackOLantern { inner: MaterialStruct<'mc> }, + Netherrack { inner: MaterialStruct<'mc> }, + SoulSand { inner: MaterialStruct<'mc> }, + SoulSoil { inner: MaterialStruct<'mc> }, + Basalt { inner: MaterialStruct<'mc> }, + PolishedBasalt { inner: MaterialStruct<'mc> }, + SmoothBasalt { inner: MaterialStruct<'mc> }, + SoulTorch { inner: MaterialStruct<'mc> }, + Glowstone { inner: MaterialStruct<'mc> }, + InfestedStone { inner: MaterialStruct<'mc> }, + InfestedCobblestone { inner: MaterialStruct<'mc> }, + InfestedStoneBricks { inner: MaterialStruct<'mc> }, + InfestedMossyStoneBricks { inner: MaterialStruct<'mc> }, + InfestedCrackedStoneBricks { inner: MaterialStruct<'mc> }, + InfestedChiseledStoneBricks { inner: MaterialStruct<'mc> }, + InfestedDeepslate { inner: MaterialStruct<'mc> }, + StoneBricks { inner: MaterialStruct<'mc> }, + MossyStoneBricks { inner: MaterialStruct<'mc> }, + CrackedStoneBricks { inner: MaterialStruct<'mc> }, + ChiseledStoneBricks { inner: MaterialStruct<'mc> }, + PackedMud { inner: MaterialStruct<'mc> }, + MudBricks { inner: MaterialStruct<'mc> }, + DeepslateBricks { inner: MaterialStruct<'mc> }, + CrackedDeepslateBricks { inner: MaterialStruct<'mc> }, + DeepslateTiles { inner: MaterialStruct<'mc> }, + CrackedDeepslateTiles { inner: MaterialStruct<'mc> }, + ChiseledDeepslate { inner: MaterialStruct<'mc> }, + ReinforcedDeepslate { inner: MaterialStruct<'mc> }, + BrownMushroomBlock { inner: MaterialStruct<'mc> }, + RedMushroomBlock { inner: MaterialStruct<'mc> }, + MushroomStem { inner: MaterialStruct<'mc> }, + IronBars { inner: MaterialStruct<'mc> }, + Chain { inner: MaterialStruct<'mc> }, + GlassPane { inner: MaterialStruct<'mc> }, + Melon { inner: MaterialStruct<'mc> }, + Vine { inner: MaterialStruct<'mc> }, + GlowLichen { inner: MaterialStruct<'mc> }, + BrickStairs { inner: MaterialStruct<'mc> }, + StoneBrickStairs { inner: MaterialStruct<'mc> }, + MudBrickStairs { inner: MaterialStruct<'mc> }, + Mycelium { inner: MaterialStruct<'mc> }, + LilyPad { inner: MaterialStruct<'mc> }, + NetherBricks { inner: MaterialStruct<'mc> }, + CrackedNetherBricks { inner: MaterialStruct<'mc> }, + ChiseledNetherBricks { inner: MaterialStruct<'mc> }, + NetherBrickFence { inner: MaterialStruct<'mc> }, + NetherBrickStairs { inner: MaterialStruct<'mc> }, + Sculk { inner: MaterialStruct<'mc> }, + SculkVein { inner: MaterialStruct<'mc> }, + SculkCatalyst { inner: MaterialStruct<'mc> }, + SculkShrieker { inner: MaterialStruct<'mc> }, + EnchantingTable { inner: MaterialStruct<'mc> }, + EndPortalFrame { inner: MaterialStruct<'mc> }, + EndStone { inner: MaterialStruct<'mc> }, + EndStoneBricks { inner: MaterialStruct<'mc> }, + DragonEgg { inner: MaterialStruct<'mc> }, + SandstoneStairs { inner: MaterialStruct<'mc> }, + EnderChest { inner: MaterialStruct<'mc> }, + EmeraldBlock { inner: MaterialStruct<'mc> }, + OakStairs { inner: MaterialStruct<'mc> }, + SpruceStairs { inner: MaterialStruct<'mc> }, + BirchStairs { inner: MaterialStruct<'mc> }, + JungleStairs { inner: MaterialStruct<'mc> }, + AcaciaStairs { inner: MaterialStruct<'mc> }, + CherryStairs { inner: MaterialStruct<'mc> }, + DarkOakStairs { inner: MaterialStruct<'mc> }, + MangroveStairs { inner: MaterialStruct<'mc> }, + BambooStairs { inner: MaterialStruct<'mc> }, + BambooMosaicStairs { inner: MaterialStruct<'mc> }, + CrimsonStairs { inner: MaterialStruct<'mc> }, + WarpedStairs { inner: MaterialStruct<'mc> }, + CommandBlock { inner: MaterialStruct<'mc> }, + Beacon { inner: MaterialStruct<'mc> }, + CobblestoneWall { inner: MaterialStruct<'mc> }, + MossyCobblestoneWall { inner: MaterialStruct<'mc> }, + BrickWall { inner: MaterialStruct<'mc> }, + PrismarineWall { inner: MaterialStruct<'mc> }, + RedSandstoneWall { inner: MaterialStruct<'mc> }, + MossyStoneBrickWall { inner: MaterialStruct<'mc> }, + GraniteWall { inner: MaterialStruct<'mc> }, + StoneBrickWall { inner: MaterialStruct<'mc> }, + MudBrickWall { inner: MaterialStruct<'mc> }, + NetherBrickWall { inner: MaterialStruct<'mc> }, + AndesiteWall { inner: MaterialStruct<'mc> }, + RedNetherBrickWall { inner: MaterialStruct<'mc> }, + SandstoneWall { inner: MaterialStruct<'mc> }, + EndStoneBrickWall { inner: MaterialStruct<'mc> }, + DioriteWall { inner: MaterialStruct<'mc> }, + BlackstoneWall { inner: MaterialStruct<'mc> }, + PolishedBlackstoneWall { inner: MaterialStruct<'mc> }, + PolishedBlackstoneBrickWall { inner: MaterialStruct<'mc> }, + CobbledDeepslateWall { inner: MaterialStruct<'mc> }, + PolishedDeepslateWall { inner: MaterialStruct<'mc> }, + DeepslateBrickWall { inner: MaterialStruct<'mc> }, + DeepslateTileWall { inner: MaterialStruct<'mc> }, + Anvil { inner: MaterialStruct<'mc> }, + ChippedAnvil { inner: MaterialStruct<'mc> }, + DamagedAnvil { inner: MaterialStruct<'mc> }, + ChiseledQuartzBlock { inner: MaterialStruct<'mc> }, + QuartzBlock { inner: MaterialStruct<'mc> }, + QuartzBricks { inner: MaterialStruct<'mc> }, + QuartzPillar { inner: MaterialStruct<'mc> }, + QuartzStairs { inner: MaterialStruct<'mc> }, + WhiteTerracotta { inner: MaterialStruct<'mc> }, + OrangeTerracotta { inner: MaterialStruct<'mc> }, + MagentaTerracotta { inner: MaterialStruct<'mc> }, + LightBlueTerracotta { inner: MaterialStruct<'mc> }, + YellowTerracotta { inner: MaterialStruct<'mc> }, + LimeTerracotta { inner: MaterialStruct<'mc> }, + PinkTerracotta { inner: MaterialStruct<'mc> }, + GrayTerracotta { inner: MaterialStruct<'mc> }, + LightGrayTerracotta { inner: MaterialStruct<'mc> }, + CyanTerracotta { inner: MaterialStruct<'mc> }, + PurpleTerracotta { inner: MaterialStruct<'mc> }, + BlueTerracotta { inner: MaterialStruct<'mc> }, + BrownTerracotta { inner: MaterialStruct<'mc> }, + GreenTerracotta { inner: MaterialStruct<'mc> }, + RedTerracotta { inner: MaterialStruct<'mc> }, + BlackTerracotta { inner: MaterialStruct<'mc> }, + Barrier { inner: MaterialStruct<'mc> }, + Light { inner: MaterialStruct<'mc> }, + HayBlock { inner: MaterialStruct<'mc> }, + WhiteCarpet { inner: MaterialStruct<'mc> }, + OrangeCarpet { inner: MaterialStruct<'mc> }, + MagentaCarpet { inner: MaterialStruct<'mc> }, + LightBlueCarpet { inner: MaterialStruct<'mc> }, + YellowCarpet { inner: MaterialStruct<'mc> }, + LimeCarpet { inner: MaterialStruct<'mc> }, + PinkCarpet { inner: MaterialStruct<'mc> }, + GrayCarpet { inner: MaterialStruct<'mc> }, + LightGrayCarpet { inner: MaterialStruct<'mc> }, + CyanCarpet { inner: MaterialStruct<'mc> }, + PurpleCarpet { inner: MaterialStruct<'mc> }, + BlueCarpet { inner: MaterialStruct<'mc> }, + BrownCarpet { inner: MaterialStruct<'mc> }, + GreenCarpet { inner: MaterialStruct<'mc> }, + RedCarpet { inner: MaterialStruct<'mc> }, + BlackCarpet { inner: MaterialStruct<'mc> }, + Terracotta { inner: MaterialStruct<'mc> }, + PackedIce { inner: MaterialStruct<'mc> }, + DirtPath { inner: MaterialStruct<'mc> }, + Sunflower { inner: MaterialStruct<'mc> }, + Lilac { inner: MaterialStruct<'mc> }, + RoseBush { inner: MaterialStruct<'mc> }, + Peony { inner: MaterialStruct<'mc> }, + TallGrass { inner: MaterialStruct<'mc> }, + LargeFern { inner: MaterialStruct<'mc> }, + WhiteStainedGlass { inner: MaterialStruct<'mc> }, + OrangeStainedGlass { inner: MaterialStruct<'mc> }, + MagentaStainedGlass { inner: MaterialStruct<'mc> }, + LightBlueStainedGlass { inner: MaterialStruct<'mc> }, + YellowStainedGlass { inner: MaterialStruct<'mc> }, + LimeStainedGlass { inner: MaterialStruct<'mc> }, + PinkStainedGlass { inner: MaterialStruct<'mc> }, + GrayStainedGlass { inner: MaterialStruct<'mc> }, + LightGrayStainedGlass { inner: MaterialStruct<'mc> }, + CyanStainedGlass { inner: MaterialStruct<'mc> }, + PurpleStainedGlass { inner: MaterialStruct<'mc> }, + BlueStainedGlass { inner: MaterialStruct<'mc> }, + BrownStainedGlass { inner: MaterialStruct<'mc> }, + GreenStainedGlass { inner: MaterialStruct<'mc> }, + RedStainedGlass { inner: MaterialStruct<'mc> }, + BlackStainedGlass { inner: MaterialStruct<'mc> }, + WhiteStainedGlassPane { inner: MaterialStruct<'mc> }, + OrangeStainedGlassPane { inner: MaterialStruct<'mc> }, + MagentaStainedGlassPane { inner: MaterialStruct<'mc> }, + LightBlueStainedGlassPane { inner: MaterialStruct<'mc> }, + YellowStainedGlassPane { inner: MaterialStruct<'mc> }, + LimeStainedGlassPane { inner: MaterialStruct<'mc> }, + PinkStainedGlassPane { inner: MaterialStruct<'mc> }, + GrayStainedGlassPane { inner: MaterialStruct<'mc> }, + LightGrayStainedGlassPane { inner: MaterialStruct<'mc> }, + CyanStainedGlassPane { inner: MaterialStruct<'mc> }, + PurpleStainedGlassPane { inner: MaterialStruct<'mc> }, + BlueStainedGlassPane { inner: MaterialStruct<'mc> }, + BrownStainedGlassPane { inner: MaterialStruct<'mc> }, + GreenStainedGlassPane { inner: MaterialStruct<'mc> }, + RedStainedGlassPane { inner: MaterialStruct<'mc> }, + BlackStainedGlassPane { inner: MaterialStruct<'mc> }, + Prismarine { inner: MaterialStruct<'mc> }, + PrismarineBricks { inner: MaterialStruct<'mc> }, + DarkPrismarine { inner: MaterialStruct<'mc> }, + PrismarineStairs { inner: MaterialStruct<'mc> }, + PrismarineBrickStairs { inner: MaterialStruct<'mc> }, + DarkPrismarineStairs { inner: MaterialStruct<'mc> }, + SeaLantern { inner: MaterialStruct<'mc> }, + RedSandstone { inner: MaterialStruct<'mc> }, + ChiseledRedSandstone { inner: MaterialStruct<'mc> }, + CutRedSandstone { inner: MaterialStruct<'mc> }, + RedSandstoneStairs { inner: MaterialStruct<'mc> }, + RepeatingCommandBlock { inner: MaterialStruct<'mc> }, + ChainCommandBlock { inner: MaterialStruct<'mc> }, + MagmaBlock { inner: MaterialStruct<'mc> }, + NetherWartBlock { inner: MaterialStruct<'mc> }, + WarpedWartBlock { inner: MaterialStruct<'mc> }, + RedNetherBricks { inner: MaterialStruct<'mc> }, + BoneBlock { inner: MaterialStruct<'mc> }, + StructureVoid { inner: MaterialStruct<'mc> }, + ShulkerBox { inner: MaterialStruct<'mc> }, + WhiteShulkerBox { inner: MaterialStruct<'mc> }, + OrangeShulkerBox { inner: MaterialStruct<'mc> }, + MagentaShulkerBox { inner: MaterialStruct<'mc> }, + LightBlueShulkerBox { inner: MaterialStruct<'mc> }, + YellowShulkerBox { inner: MaterialStruct<'mc> }, + LimeShulkerBox { inner: MaterialStruct<'mc> }, + PinkShulkerBox { inner: MaterialStruct<'mc> }, + GrayShulkerBox { inner: MaterialStruct<'mc> }, + LightGrayShulkerBox { inner: MaterialStruct<'mc> }, + CyanShulkerBox { inner: MaterialStruct<'mc> }, + PurpleShulkerBox { inner: MaterialStruct<'mc> }, + BlueShulkerBox { inner: MaterialStruct<'mc> }, + BrownShulkerBox { inner: MaterialStruct<'mc> }, + GreenShulkerBox { inner: MaterialStruct<'mc> }, + RedShulkerBox { inner: MaterialStruct<'mc> }, + BlackShulkerBox { inner: MaterialStruct<'mc> }, + WhiteGlazedTerracotta { inner: MaterialStruct<'mc> }, + OrangeGlazedTerracotta { inner: MaterialStruct<'mc> }, + MagentaGlazedTerracotta { inner: MaterialStruct<'mc> }, + LightBlueGlazedTerracotta { inner: MaterialStruct<'mc> }, + YellowGlazedTerracotta { inner: MaterialStruct<'mc> }, + LimeGlazedTerracotta { inner: MaterialStruct<'mc> }, + PinkGlazedTerracotta { inner: MaterialStruct<'mc> }, + GrayGlazedTerracotta { inner: MaterialStruct<'mc> }, + LightGrayGlazedTerracotta { inner: MaterialStruct<'mc> }, + CyanGlazedTerracotta { inner: MaterialStruct<'mc> }, + PurpleGlazedTerracotta { inner: MaterialStruct<'mc> }, + BlueGlazedTerracotta { inner: MaterialStruct<'mc> }, + BrownGlazedTerracotta { inner: MaterialStruct<'mc> }, + GreenGlazedTerracotta { inner: MaterialStruct<'mc> }, + RedGlazedTerracotta { inner: MaterialStruct<'mc> }, + BlackGlazedTerracotta { inner: MaterialStruct<'mc> }, + WhiteConcrete { inner: MaterialStruct<'mc> }, + OrangeConcrete { inner: MaterialStruct<'mc> }, + MagentaConcrete { inner: MaterialStruct<'mc> }, + LightBlueConcrete { inner: MaterialStruct<'mc> }, + YellowConcrete { inner: MaterialStruct<'mc> }, + LimeConcrete { inner: MaterialStruct<'mc> }, + PinkConcrete { inner: MaterialStruct<'mc> }, + GrayConcrete { inner: MaterialStruct<'mc> }, + LightGrayConcrete { inner: MaterialStruct<'mc> }, + CyanConcrete { inner: MaterialStruct<'mc> }, + PurpleConcrete { inner: MaterialStruct<'mc> }, + BlueConcrete { inner: MaterialStruct<'mc> }, + BrownConcrete { inner: MaterialStruct<'mc> }, + GreenConcrete { inner: MaterialStruct<'mc> }, + RedConcrete { inner: MaterialStruct<'mc> }, + BlackConcrete { inner: MaterialStruct<'mc> }, + WhiteConcretePowder { inner: MaterialStruct<'mc> }, + OrangeConcretePowder { inner: MaterialStruct<'mc> }, + MagentaConcretePowder { inner: MaterialStruct<'mc> }, + LightBlueConcretePowder { inner: MaterialStruct<'mc> }, + YellowConcretePowder { inner: MaterialStruct<'mc> }, + LimeConcretePowder { inner: MaterialStruct<'mc> }, + PinkConcretePowder { inner: MaterialStruct<'mc> }, + GrayConcretePowder { inner: MaterialStruct<'mc> }, + LightGrayConcretePowder { inner: MaterialStruct<'mc> }, + CyanConcretePowder { inner: MaterialStruct<'mc> }, + PurpleConcretePowder { inner: MaterialStruct<'mc> }, + BlueConcretePowder { inner: MaterialStruct<'mc> }, + BrownConcretePowder { inner: MaterialStruct<'mc> }, + GreenConcretePowder { inner: MaterialStruct<'mc> }, + RedConcretePowder { inner: MaterialStruct<'mc> }, + BlackConcretePowder { inner: MaterialStruct<'mc> }, + TurtleEgg { inner: MaterialStruct<'mc> }, + SnifferEgg { inner: MaterialStruct<'mc> }, + DeadTubeCoralBlock { inner: MaterialStruct<'mc> }, + DeadBrainCoralBlock { inner: MaterialStruct<'mc> }, + DeadBubbleCoralBlock { inner: MaterialStruct<'mc> }, + DeadFireCoralBlock { inner: MaterialStruct<'mc> }, + DeadHornCoralBlock { inner: MaterialStruct<'mc> }, + TubeCoralBlock { inner: MaterialStruct<'mc> }, + BrainCoralBlock { inner: MaterialStruct<'mc> }, + BubbleCoralBlock { inner: MaterialStruct<'mc> }, + FireCoralBlock { inner: MaterialStruct<'mc> }, + HornCoralBlock { inner: MaterialStruct<'mc> }, + TubeCoral { inner: MaterialStruct<'mc> }, + BrainCoral { inner: MaterialStruct<'mc> }, + BubbleCoral { inner: MaterialStruct<'mc> }, + FireCoral { inner: MaterialStruct<'mc> }, + HornCoral { inner: MaterialStruct<'mc> }, + DeadBrainCoral { inner: MaterialStruct<'mc> }, + DeadBubbleCoral { inner: MaterialStruct<'mc> }, + DeadFireCoral { inner: MaterialStruct<'mc> }, + DeadHornCoral { inner: MaterialStruct<'mc> }, + DeadTubeCoral { inner: MaterialStruct<'mc> }, + TubeCoralFan { inner: MaterialStruct<'mc> }, + BrainCoralFan { inner: MaterialStruct<'mc> }, + BubbleCoralFan { inner: MaterialStruct<'mc> }, + FireCoralFan { inner: MaterialStruct<'mc> }, + HornCoralFan { inner: MaterialStruct<'mc> }, + DeadTubeCoralFan { inner: MaterialStruct<'mc> }, + DeadBrainCoralFan { inner: MaterialStruct<'mc> }, + DeadBubbleCoralFan { inner: MaterialStruct<'mc> }, + DeadFireCoralFan { inner: MaterialStruct<'mc> }, + DeadHornCoralFan { inner: MaterialStruct<'mc> }, + BlueIce { inner: MaterialStruct<'mc> }, + Conduit { inner: MaterialStruct<'mc> }, + PolishedGraniteStairs { inner: MaterialStruct<'mc> }, + SmoothRedSandstoneStairs { inner: MaterialStruct<'mc> }, + MossyStoneBrickStairs { inner: MaterialStruct<'mc> }, + PolishedDioriteStairs { inner: MaterialStruct<'mc> }, + MossyCobblestoneStairs { inner: MaterialStruct<'mc> }, + EndStoneBrickStairs { inner: MaterialStruct<'mc> }, + StoneStairs { inner: MaterialStruct<'mc> }, + SmoothSandstoneStairs { inner: MaterialStruct<'mc> }, + SmoothQuartzStairs { inner: MaterialStruct<'mc> }, + GraniteStairs { inner: MaterialStruct<'mc> }, + AndesiteStairs { inner: MaterialStruct<'mc> }, + RedNetherBrickStairs { inner: MaterialStruct<'mc> }, + PolishedAndesiteStairs { inner: MaterialStruct<'mc> }, + DioriteStairs { inner: MaterialStruct<'mc> }, + CobbledDeepslateStairs { inner: MaterialStruct<'mc> }, + PolishedDeepslateStairs { inner: MaterialStruct<'mc> }, + DeepslateBrickStairs { inner: MaterialStruct<'mc> }, + DeepslateTileStairs { inner: MaterialStruct<'mc> }, + PolishedGraniteSlab { inner: MaterialStruct<'mc> }, + SmoothRedSandstoneSlab { inner: MaterialStruct<'mc> }, + MossyStoneBrickSlab { inner: MaterialStruct<'mc> }, + PolishedDioriteSlab { inner: MaterialStruct<'mc> }, + MossyCobblestoneSlab { inner: MaterialStruct<'mc> }, + EndStoneBrickSlab { inner: MaterialStruct<'mc> }, + SmoothSandstoneSlab { inner: MaterialStruct<'mc> }, + SmoothQuartzSlab { inner: MaterialStruct<'mc> }, + GraniteSlab { inner: MaterialStruct<'mc> }, + AndesiteSlab { inner: MaterialStruct<'mc> }, + RedNetherBrickSlab { inner: MaterialStruct<'mc> }, + PolishedAndesiteSlab { inner: MaterialStruct<'mc> }, + DioriteSlab { inner: MaterialStruct<'mc> }, + CobbledDeepslateSlab { inner: MaterialStruct<'mc> }, + PolishedDeepslateSlab { inner: MaterialStruct<'mc> }, + DeepslateBrickSlab { inner: MaterialStruct<'mc> }, + DeepslateTileSlab { inner: MaterialStruct<'mc> }, + Scaffolding { inner: MaterialStruct<'mc> }, + Redstone { inner: MaterialStruct<'mc> }, + RedstoneTorch { inner: MaterialStruct<'mc> }, + RedstoneBlock { inner: MaterialStruct<'mc> }, + Repeater { inner: MaterialStruct<'mc> }, + Comparator { inner: MaterialStruct<'mc> }, + Piston { inner: MaterialStruct<'mc> }, + StickyPiston { inner: MaterialStruct<'mc> }, + SlimeBlock { inner: MaterialStruct<'mc> }, + HoneyBlock { inner: MaterialStruct<'mc> }, + Observer { inner: MaterialStruct<'mc> }, + Hopper { inner: MaterialStruct<'mc> }, + Dispenser { inner: MaterialStruct<'mc> }, + Dropper { inner: MaterialStruct<'mc> }, + Lectern { inner: MaterialStruct<'mc> }, + Target { inner: MaterialStruct<'mc> }, + Lever { inner: MaterialStruct<'mc> }, + LightningRod { inner: MaterialStruct<'mc> }, + DaylightDetector { inner: MaterialStruct<'mc> }, + SculkSensor { inner: MaterialStruct<'mc> }, + CalibratedSculkSensor { inner: MaterialStruct<'mc> }, + TripwireHook { inner: MaterialStruct<'mc> }, + TrappedChest { inner: MaterialStruct<'mc> }, + Tnt { inner: MaterialStruct<'mc> }, + RedstoneLamp { inner: MaterialStruct<'mc> }, + NoteBlock { inner: MaterialStruct<'mc> }, + StoneButton { inner: MaterialStruct<'mc> }, + PolishedBlackstoneButton { inner: MaterialStruct<'mc> }, + OakButton { inner: MaterialStruct<'mc> }, + SpruceButton { inner: MaterialStruct<'mc> }, + BirchButton { inner: MaterialStruct<'mc> }, + JungleButton { inner: MaterialStruct<'mc> }, + AcaciaButton { inner: MaterialStruct<'mc> }, + CherryButton { inner: MaterialStruct<'mc> }, + DarkOakButton { inner: MaterialStruct<'mc> }, + MangroveButton { inner: MaterialStruct<'mc> }, + BambooButton { inner: MaterialStruct<'mc> }, + CrimsonButton { inner: MaterialStruct<'mc> }, + WarpedButton { inner: MaterialStruct<'mc> }, + StonePressurePlate { inner: MaterialStruct<'mc> }, + PolishedBlackstonePressurePlate { inner: MaterialStruct<'mc> }, + LightWeightedPressurePlate { inner: MaterialStruct<'mc> }, + HeavyWeightedPressurePlate { inner: MaterialStruct<'mc> }, + OakPressurePlate { inner: MaterialStruct<'mc> }, + SprucePressurePlate { inner: MaterialStruct<'mc> }, + BirchPressurePlate { inner: MaterialStruct<'mc> }, + JunglePressurePlate { inner: MaterialStruct<'mc> }, + AcaciaPressurePlate { inner: MaterialStruct<'mc> }, + CherryPressurePlate { inner: MaterialStruct<'mc> }, + DarkOakPressurePlate { inner: MaterialStruct<'mc> }, + MangrovePressurePlate { inner: MaterialStruct<'mc> }, + BambooPressurePlate { inner: MaterialStruct<'mc> }, + CrimsonPressurePlate { inner: MaterialStruct<'mc> }, + WarpedPressurePlate { inner: MaterialStruct<'mc> }, + IronDoor { inner: MaterialStruct<'mc> }, + OakDoor { inner: MaterialStruct<'mc> }, + SpruceDoor { inner: MaterialStruct<'mc> }, + BirchDoor { inner: MaterialStruct<'mc> }, + JungleDoor { inner: MaterialStruct<'mc> }, + AcaciaDoor { inner: MaterialStruct<'mc> }, + CherryDoor { inner: MaterialStruct<'mc> }, + DarkOakDoor { inner: MaterialStruct<'mc> }, + MangroveDoor { inner: MaterialStruct<'mc> }, + BambooDoor { inner: MaterialStruct<'mc> }, + CrimsonDoor { inner: MaterialStruct<'mc> }, + WarpedDoor { inner: MaterialStruct<'mc> }, + CopperDoor { inner: MaterialStruct<'mc> }, + ExposedCopperDoor { inner: MaterialStruct<'mc> }, + WeatheredCopperDoor { inner: MaterialStruct<'mc> }, + OxidizedCopperDoor { inner: MaterialStruct<'mc> }, + WaxedCopperDoor { inner: MaterialStruct<'mc> }, + WaxedExposedCopperDoor { inner: MaterialStruct<'mc> }, + WaxedWeatheredCopperDoor { inner: MaterialStruct<'mc> }, + WaxedOxidizedCopperDoor { inner: MaterialStruct<'mc> }, + IronTrapdoor { inner: MaterialStruct<'mc> }, + OakTrapdoor { inner: MaterialStruct<'mc> }, + SpruceTrapdoor { inner: MaterialStruct<'mc> }, + BirchTrapdoor { inner: MaterialStruct<'mc> }, + JungleTrapdoor { inner: MaterialStruct<'mc> }, + AcaciaTrapdoor { inner: MaterialStruct<'mc> }, + CherryTrapdoor { inner: MaterialStruct<'mc> }, + DarkOakTrapdoor { inner: MaterialStruct<'mc> }, + MangroveTrapdoor { inner: MaterialStruct<'mc> }, + BambooTrapdoor { inner: MaterialStruct<'mc> }, + CrimsonTrapdoor { inner: MaterialStruct<'mc> }, + WarpedTrapdoor { inner: MaterialStruct<'mc> }, + CopperTrapdoor { inner: MaterialStruct<'mc> }, + ExposedCopperTrapdoor { inner: MaterialStruct<'mc> }, + WeatheredCopperTrapdoor { inner: MaterialStruct<'mc> }, + OxidizedCopperTrapdoor { inner: MaterialStruct<'mc> }, + WaxedCopperTrapdoor { inner: MaterialStruct<'mc> }, + WaxedExposedCopperTrapdoor { inner: MaterialStruct<'mc> }, + WaxedWeatheredCopperTrapdoor { inner: MaterialStruct<'mc> }, + WaxedOxidizedCopperTrapdoor { inner: MaterialStruct<'mc> }, + OakFenceGate { inner: MaterialStruct<'mc> }, + SpruceFenceGate { inner: MaterialStruct<'mc> }, + BirchFenceGate { inner: MaterialStruct<'mc> }, + JungleFenceGate { inner: MaterialStruct<'mc> }, + AcaciaFenceGate { inner: MaterialStruct<'mc> }, + CherryFenceGate { inner: MaterialStruct<'mc> }, + DarkOakFenceGate { inner: MaterialStruct<'mc> }, + MangroveFenceGate { inner: MaterialStruct<'mc> }, + BambooFenceGate { inner: MaterialStruct<'mc> }, + CrimsonFenceGate { inner: MaterialStruct<'mc> }, + WarpedFenceGate { inner: MaterialStruct<'mc> }, + PoweredRail { inner: MaterialStruct<'mc> }, + DetectorRail { inner: MaterialStruct<'mc> }, + Rail { inner: MaterialStruct<'mc> }, + ActivatorRail { inner: MaterialStruct<'mc> }, + Saddle { inner: MaterialStruct<'mc> }, + Minecart { inner: MaterialStruct<'mc> }, + ChestMinecart { inner: MaterialStruct<'mc> }, + FurnaceMinecart { inner: MaterialStruct<'mc> }, + TntMinecart { inner: MaterialStruct<'mc> }, + HopperMinecart { inner: MaterialStruct<'mc> }, + CarrotOnAStick { inner: MaterialStruct<'mc> }, + WarpedFungusOnAStick { inner: MaterialStruct<'mc> }, + Elytra { inner: MaterialStruct<'mc> }, + OakBoat { inner: MaterialStruct<'mc> }, + OakChestBoat { inner: MaterialStruct<'mc> }, + SpruceBoat { inner: MaterialStruct<'mc> }, + SpruceChestBoat { inner: MaterialStruct<'mc> }, + BirchBoat { inner: MaterialStruct<'mc> }, + BirchChestBoat { inner: MaterialStruct<'mc> }, + JungleBoat { inner: MaterialStruct<'mc> }, + JungleChestBoat { inner: MaterialStruct<'mc> }, + AcaciaBoat { inner: MaterialStruct<'mc> }, + AcaciaChestBoat { inner: MaterialStruct<'mc> }, + CherryBoat { inner: MaterialStruct<'mc> }, + CherryChestBoat { inner: MaterialStruct<'mc> }, + DarkOakBoat { inner: MaterialStruct<'mc> }, + DarkOakChestBoat { inner: MaterialStruct<'mc> }, + MangroveBoat { inner: MaterialStruct<'mc> }, + MangroveChestBoat { inner: MaterialStruct<'mc> }, + BambooRaft { inner: MaterialStruct<'mc> }, + BambooChestRaft { inner: MaterialStruct<'mc> }, + StructureBlock { inner: MaterialStruct<'mc> }, + Jigsaw { inner: MaterialStruct<'mc> }, + TurtleHelmet { inner: MaterialStruct<'mc> }, + TurtleScute { inner: MaterialStruct<'mc> }, + ArmadilloScute { inner: MaterialStruct<'mc> }, + WolfArmor { inner: MaterialStruct<'mc> }, + FlintAndSteel { inner: MaterialStruct<'mc> }, + Bowl { inner: MaterialStruct<'mc> }, + Apple { inner: MaterialStruct<'mc> }, + Bow { inner: MaterialStruct<'mc> }, + Arrow { inner: MaterialStruct<'mc> }, + Coal { inner: MaterialStruct<'mc> }, + Charcoal { inner: MaterialStruct<'mc> }, + Diamond { inner: MaterialStruct<'mc> }, + Emerald { inner: MaterialStruct<'mc> }, + LapisLazuli { inner: MaterialStruct<'mc> }, + Quartz { inner: MaterialStruct<'mc> }, + AmethystShard { inner: MaterialStruct<'mc> }, + RawIron { inner: MaterialStruct<'mc> }, + IronIngot { inner: MaterialStruct<'mc> }, + RawCopper { inner: MaterialStruct<'mc> }, + CopperIngot { inner: MaterialStruct<'mc> }, + RawGold { inner: MaterialStruct<'mc> }, + GoldIngot { inner: MaterialStruct<'mc> }, + NetheriteIngot { inner: MaterialStruct<'mc> }, + NetheriteScrap { inner: MaterialStruct<'mc> }, + WoodenSword { inner: MaterialStruct<'mc> }, + WoodenShovel { inner: MaterialStruct<'mc> }, + WoodenPickaxe { inner: MaterialStruct<'mc> }, + WoodenAxe { inner: MaterialStruct<'mc> }, + WoodenHoe { inner: MaterialStruct<'mc> }, + StoneSword { inner: MaterialStruct<'mc> }, + StoneShovel { inner: MaterialStruct<'mc> }, + StonePickaxe { inner: MaterialStruct<'mc> }, + StoneAxe { inner: MaterialStruct<'mc> }, + StoneHoe { inner: MaterialStruct<'mc> }, + GoldenSword { inner: MaterialStruct<'mc> }, + GoldenShovel { inner: MaterialStruct<'mc> }, + GoldenPickaxe { inner: MaterialStruct<'mc> }, + GoldenAxe { inner: MaterialStruct<'mc> }, + GoldenHoe { inner: MaterialStruct<'mc> }, + IronSword { inner: MaterialStruct<'mc> }, + IronShovel { inner: MaterialStruct<'mc> }, + IronPickaxe { inner: MaterialStruct<'mc> }, + IronAxe { inner: MaterialStruct<'mc> }, + IronHoe { inner: MaterialStruct<'mc> }, + DiamondSword { inner: MaterialStruct<'mc> }, + DiamondShovel { inner: MaterialStruct<'mc> }, + DiamondPickaxe { inner: MaterialStruct<'mc> }, + DiamondAxe { inner: MaterialStruct<'mc> }, + DiamondHoe { inner: MaterialStruct<'mc> }, + NetheriteSword { inner: MaterialStruct<'mc> }, + NetheriteShovel { inner: MaterialStruct<'mc> }, + NetheritePickaxe { inner: MaterialStruct<'mc> }, + NetheriteAxe { inner: MaterialStruct<'mc> }, + NetheriteHoe { inner: MaterialStruct<'mc> }, + Stick { inner: MaterialStruct<'mc> }, + MushroomStew { inner: MaterialStruct<'mc> }, + String { inner: MaterialStruct<'mc> }, + Feather { inner: MaterialStruct<'mc> }, + Gunpowder { inner: MaterialStruct<'mc> }, + WheatSeeds { inner: MaterialStruct<'mc> }, + Wheat { inner: MaterialStruct<'mc> }, + Bread { inner: MaterialStruct<'mc> }, + LeatherHelmet { inner: MaterialStruct<'mc> }, + LeatherChestplate { inner: MaterialStruct<'mc> }, + LeatherLeggings { inner: MaterialStruct<'mc> }, + LeatherBoots { inner: MaterialStruct<'mc> }, + ChainmailHelmet { inner: MaterialStruct<'mc> }, + ChainmailChestplate { inner: MaterialStruct<'mc> }, + ChainmailLeggings { inner: MaterialStruct<'mc> }, + ChainmailBoots { inner: MaterialStruct<'mc> }, + IronHelmet { inner: MaterialStruct<'mc> }, + IronChestplate { inner: MaterialStruct<'mc> }, + IronLeggings { inner: MaterialStruct<'mc> }, + IronBoots { inner: MaterialStruct<'mc> }, + DiamondHelmet { inner: MaterialStruct<'mc> }, + DiamondChestplate { inner: MaterialStruct<'mc> }, + DiamondLeggings { inner: MaterialStruct<'mc> }, + DiamondBoots { inner: MaterialStruct<'mc> }, + GoldenHelmet { inner: MaterialStruct<'mc> }, + GoldenChestplate { inner: MaterialStruct<'mc> }, + GoldenLeggings { inner: MaterialStruct<'mc> }, + GoldenBoots { inner: MaterialStruct<'mc> }, + NetheriteHelmet { inner: MaterialStruct<'mc> }, + NetheriteChestplate { inner: MaterialStruct<'mc> }, + NetheriteLeggings { inner: MaterialStruct<'mc> }, + NetheriteBoots { inner: MaterialStruct<'mc> }, + Flint { inner: MaterialStruct<'mc> }, + Porkchop { inner: MaterialStruct<'mc> }, + CookedPorkchop { inner: MaterialStruct<'mc> }, + Painting { inner: MaterialStruct<'mc> }, + GoldenApple { inner: MaterialStruct<'mc> }, + EnchantedGoldenApple { inner: MaterialStruct<'mc> }, + OakSign { inner: MaterialStruct<'mc> }, + SpruceSign { inner: MaterialStruct<'mc> }, + BirchSign { inner: MaterialStruct<'mc> }, + JungleSign { inner: MaterialStruct<'mc> }, + AcaciaSign { inner: MaterialStruct<'mc> }, + CherrySign { inner: MaterialStruct<'mc> }, + DarkOakSign { inner: MaterialStruct<'mc> }, + MangroveSign { inner: MaterialStruct<'mc> }, + BambooSign { inner: MaterialStruct<'mc> }, + CrimsonSign { inner: MaterialStruct<'mc> }, + WarpedSign { inner: MaterialStruct<'mc> }, + OakHangingSign { inner: MaterialStruct<'mc> }, + SpruceHangingSign { inner: MaterialStruct<'mc> }, + BirchHangingSign { inner: MaterialStruct<'mc> }, + JungleHangingSign { inner: MaterialStruct<'mc> }, + AcaciaHangingSign { inner: MaterialStruct<'mc> }, + CherryHangingSign { inner: MaterialStruct<'mc> }, + DarkOakHangingSign { inner: MaterialStruct<'mc> }, + MangroveHangingSign { inner: MaterialStruct<'mc> }, + BambooHangingSign { inner: MaterialStruct<'mc> }, + CrimsonHangingSign { inner: MaterialStruct<'mc> }, + WarpedHangingSign { inner: MaterialStruct<'mc> }, + Bucket { inner: MaterialStruct<'mc> }, + WaterBucket { inner: MaterialStruct<'mc> }, + LavaBucket { inner: MaterialStruct<'mc> }, + PowderSnowBucket { inner: MaterialStruct<'mc> }, + Snowball { inner: MaterialStruct<'mc> }, + Leather { inner: MaterialStruct<'mc> }, + MilkBucket { inner: MaterialStruct<'mc> }, + PufferfishBucket { inner: MaterialStruct<'mc> }, + SalmonBucket { inner: MaterialStruct<'mc> }, + CodBucket { inner: MaterialStruct<'mc> }, + TropicalFishBucket { inner: MaterialStruct<'mc> }, + AxolotlBucket { inner: MaterialStruct<'mc> }, + TadpoleBucket { inner: MaterialStruct<'mc> }, + Brick { inner: MaterialStruct<'mc> }, + ClayBall { inner: MaterialStruct<'mc> }, + DriedKelpBlock { inner: MaterialStruct<'mc> }, + Paper { inner: MaterialStruct<'mc> }, + Book { inner: MaterialStruct<'mc> }, + SlimeBall { inner: MaterialStruct<'mc> }, + Egg { inner: MaterialStruct<'mc> }, + Compass { inner: MaterialStruct<'mc> }, + RecoveryCompass { inner: MaterialStruct<'mc> }, + Bundle { inner: MaterialStruct<'mc> }, + FishingRod { inner: MaterialStruct<'mc> }, + Clock { inner: MaterialStruct<'mc> }, + Spyglass { inner: MaterialStruct<'mc> }, + GlowstoneDust { inner: MaterialStruct<'mc> }, + Cod { inner: MaterialStruct<'mc> }, + Salmon { inner: MaterialStruct<'mc> }, + TropicalFish { inner: MaterialStruct<'mc> }, + Pufferfish { inner: MaterialStruct<'mc> }, + CookedCod { inner: MaterialStruct<'mc> }, + CookedSalmon { inner: MaterialStruct<'mc> }, + InkSac { inner: MaterialStruct<'mc> }, + GlowInkSac { inner: MaterialStruct<'mc> }, + CocoaBeans { inner: MaterialStruct<'mc> }, + WhiteDye { inner: MaterialStruct<'mc> }, + OrangeDye { inner: MaterialStruct<'mc> }, + MagentaDye { inner: MaterialStruct<'mc> }, + LightBlueDye { inner: MaterialStruct<'mc> }, + YellowDye { inner: MaterialStruct<'mc> }, + LimeDye { inner: MaterialStruct<'mc> }, + PinkDye { inner: MaterialStruct<'mc> }, + GrayDye { inner: MaterialStruct<'mc> }, + LightGrayDye { inner: MaterialStruct<'mc> }, + CyanDye { inner: MaterialStruct<'mc> }, + PurpleDye { inner: MaterialStruct<'mc> }, + BlueDye { inner: MaterialStruct<'mc> }, + BrownDye { inner: MaterialStruct<'mc> }, + GreenDye { inner: MaterialStruct<'mc> }, + RedDye { inner: MaterialStruct<'mc> }, + BlackDye { inner: MaterialStruct<'mc> }, + BoneMeal { inner: MaterialStruct<'mc> }, + Bone { inner: MaterialStruct<'mc> }, + Sugar { inner: MaterialStruct<'mc> }, + Cake { inner: MaterialStruct<'mc> }, + WhiteBed { inner: MaterialStruct<'mc> }, + OrangeBed { inner: MaterialStruct<'mc> }, + MagentaBed { inner: MaterialStruct<'mc> }, + LightBlueBed { inner: MaterialStruct<'mc> }, + YellowBed { inner: MaterialStruct<'mc> }, + LimeBed { inner: MaterialStruct<'mc> }, + PinkBed { inner: MaterialStruct<'mc> }, + GrayBed { inner: MaterialStruct<'mc> }, + LightGrayBed { inner: MaterialStruct<'mc> }, + CyanBed { inner: MaterialStruct<'mc> }, + PurpleBed { inner: MaterialStruct<'mc> }, + BlueBed { inner: MaterialStruct<'mc> }, + BrownBed { inner: MaterialStruct<'mc> }, + GreenBed { inner: MaterialStruct<'mc> }, + RedBed { inner: MaterialStruct<'mc> }, + BlackBed { inner: MaterialStruct<'mc> }, + Cookie { inner: MaterialStruct<'mc> }, + Crafter { inner: MaterialStruct<'mc> }, + FilledMap { inner: MaterialStruct<'mc> }, + Shears { inner: MaterialStruct<'mc> }, + MelonSlice { inner: MaterialStruct<'mc> }, + DriedKelp { inner: MaterialStruct<'mc> }, + PumpkinSeeds { inner: MaterialStruct<'mc> }, + MelonSeeds { inner: MaterialStruct<'mc> }, + Beef { inner: MaterialStruct<'mc> }, + CookedBeef { inner: MaterialStruct<'mc> }, + Chicken { inner: MaterialStruct<'mc> }, + CookedChicken { inner: MaterialStruct<'mc> }, + RottenFlesh { inner: MaterialStruct<'mc> }, + EnderPearl { inner: MaterialStruct<'mc> }, + BlazeRod { inner: MaterialStruct<'mc> }, + GhastTear { inner: MaterialStruct<'mc> }, + GoldNugget { inner: MaterialStruct<'mc> }, + NetherWart { inner: MaterialStruct<'mc> }, + Potion { inner: MaterialStruct<'mc> }, + GlassBottle { inner: MaterialStruct<'mc> }, + SpiderEye { inner: MaterialStruct<'mc> }, + FermentedSpiderEye { inner: MaterialStruct<'mc> }, + BlazePowder { inner: MaterialStruct<'mc> }, + MagmaCream { inner: MaterialStruct<'mc> }, + BrewingStand { inner: MaterialStruct<'mc> }, + Cauldron { inner: MaterialStruct<'mc> }, + EnderEye { inner: MaterialStruct<'mc> }, + GlisteringMelonSlice { inner: MaterialStruct<'mc> }, + ArmadilloSpawnEgg { inner: MaterialStruct<'mc> }, + AllaySpawnEgg { inner: MaterialStruct<'mc> }, + AxolotlSpawnEgg { inner: MaterialStruct<'mc> }, + BatSpawnEgg { inner: MaterialStruct<'mc> }, + BeeSpawnEgg { inner: MaterialStruct<'mc> }, + BlazeSpawnEgg { inner: MaterialStruct<'mc> }, + BoggedSpawnEgg { inner: MaterialStruct<'mc> }, + BreezeSpawnEgg { inner: MaterialStruct<'mc> }, + CatSpawnEgg { inner: MaterialStruct<'mc> }, + CamelSpawnEgg { inner: MaterialStruct<'mc> }, + CaveSpiderSpawnEgg { inner: MaterialStruct<'mc> }, + ChickenSpawnEgg { inner: MaterialStruct<'mc> }, + CodSpawnEgg { inner: MaterialStruct<'mc> }, + CowSpawnEgg { inner: MaterialStruct<'mc> }, + CreeperSpawnEgg { inner: MaterialStruct<'mc> }, + DolphinSpawnEgg { inner: MaterialStruct<'mc> }, + DonkeySpawnEgg { inner: MaterialStruct<'mc> }, + DrownedSpawnEgg { inner: MaterialStruct<'mc> }, + ElderGuardianSpawnEgg { inner: MaterialStruct<'mc> }, + EnderDragonSpawnEgg { inner: MaterialStruct<'mc> }, + EndermanSpawnEgg { inner: MaterialStruct<'mc> }, + EndermiteSpawnEgg { inner: MaterialStruct<'mc> }, + EvokerSpawnEgg { inner: MaterialStruct<'mc> }, + FoxSpawnEgg { inner: MaterialStruct<'mc> }, + FrogSpawnEgg { inner: MaterialStruct<'mc> }, + GhastSpawnEgg { inner: MaterialStruct<'mc> }, + GlowSquidSpawnEgg { inner: MaterialStruct<'mc> }, + GoatSpawnEgg { inner: MaterialStruct<'mc> }, + GuardianSpawnEgg { inner: MaterialStruct<'mc> }, + HoglinSpawnEgg { inner: MaterialStruct<'mc> }, + HorseSpawnEgg { inner: MaterialStruct<'mc> }, + HuskSpawnEgg { inner: MaterialStruct<'mc> }, + IronGolemSpawnEgg { inner: MaterialStruct<'mc> }, + LlamaSpawnEgg { inner: MaterialStruct<'mc> }, + MagmaCubeSpawnEgg { inner: MaterialStruct<'mc> }, + MooshroomSpawnEgg { inner: MaterialStruct<'mc> }, + MuleSpawnEgg { inner: MaterialStruct<'mc> }, + OcelotSpawnEgg { inner: MaterialStruct<'mc> }, + PandaSpawnEgg { inner: MaterialStruct<'mc> }, + ParrotSpawnEgg { inner: MaterialStruct<'mc> }, + PhantomSpawnEgg { inner: MaterialStruct<'mc> }, + PigSpawnEgg { inner: MaterialStruct<'mc> }, + PiglinSpawnEgg { inner: MaterialStruct<'mc> }, + PiglinBruteSpawnEgg { inner: MaterialStruct<'mc> }, + PillagerSpawnEgg { inner: MaterialStruct<'mc> }, + PolarBearSpawnEgg { inner: MaterialStruct<'mc> }, + PufferfishSpawnEgg { inner: MaterialStruct<'mc> }, + RabbitSpawnEgg { inner: MaterialStruct<'mc> }, + RavagerSpawnEgg { inner: MaterialStruct<'mc> }, + SalmonSpawnEgg { inner: MaterialStruct<'mc> }, + SheepSpawnEgg { inner: MaterialStruct<'mc> }, + ShulkerSpawnEgg { inner: MaterialStruct<'mc> }, + SilverfishSpawnEgg { inner: MaterialStruct<'mc> }, + SkeletonSpawnEgg { inner: MaterialStruct<'mc> }, + SkeletonHorseSpawnEgg { inner: MaterialStruct<'mc> }, + SlimeSpawnEgg { inner: MaterialStruct<'mc> }, + SnifferSpawnEgg { inner: MaterialStruct<'mc> }, + SnowGolemSpawnEgg { inner: MaterialStruct<'mc> }, + SpiderSpawnEgg { inner: MaterialStruct<'mc> }, + SquidSpawnEgg { inner: MaterialStruct<'mc> }, + StraySpawnEgg { inner: MaterialStruct<'mc> }, + StriderSpawnEgg { inner: MaterialStruct<'mc> }, + TadpoleSpawnEgg { inner: MaterialStruct<'mc> }, + TraderLlamaSpawnEgg { inner: MaterialStruct<'mc> }, + TropicalFishSpawnEgg { inner: MaterialStruct<'mc> }, + TurtleSpawnEgg { inner: MaterialStruct<'mc> }, + VexSpawnEgg { inner: MaterialStruct<'mc> }, + VillagerSpawnEgg { inner: MaterialStruct<'mc> }, + VindicatorSpawnEgg { inner: MaterialStruct<'mc> }, + WanderingTraderSpawnEgg { inner: MaterialStruct<'mc> }, + WardenSpawnEgg { inner: MaterialStruct<'mc> }, + WitchSpawnEgg { inner: MaterialStruct<'mc> }, + WitherSpawnEgg { inner: MaterialStruct<'mc> }, + WitherSkeletonSpawnEgg { inner: MaterialStruct<'mc> }, + WolfSpawnEgg { inner: MaterialStruct<'mc> }, + ZoglinSpawnEgg { inner: MaterialStruct<'mc> }, + ZombieSpawnEgg { inner: MaterialStruct<'mc> }, + ZombieHorseSpawnEgg { inner: MaterialStruct<'mc> }, + ZombieVillagerSpawnEgg { inner: MaterialStruct<'mc> }, + ZombifiedPiglinSpawnEgg { inner: MaterialStruct<'mc> }, + ExperienceBottle { inner: MaterialStruct<'mc> }, + FireCharge { inner: MaterialStruct<'mc> }, + WindCharge { inner: MaterialStruct<'mc> }, + WritableBook { inner: MaterialStruct<'mc> }, + WrittenBook { inner: MaterialStruct<'mc> }, + Mace { inner: MaterialStruct<'mc> }, + ItemFrame { inner: MaterialStruct<'mc> }, + GlowItemFrame { inner: MaterialStruct<'mc> }, + FlowerPot { inner: MaterialStruct<'mc> }, + Carrot { inner: MaterialStruct<'mc> }, + Potato { inner: MaterialStruct<'mc> }, + BakedPotato { inner: MaterialStruct<'mc> }, + PoisonousPotato { inner: MaterialStruct<'mc> }, + Map { inner: MaterialStruct<'mc> }, + GoldenCarrot { inner: MaterialStruct<'mc> }, + SkeletonSkull { inner: MaterialStruct<'mc> }, + WitherSkeletonSkull { inner: MaterialStruct<'mc> }, + PlayerHead { inner: MaterialStruct<'mc> }, + ZombieHead { inner: MaterialStruct<'mc> }, + CreeperHead { inner: MaterialStruct<'mc> }, + DragonHead { inner: MaterialStruct<'mc> }, + PiglinHead { inner: MaterialStruct<'mc> }, + NetherStar { inner: MaterialStruct<'mc> }, + PumpkinPie { inner: MaterialStruct<'mc> }, + FireworkRocket { inner: MaterialStruct<'mc> }, + FireworkStar { inner: MaterialStruct<'mc> }, + EnchantedBook { inner: MaterialStruct<'mc> }, + NetherBrick { inner: MaterialStruct<'mc> }, + PrismarineShard { inner: MaterialStruct<'mc> }, + PrismarineCrystals { inner: MaterialStruct<'mc> }, + Rabbit { inner: MaterialStruct<'mc> }, + CookedRabbit { inner: MaterialStruct<'mc> }, + RabbitStew { inner: MaterialStruct<'mc> }, + RabbitFoot { inner: MaterialStruct<'mc> }, + RabbitHide { inner: MaterialStruct<'mc> }, + ArmorStand { inner: MaterialStruct<'mc> }, + IronHorseArmor { inner: MaterialStruct<'mc> }, + GoldenHorseArmor { inner: MaterialStruct<'mc> }, + DiamondHorseArmor { inner: MaterialStruct<'mc> }, + LeatherHorseArmor { inner: MaterialStruct<'mc> }, + Lead { inner: MaterialStruct<'mc> }, + NameTag { inner: MaterialStruct<'mc> }, + CommandBlockMinecart { inner: MaterialStruct<'mc> }, + Mutton { inner: MaterialStruct<'mc> }, + CookedMutton { inner: MaterialStruct<'mc> }, + WhiteBanner { inner: MaterialStruct<'mc> }, + OrangeBanner { inner: MaterialStruct<'mc> }, + MagentaBanner { inner: MaterialStruct<'mc> }, + LightBlueBanner { inner: MaterialStruct<'mc> }, + YellowBanner { inner: MaterialStruct<'mc> }, + LimeBanner { inner: MaterialStruct<'mc> }, + PinkBanner { inner: MaterialStruct<'mc> }, + GrayBanner { inner: MaterialStruct<'mc> }, + LightGrayBanner { inner: MaterialStruct<'mc> }, + CyanBanner { inner: MaterialStruct<'mc> }, + PurpleBanner { inner: MaterialStruct<'mc> }, + BlueBanner { inner: MaterialStruct<'mc> }, + BrownBanner { inner: MaterialStruct<'mc> }, + GreenBanner { inner: MaterialStruct<'mc> }, + RedBanner { inner: MaterialStruct<'mc> }, + BlackBanner { inner: MaterialStruct<'mc> }, + EndCrystal { inner: MaterialStruct<'mc> }, + ChorusFruit { inner: MaterialStruct<'mc> }, + PoppedChorusFruit { inner: MaterialStruct<'mc> }, + TorchflowerSeeds { inner: MaterialStruct<'mc> }, + PitcherPod { inner: MaterialStruct<'mc> }, + Beetroot { inner: MaterialStruct<'mc> }, + BeetrootSeeds { inner: MaterialStruct<'mc> }, + BeetrootSoup { inner: MaterialStruct<'mc> }, + DragonBreath { inner: MaterialStruct<'mc> }, + SplashPotion { inner: MaterialStruct<'mc> }, + SpectralArrow { inner: MaterialStruct<'mc> }, + TippedArrow { inner: MaterialStruct<'mc> }, + LingeringPotion { inner: MaterialStruct<'mc> }, + Shield { inner: MaterialStruct<'mc> }, + TotemOfUndying { inner: MaterialStruct<'mc> }, + ShulkerShell { inner: MaterialStruct<'mc> }, + IronNugget { inner: MaterialStruct<'mc> }, + KnowledgeBook { inner: MaterialStruct<'mc> }, + DebugStick { inner: MaterialStruct<'mc> }, + MusicDisc13 { inner: MaterialStruct<'mc> }, + MusicDiscCat { inner: MaterialStruct<'mc> }, + MusicDiscBlocks { inner: MaterialStruct<'mc> }, + MusicDiscChirp { inner: MaterialStruct<'mc> }, + MusicDiscCreator { inner: MaterialStruct<'mc> }, + MusicDiscCreatorMusicBox { inner: MaterialStruct<'mc> }, + MusicDiscFar { inner: MaterialStruct<'mc> }, + MusicDiscMall { inner: MaterialStruct<'mc> }, + MusicDiscMellohi { inner: MaterialStruct<'mc> }, + MusicDiscStal { inner: MaterialStruct<'mc> }, + MusicDiscStrad { inner: MaterialStruct<'mc> }, + MusicDiscWard { inner: MaterialStruct<'mc> }, + MusicDisc11 { inner: MaterialStruct<'mc> }, + MusicDiscWait { inner: MaterialStruct<'mc> }, + MusicDiscOtherside { inner: MaterialStruct<'mc> }, + MusicDiscRelic { inner: MaterialStruct<'mc> }, + MusicDisc5 { inner: MaterialStruct<'mc> }, + MusicDiscPigstep { inner: MaterialStruct<'mc> }, + MusicDiscPrecipice { inner: MaterialStruct<'mc> }, + DiscFragment5 { inner: MaterialStruct<'mc> }, + Trident { inner: MaterialStruct<'mc> }, + PhantomMembrane { inner: MaterialStruct<'mc> }, + NautilusShell { inner: MaterialStruct<'mc> }, + HeartOfTheSea { inner: MaterialStruct<'mc> }, + Crossbow { inner: MaterialStruct<'mc> }, + SuspiciousStew { inner: MaterialStruct<'mc> }, + Loom { inner: MaterialStruct<'mc> }, + FlowerBannerPattern { inner: MaterialStruct<'mc> }, + CreeperBannerPattern { inner: MaterialStruct<'mc> }, + SkullBannerPattern { inner: MaterialStruct<'mc> }, + MojangBannerPattern { inner: MaterialStruct<'mc> }, + GlobeBannerPattern { inner: MaterialStruct<'mc> }, + PiglinBannerPattern { inner: MaterialStruct<'mc> }, + FlowBannerPattern { inner: MaterialStruct<'mc> }, + GusterBannerPattern { inner: MaterialStruct<'mc> }, + GoatHorn { inner: MaterialStruct<'mc> }, + Composter { inner: MaterialStruct<'mc> }, + Barrel { inner: MaterialStruct<'mc> }, + Smoker { inner: MaterialStruct<'mc> }, + BlastFurnace { inner: MaterialStruct<'mc> }, + CartographyTable { inner: MaterialStruct<'mc> }, + FletchingTable { inner: MaterialStruct<'mc> }, + Grindstone { inner: MaterialStruct<'mc> }, + SmithingTable { inner: MaterialStruct<'mc> }, + Stonecutter { inner: MaterialStruct<'mc> }, + Bell { inner: MaterialStruct<'mc> }, + Lantern { inner: MaterialStruct<'mc> }, + SoulLantern { inner: MaterialStruct<'mc> }, + SweetBerries { inner: MaterialStruct<'mc> }, + GlowBerries { inner: MaterialStruct<'mc> }, + Campfire { inner: MaterialStruct<'mc> }, + SoulCampfire { inner: MaterialStruct<'mc> }, + Shroomlight { inner: MaterialStruct<'mc> }, + Honeycomb { inner: MaterialStruct<'mc> }, + BeeNest { inner: MaterialStruct<'mc> }, + Beehive { inner: MaterialStruct<'mc> }, + HoneyBottle { inner: MaterialStruct<'mc> }, + HoneycombBlock { inner: MaterialStruct<'mc> }, + Lodestone { inner: MaterialStruct<'mc> }, + CryingObsidian { inner: MaterialStruct<'mc> }, + Blackstone { inner: MaterialStruct<'mc> }, + BlackstoneSlab { inner: MaterialStruct<'mc> }, + BlackstoneStairs { inner: MaterialStruct<'mc> }, + GildedBlackstone { inner: MaterialStruct<'mc> }, + PolishedBlackstone { inner: MaterialStruct<'mc> }, + PolishedBlackstoneSlab { inner: MaterialStruct<'mc> }, + PolishedBlackstoneStairs { inner: MaterialStruct<'mc> }, + ChiseledPolishedBlackstone { inner: MaterialStruct<'mc> }, + PolishedBlackstoneBricks { inner: MaterialStruct<'mc> }, + PolishedBlackstoneBrickSlab { inner: MaterialStruct<'mc> }, + PolishedBlackstoneBrickStairs { inner: MaterialStruct<'mc> }, + CrackedPolishedBlackstoneBricks { inner: MaterialStruct<'mc> }, + RespawnAnchor { inner: MaterialStruct<'mc> }, + Candle { inner: MaterialStruct<'mc> }, + WhiteCandle { inner: MaterialStruct<'mc> }, + OrangeCandle { inner: MaterialStruct<'mc> }, + MagentaCandle { inner: MaterialStruct<'mc> }, + LightBlueCandle { inner: MaterialStruct<'mc> }, + YellowCandle { inner: MaterialStruct<'mc> }, + LimeCandle { inner: MaterialStruct<'mc> }, + PinkCandle { inner: MaterialStruct<'mc> }, + GrayCandle { inner: MaterialStruct<'mc> }, + LightGrayCandle { inner: MaterialStruct<'mc> }, + CyanCandle { inner: MaterialStruct<'mc> }, + PurpleCandle { inner: MaterialStruct<'mc> }, + BlueCandle { inner: MaterialStruct<'mc> }, + BrownCandle { inner: MaterialStruct<'mc> }, + GreenCandle { inner: MaterialStruct<'mc> }, + RedCandle { inner: MaterialStruct<'mc> }, + BlackCandle { inner: MaterialStruct<'mc> }, + SmallAmethystBud { inner: MaterialStruct<'mc> }, + MediumAmethystBud { inner: MaterialStruct<'mc> }, + LargeAmethystBud { inner: MaterialStruct<'mc> }, + AmethystCluster { inner: MaterialStruct<'mc> }, + PointedDripstone { inner: MaterialStruct<'mc> }, + OchreFroglight { inner: MaterialStruct<'mc> }, + VerdantFroglight { inner: MaterialStruct<'mc> }, + PearlescentFroglight { inner: MaterialStruct<'mc> }, + Frogspawn { inner: MaterialStruct<'mc> }, + EchoShard { inner: MaterialStruct<'mc> }, + Brush { inner: MaterialStruct<'mc> }, + NetheriteUpgradeSmithingTemplate { inner: MaterialStruct<'mc> }, + SentryArmorTrimSmithingTemplate { inner: MaterialStruct<'mc> }, + DuneArmorTrimSmithingTemplate { inner: MaterialStruct<'mc> }, + CoastArmorTrimSmithingTemplate { inner: MaterialStruct<'mc> }, + WildArmorTrimSmithingTemplate { inner: MaterialStruct<'mc> }, + WardArmorTrimSmithingTemplate { inner: MaterialStruct<'mc> }, + EyeArmorTrimSmithingTemplate { inner: MaterialStruct<'mc> }, + VexArmorTrimSmithingTemplate { inner: MaterialStruct<'mc> }, + TideArmorTrimSmithingTemplate { inner: MaterialStruct<'mc> }, + SnoutArmorTrimSmithingTemplate { inner: MaterialStruct<'mc> }, + RibArmorTrimSmithingTemplate { inner: MaterialStruct<'mc> }, + SpireArmorTrimSmithingTemplate { inner: MaterialStruct<'mc> }, + WayfinderArmorTrimSmithingTemplate { inner: MaterialStruct<'mc> }, + ShaperArmorTrimSmithingTemplate { inner: MaterialStruct<'mc> }, + SilenceArmorTrimSmithingTemplate { inner: MaterialStruct<'mc> }, + RaiserArmorTrimSmithingTemplate { inner: MaterialStruct<'mc> }, + HostArmorTrimSmithingTemplate { inner: MaterialStruct<'mc> }, + FlowArmorTrimSmithingTemplate { inner: MaterialStruct<'mc> }, + BoltArmorTrimSmithingTemplate { inner: MaterialStruct<'mc> }, + AnglerPotterySherd { inner: MaterialStruct<'mc> }, + ArcherPotterySherd { inner: MaterialStruct<'mc> }, + ArmsUpPotterySherd { inner: MaterialStruct<'mc> }, + BladePotterySherd { inner: MaterialStruct<'mc> }, + BrewerPotterySherd { inner: MaterialStruct<'mc> }, + BurnPotterySherd { inner: MaterialStruct<'mc> }, + DangerPotterySherd { inner: MaterialStruct<'mc> }, + ExplorerPotterySherd { inner: MaterialStruct<'mc> }, + FlowPotterySherd { inner: MaterialStruct<'mc> }, + FriendPotterySherd { inner: MaterialStruct<'mc> }, + GusterPotterySherd { inner: MaterialStruct<'mc> }, + HeartPotterySherd { inner: MaterialStruct<'mc> }, + HeartbreakPotterySherd { inner: MaterialStruct<'mc> }, + HowlPotterySherd { inner: MaterialStruct<'mc> }, + MinerPotterySherd { inner: MaterialStruct<'mc> }, + MournerPotterySherd { inner: MaterialStruct<'mc> }, + PlentyPotterySherd { inner: MaterialStruct<'mc> }, + PrizePotterySherd { inner: MaterialStruct<'mc> }, + ScrapePotterySherd { inner: MaterialStruct<'mc> }, + SheafPotterySherd { inner: MaterialStruct<'mc> }, + ShelterPotterySherd { inner: MaterialStruct<'mc> }, + SkullPotterySherd { inner: MaterialStruct<'mc> }, + SnortPotterySherd { inner: MaterialStruct<'mc> }, + CopperGrate { inner: MaterialStruct<'mc> }, + ExposedCopperGrate { inner: MaterialStruct<'mc> }, + WeatheredCopperGrate { inner: MaterialStruct<'mc> }, + OxidizedCopperGrate { inner: MaterialStruct<'mc> }, + WaxedCopperGrate { inner: MaterialStruct<'mc> }, + WaxedExposedCopperGrate { inner: MaterialStruct<'mc> }, + WaxedWeatheredCopperGrate { inner: MaterialStruct<'mc> }, + WaxedOxidizedCopperGrate { inner: MaterialStruct<'mc> }, + CopperBulb { inner: MaterialStruct<'mc> }, + ExposedCopperBulb { inner: MaterialStruct<'mc> }, + WeatheredCopperBulb { inner: MaterialStruct<'mc> }, + OxidizedCopperBulb { inner: MaterialStruct<'mc> }, + WaxedCopperBulb { inner: MaterialStruct<'mc> }, + WaxedExposedCopperBulb { inner: MaterialStruct<'mc> }, + WaxedWeatheredCopperBulb { inner: MaterialStruct<'mc> }, + WaxedOxidizedCopperBulb { inner: MaterialStruct<'mc> }, + TrialSpawner { inner: MaterialStruct<'mc> }, + TrialKey { inner: MaterialStruct<'mc> }, + OminousTrialKey { inner: MaterialStruct<'mc> }, + Vault { inner: MaterialStruct<'mc> }, + OminousBottle { inner: MaterialStruct<'mc> }, + BreezeRod { inner: MaterialStruct<'mc> }, + Water { inner: MaterialStruct<'mc> }, + Lava { inner: MaterialStruct<'mc> }, + TallSeagrass { inner: MaterialStruct<'mc> }, + PistonHead { inner: MaterialStruct<'mc> }, + MovingPiston { inner: MaterialStruct<'mc> }, + WallTorch { inner: MaterialStruct<'mc> }, + Fire { inner: MaterialStruct<'mc> }, + SoulFire { inner: MaterialStruct<'mc> }, + RedstoneWire { inner: MaterialStruct<'mc> }, + OakWallSign { inner: MaterialStruct<'mc> }, + SpruceWallSign { inner: MaterialStruct<'mc> }, + BirchWallSign { inner: MaterialStruct<'mc> }, + AcaciaWallSign { inner: MaterialStruct<'mc> }, + CherryWallSign { inner: MaterialStruct<'mc> }, + JungleWallSign { inner: MaterialStruct<'mc> }, + DarkOakWallSign { inner: MaterialStruct<'mc> }, + MangroveWallSign { inner: MaterialStruct<'mc> }, + BambooWallSign { inner: MaterialStruct<'mc> }, + OakWallHangingSign { inner: MaterialStruct<'mc> }, + SpruceWallHangingSign { inner: MaterialStruct<'mc> }, + BirchWallHangingSign { inner: MaterialStruct<'mc> }, + AcaciaWallHangingSign { inner: MaterialStruct<'mc> }, + CherryWallHangingSign { inner: MaterialStruct<'mc> }, + JungleWallHangingSign { inner: MaterialStruct<'mc> }, + DarkOakWallHangingSign { inner: MaterialStruct<'mc> }, + MangroveWallHangingSign { inner: MaterialStruct<'mc> }, + CrimsonWallHangingSign { inner: MaterialStruct<'mc> }, + WarpedWallHangingSign { inner: MaterialStruct<'mc> }, + BambooWallHangingSign { inner: MaterialStruct<'mc> }, + RedstoneWallTorch { inner: MaterialStruct<'mc> }, + SoulWallTorch { inner: MaterialStruct<'mc> }, + NetherPortal { inner: MaterialStruct<'mc> }, + AttachedPumpkinStem { inner: MaterialStruct<'mc> }, + AttachedMelonStem { inner: MaterialStruct<'mc> }, + PumpkinStem { inner: MaterialStruct<'mc> }, + MelonStem { inner: MaterialStruct<'mc> }, + WaterCauldron { inner: MaterialStruct<'mc> }, + LavaCauldron { inner: MaterialStruct<'mc> }, + PowderSnowCauldron { inner: MaterialStruct<'mc> }, + EndPortal { inner: MaterialStruct<'mc> }, + Cocoa { inner: MaterialStruct<'mc> }, + Tripwire { inner: MaterialStruct<'mc> }, + PottedTorchflower { inner: MaterialStruct<'mc> }, + PottedOakSapling { inner: MaterialStruct<'mc> }, + PottedSpruceSapling { inner: MaterialStruct<'mc> }, + PottedBirchSapling { inner: MaterialStruct<'mc> }, + PottedJungleSapling { inner: MaterialStruct<'mc> }, + PottedAcaciaSapling { inner: MaterialStruct<'mc> }, + PottedCherrySapling { inner: MaterialStruct<'mc> }, + PottedDarkOakSapling { inner: MaterialStruct<'mc> }, + PottedMangrovePropagule { inner: MaterialStruct<'mc> }, + PottedFern { inner: MaterialStruct<'mc> }, + PottedDandelion { inner: MaterialStruct<'mc> }, + PottedPoppy { inner: MaterialStruct<'mc> }, + PottedBlueOrchid { inner: MaterialStruct<'mc> }, + PottedAllium { inner: MaterialStruct<'mc> }, + PottedAzureBluet { inner: MaterialStruct<'mc> }, + PottedRedTulip { inner: MaterialStruct<'mc> }, + PottedOrangeTulip { inner: MaterialStruct<'mc> }, + PottedWhiteTulip { inner: MaterialStruct<'mc> }, + PottedPinkTulip { inner: MaterialStruct<'mc> }, + PottedOxeyeDaisy { inner: MaterialStruct<'mc> }, + PottedCornflower { inner: MaterialStruct<'mc> }, + PottedLilyOfTheValley { inner: MaterialStruct<'mc> }, + PottedWitherRose { inner: MaterialStruct<'mc> }, + PottedRedMushroom { inner: MaterialStruct<'mc> }, + PottedBrownMushroom { inner: MaterialStruct<'mc> }, + PottedDeadBush { inner: MaterialStruct<'mc> }, + PottedCactus { inner: MaterialStruct<'mc> }, + Carrots { inner: MaterialStruct<'mc> }, + Potatoes { inner: MaterialStruct<'mc> }, + SkeletonWallSkull { inner: MaterialStruct<'mc> }, + WitherSkeletonWallSkull { inner: MaterialStruct<'mc> }, + ZombieWallHead { inner: MaterialStruct<'mc> }, + PlayerWallHead { inner: MaterialStruct<'mc> }, + CreeperWallHead { inner: MaterialStruct<'mc> }, + DragonWallHead { inner: MaterialStruct<'mc> }, + PiglinWallHead { inner: MaterialStruct<'mc> }, + WhiteWallBanner { inner: MaterialStruct<'mc> }, + OrangeWallBanner { inner: MaterialStruct<'mc> }, + MagentaWallBanner { inner: MaterialStruct<'mc> }, + LightBlueWallBanner { inner: MaterialStruct<'mc> }, + YellowWallBanner { inner: MaterialStruct<'mc> }, + LimeWallBanner { inner: MaterialStruct<'mc> }, + PinkWallBanner { inner: MaterialStruct<'mc> }, + GrayWallBanner { inner: MaterialStruct<'mc> }, + LightGrayWallBanner { inner: MaterialStruct<'mc> }, + CyanWallBanner { inner: MaterialStruct<'mc> }, + PurpleWallBanner { inner: MaterialStruct<'mc> }, + BlueWallBanner { inner: MaterialStruct<'mc> }, + BrownWallBanner { inner: MaterialStruct<'mc> }, + GreenWallBanner { inner: MaterialStruct<'mc> }, + RedWallBanner { inner: MaterialStruct<'mc> }, + BlackWallBanner { inner: MaterialStruct<'mc> }, + TorchflowerCrop { inner: MaterialStruct<'mc> }, + PitcherCrop { inner: MaterialStruct<'mc> }, + Beetroots { inner: MaterialStruct<'mc> }, + EndGateway { inner: MaterialStruct<'mc> }, + FrostedIce { inner: MaterialStruct<'mc> }, + KelpPlant { inner: MaterialStruct<'mc> }, + DeadTubeCoralWallFan { inner: MaterialStruct<'mc> }, + DeadBrainCoralWallFan { inner: MaterialStruct<'mc> }, + DeadBubbleCoralWallFan { inner: MaterialStruct<'mc> }, + DeadFireCoralWallFan { inner: MaterialStruct<'mc> }, + DeadHornCoralWallFan { inner: MaterialStruct<'mc> }, + TubeCoralWallFan { inner: MaterialStruct<'mc> }, + BrainCoralWallFan { inner: MaterialStruct<'mc> }, + BubbleCoralWallFan { inner: MaterialStruct<'mc> }, + FireCoralWallFan { inner: MaterialStruct<'mc> }, + HornCoralWallFan { inner: MaterialStruct<'mc> }, + BambooSapling { inner: MaterialStruct<'mc> }, + PottedBamboo { inner: MaterialStruct<'mc> }, + VoidAir { inner: MaterialStruct<'mc> }, + CaveAir { inner: MaterialStruct<'mc> }, + BubbleColumn { inner: MaterialStruct<'mc> }, + SweetBerryBush { inner: MaterialStruct<'mc> }, + WeepingVinesPlant { inner: MaterialStruct<'mc> }, + TwistingVinesPlant { inner: MaterialStruct<'mc> }, + CrimsonWallSign { inner: MaterialStruct<'mc> }, + WarpedWallSign { inner: MaterialStruct<'mc> }, + PottedCrimsonFungus { inner: MaterialStruct<'mc> }, + PottedWarpedFungus { inner: MaterialStruct<'mc> }, + PottedCrimsonRoots { inner: MaterialStruct<'mc> }, + PottedWarpedRoots { inner: MaterialStruct<'mc> }, + CandleCake { inner: MaterialStruct<'mc> }, + WhiteCandleCake { inner: MaterialStruct<'mc> }, + OrangeCandleCake { inner: MaterialStruct<'mc> }, + MagentaCandleCake { inner: MaterialStruct<'mc> }, + LightBlueCandleCake { inner: MaterialStruct<'mc> }, + YellowCandleCake { inner: MaterialStruct<'mc> }, + LimeCandleCake { inner: MaterialStruct<'mc> }, + PinkCandleCake { inner: MaterialStruct<'mc> }, + GrayCandleCake { inner: MaterialStruct<'mc> }, + LightGrayCandleCake { inner: MaterialStruct<'mc> }, + CyanCandleCake { inner: MaterialStruct<'mc> }, + PurpleCandleCake { inner: MaterialStruct<'mc> }, + BlueCandleCake { inner: MaterialStruct<'mc> }, + BrownCandleCake { inner: MaterialStruct<'mc> }, + GreenCandleCake { inner: MaterialStruct<'mc> }, + RedCandleCake { inner: MaterialStruct<'mc> }, + BlackCandleCake { inner: MaterialStruct<'mc> }, + PowderSnow { inner: MaterialStruct<'mc> }, + CaveVines { inner: MaterialStruct<'mc> }, + CaveVinesPlant { inner: MaterialStruct<'mc> }, + BigDripleafStem { inner: MaterialStruct<'mc> }, + PottedAzaleaBush { inner: MaterialStruct<'mc> }, + PottedFloweringAzaleaBush { inner: MaterialStruct<'mc> }, + LegacyAir { inner: MaterialStruct<'mc> }, + LegacyStone { inner: MaterialStruct<'mc> }, + LegacyGrass { inner: MaterialStruct<'mc> }, + LegacyDirt { inner: MaterialStruct<'mc> }, + LegacyCobblestone { inner: MaterialStruct<'mc> }, + LegacyWood { inner: MaterialStruct<'mc> }, + LegacySapling { inner: MaterialStruct<'mc> }, + LegacyBedrock { inner: MaterialStruct<'mc> }, + LegacyWater { inner: MaterialStruct<'mc> }, + LegacyStationaryWater { inner: MaterialStruct<'mc> }, + LegacyLava { inner: MaterialStruct<'mc> }, + LegacyStationaryLava { inner: MaterialStruct<'mc> }, + LegacySand { inner: MaterialStruct<'mc> }, + LegacyGravel { inner: MaterialStruct<'mc> }, + LegacyGoldOre { inner: MaterialStruct<'mc> }, + LegacyIronOre { inner: MaterialStruct<'mc> }, + LegacyCoalOre { inner: MaterialStruct<'mc> }, + LegacyLog { inner: MaterialStruct<'mc> }, + LegacyLeaves { inner: MaterialStruct<'mc> }, + LegacySponge { inner: MaterialStruct<'mc> }, + LegacyGlass { inner: MaterialStruct<'mc> }, + LegacyLapisOre { inner: MaterialStruct<'mc> }, + LegacyLapisBlock { inner: MaterialStruct<'mc> }, + LegacyDispenser { inner: MaterialStruct<'mc> }, + LegacySandstone { inner: MaterialStruct<'mc> }, + LegacyNoteBlock { inner: MaterialStruct<'mc> }, + LegacyBedBlock { inner: MaterialStruct<'mc> }, + LegacyPoweredRail { inner: MaterialStruct<'mc> }, + LegacyDetectorRail { inner: MaterialStruct<'mc> }, + LegacyPistonStickyBase { inner: MaterialStruct<'mc> }, + LegacyWeb { inner: MaterialStruct<'mc> }, + LegacyLongGrass { inner: MaterialStruct<'mc> }, + LegacyDeadBush { inner: MaterialStruct<'mc> }, + LegacyPistonBase { inner: MaterialStruct<'mc> }, + LegacyPistonExtension { inner: MaterialStruct<'mc> }, + LegacyWool { inner: MaterialStruct<'mc> }, + LegacyPistonMovingPiece { inner: MaterialStruct<'mc> }, + LegacyYellowFlower { inner: MaterialStruct<'mc> }, + LegacyRedRose { inner: MaterialStruct<'mc> }, + LegacyBrownMushroom { inner: MaterialStruct<'mc> }, + LegacyRedMushroom { inner: MaterialStruct<'mc> }, + LegacyGoldBlock { inner: MaterialStruct<'mc> }, + LegacyIronBlock { inner: MaterialStruct<'mc> }, + LegacyDoubleStep { inner: MaterialStruct<'mc> }, + LegacyStep { inner: MaterialStruct<'mc> }, + LegacyBrick { inner: MaterialStruct<'mc> }, + LegacyTnt { inner: MaterialStruct<'mc> }, + LegacyBookshelf { inner: MaterialStruct<'mc> }, + LegacyMossyCobblestone { inner: MaterialStruct<'mc> }, + LegacyObsidian { inner: MaterialStruct<'mc> }, + LegacyTorch { inner: MaterialStruct<'mc> }, + LegacyFire { inner: MaterialStruct<'mc> }, + LegacyMobSpawner { inner: MaterialStruct<'mc> }, + LegacyWoodStairs { inner: MaterialStruct<'mc> }, + LegacyChest { inner: MaterialStruct<'mc> }, + LegacyRedstoneWire { inner: MaterialStruct<'mc> }, + LegacyDiamondOre { inner: MaterialStruct<'mc> }, + LegacyDiamondBlock { inner: MaterialStruct<'mc> }, + LegacyWorkbench { inner: MaterialStruct<'mc> }, + LegacyCrops { inner: MaterialStruct<'mc> }, + LegacySoil { inner: MaterialStruct<'mc> }, + LegacyFurnace { inner: MaterialStruct<'mc> }, + LegacyBurningFurnace { inner: MaterialStruct<'mc> }, + LegacySignPost { inner: MaterialStruct<'mc> }, + LegacyWoodenDoor { inner: MaterialStruct<'mc> }, + LegacyLadder { inner: MaterialStruct<'mc> }, + LegacyRails { inner: MaterialStruct<'mc> }, + LegacyCobblestoneStairs { inner: MaterialStruct<'mc> }, + LegacyWallSign { inner: MaterialStruct<'mc> }, + LegacyLever { inner: MaterialStruct<'mc> }, + LegacyStonePlate { inner: MaterialStruct<'mc> }, + LegacyIronDoorBlock { inner: MaterialStruct<'mc> }, + LegacyWoodPlate { inner: MaterialStruct<'mc> }, + LegacyRedstoneOre { inner: MaterialStruct<'mc> }, + LegacyGlowingRedstoneOre { inner: MaterialStruct<'mc> }, + LegacyRedstoneTorchOff { inner: MaterialStruct<'mc> }, + LegacyRedstoneTorchOn { inner: MaterialStruct<'mc> }, + LegacyStoneButton { inner: MaterialStruct<'mc> }, + LegacySnow { inner: MaterialStruct<'mc> }, + LegacyIce { inner: MaterialStruct<'mc> }, + LegacySnowBlock { inner: MaterialStruct<'mc> }, + LegacyCactus { inner: MaterialStruct<'mc> }, + LegacyClay { inner: MaterialStruct<'mc> }, + LegacySugarCaneBlock { inner: MaterialStruct<'mc> }, + LegacyJukebox { inner: MaterialStruct<'mc> }, + LegacyFence { inner: MaterialStruct<'mc> }, + LegacyPumpkin { inner: MaterialStruct<'mc> }, + LegacyNetherrack { inner: MaterialStruct<'mc> }, + LegacySoulSand { inner: MaterialStruct<'mc> }, + LegacyGlowstone { inner: MaterialStruct<'mc> }, + LegacyPortal { inner: MaterialStruct<'mc> }, + LegacyJackOLantern { inner: MaterialStruct<'mc> }, + LegacyCakeBlock { inner: MaterialStruct<'mc> }, + LegacyDiodeBlockOff { inner: MaterialStruct<'mc> }, + LegacyDiodeBlockOn { inner: MaterialStruct<'mc> }, + LegacyStainedGlass { inner: MaterialStruct<'mc> }, + LegacyTrapDoor { inner: MaterialStruct<'mc> }, + LegacyMonsterEggs { inner: MaterialStruct<'mc> }, + LegacySmoothBrick { inner: MaterialStruct<'mc> }, + LegacyHugeMushroom1 { inner: MaterialStruct<'mc> }, + LegacyHugeMushroom2 { inner: MaterialStruct<'mc> }, + LegacyIronFence { inner: MaterialStruct<'mc> }, + LegacyThinGlass { inner: MaterialStruct<'mc> }, + LegacyMelonBlock { inner: MaterialStruct<'mc> }, + LegacyPumpkinStem { inner: MaterialStruct<'mc> }, + LegacyMelonStem { inner: MaterialStruct<'mc> }, + LegacyVine { inner: MaterialStruct<'mc> }, + LegacyFenceGate { inner: MaterialStruct<'mc> }, + LegacyBrickStairs { inner: MaterialStruct<'mc> }, + LegacySmoothStairs { inner: MaterialStruct<'mc> }, + LegacyMycel { inner: MaterialStruct<'mc> }, + LegacyWaterLily { inner: MaterialStruct<'mc> }, + LegacyNetherBrick { inner: MaterialStruct<'mc> }, + LegacyNetherFence { inner: MaterialStruct<'mc> }, + LegacyNetherBrickStairs { inner: MaterialStruct<'mc> }, + LegacyNetherWarts { inner: MaterialStruct<'mc> }, + LegacyEnchantmentTable { inner: MaterialStruct<'mc> }, + LegacyBrewingStand { inner: MaterialStruct<'mc> }, + LegacyCauldron { inner: MaterialStruct<'mc> }, + LegacyEnderPortal { inner: MaterialStruct<'mc> }, + LegacyEnderPortalFrame { inner: MaterialStruct<'mc> }, + LegacyEnderStone { inner: MaterialStruct<'mc> }, + LegacyDragonEgg { inner: MaterialStruct<'mc> }, + LegacyRedstoneLampOff { inner: MaterialStruct<'mc> }, + LegacyRedstoneLampOn { inner: MaterialStruct<'mc> }, + LegacyWoodDoubleStep { inner: MaterialStruct<'mc> }, + LegacyWoodStep { inner: MaterialStruct<'mc> }, + LegacyCocoa { inner: MaterialStruct<'mc> }, + LegacySandstoneStairs { inner: MaterialStruct<'mc> }, + LegacyEmeraldOre { inner: MaterialStruct<'mc> }, + LegacyEnderChest { inner: MaterialStruct<'mc> }, + LegacyTripwireHook { inner: MaterialStruct<'mc> }, + LegacyTripwire { inner: MaterialStruct<'mc> }, + LegacyEmeraldBlock { inner: MaterialStruct<'mc> }, + LegacySpruceWoodStairs { inner: MaterialStruct<'mc> }, + LegacyBirchWoodStairs { inner: MaterialStruct<'mc> }, + LegacyJungleWoodStairs { inner: MaterialStruct<'mc> }, + LegacyCommand { inner: MaterialStruct<'mc> }, + LegacyBeacon { inner: MaterialStruct<'mc> }, + LegacyCobbleWall { inner: MaterialStruct<'mc> }, + LegacyFlowerPot { inner: MaterialStruct<'mc> }, + LegacyCarrot { inner: MaterialStruct<'mc> }, + LegacyPotato { inner: MaterialStruct<'mc> }, + LegacyWoodButton { inner: MaterialStruct<'mc> }, + LegacySkull { inner: MaterialStruct<'mc> }, + LegacyAnvil { inner: MaterialStruct<'mc> }, + LegacyTrappedChest { inner: MaterialStruct<'mc> }, + LegacyGoldPlate { inner: MaterialStruct<'mc> }, + LegacyIronPlate { inner: MaterialStruct<'mc> }, + LegacyRedstoneComparatorOff { inner: MaterialStruct<'mc> }, + LegacyRedstoneComparatorOn { inner: MaterialStruct<'mc> }, + LegacyDaylightDetector { inner: MaterialStruct<'mc> }, + LegacyRedstoneBlock { inner: MaterialStruct<'mc> }, + LegacyQuartzOre { inner: MaterialStruct<'mc> }, + LegacyHopper { inner: MaterialStruct<'mc> }, + LegacyQuartzBlock { inner: MaterialStruct<'mc> }, + LegacyQuartzStairs { inner: MaterialStruct<'mc> }, + LegacyActivatorRail { inner: MaterialStruct<'mc> }, + LegacyDropper { inner: MaterialStruct<'mc> }, + LegacyStainedClay { inner: MaterialStruct<'mc> }, + LegacyStainedGlassPane { inner: MaterialStruct<'mc> }, + LegacyLeaves2 { inner: MaterialStruct<'mc> }, + LegacyLog2 { inner: MaterialStruct<'mc> }, + LegacyAcaciaStairs { inner: MaterialStruct<'mc> }, + LegacyDarkOakStairs { inner: MaterialStruct<'mc> }, + LegacySlimeBlock { inner: MaterialStruct<'mc> }, + LegacyBarrier { inner: MaterialStruct<'mc> }, + LegacyIronTrapdoor { inner: MaterialStruct<'mc> }, + LegacyPrismarine { inner: MaterialStruct<'mc> }, + LegacySeaLantern { inner: MaterialStruct<'mc> }, + LegacyHayBlock { inner: MaterialStruct<'mc> }, + LegacyCarpet { inner: MaterialStruct<'mc> }, + LegacyHardClay { inner: MaterialStruct<'mc> }, + LegacyCoalBlock { inner: MaterialStruct<'mc> }, + LegacyPackedIce { inner: MaterialStruct<'mc> }, + LegacyDoublePlant { inner: MaterialStruct<'mc> }, + LegacyStandingBanner { inner: MaterialStruct<'mc> }, + LegacyWallBanner { inner: MaterialStruct<'mc> }, + LegacyDaylightDetectorInverted { inner: MaterialStruct<'mc> }, + LegacyRedSandstone { inner: MaterialStruct<'mc> }, + LegacyRedSandstoneStairs { inner: MaterialStruct<'mc> }, + LegacyDoubleStoneSlab2 { inner: MaterialStruct<'mc> }, + LegacyStoneSlab2 { inner: MaterialStruct<'mc> }, + LegacySpruceFenceGate { inner: MaterialStruct<'mc> }, + LegacyBirchFenceGate { inner: MaterialStruct<'mc> }, + LegacyJungleFenceGate { inner: MaterialStruct<'mc> }, + LegacyDarkOakFenceGate { inner: MaterialStruct<'mc> }, + LegacyAcaciaFenceGate { inner: MaterialStruct<'mc> }, + LegacySpruceFence { inner: MaterialStruct<'mc> }, + LegacyBirchFence { inner: MaterialStruct<'mc> }, + LegacyJungleFence { inner: MaterialStruct<'mc> }, + LegacyDarkOakFence { inner: MaterialStruct<'mc> }, + LegacyAcaciaFence { inner: MaterialStruct<'mc> }, + LegacySpruceDoor { inner: MaterialStruct<'mc> }, + LegacyBirchDoor { inner: MaterialStruct<'mc> }, + LegacyJungleDoor { inner: MaterialStruct<'mc> }, + LegacyAcaciaDoor { inner: MaterialStruct<'mc> }, + LegacyDarkOakDoor { inner: MaterialStruct<'mc> }, + LegacyEndRod { inner: MaterialStruct<'mc> }, + LegacyChorusPlant { inner: MaterialStruct<'mc> }, + LegacyChorusFlower { inner: MaterialStruct<'mc> }, + LegacyPurpurBlock { inner: MaterialStruct<'mc> }, + LegacyPurpurPillar { inner: MaterialStruct<'mc> }, + LegacyPurpurStairs { inner: MaterialStruct<'mc> }, + LegacyPurpurDoubleSlab { inner: MaterialStruct<'mc> }, + LegacyPurpurSlab { inner: MaterialStruct<'mc> }, + LegacyEndBricks { inner: MaterialStruct<'mc> }, + LegacyBeetrootBlock { inner: MaterialStruct<'mc> }, + LegacyGrassPath { inner: MaterialStruct<'mc> }, + LegacyEndGateway { inner: MaterialStruct<'mc> }, + LegacyCommandRepeating { inner: MaterialStruct<'mc> }, + LegacyCommandChain { inner: MaterialStruct<'mc> }, + LegacyFrostedIce { inner: MaterialStruct<'mc> }, + LegacyMagma { inner: MaterialStruct<'mc> }, + LegacyNetherWartBlock { inner: MaterialStruct<'mc> }, + LegacyRedNetherBrick { inner: MaterialStruct<'mc> }, + LegacyBoneBlock { inner: MaterialStruct<'mc> }, + LegacyStructureVoid { inner: MaterialStruct<'mc> }, + LegacyObserver { inner: MaterialStruct<'mc> }, + LegacyWhiteShulkerBox { inner: MaterialStruct<'mc> }, + LegacyOrangeShulkerBox { inner: MaterialStruct<'mc> }, + LegacyMagentaShulkerBox { inner: MaterialStruct<'mc> }, + LegacyLightBlueShulkerBox { inner: MaterialStruct<'mc> }, + LegacyYellowShulkerBox { inner: MaterialStruct<'mc> }, + LegacyLimeShulkerBox { inner: MaterialStruct<'mc> }, + LegacyPinkShulkerBox { inner: MaterialStruct<'mc> }, + LegacyGrayShulkerBox { inner: MaterialStruct<'mc> }, + LegacySilverShulkerBox { inner: MaterialStruct<'mc> }, + LegacyCyanShulkerBox { inner: MaterialStruct<'mc> }, + LegacyPurpleShulkerBox { inner: MaterialStruct<'mc> }, + LegacyBlueShulkerBox { inner: MaterialStruct<'mc> }, + LegacyBrownShulkerBox { inner: MaterialStruct<'mc> }, + LegacyGreenShulkerBox { inner: MaterialStruct<'mc> }, + LegacyRedShulkerBox { inner: MaterialStruct<'mc> }, + LegacyBlackShulkerBox { inner: MaterialStruct<'mc> }, + LegacyWhiteGlazedTerracotta { inner: MaterialStruct<'mc> }, + LegacyOrangeGlazedTerracotta { inner: MaterialStruct<'mc> }, + LegacyMagentaGlazedTerracotta { inner: MaterialStruct<'mc> }, + LegacyLightBlueGlazedTerracotta { inner: MaterialStruct<'mc> }, + LegacyYellowGlazedTerracotta { inner: MaterialStruct<'mc> }, + LegacyLimeGlazedTerracotta { inner: MaterialStruct<'mc> }, + LegacyPinkGlazedTerracotta { inner: MaterialStruct<'mc> }, + LegacyGrayGlazedTerracotta { inner: MaterialStruct<'mc> }, + LegacySilverGlazedTerracotta { inner: MaterialStruct<'mc> }, + LegacyCyanGlazedTerracotta { inner: MaterialStruct<'mc> }, + LegacyPurpleGlazedTerracotta { inner: MaterialStruct<'mc> }, + LegacyBlueGlazedTerracotta { inner: MaterialStruct<'mc> }, + LegacyBrownGlazedTerracotta { inner: MaterialStruct<'mc> }, + LegacyGreenGlazedTerracotta { inner: MaterialStruct<'mc> }, + LegacyRedGlazedTerracotta { inner: MaterialStruct<'mc> }, + LegacyBlackGlazedTerracotta { inner: MaterialStruct<'mc> }, + LegacyConcrete { inner: MaterialStruct<'mc> }, + LegacyConcretePowder { inner: MaterialStruct<'mc> }, + LegacyStructureBlock { inner: MaterialStruct<'mc> }, + LegacyIronSpade { inner: MaterialStruct<'mc> }, + LegacyIronPickaxe { inner: MaterialStruct<'mc> }, + LegacyIronAxe { inner: MaterialStruct<'mc> }, + LegacyFlintAndSteel { inner: MaterialStruct<'mc> }, + LegacyApple { inner: MaterialStruct<'mc> }, + LegacyBow { inner: MaterialStruct<'mc> }, + LegacyArrow { inner: MaterialStruct<'mc> }, + LegacyCoal { inner: MaterialStruct<'mc> }, + LegacyDiamond { inner: MaterialStruct<'mc> }, + LegacyIronIngot { inner: MaterialStruct<'mc> }, + LegacyGoldIngot { inner: MaterialStruct<'mc> }, + LegacyIronSword { inner: MaterialStruct<'mc> }, + LegacyWoodSword { inner: MaterialStruct<'mc> }, + LegacyWoodSpade { inner: MaterialStruct<'mc> }, + LegacyWoodPickaxe { inner: MaterialStruct<'mc> }, + LegacyWoodAxe { inner: MaterialStruct<'mc> }, + LegacyStoneSword { inner: MaterialStruct<'mc> }, + LegacyStoneSpade { inner: MaterialStruct<'mc> }, + LegacyStonePickaxe { inner: MaterialStruct<'mc> }, + LegacyStoneAxe { inner: MaterialStruct<'mc> }, + LegacyDiamondSword { inner: MaterialStruct<'mc> }, + LegacyDiamondSpade { inner: MaterialStruct<'mc> }, + LegacyDiamondPickaxe { inner: MaterialStruct<'mc> }, + LegacyDiamondAxe { inner: MaterialStruct<'mc> }, + LegacyStick { inner: MaterialStruct<'mc> }, + LegacyBowl { inner: MaterialStruct<'mc> }, + LegacyMushroomSoup { inner: MaterialStruct<'mc> }, + LegacyGoldSword { inner: MaterialStruct<'mc> }, + LegacyGoldSpade { inner: MaterialStruct<'mc> }, + LegacyGoldPickaxe { inner: MaterialStruct<'mc> }, + LegacyGoldAxe { inner: MaterialStruct<'mc> }, + LegacyString { inner: MaterialStruct<'mc> }, + LegacyFeather { inner: MaterialStruct<'mc> }, + LegacySulphur { inner: MaterialStruct<'mc> }, + LegacyWoodHoe { inner: MaterialStruct<'mc> }, + LegacyStoneHoe { inner: MaterialStruct<'mc> }, + LegacyIronHoe { inner: MaterialStruct<'mc> }, + LegacyDiamondHoe { inner: MaterialStruct<'mc> }, + LegacyGoldHoe { inner: MaterialStruct<'mc> }, + LegacySeeds { inner: MaterialStruct<'mc> }, + LegacyWheat { inner: MaterialStruct<'mc> }, + LegacyBread { inner: MaterialStruct<'mc> }, + LegacyLeatherHelmet { inner: MaterialStruct<'mc> }, + LegacyLeatherChestplate { inner: MaterialStruct<'mc> }, + LegacyLeatherLeggings { inner: MaterialStruct<'mc> }, + LegacyLeatherBoots { inner: MaterialStruct<'mc> }, + LegacyChainmailHelmet { inner: MaterialStruct<'mc> }, + LegacyChainmailChestplate { inner: MaterialStruct<'mc> }, + LegacyChainmailLeggings { inner: MaterialStruct<'mc> }, + LegacyChainmailBoots { inner: MaterialStruct<'mc> }, + LegacyIronHelmet { inner: MaterialStruct<'mc> }, + LegacyIronChestplate { inner: MaterialStruct<'mc> }, + LegacyIronLeggings { inner: MaterialStruct<'mc> }, + LegacyIronBoots { inner: MaterialStruct<'mc> }, + LegacyDiamondHelmet { inner: MaterialStruct<'mc> }, + LegacyDiamondChestplate { inner: MaterialStruct<'mc> }, + LegacyDiamondLeggings { inner: MaterialStruct<'mc> }, + LegacyDiamondBoots { inner: MaterialStruct<'mc> }, + LegacyGoldHelmet { inner: MaterialStruct<'mc> }, + LegacyGoldChestplate { inner: MaterialStruct<'mc> }, + LegacyGoldLeggings { inner: MaterialStruct<'mc> }, + LegacyGoldBoots { inner: MaterialStruct<'mc> }, + LegacyFlint { inner: MaterialStruct<'mc> }, + LegacyPork { inner: MaterialStruct<'mc> }, + LegacyGrilledPork { inner: MaterialStruct<'mc> }, + LegacyPainting { inner: MaterialStruct<'mc> }, + LegacyGoldenApple { inner: MaterialStruct<'mc> }, + LegacySign { inner: MaterialStruct<'mc> }, + LegacyWoodDoor { inner: MaterialStruct<'mc> }, + LegacyBucket { inner: MaterialStruct<'mc> }, + LegacyWaterBucket { inner: MaterialStruct<'mc> }, + LegacyLavaBucket { inner: MaterialStruct<'mc> }, + LegacyMinecart { inner: MaterialStruct<'mc> }, + LegacySaddle { inner: MaterialStruct<'mc> }, + LegacyIronDoor { inner: MaterialStruct<'mc> }, + LegacyRedstone { inner: MaterialStruct<'mc> }, + LegacySnowBall { inner: MaterialStruct<'mc> }, + LegacyBoat { inner: MaterialStruct<'mc> }, + LegacyLeather { inner: MaterialStruct<'mc> }, + LegacyMilkBucket { inner: MaterialStruct<'mc> }, + LegacyClayBrick { inner: MaterialStruct<'mc> }, + LegacyClayBall { inner: MaterialStruct<'mc> }, + LegacySugarCane { inner: MaterialStruct<'mc> }, + LegacyPaper { inner: MaterialStruct<'mc> }, + LegacyBook { inner: MaterialStruct<'mc> }, + LegacySlimeBall { inner: MaterialStruct<'mc> }, + LegacyStorageMinecart { inner: MaterialStruct<'mc> }, + LegacyPoweredMinecart { inner: MaterialStruct<'mc> }, + LegacyEgg { inner: MaterialStruct<'mc> }, + LegacyCompass { inner: MaterialStruct<'mc> }, + LegacyFishingRod { inner: MaterialStruct<'mc> }, + LegacyWatch { inner: MaterialStruct<'mc> }, + LegacyGlowstoneDust { inner: MaterialStruct<'mc> }, + LegacyRawFish { inner: MaterialStruct<'mc> }, + LegacyCookedFish { inner: MaterialStruct<'mc> }, + LegacyInkSack { inner: MaterialStruct<'mc> }, + LegacyBone { inner: MaterialStruct<'mc> }, + LegacySugar { inner: MaterialStruct<'mc> }, + LegacyCake { inner: MaterialStruct<'mc> }, + LegacyBed { inner: MaterialStruct<'mc> }, + LegacyDiode { inner: MaterialStruct<'mc> }, + LegacyCookie { inner: MaterialStruct<'mc> }, + LegacyMap { inner: MaterialStruct<'mc> }, + LegacyShears { inner: MaterialStruct<'mc> }, + LegacyMelon { inner: MaterialStruct<'mc> }, + LegacyPumpkinSeeds { inner: MaterialStruct<'mc> }, + LegacyMelonSeeds { inner: MaterialStruct<'mc> }, + LegacyRawBeef { inner: MaterialStruct<'mc> }, + LegacyCookedBeef { inner: MaterialStruct<'mc> }, + LegacyRawChicken { inner: MaterialStruct<'mc> }, + LegacyCookedChicken { inner: MaterialStruct<'mc> }, + LegacyRottenFlesh { inner: MaterialStruct<'mc> }, + LegacyEnderPearl { inner: MaterialStruct<'mc> }, + LegacyBlazeRod { inner: MaterialStruct<'mc> }, + LegacyGhastTear { inner: MaterialStruct<'mc> }, + LegacyGoldNugget { inner: MaterialStruct<'mc> }, + LegacyNetherStalk { inner: MaterialStruct<'mc> }, + LegacyPotion { inner: MaterialStruct<'mc> }, + LegacyGlassBottle { inner: MaterialStruct<'mc> }, + LegacySpiderEye { inner: MaterialStruct<'mc> }, + LegacyFermentedSpiderEye { inner: MaterialStruct<'mc> }, + LegacyBlazePowder { inner: MaterialStruct<'mc> }, + LegacyMagmaCream { inner: MaterialStruct<'mc> }, + LegacyBrewingStandItem { inner: MaterialStruct<'mc> }, + LegacyCauldronItem { inner: MaterialStruct<'mc> }, + LegacyEyeOfEnder { inner: MaterialStruct<'mc> }, + LegacySpeckledMelon { inner: MaterialStruct<'mc> }, + LegacyMonsterEgg { inner: MaterialStruct<'mc> }, + LegacyExpBottle { inner: MaterialStruct<'mc> }, + LegacyFireball { inner: MaterialStruct<'mc> }, + LegacyBookAndQuill { inner: MaterialStruct<'mc> }, + LegacyWrittenBook { inner: MaterialStruct<'mc> }, + LegacyEmerald { inner: MaterialStruct<'mc> }, + LegacyItemFrame { inner: MaterialStruct<'mc> }, + LegacyFlowerPotItem { inner: MaterialStruct<'mc> }, + LegacyCarrotItem { inner: MaterialStruct<'mc> }, + LegacyPotatoItem { inner: MaterialStruct<'mc> }, + LegacyBakedPotato { inner: MaterialStruct<'mc> }, + LegacyPoisonousPotato { inner: MaterialStruct<'mc> }, + LegacyEmptyMap { inner: MaterialStruct<'mc> }, + LegacyGoldenCarrot { inner: MaterialStruct<'mc> }, + LegacySkullItem { inner: MaterialStruct<'mc> }, + LegacyCarrotStick { inner: MaterialStruct<'mc> }, + LegacyNetherStar { inner: MaterialStruct<'mc> }, + LegacyPumpkinPie { inner: MaterialStruct<'mc> }, + LegacyFirework { inner: MaterialStruct<'mc> }, + LegacyFireworkCharge { inner: MaterialStruct<'mc> }, + LegacyEnchantedBook { inner: MaterialStruct<'mc> }, + LegacyRedstoneComparator { inner: MaterialStruct<'mc> }, + LegacyNetherBrickItem { inner: MaterialStruct<'mc> }, + LegacyQuartz { inner: MaterialStruct<'mc> }, + LegacyExplosiveMinecart { inner: MaterialStruct<'mc> }, + LegacyHopperMinecart { inner: MaterialStruct<'mc> }, + LegacyPrismarineShard { inner: MaterialStruct<'mc> }, + LegacyPrismarineCrystals { inner: MaterialStruct<'mc> }, + LegacyRabbit { inner: MaterialStruct<'mc> }, + LegacyCookedRabbit { inner: MaterialStruct<'mc> }, + LegacyRabbitStew { inner: MaterialStruct<'mc> }, + LegacyRabbitFoot { inner: MaterialStruct<'mc> }, + LegacyRabbitHide { inner: MaterialStruct<'mc> }, + LegacyArmorStand { inner: MaterialStruct<'mc> }, + LegacyIronBarding { inner: MaterialStruct<'mc> }, + LegacyGoldBarding { inner: MaterialStruct<'mc> }, + LegacyDiamondBarding { inner: MaterialStruct<'mc> }, + LegacyLeash { inner: MaterialStruct<'mc> }, + LegacyNameTag { inner: MaterialStruct<'mc> }, + LegacyCommandMinecart { inner: MaterialStruct<'mc> }, + LegacyMutton { inner: MaterialStruct<'mc> }, + LegacyCookedMutton { inner: MaterialStruct<'mc> }, + LegacyBanner { inner: MaterialStruct<'mc> }, + LegacyEndCrystal { inner: MaterialStruct<'mc> }, + LegacySpruceDoorItem { inner: MaterialStruct<'mc> }, + LegacyBirchDoorItem { inner: MaterialStruct<'mc> }, + LegacyJungleDoorItem { inner: MaterialStruct<'mc> }, + LegacyAcaciaDoorItem { inner: MaterialStruct<'mc> }, + LegacyDarkOakDoorItem { inner: MaterialStruct<'mc> }, + LegacyChorusFruit { inner: MaterialStruct<'mc> }, + LegacyChorusFruitPopped { inner: MaterialStruct<'mc> }, + LegacyBeetroot { inner: MaterialStruct<'mc> }, + LegacyBeetrootSeeds { inner: MaterialStruct<'mc> }, + LegacyBeetrootSoup { inner: MaterialStruct<'mc> }, + LegacyDragonsBreath { inner: MaterialStruct<'mc> }, + LegacySplashPotion { inner: MaterialStruct<'mc> }, + LegacySpectralArrow { inner: MaterialStruct<'mc> }, + LegacyTippedArrow { inner: MaterialStruct<'mc> }, + LegacyLingeringPotion { inner: MaterialStruct<'mc> }, + LegacyShield { inner: MaterialStruct<'mc> }, + LegacyElytra { inner: MaterialStruct<'mc> }, + LegacyBoatSpruce { inner: MaterialStruct<'mc> }, + LegacyBoatBirch { inner: MaterialStruct<'mc> }, + LegacyBoatJungle { inner: MaterialStruct<'mc> }, + LegacyBoatAcacia { inner: MaterialStruct<'mc> }, + LegacyBoatDarkOak { inner: MaterialStruct<'mc> }, + LegacyTotem { inner: MaterialStruct<'mc> }, + LegacyShulkerShell { inner: MaterialStruct<'mc> }, + LegacyIronNugget { inner: MaterialStruct<'mc> }, + LegacyKnowledgeBook { inner: MaterialStruct<'mc> }, + LegacyGoldRecord { inner: MaterialStruct<'mc> }, + LegacyGreenRecord { inner: MaterialStruct<'mc> }, + LegacyRecord3 { inner: MaterialStruct<'mc> }, + LegacyRecord4 { inner: MaterialStruct<'mc> }, + LegacyRecord5 { inner: MaterialStruct<'mc> }, + LegacyRecord6 { inner: MaterialStruct<'mc> }, + LegacyRecord7 { inner: MaterialStruct<'mc> }, + LegacyRecord8 { inner: MaterialStruct<'mc> }, + LegacyRecord9 { inner: MaterialStruct<'mc> }, + LegacyRecord10 { inner: MaterialStruct<'mc> }, + LegacyRecord11 { inner: MaterialStruct<'mc> }, + LegacyRecord12 { inner: MaterialStruct<'mc> }, +} +impl<'mc> std::fmt::Display for Material<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Material::Air { .. } => f.write_str("AIR"), + Material::Stone { .. } => f.write_str("STONE"), + Material::Granite { .. } => f.write_str("GRANITE"), + Material::PolishedGranite { .. } => f.write_str("POLISHED_GRANITE"), + Material::Diorite { .. } => f.write_str("DIORITE"), + Material::PolishedDiorite { .. } => f.write_str("POLISHED_DIORITE"), + Material::Andesite { .. } => f.write_str("ANDESITE"), + Material::PolishedAndesite { .. } => f.write_str("POLISHED_ANDESITE"), + Material::Deepslate { .. } => f.write_str("DEEPSLATE"), + Material::CobbledDeepslate { .. } => f.write_str("COBBLED_DEEPSLATE"), + Material::PolishedDeepslate { .. } => f.write_str("POLISHED_DEEPSLATE"), + Material::Calcite { .. } => f.write_str("CALCITE"), + Material::Tuff { .. } => f.write_str("TUFF"), + Material::TuffSlab { .. } => f.write_str("TUFF_SLAB"), + Material::TuffStairs { .. } => f.write_str("TUFF_STAIRS"), + Material::TuffWall { .. } => f.write_str("TUFF_WALL"), + Material::ChiseledTuff { .. } => f.write_str("CHISELED_TUFF"), + Material::PolishedTuff { .. } => f.write_str("POLISHED_TUFF"), + Material::PolishedTuffSlab { .. } => f.write_str("POLISHED_TUFF_SLAB"), + Material::PolishedTuffStairs { .. } => f.write_str("POLISHED_TUFF_STAIRS"), + Material::PolishedTuffWall { .. } => f.write_str("POLISHED_TUFF_WALL"), + Material::TuffBricks { .. } => f.write_str("TUFF_BRICKS"), + Material::TuffBrickSlab { .. } => f.write_str("TUFF_BRICK_SLAB"), + Material::TuffBrickStairs { .. } => f.write_str("TUFF_BRICK_STAIRS"), + Material::TuffBrickWall { .. } => f.write_str("TUFF_BRICK_WALL"), + Material::ChiseledTuffBricks { .. } => f.write_str("CHISELED_TUFF_BRICKS"), + Material::DripstoneBlock { .. } => f.write_str("DRIPSTONE_BLOCK"), + Material::GrassBlock { .. } => f.write_str("GRASS_BLOCK"), + Material::Dirt { .. } => f.write_str("DIRT"), + Material::CoarseDirt { .. } => f.write_str("COARSE_DIRT"), + Material::Podzol { .. } => f.write_str("PODZOL"), + Material::RootedDirt { .. } => f.write_str("ROOTED_DIRT"), + Material::Mud { .. } => f.write_str("MUD"), + Material::CrimsonNylium { .. } => f.write_str("CRIMSON_NYLIUM"), + Material::WarpedNylium { .. } => f.write_str("WARPED_NYLIUM"), + Material::Cobblestone { .. } => f.write_str("COBBLESTONE"), + Material::OakPlanks { .. } => f.write_str("OAK_PLANKS"), + Material::SprucePlanks { .. } => f.write_str("SPRUCE_PLANKS"), + Material::BirchPlanks { .. } => f.write_str("BIRCH_PLANKS"), + Material::JunglePlanks { .. } => f.write_str("JUNGLE_PLANKS"), + Material::AcaciaPlanks { .. } => f.write_str("ACACIA_PLANKS"), + Material::CherryPlanks { .. } => f.write_str("CHERRY_PLANKS"), + Material::DarkOakPlanks { .. } => f.write_str("DARK_OAK_PLANKS"), + Material::MangrovePlanks { .. } => f.write_str("MANGROVE_PLANKS"), + Material::BambooPlanks { .. } => f.write_str("BAMBOO_PLANKS"), + Material::CrimsonPlanks { .. } => f.write_str("CRIMSON_PLANKS"), + Material::WarpedPlanks { .. } => f.write_str("WARPED_PLANKS"), + Material::BambooMosaic { .. } => f.write_str("BAMBOO_MOSAIC"), + Material::OakSapling { .. } => f.write_str("OAK_SAPLING"), + Material::SpruceSapling { .. } => f.write_str("SPRUCE_SAPLING"), + Material::BirchSapling { .. } => f.write_str("BIRCH_SAPLING"), + Material::JungleSapling { .. } => f.write_str("JUNGLE_SAPLING"), + Material::AcaciaSapling { .. } => f.write_str("ACACIA_SAPLING"), + Material::CherrySapling { .. } => f.write_str("CHERRY_SAPLING"), + Material::DarkOakSapling { .. } => f.write_str("DARK_OAK_SAPLING"), + Material::MangrovePropagule { .. } => f.write_str("MANGROVE_PROPAGULE"), + Material::Bedrock { .. } => f.write_str("BEDROCK"), + Material::Sand { .. } => f.write_str("SAND"), + Material::SuspiciousSand { .. } => f.write_str("SUSPICIOUS_SAND"), + Material::SuspiciousGravel { .. } => f.write_str("SUSPICIOUS_GRAVEL"), + Material::RedSand { .. } => f.write_str("RED_SAND"), + Material::Gravel { .. } => f.write_str("GRAVEL"), + Material::CoalOre { .. } => f.write_str("COAL_ORE"), + Material::DeepslateCoalOre { .. } => f.write_str("DEEPSLATE_COAL_ORE"), + Material::IronOre { .. } => f.write_str("IRON_ORE"), + Material::DeepslateIronOre { .. } => f.write_str("DEEPSLATE_IRON_ORE"), + Material::CopperOre { .. } => f.write_str("COPPER_ORE"), + Material::DeepslateCopperOre { .. } => f.write_str("DEEPSLATE_COPPER_ORE"), + Material::GoldOre { .. } => f.write_str("GOLD_ORE"), + Material::DeepslateGoldOre { .. } => f.write_str("DEEPSLATE_GOLD_ORE"), + Material::RedstoneOre { .. } => f.write_str("REDSTONE_ORE"), + Material::DeepslateRedstoneOre { .. } => f.write_str("DEEPSLATE_REDSTONE_ORE"), + Material::EmeraldOre { .. } => f.write_str("EMERALD_ORE"), + Material::DeepslateEmeraldOre { .. } => f.write_str("DEEPSLATE_EMERALD_ORE"), + Material::LapisOre { .. } => f.write_str("LAPIS_ORE"), + Material::DeepslateLapisOre { .. } => f.write_str("DEEPSLATE_LAPIS_ORE"), + Material::DiamondOre { .. } => f.write_str("DIAMOND_ORE"), + Material::DeepslateDiamondOre { .. } => f.write_str("DEEPSLATE_DIAMOND_ORE"), + Material::NetherGoldOre { .. } => f.write_str("NETHER_GOLD_ORE"), + Material::NetherQuartzOre { .. } => f.write_str("NETHER_QUARTZ_ORE"), + Material::AncientDebris { .. } => f.write_str("ANCIENT_DEBRIS"), + Material::CoalBlock { .. } => f.write_str("COAL_BLOCK"), + Material::RawIronBlock { .. } => f.write_str("RAW_IRON_BLOCK"), + Material::RawCopperBlock { .. } => f.write_str("RAW_COPPER_BLOCK"), + Material::RawGoldBlock { .. } => f.write_str("RAW_GOLD_BLOCK"), + Material::HeavyCore { .. } => f.write_str("HEAVY_CORE"), + Material::AmethystBlock { .. } => f.write_str("AMETHYST_BLOCK"), + Material::BuddingAmethyst { .. } => f.write_str("BUDDING_AMETHYST"), + Material::IronBlock { .. } => f.write_str("IRON_BLOCK"), + Material::CopperBlock { .. } => f.write_str("COPPER_BLOCK"), + Material::GoldBlock { .. } => f.write_str("GOLD_BLOCK"), + Material::DiamondBlock { .. } => f.write_str("DIAMOND_BLOCK"), + Material::NetheriteBlock { .. } => f.write_str("NETHERITE_BLOCK"), + Material::ExposedCopper { .. } => f.write_str("EXPOSED_COPPER"), + Material::WeatheredCopper { .. } => f.write_str("WEATHERED_COPPER"), + Material::OxidizedCopper { .. } => f.write_str("OXIDIZED_COPPER"), + Material::ChiseledCopper { .. } => f.write_str("CHISELED_COPPER"), + Material::ExposedChiseledCopper { .. } => f.write_str("EXPOSED_CHISELED_COPPER"), + Material::WeatheredChiseledCopper { .. } => f.write_str("WEATHERED_CHISELED_COPPER"), + Material::OxidizedChiseledCopper { .. } => f.write_str("OXIDIZED_CHISELED_COPPER"), + Material::CutCopper { .. } => f.write_str("CUT_COPPER"), + Material::ExposedCutCopper { .. } => f.write_str("EXPOSED_CUT_COPPER"), + Material::WeatheredCutCopper { .. } => f.write_str("WEATHERED_CUT_COPPER"), + Material::OxidizedCutCopper { .. } => f.write_str("OXIDIZED_CUT_COPPER"), + Material::CutCopperStairs { .. } => f.write_str("CUT_COPPER_STAIRS"), + Material::ExposedCutCopperStairs { .. } => f.write_str("EXPOSED_CUT_COPPER_STAIRS"), + Material::WeatheredCutCopperStairs { .. } => f.write_str("WEATHERED_CUT_COPPER_STAIRS"), + Material::OxidizedCutCopperStairs { .. } => f.write_str("OXIDIZED_CUT_COPPER_STAIRS"), + Material::CutCopperSlab { .. } => f.write_str("CUT_COPPER_SLAB"), + Material::ExposedCutCopperSlab { .. } => f.write_str("EXPOSED_CUT_COPPER_SLAB"), + Material::WeatheredCutCopperSlab { .. } => f.write_str("WEATHERED_CUT_COPPER_SLAB"), + Material::OxidizedCutCopperSlab { .. } => f.write_str("OXIDIZED_CUT_COPPER_SLAB"), + Material::WaxedCopperBlock { .. } => f.write_str("WAXED_COPPER_BLOCK"), + Material::WaxedExposedCopper { .. } => f.write_str("WAXED_EXPOSED_COPPER"), + Material::WaxedWeatheredCopper { .. } => f.write_str("WAXED_WEATHERED_COPPER"), + Material::WaxedOxidizedCopper { .. } => f.write_str("WAXED_OXIDIZED_COPPER"), + Material::WaxedChiseledCopper { .. } => f.write_str("WAXED_CHISELED_COPPER"), + Material::WaxedExposedChiseledCopper { .. } => { + f.write_str("WAXED_EXPOSED_CHISELED_COPPER") + } + Material::WaxedWeatheredChiseledCopper { .. } => { + f.write_str("WAXED_WEATHERED_CHISELED_COPPER") + } + Material::WaxedOxidizedChiseledCopper { .. } => { + f.write_str("WAXED_OXIDIZED_CHISELED_COPPER") + } + Material::WaxedCutCopper { .. } => f.write_str("WAXED_CUT_COPPER"), + Material::WaxedExposedCutCopper { .. } => f.write_str("WAXED_EXPOSED_CUT_COPPER"), + Material::WaxedWeatheredCutCopper { .. } => f.write_str("WAXED_WEATHERED_CUT_COPPER"), + Material::WaxedOxidizedCutCopper { .. } => f.write_str("WAXED_OXIDIZED_CUT_COPPER"), + Material::WaxedCutCopperStairs { .. } => f.write_str("WAXED_CUT_COPPER_STAIRS"), + Material::WaxedExposedCutCopperStairs { .. } => { + f.write_str("WAXED_EXPOSED_CUT_COPPER_STAIRS") + } + Material::WaxedWeatheredCutCopperStairs { .. } => { + f.write_str("WAXED_WEATHERED_CUT_COPPER_STAIRS") + } + Material::WaxedOxidizedCutCopperStairs { .. } => { + f.write_str("WAXED_OXIDIZED_CUT_COPPER_STAIRS") + } + Material::WaxedCutCopperSlab { .. } => f.write_str("WAXED_CUT_COPPER_SLAB"), + Material::WaxedExposedCutCopperSlab { .. } => { + f.write_str("WAXED_EXPOSED_CUT_COPPER_SLAB") + } + Material::WaxedWeatheredCutCopperSlab { .. } => { + f.write_str("WAXED_WEATHERED_CUT_COPPER_SLAB") + } + Material::WaxedOxidizedCutCopperSlab { .. } => { + f.write_str("WAXED_OXIDIZED_CUT_COPPER_SLAB") + } + Material::OakLog { .. } => f.write_str("OAK_LOG"), + Material::SpruceLog { .. } => f.write_str("SPRUCE_LOG"), + Material::BirchLog { .. } => f.write_str("BIRCH_LOG"), + Material::JungleLog { .. } => f.write_str("JUNGLE_LOG"), + Material::AcaciaLog { .. } => f.write_str("ACACIA_LOG"), + Material::CherryLog { .. } => f.write_str("CHERRY_LOG"), + Material::DarkOakLog { .. } => f.write_str("DARK_OAK_LOG"), + Material::MangroveLog { .. } => f.write_str("MANGROVE_LOG"), + Material::MangroveRoots { .. } => f.write_str("MANGROVE_ROOTS"), + Material::MuddyMangroveRoots { .. } => f.write_str("MUDDY_MANGROVE_ROOTS"), + Material::CrimsonStem { .. } => f.write_str("CRIMSON_STEM"), + Material::WarpedStem { .. } => f.write_str("WARPED_STEM"), + Material::BambooBlock { .. } => f.write_str("BAMBOO_BLOCK"), + Material::StrippedOakLog { .. } => f.write_str("STRIPPED_OAK_LOG"), + Material::StrippedSpruceLog { .. } => f.write_str("STRIPPED_SPRUCE_LOG"), + Material::StrippedBirchLog { .. } => f.write_str("STRIPPED_BIRCH_LOG"), + Material::StrippedJungleLog { .. } => f.write_str("STRIPPED_JUNGLE_LOG"), + Material::StrippedAcaciaLog { .. } => f.write_str("STRIPPED_ACACIA_LOG"), + Material::StrippedCherryLog { .. } => f.write_str("STRIPPED_CHERRY_LOG"), + Material::StrippedDarkOakLog { .. } => f.write_str("STRIPPED_DARK_OAK_LOG"), + Material::StrippedMangroveLog { .. } => f.write_str("STRIPPED_MANGROVE_LOG"), + Material::StrippedCrimsonStem { .. } => f.write_str("STRIPPED_CRIMSON_STEM"), + Material::StrippedWarpedStem { .. } => f.write_str("STRIPPED_WARPED_STEM"), + Material::StrippedOakWood { .. } => f.write_str("STRIPPED_OAK_WOOD"), + Material::StrippedSpruceWood { .. } => f.write_str("STRIPPED_SPRUCE_WOOD"), + Material::StrippedBirchWood { .. } => f.write_str("STRIPPED_BIRCH_WOOD"), + Material::StrippedJungleWood { .. } => f.write_str("STRIPPED_JUNGLE_WOOD"), + Material::StrippedAcaciaWood { .. } => f.write_str("STRIPPED_ACACIA_WOOD"), + Material::StrippedCherryWood { .. } => f.write_str("STRIPPED_CHERRY_WOOD"), + Material::StrippedDarkOakWood { .. } => f.write_str("STRIPPED_DARK_OAK_WOOD"), + Material::StrippedMangroveWood { .. } => f.write_str("STRIPPED_MANGROVE_WOOD"), + Material::StrippedCrimsonHyphae { .. } => f.write_str("STRIPPED_CRIMSON_HYPHAE"), + Material::StrippedWarpedHyphae { .. } => f.write_str("STRIPPED_WARPED_HYPHAE"), + Material::StrippedBambooBlock { .. } => f.write_str("STRIPPED_BAMBOO_BLOCK"), + Material::OakWood { .. } => f.write_str("OAK_WOOD"), + Material::SpruceWood { .. } => f.write_str("SPRUCE_WOOD"), + Material::BirchWood { .. } => f.write_str("BIRCH_WOOD"), + Material::JungleWood { .. } => f.write_str("JUNGLE_WOOD"), + Material::AcaciaWood { .. } => f.write_str("ACACIA_WOOD"), + Material::CherryWood { .. } => f.write_str("CHERRY_WOOD"), + Material::DarkOakWood { .. } => f.write_str("DARK_OAK_WOOD"), + Material::MangroveWood { .. } => f.write_str("MANGROVE_WOOD"), + Material::CrimsonHyphae { .. } => f.write_str("CRIMSON_HYPHAE"), + Material::WarpedHyphae { .. } => f.write_str("WARPED_HYPHAE"), + Material::OakLeaves { .. } => f.write_str("OAK_LEAVES"), + Material::SpruceLeaves { .. } => f.write_str("SPRUCE_LEAVES"), + Material::BirchLeaves { .. } => f.write_str("BIRCH_LEAVES"), + Material::JungleLeaves { .. } => f.write_str("JUNGLE_LEAVES"), + Material::AcaciaLeaves { .. } => f.write_str("ACACIA_LEAVES"), + Material::CherryLeaves { .. } => f.write_str("CHERRY_LEAVES"), + Material::DarkOakLeaves { .. } => f.write_str("DARK_OAK_LEAVES"), + Material::MangroveLeaves { .. } => f.write_str("MANGROVE_LEAVES"), + Material::AzaleaLeaves { .. } => f.write_str("AZALEA_LEAVES"), + Material::FloweringAzaleaLeaves { .. } => f.write_str("FLOWERING_AZALEA_LEAVES"), + Material::Sponge { .. } => f.write_str("SPONGE"), + Material::WetSponge { .. } => f.write_str("WET_SPONGE"), + Material::Glass { .. } => f.write_str("GLASS"), + Material::TintedGlass { .. } => f.write_str("TINTED_GLASS"), + Material::LapisBlock { .. } => f.write_str("LAPIS_BLOCK"), + Material::Sandstone { .. } => f.write_str("SANDSTONE"), + Material::ChiseledSandstone { .. } => f.write_str("CHISELED_SANDSTONE"), + Material::CutSandstone { .. } => f.write_str("CUT_SANDSTONE"), + Material::Cobweb { .. } => f.write_str("COBWEB"), + Material::ShortGrass { .. } => f.write_str("SHORT_GRASS"), + Material::Fern { .. } => f.write_str("FERN"), + Material::Azalea { .. } => f.write_str("AZALEA"), + Material::FloweringAzalea { .. } => f.write_str("FLOWERING_AZALEA"), + Material::DeadBush { .. } => f.write_str("DEAD_BUSH"), + Material::Seagrass { .. } => f.write_str("SEAGRASS"), + Material::SeaPickle { .. } => f.write_str("SEA_PICKLE"), + Material::WhiteWool { .. } => f.write_str("WHITE_WOOL"), + Material::OrangeWool { .. } => f.write_str("ORANGE_WOOL"), + Material::MagentaWool { .. } => f.write_str("MAGENTA_WOOL"), + Material::LightBlueWool { .. } => f.write_str("LIGHT_BLUE_WOOL"), + Material::YellowWool { .. } => f.write_str("YELLOW_WOOL"), + Material::LimeWool { .. } => f.write_str("LIME_WOOL"), + Material::PinkWool { .. } => f.write_str("PINK_WOOL"), + Material::GrayWool { .. } => f.write_str("GRAY_WOOL"), + Material::LightGrayWool { .. } => f.write_str("LIGHT_GRAY_WOOL"), + Material::CyanWool { .. } => f.write_str("CYAN_WOOL"), + Material::PurpleWool { .. } => f.write_str("PURPLE_WOOL"), + Material::BlueWool { .. } => f.write_str("BLUE_WOOL"), + Material::BrownWool { .. } => f.write_str("BROWN_WOOL"), + Material::GreenWool { .. } => f.write_str("GREEN_WOOL"), + Material::RedWool { .. } => f.write_str("RED_WOOL"), + Material::BlackWool { .. } => f.write_str("BLACK_WOOL"), + Material::Dandelion { .. } => f.write_str("DANDELION"), + Material::Poppy { .. } => f.write_str("POPPY"), + Material::BlueOrchid { .. } => f.write_str("BLUE_ORCHID"), + Material::Allium { .. } => f.write_str("ALLIUM"), + Material::AzureBluet { .. } => f.write_str("AZURE_BLUET"), + Material::RedTulip { .. } => f.write_str("RED_TULIP"), + Material::OrangeTulip { .. } => f.write_str("ORANGE_TULIP"), + Material::WhiteTulip { .. } => f.write_str("WHITE_TULIP"), + Material::PinkTulip { .. } => f.write_str("PINK_TULIP"), + Material::OxeyeDaisy { .. } => f.write_str("OXEYE_DAISY"), + Material::Cornflower { .. } => f.write_str("CORNFLOWER"), + Material::LilyOfTheValley { .. } => f.write_str("LILY_OF_THE_VALLEY"), + Material::WitherRose { .. } => f.write_str("WITHER_ROSE"), + Material::Torchflower { .. } => f.write_str("TORCHFLOWER"), + Material::PitcherPlant { .. } => f.write_str("PITCHER_PLANT"), + Material::SporeBlossom { .. } => f.write_str("SPORE_BLOSSOM"), + Material::BrownMushroom { .. } => f.write_str("BROWN_MUSHROOM"), + Material::RedMushroom { .. } => f.write_str("RED_MUSHROOM"), + Material::CrimsonFungus { .. } => f.write_str("CRIMSON_FUNGUS"), + Material::WarpedFungus { .. } => f.write_str("WARPED_FUNGUS"), + Material::CrimsonRoots { .. } => f.write_str("CRIMSON_ROOTS"), + Material::WarpedRoots { .. } => f.write_str("WARPED_ROOTS"), + Material::NetherSprouts { .. } => f.write_str("NETHER_SPROUTS"), + Material::WeepingVines { .. } => f.write_str("WEEPING_VINES"), + Material::TwistingVines { .. } => f.write_str("TWISTING_VINES"), + Material::SugarCane { .. } => f.write_str("SUGAR_CANE"), + Material::Kelp { .. } => f.write_str("KELP"), + Material::MossCarpet { .. } => f.write_str("MOSS_CARPET"), + Material::PinkPetals { .. } => f.write_str("PINK_PETALS"), + Material::MossBlock { .. } => f.write_str("MOSS_BLOCK"), + Material::HangingRoots { .. } => f.write_str("HANGING_ROOTS"), + Material::BigDripleaf { .. } => f.write_str("BIG_DRIPLEAF"), + Material::SmallDripleaf { .. } => f.write_str("SMALL_DRIPLEAF"), + Material::Bamboo { .. } => f.write_str("BAMBOO"), + Material::OakSlab { .. } => f.write_str("OAK_SLAB"), + Material::SpruceSlab { .. } => f.write_str("SPRUCE_SLAB"), + Material::BirchSlab { .. } => f.write_str("BIRCH_SLAB"), + Material::JungleSlab { .. } => f.write_str("JUNGLE_SLAB"), + Material::AcaciaSlab { .. } => f.write_str("ACACIA_SLAB"), + Material::CherrySlab { .. } => f.write_str("CHERRY_SLAB"), + Material::DarkOakSlab { .. } => f.write_str("DARK_OAK_SLAB"), + Material::MangroveSlab { .. } => f.write_str("MANGROVE_SLAB"), + Material::BambooSlab { .. } => f.write_str("BAMBOO_SLAB"), + Material::BambooMosaicSlab { .. } => f.write_str("BAMBOO_MOSAIC_SLAB"), + Material::CrimsonSlab { .. } => f.write_str("CRIMSON_SLAB"), + Material::WarpedSlab { .. } => f.write_str("WARPED_SLAB"), + Material::StoneSlab { .. } => f.write_str("STONE_SLAB"), + Material::SmoothStoneSlab { .. } => f.write_str("SMOOTH_STONE_SLAB"), + Material::SandstoneSlab { .. } => f.write_str("SANDSTONE_SLAB"), + Material::CutSandstoneSlab { .. } => f.write_str("CUT_SANDSTONE_SLAB"), + Material::PetrifiedOakSlab { .. } => f.write_str("PETRIFIED_OAK_SLAB"), + Material::CobblestoneSlab { .. } => f.write_str("COBBLESTONE_SLAB"), + Material::BrickSlab { .. } => f.write_str("BRICK_SLAB"), + Material::StoneBrickSlab { .. } => f.write_str("STONE_BRICK_SLAB"), + Material::MudBrickSlab { .. } => f.write_str("MUD_BRICK_SLAB"), + Material::NetherBrickSlab { .. } => f.write_str("NETHER_BRICK_SLAB"), + Material::QuartzSlab { .. } => f.write_str("QUARTZ_SLAB"), + Material::RedSandstoneSlab { .. } => f.write_str("RED_SANDSTONE_SLAB"), + Material::CutRedSandstoneSlab { .. } => f.write_str("CUT_RED_SANDSTONE_SLAB"), + Material::PurpurSlab { .. } => f.write_str("PURPUR_SLAB"), + Material::PrismarineSlab { .. } => f.write_str("PRISMARINE_SLAB"), + Material::PrismarineBrickSlab { .. } => f.write_str("PRISMARINE_BRICK_SLAB"), + Material::DarkPrismarineSlab { .. } => f.write_str("DARK_PRISMARINE_SLAB"), + Material::SmoothQuartz { .. } => f.write_str("SMOOTH_QUARTZ"), + Material::SmoothRedSandstone { .. } => f.write_str("SMOOTH_RED_SANDSTONE"), + Material::SmoothSandstone { .. } => f.write_str("SMOOTH_SANDSTONE"), + Material::SmoothStone { .. } => f.write_str("SMOOTH_STONE"), + Material::Bricks { .. } => f.write_str("BRICKS"), + Material::Bookshelf { .. } => f.write_str("BOOKSHELF"), + Material::ChiseledBookshelf { .. } => f.write_str("CHISELED_BOOKSHELF"), + Material::DecoratedPot { .. } => f.write_str("DECORATED_POT"), + Material::MossyCobblestone { .. } => f.write_str("MOSSY_COBBLESTONE"), + Material::Obsidian { .. } => f.write_str("OBSIDIAN"), + Material::Torch { .. } => f.write_str("TORCH"), + Material::EndRod { .. } => f.write_str("END_ROD"), + Material::ChorusPlant { .. } => f.write_str("CHORUS_PLANT"), + Material::ChorusFlower { .. } => f.write_str("CHORUS_FLOWER"), + Material::PurpurBlock { .. } => f.write_str("PURPUR_BLOCK"), + Material::PurpurPillar { .. } => f.write_str("PURPUR_PILLAR"), + Material::PurpurStairs { .. } => f.write_str("PURPUR_STAIRS"), + Material::Spawner { .. } => f.write_str("SPAWNER"), + Material::Chest { .. } => f.write_str("CHEST"), + Material::CraftingTable { .. } => f.write_str("CRAFTING_TABLE"), + Material::Farmland { .. } => f.write_str("FARMLAND"), + Material::Furnace { .. } => f.write_str("FURNACE"), + Material::Ladder { .. } => f.write_str("LADDER"), + Material::CobblestoneStairs { .. } => f.write_str("COBBLESTONE_STAIRS"), + Material::Snow { .. } => f.write_str("SNOW"), + Material::Ice { .. } => f.write_str("ICE"), + Material::SnowBlock { .. } => f.write_str("SNOW_BLOCK"), + Material::Cactus { .. } => f.write_str("CACTUS"), + Material::Clay { .. } => f.write_str("CLAY"), + Material::Jukebox { .. } => f.write_str("JUKEBOX"), + Material::OakFence { .. } => f.write_str("OAK_FENCE"), + Material::SpruceFence { .. } => f.write_str("SPRUCE_FENCE"), + Material::BirchFence { .. } => f.write_str("BIRCH_FENCE"), + Material::JungleFence { .. } => f.write_str("JUNGLE_FENCE"), + Material::AcaciaFence { .. } => f.write_str("ACACIA_FENCE"), + Material::CherryFence { .. } => f.write_str("CHERRY_FENCE"), + Material::DarkOakFence { .. } => f.write_str("DARK_OAK_FENCE"), + Material::MangroveFence { .. } => f.write_str("MANGROVE_FENCE"), + Material::BambooFence { .. } => f.write_str("BAMBOO_FENCE"), + Material::CrimsonFence { .. } => f.write_str("CRIMSON_FENCE"), + Material::WarpedFence { .. } => f.write_str("WARPED_FENCE"), + Material::Pumpkin { .. } => f.write_str("PUMPKIN"), + Material::CarvedPumpkin { .. } => f.write_str("CARVED_PUMPKIN"), + Material::JackOLantern { .. } => f.write_str("JACK_O_LANTERN"), + Material::Netherrack { .. } => f.write_str("NETHERRACK"), + Material::SoulSand { .. } => f.write_str("SOUL_SAND"), + Material::SoulSoil { .. } => f.write_str("SOUL_SOIL"), + Material::Basalt { .. } => f.write_str("BASALT"), + Material::PolishedBasalt { .. } => f.write_str("POLISHED_BASALT"), + Material::SmoothBasalt { .. } => f.write_str("SMOOTH_BASALT"), + Material::SoulTorch { .. } => f.write_str("SOUL_TORCH"), + Material::Glowstone { .. } => f.write_str("GLOWSTONE"), + Material::InfestedStone { .. } => f.write_str("INFESTED_STONE"), + Material::InfestedCobblestone { .. } => f.write_str("INFESTED_COBBLESTONE"), + Material::InfestedStoneBricks { .. } => f.write_str("INFESTED_STONE_BRICKS"), + Material::InfestedMossyStoneBricks { .. } => f.write_str("INFESTED_MOSSY_STONE_BRICKS"), + Material::InfestedCrackedStoneBricks { .. } => { + f.write_str("INFESTED_CRACKED_STONE_BRICKS") + } + Material::InfestedChiseledStoneBricks { .. } => { + f.write_str("INFESTED_CHISELED_STONE_BRICKS") + } + Material::InfestedDeepslate { .. } => f.write_str("INFESTED_DEEPSLATE"), + Material::StoneBricks { .. } => f.write_str("STONE_BRICKS"), + Material::MossyStoneBricks { .. } => f.write_str("MOSSY_STONE_BRICKS"), + Material::CrackedStoneBricks { .. } => f.write_str("CRACKED_STONE_BRICKS"), + Material::ChiseledStoneBricks { .. } => f.write_str("CHISELED_STONE_BRICKS"), + Material::PackedMud { .. } => f.write_str("PACKED_MUD"), + Material::MudBricks { .. } => f.write_str("MUD_BRICKS"), + Material::DeepslateBricks { .. } => f.write_str("DEEPSLATE_BRICKS"), + Material::CrackedDeepslateBricks { .. } => f.write_str("CRACKED_DEEPSLATE_BRICKS"), + Material::DeepslateTiles { .. } => f.write_str("DEEPSLATE_TILES"), + Material::CrackedDeepslateTiles { .. } => f.write_str("CRACKED_DEEPSLATE_TILES"), + Material::ChiseledDeepslate { .. } => f.write_str("CHISELED_DEEPSLATE"), + Material::ReinforcedDeepslate { .. } => f.write_str("REINFORCED_DEEPSLATE"), + Material::BrownMushroomBlock { .. } => f.write_str("BROWN_MUSHROOM_BLOCK"), + Material::RedMushroomBlock { .. } => f.write_str("RED_MUSHROOM_BLOCK"), + Material::MushroomStem { .. } => f.write_str("MUSHROOM_STEM"), + Material::IronBars { .. } => f.write_str("IRON_BARS"), + Material::Chain { .. } => f.write_str("CHAIN"), + Material::GlassPane { .. } => f.write_str("GLASS_PANE"), + Material::Melon { .. } => f.write_str("MELON"), + Material::Vine { .. } => f.write_str("VINE"), + Material::GlowLichen { .. } => f.write_str("GLOW_LICHEN"), + Material::BrickStairs { .. } => f.write_str("BRICK_STAIRS"), + Material::StoneBrickStairs { .. } => f.write_str("STONE_BRICK_STAIRS"), + Material::MudBrickStairs { .. } => f.write_str("MUD_BRICK_STAIRS"), + Material::Mycelium { .. } => f.write_str("MYCELIUM"), + Material::LilyPad { .. } => f.write_str("LILY_PAD"), + Material::NetherBricks { .. } => f.write_str("NETHER_BRICKS"), + Material::CrackedNetherBricks { .. } => f.write_str("CRACKED_NETHER_BRICKS"), + Material::ChiseledNetherBricks { .. } => f.write_str("CHISELED_NETHER_BRICKS"), + Material::NetherBrickFence { .. } => f.write_str("NETHER_BRICK_FENCE"), + Material::NetherBrickStairs { .. } => f.write_str("NETHER_BRICK_STAIRS"), + Material::Sculk { .. } => f.write_str("SCULK"), + Material::SculkVein { .. } => f.write_str("SCULK_VEIN"), + Material::SculkCatalyst { .. } => f.write_str("SCULK_CATALYST"), + Material::SculkShrieker { .. } => f.write_str("SCULK_SHRIEKER"), + Material::EnchantingTable { .. } => f.write_str("ENCHANTING_TABLE"), + Material::EndPortalFrame { .. } => f.write_str("END_PORTAL_FRAME"), + Material::EndStone { .. } => f.write_str("END_STONE"), + Material::EndStoneBricks { .. } => f.write_str("END_STONE_BRICKS"), + Material::DragonEgg { .. } => f.write_str("DRAGON_EGG"), + Material::SandstoneStairs { .. } => f.write_str("SANDSTONE_STAIRS"), + Material::EnderChest { .. } => f.write_str("ENDER_CHEST"), + Material::EmeraldBlock { .. } => f.write_str("EMERALD_BLOCK"), + Material::OakStairs { .. } => f.write_str("OAK_STAIRS"), + Material::SpruceStairs { .. } => f.write_str("SPRUCE_STAIRS"), + Material::BirchStairs { .. } => f.write_str("BIRCH_STAIRS"), + Material::JungleStairs { .. } => f.write_str("JUNGLE_STAIRS"), + Material::AcaciaStairs { .. } => f.write_str("ACACIA_STAIRS"), + Material::CherryStairs { .. } => f.write_str("CHERRY_STAIRS"), + Material::DarkOakStairs { .. } => f.write_str("DARK_OAK_STAIRS"), + Material::MangroveStairs { .. } => f.write_str("MANGROVE_STAIRS"), + Material::BambooStairs { .. } => f.write_str("BAMBOO_STAIRS"), + Material::BambooMosaicStairs { .. } => f.write_str("BAMBOO_MOSAIC_STAIRS"), + Material::CrimsonStairs { .. } => f.write_str("CRIMSON_STAIRS"), + Material::WarpedStairs { .. } => f.write_str("WARPED_STAIRS"), + Material::CommandBlock { .. } => f.write_str("COMMAND_BLOCK"), + Material::Beacon { .. } => f.write_str("BEACON"), + Material::CobblestoneWall { .. } => f.write_str("COBBLESTONE_WALL"), + Material::MossyCobblestoneWall { .. } => f.write_str("MOSSY_COBBLESTONE_WALL"), + Material::BrickWall { .. } => f.write_str("BRICK_WALL"), + Material::PrismarineWall { .. } => f.write_str("PRISMARINE_WALL"), + Material::RedSandstoneWall { .. } => f.write_str("RED_SANDSTONE_WALL"), + Material::MossyStoneBrickWall { .. } => f.write_str("MOSSY_STONE_BRICK_WALL"), + Material::GraniteWall { .. } => f.write_str("GRANITE_WALL"), + Material::StoneBrickWall { .. } => f.write_str("STONE_BRICK_WALL"), + Material::MudBrickWall { .. } => f.write_str("MUD_BRICK_WALL"), + Material::NetherBrickWall { .. } => f.write_str("NETHER_BRICK_WALL"), + Material::AndesiteWall { .. } => f.write_str("ANDESITE_WALL"), + Material::RedNetherBrickWall { .. } => f.write_str("RED_NETHER_BRICK_WALL"), + Material::SandstoneWall { .. } => f.write_str("SANDSTONE_WALL"), + Material::EndStoneBrickWall { .. } => f.write_str("END_STONE_BRICK_WALL"), + Material::DioriteWall { .. } => f.write_str("DIORITE_WALL"), + Material::BlackstoneWall { .. } => f.write_str("BLACKSTONE_WALL"), + Material::PolishedBlackstoneWall { .. } => f.write_str("POLISHED_BLACKSTONE_WALL"), + Material::PolishedBlackstoneBrickWall { .. } => { + f.write_str("POLISHED_BLACKSTONE_BRICK_WALL") + } + Material::CobbledDeepslateWall { .. } => f.write_str("COBBLED_DEEPSLATE_WALL"), + Material::PolishedDeepslateWall { .. } => f.write_str("POLISHED_DEEPSLATE_WALL"), + Material::DeepslateBrickWall { .. } => f.write_str("DEEPSLATE_BRICK_WALL"), + Material::DeepslateTileWall { .. } => f.write_str("DEEPSLATE_TILE_WALL"), + Material::Anvil { .. } => f.write_str("ANVIL"), + Material::ChippedAnvil { .. } => f.write_str("CHIPPED_ANVIL"), + Material::DamagedAnvil { .. } => f.write_str("DAMAGED_ANVIL"), + Material::ChiseledQuartzBlock { .. } => f.write_str("CHISELED_QUARTZ_BLOCK"), + Material::QuartzBlock { .. } => f.write_str("QUARTZ_BLOCK"), + Material::QuartzBricks { .. } => f.write_str("QUARTZ_BRICKS"), + Material::QuartzPillar { .. } => f.write_str("QUARTZ_PILLAR"), + Material::QuartzStairs { .. } => f.write_str("QUARTZ_STAIRS"), + Material::WhiteTerracotta { .. } => f.write_str("WHITE_TERRACOTTA"), + Material::OrangeTerracotta { .. } => f.write_str("ORANGE_TERRACOTTA"), + Material::MagentaTerracotta { .. } => f.write_str("MAGENTA_TERRACOTTA"), + Material::LightBlueTerracotta { .. } => f.write_str("LIGHT_BLUE_TERRACOTTA"), + Material::YellowTerracotta { .. } => f.write_str("YELLOW_TERRACOTTA"), + Material::LimeTerracotta { .. } => f.write_str("LIME_TERRACOTTA"), + Material::PinkTerracotta { .. } => f.write_str("PINK_TERRACOTTA"), + Material::GrayTerracotta { .. } => f.write_str("GRAY_TERRACOTTA"), + Material::LightGrayTerracotta { .. } => f.write_str("LIGHT_GRAY_TERRACOTTA"), + Material::CyanTerracotta { .. } => f.write_str("CYAN_TERRACOTTA"), + Material::PurpleTerracotta { .. } => f.write_str("PURPLE_TERRACOTTA"), + Material::BlueTerracotta { .. } => f.write_str("BLUE_TERRACOTTA"), + Material::BrownTerracotta { .. } => f.write_str("BROWN_TERRACOTTA"), + Material::GreenTerracotta { .. } => f.write_str("GREEN_TERRACOTTA"), + Material::RedTerracotta { .. } => f.write_str("RED_TERRACOTTA"), + Material::BlackTerracotta { .. } => f.write_str("BLACK_TERRACOTTA"), + Material::Barrier { .. } => f.write_str("BARRIER"), + Material::Light { .. } => f.write_str("LIGHT"), + Material::HayBlock { .. } => f.write_str("HAY_BLOCK"), + Material::WhiteCarpet { .. } => f.write_str("WHITE_CARPET"), + Material::OrangeCarpet { .. } => f.write_str("ORANGE_CARPET"), + Material::MagentaCarpet { .. } => f.write_str("MAGENTA_CARPET"), + Material::LightBlueCarpet { .. } => f.write_str("LIGHT_BLUE_CARPET"), + Material::YellowCarpet { .. } => f.write_str("YELLOW_CARPET"), + Material::LimeCarpet { .. } => f.write_str("LIME_CARPET"), + Material::PinkCarpet { .. } => f.write_str("PINK_CARPET"), + Material::GrayCarpet { .. } => f.write_str("GRAY_CARPET"), + Material::LightGrayCarpet { .. } => f.write_str("LIGHT_GRAY_CARPET"), + Material::CyanCarpet { .. } => f.write_str("CYAN_CARPET"), + Material::PurpleCarpet { .. } => f.write_str("PURPLE_CARPET"), + Material::BlueCarpet { .. } => f.write_str("BLUE_CARPET"), + Material::BrownCarpet { .. } => f.write_str("BROWN_CARPET"), + Material::GreenCarpet { .. } => f.write_str("GREEN_CARPET"), + Material::RedCarpet { .. } => f.write_str("RED_CARPET"), + Material::BlackCarpet { .. } => f.write_str("BLACK_CARPET"), + Material::Terracotta { .. } => f.write_str("TERRACOTTA"), + Material::PackedIce { .. } => f.write_str("PACKED_ICE"), + Material::DirtPath { .. } => f.write_str("DIRT_PATH"), + Material::Sunflower { .. } => f.write_str("SUNFLOWER"), + Material::Lilac { .. } => f.write_str("LILAC"), + Material::RoseBush { .. } => f.write_str("ROSE_BUSH"), + Material::Peony { .. } => f.write_str("PEONY"), + Material::TallGrass { .. } => f.write_str("TALL_GRASS"), + Material::LargeFern { .. } => f.write_str("LARGE_FERN"), + Material::WhiteStainedGlass { .. } => f.write_str("WHITE_STAINED_GLASS"), + Material::OrangeStainedGlass { .. } => f.write_str("ORANGE_STAINED_GLASS"), + Material::MagentaStainedGlass { .. } => f.write_str("MAGENTA_STAINED_GLASS"), + Material::LightBlueStainedGlass { .. } => f.write_str("LIGHT_BLUE_STAINED_GLASS"), + Material::YellowStainedGlass { .. } => f.write_str("YELLOW_STAINED_GLASS"), + Material::LimeStainedGlass { .. } => f.write_str("LIME_STAINED_GLASS"), + Material::PinkStainedGlass { .. } => f.write_str("PINK_STAINED_GLASS"), + Material::GrayStainedGlass { .. } => f.write_str("GRAY_STAINED_GLASS"), + Material::LightGrayStainedGlass { .. } => f.write_str("LIGHT_GRAY_STAINED_GLASS"), + Material::CyanStainedGlass { .. } => f.write_str("CYAN_STAINED_GLASS"), + Material::PurpleStainedGlass { .. } => f.write_str("PURPLE_STAINED_GLASS"), + Material::BlueStainedGlass { .. } => f.write_str("BLUE_STAINED_GLASS"), + Material::BrownStainedGlass { .. } => f.write_str("BROWN_STAINED_GLASS"), + Material::GreenStainedGlass { .. } => f.write_str("GREEN_STAINED_GLASS"), + Material::RedStainedGlass { .. } => f.write_str("RED_STAINED_GLASS"), + Material::BlackStainedGlass { .. } => f.write_str("BLACK_STAINED_GLASS"), + Material::WhiteStainedGlassPane { .. } => f.write_str("WHITE_STAINED_GLASS_PANE"), + Material::OrangeStainedGlassPane { .. } => f.write_str("ORANGE_STAINED_GLASS_PANE"), + Material::MagentaStainedGlassPane { .. } => f.write_str("MAGENTA_STAINED_GLASS_PANE"), + Material::LightBlueStainedGlassPane { .. } => { + f.write_str("LIGHT_BLUE_STAINED_GLASS_PANE") + } + Material::YellowStainedGlassPane { .. } => f.write_str("YELLOW_STAINED_GLASS_PANE"), + Material::LimeStainedGlassPane { .. } => f.write_str("LIME_STAINED_GLASS_PANE"), + Material::PinkStainedGlassPane { .. } => f.write_str("PINK_STAINED_GLASS_PANE"), + Material::GrayStainedGlassPane { .. } => f.write_str("GRAY_STAINED_GLASS_PANE"), + Material::LightGrayStainedGlassPane { .. } => { + f.write_str("LIGHT_GRAY_STAINED_GLASS_PANE") + } + Material::CyanStainedGlassPane { .. } => f.write_str("CYAN_STAINED_GLASS_PANE"), + Material::PurpleStainedGlassPane { .. } => f.write_str("PURPLE_STAINED_GLASS_PANE"), + Material::BlueStainedGlassPane { .. } => f.write_str("BLUE_STAINED_GLASS_PANE"), + Material::BrownStainedGlassPane { .. } => f.write_str("BROWN_STAINED_GLASS_PANE"), + Material::GreenStainedGlassPane { .. } => f.write_str("GREEN_STAINED_GLASS_PANE"), + Material::RedStainedGlassPane { .. } => f.write_str("RED_STAINED_GLASS_PANE"), + Material::BlackStainedGlassPane { .. } => f.write_str("BLACK_STAINED_GLASS_PANE"), + Material::Prismarine { .. } => f.write_str("PRISMARINE"), + Material::PrismarineBricks { .. } => f.write_str("PRISMARINE_BRICKS"), + Material::DarkPrismarine { .. } => f.write_str("DARK_PRISMARINE"), + Material::PrismarineStairs { .. } => f.write_str("PRISMARINE_STAIRS"), + Material::PrismarineBrickStairs { .. } => f.write_str("PRISMARINE_BRICK_STAIRS"), + Material::DarkPrismarineStairs { .. } => f.write_str("DARK_PRISMARINE_STAIRS"), + Material::SeaLantern { .. } => f.write_str("SEA_LANTERN"), + Material::RedSandstone { .. } => f.write_str("RED_SANDSTONE"), + Material::ChiseledRedSandstone { .. } => f.write_str("CHISELED_RED_SANDSTONE"), + Material::CutRedSandstone { .. } => f.write_str("CUT_RED_SANDSTONE"), + Material::RedSandstoneStairs { .. } => f.write_str("RED_SANDSTONE_STAIRS"), + Material::RepeatingCommandBlock { .. } => f.write_str("REPEATING_COMMAND_BLOCK"), + Material::ChainCommandBlock { .. } => f.write_str("CHAIN_COMMAND_BLOCK"), + Material::MagmaBlock { .. } => f.write_str("MAGMA_BLOCK"), + Material::NetherWartBlock { .. } => f.write_str("NETHER_WART_BLOCK"), + Material::WarpedWartBlock { .. } => f.write_str("WARPED_WART_BLOCK"), + Material::RedNetherBricks { .. } => f.write_str("RED_NETHER_BRICKS"), + Material::BoneBlock { .. } => f.write_str("BONE_BLOCK"), + Material::StructureVoid { .. } => f.write_str("STRUCTURE_VOID"), + Material::ShulkerBox { .. } => f.write_str("SHULKER_BOX"), + Material::WhiteShulkerBox { .. } => f.write_str("WHITE_SHULKER_BOX"), + Material::OrangeShulkerBox { .. } => f.write_str("ORANGE_SHULKER_BOX"), + Material::MagentaShulkerBox { .. } => f.write_str("MAGENTA_SHULKER_BOX"), + Material::LightBlueShulkerBox { .. } => f.write_str("LIGHT_BLUE_SHULKER_BOX"), + Material::YellowShulkerBox { .. } => f.write_str("YELLOW_SHULKER_BOX"), + Material::LimeShulkerBox { .. } => f.write_str("LIME_SHULKER_BOX"), + Material::PinkShulkerBox { .. } => f.write_str("PINK_SHULKER_BOX"), + Material::GrayShulkerBox { .. } => f.write_str("GRAY_SHULKER_BOX"), + Material::LightGrayShulkerBox { .. } => f.write_str("LIGHT_GRAY_SHULKER_BOX"), + Material::CyanShulkerBox { .. } => f.write_str("CYAN_SHULKER_BOX"), + Material::PurpleShulkerBox { .. } => f.write_str("PURPLE_SHULKER_BOX"), + Material::BlueShulkerBox { .. } => f.write_str("BLUE_SHULKER_BOX"), + Material::BrownShulkerBox { .. } => f.write_str("BROWN_SHULKER_BOX"), + Material::GreenShulkerBox { .. } => f.write_str("GREEN_SHULKER_BOX"), + Material::RedShulkerBox { .. } => f.write_str("RED_SHULKER_BOX"), + Material::BlackShulkerBox { .. } => f.write_str("BLACK_SHULKER_BOX"), + Material::WhiteGlazedTerracotta { .. } => f.write_str("WHITE_GLAZED_TERRACOTTA"), + Material::OrangeGlazedTerracotta { .. } => f.write_str("ORANGE_GLAZED_TERRACOTTA"), + Material::MagentaGlazedTerracotta { .. } => f.write_str("MAGENTA_GLAZED_TERRACOTTA"), + Material::LightBlueGlazedTerracotta { .. } => { + f.write_str("LIGHT_BLUE_GLAZED_TERRACOTTA") + } + Material::YellowGlazedTerracotta { .. } => f.write_str("YELLOW_GLAZED_TERRACOTTA"), + Material::LimeGlazedTerracotta { .. } => f.write_str("LIME_GLAZED_TERRACOTTA"), + Material::PinkGlazedTerracotta { .. } => f.write_str("PINK_GLAZED_TERRACOTTA"), + Material::GrayGlazedTerracotta { .. } => f.write_str("GRAY_GLAZED_TERRACOTTA"), + Material::LightGrayGlazedTerracotta { .. } => { + f.write_str("LIGHT_GRAY_GLAZED_TERRACOTTA") + } + Material::CyanGlazedTerracotta { .. } => f.write_str("CYAN_GLAZED_TERRACOTTA"), + Material::PurpleGlazedTerracotta { .. } => f.write_str("PURPLE_GLAZED_TERRACOTTA"), + Material::BlueGlazedTerracotta { .. } => f.write_str("BLUE_GLAZED_TERRACOTTA"), + Material::BrownGlazedTerracotta { .. } => f.write_str("BROWN_GLAZED_TERRACOTTA"), + Material::GreenGlazedTerracotta { .. } => f.write_str("GREEN_GLAZED_TERRACOTTA"), + Material::RedGlazedTerracotta { .. } => f.write_str("RED_GLAZED_TERRACOTTA"), + Material::BlackGlazedTerracotta { .. } => f.write_str("BLACK_GLAZED_TERRACOTTA"), + Material::WhiteConcrete { .. } => f.write_str("WHITE_CONCRETE"), + Material::OrangeConcrete { .. } => f.write_str("ORANGE_CONCRETE"), + Material::MagentaConcrete { .. } => f.write_str("MAGENTA_CONCRETE"), + Material::LightBlueConcrete { .. } => f.write_str("LIGHT_BLUE_CONCRETE"), + Material::YellowConcrete { .. } => f.write_str("YELLOW_CONCRETE"), + Material::LimeConcrete { .. } => f.write_str("LIME_CONCRETE"), + Material::PinkConcrete { .. } => f.write_str("PINK_CONCRETE"), + Material::GrayConcrete { .. } => f.write_str("GRAY_CONCRETE"), + Material::LightGrayConcrete { .. } => f.write_str("LIGHT_GRAY_CONCRETE"), + Material::CyanConcrete { .. } => f.write_str("CYAN_CONCRETE"), + Material::PurpleConcrete { .. } => f.write_str("PURPLE_CONCRETE"), + Material::BlueConcrete { .. } => f.write_str("BLUE_CONCRETE"), + Material::BrownConcrete { .. } => f.write_str("BROWN_CONCRETE"), + Material::GreenConcrete { .. } => f.write_str("GREEN_CONCRETE"), + Material::RedConcrete { .. } => f.write_str("RED_CONCRETE"), + Material::BlackConcrete { .. } => f.write_str("BLACK_CONCRETE"), + Material::WhiteConcretePowder { .. } => f.write_str("WHITE_CONCRETE_POWDER"), + Material::OrangeConcretePowder { .. } => f.write_str("ORANGE_CONCRETE_POWDER"), + Material::MagentaConcretePowder { .. } => f.write_str("MAGENTA_CONCRETE_POWDER"), + Material::LightBlueConcretePowder { .. } => f.write_str("LIGHT_BLUE_CONCRETE_POWDER"), + Material::YellowConcretePowder { .. } => f.write_str("YELLOW_CONCRETE_POWDER"), + Material::LimeConcretePowder { .. } => f.write_str("LIME_CONCRETE_POWDER"), + Material::PinkConcretePowder { .. } => f.write_str("PINK_CONCRETE_POWDER"), + Material::GrayConcretePowder { .. } => f.write_str("GRAY_CONCRETE_POWDER"), + Material::LightGrayConcretePowder { .. } => f.write_str("LIGHT_GRAY_CONCRETE_POWDER"), + Material::CyanConcretePowder { .. } => f.write_str("CYAN_CONCRETE_POWDER"), + Material::PurpleConcretePowder { .. } => f.write_str("PURPLE_CONCRETE_POWDER"), + Material::BlueConcretePowder { .. } => f.write_str("BLUE_CONCRETE_POWDER"), + Material::BrownConcretePowder { .. } => f.write_str("BROWN_CONCRETE_POWDER"), + Material::GreenConcretePowder { .. } => f.write_str("GREEN_CONCRETE_POWDER"), + Material::RedConcretePowder { .. } => f.write_str("RED_CONCRETE_POWDER"), + Material::BlackConcretePowder { .. } => f.write_str("BLACK_CONCRETE_POWDER"), + Material::TurtleEgg { .. } => f.write_str("TURTLE_EGG"), + Material::SnifferEgg { .. } => f.write_str("SNIFFER_EGG"), + Material::DeadTubeCoralBlock { .. } => f.write_str("DEAD_TUBE_CORAL_BLOCK"), + Material::DeadBrainCoralBlock { .. } => f.write_str("DEAD_BRAIN_CORAL_BLOCK"), + Material::DeadBubbleCoralBlock { .. } => f.write_str("DEAD_BUBBLE_CORAL_BLOCK"), + Material::DeadFireCoralBlock { .. } => f.write_str("DEAD_FIRE_CORAL_BLOCK"), + Material::DeadHornCoralBlock { .. } => f.write_str("DEAD_HORN_CORAL_BLOCK"), + Material::TubeCoralBlock { .. } => f.write_str("TUBE_CORAL_BLOCK"), + Material::BrainCoralBlock { .. } => f.write_str("BRAIN_CORAL_BLOCK"), + Material::BubbleCoralBlock { .. } => f.write_str("BUBBLE_CORAL_BLOCK"), + Material::FireCoralBlock { .. } => f.write_str("FIRE_CORAL_BLOCK"), + Material::HornCoralBlock { .. } => f.write_str("HORN_CORAL_BLOCK"), + Material::TubeCoral { .. } => f.write_str("TUBE_CORAL"), + Material::BrainCoral { .. } => f.write_str("BRAIN_CORAL"), + Material::BubbleCoral { .. } => f.write_str("BUBBLE_CORAL"), + Material::FireCoral { .. } => f.write_str("FIRE_CORAL"), + Material::HornCoral { .. } => f.write_str("HORN_CORAL"), + Material::DeadBrainCoral { .. } => f.write_str("DEAD_BRAIN_CORAL"), + Material::DeadBubbleCoral { .. } => f.write_str("DEAD_BUBBLE_CORAL"), + Material::DeadFireCoral { .. } => f.write_str("DEAD_FIRE_CORAL"), + Material::DeadHornCoral { .. } => f.write_str("DEAD_HORN_CORAL"), + Material::DeadTubeCoral { .. } => f.write_str("DEAD_TUBE_CORAL"), + Material::TubeCoralFan { .. } => f.write_str("TUBE_CORAL_FAN"), + Material::BrainCoralFan { .. } => f.write_str("BRAIN_CORAL_FAN"), + Material::BubbleCoralFan { .. } => f.write_str("BUBBLE_CORAL_FAN"), + Material::FireCoralFan { .. } => f.write_str("FIRE_CORAL_FAN"), + Material::HornCoralFan { .. } => f.write_str("HORN_CORAL_FAN"), + Material::DeadTubeCoralFan { .. } => f.write_str("DEAD_TUBE_CORAL_FAN"), + Material::DeadBrainCoralFan { .. } => f.write_str("DEAD_BRAIN_CORAL_FAN"), + Material::DeadBubbleCoralFan { .. } => f.write_str("DEAD_BUBBLE_CORAL_FAN"), + Material::DeadFireCoralFan { .. } => f.write_str("DEAD_FIRE_CORAL_FAN"), + Material::DeadHornCoralFan { .. } => f.write_str("DEAD_HORN_CORAL_FAN"), + Material::BlueIce { .. } => f.write_str("BLUE_ICE"), + Material::Conduit { .. } => f.write_str("CONDUIT"), + Material::PolishedGraniteStairs { .. } => f.write_str("POLISHED_GRANITE_STAIRS"), + Material::SmoothRedSandstoneStairs { .. } => f.write_str("SMOOTH_RED_SANDSTONE_STAIRS"), + Material::MossyStoneBrickStairs { .. } => f.write_str("MOSSY_STONE_BRICK_STAIRS"), + Material::PolishedDioriteStairs { .. } => f.write_str("POLISHED_DIORITE_STAIRS"), + Material::MossyCobblestoneStairs { .. } => f.write_str("MOSSY_COBBLESTONE_STAIRS"), + Material::EndStoneBrickStairs { .. } => f.write_str("END_STONE_BRICK_STAIRS"), + Material::StoneStairs { .. } => f.write_str("STONE_STAIRS"), + Material::SmoothSandstoneStairs { .. } => f.write_str("SMOOTH_SANDSTONE_STAIRS"), + Material::SmoothQuartzStairs { .. } => f.write_str("SMOOTH_QUARTZ_STAIRS"), + Material::GraniteStairs { .. } => f.write_str("GRANITE_STAIRS"), + Material::AndesiteStairs { .. } => f.write_str("ANDESITE_STAIRS"), + Material::RedNetherBrickStairs { .. } => f.write_str("RED_NETHER_BRICK_STAIRS"), + Material::PolishedAndesiteStairs { .. } => f.write_str("POLISHED_ANDESITE_STAIRS"), + Material::DioriteStairs { .. } => f.write_str("DIORITE_STAIRS"), + Material::CobbledDeepslateStairs { .. } => f.write_str("COBBLED_DEEPSLATE_STAIRS"), + Material::PolishedDeepslateStairs { .. } => f.write_str("POLISHED_DEEPSLATE_STAIRS"), + Material::DeepslateBrickStairs { .. } => f.write_str("DEEPSLATE_BRICK_STAIRS"), + Material::DeepslateTileStairs { .. } => f.write_str("DEEPSLATE_TILE_STAIRS"), + Material::PolishedGraniteSlab { .. } => f.write_str("POLISHED_GRANITE_SLAB"), + Material::SmoothRedSandstoneSlab { .. } => f.write_str("SMOOTH_RED_SANDSTONE_SLAB"), + Material::MossyStoneBrickSlab { .. } => f.write_str("MOSSY_STONE_BRICK_SLAB"), + Material::PolishedDioriteSlab { .. } => f.write_str("POLISHED_DIORITE_SLAB"), + Material::MossyCobblestoneSlab { .. } => f.write_str("MOSSY_COBBLESTONE_SLAB"), + Material::EndStoneBrickSlab { .. } => f.write_str("END_STONE_BRICK_SLAB"), + Material::SmoothSandstoneSlab { .. } => f.write_str("SMOOTH_SANDSTONE_SLAB"), + Material::SmoothQuartzSlab { .. } => f.write_str("SMOOTH_QUARTZ_SLAB"), + Material::GraniteSlab { .. } => f.write_str("GRANITE_SLAB"), + Material::AndesiteSlab { .. } => f.write_str("ANDESITE_SLAB"), + Material::RedNetherBrickSlab { .. } => f.write_str("RED_NETHER_BRICK_SLAB"), + Material::PolishedAndesiteSlab { .. } => f.write_str("POLISHED_ANDESITE_SLAB"), + Material::DioriteSlab { .. } => f.write_str("DIORITE_SLAB"), + Material::CobbledDeepslateSlab { .. } => f.write_str("COBBLED_DEEPSLATE_SLAB"), + Material::PolishedDeepslateSlab { .. } => f.write_str("POLISHED_DEEPSLATE_SLAB"), + Material::DeepslateBrickSlab { .. } => f.write_str("DEEPSLATE_BRICK_SLAB"), + Material::DeepslateTileSlab { .. } => f.write_str("DEEPSLATE_TILE_SLAB"), + Material::Scaffolding { .. } => f.write_str("SCAFFOLDING"), + Material::Redstone { .. } => f.write_str("REDSTONE"), + Material::RedstoneTorch { .. } => f.write_str("REDSTONE_TORCH"), + Material::RedstoneBlock { .. } => f.write_str("REDSTONE_BLOCK"), + Material::Repeater { .. } => f.write_str("REPEATER"), + Material::Comparator { .. } => f.write_str("COMPARATOR"), + Material::Piston { .. } => f.write_str("PISTON"), + Material::StickyPiston { .. } => f.write_str("STICKY_PISTON"), + Material::SlimeBlock { .. } => f.write_str("SLIME_BLOCK"), + Material::HoneyBlock { .. } => f.write_str("HONEY_BLOCK"), + Material::Observer { .. } => f.write_str("OBSERVER"), + Material::Hopper { .. } => f.write_str("HOPPER"), + Material::Dispenser { .. } => f.write_str("DISPENSER"), + Material::Dropper { .. } => f.write_str("DROPPER"), + Material::Lectern { .. } => f.write_str("LECTERN"), + Material::Target { .. } => f.write_str("TARGET"), + Material::Lever { .. } => f.write_str("LEVER"), + Material::LightningRod { .. } => f.write_str("LIGHTNING_ROD"), + Material::DaylightDetector { .. } => f.write_str("DAYLIGHT_DETECTOR"), + Material::SculkSensor { .. } => f.write_str("SCULK_SENSOR"), + Material::CalibratedSculkSensor { .. } => f.write_str("CALIBRATED_SCULK_SENSOR"), + Material::TripwireHook { .. } => f.write_str("TRIPWIRE_HOOK"), + Material::TrappedChest { .. } => f.write_str("TRAPPED_CHEST"), + Material::Tnt { .. } => f.write_str("TNT"), + Material::RedstoneLamp { .. } => f.write_str("REDSTONE_LAMP"), + Material::NoteBlock { .. } => f.write_str("NOTE_BLOCK"), + Material::StoneButton { .. } => f.write_str("STONE_BUTTON"), + Material::PolishedBlackstoneButton { .. } => f.write_str("POLISHED_BLACKSTONE_BUTTON"), + Material::OakButton { .. } => f.write_str("OAK_BUTTON"), + Material::SpruceButton { .. } => f.write_str("SPRUCE_BUTTON"), + Material::BirchButton { .. } => f.write_str("BIRCH_BUTTON"), + Material::JungleButton { .. } => f.write_str("JUNGLE_BUTTON"), + Material::AcaciaButton { .. } => f.write_str("ACACIA_BUTTON"), + Material::CherryButton { .. } => f.write_str("CHERRY_BUTTON"), + Material::DarkOakButton { .. } => f.write_str("DARK_OAK_BUTTON"), + Material::MangroveButton { .. } => f.write_str("MANGROVE_BUTTON"), + Material::BambooButton { .. } => f.write_str("BAMBOO_BUTTON"), + Material::CrimsonButton { .. } => f.write_str("CRIMSON_BUTTON"), + Material::WarpedButton { .. } => f.write_str("WARPED_BUTTON"), + Material::StonePressurePlate { .. } => f.write_str("STONE_PRESSURE_PLATE"), + Material::PolishedBlackstonePressurePlate { .. } => { + f.write_str("POLISHED_BLACKSTONE_PRESSURE_PLATE") + } + Material::LightWeightedPressurePlate { .. } => { + f.write_str("LIGHT_WEIGHTED_PRESSURE_PLATE") + } + Material::HeavyWeightedPressurePlate { .. } => { + f.write_str("HEAVY_WEIGHTED_PRESSURE_PLATE") + } + Material::OakPressurePlate { .. } => f.write_str("OAK_PRESSURE_PLATE"), + Material::SprucePressurePlate { .. } => f.write_str("SPRUCE_PRESSURE_PLATE"), + Material::BirchPressurePlate { .. } => f.write_str("BIRCH_PRESSURE_PLATE"), + Material::JunglePressurePlate { .. } => f.write_str("JUNGLE_PRESSURE_PLATE"), + Material::AcaciaPressurePlate { .. } => f.write_str("ACACIA_PRESSURE_PLATE"), + Material::CherryPressurePlate { .. } => f.write_str("CHERRY_PRESSURE_PLATE"), + Material::DarkOakPressurePlate { .. } => f.write_str("DARK_OAK_PRESSURE_PLATE"), + Material::MangrovePressurePlate { .. } => f.write_str("MANGROVE_PRESSURE_PLATE"), + Material::BambooPressurePlate { .. } => f.write_str("BAMBOO_PRESSURE_PLATE"), + Material::CrimsonPressurePlate { .. } => f.write_str("CRIMSON_PRESSURE_PLATE"), + Material::WarpedPressurePlate { .. } => f.write_str("WARPED_PRESSURE_PLATE"), + Material::IronDoor { .. } => f.write_str("IRON_DOOR"), + Material::OakDoor { .. } => f.write_str("OAK_DOOR"), + Material::SpruceDoor { .. } => f.write_str("SPRUCE_DOOR"), + Material::BirchDoor { .. } => f.write_str("BIRCH_DOOR"), + Material::JungleDoor { .. } => f.write_str("JUNGLE_DOOR"), + Material::AcaciaDoor { .. } => f.write_str("ACACIA_DOOR"), + Material::CherryDoor { .. } => f.write_str("CHERRY_DOOR"), + Material::DarkOakDoor { .. } => f.write_str("DARK_OAK_DOOR"), + Material::MangroveDoor { .. } => f.write_str("MANGROVE_DOOR"), + Material::BambooDoor { .. } => f.write_str("BAMBOO_DOOR"), + Material::CrimsonDoor { .. } => f.write_str("CRIMSON_DOOR"), + Material::WarpedDoor { .. } => f.write_str("WARPED_DOOR"), + Material::CopperDoor { .. } => f.write_str("COPPER_DOOR"), + Material::ExposedCopperDoor { .. } => f.write_str("EXPOSED_COPPER_DOOR"), + Material::WeatheredCopperDoor { .. } => f.write_str("WEATHERED_COPPER_DOOR"), + Material::OxidizedCopperDoor { .. } => f.write_str("OXIDIZED_COPPER_DOOR"), + Material::WaxedCopperDoor { .. } => f.write_str("WAXED_COPPER_DOOR"), + Material::WaxedExposedCopperDoor { .. } => f.write_str("WAXED_EXPOSED_COPPER_DOOR"), + Material::WaxedWeatheredCopperDoor { .. } => f.write_str("WAXED_WEATHERED_COPPER_DOOR"), + Material::WaxedOxidizedCopperDoor { .. } => f.write_str("WAXED_OXIDIZED_COPPER_DOOR"), + Material::IronTrapdoor { .. } => f.write_str("IRON_TRAPDOOR"), + Material::OakTrapdoor { .. } => f.write_str("OAK_TRAPDOOR"), + Material::SpruceTrapdoor { .. } => f.write_str("SPRUCE_TRAPDOOR"), + Material::BirchTrapdoor { .. } => f.write_str("BIRCH_TRAPDOOR"), + Material::JungleTrapdoor { .. } => f.write_str("JUNGLE_TRAPDOOR"), + Material::AcaciaTrapdoor { .. } => f.write_str("ACACIA_TRAPDOOR"), + Material::CherryTrapdoor { .. } => f.write_str("CHERRY_TRAPDOOR"), + Material::DarkOakTrapdoor { .. } => f.write_str("DARK_OAK_TRAPDOOR"), + Material::MangroveTrapdoor { .. } => f.write_str("MANGROVE_TRAPDOOR"), + Material::BambooTrapdoor { .. } => f.write_str("BAMBOO_TRAPDOOR"), + Material::CrimsonTrapdoor { .. } => f.write_str("CRIMSON_TRAPDOOR"), + Material::WarpedTrapdoor { .. } => f.write_str("WARPED_TRAPDOOR"), + Material::CopperTrapdoor { .. } => f.write_str("COPPER_TRAPDOOR"), + Material::ExposedCopperTrapdoor { .. } => f.write_str("EXPOSED_COPPER_TRAPDOOR"), + Material::WeatheredCopperTrapdoor { .. } => f.write_str("WEATHERED_COPPER_TRAPDOOR"), + Material::OxidizedCopperTrapdoor { .. } => f.write_str("OXIDIZED_COPPER_TRAPDOOR"), + Material::WaxedCopperTrapdoor { .. } => f.write_str("WAXED_COPPER_TRAPDOOR"), + Material::WaxedExposedCopperTrapdoor { .. } => { + f.write_str("WAXED_EXPOSED_COPPER_TRAPDOOR") + } + Material::WaxedWeatheredCopperTrapdoor { .. } => { + f.write_str("WAXED_WEATHERED_COPPER_TRAPDOOR") + } + Material::WaxedOxidizedCopperTrapdoor { .. } => { + f.write_str("WAXED_OXIDIZED_COPPER_TRAPDOOR") + } + Material::OakFenceGate { .. } => f.write_str("OAK_FENCE_GATE"), + Material::SpruceFenceGate { .. } => f.write_str("SPRUCE_FENCE_GATE"), + Material::BirchFenceGate { .. } => f.write_str("BIRCH_FENCE_GATE"), + Material::JungleFenceGate { .. } => f.write_str("JUNGLE_FENCE_GATE"), + Material::AcaciaFenceGate { .. } => f.write_str("ACACIA_FENCE_GATE"), + Material::CherryFenceGate { .. } => f.write_str("CHERRY_FENCE_GATE"), + Material::DarkOakFenceGate { .. } => f.write_str("DARK_OAK_FENCE_GATE"), + Material::MangroveFenceGate { .. } => f.write_str("MANGROVE_FENCE_GATE"), + Material::BambooFenceGate { .. } => f.write_str("BAMBOO_FENCE_GATE"), + Material::CrimsonFenceGate { .. } => f.write_str("CRIMSON_FENCE_GATE"), + Material::WarpedFenceGate { .. } => f.write_str("WARPED_FENCE_GATE"), + Material::PoweredRail { .. } => f.write_str("POWERED_RAIL"), + Material::DetectorRail { .. } => f.write_str("DETECTOR_RAIL"), + Material::Rail { .. } => f.write_str("RAIL"), + Material::ActivatorRail { .. } => f.write_str("ACTIVATOR_RAIL"), + Material::Saddle { .. } => f.write_str("SADDLE"), + Material::Minecart { .. } => f.write_str("MINECART"), + Material::ChestMinecart { .. } => f.write_str("CHEST_MINECART"), + Material::FurnaceMinecart { .. } => f.write_str("FURNACE_MINECART"), + Material::TntMinecart { .. } => f.write_str("TNT_MINECART"), + Material::HopperMinecart { .. } => f.write_str("HOPPER_MINECART"), + Material::CarrotOnAStick { .. } => f.write_str("CARROT_ON_A_STICK"), + Material::WarpedFungusOnAStick { .. } => f.write_str("WARPED_FUNGUS_ON_A_STICK"), + Material::Elytra { .. } => f.write_str("ELYTRA"), + Material::OakBoat { .. } => f.write_str("OAK_BOAT"), + Material::OakChestBoat { .. } => f.write_str("OAK_CHEST_BOAT"), + Material::SpruceBoat { .. } => f.write_str("SPRUCE_BOAT"), + Material::SpruceChestBoat { .. } => f.write_str("SPRUCE_CHEST_BOAT"), + Material::BirchBoat { .. } => f.write_str("BIRCH_BOAT"), + Material::BirchChestBoat { .. } => f.write_str("BIRCH_CHEST_BOAT"), + Material::JungleBoat { .. } => f.write_str("JUNGLE_BOAT"), + Material::JungleChestBoat { .. } => f.write_str("JUNGLE_CHEST_BOAT"), + Material::AcaciaBoat { .. } => f.write_str("ACACIA_BOAT"), + Material::AcaciaChestBoat { .. } => f.write_str("ACACIA_CHEST_BOAT"), + Material::CherryBoat { .. } => f.write_str("CHERRY_BOAT"), + Material::CherryChestBoat { .. } => f.write_str("CHERRY_CHEST_BOAT"), + Material::DarkOakBoat { .. } => f.write_str("DARK_OAK_BOAT"), + Material::DarkOakChestBoat { .. } => f.write_str("DARK_OAK_CHEST_BOAT"), + Material::MangroveBoat { .. } => f.write_str("MANGROVE_BOAT"), + Material::MangroveChestBoat { .. } => f.write_str("MANGROVE_CHEST_BOAT"), + Material::BambooRaft { .. } => f.write_str("BAMBOO_RAFT"), + Material::BambooChestRaft { .. } => f.write_str("BAMBOO_CHEST_RAFT"), + Material::StructureBlock { .. } => f.write_str("STRUCTURE_BLOCK"), + Material::Jigsaw { .. } => f.write_str("JIGSAW"), + Material::TurtleHelmet { .. } => f.write_str("TURTLE_HELMET"), + Material::TurtleScute { .. } => f.write_str("TURTLE_SCUTE"), + Material::ArmadilloScute { .. } => f.write_str("ARMADILLO_SCUTE"), + Material::WolfArmor { .. } => f.write_str("WOLF_ARMOR"), + Material::FlintAndSteel { .. } => f.write_str("FLINT_AND_STEEL"), + Material::Bowl { .. } => f.write_str("BOWL"), + Material::Apple { .. } => f.write_str("APPLE"), + Material::Bow { .. } => f.write_str("BOW"), + Material::Arrow { .. } => f.write_str("ARROW"), + Material::Coal { .. } => f.write_str("COAL"), + Material::Charcoal { .. } => f.write_str("CHARCOAL"), + Material::Diamond { .. } => f.write_str("DIAMOND"), + Material::Emerald { .. } => f.write_str("EMERALD"), + Material::LapisLazuli { .. } => f.write_str("LAPIS_LAZULI"), + Material::Quartz { .. } => f.write_str("QUARTZ"), + Material::AmethystShard { .. } => f.write_str("AMETHYST_SHARD"), + Material::RawIron { .. } => f.write_str("RAW_IRON"), + Material::IronIngot { .. } => f.write_str("IRON_INGOT"), + Material::RawCopper { .. } => f.write_str("RAW_COPPER"), + Material::CopperIngot { .. } => f.write_str("COPPER_INGOT"), + Material::RawGold { .. } => f.write_str("RAW_GOLD"), + Material::GoldIngot { .. } => f.write_str("GOLD_INGOT"), + Material::NetheriteIngot { .. } => f.write_str("NETHERITE_INGOT"), + Material::NetheriteScrap { .. } => f.write_str("NETHERITE_SCRAP"), + Material::WoodenSword { .. } => f.write_str("WOODEN_SWORD"), + Material::WoodenShovel { .. } => f.write_str("WOODEN_SHOVEL"), + Material::WoodenPickaxe { .. } => f.write_str("WOODEN_PICKAXE"), + Material::WoodenAxe { .. } => f.write_str("WOODEN_AXE"), + Material::WoodenHoe { .. } => f.write_str("WOODEN_HOE"), + Material::StoneSword { .. } => f.write_str("STONE_SWORD"), + Material::StoneShovel { .. } => f.write_str("STONE_SHOVEL"), + Material::StonePickaxe { .. } => f.write_str("STONE_PICKAXE"), + Material::StoneAxe { .. } => f.write_str("STONE_AXE"), + Material::StoneHoe { .. } => f.write_str("STONE_HOE"), + Material::GoldenSword { .. } => f.write_str("GOLDEN_SWORD"), + Material::GoldenShovel { .. } => f.write_str("GOLDEN_SHOVEL"), + Material::GoldenPickaxe { .. } => f.write_str("GOLDEN_PICKAXE"), + Material::GoldenAxe { .. } => f.write_str("GOLDEN_AXE"), + Material::GoldenHoe { .. } => f.write_str("GOLDEN_HOE"), + Material::IronSword { .. } => f.write_str("IRON_SWORD"), + Material::IronShovel { .. } => f.write_str("IRON_SHOVEL"), + Material::IronPickaxe { .. } => f.write_str("IRON_PICKAXE"), + Material::IronAxe { .. } => f.write_str("IRON_AXE"), + Material::IronHoe { .. } => f.write_str("IRON_HOE"), + Material::DiamondSword { .. } => f.write_str("DIAMOND_SWORD"), + Material::DiamondShovel { .. } => f.write_str("DIAMOND_SHOVEL"), + Material::DiamondPickaxe { .. } => f.write_str("DIAMOND_PICKAXE"), + Material::DiamondAxe { .. } => f.write_str("DIAMOND_AXE"), + Material::DiamondHoe { .. } => f.write_str("DIAMOND_HOE"), + Material::NetheriteSword { .. } => f.write_str("NETHERITE_SWORD"), + Material::NetheriteShovel { .. } => f.write_str("NETHERITE_SHOVEL"), + Material::NetheritePickaxe { .. } => f.write_str("NETHERITE_PICKAXE"), + Material::NetheriteAxe { .. } => f.write_str("NETHERITE_AXE"), + Material::NetheriteHoe { .. } => f.write_str("NETHERITE_HOE"), + Material::Stick { .. } => f.write_str("STICK"), + Material::MushroomStew { .. } => f.write_str("MUSHROOM_STEW"), + Material::String { .. } => f.write_str("STRING"), + Material::Feather { .. } => f.write_str("FEATHER"), + Material::Gunpowder { .. } => f.write_str("GUNPOWDER"), + Material::WheatSeeds { .. } => f.write_str("WHEAT_SEEDS"), + Material::Wheat { .. } => f.write_str("WHEAT"), + Material::Bread { .. } => f.write_str("BREAD"), + Material::LeatherHelmet { .. } => f.write_str("LEATHER_HELMET"), + Material::LeatherChestplate { .. } => f.write_str("LEATHER_CHESTPLATE"), + Material::LeatherLeggings { .. } => f.write_str("LEATHER_LEGGINGS"), + Material::LeatherBoots { .. } => f.write_str("LEATHER_BOOTS"), + Material::ChainmailHelmet { .. } => f.write_str("CHAINMAIL_HELMET"), + Material::ChainmailChestplate { .. } => f.write_str("CHAINMAIL_CHESTPLATE"), + Material::ChainmailLeggings { .. } => f.write_str("CHAINMAIL_LEGGINGS"), + Material::ChainmailBoots { .. } => f.write_str("CHAINMAIL_BOOTS"), + Material::IronHelmet { .. } => f.write_str("IRON_HELMET"), + Material::IronChestplate { .. } => f.write_str("IRON_CHESTPLATE"), + Material::IronLeggings { .. } => f.write_str("IRON_LEGGINGS"), + Material::IronBoots { .. } => f.write_str("IRON_BOOTS"), + Material::DiamondHelmet { .. } => f.write_str("DIAMOND_HELMET"), + Material::DiamondChestplate { .. } => f.write_str("DIAMOND_CHESTPLATE"), + Material::DiamondLeggings { .. } => f.write_str("DIAMOND_LEGGINGS"), + Material::DiamondBoots { .. } => f.write_str("DIAMOND_BOOTS"), + Material::GoldenHelmet { .. } => f.write_str("GOLDEN_HELMET"), + Material::GoldenChestplate { .. } => f.write_str("GOLDEN_CHESTPLATE"), + Material::GoldenLeggings { .. } => f.write_str("GOLDEN_LEGGINGS"), + Material::GoldenBoots { .. } => f.write_str("GOLDEN_BOOTS"), + Material::NetheriteHelmet { .. } => f.write_str("NETHERITE_HELMET"), + Material::NetheriteChestplate { .. } => f.write_str("NETHERITE_CHESTPLATE"), + Material::NetheriteLeggings { .. } => f.write_str("NETHERITE_LEGGINGS"), + Material::NetheriteBoots { .. } => f.write_str("NETHERITE_BOOTS"), + Material::Flint { .. } => f.write_str("FLINT"), + Material::Porkchop { .. } => f.write_str("PORKCHOP"), + Material::CookedPorkchop { .. } => f.write_str("COOKED_PORKCHOP"), + Material::Painting { .. } => f.write_str("PAINTING"), + Material::GoldenApple { .. } => f.write_str("GOLDEN_APPLE"), + Material::EnchantedGoldenApple { .. } => f.write_str("ENCHANTED_GOLDEN_APPLE"), + Material::OakSign { .. } => f.write_str("OAK_SIGN"), + Material::SpruceSign { .. } => f.write_str("SPRUCE_SIGN"), + Material::BirchSign { .. } => f.write_str("BIRCH_SIGN"), + Material::JungleSign { .. } => f.write_str("JUNGLE_SIGN"), + Material::AcaciaSign { .. } => f.write_str("ACACIA_SIGN"), + Material::CherrySign { .. } => f.write_str("CHERRY_SIGN"), + Material::DarkOakSign { .. } => f.write_str("DARK_OAK_SIGN"), + Material::MangroveSign { .. } => f.write_str("MANGROVE_SIGN"), + Material::BambooSign { .. } => f.write_str("BAMBOO_SIGN"), + Material::CrimsonSign { .. } => f.write_str("CRIMSON_SIGN"), + Material::WarpedSign { .. } => f.write_str("WARPED_SIGN"), + Material::OakHangingSign { .. } => f.write_str("OAK_HANGING_SIGN"), + Material::SpruceHangingSign { .. } => f.write_str("SPRUCE_HANGING_SIGN"), + Material::BirchHangingSign { .. } => f.write_str("BIRCH_HANGING_SIGN"), + Material::JungleHangingSign { .. } => f.write_str("JUNGLE_HANGING_SIGN"), + Material::AcaciaHangingSign { .. } => f.write_str("ACACIA_HANGING_SIGN"), + Material::CherryHangingSign { .. } => f.write_str("CHERRY_HANGING_SIGN"), + Material::DarkOakHangingSign { .. } => f.write_str("DARK_OAK_HANGING_SIGN"), + Material::MangroveHangingSign { .. } => f.write_str("MANGROVE_HANGING_SIGN"), + Material::BambooHangingSign { .. } => f.write_str("BAMBOO_HANGING_SIGN"), + Material::CrimsonHangingSign { .. } => f.write_str("CRIMSON_HANGING_SIGN"), + Material::WarpedHangingSign { .. } => f.write_str("WARPED_HANGING_SIGN"), + Material::Bucket { .. } => f.write_str("BUCKET"), + Material::WaterBucket { .. } => f.write_str("WATER_BUCKET"), + Material::LavaBucket { .. } => f.write_str("LAVA_BUCKET"), + Material::PowderSnowBucket { .. } => f.write_str("POWDER_SNOW_BUCKET"), + Material::Snowball { .. } => f.write_str("SNOWBALL"), + Material::Leather { .. } => f.write_str("LEATHER"), + Material::MilkBucket { .. } => f.write_str("MILK_BUCKET"), + Material::PufferfishBucket { .. } => f.write_str("PUFFERFISH_BUCKET"), + Material::SalmonBucket { .. } => f.write_str("SALMON_BUCKET"), + Material::CodBucket { .. } => f.write_str("COD_BUCKET"), + Material::TropicalFishBucket { .. } => f.write_str("TROPICAL_FISH_BUCKET"), + Material::AxolotlBucket { .. } => f.write_str("AXOLOTL_BUCKET"), + Material::TadpoleBucket { .. } => f.write_str("TADPOLE_BUCKET"), + Material::Brick { .. } => f.write_str("BRICK"), + Material::ClayBall { .. } => f.write_str("CLAY_BALL"), + Material::DriedKelpBlock { .. } => f.write_str("DRIED_KELP_BLOCK"), + Material::Paper { .. } => f.write_str("PAPER"), + Material::Book { .. } => f.write_str("BOOK"), + Material::SlimeBall { .. } => f.write_str("SLIME_BALL"), + Material::Egg { .. } => f.write_str("EGG"), + Material::Compass { .. } => f.write_str("COMPASS"), + Material::RecoveryCompass { .. } => f.write_str("RECOVERY_COMPASS"), + Material::Bundle { .. } => f.write_str("BUNDLE"), + Material::FishingRod { .. } => f.write_str("FISHING_ROD"), + Material::Clock { .. } => f.write_str("CLOCK"), + Material::Spyglass { .. } => f.write_str("SPYGLASS"), + Material::GlowstoneDust { .. } => f.write_str("GLOWSTONE_DUST"), + Material::Cod { .. } => f.write_str("COD"), + Material::Salmon { .. } => f.write_str("SALMON"), + Material::TropicalFish { .. } => f.write_str("TROPICAL_FISH"), + Material::Pufferfish { .. } => f.write_str("PUFFERFISH"), + Material::CookedCod { .. } => f.write_str("COOKED_COD"), + Material::CookedSalmon { .. } => f.write_str("COOKED_SALMON"), + Material::InkSac { .. } => f.write_str("INK_SAC"), + Material::GlowInkSac { .. } => f.write_str("GLOW_INK_SAC"), + Material::CocoaBeans { .. } => f.write_str("COCOA_BEANS"), + Material::WhiteDye { .. } => f.write_str("WHITE_DYE"), + Material::OrangeDye { .. } => f.write_str("ORANGE_DYE"), + Material::MagentaDye { .. } => f.write_str("MAGENTA_DYE"), + Material::LightBlueDye { .. } => f.write_str("LIGHT_BLUE_DYE"), + Material::YellowDye { .. } => f.write_str("YELLOW_DYE"), + Material::LimeDye { .. } => f.write_str("LIME_DYE"), + Material::PinkDye { .. } => f.write_str("PINK_DYE"), + Material::GrayDye { .. } => f.write_str("GRAY_DYE"), + Material::LightGrayDye { .. } => f.write_str("LIGHT_GRAY_DYE"), + Material::CyanDye { .. } => f.write_str("CYAN_DYE"), + Material::PurpleDye { .. } => f.write_str("PURPLE_DYE"), + Material::BlueDye { .. } => f.write_str("BLUE_DYE"), + Material::BrownDye { .. } => f.write_str("BROWN_DYE"), + Material::GreenDye { .. } => f.write_str("GREEN_DYE"), + Material::RedDye { .. } => f.write_str("RED_DYE"), + Material::BlackDye { .. } => f.write_str("BLACK_DYE"), + Material::BoneMeal { .. } => f.write_str("BONE_MEAL"), + Material::Bone { .. } => f.write_str("BONE"), + Material::Sugar { .. } => f.write_str("SUGAR"), + Material::Cake { .. } => f.write_str("CAKE"), + Material::WhiteBed { .. } => f.write_str("WHITE_BED"), + Material::OrangeBed { .. } => f.write_str("ORANGE_BED"), + Material::MagentaBed { .. } => f.write_str("MAGENTA_BED"), + Material::LightBlueBed { .. } => f.write_str("LIGHT_BLUE_BED"), + Material::YellowBed { .. } => f.write_str("YELLOW_BED"), + Material::LimeBed { .. } => f.write_str("LIME_BED"), + Material::PinkBed { .. } => f.write_str("PINK_BED"), + Material::GrayBed { .. } => f.write_str("GRAY_BED"), + Material::LightGrayBed { .. } => f.write_str("LIGHT_GRAY_BED"), + Material::CyanBed { .. } => f.write_str("CYAN_BED"), + Material::PurpleBed { .. } => f.write_str("PURPLE_BED"), + Material::BlueBed { .. } => f.write_str("BLUE_BED"), + Material::BrownBed { .. } => f.write_str("BROWN_BED"), + Material::GreenBed { .. } => f.write_str("GREEN_BED"), + Material::RedBed { .. } => f.write_str("RED_BED"), + Material::BlackBed { .. } => f.write_str("BLACK_BED"), + Material::Cookie { .. } => f.write_str("COOKIE"), + Material::Crafter { .. } => f.write_str("CRAFTER"), + Material::FilledMap { .. } => f.write_str("FILLED_MAP"), + Material::Shears { .. } => f.write_str("SHEARS"), + Material::MelonSlice { .. } => f.write_str("MELON_SLICE"), + Material::DriedKelp { .. } => f.write_str("DRIED_KELP"), + Material::PumpkinSeeds { .. } => f.write_str("PUMPKIN_SEEDS"), + Material::MelonSeeds { .. } => f.write_str("MELON_SEEDS"), + Material::Beef { .. } => f.write_str("BEEF"), + Material::CookedBeef { .. } => f.write_str("COOKED_BEEF"), + Material::Chicken { .. } => f.write_str("CHICKEN"), + Material::CookedChicken { .. } => f.write_str("COOKED_CHICKEN"), + Material::RottenFlesh { .. } => f.write_str("ROTTEN_FLESH"), + Material::EnderPearl { .. } => f.write_str("ENDER_PEARL"), + Material::BlazeRod { .. } => f.write_str("BLAZE_ROD"), + Material::GhastTear { .. } => f.write_str("GHAST_TEAR"), + Material::GoldNugget { .. } => f.write_str("GOLD_NUGGET"), + Material::NetherWart { .. } => f.write_str("NETHER_WART"), + Material::Potion { .. } => f.write_str("POTION"), + Material::GlassBottle { .. } => f.write_str("GLASS_BOTTLE"), + Material::SpiderEye { .. } => f.write_str("SPIDER_EYE"), + Material::FermentedSpiderEye { .. } => f.write_str("FERMENTED_SPIDER_EYE"), + Material::BlazePowder { .. } => f.write_str("BLAZE_POWDER"), + Material::MagmaCream { .. } => f.write_str("MAGMA_CREAM"), + Material::BrewingStand { .. } => f.write_str("BREWING_STAND"), + Material::Cauldron { .. } => f.write_str("CAULDRON"), + Material::EnderEye { .. } => f.write_str("ENDER_EYE"), + Material::GlisteringMelonSlice { .. } => f.write_str("GLISTERING_MELON_SLICE"), + Material::ArmadilloSpawnEgg { .. } => f.write_str("ARMADILLO_SPAWN_EGG"), + Material::AllaySpawnEgg { .. } => f.write_str("ALLAY_SPAWN_EGG"), + Material::AxolotlSpawnEgg { .. } => f.write_str("AXOLOTL_SPAWN_EGG"), + Material::BatSpawnEgg { .. } => f.write_str("BAT_SPAWN_EGG"), + Material::BeeSpawnEgg { .. } => f.write_str("BEE_SPAWN_EGG"), + Material::BlazeSpawnEgg { .. } => f.write_str("BLAZE_SPAWN_EGG"), + Material::BoggedSpawnEgg { .. } => f.write_str("BOGGED_SPAWN_EGG"), + Material::BreezeSpawnEgg { .. } => f.write_str("BREEZE_SPAWN_EGG"), + Material::CatSpawnEgg { .. } => f.write_str("CAT_SPAWN_EGG"), + Material::CamelSpawnEgg { .. } => f.write_str("CAMEL_SPAWN_EGG"), + Material::CaveSpiderSpawnEgg { .. } => f.write_str("CAVE_SPIDER_SPAWN_EGG"), + Material::ChickenSpawnEgg { .. } => f.write_str("CHICKEN_SPAWN_EGG"), + Material::CodSpawnEgg { .. } => f.write_str("COD_SPAWN_EGG"), + Material::CowSpawnEgg { .. } => f.write_str("COW_SPAWN_EGG"), + Material::CreeperSpawnEgg { .. } => f.write_str("CREEPER_SPAWN_EGG"), + Material::DolphinSpawnEgg { .. } => f.write_str("DOLPHIN_SPAWN_EGG"), + Material::DonkeySpawnEgg { .. } => f.write_str("DONKEY_SPAWN_EGG"), + Material::DrownedSpawnEgg { .. } => f.write_str("DROWNED_SPAWN_EGG"), + Material::ElderGuardianSpawnEgg { .. } => f.write_str("ELDER_GUARDIAN_SPAWN_EGG"), + Material::EnderDragonSpawnEgg { .. } => f.write_str("ENDER_DRAGON_SPAWN_EGG"), + Material::EndermanSpawnEgg { .. } => f.write_str("ENDERMAN_SPAWN_EGG"), + Material::EndermiteSpawnEgg { .. } => f.write_str("ENDERMITE_SPAWN_EGG"), + Material::EvokerSpawnEgg { .. } => f.write_str("EVOKER_SPAWN_EGG"), + Material::FoxSpawnEgg { .. } => f.write_str("FOX_SPAWN_EGG"), + Material::FrogSpawnEgg { .. } => f.write_str("FROG_SPAWN_EGG"), + Material::GhastSpawnEgg { .. } => f.write_str("GHAST_SPAWN_EGG"), + Material::GlowSquidSpawnEgg { .. } => f.write_str("GLOW_SQUID_SPAWN_EGG"), + Material::GoatSpawnEgg { .. } => f.write_str("GOAT_SPAWN_EGG"), + Material::GuardianSpawnEgg { .. } => f.write_str("GUARDIAN_SPAWN_EGG"), + Material::HoglinSpawnEgg { .. } => f.write_str("HOGLIN_SPAWN_EGG"), + Material::HorseSpawnEgg { .. } => f.write_str("HORSE_SPAWN_EGG"), + Material::HuskSpawnEgg { .. } => f.write_str("HUSK_SPAWN_EGG"), + Material::IronGolemSpawnEgg { .. } => f.write_str("IRON_GOLEM_SPAWN_EGG"), + Material::LlamaSpawnEgg { .. } => f.write_str("LLAMA_SPAWN_EGG"), + Material::MagmaCubeSpawnEgg { .. } => f.write_str("MAGMA_CUBE_SPAWN_EGG"), + Material::MooshroomSpawnEgg { .. } => f.write_str("MOOSHROOM_SPAWN_EGG"), + Material::MuleSpawnEgg { .. } => f.write_str("MULE_SPAWN_EGG"), + Material::OcelotSpawnEgg { .. } => f.write_str("OCELOT_SPAWN_EGG"), + Material::PandaSpawnEgg { .. } => f.write_str("PANDA_SPAWN_EGG"), + Material::ParrotSpawnEgg { .. } => f.write_str("PARROT_SPAWN_EGG"), + Material::PhantomSpawnEgg { .. } => f.write_str("PHANTOM_SPAWN_EGG"), + Material::PigSpawnEgg { .. } => f.write_str("PIG_SPAWN_EGG"), + Material::PiglinSpawnEgg { .. } => f.write_str("PIGLIN_SPAWN_EGG"), + Material::PiglinBruteSpawnEgg { .. } => f.write_str("PIGLIN_BRUTE_SPAWN_EGG"), + Material::PillagerSpawnEgg { .. } => f.write_str("PILLAGER_SPAWN_EGG"), + Material::PolarBearSpawnEgg { .. } => f.write_str("POLAR_BEAR_SPAWN_EGG"), + Material::PufferfishSpawnEgg { .. } => f.write_str("PUFFERFISH_SPAWN_EGG"), + Material::RabbitSpawnEgg { .. } => f.write_str("RABBIT_SPAWN_EGG"), + Material::RavagerSpawnEgg { .. } => f.write_str("RAVAGER_SPAWN_EGG"), + Material::SalmonSpawnEgg { .. } => f.write_str("SALMON_SPAWN_EGG"), + Material::SheepSpawnEgg { .. } => f.write_str("SHEEP_SPAWN_EGG"), + Material::ShulkerSpawnEgg { .. } => f.write_str("SHULKER_SPAWN_EGG"), + Material::SilverfishSpawnEgg { .. } => f.write_str("SILVERFISH_SPAWN_EGG"), + Material::SkeletonSpawnEgg { .. } => f.write_str("SKELETON_SPAWN_EGG"), + Material::SkeletonHorseSpawnEgg { .. } => f.write_str("SKELETON_HORSE_SPAWN_EGG"), + Material::SlimeSpawnEgg { .. } => f.write_str("SLIME_SPAWN_EGG"), + Material::SnifferSpawnEgg { .. } => f.write_str("SNIFFER_SPAWN_EGG"), + Material::SnowGolemSpawnEgg { .. } => f.write_str("SNOW_GOLEM_SPAWN_EGG"), + Material::SpiderSpawnEgg { .. } => f.write_str("SPIDER_SPAWN_EGG"), + Material::SquidSpawnEgg { .. } => f.write_str("SQUID_SPAWN_EGG"), + Material::StraySpawnEgg { .. } => f.write_str("STRAY_SPAWN_EGG"), + Material::StriderSpawnEgg { .. } => f.write_str("STRIDER_SPAWN_EGG"), + Material::TadpoleSpawnEgg { .. } => f.write_str("TADPOLE_SPAWN_EGG"), + Material::TraderLlamaSpawnEgg { .. } => f.write_str("TRADER_LLAMA_SPAWN_EGG"), + Material::TropicalFishSpawnEgg { .. } => f.write_str("TROPICAL_FISH_SPAWN_EGG"), + Material::TurtleSpawnEgg { .. } => f.write_str("TURTLE_SPAWN_EGG"), + Material::VexSpawnEgg { .. } => f.write_str("VEX_SPAWN_EGG"), + Material::VillagerSpawnEgg { .. } => f.write_str("VILLAGER_SPAWN_EGG"), + Material::VindicatorSpawnEgg { .. } => f.write_str("VINDICATOR_SPAWN_EGG"), + Material::WanderingTraderSpawnEgg { .. } => f.write_str("WANDERING_TRADER_SPAWN_EGG"), + Material::WardenSpawnEgg { .. } => f.write_str("WARDEN_SPAWN_EGG"), + Material::WitchSpawnEgg { .. } => f.write_str("WITCH_SPAWN_EGG"), + Material::WitherSpawnEgg { .. } => f.write_str("WITHER_SPAWN_EGG"), + Material::WitherSkeletonSpawnEgg { .. } => f.write_str("WITHER_SKELETON_SPAWN_EGG"), + Material::WolfSpawnEgg { .. } => f.write_str("WOLF_SPAWN_EGG"), + Material::ZoglinSpawnEgg { .. } => f.write_str("ZOGLIN_SPAWN_EGG"), + Material::ZombieSpawnEgg { .. } => f.write_str("ZOMBIE_SPAWN_EGG"), + Material::ZombieHorseSpawnEgg { .. } => f.write_str("ZOMBIE_HORSE_SPAWN_EGG"), + Material::ZombieVillagerSpawnEgg { .. } => f.write_str("ZOMBIE_VILLAGER_SPAWN_EGG"), + Material::ZombifiedPiglinSpawnEgg { .. } => f.write_str("ZOMBIFIED_PIGLIN_SPAWN_EGG"), + Material::ExperienceBottle { .. } => f.write_str("EXPERIENCE_BOTTLE"), + Material::FireCharge { .. } => f.write_str("FIRE_CHARGE"), + Material::WindCharge { .. } => f.write_str("WIND_CHARGE"), + Material::WritableBook { .. } => f.write_str("WRITABLE_BOOK"), + Material::WrittenBook { .. } => f.write_str("WRITTEN_BOOK"), + Material::Mace { .. } => f.write_str("MACE"), + Material::ItemFrame { .. } => f.write_str("ITEM_FRAME"), + Material::GlowItemFrame { .. } => f.write_str("GLOW_ITEM_FRAME"), + Material::FlowerPot { .. } => f.write_str("FLOWER_POT"), + Material::Carrot { .. } => f.write_str("CARROT"), + Material::Potato { .. } => f.write_str("POTATO"), + Material::BakedPotato { .. } => f.write_str("BAKED_POTATO"), + Material::PoisonousPotato { .. } => f.write_str("POISONOUS_POTATO"), + Material::Map { .. } => f.write_str("MAP"), + Material::GoldenCarrot { .. } => f.write_str("GOLDEN_CARROT"), + Material::SkeletonSkull { .. } => f.write_str("SKELETON_SKULL"), + Material::WitherSkeletonSkull { .. } => f.write_str("WITHER_SKELETON_SKULL"), + Material::PlayerHead { .. } => f.write_str("PLAYER_HEAD"), + Material::ZombieHead { .. } => f.write_str("ZOMBIE_HEAD"), + Material::CreeperHead { .. } => f.write_str("CREEPER_HEAD"), + Material::DragonHead { .. } => f.write_str("DRAGON_HEAD"), + Material::PiglinHead { .. } => f.write_str("PIGLIN_HEAD"), + Material::NetherStar { .. } => f.write_str("NETHER_STAR"), + Material::PumpkinPie { .. } => f.write_str("PUMPKIN_PIE"), + Material::FireworkRocket { .. } => f.write_str("FIREWORK_ROCKET"), + Material::FireworkStar { .. } => f.write_str("FIREWORK_STAR"), + Material::EnchantedBook { .. } => f.write_str("ENCHANTED_BOOK"), + Material::NetherBrick { .. } => f.write_str("NETHER_BRICK"), + Material::PrismarineShard { .. } => f.write_str("PRISMARINE_SHARD"), + Material::PrismarineCrystals { .. } => f.write_str("PRISMARINE_CRYSTALS"), + Material::Rabbit { .. } => f.write_str("RABBIT"), + Material::CookedRabbit { .. } => f.write_str("COOKED_RABBIT"), + Material::RabbitStew { .. } => f.write_str("RABBIT_STEW"), + Material::RabbitFoot { .. } => f.write_str("RABBIT_FOOT"), + Material::RabbitHide { .. } => f.write_str("RABBIT_HIDE"), + Material::ArmorStand { .. } => f.write_str("ARMOR_STAND"), + Material::IronHorseArmor { .. } => f.write_str("IRON_HORSE_ARMOR"), + Material::GoldenHorseArmor { .. } => f.write_str("GOLDEN_HORSE_ARMOR"), + Material::DiamondHorseArmor { .. } => f.write_str("DIAMOND_HORSE_ARMOR"), + Material::LeatherHorseArmor { .. } => f.write_str("LEATHER_HORSE_ARMOR"), + Material::Lead { .. } => f.write_str("LEAD"), + Material::NameTag { .. } => f.write_str("NAME_TAG"), + Material::CommandBlockMinecart { .. } => f.write_str("COMMAND_BLOCK_MINECART"), + Material::Mutton { .. } => f.write_str("MUTTON"), + Material::CookedMutton { .. } => f.write_str("COOKED_MUTTON"), + Material::WhiteBanner { .. } => f.write_str("WHITE_BANNER"), + Material::OrangeBanner { .. } => f.write_str("ORANGE_BANNER"), + Material::MagentaBanner { .. } => f.write_str("MAGENTA_BANNER"), + Material::LightBlueBanner { .. } => f.write_str("LIGHT_BLUE_BANNER"), + Material::YellowBanner { .. } => f.write_str("YELLOW_BANNER"), + Material::LimeBanner { .. } => f.write_str("LIME_BANNER"), + Material::PinkBanner { .. } => f.write_str("PINK_BANNER"), + Material::GrayBanner { .. } => f.write_str("GRAY_BANNER"), + Material::LightGrayBanner { .. } => f.write_str("LIGHT_GRAY_BANNER"), + Material::CyanBanner { .. } => f.write_str("CYAN_BANNER"), + Material::PurpleBanner { .. } => f.write_str("PURPLE_BANNER"), + Material::BlueBanner { .. } => f.write_str("BLUE_BANNER"), + Material::BrownBanner { .. } => f.write_str("BROWN_BANNER"), + Material::GreenBanner { .. } => f.write_str("GREEN_BANNER"), + Material::RedBanner { .. } => f.write_str("RED_BANNER"), + Material::BlackBanner { .. } => f.write_str("BLACK_BANNER"), + Material::EndCrystal { .. } => f.write_str("END_CRYSTAL"), + Material::ChorusFruit { .. } => f.write_str("CHORUS_FRUIT"), + Material::PoppedChorusFruit { .. } => f.write_str("POPPED_CHORUS_FRUIT"), + Material::TorchflowerSeeds { .. } => f.write_str("TORCHFLOWER_SEEDS"), + Material::PitcherPod { .. } => f.write_str("PITCHER_POD"), + Material::Beetroot { .. } => f.write_str("BEETROOT"), + Material::BeetrootSeeds { .. } => f.write_str("BEETROOT_SEEDS"), + Material::BeetrootSoup { .. } => f.write_str("BEETROOT_SOUP"), + Material::DragonBreath { .. } => f.write_str("DRAGON_BREATH"), + Material::SplashPotion { .. } => f.write_str("SPLASH_POTION"), + Material::SpectralArrow { .. } => f.write_str("SPECTRAL_ARROW"), + Material::TippedArrow { .. } => f.write_str("TIPPED_ARROW"), + Material::LingeringPotion { .. } => f.write_str("LINGERING_POTION"), + Material::Shield { .. } => f.write_str("SHIELD"), + Material::TotemOfUndying { .. } => f.write_str("TOTEM_OF_UNDYING"), + Material::ShulkerShell { .. } => f.write_str("SHULKER_SHELL"), + Material::IronNugget { .. } => f.write_str("IRON_NUGGET"), + Material::KnowledgeBook { .. } => f.write_str("KNOWLEDGE_BOOK"), + Material::DebugStick { .. } => f.write_str("DEBUG_STICK"), + Material::MusicDisc13 { .. } => f.write_str("MUSIC_DISC_13"), + Material::MusicDiscCat { .. } => f.write_str("MUSIC_DISC_CAT"), + Material::MusicDiscBlocks { .. } => f.write_str("MUSIC_DISC_BLOCKS"), + Material::MusicDiscChirp { .. } => f.write_str("MUSIC_DISC_CHIRP"), + Material::MusicDiscCreator { .. } => f.write_str("MUSIC_DISC_CREATOR"), + Material::MusicDiscCreatorMusicBox { .. } => { + f.write_str("MUSIC_DISC_CREATOR_MUSIC_BOX") + } + Material::MusicDiscFar { .. } => f.write_str("MUSIC_DISC_FAR"), + Material::MusicDiscMall { .. } => f.write_str("MUSIC_DISC_MALL"), + Material::MusicDiscMellohi { .. } => f.write_str("MUSIC_DISC_MELLOHI"), + Material::MusicDiscStal { .. } => f.write_str("MUSIC_DISC_STAL"), + Material::MusicDiscStrad { .. } => f.write_str("MUSIC_DISC_STRAD"), + Material::MusicDiscWard { .. } => f.write_str("MUSIC_DISC_WARD"), + Material::MusicDisc11 { .. } => f.write_str("MUSIC_DISC_11"), + Material::MusicDiscWait { .. } => f.write_str("MUSIC_DISC_WAIT"), + Material::MusicDiscOtherside { .. } => f.write_str("MUSIC_DISC_OTHERSIDE"), + Material::MusicDiscRelic { .. } => f.write_str("MUSIC_DISC_RELIC"), + Material::MusicDisc5 { .. } => f.write_str("MUSIC_DISC_5"), + Material::MusicDiscPigstep { .. } => f.write_str("MUSIC_DISC_PIGSTEP"), + Material::MusicDiscPrecipice { .. } => f.write_str("MUSIC_DISC_PRECIPICE"), + Material::DiscFragment5 { .. } => f.write_str("DISC_FRAGMENT_5"), + Material::Trident { .. } => f.write_str("TRIDENT"), + Material::PhantomMembrane { .. } => f.write_str("PHANTOM_MEMBRANE"), + Material::NautilusShell { .. } => f.write_str("NAUTILUS_SHELL"), + Material::HeartOfTheSea { .. } => f.write_str("HEART_OF_THE_SEA"), + Material::Crossbow { .. } => f.write_str("CROSSBOW"), + Material::SuspiciousStew { .. } => f.write_str("SUSPICIOUS_STEW"), + Material::Loom { .. } => f.write_str("LOOM"), + Material::FlowerBannerPattern { .. } => f.write_str("FLOWER_BANNER_PATTERN"), + Material::CreeperBannerPattern { .. } => f.write_str("CREEPER_BANNER_PATTERN"), + Material::SkullBannerPattern { .. } => f.write_str("SKULL_BANNER_PATTERN"), + Material::MojangBannerPattern { .. } => f.write_str("MOJANG_BANNER_PATTERN"), + Material::GlobeBannerPattern { .. } => f.write_str("GLOBE_BANNER_PATTERN"), + Material::PiglinBannerPattern { .. } => f.write_str("PIGLIN_BANNER_PATTERN"), + Material::FlowBannerPattern { .. } => f.write_str("FLOW_BANNER_PATTERN"), + Material::GusterBannerPattern { .. } => f.write_str("GUSTER_BANNER_PATTERN"), + Material::GoatHorn { .. } => f.write_str("GOAT_HORN"), + Material::Composter { .. } => f.write_str("COMPOSTER"), + Material::Barrel { .. } => f.write_str("BARREL"), + Material::Smoker { .. } => f.write_str("SMOKER"), + Material::BlastFurnace { .. } => f.write_str("BLAST_FURNACE"), + Material::CartographyTable { .. } => f.write_str("CARTOGRAPHY_TABLE"), + Material::FletchingTable { .. } => f.write_str("FLETCHING_TABLE"), + Material::Grindstone { .. } => f.write_str("GRINDSTONE"), + Material::SmithingTable { .. } => f.write_str("SMITHING_TABLE"), + Material::Stonecutter { .. } => f.write_str("STONECUTTER"), + Material::Bell { .. } => f.write_str("BELL"), + Material::Lantern { .. } => f.write_str("LANTERN"), + Material::SoulLantern { .. } => f.write_str("SOUL_LANTERN"), + Material::SweetBerries { .. } => f.write_str("SWEET_BERRIES"), + Material::GlowBerries { .. } => f.write_str("GLOW_BERRIES"), + Material::Campfire { .. } => f.write_str("CAMPFIRE"), + Material::SoulCampfire { .. } => f.write_str("SOUL_CAMPFIRE"), + Material::Shroomlight { .. } => f.write_str("SHROOMLIGHT"), + Material::Honeycomb { .. } => f.write_str("HONEYCOMB"), + Material::BeeNest { .. } => f.write_str("BEE_NEST"), + Material::Beehive { .. } => f.write_str("BEEHIVE"), + Material::HoneyBottle { .. } => f.write_str("HONEY_BOTTLE"), + Material::HoneycombBlock { .. } => f.write_str("HONEYCOMB_BLOCK"), + Material::Lodestone { .. } => f.write_str("LODESTONE"), + Material::CryingObsidian { .. } => f.write_str("CRYING_OBSIDIAN"), + Material::Blackstone { .. } => f.write_str("BLACKSTONE"), + Material::BlackstoneSlab { .. } => f.write_str("BLACKSTONE_SLAB"), + Material::BlackstoneStairs { .. } => f.write_str("BLACKSTONE_STAIRS"), + Material::GildedBlackstone { .. } => f.write_str("GILDED_BLACKSTONE"), + Material::PolishedBlackstone { .. } => f.write_str("POLISHED_BLACKSTONE"), + Material::PolishedBlackstoneSlab { .. } => f.write_str("POLISHED_BLACKSTONE_SLAB"), + Material::PolishedBlackstoneStairs { .. } => f.write_str("POLISHED_BLACKSTONE_STAIRS"), + Material::ChiseledPolishedBlackstone { .. } => { + f.write_str("CHISELED_POLISHED_BLACKSTONE") + } + Material::PolishedBlackstoneBricks { .. } => f.write_str("POLISHED_BLACKSTONE_BRICKS"), + Material::PolishedBlackstoneBrickSlab { .. } => { + f.write_str("POLISHED_BLACKSTONE_BRICK_SLAB") + } + Material::PolishedBlackstoneBrickStairs { .. } => { + f.write_str("POLISHED_BLACKSTONE_BRICK_STAIRS") + } + Material::CrackedPolishedBlackstoneBricks { .. } => { + f.write_str("CRACKED_POLISHED_BLACKSTONE_BRICKS") + } + Material::RespawnAnchor { .. } => f.write_str("RESPAWN_ANCHOR"), + Material::Candle { .. } => f.write_str("CANDLE"), + Material::WhiteCandle { .. } => f.write_str("WHITE_CANDLE"), + Material::OrangeCandle { .. } => f.write_str("ORANGE_CANDLE"), + Material::MagentaCandle { .. } => f.write_str("MAGENTA_CANDLE"), + Material::LightBlueCandle { .. } => f.write_str("LIGHT_BLUE_CANDLE"), + Material::YellowCandle { .. } => f.write_str("YELLOW_CANDLE"), + Material::LimeCandle { .. } => f.write_str("LIME_CANDLE"), + Material::PinkCandle { .. } => f.write_str("PINK_CANDLE"), + Material::GrayCandle { .. } => f.write_str("GRAY_CANDLE"), + Material::LightGrayCandle { .. } => f.write_str("LIGHT_GRAY_CANDLE"), + Material::CyanCandle { .. } => f.write_str("CYAN_CANDLE"), + Material::PurpleCandle { .. } => f.write_str("PURPLE_CANDLE"), + Material::BlueCandle { .. } => f.write_str("BLUE_CANDLE"), + Material::BrownCandle { .. } => f.write_str("BROWN_CANDLE"), + Material::GreenCandle { .. } => f.write_str("GREEN_CANDLE"), + Material::RedCandle { .. } => f.write_str("RED_CANDLE"), + Material::BlackCandle { .. } => f.write_str("BLACK_CANDLE"), + Material::SmallAmethystBud { .. } => f.write_str("SMALL_AMETHYST_BUD"), + Material::MediumAmethystBud { .. } => f.write_str("MEDIUM_AMETHYST_BUD"), + Material::LargeAmethystBud { .. } => f.write_str("LARGE_AMETHYST_BUD"), + Material::AmethystCluster { .. } => f.write_str("AMETHYST_CLUSTER"), + Material::PointedDripstone { .. } => f.write_str("POINTED_DRIPSTONE"), + Material::OchreFroglight { .. } => f.write_str("OCHRE_FROGLIGHT"), + Material::VerdantFroglight { .. } => f.write_str("VERDANT_FROGLIGHT"), + Material::PearlescentFroglight { .. } => f.write_str("PEARLESCENT_FROGLIGHT"), + Material::Frogspawn { .. } => f.write_str("FROGSPAWN"), + Material::EchoShard { .. } => f.write_str("ECHO_SHARD"), + Material::Brush { .. } => f.write_str("BRUSH"), + Material::NetheriteUpgradeSmithingTemplate { .. } => { + f.write_str("NETHERITE_UPGRADE_SMITHING_TEMPLATE") + } + Material::SentryArmorTrimSmithingTemplate { .. } => { + f.write_str("SENTRY_ARMOR_TRIM_SMITHING_TEMPLATE") + } + Material::DuneArmorTrimSmithingTemplate { .. } => { + f.write_str("DUNE_ARMOR_TRIM_SMITHING_TEMPLATE") + } + Material::CoastArmorTrimSmithingTemplate { .. } => { + f.write_str("COAST_ARMOR_TRIM_SMITHING_TEMPLATE") + } + Material::WildArmorTrimSmithingTemplate { .. } => { + f.write_str("WILD_ARMOR_TRIM_SMITHING_TEMPLATE") + } + Material::WardArmorTrimSmithingTemplate { .. } => { + f.write_str("WARD_ARMOR_TRIM_SMITHING_TEMPLATE") + } + Material::EyeArmorTrimSmithingTemplate { .. } => { + f.write_str("EYE_ARMOR_TRIM_SMITHING_TEMPLATE") + } + Material::VexArmorTrimSmithingTemplate { .. } => { + f.write_str("VEX_ARMOR_TRIM_SMITHING_TEMPLATE") + } + Material::TideArmorTrimSmithingTemplate { .. } => { + f.write_str("TIDE_ARMOR_TRIM_SMITHING_TEMPLATE") + } + Material::SnoutArmorTrimSmithingTemplate { .. } => { + f.write_str("SNOUT_ARMOR_TRIM_SMITHING_TEMPLATE") + } + Material::RibArmorTrimSmithingTemplate { .. } => { + f.write_str("RIB_ARMOR_TRIM_SMITHING_TEMPLATE") + } + Material::SpireArmorTrimSmithingTemplate { .. } => { + f.write_str("SPIRE_ARMOR_TRIM_SMITHING_TEMPLATE") + } + Material::WayfinderArmorTrimSmithingTemplate { .. } => { + f.write_str("WAYFINDER_ARMOR_TRIM_SMITHING_TEMPLATE") + } + Material::ShaperArmorTrimSmithingTemplate { .. } => { + f.write_str("SHAPER_ARMOR_TRIM_SMITHING_TEMPLATE") + } + Material::SilenceArmorTrimSmithingTemplate { .. } => { + f.write_str("SILENCE_ARMOR_TRIM_SMITHING_TEMPLATE") + } + Material::RaiserArmorTrimSmithingTemplate { .. } => { + f.write_str("RAISER_ARMOR_TRIM_SMITHING_TEMPLATE") + } + Material::HostArmorTrimSmithingTemplate { .. } => { + f.write_str("HOST_ARMOR_TRIM_SMITHING_TEMPLATE") + } + Material::FlowArmorTrimSmithingTemplate { .. } => { + f.write_str("FLOW_ARMOR_TRIM_SMITHING_TEMPLATE") + } + Material::BoltArmorTrimSmithingTemplate { .. } => { + f.write_str("BOLT_ARMOR_TRIM_SMITHING_TEMPLATE") + } + Material::AnglerPotterySherd { .. } => f.write_str("ANGLER_POTTERY_SHERD"), + Material::ArcherPotterySherd { .. } => f.write_str("ARCHER_POTTERY_SHERD"), + Material::ArmsUpPotterySherd { .. } => f.write_str("ARMS_UP_POTTERY_SHERD"), + Material::BladePotterySherd { .. } => f.write_str("BLADE_POTTERY_SHERD"), + Material::BrewerPotterySherd { .. } => f.write_str("BREWER_POTTERY_SHERD"), + Material::BurnPotterySherd { .. } => f.write_str("BURN_POTTERY_SHERD"), + Material::DangerPotterySherd { .. } => f.write_str("DANGER_POTTERY_SHERD"), + Material::ExplorerPotterySherd { .. } => f.write_str("EXPLORER_POTTERY_SHERD"), + Material::FlowPotterySherd { .. } => f.write_str("FLOW_POTTERY_SHERD"), + Material::FriendPotterySherd { .. } => f.write_str("FRIEND_POTTERY_SHERD"), + Material::GusterPotterySherd { .. } => f.write_str("GUSTER_POTTERY_SHERD"), + Material::HeartPotterySherd { .. } => f.write_str("HEART_POTTERY_SHERD"), + Material::HeartbreakPotterySherd { .. } => f.write_str("HEARTBREAK_POTTERY_SHERD"), + Material::HowlPotterySherd { .. } => f.write_str("HOWL_POTTERY_SHERD"), + Material::MinerPotterySherd { .. } => f.write_str("MINER_POTTERY_SHERD"), + Material::MournerPotterySherd { .. } => f.write_str("MOURNER_POTTERY_SHERD"), + Material::PlentyPotterySherd { .. } => f.write_str("PLENTY_POTTERY_SHERD"), + Material::PrizePotterySherd { .. } => f.write_str("PRIZE_POTTERY_SHERD"), + Material::ScrapePotterySherd { .. } => f.write_str("SCRAPE_POTTERY_SHERD"), + Material::SheafPotterySherd { .. } => f.write_str("SHEAF_POTTERY_SHERD"), + Material::ShelterPotterySherd { .. } => f.write_str("SHELTER_POTTERY_SHERD"), + Material::SkullPotterySherd { .. } => f.write_str("SKULL_POTTERY_SHERD"), + Material::SnortPotterySherd { .. } => f.write_str("SNORT_POTTERY_SHERD"), + Material::CopperGrate { .. } => f.write_str("COPPER_GRATE"), + Material::ExposedCopperGrate { .. } => f.write_str("EXPOSED_COPPER_GRATE"), + Material::WeatheredCopperGrate { .. } => f.write_str("WEATHERED_COPPER_GRATE"), + Material::OxidizedCopperGrate { .. } => f.write_str("OXIDIZED_COPPER_GRATE"), + Material::WaxedCopperGrate { .. } => f.write_str("WAXED_COPPER_GRATE"), + Material::WaxedExposedCopperGrate { .. } => f.write_str("WAXED_EXPOSED_COPPER_GRATE"), + Material::WaxedWeatheredCopperGrate { .. } => { + f.write_str("WAXED_WEATHERED_COPPER_GRATE") + } + Material::WaxedOxidizedCopperGrate { .. } => f.write_str("WAXED_OXIDIZED_COPPER_GRATE"), + Material::CopperBulb { .. } => f.write_str("COPPER_BULB"), + Material::ExposedCopperBulb { .. } => f.write_str("EXPOSED_COPPER_BULB"), + Material::WeatheredCopperBulb { .. } => f.write_str("WEATHERED_COPPER_BULB"), + Material::OxidizedCopperBulb { .. } => f.write_str("OXIDIZED_COPPER_BULB"), + Material::WaxedCopperBulb { .. } => f.write_str("WAXED_COPPER_BULB"), + Material::WaxedExposedCopperBulb { .. } => f.write_str("WAXED_EXPOSED_COPPER_BULB"), + Material::WaxedWeatheredCopperBulb { .. } => f.write_str("WAXED_WEATHERED_COPPER_BULB"), + Material::WaxedOxidizedCopperBulb { .. } => f.write_str("WAXED_OXIDIZED_COPPER_BULB"), + Material::TrialSpawner { .. } => f.write_str("TRIAL_SPAWNER"), + Material::TrialKey { .. } => f.write_str("TRIAL_KEY"), + Material::OminousTrialKey { .. } => f.write_str("OMINOUS_TRIAL_KEY"), + Material::Vault { .. } => f.write_str("VAULT"), + Material::OminousBottle { .. } => f.write_str("OMINOUS_BOTTLE"), + Material::BreezeRod { .. } => f.write_str("BREEZE_ROD"), + Material::Water { .. } => f.write_str("WATER"), + Material::Lava { .. } => f.write_str("LAVA"), + Material::TallSeagrass { .. } => f.write_str("TALL_SEAGRASS"), + Material::PistonHead { .. } => f.write_str("PISTON_HEAD"), + Material::MovingPiston { .. } => f.write_str("MOVING_PISTON"), + Material::WallTorch { .. } => f.write_str("WALL_TORCH"), + Material::Fire { .. } => f.write_str("FIRE"), + Material::SoulFire { .. } => f.write_str("SOUL_FIRE"), + Material::RedstoneWire { .. } => f.write_str("REDSTONE_WIRE"), + Material::OakWallSign { .. } => f.write_str("OAK_WALL_SIGN"), + Material::SpruceWallSign { .. } => f.write_str("SPRUCE_WALL_SIGN"), + Material::BirchWallSign { .. } => f.write_str("BIRCH_WALL_SIGN"), + Material::AcaciaWallSign { .. } => f.write_str("ACACIA_WALL_SIGN"), + Material::CherryWallSign { .. } => f.write_str("CHERRY_WALL_SIGN"), + Material::JungleWallSign { .. } => f.write_str("JUNGLE_WALL_SIGN"), + Material::DarkOakWallSign { .. } => f.write_str("DARK_OAK_WALL_SIGN"), + Material::MangroveWallSign { .. } => f.write_str("MANGROVE_WALL_SIGN"), + Material::BambooWallSign { .. } => f.write_str("BAMBOO_WALL_SIGN"), + Material::OakWallHangingSign { .. } => f.write_str("OAK_WALL_HANGING_SIGN"), + Material::SpruceWallHangingSign { .. } => f.write_str("SPRUCE_WALL_HANGING_SIGN"), + Material::BirchWallHangingSign { .. } => f.write_str("BIRCH_WALL_HANGING_SIGN"), + Material::AcaciaWallHangingSign { .. } => f.write_str("ACACIA_WALL_HANGING_SIGN"), + Material::CherryWallHangingSign { .. } => f.write_str("CHERRY_WALL_HANGING_SIGN"), + Material::JungleWallHangingSign { .. } => f.write_str("JUNGLE_WALL_HANGING_SIGN"), + Material::DarkOakWallHangingSign { .. } => f.write_str("DARK_OAK_WALL_HANGING_SIGN"), + Material::MangroveWallHangingSign { .. } => f.write_str("MANGROVE_WALL_HANGING_SIGN"), + Material::CrimsonWallHangingSign { .. } => f.write_str("CRIMSON_WALL_HANGING_SIGN"), + Material::WarpedWallHangingSign { .. } => f.write_str("WARPED_WALL_HANGING_SIGN"), + Material::BambooWallHangingSign { .. } => f.write_str("BAMBOO_WALL_HANGING_SIGN"), + Material::RedstoneWallTorch { .. } => f.write_str("REDSTONE_WALL_TORCH"), + Material::SoulWallTorch { .. } => f.write_str("SOUL_WALL_TORCH"), + Material::NetherPortal { .. } => f.write_str("NETHER_PORTAL"), + Material::AttachedPumpkinStem { .. } => f.write_str("ATTACHED_PUMPKIN_STEM"), + Material::AttachedMelonStem { .. } => f.write_str("ATTACHED_MELON_STEM"), + Material::PumpkinStem { .. } => f.write_str("PUMPKIN_STEM"), + Material::MelonStem { .. } => f.write_str("MELON_STEM"), + Material::WaterCauldron { .. } => f.write_str("WATER_CAULDRON"), + Material::LavaCauldron { .. } => f.write_str("LAVA_CAULDRON"), + Material::PowderSnowCauldron { .. } => f.write_str("POWDER_SNOW_CAULDRON"), + Material::EndPortal { .. } => f.write_str("END_PORTAL"), + Material::Cocoa { .. } => f.write_str("COCOA"), + Material::Tripwire { .. } => f.write_str("TRIPWIRE"), + Material::PottedTorchflower { .. } => f.write_str("POTTED_TORCHFLOWER"), + Material::PottedOakSapling { .. } => f.write_str("POTTED_OAK_SAPLING"), + Material::PottedSpruceSapling { .. } => f.write_str("POTTED_SPRUCE_SAPLING"), + Material::PottedBirchSapling { .. } => f.write_str("POTTED_BIRCH_SAPLING"), + Material::PottedJungleSapling { .. } => f.write_str("POTTED_JUNGLE_SAPLING"), + Material::PottedAcaciaSapling { .. } => f.write_str("POTTED_ACACIA_SAPLING"), + Material::PottedCherrySapling { .. } => f.write_str("POTTED_CHERRY_SAPLING"), + Material::PottedDarkOakSapling { .. } => f.write_str("POTTED_DARK_OAK_SAPLING"), + Material::PottedMangrovePropagule { .. } => f.write_str("POTTED_MANGROVE_PROPAGULE"), + Material::PottedFern { .. } => f.write_str("POTTED_FERN"), + Material::PottedDandelion { .. } => f.write_str("POTTED_DANDELION"), + Material::PottedPoppy { .. } => f.write_str("POTTED_POPPY"), + Material::PottedBlueOrchid { .. } => f.write_str("POTTED_BLUE_ORCHID"), + Material::PottedAllium { .. } => f.write_str("POTTED_ALLIUM"), + Material::PottedAzureBluet { .. } => f.write_str("POTTED_AZURE_BLUET"), + Material::PottedRedTulip { .. } => f.write_str("POTTED_RED_TULIP"), + Material::PottedOrangeTulip { .. } => f.write_str("POTTED_ORANGE_TULIP"), + Material::PottedWhiteTulip { .. } => f.write_str("POTTED_WHITE_TULIP"), + Material::PottedPinkTulip { .. } => f.write_str("POTTED_PINK_TULIP"), + Material::PottedOxeyeDaisy { .. } => f.write_str("POTTED_OXEYE_DAISY"), + Material::PottedCornflower { .. } => f.write_str("POTTED_CORNFLOWER"), + Material::PottedLilyOfTheValley { .. } => f.write_str("POTTED_LILY_OF_THE_VALLEY"), + Material::PottedWitherRose { .. } => f.write_str("POTTED_WITHER_ROSE"), + Material::PottedRedMushroom { .. } => f.write_str("POTTED_RED_MUSHROOM"), + Material::PottedBrownMushroom { .. } => f.write_str("POTTED_BROWN_MUSHROOM"), + Material::PottedDeadBush { .. } => f.write_str("POTTED_DEAD_BUSH"), + Material::PottedCactus { .. } => f.write_str("POTTED_CACTUS"), + Material::Carrots { .. } => f.write_str("CARROTS"), + Material::Potatoes { .. } => f.write_str("POTATOES"), + Material::SkeletonWallSkull { .. } => f.write_str("SKELETON_WALL_SKULL"), + Material::WitherSkeletonWallSkull { .. } => f.write_str("WITHER_SKELETON_WALL_SKULL"), + Material::ZombieWallHead { .. } => f.write_str("ZOMBIE_WALL_HEAD"), + Material::PlayerWallHead { .. } => f.write_str("PLAYER_WALL_HEAD"), + Material::CreeperWallHead { .. } => f.write_str("CREEPER_WALL_HEAD"), + Material::DragonWallHead { .. } => f.write_str("DRAGON_WALL_HEAD"), + Material::PiglinWallHead { .. } => f.write_str("PIGLIN_WALL_HEAD"), + Material::WhiteWallBanner { .. } => f.write_str("WHITE_WALL_BANNER"), + Material::OrangeWallBanner { .. } => f.write_str("ORANGE_WALL_BANNER"), + Material::MagentaWallBanner { .. } => f.write_str("MAGENTA_WALL_BANNER"), + Material::LightBlueWallBanner { .. } => f.write_str("LIGHT_BLUE_WALL_BANNER"), + Material::YellowWallBanner { .. } => f.write_str("YELLOW_WALL_BANNER"), + Material::LimeWallBanner { .. } => f.write_str("LIME_WALL_BANNER"), + Material::PinkWallBanner { .. } => f.write_str("PINK_WALL_BANNER"), + Material::GrayWallBanner { .. } => f.write_str("GRAY_WALL_BANNER"), + Material::LightGrayWallBanner { .. } => f.write_str("LIGHT_GRAY_WALL_BANNER"), + Material::CyanWallBanner { .. } => f.write_str("CYAN_WALL_BANNER"), + Material::PurpleWallBanner { .. } => f.write_str("PURPLE_WALL_BANNER"), + Material::BlueWallBanner { .. } => f.write_str("BLUE_WALL_BANNER"), + Material::BrownWallBanner { .. } => f.write_str("BROWN_WALL_BANNER"), + Material::GreenWallBanner { .. } => f.write_str("GREEN_WALL_BANNER"), + Material::RedWallBanner { .. } => f.write_str("RED_WALL_BANNER"), + Material::BlackWallBanner { .. } => f.write_str("BLACK_WALL_BANNER"), + Material::TorchflowerCrop { .. } => f.write_str("TORCHFLOWER_CROP"), + Material::PitcherCrop { .. } => f.write_str("PITCHER_CROP"), + Material::Beetroots { .. } => f.write_str("BEETROOTS"), + Material::EndGateway { .. } => f.write_str("END_GATEWAY"), + Material::FrostedIce { .. } => f.write_str("FROSTED_ICE"), + Material::KelpPlant { .. } => f.write_str("KELP_PLANT"), + Material::DeadTubeCoralWallFan { .. } => f.write_str("DEAD_TUBE_CORAL_WALL_FAN"), + Material::DeadBrainCoralWallFan { .. } => f.write_str("DEAD_BRAIN_CORAL_WALL_FAN"), + Material::DeadBubbleCoralWallFan { .. } => f.write_str("DEAD_BUBBLE_CORAL_WALL_FAN"), + Material::DeadFireCoralWallFan { .. } => f.write_str("DEAD_FIRE_CORAL_WALL_FAN"), + Material::DeadHornCoralWallFan { .. } => f.write_str("DEAD_HORN_CORAL_WALL_FAN"), + Material::TubeCoralWallFan { .. } => f.write_str("TUBE_CORAL_WALL_FAN"), + Material::BrainCoralWallFan { .. } => f.write_str("BRAIN_CORAL_WALL_FAN"), + Material::BubbleCoralWallFan { .. } => f.write_str("BUBBLE_CORAL_WALL_FAN"), + Material::FireCoralWallFan { .. } => f.write_str("FIRE_CORAL_WALL_FAN"), + Material::HornCoralWallFan { .. } => f.write_str("HORN_CORAL_WALL_FAN"), + Material::BambooSapling { .. } => f.write_str("BAMBOO_SAPLING"), + Material::PottedBamboo { .. } => f.write_str("POTTED_BAMBOO"), + Material::VoidAir { .. } => f.write_str("VOID_AIR"), + Material::CaveAir { .. } => f.write_str("CAVE_AIR"), + Material::BubbleColumn { .. } => f.write_str("BUBBLE_COLUMN"), + Material::SweetBerryBush { .. } => f.write_str("SWEET_BERRY_BUSH"), + Material::WeepingVinesPlant { .. } => f.write_str("WEEPING_VINES_PLANT"), + Material::TwistingVinesPlant { .. } => f.write_str("TWISTING_VINES_PLANT"), + Material::CrimsonWallSign { .. } => f.write_str("CRIMSON_WALL_SIGN"), + Material::WarpedWallSign { .. } => f.write_str("WARPED_WALL_SIGN"), + Material::PottedCrimsonFungus { .. } => f.write_str("POTTED_CRIMSON_FUNGUS"), + Material::PottedWarpedFungus { .. } => f.write_str("POTTED_WARPED_FUNGUS"), + Material::PottedCrimsonRoots { .. } => f.write_str("POTTED_CRIMSON_ROOTS"), + Material::PottedWarpedRoots { .. } => f.write_str("POTTED_WARPED_ROOTS"), + Material::CandleCake { .. } => f.write_str("CANDLE_CAKE"), + Material::WhiteCandleCake { .. } => f.write_str("WHITE_CANDLE_CAKE"), + Material::OrangeCandleCake { .. } => f.write_str("ORANGE_CANDLE_CAKE"), + Material::MagentaCandleCake { .. } => f.write_str("MAGENTA_CANDLE_CAKE"), + Material::LightBlueCandleCake { .. } => f.write_str("LIGHT_BLUE_CANDLE_CAKE"), + Material::YellowCandleCake { .. } => f.write_str("YELLOW_CANDLE_CAKE"), + Material::LimeCandleCake { .. } => f.write_str("LIME_CANDLE_CAKE"), + Material::PinkCandleCake { .. } => f.write_str("PINK_CANDLE_CAKE"), + Material::GrayCandleCake { .. } => f.write_str("GRAY_CANDLE_CAKE"), + Material::LightGrayCandleCake { .. } => f.write_str("LIGHT_GRAY_CANDLE_CAKE"), + Material::CyanCandleCake { .. } => f.write_str("CYAN_CANDLE_CAKE"), + Material::PurpleCandleCake { .. } => f.write_str("PURPLE_CANDLE_CAKE"), + Material::BlueCandleCake { .. } => f.write_str("BLUE_CANDLE_CAKE"), + Material::BrownCandleCake { .. } => f.write_str("BROWN_CANDLE_CAKE"), + Material::GreenCandleCake { .. } => f.write_str("GREEN_CANDLE_CAKE"), + Material::RedCandleCake { .. } => f.write_str("RED_CANDLE_CAKE"), + Material::BlackCandleCake { .. } => f.write_str("BLACK_CANDLE_CAKE"), + Material::PowderSnow { .. } => f.write_str("POWDER_SNOW"), + Material::CaveVines { .. } => f.write_str("CAVE_VINES"), + Material::CaveVinesPlant { .. } => f.write_str("CAVE_VINES_PLANT"), + Material::BigDripleafStem { .. } => f.write_str("BIG_DRIPLEAF_STEM"), + Material::PottedAzaleaBush { .. } => f.write_str("POTTED_AZALEA_BUSH"), + Material::PottedFloweringAzaleaBush { .. } => { + f.write_str("POTTED_FLOWERING_AZALEA_BUSH") + } + Material::LegacyAir { .. } => f.write_str("LEGACY_AIR"), + Material::LegacyStone { .. } => f.write_str("LEGACY_STONE"), + Material::LegacyGrass { .. } => f.write_str("LEGACY_GRASS"), + Material::LegacyDirt { .. } => f.write_str("LEGACY_DIRT"), + Material::LegacyCobblestone { .. } => f.write_str("LEGACY_COBBLESTONE"), + Material::LegacyWood { .. } => f.write_str("LEGACY_WOOD"), + Material::LegacySapling { .. } => f.write_str("LEGACY_SAPLING"), + Material::LegacyBedrock { .. } => f.write_str("LEGACY_BEDROCK"), + Material::LegacyWater { .. } => f.write_str("LEGACY_WATER"), + Material::LegacyStationaryWater { .. } => f.write_str("LEGACY_STATIONARY_WATER"), + Material::LegacyLava { .. } => f.write_str("LEGACY_LAVA"), + Material::LegacyStationaryLava { .. } => f.write_str("LEGACY_STATIONARY_LAVA"), + Material::LegacySand { .. } => f.write_str("LEGACY_SAND"), + Material::LegacyGravel { .. } => f.write_str("LEGACY_GRAVEL"), + Material::LegacyGoldOre { .. } => f.write_str("LEGACY_GOLD_ORE"), + Material::LegacyIronOre { .. } => f.write_str("LEGACY_IRON_ORE"), + Material::LegacyCoalOre { .. } => f.write_str("LEGACY_COAL_ORE"), + Material::LegacyLog { .. } => f.write_str("LEGACY_LOG"), + Material::LegacyLeaves { .. } => f.write_str("LEGACY_LEAVES"), + Material::LegacySponge { .. } => f.write_str("LEGACY_SPONGE"), + Material::LegacyGlass { .. } => f.write_str("LEGACY_GLASS"), + Material::LegacyLapisOre { .. } => f.write_str("LEGACY_LAPIS_ORE"), + Material::LegacyLapisBlock { .. } => f.write_str("LEGACY_LAPIS_BLOCK"), + Material::LegacyDispenser { .. } => f.write_str("LEGACY_DISPENSER"), + Material::LegacySandstone { .. } => f.write_str("LEGACY_SANDSTONE"), + Material::LegacyNoteBlock { .. } => f.write_str("LEGACY_NOTE_BLOCK"), + Material::LegacyBedBlock { .. } => f.write_str("LEGACY_BED_BLOCK"), + Material::LegacyPoweredRail { .. } => f.write_str("LEGACY_POWERED_RAIL"), + Material::LegacyDetectorRail { .. } => f.write_str("LEGACY_DETECTOR_RAIL"), + Material::LegacyPistonStickyBase { .. } => f.write_str("LEGACY_PISTON_STICKY_BASE"), + Material::LegacyWeb { .. } => f.write_str("LEGACY_WEB"), + Material::LegacyLongGrass { .. } => f.write_str("LEGACY_LONG_GRASS"), + Material::LegacyDeadBush { .. } => f.write_str("LEGACY_DEAD_BUSH"), + Material::LegacyPistonBase { .. } => f.write_str("LEGACY_PISTON_BASE"), + Material::LegacyPistonExtension { .. } => f.write_str("LEGACY_PISTON_EXTENSION"), + Material::LegacyWool { .. } => f.write_str("LEGACY_WOOL"), + Material::LegacyPistonMovingPiece { .. } => f.write_str("LEGACY_PISTON_MOVING_PIECE"), + Material::LegacyYellowFlower { .. } => f.write_str("LEGACY_YELLOW_FLOWER"), + Material::LegacyRedRose { .. } => f.write_str("LEGACY_RED_ROSE"), + Material::LegacyBrownMushroom { .. } => f.write_str("LEGACY_BROWN_MUSHROOM"), + Material::LegacyRedMushroom { .. } => f.write_str("LEGACY_RED_MUSHROOM"), + Material::LegacyGoldBlock { .. } => f.write_str("LEGACY_GOLD_BLOCK"), + Material::LegacyIronBlock { .. } => f.write_str("LEGACY_IRON_BLOCK"), + Material::LegacyDoubleStep { .. } => f.write_str("LEGACY_DOUBLE_STEP"), + Material::LegacyStep { .. } => f.write_str("LEGACY_STEP"), + Material::LegacyBrick { .. } => f.write_str("LEGACY_BRICK"), + Material::LegacyTnt { .. } => f.write_str("LEGACY_TNT"), + Material::LegacyBookshelf { .. } => f.write_str("LEGACY_BOOKSHELF"), + Material::LegacyMossyCobblestone { .. } => f.write_str("LEGACY_MOSSY_COBBLESTONE"), + Material::LegacyObsidian { .. } => f.write_str("LEGACY_OBSIDIAN"), + Material::LegacyTorch { .. } => f.write_str("LEGACY_TORCH"), + Material::LegacyFire { .. } => f.write_str("LEGACY_FIRE"), + Material::LegacyMobSpawner { .. } => f.write_str("LEGACY_MOB_SPAWNER"), + Material::LegacyWoodStairs { .. } => f.write_str("LEGACY_WOOD_STAIRS"), + Material::LegacyChest { .. } => f.write_str("LEGACY_CHEST"), + Material::LegacyRedstoneWire { .. } => f.write_str("LEGACY_REDSTONE_WIRE"), + Material::LegacyDiamondOre { .. } => f.write_str("LEGACY_DIAMOND_ORE"), + Material::LegacyDiamondBlock { .. } => f.write_str("LEGACY_DIAMOND_BLOCK"), + Material::LegacyWorkbench { .. } => f.write_str("LEGACY_WORKBENCH"), + Material::LegacyCrops { .. } => f.write_str("LEGACY_CROPS"), + Material::LegacySoil { .. } => f.write_str("LEGACY_SOIL"), + Material::LegacyFurnace { .. } => f.write_str("LEGACY_FURNACE"), + Material::LegacyBurningFurnace { .. } => f.write_str("LEGACY_BURNING_FURNACE"), + Material::LegacySignPost { .. } => f.write_str("LEGACY_SIGN_POST"), + Material::LegacyWoodenDoor { .. } => f.write_str("LEGACY_WOODEN_DOOR"), + Material::LegacyLadder { .. } => f.write_str("LEGACY_LADDER"), + Material::LegacyRails { .. } => f.write_str("LEGACY_RAILS"), + Material::LegacyCobblestoneStairs { .. } => f.write_str("LEGACY_COBBLESTONE_STAIRS"), + Material::LegacyWallSign { .. } => f.write_str("LEGACY_WALL_SIGN"), + Material::LegacyLever { .. } => f.write_str("LEGACY_LEVER"), + Material::LegacyStonePlate { .. } => f.write_str("LEGACY_STONE_PLATE"), + Material::LegacyIronDoorBlock { .. } => f.write_str("LEGACY_IRON_DOOR_BLOCK"), + Material::LegacyWoodPlate { .. } => f.write_str("LEGACY_WOOD_PLATE"), + Material::LegacyRedstoneOre { .. } => f.write_str("LEGACY_REDSTONE_ORE"), + Material::LegacyGlowingRedstoneOre { .. } => f.write_str("LEGACY_GLOWING_REDSTONE_ORE"), + Material::LegacyRedstoneTorchOff { .. } => f.write_str("LEGACY_REDSTONE_TORCH_OFF"), + Material::LegacyRedstoneTorchOn { .. } => f.write_str("LEGACY_REDSTONE_TORCH_ON"), + Material::LegacyStoneButton { .. } => f.write_str("LEGACY_STONE_BUTTON"), + Material::LegacySnow { .. } => f.write_str("LEGACY_SNOW"), + Material::LegacyIce { .. } => f.write_str("LEGACY_ICE"), + Material::LegacySnowBlock { .. } => f.write_str("LEGACY_SNOW_BLOCK"), + Material::LegacyCactus { .. } => f.write_str("LEGACY_CACTUS"), + Material::LegacyClay { .. } => f.write_str("LEGACY_CLAY"), + Material::LegacySugarCaneBlock { .. } => f.write_str("LEGACY_SUGAR_CANE_BLOCK"), + Material::LegacyJukebox { .. } => f.write_str("LEGACY_JUKEBOX"), + Material::LegacyFence { .. } => f.write_str("LEGACY_FENCE"), + Material::LegacyPumpkin { .. } => f.write_str("LEGACY_PUMPKIN"), + Material::LegacyNetherrack { .. } => f.write_str("LEGACY_NETHERRACK"), + Material::LegacySoulSand { .. } => f.write_str("LEGACY_SOUL_SAND"), + Material::LegacyGlowstone { .. } => f.write_str("LEGACY_GLOWSTONE"), + Material::LegacyPortal { .. } => f.write_str("LEGACY_PORTAL"), + Material::LegacyJackOLantern { .. } => f.write_str("LEGACY_JACK_O_LANTERN"), + Material::LegacyCakeBlock { .. } => f.write_str("LEGACY_CAKE_BLOCK"), + Material::LegacyDiodeBlockOff { .. } => f.write_str("LEGACY_DIODE_BLOCK_OFF"), + Material::LegacyDiodeBlockOn { .. } => f.write_str("LEGACY_DIODE_BLOCK_ON"), + Material::LegacyStainedGlass { .. } => f.write_str("LEGACY_STAINED_GLASS"), + Material::LegacyTrapDoor { .. } => f.write_str("LEGACY_TRAP_DOOR"), + Material::LegacyMonsterEggs { .. } => f.write_str("LEGACY_MONSTER_EGGS"), + Material::LegacySmoothBrick { .. } => f.write_str("LEGACY_SMOOTH_BRICK"), + Material::LegacyHugeMushroom1 { .. } => f.write_str("LEGACY_HUGE_MUSHROOM_1"), + Material::LegacyHugeMushroom2 { .. } => f.write_str("LEGACY_HUGE_MUSHROOM_2"), + Material::LegacyIronFence { .. } => f.write_str("LEGACY_IRON_FENCE"), + Material::LegacyThinGlass { .. } => f.write_str("LEGACY_THIN_GLASS"), + Material::LegacyMelonBlock { .. } => f.write_str("LEGACY_MELON_BLOCK"), + Material::LegacyPumpkinStem { .. } => f.write_str("LEGACY_PUMPKIN_STEM"), + Material::LegacyMelonStem { .. } => f.write_str("LEGACY_MELON_STEM"), + Material::LegacyVine { .. } => f.write_str("LEGACY_VINE"), + Material::LegacyFenceGate { .. } => f.write_str("LEGACY_FENCE_GATE"), + Material::LegacyBrickStairs { .. } => f.write_str("LEGACY_BRICK_STAIRS"), + Material::LegacySmoothStairs { .. } => f.write_str("LEGACY_SMOOTH_STAIRS"), + Material::LegacyMycel { .. } => f.write_str("LEGACY_MYCEL"), + Material::LegacyWaterLily { .. } => f.write_str("LEGACY_WATER_LILY"), + Material::LegacyNetherBrick { .. } => f.write_str("LEGACY_NETHER_BRICK"), + Material::LegacyNetherFence { .. } => f.write_str("LEGACY_NETHER_FENCE"), + Material::LegacyNetherBrickStairs { .. } => f.write_str("LEGACY_NETHER_BRICK_STAIRS"), + Material::LegacyNetherWarts { .. } => f.write_str("LEGACY_NETHER_WARTS"), + Material::LegacyEnchantmentTable { .. } => f.write_str("LEGACY_ENCHANTMENT_TABLE"), + Material::LegacyBrewingStand { .. } => f.write_str("LEGACY_BREWING_STAND"), + Material::LegacyCauldron { .. } => f.write_str("LEGACY_CAULDRON"), + Material::LegacyEnderPortal { .. } => f.write_str("LEGACY_ENDER_PORTAL"), + Material::LegacyEnderPortalFrame { .. } => f.write_str("LEGACY_ENDER_PORTAL_FRAME"), + Material::LegacyEnderStone { .. } => f.write_str("LEGACY_ENDER_STONE"), + Material::LegacyDragonEgg { .. } => f.write_str("LEGACY_DRAGON_EGG"), + Material::LegacyRedstoneLampOff { .. } => f.write_str("LEGACY_REDSTONE_LAMP_OFF"), + Material::LegacyRedstoneLampOn { .. } => f.write_str("LEGACY_REDSTONE_LAMP_ON"), + Material::LegacyWoodDoubleStep { .. } => f.write_str("LEGACY_WOOD_DOUBLE_STEP"), + Material::LegacyWoodStep { .. } => f.write_str("LEGACY_WOOD_STEP"), + Material::LegacyCocoa { .. } => f.write_str("LEGACY_COCOA"), + Material::LegacySandstoneStairs { .. } => f.write_str("LEGACY_SANDSTONE_STAIRS"), + Material::LegacyEmeraldOre { .. } => f.write_str("LEGACY_EMERALD_ORE"), + Material::LegacyEnderChest { .. } => f.write_str("LEGACY_ENDER_CHEST"), + Material::LegacyTripwireHook { .. } => f.write_str("LEGACY_TRIPWIRE_HOOK"), + Material::LegacyTripwire { .. } => f.write_str("LEGACY_TRIPWIRE"), + Material::LegacyEmeraldBlock { .. } => f.write_str("LEGACY_EMERALD_BLOCK"), + Material::LegacySpruceWoodStairs { .. } => f.write_str("LEGACY_SPRUCE_WOOD_STAIRS"), + Material::LegacyBirchWoodStairs { .. } => f.write_str("LEGACY_BIRCH_WOOD_STAIRS"), + Material::LegacyJungleWoodStairs { .. } => f.write_str("LEGACY_JUNGLE_WOOD_STAIRS"), + Material::LegacyCommand { .. } => f.write_str("LEGACY_COMMAND"), + Material::LegacyBeacon { .. } => f.write_str("LEGACY_BEACON"), + Material::LegacyCobbleWall { .. } => f.write_str("LEGACY_COBBLE_WALL"), + Material::LegacyFlowerPot { .. } => f.write_str("LEGACY_FLOWER_POT"), + Material::LegacyCarrot { .. } => f.write_str("LEGACY_CARROT"), + Material::LegacyPotato { .. } => f.write_str("LEGACY_POTATO"), + Material::LegacyWoodButton { .. } => f.write_str("LEGACY_WOOD_BUTTON"), + Material::LegacySkull { .. } => f.write_str("LEGACY_SKULL"), + Material::LegacyAnvil { .. } => f.write_str("LEGACY_ANVIL"), + Material::LegacyTrappedChest { .. } => f.write_str("LEGACY_TRAPPED_CHEST"), + Material::LegacyGoldPlate { .. } => f.write_str("LEGACY_GOLD_PLATE"), + Material::LegacyIronPlate { .. } => f.write_str("LEGACY_IRON_PLATE"), + Material::LegacyRedstoneComparatorOff { .. } => { + f.write_str("LEGACY_REDSTONE_COMPARATOR_OFF") + } + Material::LegacyRedstoneComparatorOn { .. } => { + f.write_str("LEGACY_REDSTONE_COMPARATOR_ON") + } + Material::LegacyDaylightDetector { .. } => f.write_str("LEGACY_DAYLIGHT_DETECTOR"), + Material::LegacyRedstoneBlock { .. } => f.write_str("LEGACY_REDSTONE_BLOCK"), + Material::LegacyQuartzOre { .. } => f.write_str("LEGACY_QUARTZ_ORE"), + Material::LegacyHopper { .. } => f.write_str("LEGACY_HOPPER"), + Material::LegacyQuartzBlock { .. } => f.write_str("LEGACY_QUARTZ_BLOCK"), + Material::LegacyQuartzStairs { .. } => f.write_str("LEGACY_QUARTZ_STAIRS"), + Material::LegacyActivatorRail { .. } => f.write_str("LEGACY_ACTIVATOR_RAIL"), + Material::LegacyDropper { .. } => f.write_str("LEGACY_DROPPER"), + Material::LegacyStainedClay { .. } => f.write_str("LEGACY_STAINED_CLAY"), + Material::LegacyStainedGlassPane { .. } => f.write_str("LEGACY_STAINED_GLASS_PANE"), + Material::LegacyLeaves2 { .. } => f.write_str("LEGACY_LEAVES_2"), + Material::LegacyLog2 { .. } => f.write_str("LEGACY_LOG_2"), + Material::LegacyAcaciaStairs { .. } => f.write_str("LEGACY_ACACIA_STAIRS"), + Material::LegacyDarkOakStairs { .. } => f.write_str("LEGACY_DARK_OAK_STAIRS"), + Material::LegacySlimeBlock { .. } => f.write_str("LEGACY_SLIME_BLOCK"), + Material::LegacyBarrier { .. } => f.write_str("LEGACY_BARRIER"), + Material::LegacyIronTrapdoor { .. } => f.write_str("LEGACY_IRON_TRAPDOOR"), + Material::LegacyPrismarine { .. } => f.write_str("LEGACY_PRISMARINE"), + Material::LegacySeaLantern { .. } => f.write_str("LEGACY_SEA_LANTERN"), + Material::LegacyHayBlock { .. } => f.write_str("LEGACY_HAY_BLOCK"), + Material::LegacyCarpet { .. } => f.write_str("LEGACY_CARPET"), + Material::LegacyHardClay { .. } => f.write_str("LEGACY_HARD_CLAY"), + Material::LegacyCoalBlock { .. } => f.write_str("LEGACY_COAL_BLOCK"), + Material::LegacyPackedIce { .. } => f.write_str("LEGACY_PACKED_ICE"), + Material::LegacyDoublePlant { .. } => f.write_str("LEGACY_DOUBLE_PLANT"), + Material::LegacyStandingBanner { .. } => f.write_str("LEGACY_STANDING_BANNER"), + Material::LegacyWallBanner { .. } => f.write_str("LEGACY_WALL_BANNER"), + Material::LegacyDaylightDetectorInverted { .. } => { + f.write_str("LEGACY_DAYLIGHT_DETECTOR_INVERTED") + } + Material::LegacyRedSandstone { .. } => f.write_str("LEGACY_RED_SANDSTONE"), + Material::LegacyRedSandstoneStairs { .. } => f.write_str("LEGACY_RED_SANDSTONE_STAIRS"), + Material::LegacyDoubleStoneSlab2 { .. } => f.write_str("LEGACY_DOUBLE_STONE_SLAB2"), + Material::LegacyStoneSlab2 { .. } => f.write_str("LEGACY_STONE_SLAB2"), + Material::LegacySpruceFenceGate { .. } => f.write_str("LEGACY_SPRUCE_FENCE_GATE"), + Material::LegacyBirchFenceGate { .. } => f.write_str("LEGACY_BIRCH_FENCE_GATE"), + Material::LegacyJungleFenceGate { .. } => f.write_str("LEGACY_JUNGLE_FENCE_GATE"), + Material::LegacyDarkOakFenceGate { .. } => f.write_str("LEGACY_DARK_OAK_FENCE_GATE"), + Material::LegacyAcaciaFenceGate { .. } => f.write_str("LEGACY_ACACIA_FENCE_GATE"), + Material::LegacySpruceFence { .. } => f.write_str("LEGACY_SPRUCE_FENCE"), + Material::LegacyBirchFence { .. } => f.write_str("LEGACY_BIRCH_FENCE"), + Material::LegacyJungleFence { .. } => f.write_str("LEGACY_JUNGLE_FENCE"), + Material::LegacyDarkOakFence { .. } => f.write_str("LEGACY_DARK_OAK_FENCE"), + Material::LegacyAcaciaFence { .. } => f.write_str("LEGACY_ACACIA_FENCE"), + Material::LegacySpruceDoor { .. } => f.write_str("LEGACY_SPRUCE_DOOR"), + Material::LegacyBirchDoor { .. } => f.write_str("LEGACY_BIRCH_DOOR"), + Material::LegacyJungleDoor { .. } => f.write_str("LEGACY_JUNGLE_DOOR"), + Material::LegacyAcaciaDoor { .. } => f.write_str("LEGACY_ACACIA_DOOR"), + Material::LegacyDarkOakDoor { .. } => f.write_str("LEGACY_DARK_OAK_DOOR"), + Material::LegacyEndRod { .. } => f.write_str("LEGACY_END_ROD"), + Material::LegacyChorusPlant { .. } => f.write_str("LEGACY_CHORUS_PLANT"), + Material::LegacyChorusFlower { .. } => f.write_str("LEGACY_CHORUS_FLOWER"), + Material::LegacyPurpurBlock { .. } => f.write_str("LEGACY_PURPUR_BLOCK"), + Material::LegacyPurpurPillar { .. } => f.write_str("LEGACY_PURPUR_PILLAR"), + Material::LegacyPurpurStairs { .. } => f.write_str("LEGACY_PURPUR_STAIRS"), + Material::LegacyPurpurDoubleSlab { .. } => f.write_str("LEGACY_PURPUR_DOUBLE_SLAB"), + Material::LegacyPurpurSlab { .. } => f.write_str("LEGACY_PURPUR_SLAB"), + Material::LegacyEndBricks { .. } => f.write_str("LEGACY_END_BRICKS"), + Material::LegacyBeetrootBlock { .. } => f.write_str("LEGACY_BEETROOT_BLOCK"), + Material::LegacyGrassPath { .. } => f.write_str("LEGACY_GRASS_PATH"), + Material::LegacyEndGateway { .. } => f.write_str("LEGACY_END_GATEWAY"), + Material::LegacyCommandRepeating { .. } => f.write_str("LEGACY_COMMAND_REPEATING"), + Material::LegacyCommandChain { .. } => f.write_str("LEGACY_COMMAND_CHAIN"), + Material::LegacyFrostedIce { .. } => f.write_str("LEGACY_FROSTED_ICE"), + Material::LegacyMagma { .. } => f.write_str("LEGACY_MAGMA"), + Material::LegacyNetherWartBlock { .. } => f.write_str("LEGACY_NETHER_WART_BLOCK"), + Material::LegacyRedNetherBrick { .. } => f.write_str("LEGACY_RED_NETHER_BRICK"), + Material::LegacyBoneBlock { .. } => f.write_str("LEGACY_BONE_BLOCK"), + Material::LegacyStructureVoid { .. } => f.write_str("LEGACY_STRUCTURE_VOID"), + Material::LegacyObserver { .. } => f.write_str("LEGACY_OBSERVER"), + Material::LegacyWhiteShulkerBox { .. } => f.write_str("LEGACY_WHITE_SHULKER_BOX"), + Material::LegacyOrangeShulkerBox { .. } => f.write_str("LEGACY_ORANGE_SHULKER_BOX"), + Material::LegacyMagentaShulkerBox { .. } => f.write_str("LEGACY_MAGENTA_SHULKER_BOX"), + Material::LegacyLightBlueShulkerBox { .. } => { + f.write_str("LEGACY_LIGHT_BLUE_SHULKER_BOX") + } + Material::LegacyYellowShulkerBox { .. } => f.write_str("LEGACY_YELLOW_SHULKER_BOX"), + Material::LegacyLimeShulkerBox { .. } => f.write_str("LEGACY_LIME_SHULKER_BOX"), + Material::LegacyPinkShulkerBox { .. } => f.write_str("LEGACY_PINK_SHULKER_BOX"), + Material::LegacyGrayShulkerBox { .. } => f.write_str("LEGACY_GRAY_SHULKER_BOX"), + Material::LegacySilverShulkerBox { .. } => f.write_str("LEGACY_SILVER_SHULKER_BOX"), + Material::LegacyCyanShulkerBox { .. } => f.write_str("LEGACY_CYAN_SHULKER_BOX"), + Material::LegacyPurpleShulkerBox { .. } => f.write_str("LEGACY_PURPLE_SHULKER_BOX"), + Material::LegacyBlueShulkerBox { .. } => f.write_str("LEGACY_BLUE_SHULKER_BOX"), + Material::LegacyBrownShulkerBox { .. } => f.write_str("LEGACY_BROWN_SHULKER_BOX"), + Material::LegacyGreenShulkerBox { .. } => f.write_str("LEGACY_GREEN_SHULKER_BOX"), + Material::LegacyRedShulkerBox { .. } => f.write_str("LEGACY_RED_SHULKER_BOX"), + Material::LegacyBlackShulkerBox { .. } => f.write_str("LEGACY_BLACK_SHULKER_BOX"), + Material::LegacyWhiteGlazedTerracotta { .. } => { + f.write_str("LEGACY_WHITE_GLAZED_TERRACOTTA") + } + Material::LegacyOrangeGlazedTerracotta { .. } => { + f.write_str("LEGACY_ORANGE_GLAZED_TERRACOTTA") + } + Material::LegacyMagentaGlazedTerracotta { .. } => { + f.write_str("LEGACY_MAGENTA_GLAZED_TERRACOTTA") + } + Material::LegacyLightBlueGlazedTerracotta { .. } => { + f.write_str("LEGACY_LIGHT_BLUE_GLAZED_TERRACOTTA") + } + Material::LegacyYellowGlazedTerracotta { .. } => { + f.write_str("LEGACY_YELLOW_GLAZED_TERRACOTTA") + } + Material::LegacyLimeGlazedTerracotta { .. } => { + f.write_str("LEGACY_LIME_GLAZED_TERRACOTTA") + } + Material::LegacyPinkGlazedTerracotta { .. } => { + f.write_str("LEGACY_PINK_GLAZED_TERRACOTTA") + } + Material::LegacyGrayGlazedTerracotta { .. } => { + f.write_str("LEGACY_GRAY_GLAZED_TERRACOTTA") + } + Material::LegacySilverGlazedTerracotta { .. } => { + f.write_str("LEGACY_SILVER_GLAZED_TERRACOTTA") + } + Material::LegacyCyanGlazedTerracotta { .. } => { + f.write_str("LEGACY_CYAN_GLAZED_TERRACOTTA") + } + Material::LegacyPurpleGlazedTerracotta { .. } => { + f.write_str("LEGACY_PURPLE_GLAZED_TERRACOTTA") + } + Material::LegacyBlueGlazedTerracotta { .. } => { + f.write_str("LEGACY_BLUE_GLAZED_TERRACOTTA") + } + Material::LegacyBrownGlazedTerracotta { .. } => { + f.write_str("LEGACY_BROWN_GLAZED_TERRACOTTA") + } + Material::LegacyGreenGlazedTerracotta { .. } => { + f.write_str("LEGACY_GREEN_GLAZED_TERRACOTTA") + } + Material::LegacyRedGlazedTerracotta { .. } => { + f.write_str("LEGACY_RED_GLAZED_TERRACOTTA") + } + Material::LegacyBlackGlazedTerracotta { .. } => { + f.write_str("LEGACY_BLACK_GLAZED_TERRACOTTA") + } + Material::LegacyConcrete { .. } => f.write_str("LEGACY_CONCRETE"), + Material::LegacyConcretePowder { .. } => f.write_str("LEGACY_CONCRETE_POWDER"), + Material::LegacyStructureBlock { .. } => f.write_str("LEGACY_STRUCTURE_BLOCK"), + Material::LegacyIronSpade { .. } => f.write_str("LEGACY_IRON_SPADE"), + Material::LegacyIronPickaxe { .. } => f.write_str("LEGACY_IRON_PICKAXE"), + Material::LegacyIronAxe { .. } => f.write_str("LEGACY_IRON_AXE"), + Material::LegacyFlintAndSteel { .. } => f.write_str("LEGACY_FLINT_AND_STEEL"), + Material::LegacyApple { .. } => f.write_str("LEGACY_APPLE"), + Material::LegacyBow { .. } => f.write_str("LEGACY_BOW"), + Material::LegacyArrow { .. } => f.write_str("LEGACY_ARROW"), + Material::LegacyCoal { .. } => f.write_str("LEGACY_COAL"), + Material::LegacyDiamond { .. } => f.write_str("LEGACY_DIAMOND"), + Material::LegacyIronIngot { .. } => f.write_str("LEGACY_IRON_INGOT"), + Material::LegacyGoldIngot { .. } => f.write_str("LEGACY_GOLD_INGOT"), + Material::LegacyIronSword { .. } => f.write_str("LEGACY_IRON_SWORD"), + Material::LegacyWoodSword { .. } => f.write_str("LEGACY_WOOD_SWORD"), + Material::LegacyWoodSpade { .. } => f.write_str("LEGACY_WOOD_SPADE"), + Material::LegacyWoodPickaxe { .. } => f.write_str("LEGACY_WOOD_PICKAXE"), + Material::LegacyWoodAxe { .. } => f.write_str("LEGACY_WOOD_AXE"), + Material::LegacyStoneSword { .. } => f.write_str("LEGACY_STONE_SWORD"), + Material::LegacyStoneSpade { .. } => f.write_str("LEGACY_STONE_SPADE"), + Material::LegacyStonePickaxe { .. } => f.write_str("LEGACY_STONE_PICKAXE"), + Material::LegacyStoneAxe { .. } => f.write_str("LEGACY_STONE_AXE"), + Material::LegacyDiamondSword { .. } => f.write_str("LEGACY_DIAMOND_SWORD"), + Material::LegacyDiamondSpade { .. } => f.write_str("LEGACY_DIAMOND_SPADE"), + Material::LegacyDiamondPickaxe { .. } => f.write_str("LEGACY_DIAMOND_PICKAXE"), + Material::LegacyDiamondAxe { .. } => f.write_str("LEGACY_DIAMOND_AXE"), + Material::LegacyStick { .. } => f.write_str("LEGACY_STICK"), + Material::LegacyBowl { .. } => f.write_str("LEGACY_BOWL"), + Material::LegacyMushroomSoup { .. } => f.write_str("LEGACY_MUSHROOM_SOUP"), + Material::LegacyGoldSword { .. } => f.write_str("LEGACY_GOLD_SWORD"), + Material::LegacyGoldSpade { .. } => f.write_str("LEGACY_GOLD_SPADE"), + Material::LegacyGoldPickaxe { .. } => f.write_str("LEGACY_GOLD_PICKAXE"), + Material::LegacyGoldAxe { .. } => f.write_str("LEGACY_GOLD_AXE"), + Material::LegacyString { .. } => f.write_str("LEGACY_STRING"), + Material::LegacyFeather { .. } => f.write_str("LEGACY_FEATHER"), + Material::LegacySulphur { .. } => f.write_str("LEGACY_SULPHUR"), + Material::LegacyWoodHoe { .. } => f.write_str("LEGACY_WOOD_HOE"), + Material::LegacyStoneHoe { .. } => f.write_str("LEGACY_STONE_HOE"), + Material::LegacyIronHoe { .. } => f.write_str("LEGACY_IRON_HOE"), + Material::LegacyDiamondHoe { .. } => f.write_str("LEGACY_DIAMOND_HOE"), + Material::LegacyGoldHoe { .. } => f.write_str("LEGACY_GOLD_HOE"), + Material::LegacySeeds { .. } => f.write_str("LEGACY_SEEDS"), + Material::LegacyWheat { .. } => f.write_str("LEGACY_WHEAT"), + Material::LegacyBread { .. } => f.write_str("LEGACY_BREAD"), + Material::LegacyLeatherHelmet { .. } => f.write_str("LEGACY_LEATHER_HELMET"), + Material::LegacyLeatherChestplate { .. } => f.write_str("LEGACY_LEATHER_CHESTPLATE"), + Material::LegacyLeatherLeggings { .. } => f.write_str("LEGACY_LEATHER_LEGGINGS"), + Material::LegacyLeatherBoots { .. } => f.write_str("LEGACY_LEATHER_BOOTS"), + Material::LegacyChainmailHelmet { .. } => f.write_str("LEGACY_CHAINMAIL_HELMET"), + Material::LegacyChainmailChestplate { .. } => { + f.write_str("LEGACY_CHAINMAIL_CHESTPLATE") + } + Material::LegacyChainmailLeggings { .. } => f.write_str("LEGACY_CHAINMAIL_LEGGINGS"), + Material::LegacyChainmailBoots { .. } => f.write_str("LEGACY_CHAINMAIL_BOOTS"), + Material::LegacyIronHelmet { .. } => f.write_str("LEGACY_IRON_HELMET"), + Material::LegacyIronChestplate { .. } => f.write_str("LEGACY_IRON_CHESTPLATE"), + Material::LegacyIronLeggings { .. } => f.write_str("LEGACY_IRON_LEGGINGS"), + Material::LegacyIronBoots { .. } => f.write_str("LEGACY_IRON_BOOTS"), + Material::LegacyDiamondHelmet { .. } => f.write_str("LEGACY_DIAMOND_HELMET"), + Material::LegacyDiamondChestplate { .. } => f.write_str("LEGACY_DIAMOND_CHESTPLATE"), + Material::LegacyDiamondLeggings { .. } => f.write_str("LEGACY_DIAMOND_LEGGINGS"), + Material::LegacyDiamondBoots { .. } => f.write_str("LEGACY_DIAMOND_BOOTS"), + Material::LegacyGoldHelmet { .. } => f.write_str("LEGACY_GOLD_HELMET"), + Material::LegacyGoldChestplate { .. } => f.write_str("LEGACY_GOLD_CHESTPLATE"), + Material::LegacyGoldLeggings { .. } => f.write_str("LEGACY_GOLD_LEGGINGS"), + Material::LegacyGoldBoots { .. } => f.write_str("LEGACY_GOLD_BOOTS"), + Material::LegacyFlint { .. } => f.write_str("LEGACY_FLINT"), + Material::LegacyPork { .. } => f.write_str("LEGACY_PORK"), + Material::LegacyGrilledPork { .. } => f.write_str("LEGACY_GRILLED_PORK"), + Material::LegacyPainting { .. } => f.write_str("LEGACY_PAINTING"), + Material::LegacyGoldenApple { .. } => f.write_str("LEGACY_GOLDEN_APPLE"), + Material::LegacySign { .. } => f.write_str("LEGACY_SIGN"), + Material::LegacyWoodDoor { .. } => f.write_str("LEGACY_WOOD_DOOR"), + Material::LegacyBucket { .. } => f.write_str("LEGACY_BUCKET"), + Material::LegacyWaterBucket { .. } => f.write_str("LEGACY_WATER_BUCKET"), + Material::LegacyLavaBucket { .. } => f.write_str("LEGACY_LAVA_BUCKET"), + Material::LegacyMinecart { .. } => f.write_str("LEGACY_MINECART"), + Material::LegacySaddle { .. } => f.write_str("LEGACY_SADDLE"), + Material::LegacyIronDoor { .. } => f.write_str("LEGACY_IRON_DOOR"), + Material::LegacyRedstone { .. } => f.write_str("LEGACY_REDSTONE"), + Material::LegacySnowBall { .. } => f.write_str("LEGACY_SNOW_BALL"), + Material::LegacyBoat { .. } => f.write_str("LEGACY_BOAT"), + Material::LegacyLeather { .. } => f.write_str("LEGACY_LEATHER"), + Material::LegacyMilkBucket { .. } => f.write_str("LEGACY_MILK_BUCKET"), + Material::LegacyClayBrick { .. } => f.write_str("LEGACY_CLAY_BRICK"), + Material::LegacyClayBall { .. } => f.write_str("LEGACY_CLAY_BALL"), + Material::LegacySugarCane { .. } => f.write_str("LEGACY_SUGAR_CANE"), + Material::LegacyPaper { .. } => f.write_str("LEGACY_PAPER"), + Material::LegacyBook { .. } => f.write_str("LEGACY_BOOK"), + Material::LegacySlimeBall { .. } => f.write_str("LEGACY_SLIME_BALL"), + Material::LegacyStorageMinecart { .. } => f.write_str("LEGACY_STORAGE_MINECART"), + Material::LegacyPoweredMinecart { .. } => f.write_str("LEGACY_POWERED_MINECART"), + Material::LegacyEgg { .. } => f.write_str("LEGACY_EGG"), + Material::LegacyCompass { .. } => f.write_str("LEGACY_COMPASS"), + Material::LegacyFishingRod { .. } => f.write_str("LEGACY_FISHING_ROD"), + Material::LegacyWatch { .. } => f.write_str("LEGACY_WATCH"), + Material::LegacyGlowstoneDust { .. } => f.write_str("LEGACY_GLOWSTONE_DUST"), + Material::LegacyRawFish { .. } => f.write_str("LEGACY_RAW_FISH"), + Material::LegacyCookedFish { .. } => f.write_str("LEGACY_COOKED_FISH"), + Material::LegacyInkSack { .. } => f.write_str("LEGACY_INK_SACK"), + Material::LegacyBone { .. } => f.write_str("LEGACY_BONE"), + Material::LegacySugar { .. } => f.write_str("LEGACY_SUGAR"), + Material::LegacyCake { .. } => f.write_str("LEGACY_CAKE"), + Material::LegacyBed { .. } => f.write_str("LEGACY_BED"), + Material::LegacyDiode { .. } => f.write_str("LEGACY_DIODE"), + Material::LegacyCookie { .. } => f.write_str("LEGACY_COOKIE"), + Material::LegacyMap { .. } => f.write_str("LEGACY_MAP"), + Material::LegacyShears { .. } => f.write_str("LEGACY_SHEARS"), + Material::LegacyMelon { .. } => f.write_str("LEGACY_MELON"), + Material::LegacyPumpkinSeeds { .. } => f.write_str("LEGACY_PUMPKIN_SEEDS"), + Material::LegacyMelonSeeds { .. } => f.write_str("LEGACY_MELON_SEEDS"), + Material::LegacyRawBeef { .. } => f.write_str("LEGACY_RAW_BEEF"), + Material::LegacyCookedBeef { .. } => f.write_str("LEGACY_COOKED_BEEF"), + Material::LegacyRawChicken { .. } => f.write_str("LEGACY_RAW_CHICKEN"), + Material::LegacyCookedChicken { .. } => f.write_str("LEGACY_COOKED_CHICKEN"), + Material::LegacyRottenFlesh { .. } => f.write_str("LEGACY_ROTTEN_FLESH"), + Material::LegacyEnderPearl { .. } => f.write_str("LEGACY_ENDER_PEARL"), + Material::LegacyBlazeRod { .. } => f.write_str("LEGACY_BLAZE_ROD"), + Material::LegacyGhastTear { .. } => f.write_str("LEGACY_GHAST_TEAR"), + Material::LegacyGoldNugget { .. } => f.write_str("LEGACY_GOLD_NUGGET"), + Material::LegacyNetherStalk { .. } => f.write_str("LEGACY_NETHER_STALK"), + Material::LegacyPotion { .. } => f.write_str("LEGACY_POTION"), + Material::LegacyGlassBottle { .. } => f.write_str("LEGACY_GLASS_BOTTLE"), + Material::LegacySpiderEye { .. } => f.write_str("LEGACY_SPIDER_EYE"), + Material::LegacyFermentedSpiderEye { .. } => f.write_str("LEGACY_FERMENTED_SPIDER_EYE"), + Material::LegacyBlazePowder { .. } => f.write_str("LEGACY_BLAZE_POWDER"), + Material::LegacyMagmaCream { .. } => f.write_str("LEGACY_MAGMA_CREAM"), + Material::LegacyBrewingStandItem { .. } => f.write_str("LEGACY_BREWING_STAND_ITEM"), + Material::LegacyCauldronItem { .. } => f.write_str("LEGACY_CAULDRON_ITEM"), + Material::LegacyEyeOfEnder { .. } => f.write_str("LEGACY_EYE_OF_ENDER"), + Material::LegacySpeckledMelon { .. } => f.write_str("LEGACY_SPECKLED_MELON"), + Material::LegacyMonsterEgg { .. } => f.write_str("LEGACY_MONSTER_EGG"), + Material::LegacyExpBottle { .. } => f.write_str("LEGACY_EXP_BOTTLE"), + Material::LegacyFireball { .. } => f.write_str("LEGACY_FIREBALL"), + Material::LegacyBookAndQuill { .. } => f.write_str("LEGACY_BOOK_AND_QUILL"), + Material::LegacyWrittenBook { .. } => f.write_str("LEGACY_WRITTEN_BOOK"), + Material::LegacyEmerald { .. } => f.write_str("LEGACY_EMERALD"), + Material::LegacyItemFrame { .. } => f.write_str("LEGACY_ITEM_FRAME"), + Material::LegacyFlowerPotItem { .. } => f.write_str("LEGACY_FLOWER_POT_ITEM"), + Material::LegacyCarrotItem { .. } => f.write_str("LEGACY_CARROT_ITEM"), + Material::LegacyPotatoItem { .. } => f.write_str("LEGACY_POTATO_ITEM"), + Material::LegacyBakedPotato { .. } => f.write_str("LEGACY_BAKED_POTATO"), + Material::LegacyPoisonousPotato { .. } => f.write_str("LEGACY_POISONOUS_POTATO"), + Material::LegacyEmptyMap { .. } => f.write_str("LEGACY_EMPTY_MAP"), + Material::LegacyGoldenCarrot { .. } => f.write_str("LEGACY_GOLDEN_CARROT"), + Material::LegacySkullItem { .. } => f.write_str("LEGACY_SKULL_ITEM"), + Material::LegacyCarrotStick { .. } => f.write_str("LEGACY_CARROT_STICK"), + Material::LegacyNetherStar { .. } => f.write_str("LEGACY_NETHER_STAR"), + Material::LegacyPumpkinPie { .. } => f.write_str("LEGACY_PUMPKIN_PIE"), + Material::LegacyFirework { .. } => f.write_str("LEGACY_FIREWORK"), + Material::LegacyFireworkCharge { .. } => f.write_str("LEGACY_FIREWORK_CHARGE"), + Material::LegacyEnchantedBook { .. } => f.write_str("LEGACY_ENCHANTED_BOOK"), + Material::LegacyRedstoneComparator { .. } => f.write_str("LEGACY_REDSTONE_COMPARATOR"), + Material::LegacyNetherBrickItem { .. } => f.write_str("LEGACY_NETHER_BRICK_ITEM"), + Material::LegacyQuartz { .. } => f.write_str("LEGACY_QUARTZ"), + Material::LegacyExplosiveMinecart { .. } => f.write_str("LEGACY_EXPLOSIVE_MINECART"), + Material::LegacyHopperMinecart { .. } => f.write_str("LEGACY_HOPPER_MINECART"), + Material::LegacyPrismarineShard { .. } => f.write_str("LEGACY_PRISMARINE_SHARD"), + Material::LegacyPrismarineCrystals { .. } => f.write_str("LEGACY_PRISMARINE_CRYSTALS"), + Material::LegacyRabbit { .. } => f.write_str("LEGACY_RABBIT"), + Material::LegacyCookedRabbit { .. } => f.write_str("LEGACY_COOKED_RABBIT"), + Material::LegacyRabbitStew { .. } => f.write_str("LEGACY_RABBIT_STEW"), + Material::LegacyRabbitFoot { .. } => f.write_str("LEGACY_RABBIT_FOOT"), + Material::LegacyRabbitHide { .. } => f.write_str("LEGACY_RABBIT_HIDE"), + Material::LegacyArmorStand { .. } => f.write_str("LEGACY_ARMOR_STAND"), + Material::LegacyIronBarding { .. } => f.write_str("LEGACY_IRON_BARDING"), + Material::LegacyGoldBarding { .. } => f.write_str("LEGACY_GOLD_BARDING"), + Material::LegacyDiamondBarding { .. } => f.write_str("LEGACY_DIAMOND_BARDING"), + Material::LegacyLeash { .. } => f.write_str("LEGACY_LEASH"), + Material::LegacyNameTag { .. } => f.write_str("LEGACY_NAME_TAG"), + Material::LegacyCommandMinecart { .. } => f.write_str("LEGACY_COMMAND_MINECART"), + Material::LegacyMutton { .. } => f.write_str("LEGACY_MUTTON"), + Material::LegacyCookedMutton { .. } => f.write_str("LEGACY_COOKED_MUTTON"), + Material::LegacyBanner { .. } => f.write_str("LEGACY_BANNER"), + Material::LegacyEndCrystal { .. } => f.write_str("LEGACY_END_CRYSTAL"), + Material::LegacySpruceDoorItem { .. } => f.write_str("LEGACY_SPRUCE_DOOR_ITEM"), + Material::LegacyBirchDoorItem { .. } => f.write_str("LEGACY_BIRCH_DOOR_ITEM"), + Material::LegacyJungleDoorItem { .. } => f.write_str("LEGACY_JUNGLE_DOOR_ITEM"), + Material::LegacyAcaciaDoorItem { .. } => f.write_str("LEGACY_ACACIA_DOOR_ITEM"), + Material::LegacyDarkOakDoorItem { .. } => f.write_str("LEGACY_DARK_OAK_DOOR_ITEM"), + Material::LegacyChorusFruit { .. } => f.write_str("LEGACY_CHORUS_FRUIT"), + Material::LegacyChorusFruitPopped { .. } => f.write_str("LEGACY_CHORUS_FRUIT_POPPED"), + Material::LegacyBeetroot { .. } => f.write_str("LEGACY_BEETROOT"), + Material::LegacyBeetrootSeeds { .. } => f.write_str("LEGACY_BEETROOT_SEEDS"), + Material::LegacyBeetrootSoup { .. } => f.write_str("LEGACY_BEETROOT_SOUP"), + Material::LegacyDragonsBreath { .. } => f.write_str("LEGACY_DRAGONS_BREATH"), + Material::LegacySplashPotion { .. } => f.write_str("LEGACY_SPLASH_POTION"), + Material::LegacySpectralArrow { .. } => f.write_str("LEGACY_SPECTRAL_ARROW"), + Material::LegacyTippedArrow { .. } => f.write_str("LEGACY_TIPPED_ARROW"), + Material::LegacyLingeringPotion { .. } => f.write_str("LEGACY_LINGERING_POTION"), + Material::LegacyShield { .. } => f.write_str("LEGACY_SHIELD"), + Material::LegacyElytra { .. } => f.write_str("LEGACY_ELYTRA"), + Material::LegacyBoatSpruce { .. } => f.write_str("LEGACY_BOAT_SPRUCE"), + Material::LegacyBoatBirch { .. } => f.write_str("LEGACY_BOAT_BIRCH"), + Material::LegacyBoatJungle { .. } => f.write_str("LEGACY_BOAT_JUNGLE"), + Material::LegacyBoatAcacia { .. } => f.write_str("LEGACY_BOAT_ACACIA"), + Material::LegacyBoatDarkOak { .. } => f.write_str("LEGACY_BOAT_DARK_OAK"), + Material::LegacyTotem { .. } => f.write_str("LEGACY_TOTEM"), + Material::LegacyShulkerShell { .. } => f.write_str("LEGACY_SHULKER_SHELL"), + Material::LegacyIronNugget { .. } => f.write_str("LEGACY_IRON_NUGGET"), + Material::LegacyKnowledgeBook { .. } => f.write_str("LEGACY_KNOWLEDGE_BOOK"), + Material::LegacyGoldRecord { .. } => f.write_str("LEGACY_GOLD_RECORD"), + Material::LegacyGreenRecord { .. } => f.write_str("LEGACY_GREEN_RECORD"), + Material::LegacyRecord3 { .. } => f.write_str("LEGACY_RECORD_3"), + Material::LegacyRecord4 { .. } => f.write_str("LEGACY_RECORD_4"), + Material::LegacyRecord5 { .. } => f.write_str("LEGACY_RECORD_5"), + Material::LegacyRecord6 { .. } => f.write_str("LEGACY_RECORD_6"), + Material::LegacyRecord7 { .. } => f.write_str("LEGACY_RECORD_7"), + Material::LegacyRecord8 { .. } => f.write_str("LEGACY_RECORD_8"), + Material::LegacyRecord9 { .. } => f.write_str("LEGACY_RECORD_9"), + Material::LegacyRecord10 { .. } => f.write_str("LEGACY_RECORD_10"), + Material::LegacyRecord11 { .. } => f.write_str("LEGACY_RECORD_11"), + Material::LegacyRecord12 { .. } => f.write_str("LEGACY_RECORD_12"), + } + } +} +impl<'mc> std::ops::Deref for Material<'mc> { + type Target = MaterialStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + Material::Air { inner } => inner, + Material::Stone { inner } => inner, + Material::Granite { inner } => inner, + Material::PolishedGranite { inner } => inner, + Material::Diorite { inner } => inner, + Material::PolishedDiorite { inner } => inner, + Material::Andesite { inner } => inner, + Material::PolishedAndesite { inner } => inner, + Material::Deepslate { inner } => inner, + Material::CobbledDeepslate { inner } => inner, + Material::PolishedDeepslate { inner } => inner, + Material::Calcite { inner } => inner, + Material::Tuff { inner } => inner, + Material::TuffSlab { inner } => inner, + Material::TuffStairs { inner } => inner, + Material::TuffWall { inner } => inner, + Material::ChiseledTuff { inner } => inner, + Material::PolishedTuff { inner } => inner, + Material::PolishedTuffSlab { inner } => inner, + Material::PolishedTuffStairs { inner } => inner, + Material::PolishedTuffWall { inner } => inner, + Material::TuffBricks { inner } => inner, + Material::TuffBrickSlab { inner } => inner, + Material::TuffBrickStairs { inner } => inner, + Material::TuffBrickWall { inner } => inner, + Material::ChiseledTuffBricks { inner } => inner, + Material::DripstoneBlock { inner } => inner, + Material::GrassBlock { inner } => inner, + Material::Dirt { inner } => inner, + Material::CoarseDirt { inner } => inner, + Material::Podzol { inner } => inner, + Material::RootedDirt { inner } => inner, + Material::Mud { inner } => inner, + Material::CrimsonNylium { inner } => inner, + Material::WarpedNylium { inner } => inner, + Material::Cobblestone { inner } => inner, + Material::OakPlanks { inner } => inner, + Material::SprucePlanks { inner } => inner, + Material::BirchPlanks { inner } => inner, + Material::JunglePlanks { inner } => inner, + Material::AcaciaPlanks { inner } => inner, + Material::CherryPlanks { inner } => inner, + Material::DarkOakPlanks { inner } => inner, + Material::MangrovePlanks { inner } => inner, + Material::BambooPlanks { inner } => inner, + Material::CrimsonPlanks { inner } => inner, + Material::WarpedPlanks { inner } => inner, + Material::BambooMosaic { inner } => inner, + Material::OakSapling { inner } => inner, + Material::SpruceSapling { inner } => inner, + Material::BirchSapling { inner } => inner, + Material::JungleSapling { inner } => inner, + Material::AcaciaSapling { inner } => inner, + Material::CherrySapling { inner } => inner, + Material::DarkOakSapling { inner } => inner, + Material::MangrovePropagule { inner } => inner, + Material::Bedrock { inner } => inner, + Material::Sand { inner } => inner, + Material::SuspiciousSand { inner } => inner, + Material::SuspiciousGravel { inner } => inner, + Material::RedSand { inner } => inner, + Material::Gravel { inner } => inner, + Material::CoalOre { inner } => inner, + Material::DeepslateCoalOre { inner } => inner, + Material::IronOre { inner } => inner, + Material::DeepslateIronOre { inner } => inner, + Material::CopperOre { inner } => inner, + Material::DeepslateCopperOre { inner } => inner, + Material::GoldOre { inner } => inner, + Material::DeepslateGoldOre { inner } => inner, + Material::RedstoneOre { inner } => inner, + Material::DeepslateRedstoneOre { inner } => inner, + Material::EmeraldOre { inner } => inner, + Material::DeepslateEmeraldOre { inner } => inner, + Material::LapisOre { inner } => inner, + Material::DeepslateLapisOre { inner } => inner, + Material::DiamondOre { inner } => inner, + Material::DeepslateDiamondOre { inner } => inner, + Material::NetherGoldOre { inner } => inner, + Material::NetherQuartzOre { inner } => inner, + Material::AncientDebris { inner } => inner, + Material::CoalBlock { inner } => inner, + Material::RawIronBlock { inner } => inner, + Material::RawCopperBlock { inner } => inner, + Material::RawGoldBlock { inner } => inner, + Material::HeavyCore { inner } => inner, + Material::AmethystBlock { inner } => inner, + Material::BuddingAmethyst { inner } => inner, + Material::IronBlock { inner } => inner, + Material::CopperBlock { inner } => inner, + Material::GoldBlock { inner } => inner, + Material::DiamondBlock { inner } => inner, + Material::NetheriteBlock { inner } => inner, + Material::ExposedCopper { inner } => inner, + Material::WeatheredCopper { inner } => inner, + Material::OxidizedCopper { inner } => inner, + Material::ChiseledCopper { inner } => inner, + Material::ExposedChiseledCopper { inner } => inner, + Material::WeatheredChiseledCopper { inner } => inner, + Material::OxidizedChiseledCopper { inner } => inner, + Material::CutCopper { inner } => inner, + Material::ExposedCutCopper { inner } => inner, + Material::WeatheredCutCopper { inner } => inner, + Material::OxidizedCutCopper { inner } => inner, + Material::CutCopperStairs { inner } => inner, + Material::ExposedCutCopperStairs { inner } => inner, + Material::WeatheredCutCopperStairs { inner } => inner, + Material::OxidizedCutCopperStairs { inner } => inner, + Material::CutCopperSlab { inner } => inner, + Material::ExposedCutCopperSlab { inner } => inner, + Material::WeatheredCutCopperSlab { inner } => inner, + Material::OxidizedCutCopperSlab { inner } => inner, + Material::WaxedCopperBlock { inner } => inner, + Material::WaxedExposedCopper { inner } => inner, + Material::WaxedWeatheredCopper { inner } => inner, + Material::WaxedOxidizedCopper { inner } => inner, + Material::WaxedChiseledCopper { inner } => inner, + Material::WaxedExposedChiseledCopper { inner } => inner, + Material::WaxedWeatheredChiseledCopper { inner } => inner, + Material::WaxedOxidizedChiseledCopper { inner } => inner, + Material::WaxedCutCopper { inner } => inner, + Material::WaxedExposedCutCopper { inner } => inner, + Material::WaxedWeatheredCutCopper { inner } => inner, + Material::WaxedOxidizedCutCopper { inner } => inner, + Material::WaxedCutCopperStairs { inner } => inner, + Material::WaxedExposedCutCopperStairs { inner } => inner, + Material::WaxedWeatheredCutCopperStairs { inner } => inner, + Material::WaxedOxidizedCutCopperStairs { inner } => inner, + Material::WaxedCutCopperSlab { inner } => inner, + Material::WaxedExposedCutCopperSlab { inner } => inner, + Material::WaxedWeatheredCutCopperSlab { inner } => inner, + Material::WaxedOxidizedCutCopperSlab { inner } => inner, + Material::OakLog { inner } => inner, + Material::SpruceLog { inner } => inner, + Material::BirchLog { inner } => inner, + Material::JungleLog { inner } => inner, + Material::AcaciaLog { inner } => inner, + Material::CherryLog { inner } => inner, + Material::DarkOakLog { inner } => inner, + Material::MangroveLog { inner } => inner, + Material::MangroveRoots { inner } => inner, + Material::MuddyMangroveRoots { inner } => inner, + Material::CrimsonStem { inner } => inner, + Material::WarpedStem { inner } => inner, + Material::BambooBlock { inner } => inner, + Material::StrippedOakLog { inner } => inner, + Material::StrippedSpruceLog { inner } => inner, + Material::StrippedBirchLog { inner } => inner, + Material::StrippedJungleLog { inner } => inner, + Material::StrippedAcaciaLog { inner } => inner, + Material::StrippedCherryLog { inner } => inner, + Material::StrippedDarkOakLog { inner } => inner, + Material::StrippedMangroveLog { inner } => inner, + Material::StrippedCrimsonStem { inner } => inner, + Material::StrippedWarpedStem { inner } => inner, + Material::StrippedOakWood { inner } => inner, + Material::StrippedSpruceWood { inner } => inner, + Material::StrippedBirchWood { inner } => inner, + Material::StrippedJungleWood { inner } => inner, + Material::StrippedAcaciaWood { inner } => inner, + Material::StrippedCherryWood { inner } => inner, + Material::StrippedDarkOakWood { inner } => inner, + Material::StrippedMangroveWood { inner } => inner, + Material::StrippedCrimsonHyphae { inner } => inner, + Material::StrippedWarpedHyphae { inner } => inner, + Material::StrippedBambooBlock { inner } => inner, + Material::OakWood { inner } => inner, + Material::SpruceWood { inner } => inner, + Material::BirchWood { inner } => inner, + Material::JungleWood { inner } => inner, + Material::AcaciaWood { inner } => inner, + Material::CherryWood { inner } => inner, + Material::DarkOakWood { inner } => inner, + Material::MangroveWood { inner } => inner, + Material::CrimsonHyphae { inner } => inner, + Material::WarpedHyphae { inner } => inner, + Material::OakLeaves { inner } => inner, + Material::SpruceLeaves { inner } => inner, + Material::BirchLeaves { inner } => inner, + Material::JungleLeaves { inner } => inner, + Material::AcaciaLeaves { inner } => inner, + Material::CherryLeaves { inner } => inner, + Material::DarkOakLeaves { inner } => inner, + Material::MangroveLeaves { inner } => inner, + Material::AzaleaLeaves { inner } => inner, + Material::FloweringAzaleaLeaves { inner } => inner, + Material::Sponge { inner } => inner, + Material::WetSponge { inner } => inner, + Material::Glass { inner } => inner, + Material::TintedGlass { inner } => inner, + Material::LapisBlock { inner } => inner, + Material::Sandstone { inner } => inner, + Material::ChiseledSandstone { inner } => inner, + Material::CutSandstone { inner } => inner, + Material::Cobweb { inner } => inner, + Material::ShortGrass { inner } => inner, + Material::Fern { inner } => inner, + Material::Azalea { inner } => inner, + Material::FloweringAzalea { inner } => inner, + Material::DeadBush { inner } => inner, + Material::Seagrass { inner } => inner, + Material::SeaPickle { inner } => inner, + Material::WhiteWool { inner } => inner, + Material::OrangeWool { inner } => inner, + Material::MagentaWool { inner } => inner, + Material::LightBlueWool { inner } => inner, + Material::YellowWool { inner } => inner, + Material::LimeWool { inner } => inner, + Material::PinkWool { inner } => inner, + Material::GrayWool { inner } => inner, + Material::LightGrayWool { inner } => inner, + Material::CyanWool { inner } => inner, + Material::PurpleWool { inner } => inner, + Material::BlueWool { inner } => inner, + Material::BrownWool { inner } => inner, + Material::GreenWool { inner } => inner, + Material::RedWool { inner } => inner, + Material::BlackWool { inner } => inner, + Material::Dandelion { inner } => inner, + Material::Poppy { inner } => inner, + Material::BlueOrchid { inner } => inner, + Material::Allium { inner } => inner, + Material::AzureBluet { inner } => inner, + Material::RedTulip { inner } => inner, + Material::OrangeTulip { inner } => inner, + Material::WhiteTulip { inner } => inner, + Material::PinkTulip { inner } => inner, + Material::OxeyeDaisy { inner } => inner, + Material::Cornflower { inner } => inner, + Material::LilyOfTheValley { inner } => inner, + Material::WitherRose { inner } => inner, + Material::Torchflower { inner } => inner, + Material::PitcherPlant { inner } => inner, + Material::SporeBlossom { inner } => inner, + Material::BrownMushroom { inner } => inner, + Material::RedMushroom { inner } => inner, + Material::CrimsonFungus { inner } => inner, + Material::WarpedFungus { inner } => inner, + Material::CrimsonRoots { inner } => inner, + Material::WarpedRoots { inner } => inner, + Material::NetherSprouts { inner } => inner, + Material::WeepingVines { inner } => inner, + Material::TwistingVines { inner } => inner, + Material::SugarCane { inner } => inner, + Material::Kelp { inner } => inner, + Material::MossCarpet { inner } => inner, + Material::PinkPetals { inner } => inner, + Material::MossBlock { inner } => inner, + Material::HangingRoots { inner } => inner, + Material::BigDripleaf { inner } => inner, + Material::SmallDripleaf { inner } => inner, + Material::Bamboo { inner } => inner, + Material::OakSlab { inner } => inner, + Material::SpruceSlab { inner } => inner, + Material::BirchSlab { inner } => inner, + Material::JungleSlab { inner } => inner, + Material::AcaciaSlab { inner } => inner, + Material::CherrySlab { inner } => inner, + Material::DarkOakSlab { inner } => inner, + Material::MangroveSlab { inner } => inner, + Material::BambooSlab { inner } => inner, + Material::BambooMosaicSlab { inner } => inner, + Material::CrimsonSlab { inner } => inner, + Material::WarpedSlab { inner } => inner, + Material::StoneSlab { inner } => inner, + Material::SmoothStoneSlab { inner } => inner, + Material::SandstoneSlab { inner } => inner, + Material::CutSandstoneSlab { inner } => inner, + Material::PetrifiedOakSlab { inner } => inner, + Material::CobblestoneSlab { inner } => inner, + Material::BrickSlab { inner } => inner, + Material::StoneBrickSlab { inner } => inner, + Material::MudBrickSlab { inner } => inner, + Material::NetherBrickSlab { inner } => inner, + Material::QuartzSlab { inner } => inner, + Material::RedSandstoneSlab { inner } => inner, + Material::CutRedSandstoneSlab { inner } => inner, + Material::PurpurSlab { inner } => inner, + Material::PrismarineSlab { inner } => inner, + Material::PrismarineBrickSlab { inner } => inner, + Material::DarkPrismarineSlab { inner } => inner, + Material::SmoothQuartz { inner } => inner, + Material::SmoothRedSandstone { inner } => inner, + Material::SmoothSandstone { inner } => inner, + Material::SmoothStone { inner } => inner, + Material::Bricks { inner } => inner, + Material::Bookshelf { inner } => inner, + Material::ChiseledBookshelf { inner } => inner, + Material::DecoratedPot { inner } => inner, + Material::MossyCobblestone { inner } => inner, + Material::Obsidian { inner } => inner, + Material::Torch { inner } => inner, + Material::EndRod { inner } => inner, + Material::ChorusPlant { inner } => inner, + Material::ChorusFlower { inner } => inner, + Material::PurpurBlock { inner } => inner, + Material::PurpurPillar { inner } => inner, + Material::PurpurStairs { inner } => inner, + Material::Spawner { inner } => inner, + Material::Chest { inner } => inner, + Material::CraftingTable { inner } => inner, + Material::Farmland { inner } => inner, + Material::Furnace { inner } => inner, + Material::Ladder { inner } => inner, + Material::CobblestoneStairs { inner } => inner, + Material::Snow { inner } => inner, + Material::Ice { inner } => inner, + Material::SnowBlock { inner } => inner, + Material::Cactus { inner } => inner, + Material::Clay { inner } => inner, + Material::Jukebox { inner } => inner, + Material::OakFence { inner } => inner, + Material::SpruceFence { inner } => inner, + Material::BirchFence { inner } => inner, + Material::JungleFence { inner } => inner, + Material::AcaciaFence { inner } => inner, + Material::CherryFence { inner } => inner, + Material::DarkOakFence { inner } => inner, + Material::MangroveFence { inner } => inner, + Material::BambooFence { inner } => inner, + Material::CrimsonFence { inner } => inner, + Material::WarpedFence { inner } => inner, + Material::Pumpkin { inner } => inner, + Material::CarvedPumpkin { inner } => inner, + Material::JackOLantern { inner } => inner, + Material::Netherrack { inner } => inner, + Material::SoulSand { inner } => inner, + Material::SoulSoil { inner } => inner, + Material::Basalt { inner } => inner, + Material::PolishedBasalt { inner } => inner, + Material::SmoothBasalt { inner } => inner, + Material::SoulTorch { inner } => inner, + Material::Glowstone { inner } => inner, + Material::InfestedStone { inner } => inner, + Material::InfestedCobblestone { inner } => inner, + Material::InfestedStoneBricks { inner } => inner, + Material::InfestedMossyStoneBricks { inner } => inner, + Material::InfestedCrackedStoneBricks { inner } => inner, + Material::InfestedChiseledStoneBricks { inner } => inner, + Material::InfestedDeepslate { inner } => inner, + Material::StoneBricks { inner } => inner, + Material::MossyStoneBricks { inner } => inner, + Material::CrackedStoneBricks { inner } => inner, + Material::ChiseledStoneBricks { inner } => inner, + Material::PackedMud { inner } => inner, + Material::MudBricks { inner } => inner, + Material::DeepslateBricks { inner } => inner, + Material::CrackedDeepslateBricks { inner } => inner, + Material::DeepslateTiles { inner } => inner, + Material::CrackedDeepslateTiles { inner } => inner, + Material::ChiseledDeepslate { inner } => inner, + Material::ReinforcedDeepslate { inner } => inner, + Material::BrownMushroomBlock { inner } => inner, + Material::RedMushroomBlock { inner } => inner, + Material::MushroomStem { inner } => inner, + Material::IronBars { inner } => inner, + Material::Chain { inner } => inner, + Material::GlassPane { inner } => inner, + Material::Melon { inner } => inner, + Material::Vine { inner } => inner, + Material::GlowLichen { inner } => inner, + Material::BrickStairs { inner } => inner, + Material::StoneBrickStairs { inner } => inner, + Material::MudBrickStairs { inner } => inner, + Material::Mycelium { inner } => inner, + Material::LilyPad { inner } => inner, + Material::NetherBricks { inner } => inner, + Material::CrackedNetherBricks { inner } => inner, + Material::ChiseledNetherBricks { inner } => inner, + Material::NetherBrickFence { inner } => inner, + Material::NetherBrickStairs { inner } => inner, + Material::Sculk { inner } => inner, + Material::SculkVein { inner } => inner, + Material::SculkCatalyst { inner } => inner, + Material::SculkShrieker { inner } => inner, + Material::EnchantingTable { inner } => inner, + Material::EndPortalFrame { inner } => inner, + Material::EndStone { inner } => inner, + Material::EndStoneBricks { inner } => inner, + Material::DragonEgg { inner } => inner, + Material::SandstoneStairs { inner } => inner, + Material::EnderChest { inner } => inner, + Material::EmeraldBlock { inner } => inner, + Material::OakStairs { inner } => inner, + Material::SpruceStairs { inner } => inner, + Material::BirchStairs { inner } => inner, + Material::JungleStairs { inner } => inner, + Material::AcaciaStairs { inner } => inner, + Material::CherryStairs { inner } => inner, + Material::DarkOakStairs { inner } => inner, + Material::MangroveStairs { inner } => inner, + Material::BambooStairs { inner } => inner, + Material::BambooMosaicStairs { inner } => inner, + Material::CrimsonStairs { inner } => inner, + Material::WarpedStairs { inner } => inner, + Material::CommandBlock { inner } => inner, + Material::Beacon { inner } => inner, + Material::CobblestoneWall { inner } => inner, + Material::MossyCobblestoneWall { inner } => inner, + Material::BrickWall { inner } => inner, + Material::PrismarineWall { inner } => inner, + Material::RedSandstoneWall { inner } => inner, + Material::MossyStoneBrickWall { inner } => inner, + Material::GraniteWall { inner } => inner, + Material::StoneBrickWall { inner } => inner, + Material::MudBrickWall { inner } => inner, + Material::NetherBrickWall { inner } => inner, + Material::AndesiteWall { inner } => inner, + Material::RedNetherBrickWall { inner } => inner, + Material::SandstoneWall { inner } => inner, + Material::EndStoneBrickWall { inner } => inner, + Material::DioriteWall { inner } => inner, + Material::BlackstoneWall { inner } => inner, + Material::PolishedBlackstoneWall { inner } => inner, + Material::PolishedBlackstoneBrickWall { inner } => inner, + Material::CobbledDeepslateWall { inner } => inner, + Material::PolishedDeepslateWall { inner } => inner, + Material::DeepslateBrickWall { inner } => inner, + Material::DeepslateTileWall { inner } => inner, + Material::Anvil { inner } => inner, + Material::ChippedAnvil { inner } => inner, + Material::DamagedAnvil { inner } => inner, + Material::ChiseledQuartzBlock { inner } => inner, + Material::QuartzBlock { inner } => inner, + Material::QuartzBricks { inner } => inner, + Material::QuartzPillar { inner } => inner, + Material::QuartzStairs { inner } => inner, + Material::WhiteTerracotta { inner } => inner, + Material::OrangeTerracotta { inner } => inner, + Material::MagentaTerracotta { inner } => inner, + Material::LightBlueTerracotta { inner } => inner, + Material::YellowTerracotta { inner } => inner, + Material::LimeTerracotta { inner } => inner, + Material::PinkTerracotta { inner } => inner, + Material::GrayTerracotta { inner } => inner, + Material::LightGrayTerracotta { inner } => inner, + Material::CyanTerracotta { inner } => inner, + Material::PurpleTerracotta { inner } => inner, + Material::BlueTerracotta { inner } => inner, + Material::BrownTerracotta { inner } => inner, + Material::GreenTerracotta { inner } => inner, + Material::RedTerracotta { inner } => inner, + Material::BlackTerracotta { inner } => inner, + Material::Barrier { inner } => inner, + Material::Light { inner } => inner, + Material::HayBlock { inner } => inner, + Material::WhiteCarpet { inner } => inner, + Material::OrangeCarpet { inner } => inner, + Material::MagentaCarpet { inner } => inner, + Material::LightBlueCarpet { inner } => inner, + Material::YellowCarpet { inner } => inner, + Material::LimeCarpet { inner } => inner, + Material::PinkCarpet { inner } => inner, + Material::GrayCarpet { inner } => inner, + Material::LightGrayCarpet { inner } => inner, + Material::CyanCarpet { inner } => inner, + Material::PurpleCarpet { inner } => inner, + Material::BlueCarpet { inner } => inner, + Material::BrownCarpet { inner } => inner, + Material::GreenCarpet { inner } => inner, + Material::RedCarpet { inner } => inner, + Material::BlackCarpet { inner } => inner, + Material::Terracotta { inner } => inner, + Material::PackedIce { inner } => inner, + Material::DirtPath { inner } => inner, + Material::Sunflower { inner } => inner, + Material::Lilac { inner } => inner, + Material::RoseBush { inner } => inner, + Material::Peony { inner } => inner, + Material::TallGrass { inner } => inner, + Material::LargeFern { inner } => inner, + Material::WhiteStainedGlass { inner } => inner, + Material::OrangeStainedGlass { inner } => inner, + Material::MagentaStainedGlass { inner } => inner, + Material::LightBlueStainedGlass { inner } => inner, + Material::YellowStainedGlass { inner } => inner, + Material::LimeStainedGlass { inner } => inner, + Material::PinkStainedGlass { inner } => inner, + Material::GrayStainedGlass { inner } => inner, + Material::LightGrayStainedGlass { inner } => inner, + Material::CyanStainedGlass { inner } => inner, + Material::PurpleStainedGlass { inner } => inner, + Material::BlueStainedGlass { inner } => inner, + Material::BrownStainedGlass { inner } => inner, + Material::GreenStainedGlass { inner } => inner, + Material::RedStainedGlass { inner } => inner, + Material::BlackStainedGlass { inner } => inner, + Material::WhiteStainedGlassPane { inner } => inner, + Material::OrangeStainedGlassPane { inner } => inner, + Material::MagentaStainedGlassPane { inner } => inner, + Material::LightBlueStainedGlassPane { inner } => inner, + Material::YellowStainedGlassPane { inner } => inner, + Material::LimeStainedGlassPane { inner } => inner, + Material::PinkStainedGlassPane { inner } => inner, + Material::GrayStainedGlassPane { inner } => inner, + Material::LightGrayStainedGlassPane { inner } => inner, + Material::CyanStainedGlassPane { inner } => inner, + Material::PurpleStainedGlassPane { inner } => inner, + Material::BlueStainedGlassPane { inner } => inner, + Material::BrownStainedGlassPane { inner } => inner, + Material::GreenStainedGlassPane { inner } => inner, + Material::RedStainedGlassPane { inner } => inner, + Material::BlackStainedGlassPane { inner } => inner, + Material::Prismarine { inner } => inner, + Material::PrismarineBricks { inner } => inner, + Material::DarkPrismarine { inner } => inner, + Material::PrismarineStairs { inner } => inner, + Material::PrismarineBrickStairs { inner } => inner, + Material::DarkPrismarineStairs { inner } => inner, + Material::SeaLantern { inner } => inner, + Material::RedSandstone { inner } => inner, + Material::ChiseledRedSandstone { inner } => inner, + Material::CutRedSandstone { inner } => inner, + Material::RedSandstoneStairs { inner } => inner, + Material::RepeatingCommandBlock { inner } => inner, + Material::ChainCommandBlock { inner } => inner, + Material::MagmaBlock { inner } => inner, + Material::NetherWartBlock { inner } => inner, + Material::WarpedWartBlock { inner } => inner, + Material::RedNetherBricks { inner } => inner, + Material::BoneBlock { inner } => inner, + Material::StructureVoid { inner } => inner, + Material::ShulkerBox { inner } => inner, + Material::WhiteShulkerBox { inner } => inner, + Material::OrangeShulkerBox { inner } => inner, + Material::MagentaShulkerBox { inner } => inner, + Material::LightBlueShulkerBox { inner } => inner, + Material::YellowShulkerBox { inner } => inner, + Material::LimeShulkerBox { inner } => inner, + Material::PinkShulkerBox { inner } => inner, + Material::GrayShulkerBox { inner } => inner, + Material::LightGrayShulkerBox { inner } => inner, + Material::CyanShulkerBox { inner } => inner, + Material::PurpleShulkerBox { inner } => inner, + Material::BlueShulkerBox { inner } => inner, + Material::BrownShulkerBox { inner } => inner, + Material::GreenShulkerBox { inner } => inner, + Material::RedShulkerBox { inner } => inner, + Material::BlackShulkerBox { inner } => inner, + Material::WhiteGlazedTerracotta { inner } => inner, + Material::OrangeGlazedTerracotta { inner } => inner, + Material::MagentaGlazedTerracotta { inner } => inner, + Material::LightBlueGlazedTerracotta { inner } => inner, + Material::YellowGlazedTerracotta { inner } => inner, + Material::LimeGlazedTerracotta { inner } => inner, + Material::PinkGlazedTerracotta { inner } => inner, + Material::GrayGlazedTerracotta { inner } => inner, + Material::LightGrayGlazedTerracotta { inner } => inner, + Material::CyanGlazedTerracotta { inner } => inner, + Material::PurpleGlazedTerracotta { inner } => inner, + Material::BlueGlazedTerracotta { inner } => inner, + Material::BrownGlazedTerracotta { inner } => inner, + Material::GreenGlazedTerracotta { inner } => inner, + Material::RedGlazedTerracotta { inner } => inner, + Material::BlackGlazedTerracotta { inner } => inner, + Material::WhiteConcrete { inner } => inner, + Material::OrangeConcrete { inner } => inner, + Material::MagentaConcrete { inner } => inner, + Material::LightBlueConcrete { inner } => inner, + Material::YellowConcrete { inner } => inner, + Material::LimeConcrete { inner } => inner, + Material::PinkConcrete { inner } => inner, + Material::GrayConcrete { inner } => inner, + Material::LightGrayConcrete { inner } => inner, + Material::CyanConcrete { inner } => inner, + Material::PurpleConcrete { inner } => inner, + Material::BlueConcrete { inner } => inner, + Material::BrownConcrete { inner } => inner, + Material::GreenConcrete { inner } => inner, + Material::RedConcrete { inner } => inner, + Material::BlackConcrete { inner } => inner, + Material::WhiteConcretePowder { inner } => inner, + Material::OrangeConcretePowder { inner } => inner, + Material::MagentaConcretePowder { inner } => inner, + Material::LightBlueConcretePowder { inner } => inner, + Material::YellowConcretePowder { inner } => inner, + Material::LimeConcretePowder { inner } => inner, + Material::PinkConcretePowder { inner } => inner, + Material::GrayConcretePowder { inner } => inner, + Material::LightGrayConcretePowder { inner } => inner, + Material::CyanConcretePowder { inner } => inner, + Material::PurpleConcretePowder { inner } => inner, + Material::BlueConcretePowder { inner } => inner, + Material::BrownConcretePowder { inner } => inner, + Material::GreenConcretePowder { inner } => inner, + Material::RedConcretePowder { inner } => inner, + Material::BlackConcretePowder { inner } => inner, + Material::TurtleEgg { inner } => inner, + Material::SnifferEgg { inner } => inner, + Material::DeadTubeCoralBlock { inner } => inner, + Material::DeadBrainCoralBlock { inner } => inner, + Material::DeadBubbleCoralBlock { inner } => inner, + Material::DeadFireCoralBlock { inner } => inner, + Material::DeadHornCoralBlock { inner } => inner, + Material::TubeCoralBlock { inner } => inner, + Material::BrainCoralBlock { inner } => inner, + Material::BubbleCoralBlock { inner } => inner, + Material::FireCoralBlock { inner } => inner, + Material::HornCoralBlock { inner } => inner, + Material::TubeCoral { inner } => inner, + Material::BrainCoral { inner } => inner, + Material::BubbleCoral { inner } => inner, + Material::FireCoral { inner } => inner, + Material::HornCoral { inner } => inner, + Material::DeadBrainCoral { inner } => inner, + Material::DeadBubbleCoral { inner } => inner, + Material::DeadFireCoral { inner } => inner, + Material::DeadHornCoral { inner } => inner, + Material::DeadTubeCoral { inner } => inner, + Material::TubeCoralFan { inner } => inner, + Material::BrainCoralFan { inner } => inner, + Material::BubbleCoralFan { inner } => inner, + Material::FireCoralFan { inner } => inner, + Material::HornCoralFan { inner } => inner, + Material::DeadTubeCoralFan { inner } => inner, + Material::DeadBrainCoralFan { inner } => inner, + Material::DeadBubbleCoralFan { inner } => inner, + Material::DeadFireCoralFan { inner } => inner, + Material::DeadHornCoralFan { inner } => inner, + Material::BlueIce { inner } => inner, + Material::Conduit { inner } => inner, + Material::PolishedGraniteStairs { inner } => inner, + Material::SmoothRedSandstoneStairs { inner } => inner, + Material::MossyStoneBrickStairs { inner } => inner, + Material::PolishedDioriteStairs { inner } => inner, + Material::MossyCobblestoneStairs { inner } => inner, + Material::EndStoneBrickStairs { inner } => inner, + Material::StoneStairs { inner } => inner, + Material::SmoothSandstoneStairs { inner } => inner, + Material::SmoothQuartzStairs { inner } => inner, + Material::GraniteStairs { inner } => inner, + Material::AndesiteStairs { inner } => inner, + Material::RedNetherBrickStairs { inner } => inner, + Material::PolishedAndesiteStairs { inner } => inner, + Material::DioriteStairs { inner } => inner, + Material::CobbledDeepslateStairs { inner } => inner, + Material::PolishedDeepslateStairs { inner } => inner, + Material::DeepslateBrickStairs { inner } => inner, + Material::DeepslateTileStairs { inner } => inner, + Material::PolishedGraniteSlab { inner } => inner, + Material::SmoothRedSandstoneSlab { inner } => inner, + Material::MossyStoneBrickSlab { inner } => inner, + Material::PolishedDioriteSlab { inner } => inner, + Material::MossyCobblestoneSlab { inner } => inner, + Material::EndStoneBrickSlab { inner } => inner, + Material::SmoothSandstoneSlab { inner } => inner, + Material::SmoothQuartzSlab { inner } => inner, + Material::GraniteSlab { inner } => inner, + Material::AndesiteSlab { inner } => inner, + Material::RedNetherBrickSlab { inner } => inner, + Material::PolishedAndesiteSlab { inner } => inner, + Material::DioriteSlab { inner } => inner, + Material::CobbledDeepslateSlab { inner } => inner, + Material::PolishedDeepslateSlab { inner } => inner, + Material::DeepslateBrickSlab { inner } => inner, + Material::DeepslateTileSlab { inner } => inner, + Material::Scaffolding { inner } => inner, + Material::Redstone { inner } => inner, + Material::RedstoneTorch { inner } => inner, + Material::RedstoneBlock { inner } => inner, + Material::Repeater { inner } => inner, + Material::Comparator { inner } => inner, + Material::Piston { inner } => inner, + Material::StickyPiston { inner } => inner, + Material::SlimeBlock { inner } => inner, + Material::HoneyBlock { inner } => inner, + Material::Observer { inner } => inner, + Material::Hopper { inner } => inner, + Material::Dispenser { inner } => inner, + Material::Dropper { inner } => inner, + Material::Lectern { inner } => inner, + Material::Target { inner } => inner, + Material::Lever { inner } => inner, + Material::LightningRod { inner } => inner, + Material::DaylightDetector { inner } => inner, + Material::SculkSensor { inner } => inner, + Material::CalibratedSculkSensor { inner } => inner, + Material::TripwireHook { inner } => inner, + Material::TrappedChest { inner } => inner, + Material::Tnt { inner } => inner, + Material::RedstoneLamp { inner } => inner, + Material::NoteBlock { inner } => inner, + Material::StoneButton { inner } => inner, + Material::PolishedBlackstoneButton { inner } => inner, + Material::OakButton { inner } => inner, + Material::SpruceButton { inner } => inner, + Material::BirchButton { inner } => inner, + Material::JungleButton { inner } => inner, + Material::AcaciaButton { inner } => inner, + Material::CherryButton { inner } => inner, + Material::DarkOakButton { inner } => inner, + Material::MangroveButton { inner } => inner, + Material::BambooButton { inner } => inner, + Material::CrimsonButton { inner } => inner, + Material::WarpedButton { inner } => inner, + Material::StonePressurePlate { inner } => inner, + Material::PolishedBlackstonePressurePlate { inner } => inner, + Material::LightWeightedPressurePlate { inner } => inner, + Material::HeavyWeightedPressurePlate { inner } => inner, + Material::OakPressurePlate { inner } => inner, + Material::SprucePressurePlate { inner } => inner, + Material::BirchPressurePlate { inner } => inner, + Material::JunglePressurePlate { inner } => inner, + Material::AcaciaPressurePlate { inner } => inner, + Material::CherryPressurePlate { inner } => inner, + Material::DarkOakPressurePlate { inner } => inner, + Material::MangrovePressurePlate { inner } => inner, + Material::BambooPressurePlate { inner } => inner, + Material::CrimsonPressurePlate { inner } => inner, + Material::WarpedPressurePlate { inner } => inner, + Material::IronDoor { inner } => inner, + Material::OakDoor { inner } => inner, + Material::SpruceDoor { inner } => inner, + Material::BirchDoor { inner } => inner, + Material::JungleDoor { inner } => inner, + Material::AcaciaDoor { inner } => inner, + Material::CherryDoor { inner } => inner, + Material::DarkOakDoor { inner } => inner, + Material::MangroveDoor { inner } => inner, + Material::BambooDoor { inner } => inner, + Material::CrimsonDoor { inner } => inner, + Material::WarpedDoor { inner } => inner, + Material::CopperDoor { inner } => inner, + Material::ExposedCopperDoor { inner } => inner, + Material::WeatheredCopperDoor { inner } => inner, + Material::OxidizedCopperDoor { inner } => inner, + Material::WaxedCopperDoor { inner } => inner, + Material::WaxedExposedCopperDoor { inner } => inner, + Material::WaxedWeatheredCopperDoor { inner } => inner, + Material::WaxedOxidizedCopperDoor { inner } => inner, + Material::IronTrapdoor { inner } => inner, + Material::OakTrapdoor { inner } => inner, + Material::SpruceTrapdoor { inner } => inner, + Material::BirchTrapdoor { inner } => inner, + Material::JungleTrapdoor { inner } => inner, + Material::AcaciaTrapdoor { inner } => inner, + Material::CherryTrapdoor { inner } => inner, + Material::DarkOakTrapdoor { inner } => inner, + Material::MangroveTrapdoor { inner } => inner, + Material::BambooTrapdoor { inner } => inner, + Material::CrimsonTrapdoor { inner } => inner, + Material::WarpedTrapdoor { inner } => inner, + Material::CopperTrapdoor { inner } => inner, + Material::ExposedCopperTrapdoor { inner } => inner, + Material::WeatheredCopperTrapdoor { inner } => inner, + Material::OxidizedCopperTrapdoor { inner } => inner, + Material::WaxedCopperTrapdoor { inner } => inner, + Material::WaxedExposedCopperTrapdoor { inner } => inner, + Material::WaxedWeatheredCopperTrapdoor { inner } => inner, + Material::WaxedOxidizedCopperTrapdoor { inner } => inner, + Material::OakFenceGate { inner } => inner, + Material::SpruceFenceGate { inner } => inner, + Material::BirchFenceGate { inner } => inner, + Material::JungleFenceGate { inner } => inner, + Material::AcaciaFenceGate { inner } => inner, + Material::CherryFenceGate { inner } => inner, + Material::DarkOakFenceGate { inner } => inner, + Material::MangroveFenceGate { inner } => inner, + Material::BambooFenceGate { inner } => inner, + Material::CrimsonFenceGate { inner } => inner, + Material::WarpedFenceGate { inner } => inner, + Material::PoweredRail { inner } => inner, + Material::DetectorRail { inner } => inner, + Material::Rail { inner } => inner, + Material::ActivatorRail { inner } => inner, + Material::Saddle { inner } => inner, + Material::Minecart { inner } => inner, + Material::ChestMinecart { inner } => inner, + Material::FurnaceMinecart { inner } => inner, + Material::TntMinecart { inner } => inner, + Material::HopperMinecart { inner } => inner, + Material::CarrotOnAStick { inner } => inner, + Material::WarpedFungusOnAStick { inner } => inner, + Material::Elytra { inner } => inner, + Material::OakBoat { inner } => inner, + Material::OakChestBoat { inner } => inner, + Material::SpruceBoat { inner } => inner, + Material::SpruceChestBoat { inner } => inner, + Material::BirchBoat { inner } => inner, + Material::BirchChestBoat { inner } => inner, + Material::JungleBoat { inner } => inner, + Material::JungleChestBoat { inner } => inner, + Material::AcaciaBoat { inner } => inner, + Material::AcaciaChestBoat { inner } => inner, + Material::CherryBoat { inner } => inner, + Material::CherryChestBoat { inner } => inner, + Material::DarkOakBoat { inner } => inner, + Material::DarkOakChestBoat { inner } => inner, + Material::MangroveBoat { inner } => inner, + Material::MangroveChestBoat { inner } => inner, + Material::BambooRaft { inner } => inner, + Material::BambooChestRaft { inner } => inner, + Material::StructureBlock { inner } => inner, + Material::Jigsaw { inner } => inner, + Material::TurtleHelmet { inner } => inner, + Material::TurtleScute { inner } => inner, + Material::ArmadilloScute { inner } => inner, + Material::WolfArmor { inner } => inner, + Material::FlintAndSteel { inner } => inner, + Material::Bowl { inner } => inner, + Material::Apple { inner } => inner, + Material::Bow { inner } => inner, + Material::Arrow { inner } => inner, + Material::Coal { inner } => inner, + Material::Charcoal { inner } => inner, + Material::Diamond { inner } => inner, + Material::Emerald { inner } => inner, + Material::LapisLazuli { inner } => inner, + Material::Quartz { inner } => inner, + Material::AmethystShard { inner } => inner, + Material::RawIron { inner } => inner, + Material::IronIngot { inner } => inner, + Material::RawCopper { inner } => inner, + Material::CopperIngot { inner } => inner, + Material::RawGold { inner } => inner, + Material::GoldIngot { inner } => inner, + Material::NetheriteIngot { inner } => inner, + Material::NetheriteScrap { inner } => inner, + Material::WoodenSword { inner } => inner, + Material::WoodenShovel { inner } => inner, + Material::WoodenPickaxe { inner } => inner, + Material::WoodenAxe { inner } => inner, + Material::WoodenHoe { inner } => inner, + Material::StoneSword { inner } => inner, + Material::StoneShovel { inner } => inner, + Material::StonePickaxe { inner } => inner, + Material::StoneAxe { inner } => inner, + Material::StoneHoe { inner } => inner, + Material::GoldenSword { inner } => inner, + Material::GoldenShovel { inner } => inner, + Material::GoldenPickaxe { inner } => inner, + Material::GoldenAxe { inner } => inner, + Material::GoldenHoe { inner } => inner, + Material::IronSword { inner } => inner, + Material::IronShovel { inner } => inner, + Material::IronPickaxe { inner } => inner, + Material::IronAxe { inner } => inner, + Material::IronHoe { inner } => inner, + Material::DiamondSword { inner } => inner, + Material::DiamondShovel { inner } => inner, + Material::DiamondPickaxe { inner } => inner, + Material::DiamondAxe { inner } => inner, + Material::DiamondHoe { inner } => inner, + Material::NetheriteSword { inner } => inner, + Material::NetheriteShovel { inner } => inner, + Material::NetheritePickaxe { inner } => inner, + Material::NetheriteAxe { inner } => inner, + Material::NetheriteHoe { inner } => inner, + Material::Stick { inner } => inner, + Material::MushroomStew { inner } => inner, + Material::String { inner } => inner, + Material::Feather { inner } => inner, + Material::Gunpowder { inner } => inner, + Material::WheatSeeds { inner } => inner, + Material::Wheat { inner } => inner, + Material::Bread { inner } => inner, + Material::LeatherHelmet { inner } => inner, + Material::LeatherChestplate { inner } => inner, + Material::LeatherLeggings { inner } => inner, + Material::LeatherBoots { inner } => inner, + Material::ChainmailHelmet { inner } => inner, + Material::ChainmailChestplate { inner } => inner, + Material::ChainmailLeggings { inner } => inner, + Material::ChainmailBoots { inner } => inner, + Material::IronHelmet { inner } => inner, + Material::IronChestplate { inner } => inner, + Material::IronLeggings { inner } => inner, + Material::IronBoots { inner } => inner, + Material::DiamondHelmet { inner } => inner, + Material::DiamondChestplate { inner } => inner, + Material::DiamondLeggings { inner } => inner, + Material::DiamondBoots { inner } => inner, + Material::GoldenHelmet { inner } => inner, + Material::GoldenChestplate { inner } => inner, + Material::GoldenLeggings { inner } => inner, + Material::GoldenBoots { inner } => inner, + Material::NetheriteHelmet { inner } => inner, + Material::NetheriteChestplate { inner } => inner, + Material::NetheriteLeggings { inner } => inner, + Material::NetheriteBoots { inner } => inner, + Material::Flint { inner } => inner, + Material::Porkchop { inner } => inner, + Material::CookedPorkchop { inner } => inner, + Material::Painting { inner } => inner, + Material::GoldenApple { inner } => inner, + Material::EnchantedGoldenApple { inner } => inner, + Material::OakSign { inner } => inner, + Material::SpruceSign { inner } => inner, + Material::BirchSign { inner } => inner, + Material::JungleSign { inner } => inner, + Material::AcaciaSign { inner } => inner, + Material::CherrySign { inner } => inner, + Material::DarkOakSign { inner } => inner, + Material::MangroveSign { inner } => inner, + Material::BambooSign { inner } => inner, + Material::CrimsonSign { inner } => inner, + Material::WarpedSign { inner } => inner, + Material::OakHangingSign { inner } => inner, + Material::SpruceHangingSign { inner } => inner, + Material::BirchHangingSign { inner } => inner, + Material::JungleHangingSign { inner } => inner, + Material::AcaciaHangingSign { inner } => inner, + Material::CherryHangingSign { inner } => inner, + Material::DarkOakHangingSign { inner } => inner, + Material::MangroveHangingSign { inner } => inner, + Material::BambooHangingSign { inner } => inner, + Material::CrimsonHangingSign { inner } => inner, + Material::WarpedHangingSign { inner } => inner, + Material::Bucket { inner } => inner, + Material::WaterBucket { inner } => inner, + Material::LavaBucket { inner } => inner, + Material::PowderSnowBucket { inner } => inner, + Material::Snowball { inner } => inner, + Material::Leather { inner } => inner, + Material::MilkBucket { inner } => inner, + Material::PufferfishBucket { inner } => inner, + Material::SalmonBucket { inner } => inner, + Material::CodBucket { inner } => inner, + Material::TropicalFishBucket { inner } => inner, + Material::AxolotlBucket { inner } => inner, + Material::TadpoleBucket { inner } => inner, + Material::Brick { inner } => inner, + Material::ClayBall { inner } => inner, + Material::DriedKelpBlock { inner } => inner, + Material::Paper { inner } => inner, + Material::Book { inner } => inner, + Material::SlimeBall { inner } => inner, + Material::Egg { inner } => inner, + Material::Compass { inner } => inner, + Material::RecoveryCompass { inner } => inner, + Material::Bundle { inner } => inner, + Material::FishingRod { inner } => inner, + Material::Clock { inner } => inner, + Material::Spyglass { inner } => inner, + Material::GlowstoneDust { inner } => inner, + Material::Cod { inner } => inner, + Material::Salmon { inner } => inner, + Material::TropicalFish { inner } => inner, + Material::Pufferfish { inner } => inner, + Material::CookedCod { inner } => inner, + Material::CookedSalmon { inner } => inner, + Material::InkSac { inner } => inner, + Material::GlowInkSac { inner } => inner, + Material::CocoaBeans { inner } => inner, + Material::WhiteDye { inner } => inner, + Material::OrangeDye { inner } => inner, + Material::MagentaDye { inner } => inner, + Material::LightBlueDye { inner } => inner, + Material::YellowDye { inner } => inner, + Material::LimeDye { inner } => inner, + Material::PinkDye { inner } => inner, + Material::GrayDye { inner } => inner, + Material::LightGrayDye { inner } => inner, + Material::CyanDye { inner } => inner, + Material::PurpleDye { inner } => inner, + Material::BlueDye { inner } => inner, + Material::BrownDye { inner } => inner, + Material::GreenDye { inner } => inner, + Material::RedDye { inner } => inner, + Material::BlackDye { inner } => inner, + Material::BoneMeal { inner } => inner, + Material::Bone { inner } => inner, + Material::Sugar { inner } => inner, + Material::Cake { inner } => inner, + Material::WhiteBed { inner } => inner, + Material::OrangeBed { inner } => inner, + Material::MagentaBed { inner } => inner, + Material::LightBlueBed { inner } => inner, + Material::YellowBed { inner } => inner, + Material::LimeBed { inner } => inner, + Material::PinkBed { inner } => inner, + Material::GrayBed { inner } => inner, + Material::LightGrayBed { inner } => inner, + Material::CyanBed { inner } => inner, + Material::PurpleBed { inner } => inner, + Material::BlueBed { inner } => inner, + Material::BrownBed { inner } => inner, + Material::GreenBed { inner } => inner, + Material::RedBed { inner } => inner, + Material::BlackBed { inner } => inner, + Material::Cookie { inner } => inner, + Material::Crafter { inner } => inner, + Material::FilledMap { inner } => inner, + Material::Shears { inner } => inner, + Material::MelonSlice { inner } => inner, + Material::DriedKelp { inner } => inner, + Material::PumpkinSeeds { inner } => inner, + Material::MelonSeeds { inner } => inner, + Material::Beef { inner } => inner, + Material::CookedBeef { inner } => inner, + Material::Chicken { inner } => inner, + Material::CookedChicken { inner } => inner, + Material::RottenFlesh { inner } => inner, + Material::EnderPearl { inner } => inner, + Material::BlazeRod { inner } => inner, + Material::GhastTear { inner } => inner, + Material::GoldNugget { inner } => inner, + Material::NetherWart { inner } => inner, + Material::Potion { inner } => inner, + Material::GlassBottle { inner } => inner, + Material::SpiderEye { inner } => inner, + Material::FermentedSpiderEye { inner } => inner, + Material::BlazePowder { inner } => inner, + Material::MagmaCream { inner } => inner, + Material::BrewingStand { inner } => inner, + Material::Cauldron { inner } => inner, + Material::EnderEye { inner } => inner, + Material::GlisteringMelonSlice { inner } => inner, + Material::ArmadilloSpawnEgg { inner } => inner, + Material::AllaySpawnEgg { inner } => inner, + Material::AxolotlSpawnEgg { inner } => inner, + Material::BatSpawnEgg { inner } => inner, + Material::BeeSpawnEgg { inner } => inner, + Material::BlazeSpawnEgg { inner } => inner, + Material::BoggedSpawnEgg { inner } => inner, + Material::BreezeSpawnEgg { inner } => inner, + Material::CatSpawnEgg { inner } => inner, + Material::CamelSpawnEgg { inner } => inner, + Material::CaveSpiderSpawnEgg { inner } => inner, + Material::ChickenSpawnEgg { inner } => inner, + Material::CodSpawnEgg { inner } => inner, + Material::CowSpawnEgg { inner } => inner, + Material::CreeperSpawnEgg { inner } => inner, + Material::DolphinSpawnEgg { inner } => inner, + Material::DonkeySpawnEgg { inner } => inner, + Material::DrownedSpawnEgg { inner } => inner, + Material::ElderGuardianSpawnEgg { inner } => inner, + Material::EnderDragonSpawnEgg { inner } => inner, + Material::EndermanSpawnEgg { inner } => inner, + Material::EndermiteSpawnEgg { inner } => inner, + Material::EvokerSpawnEgg { inner } => inner, + Material::FoxSpawnEgg { inner } => inner, + Material::FrogSpawnEgg { inner } => inner, + Material::GhastSpawnEgg { inner } => inner, + Material::GlowSquidSpawnEgg { inner } => inner, + Material::GoatSpawnEgg { inner } => inner, + Material::GuardianSpawnEgg { inner } => inner, + Material::HoglinSpawnEgg { inner } => inner, + Material::HorseSpawnEgg { inner } => inner, + Material::HuskSpawnEgg { inner } => inner, + Material::IronGolemSpawnEgg { inner } => inner, + Material::LlamaSpawnEgg { inner } => inner, + Material::MagmaCubeSpawnEgg { inner } => inner, + Material::MooshroomSpawnEgg { inner } => inner, + Material::MuleSpawnEgg { inner } => inner, + Material::OcelotSpawnEgg { inner } => inner, + Material::PandaSpawnEgg { inner } => inner, + Material::ParrotSpawnEgg { inner } => inner, + Material::PhantomSpawnEgg { inner } => inner, + Material::PigSpawnEgg { inner } => inner, + Material::PiglinSpawnEgg { inner } => inner, + Material::PiglinBruteSpawnEgg { inner } => inner, + Material::PillagerSpawnEgg { inner } => inner, + Material::PolarBearSpawnEgg { inner } => inner, + Material::PufferfishSpawnEgg { inner } => inner, + Material::RabbitSpawnEgg { inner } => inner, + Material::RavagerSpawnEgg { inner } => inner, + Material::SalmonSpawnEgg { inner } => inner, + Material::SheepSpawnEgg { inner } => inner, + Material::ShulkerSpawnEgg { inner } => inner, + Material::SilverfishSpawnEgg { inner } => inner, + Material::SkeletonSpawnEgg { inner } => inner, + Material::SkeletonHorseSpawnEgg { inner } => inner, + Material::SlimeSpawnEgg { inner } => inner, + Material::SnifferSpawnEgg { inner } => inner, + Material::SnowGolemSpawnEgg { inner } => inner, + Material::SpiderSpawnEgg { inner } => inner, + Material::SquidSpawnEgg { inner } => inner, + Material::StraySpawnEgg { inner } => inner, + Material::StriderSpawnEgg { inner } => inner, + Material::TadpoleSpawnEgg { inner } => inner, + Material::TraderLlamaSpawnEgg { inner } => inner, + Material::TropicalFishSpawnEgg { inner } => inner, + Material::TurtleSpawnEgg { inner } => inner, + Material::VexSpawnEgg { inner } => inner, + Material::VillagerSpawnEgg { inner } => inner, + Material::VindicatorSpawnEgg { inner } => inner, + Material::WanderingTraderSpawnEgg { inner } => inner, + Material::WardenSpawnEgg { inner } => inner, + Material::WitchSpawnEgg { inner } => inner, + Material::WitherSpawnEgg { inner } => inner, + Material::WitherSkeletonSpawnEgg { inner } => inner, + Material::WolfSpawnEgg { inner } => inner, + Material::ZoglinSpawnEgg { inner } => inner, + Material::ZombieSpawnEgg { inner } => inner, + Material::ZombieHorseSpawnEgg { inner } => inner, + Material::ZombieVillagerSpawnEgg { inner } => inner, + Material::ZombifiedPiglinSpawnEgg { inner } => inner, + Material::ExperienceBottle { inner } => inner, + Material::FireCharge { inner } => inner, + Material::WindCharge { inner } => inner, + Material::WritableBook { inner } => inner, + Material::WrittenBook { inner } => inner, + Material::Mace { inner } => inner, + Material::ItemFrame { inner } => inner, + Material::GlowItemFrame { inner } => inner, + Material::FlowerPot { inner } => inner, + Material::Carrot { inner } => inner, + Material::Potato { inner } => inner, + Material::BakedPotato { inner } => inner, + Material::PoisonousPotato { inner } => inner, + Material::Map { inner } => inner, + Material::GoldenCarrot { inner } => inner, + Material::SkeletonSkull { inner } => inner, + Material::WitherSkeletonSkull { inner } => inner, + Material::PlayerHead { inner } => inner, + Material::ZombieHead { inner } => inner, + Material::CreeperHead { inner } => inner, + Material::DragonHead { inner } => inner, + Material::PiglinHead { inner } => inner, + Material::NetherStar { inner } => inner, + Material::PumpkinPie { inner } => inner, + Material::FireworkRocket { inner } => inner, + Material::FireworkStar { inner } => inner, + Material::EnchantedBook { inner } => inner, + Material::NetherBrick { inner } => inner, + Material::PrismarineShard { inner } => inner, + Material::PrismarineCrystals { inner } => inner, + Material::Rabbit { inner } => inner, + Material::CookedRabbit { inner } => inner, + Material::RabbitStew { inner } => inner, + Material::RabbitFoot { inner } => inner, + Material::RabbitHide { inner } => inner, + Material::ArmorStand { inner } => inner, + Material::IronHorseArmor { inner } => inner, + Material::GoldenHorseArmor { inner } => inner, + Material::DiamondHorseArmor { inner } => inner, + Material::LeatherHorseArmor { inner } => inner, + Material::Lead { inner } => inner, + Material::NameTag { inner } => inner, + Material::CommandBlockMinecart { inner } => inner, + Material::Mutton { inner } => inner, + Material::CookedMutton { inner } => inner, + Material::WhiteBanner { inner } => inner, + Material::OrangeBanner { inner } => inner, + Material::MagentaBanner { inner } => inner, + Material::LightBlueBanner { inner } => inner, + Material::YellowBanner { inner } => inner, + Material::LimeBanner { inner } => inner, + Material::PinkBanner { inner } => inner, + Material::GrayBanner { inner } => inner, + Material::LightGrayBanner { inner } => inner, + Material::CyanBanner { inner } => inner, + Material::PurpleBanner { inner } => inner, + Material::BlueBanner { inner } => inner, + Material::BrownBanner { inner } => inner, + Material::GreenBanner { inner } => inner, + Material::RedBanner { inner } => inner, + Material::BlackBanner { inner } => inner, + Material::EndCrystal { inner } => inner, + Material::ChorusFruit { inner } => inner, + Material::PoppedChorusFruit { inner } => inner, + Material::TorchflowerSeeds { inner } => inner, + Material::PitcherPod { inner } => inner, + Material::Beetroot { inner } => inner, + Material::BeetrootSeeds { inner } => inner, + Material::BeetrootSoup { inner } => inner, + Material::DragonBreath { inner } => inner, + Material::SplashPotion { inner } => inner, + Material::SpectralArrow { inner } => inner, + Material::TippedArrow { inner } => inner, + Material::LingeringPotion { inner } => inner, + Material::Shield { inner } => inner, + Material::TotemOfUndying { inner } => inner, + Material::ShulkerShell { inner } => inner, + Material::IronNugget { inner } => inner, + Material::KnowledgeBook { inner } => inner, + Material::DebugStick { inner } => inner, + Material::MusicDisc13 { inner } => inner, + Material::MusicDiscCat { inner } => inner, + Material::MusicDiscBlocks { inner } => inner, + Material::MusicDiscChirp { inner } => inner, + Material::MusicDiscCreator { inner } => inner, + Material::MusicDiscCreatorMusicBox { inner } => inner, + Material::MusicDiscFar { inner } => inner, + Material::MusicDiscMall { inner } => inner, + Material::MusicDiscMellohi { inner } => inner, + Material::MusicDiscStal { inner } => inner, + Material::MusicDiscStrad { inner } => inner, + Material::MusicDiscWard { inner } => inner, + Material::MusicDisc11 { inner } => inner, + Material::MusicDiscWait { inner } => inner, + Material::MusicDiscOtherside { inner } => inner, + Material::MusicDiscRelic { inner } => inner, + Material::MusicDisc5 { inner } => inner, + Material::MusicDiscPigstep { inner } => inner, + Material::MusicDiscPrecipice { inner } => inner, + Material::DiscFragment5 { inner } => inner, + Material::Trident { inner } => inner, + Material::PhantomMembrane { inner } => inner, + Material::NautilusShell { inner } => inner, + Material::HeartOfTheSea { inner } => inner, + Material::Crossbow { inner } => inner, + Material::SuspiciousStew { inner } => inner, + Material::Loom { inner } => inner, + Material::FlowerBannerPattern { inner } => inner, + Material::CreeperBannerPattern { inner } => inner, + Material::SkullBannerPattern { inner } => inner, + Material::MojangBannerPattern { inner } => inner, + Material::GlobeBannerPattern { inner } => inner, + Material::PiglinBannerPattern { inner } => inner, + Material::FlowBannerPattern { inner } => inner, + Material::GusterBannerPattern { inner } => inner, + Material::GoatHorn { inner } => inner, + Material::Composter { inner } => inner, + Material::Barrel { inner } => inner, + Material::Smoker { inner } => inner, + Material::BlastFurnace { inner } => inner, + Material::CartographyTable { inner } => inner, + Material::FletchingTable { inner } => inner, + Material::Grindstone { inner } => inner, + Material::SmithingTable { inner } => inner, + Material::Stonecutter { inner } => inner, + Material::Bell { inner } => inner, + Material::Lantern { inner } => inner, + Material::SoulLantern { inner } => inner, + Material::SweetBerries { inner } => inner, + Material::GlowBerries { inner } => inner, + Material::Campfire { inner } => inner, + Material::SoulCampfire { inner } => inner, + Material::Shroomlight { inner } => inner, + Material::Honeycomb { inner } => inner, + Material::BeeNest { inner } => inner, + Material::Beehive { inner } => inner, + Material::HoneyBottle { inner } => inner, + Material::HoneycombBlock { inner } => inner, + Material::Lodestone { inner } => inner, + Material::CryingObsidian { inner } => inner, + Material::Blackstone { inner } => inner, + Material::BlackstoneSlab { inner } => inner, + Material::BlackstoneStairs { inner } => inner, + Material::GildedBlackstone { inner } => inner, + Material::PolishedBlackstone { inner } => inner, + Material::PolishedBlackstoneSlab { inner } => inner, + Material::PolishedBlackstoneStairs { inner } => inner, + Material::ChiseledPolishedBlackstone { inner } => inner, + Material::PolishedBlackstoneBricks { inner } => inner, + Material::PolishedBlackstoneBrickSlab { inner } => inner, + Material::PolishedBlackstoneBrickStairs { inner } => inner, + Material::CrackedPolishedBlackstoneBricks { inner } => inner, + Material::RespawnAnchor { inner } => inner, + Material::Candle { inner } => inner, + Material::WhiteCandle { inner } => inner, + Material::OrangeCandle { inner } => inner, + Material::MagentaCandle { inner } => inner, + Material::LightBlueCandle { inner } => inner, + Material::YellowCandle { inner } => inner, + Material::LimeCandle { inner } => inner, + Material::PinkCandle { inner } => inner, + Material::GrayCandle { inner } => inner, + Material::LightGrayCandle { inner } => inner, + Material::CyanCandle { inner } => inner, + Material::PurpleCandle { inner } => inner, + Material::BlueCandle { inner } => inner, + Material::BrownCandle { inner } => inner, + Material::GreenCandle { inner } => inner, + Material::RedCandle { inner } => inner, + Material::BlackCandle { inner } => inner, + Material::SmallAmethystBud { inner } => inner, + Material::MediumAmethystBud { inner } => inner, + Material::LargeAmethystBud { inner } => inner, + Material::AmethystCluster { inner } => inner, + Material::PointedDripstone { inner } => inner, + Material::OchreFroglight { inner } => inner, + Material::VerdantFroglight { inner } => inner, + Material::PearlescentFroglight { inner } => inner, + Material::Frogspawn { inner } => inner, + Material::EchoShard { inner } => inner, + Material::Brush { inner } => inner, + Material::NetheriteUpgradeSmithingTemplate { inner } => inner, + Material::SentryArmorTrimSmithingTemplate { inner } => inner, + Material::DuneArmorTrimSmithingTemplate { inner } => inner, + Material::CoastArmorTrimSmithingTemplate { inner } => inner, + Material::WildArmorTrimSmithingTemplate { inner } => inner, + Material::WardArmorTrimSmithingTemplate { inner } => inner, + Material::EyeArmorTrimSmithingTemplate { inner } => inner, + Material::VexArmorTrimSmithingTemplate { inner } => inner, + Material::TideArmorTrimSmithingTemplate { inner } => inner, + Material::SnoutArmorTrimSmithingTemplate { inner } => inner, + Material::RibArmorTrimSmithingTemplate { inner } => inner, + Material::SpireArmorTrimSmithingTemplate { inner } => inner, + Material::WayfinderArmorTrimSmithingTemplate { inner } => inner, + Material::ShaperArmorTrimSmithingTemplate { inner } => inner, + Material::SilenceArmorTrimSmithingTemplate { inner } => inner, + Material::RaiserArmorTrimSmithingTemplate { inner } => inner, + Material::HostArmorTrimSmithingTemplate { inner } => inner, + Material::FlowArmorTrimSmithingTemplate { inner } => inner, + Material::BoltArmorTrimSmithingTemplate { inner } => inner, + Material::AnglerPotterySherd { inner } => inner, + Material::ArcherPotterySherd { inner } => inner, + Material::ArmsUpPotterySherd { inner } => inner, + Material::BladePotterySherd { inner } => inner, + Material::BrewerPotterySherd { inner } => inner, + Material::BurnPotterySherd { inner } => inner, + Material::DangerPotterySherd { inner } => inner, + Material::ExplorerPotterySherd { inner } => inner, + Material::FlowPotterySherd { inner } => inner, + Material::FriendPotterySherd { inner } => inner, + Material::GusterPotterySherd { inner } => inner, + Material::HeartPotterySherd { inner } => inner, + Material::HeartbreakPotterySherd { inner } => inner, + Material::HowlPotterySherd { inner } => inner, + Material::MinerPotterySherd { inner } => inner, + Material::MournerPotterySherd { inner } => inner, + Material::PlentyPotterySherd { inner } => inner, + Material::PrizePotterySherd { inner } => inner, + Material::ScrapePotterySherd { inner } => inner, + Material::SheafPotterySherd { inner } => inner, + Material::ShelterPotterySherd { inner } => inner, + Material::SkullPotterySherd { inner } => inner, + Material::SnortPotterySherd { inner } => inner, + Material::CopperGrate { inner } => inner, + Material::ExposedCopperGrate { inner } => inner, + Material::WeatheredCopperGrate { inner } => inner, + Material::OxidizedCopperGrate { inner } => inner, + Material::WaxedCopperGrate { inner } => inner, + Material::WaxedExposedCopperGrate { inner } => inner, + Material::WaxedWeatheredCopperGrate { inner } => inner, + Material::WaxedOxidizedCopperGrate { inner } => inner, + Material::CopperBulb { inner } => inner, + Material::ExposedCopperBulb { inner } => inner, + Material::WeatheredCopperBulb { inner } => inner, + Material::OxidizedCopperBulb { inner } => inner, + Material::WaxedCopperBulb { inner } => inner, + Material::WaxedExposedCopperBulb { inner } => inner, + Material::WaxedWeatheredCopperBulb { inner } => inner, + Material::WaxedOxidizedCopperBulb { inner } => inner, + Material::TrialSpawner { inner } => inner, + Material::TrialKey { inner } => inner, + Material::OminousTrialKey { inner } => inner, + Material::Vault { inner } => inner, + Material::OminousBottle { inner } => inner, + Material::BreezeRod { inner } => inner, + Material::Water { inner } => inner, + Material::Lava { inner } => inner, + Material::TallSeagrass { inner } => inner, + Material::PistonHead { inner } => inner, + Material::MovingPiston { inner } => inner, + Material::WallTorch { inner } => inner, + Material::Fire { inner } => inner, + Material::SoulFire { inner } => inner, + Material::RedstoneWire { inner } => inner, + Material::OakWallSign { inner } => inner, + Material::SpruceWallSign { inner } => inner, + Material::BirchWallSign { inner } => inner, + Material::AcaciaWallSign { inner } => inner, + Material::CherryWallSign { inner } => inner, + Material::JungleWallSign { inner } => inner, + Material::DarkOakWallSign { inner } => inner, + Material::MangroveWallSign { inner } => inner, + Material::BambooWallSign { inner } => inner, + Material::OakWallHangingSign { inner } => inner, + Material::SpruceWallHangingSign { inner } => inner, + Material::BirchWallHangingSign { inner } => inner, + Material::AcaciaWallHangingSign { inner } => inner, + Material::CherryWallHangingSign { inner } => inner, + Material::JungleWallHangingSign { inner } => inner, + Material::DarkOakWallHangingSign { inner } => inner, + Material::MangroveWallHangingSign { inner } => inner, + Material::CrimsonWallHangingSign { inner } => inner, + Material::WarpedWallHangingSign { inner } => inner, + Material::BambooWallHangingSign { inner } => inner, + Material::RedstoneWallTorch { inner } => inner, + Material::SoulWallTorch { inner } => inner, + Material::NetherPortal { inner } => inner, + Material::AttachedPumpkinStem { inner } => inner, + Material::AttachedMelonStem { inner } => inner, + Material::PumpkinStem { inner } => inner, + Material::MelonStem { inner } => inner, + Material::WaterCauldron { inner } => inner, + Material::LavaCauldron { inner } => inner, + Material::PowderSnowCauldron { inner } => inner, + Material::EndPortal { inner } => inner, + Material::Cocoa { inner } => inner, + Material::Tripwire { inner } => inner, + Material::PottedTorchflower { inner } => inner, + Material::PottedOakSapling { inner } => inner, + Material::PottedSpruceSapling { inner } => inner, + Material::PottedBirchSapling { inner } => inner, + Material::PottedJungleSapling { inner } => inner, + Material::PottedAcaciaSapling { inner } => inner, + Material::PottedCherrySapling { inner } => inner, + Material::PottedDarkOakSapling { inner } => inner, + Material::PottedMangrovePropagule { inner } => inner, + Material::PottedFern { inner } => inner, + Material::PottedDandelion { inner } => inner, + Material::PottedPoppy { inner } => inner, + Material::PottedBlueOrchid { inner } => inner, + Material::PottedAllium { inner } => inner, + Material::PottedAzureBluet { inner } => inner, + Material::PottedRedTulip { inner } => inner, + Material::PottedOrangeTulip { inner } => inner, + Material::PottedWhiteTulip { inner } => inner, + Material::PottedPinkTulip { inner } => inner, + Material::PottedOxeyeDaisy { inner } => inner, + Material::PottedCornflower { inner } => inner, + Material::PottedLilyOfTheValley { inner } => inner, + Material::PottedWitherRose { inner } => inner, + Material::PottedRedMushroom { inner } => inner, + Material::PottedBrownMushroom { inner } => inner, + Material::PottedDeadBush { inner } => inner, + Material::PottedCactus { inner } => inner, + Material::Carrots { inner } => inner, + Material::Potatoes { inner } => inner, + Material::SkeletonWallSkull { inner } => inner, + Material::WitherSkeletonWallSkull { inner } => inner, + Material::ZombieWallHead { inner } => inner, + Material::PlayerWallHead { inner } => inner, + Material::CreeperWallHead { inner } => inner, + Material::DragonWallHead { inner } => inner, + Material::PiglinWallHead { inner } => inner, + Material::WhiteWallBanner { inner } => inner, + Material::OrangeWallBanner { inner } => inner, + Material::MagentaWallBanner { inner } => inner, + Material::LightBlueWallBanner { inner } => inner, + Material::YellowWallBanner { inner } => inner, + Material::LimeWallBanner { inner } => inner, + Material::PinkWallBanner { inner } => inner, + Material::GrayWallBanner { inner } => inner, + Material::LightGrayWallBanner { inner } => inner, + Material::CyanWallBanner { inner } => inner, + Material::PurpleWallBanner { inner } => inner, + Material::BlueWallBanner { inner } => inner, + Material::BrownWallBanner { inner } => inner, + Material::GreenWallBanner { inner } => inner, + Material::RedWallBanner { inner } => inner, + Material::BlackWallBanner { inner } => inner, + Material::TorchflowerCrop { inner } => inner, + Material::PitcherCrop { inner } => inner, + Material::Beetroots { inner } => inner, + Material::EndGateway { inner } => inner, + Material::FrostedIce { inner } => inner, + Material::KelpPlant { inner } => inner, + Material::DeadTubeCoralWallFan { inner } => inner, + Material::DeadBrainCoralWallFan { inner } => inner, + Material::DeadBubbleCoralWallFan { inner } => inner, + Material::DeadFireCoralWallFan { inner } => inner, + Material::DeadHornCoralWallFan { inner } => inner, + Material::TubeCoralWallFan { inner } => inner, + Material::BrainCoralWallFan { inner } => inner, + Material::BubbleCoralWallFan { inner } => inner, + Material::FireCoralWallFan { inner } => inner, + Material::HornCoralWallFan { inner } => inner, + Material::BambooSapling { inner } => inner, + Material::PottedBamboo { inner } => inner, + Material::VoidAir { inner } => inner, + Material::CaveAir { inner } => inner, + Material::BubbleColumn { inner } => inner, + Material::SweetBerryBush { inner } => inner, + Material::WeepingVinesPlant { inner } => inner, + Material::TwistingVinesPlant { inner } => inner, + Material::CrimsonWallSign { inner } => inner, + Material::WarpedWallSign { inner } => inner, + Material::PottedCrimsonFungus { inner } => inner, + Material::PottedWarpedFungus { inner } => inner, + Material::PottedCrimsonRoots { inner } => inner, + Material::PottedWarpedRoots { inner } => inner, + Material::CandleCake { inner } => inner, + Material::WhiteCandleCake { inner } => inner, + Material::OrangeCandleCake { inner } => inner, + Material::MagentaCandleCake { inner } => inner, + Material::LightBlueCandleCake { inner } => inner, + Material::YellowCandleCake { inner } => inner, + Material::LimeCandleCake { inner } => inner, + Material::PinkCandleCake { inner } => inner, + Material::GrayCandleCake { inner } => inner, + Material::LightGrayCandleCake { inner } => inner, + Material::CyanCandleCake { inner } => inner, + Material::PurpleCandleCake { inner } => inner, + Material::BlueCandleCake { inner } => inner, + Material::BrownCandleCake { inner } => inner, + Material::GreenCandleCake { inner } => inner, + Material::RedCandleCake { inner } => inner, + Material::BlackCandleCake { inner } => inner, + Material::PowderSnow { inner } => inner, + Material::CaveVines { inner } => inner, + Material::CaveVinesPlant { inner } => inner, + Material::BigDripleafStem { inner } => inner, + Material::PottedAzaleaBush { inner } => inner, + Material::PottedFloweringAzaleaBush { inner } => inner, + Material::LegacyAir { inner } => inner, + Material::LegacyStone { inner } => inner, + Material::LegacyGrass { inner } => inner, + Material::LegacyDirt { inner } => inner, + Material::LegacyCobblestone { inner } => inner, + Material::LegacyWood { inner } => inner, + Material::LegacySapling { inner } => inner, + Material::LegacyBedrock { inner } => inner, + Material::LegacyWater { inner } => inner, + Material::LegacyStationaryWater { inner } => inner, + Material::LegacyLava { inner } => inner, + Material::LegacyStationaryLava { inner } => inner, + Material::LegacySand { inner } => inner, + Material::LegacyGravel { inner } => inner, + Material::LegacyGoldOre { inner } => inner, + Material::LegacyIronOre { inner } => inner, + Material::LegacyCoalOre { inner } => inner, + Material::LegacyLog { inner } => inner, + Material::LegacyLeaves { inner } => inner, + Material::LegacySponge { inner } => inner, + Material::LegacyGlass { inner } => inner, + Material::LegacyLapisOre { inner } => inner, + Material::LegacyLapisBlock { inner } => inner, + Material::LegacyDispenser { inner } => inner, + Material::LegacySandstone { inner } => inner, + Material::LegacyNoteBlock { inner } => inner, + Material::LegacyBedBlock { inner } => inner, + Material::LegacyPoweredRail { inner } => inner, + Material::LegacyDetectorRail { inner } => inner, + Material::LegacyPistonStickyBase { inner } => inner, + Material::LegacyWeb { inner } => inner, + Material::LegacyLongGrass { inner } => inner, + Material::LegacyDeadBush { inner } => inner, + Material::LegacyPistonBase { inner } => inner, + Material::LegacyPistonExtension { inner } => inner, + Material::LegacyWool { inner } => inner, + Material::LegacyPistonMovingPiece { inner } => inner, + Material::LegacyYellowFlower { inner } => inner, + Material::LegacyRedRose { inner } => inner, + Material::LegacyBrownMushroom { inner } => inner, + Material::LegacyRedMushroom { inner } => inner, + Material::LegacyGoldBlock { inner } => inner, + Material::LegacyIronBlock { inner } => inner, + Material::LegacyDoubleStep { inner } => inner, + Material::LegacyStep { inner } => inner, + Material::LegacyBrick { inner } => inner, + Material::LegacyTnt { inner } => inner, + Material::LegacyBookshelf { inner } => inner, + Material::LegacyMossyCobblestone { inner } => inner, + Material::LegacyObsidian { inner } => inner, + Material::LegacyTorch { inner } => inner, + Material::LegacyFire { inner } => inner, + Material::LegacyMobSpawner { inner } => inner, + Material::LegacyWoodStairs { inner } => inner, + Material::LegacyChest { inner } => inner, + Material::LegacyRedstoneWire { inner } => inner, + Material::LegacyDiamondOre { inner } => inner, + Material::LegacyDiamondBlock { inner } => inner, + Material::LegacyWorkbench { inner } => inner, + Material::LegacyCrops { inner } => inner, + Material::LegacySoil { inner } => inner, + Material::LegacyFurnace { inner } => inner, + Material::LegacyBurningFurnace { inner } => inner, + Material::LegacySignPost { inner } => inner, + Material::LegacyWoodenDoor { inner } => inner, + Material::LegacyLadder { inner } => inner, + Material::LegacyRails { inner } => inner, + Material::LegacyCobblestoneStairs { inner } => inner, + Material::LegacyWallSign { inner } => inner, + Material::LegacyLever { inner } => inner, + Material::LegacyStonePlate { inner } => inner, + Material::LegacyIronDoorBlock { inner } => inner, + Material::LegacyWoodPlate { inner } => inner, + Material::LegacyRedstoneOre { inner } => inner, + Material::LegacyGlowingRedstoneOre { inner } => inner, + Material::LegacyRedstoneTorchOff { inner } => inner, + Material::LegacyRedstoneTorchOn { inner } => inner, + Material::LegacyStoneButton { inner } => inner, + Material::LegacySnow { inner } => inner, + Material::LegacyIce { inner } => inner, + Material::LegacySnowBlock { inner } => inner, + Material::LegacyCactus { inner } => inner, + Material::LegacyClay { inner } => inner, + Material::LegacySugarCaneBlock { inner } => inner, + Material::LegacyJukebox { inner } => inner, + Material::LegacyFence { inner } => inner, + Material::LegacyPumpkin { inner } => inner, + Material::LegacyNetherrack { inner } => inner, + Material::LegacySoulSand { inner } => inner, + Material::LegacyGlowstone { inner } => inner, + Material::LegacyPortal { inner } => inner, + Material::LegacyJackOLantern { inner } => inner, + Material::LegacyCakeBlock { inner } => inner, + Material::LegacyDiodeBlockOff { inner } => inner, + Material::LegacyDiodeBlockOn { inner } => inner, + Material::LegacyStainedGlass { inner } => inner, + Material::LegacyTrapDoor { inner } => inner, + Material::LegacyMonsterEggs { inner } => inner, + Material::LegacySmoothBrick { inner } => inner, + Material::LegacyHugeMushroom1 { inner } => inner, + Material::LegacyHugeMushroom2 { inner } => inner, + Material::LegacyIronFence { inner } => inner, + Material::LegacyThinGlass { inner } => inner, + Material::LegacyMelonBlock { inner } => inner, + Material::LegacyPumpkinStem { inner } => inner, + Material::LegacyMelonStem { inner } => inner, + Material::LegacyVine { inner } => inner, + Material::LegacyFenceGate { inner } => inner, + Material::LegacyBrickStairs { inner } => inner, + Material::LegacySmoothStairs { inner } => inner, + Material::LegacyMycel { inner } => inner, + Material::LegacyWaterLily { inner } => inner, + Material::LegacyNetherBrick { inner } => inner, + Material::LegacyNetherFence { inner } => inner, + Material::LegacyNetherBrickStairs { inner } => inner, + Material::LegacyNetherWarts { inner } => inner, + Material::LegacyEnchantmentTable { inner } => inner, + Material::LegacyBrewingStand { inner } => inner, + Material::LegacyCauldron { inner } => inner, + Material::LegacyEnderPortal { inner } => inner, + Material::LegacyEnderPortalFrame { inner } => inner, + Material::LegacyEnderStone { inner } => inner, + Material::LegacyDragonEgg { inner } => inner, + Material::LegacyRedstoneLampOff { inner } => inner, + Material::LegacyRedstoneLampOn { inner } => inner, + Material::LegacyWoodDoubleStep { inner } => inner, + Material::LegacyWoodStep { inner } => inner, + Material::LegacyCocoa { inner } => inner, + Material::LegacySandstoneStairs { inner } => inner, + Material::LegacyEmeraldOre { inner } => inner, + Material::LegacyEnderChest { inner } => inner, + Material::LegacyTripwireHook { inner } => inner, + Material::LegacyTripwire { inner } => inner, + Material::LegacyEmeraldBlock { inner } => inner, + Material::LegacySpruceWoodStairs { inner } => inner, + Material::LegacyBirchWoodStairs { inner } => inner, + Material::LegacyJungleWoodStairs { inner } => inner, + Material::LegacyCommand { inner } => inner, + Material::LegacyBeacon { inner } => inner, + Material::LegacyCobbleWall { inner } => inner, + Material::LegacyFlowerPot { inner } => inner, + Material::LegacyCarrot { inner } => inner, + Material::LegacyPotato { inner } => inner, + Material::LegacyWoodButton { inner } => inner, + Material::LegacySkull { inner } => inner, + Material::LegacyAnvil { inner } => inner, + Material::LegacyTrappedChest { inner } => inner, + Material::LegacyGoldPlate { inner } => inner, + Material::LegacyIronPlate { inner } => inner, + Material::LegacyRedstoneComparatorOff { inner } => inner, + Material::LegacyRedstoneComparatorOn { inner } => inner, + Material::LegacyDaylightDetector { inner } => inner, + Material::LegacyRedstoneBlock { inner } => inner, + Material::LegacyQuartzOre { inner } => inner, + Material::LegacyHopper { inner } => inner, + Material::LegacyQuartzBlock { inner } => inner, + Material::LegacyQuartzStairs { inner } => inner, + Material::LegacyActivatorRail { inner } => inner, + Material::LegacyDropper { inner } => inner, + Material::LegacyStainedClay { inner } => inner, + Material::LegacyStainedGlassPane { inner } => inner, + Material::LegacyLeaves2 { inner } => inner, + Material::LegacyLog2 { inner } => inner, + Material::LegacyAcaciaStairs { inner } => inner, + Material::LegacyDarkOakStairs { inner } => inner, + Material::LegacySlimeBlock { inner } => inner, + Material::LegacyBarrier { inner } => inner, + Material::LegacyIronTrapdoor { inner } => inner, + Material::LegacyPrismarine { inner } => inner, + Material::LegacySeaLantern { inner } => inner, + Material::LegacyHayBlock { inner } => inner, + Material::LegacyCarpet { inner } => inner, + Material::LegacyHardClay { inner } => inner, + Material::LegacyCoalBlock { inner } => inner, + Material::LegacyPackedIce { inner } => inner, + Material::LegacyDoublePlant { inner } => inner, + Material::LegacyStandingBanner { inner } => inner, + Material::LegacyWallBanner { inner } => inner, + Material::LegacyDaylightDetectorInverted { inner } => inner, + Material::LegacyRedSandstone { inner } => inner, + Material::LegacyRedSandstoneStairs { inner } => inner, + Material::LegacyDoubleStoneSlab2 { inner } => inner, + Material::LegacyStoneSlab2 { inner } => inner, + Material::LegacySpruceFenceGate { inner } => inner, + Material::LegacyBirchFenceGate { inner } => inner, + Material::LegacyJungleFenceGate { inner } => inner, + Material::LegacyDarkOakFenceGate { inner } => inner, + Material::LegacyAcaciaFenceGate { inner } => inner, + Material::LegacySpruceFence { inner } => inner, + Material::LegacyBirchFence { inner } => inner, + Material::LegacyJungleFence { inner } => inner, + Material::LegacyDarkOakFence { inner } => inner, + Material::LegacyAcaciaFence { inner } => inner, + Material::LegacySpruceDoor { inner } => inner, + Material::LegacyBirchDoor { inner } => inner, + Material::LegacyJungleDoor { inner } => inner, + Material::LegacyAcaciaDoor { inner } => inner, + Material::LegacyDarkOakDoor { inner } => inner, + Material::LegacyEndRod { inner } => inner, + Material::LegacyChorusPlant { inner } => inner, + Material::LegacyChorusFlower { inner } => inner, + Material::LegacyPurpurBlock { inner } => inner, + Material::LegacyPurpurPillar { inner } => inner, + Material::LegacyPurpurStairs { inner } => inner, + Material::LegacyPurpurDoubleSlab { inner } => inner, + Material::LegacyPurpurSlab { inner } => inner, + Material::LegacyEndBricks { inner } => inner, + Material::LegacyBeetrootBlock { inner } => inner, + Material::LegacyGrassPath { inner } => inner, + Material::LegacyEndGateway { inner } => inner, + Material::LegacyCommandRepeating { inner } => inner, + Material::LegacyCommandChain { inner } => inner, + Material::LegacyFrostedIce { inner } => inner, + Material::LegacyMagma { inner } => inner, + Material::LegacyNetherWartBlock { inner } => inner, + Material::LegacyRedNetherBrick { inner } => inner, + Material::LegacyBoneBlock { inner } => inner, + Material::LegacyStructureVoid { inner } => inner, + Material::LegacyObserver { inner } => inner, + Material::LegacyWhiteShulkerBox { inner } => inner, + Material::LegacyOrangeShulkerBox { inner } => inner, + Material::LegacyMagentaShulkerBox { inner } => inner, + Material::LegacyLightBlueShulkerBox { inner } => inner, + Material::LegacyYellowShulkerBox { inner } => inner, + Material::LegacyLimeShulkerBox { inner } => inner, + Material::LegacyPinkShulkerBox { inner } => inner, + Material::LegacyGrayShulkerBox { inner } => inner, + Material::LegacySilverShulkerBox { inner } => inner, + Material::LegacyCyanShulkerBox { inner } => inner, + Material::LegacyPurpleShulkerBox { inner } => inner, + Material::LegacyBlueShulkerBox { inner } => inner, + Material::LegacyBrownShulkerBox { inner } => inner, + Material::LegacyGreenShulkerBox { inner } => inner, + Material::LegacyRedShulkerBox { inner } => inner, + Material::LegacyBlackShulkerBox { inner } => inner, + Material::LegacyWhiteGlazedTerracotta { inner } => inner, + Material::LegacyOrangeGlazedTerracotta { inner } => inner, + Material::LegacyMagentaGlazedTerracotta { inner } => inner, + Material::LegacyLightBlueGlazedTerracotta { inner } => inner, + Material::LegacyYellowGlazedTerracotta { inner } => inner, + Material::LegacyLimeGlazedTerracotta { inner } => inner, + Material::LegacyPinkGlazedTerracotta { inner } => inner, + Material::LegacyGrayGlazedTerracotta { inner } => inner, + Material::LegacySilverGlazedTerracotta { inner } => inner, + Material::LegacyCyanGlazedTerracotta { inner } => inner, + Material::LegacyPurpleGlazedTerracotta { inner } => inner, + Material::LegacyBlueGlazedTerracotta { inner } => inner, + Material::LegacyBrownGlazedTerracotta { inner } => inner, + Material::LegacyGreenGlazedTerracotta { inner } => inner, + Material::LegacyRedGlazedTerracotta { inner } => inner, + Material::LegacyBlackGlazedTerracotta { inner } => inner, + Material::LegacyConcrete { inner } => inner, + Material::LegacyConcretePowder { inner } => inner, + Material::LegacyStructureBlock { inner } => inner, + Material::LegacyIronSpade { inner } => inner, + Material::LegacyIronPickaxe { inner } => inner, + Material::LegacyIronAxe { inner } => inner, + Material::LegacyFlintAndSteel { inner } => inner, + Material::LegacyApple { inner } => inner, + Material::LegacyBow { inner } => inner, + Material::LegacyArrow { inner } => inner, + Material::LegacyCoal { inner } => inner, + Material::LegacyDiamond { inner } => inner, + Material::LegacyIronIngot { inner } => inner, + Material::LegacyGoldIngot { inner } => inner, + Material::LegacyIronSword { inner } => inner, + Material::LegacyWoodSword { inner } => inner, + Material::LegacyWoodSpade { inner } => inner, + Material::LegacyWoodPickaxe { inner } => inner, + Material::LegacyWoodAxe { inner } => inner, + Material::LegacyStoneSword { inner } => inner, + Material::LegacyStoneSpade { inner } => inner, + Material::LegacyStonePickaxe { inner } => inner, + Material::LegacyStoneAxe { inner } => inner, + Material::LegacyDiamondSword { inner } => inner, + Material::LegacyDiamondSpade { inner } => inner, + Material::LegacyDiamondPickaxe { inner } => inner, + Material::LegacyDiamondAxe { inner } => inner, + Material::LegacyStick { inner } => inner, + Material::LegacyBowl { inner } => inner, + Material::LegacyMushroomSoup { inner } => inner, + Material::LegacyGoldSword { inner } => inner, + Material::LegacyGoldSpade { inner } => inner, + Material::LegacyGoldPickaxe { inner } => inner, + Material::LegacyGoldAxe { inner } => inner, + Material::LegacyString { inner } => inner, + Material::LegacyFeather { inner } => inner, + Material::LegacySulphur { inner } => inner, + Material::LegacyWoodHoe { inner } => inner, + Material::LegacyStoneHoe { inner } => inner, + Material::LegacyIronHoe { inner } => inner, + Material::LegacyDiamondHoe { inner } => inner, + Material::LegacyGoldHoe { inner } => inner, + Material::LegacySeeds { inner } => inner, + Material::LegacyWheat { inner } => inner, + Material::LegacyBread { inner } => inner, + Material::LegacyLeatherHelmet { inner } => inner, + Material::LegacyLeatherChestplate { inner } => inner, + Material::LegacyLeatherLeggings { inner } => inner, + Material::LegacyLeatherBoots { inner } => inner, + Material::LegacyChainmailHelmet { inner } => inner, + Material::LegacyChainmailChestplate { inner } => inner, + Material::LegacyChainmailLeggings { inner } => inner, + Material::LegacyChainmailBoots { inner } => inner, + Material::LegacyIronHelmet { inner } => inner, + Material::LegacyIronChestplate { inner } => inner, + Material::LegacyIronLeggings { inner } => inner, + Material::LegacyIronBoots { inner } => inner, + Material::LegacyDiamondHelmet { inner } => inner, + Material::LegacyDiamondChestplate { inner } => inner, + Material::LegacyDiamondLeggings { inner } => inner, + Material::LegacyDiamondBoots { inner } => inner, + Material::LegacyGoldHelmet { inner } => inner, + Material::LegacyGoldChestplate { inner } => inner, + Material::LegacyGoldLeggings { inner } => inner, + Material::LegacyGoldBoots { inner } => inner, + Material::LegacyFlint { inner } => inner, + Material::LegacyPork { inner } => inner, + Material::LegacyGrilledPork { inner } => inner, + Material::LegacyPainting { inner } => inner, + Material::LegacyGoldenApple { inner } => inner, + Material::LegacySign { inner } => inner, + Material::LegacyWoodDoor { inner } => inner, + Material::LegacyBucket { inner } => inner, + Material::LegacyWaterBucket { inner } => inner, + Material::LegacyLavaBucket { inner } => inner, + Material::LegacyMinecart { inner } => inner, + Material::LegacySaddle { inner } => inner, + Material::LegacyIronDoor { inner } => inner, + Material::LegacyRedstone { inner } => inner, + Material::LegacySnowBall { inner } => inner, + Material::LegacyBoat { inner } => inner, + Material::LegacyLeather { inner } => inner, + Material::LegacyMilkBucket { inner } => inner, + Material::LegacyClayBrick { inner } => inner, + Material::LegacyClayBall { inner } => inner, + Material::LegacySugarCane { inner } => inner, + Material::LegacyPaper { inner } => inner, + Material::LegacyBook { inner } => inner, + Material::LegacySlimeBall { inner } => inner, + Material::LegacyStorageMinecart { inner } => inner, + Material::LegacyPoweredMinecart { inner } => inner, + Material::LegacyEgg { inner } => inner, + Material::LegacyCompass { inner } => inner, + Material::LegacyFishingRod { inner } => inner, + Material::LegacyWatch { inner } => inner, + Material::LegacyGlowstoneDust { inner } => inner, + Material::LegacyRawFish { inner } => inner, + Material::LegacyCookedFish { inner } => inner, + Material::LegacyInkSack { inner } => inner, + Material::LegacyBone { inner } => inner, + Material::LegacySugar { inner } => inner, + Material::LegacyCake { inner } => inner, + Material::LegacyBed { inner } => inner, + Material::LegacyDiode { inner } => inner, + Material::LegacyCookie { inner } => inner, + Material::LegacyMap { inner } => inner, + Material::LegacyShears { inner } => inner, + Material::LegacyMelon { inner } => inner, + Material::LegacyPumpkinSeeds { inner } => inner, + Material::LegacyMelonSeeds { inner } => inner, + Material::LegacyRawBeef { inner } => inner, + Material::LegacyCookedBeef { inner } => inner, + Material::LegacyRawChicken { inner } => inner, + Material::LegacyCookedChicken { inner } => inner, + Material::LegacyRottenFlesh { inner } => inner, + Material::LegacyEnderPearl { inner } => inner, + Material::LegacyBlazeRod { inner } => inner, + Material::LegacyGhastTear { inner } => inner, + Material::LegacyGoldNugget { inner } => inner, + Material::LegacyNetherStalk { inner } => inner, + Material::LegacyPotion { inner } => inner, + Material::LegacyGlassBottle { inner } => inner, + Material::LegacySpiderEye { inner } => inner, + Material::LegacyFermentedSpiderEye { inner } => inner, + Material::LegacyBlazePowder { inner } => inner, + Material::LegacyMagmaCream { inner } => inner, + Material::LegacyBrewingStandItem { inner } => inner, + Material::LegacyCauldronItem { inner } => inner, + Material::LegacyEyeOfEnder { inner } => inner, + Material::LegacySpeckledMelon { inner } => inner, + Material::LegacyMonsterEgg { inner } => inner, + Material::LegacyExpBottle { inner } => inner, + Material::LegacyFireball { inner } => inner, + Material::LegacyBookAndQuill { inner } => inner, + Material::LegacyWrittenBook { inner } => inner, + Material::LegacyEmerald { inner } => inner, + Material::LegacyItemFrame { inner } => inner, + Material::LegacyFlowerPotItem { inner } => inner, + Material::LegacyCarrotItem { inner } => inner, + Material::LegacyPotatoItem { inner } => inner, + Material::LegacyBakedPotato { inner } => inner, + Material::LegacyPoisonousPotato { inner } => inner, + Material::LegacyEmptyMap { inner } => inner, + Material::LegacyGoldenCarrot { inner } => inner, + Material::LegacySkullItem { inner } => inner, + Material::LegacyCarrotStick { inner } => inner, + Material::LegacyNetherStar { inner } => inner, + Material::LegacyPumpkinPie { inner } => inner, + Material::LegacyFirework { inner } => inner, + Material::LegacyFireworkCharge { inner } => inner, + Material::LegacyEnchantedBook { inner } => inner, + Material::LegacyRedstoneComparator { inner } => inner, + Material::LegacyNetherBrickItem { inner } => inner, + Material::LegacyQuartz { inner } => inner, + Material::LegacyExplosiveMinecart { inner } => inner, + Material::LegacyHopperMinecart { inner } => inner, + Material::LegacyPrismarineShard { inner } => inner, + Material::LegacyPrismarineCrystals { inner } => inner, + Material::LegacyRabbit { inner } => inner, + Material::LegacyCookedRabbit { inner } => inner, + Material::LegacyRabbitStew { inner } => inner, + Material::LegacyRabbitFoot { inner } => inner, + Material::LegacyRabbitHide { inner } => inner, + Material::LegacyArmorStand { inner } => inner, + Material::LegacyIronBarding { inner } => inner, + Material::LegacyGoldBarding { inner } => inner, + Material::LegacyDiamondBarding { inner } => inner, + Material::LegacyLeash { inner } => inner, + Material::LegacyNameTag { inner } => inner, + Material::LegacyCommandMinecart { inner } => inner, + Material::LegacyMutton { inner } => inner, + Material::LegacyCookedMutton { inner } => inner, + Material::LegacyBanner { inner } => inner, + Material::LegacyEndCrystal { inner } => inner, + Material::LegacySpruceDoorItem { inner } => inner, + Material::LegacyBirchDoorItem { inner } => inner, + Material::LegacyJungleDoorItem { inner } => inner, + Material::LegacyAcaciaDoorItem { inner } => inner, + Material::LegacyDarkOakDoorItem { inner } => inner, + Material::LegacyChorusFruit { inner } => inner, + Material::LegacyChorusFruitPopped { inner } => inner, + Material::LegacyBeetroot { inner } => inner, + Material::LegacyBeetrootSeeds { inner } => inner, + Material::LegacyBeetrootSoup { inner } => inner, + Material::LegacyDragonsBreath { inner } => inner, + Material::LegacySplashPotion { inner } => inner, + Material::LegacySpectralArrow { inner } => inner, + Material::LegacyTippedArrow { inner } => inner, + Material::LegacyLingeringPotion { inner } => inner, + Material::LegacyShield { inner } => inner, + Material::LegacyElytra { inner } => inner, + Material::LegacyBoatSpruce { inner } => inner, + Material::LegacyBoatBirch { inner } => inner, + Material::LegacyBoatJungle { inner } => inner, + Material::LegacyBoatAcacia { inner } => inner, + Material::LegacyBoatDarkOak { inner } => inner, + Material::LegacyTotem { inner } => inner, + Material::LegacyShulkerShell { inner } => inner, + Material::LegacyIronNugget { inner } => inner, + Material::LegacyKnowledgeBook { inner } => inner, + Material::LegacyGoldRecord { inner } => inner, + Material::LegacyGreenRecord { inner } => inner, + Material::LegacyRecord3 { inner } => inner, + Material::LegacyRecord4 { inner } => inner, + Material::LegacyRecord5 { inner } => inner, + Material::LegacyRecord6 { inner } => inner, + Material::LegacyRecord7 { inner } => inner, + Material::LegacyRecord8 { inner } => inner, + Material::LegacyRecord9 { inner } => inner, + Material::LegacyRecord10 { inner } => inner, + Material::LegacyRecord11 { inner } => inner, + Material::LegacyRecord12 { inner } => inner, + } + } +} + +impl<'mc> Material<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/Material"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/Material;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "AIR" => Ok(Material::Air { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE" => Ok(Material::Stone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRANITE" => Ok(Material::Granite { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_GRANITE" => Ok(Material::PolishedGranite { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIORITE" => Ok(Material::Diorite { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_DIORITE" => Ok(Material::PolishedDiorite { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ANDESITE" => Ok(Material::Andesite { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_ANDESITE" => Ok(Material::PolishedAndesite { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE" => Ok(Material::Deepslate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COBBLED_DEEPSLATE" => Ok(Material::CobbledDeepslate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_DEEPSLATE" => Ok(Material::PolishedDeepslate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CALCITE" => Ok(Material::Calcite { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TUFF" => Ok(Material::Tuff { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TUFF_SLAB" => Ok(Material::TuffSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TUFF_STAIRS" => Ok(Material::TuffStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TUFF_WALL" => Ok(Material::TuffWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHISELED_TUFF" => Ok(Material::ChiseledTuff { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_TUFF" => Ok(Material::PolishedTuff { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_TUFF_SLAB" => Ok(Material::PolishedTuffSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_TUFF_STAIRS" => Ok(Material::PolishedTuffStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_TUFF_WALL" => Ok(Material::PolishedTuffWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TUFF_BRICKS" => Ok(Material::TuffBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TUFF_BRICK_SLAB" => Ok(Material::TuffBrickSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TUFF_BRICK_STAIRS" => Ok(Material::TuffBrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TUFF_BRICK_WALL" => Ok(Material::TuffBrickWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHISELED_TUFF_BRICKS" => Ok(Material::ChiseledTuffBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DRIPSTONE_BLOCK" => Ok(Material::DripstoneBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRASS_BLOCK" => Ok(Material::GrassBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIRT" => Ok(Material::Dirt { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COARSE_DIRT" => Ok(Material::CoarseDirt { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PODZOL" => Ok(Material::Podzol { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ROOTED_DIRT" => Ok(Material::RootedDirt { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUD" => Ok(Material::Mud { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_NYLIUM" => Ok(Material::CrimsonNylium { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_NYLIUM" => Ok(Material::WarpedNylium { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COBBLESTONE" => Ok(Material::Cobblestone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_PLANKS" => Ok(Material::OakPlanks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_PLANKS" => Ok(Material::SprucePlanks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_PLANKS" => Ok(Material::BirchPlanks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_PLANKS" => Ok(Material::JunglePlanks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_PLANKS" => Ok(Material::AcaciaPlanks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_PLANKS" => Ok(Material::CherryPlanks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_PLANKS" => Ok(Material::DarkOakPlanks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_PLANKS" => Ok(Material::MangrovePlanks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_PLANKS" => Ok(Material::BambooPlanks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_PLANKS" => Ok(Material::CrimsonPlanks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_PLANKS" => Ok(Material::WarpedPlanks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_MOSAIC" => Ok(Material::BambooMosaic { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_SAPLING" => Ok(Material::OakSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_SAPLING" => Ok(Material::SpruceSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_SAPLING" => Ok(Material::BirchSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_SAPLING" => Ok(Material::JungleSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_SAPLING" => Ok(Material::AcaciaSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_SAPLING" => Ok(Material::CherrySapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_SAPLING" => Ok(Material::DarkOakSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_PROPAGULE" => Ok(Material::MangrovePropagule { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BEDROCK" => Ok(Material::Bedrock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SAND" => Ok(Material::Sand { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SUSPICIOUS_SAND" => Ok(Material::SuspiciousSand { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SUSPICIOUS_GRAVEL" => Ok(Material::SuspiciousGravel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_SAND" => Ok(Material::RedSand { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAVEL" => Ok(Material::Gravel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COAL_ORE" => Ok(Material::CoalOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_COAL_ORE" => Ok(Material::DeepslateCoalOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_ORE" => Ok(Material::IronOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_IRON_ORE" => Ok(Material::DeepslateIronOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COPPER_ORE" => Ok(Material::CopperOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_COPPER_ORE" => Ok(Material::DeepslateCopperOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLD_ORE" => Ok(Material::GoldOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_GOLD_ORE" => Ok(Material::DeepslateGoldOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "REDSTONE_ORE" => Ok(Material::RedstoneOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_REDSTONE_ORE" => Ok(Material::DeepslateRedstoneOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EMERALD_ORE" => Ok(Material::EmeraldOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_EMERALD_ORE" => Ok(Material::DeepslateEmeraldOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LAPIS_ORE" => Ok(Material::LapisOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_LAPIS_ORE" => Ok(Material::DeepslateLapisOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND_ORE" => Ok(Material::DiamondOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_DIAMOND_ORE" => Ok(Material::DeepslateDiamondOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_GOLD_ORE" => Ok(Material::NetherGoldOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_QUARTZ_ORE" => Ok(Material::NetherQuartzOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ANCIENT_DEBRIS" => Ok(Material::AncientDebris { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COAL_BLOCK" => Ok(Material::CoalBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RAW_IRON_BLOCK" => Ok(Material::RawIronBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RAW_COPPER_BLOCK" => Ok(Material::RawCopperBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RAW_GOLD_BLOCK" => Ok(Material::RawGoldBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HEAVY_CORE" => Ok(Material::HeavyCore { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "AMETHYST_BLOCK" => Ok(Material::AmethystBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BUDDING_AMETHYST" => Ok(Material::BuddingAmethyst { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_BLOCK" => Ok(Material::IronBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COPPER_BLOCK" => Ok(Material::CopperBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLD_BLOCK" => Ok(Material::GoldBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND_BLOCK" => Ok(Material::DiamondBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_BLOCK" => Ok(Material::NetheriteBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EXPOSED_COPPER" => Ok(Material::ExposedCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WEATHERED_COPPER" => Ok(Material::WeatheredCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OXIDIZED_COPPER" => Ok(Material::OxidizedCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHISELED_COPPER" => Ok(Material::ChiseledCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EXPOSED_CHISELED_COPPER" => Ok(Material::ExposedChiseledCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WEATHERED_CHISELED_COPPER" => Ok(Material::WeatheredChiseledCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OXIDIZED_CHISELED_COPPER" => Ok(Material::OxidizedChiseledCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CUT_COPPER" => Ok(Material::CutCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EXPOSED_CUT_COPPER" => Ok(Material::ExposedCutCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WEATHERED_CUT_COPPER" => Ok(Material::WeatheredCutCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OXIDIZED_CUT_COPPER" => Ok(Material::OxidizedCutCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CUT_COPPER_STAIRS" => Ok(Material::CutCopperStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EXPOSED_CUT_COPPER_STAIRS" => Ok(Material::ExposedCutCopperStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WEATHERED_CUT_COPPER_STAIRS" => Ok(Material::WeatheredCutCopperStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OXIDIZED_CUT_COPPER_STAIRS" => Ok(Material::OxidizedCutCopperStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CUT_COPPER_SLAB" => Ok(Material::CutCopperSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EXPOSED_CUT_COPPER_SLAB" => Ok(Material::ExposedCutCopperSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WEATHERED_CUT_COPPER_SLAB" => Ok(Material::WeatheredCutCopperSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OXIDIZED_CUT_COPPER_SLAB" => Ok(Material::OxidizedCutCopperSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_COPPER_BLOCK" => Ok(Material::WaxedCopperBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_EXPOSED_COPPER" => Ok(Material::WaxedExposedCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_WEATHERED_COPPER" => Ok(Material::WaxedWeatheredCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_OXIDIZED_COPPER" => Ok(Material::WaxedOxidizedCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_CHISELED_COPPER" => Ok(Material::WaxedChiseledCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_EXPOSED_CHISELED_COPPER" => Ok(Material::WaxedExposedChiseledCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_WEATHERED_CHISELED_COPPER" => Ok(Material::WaxedWeatheredChiseledCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_OXIDIZED_CHISELED_COPPER" => Ok(Material::WaxedOxidizedChiseledCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_CUT_COPPER" => Ok(Material::WaxedCutCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_EXPOSED_CUT_COPPER" => Ok(Material::WaxedExposedCutCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_WEATHERED_CUT_COPPER" => Ok(Material::WaxedWeatheredCutCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_OXIDIZED_CUT_COPPER" => Ok(Material::WaxedOxidizedCutCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_CUT_COPPER_STAIRS" => Ok(Material::WaxedCutCopperStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_EXPOSED_CUT_COPPER_STAIRS" => Ok(Material::WaxedExposedCutCopperStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_WEATHERED_CUT_COPPER_STAIRS" => Ok(Material::WaxedWeatheredCutCopperStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_OXIDIZED_CUT_COPPER_STAIRS" => Ok(Material::WaxedOxidizedCutCopperStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_CUT_COPPER_SLAB" => Ok(Material::WaxedCutCopperSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_EXPOSED_CUT_COPPER_SLAB" => Ok(Material::WaxedExposedCutCopperSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_WEATHERED_CUT_COPPER_SLAB" => Ok(Material::WaxedWeatheredCutCopperSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_OXIDIZED_CUT_COPPER_SLAB" => Ok(Material::WaxedOxidizedCutCopperSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_LOG" => Ok(Material::OakLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_LOG" => Ok(Material::SpruceLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_LOG" => Ok(Material::BirchLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_LOG" => Ok(Material::JungleLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_LOG" => Ok(Material::AcaciaLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_LOG" => Ok(Material::CherryLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_LOG" => Ok(Material::DarkOakLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_LOG" => Ok(Material::MangroveLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_ROOTS" => Ok(Material::MangroveRoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUDDY_MANGROVE_ROOTS" => Ok(Material::MuddyMangroveRoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_STEM" => Ok(Material::CrimsonStem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_STEM" => Ok(Material::WarpedStem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_BLOCK" => Ok(Material::BambooBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_OAK_LOG" => Ok(Material::StrippedOakLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_SPRUCE_LOG" => Ok(Material::StrippedSpruceLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_BIRCH_LOG" => Ok(Material::StrippedBirchLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_JUNGLE_LOG" => Ok(Material::StrippedJungleLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_ACACIA_LOG" => Ok(Material::StrippedAcaciaLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_CHERRY_LOG" => Ok(Material::StrippedCherryLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_DARK_OAK_LOG" => Ok(Material::StrippedDarkOakLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_MANGROVE_LOG" => Ok(Material::StrippedMangroveLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_CRIMSON_STEM" => Ok(Material::StrippedCrimsonStem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_WARPED_STEM" => Ok(Material::StrippedWarpedStem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_OAK_WOOD" => Ok(Material::StrippedOakWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_SPRUCE_WOOD" => Ok(Material::StrippedSpruceWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_BIRCH_WOOD" => Ok(Material::StrippedBirchWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_JUNGLE_WOOD" => Ok(Material::StrippedJungleWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_ACACIA_WOOD" => Ok(Material::StrippedAcaciaWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_CHERRY_WOOD" => Ok(Material::StrippedCherryWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_DARK_OAK_WOOD" => Ok(Material::StrippedDarkOakWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_MANGROVE_WOOD" => Ok(Material::StrippedMangroveWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_CRIMSON_HYPHAE" => Ok(Material::StrippedCrimsonHyphae { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_WARPED_HYPHAE" => Ok(Material::StrippedWarpedHyphae { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_BAMBOO_BLOCK" => Ok(Material::StrippedBambooBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_WOOD" => Ok(Material::OakWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_WOOD" => Ok(Material::SpruceWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_WOOD" => Ok(Material::BirchWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_WOOD" => Ok(Material::JungleWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_WOOD" => Ok(Material::AcaciaWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_WOOD" => Ok(Material::CherryWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_WOOD" => Ok(Material::DarkOakWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_WOOD" => Ok(Material::MangroveWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_HYPHAE" => Ok(Material::CrimsonHyphae { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_HYPHAE" => Ok(Material::WarpedHyphae { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_LEAVES" => Ok(Material::OakLeaves { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_LEAVES" => Ok(Material::SpruceLeaves { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_LEAVES" => Ok(Material::BirchLeaves { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_LEAVES" => Ok(Material::JungleLeaves { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_LEAVES" => Ok(Material::AcaciaLeaves { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_LEAVES" => Ok(Material::CherryLeaves { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_LEAVES" => Ok(Material::DarkOakLeaves { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_LEAVES" => Ok(Material::MangroveLeaves { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "AZALEA_LEAVES" => Ok(Material::AzaleaLeaves { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FLOWERING_AZALEA_LEAVES" => Ok(Material::FloweringAzaleaLeaves { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPONGE" => Ok(Material::Sponge { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WET_SPONGE" => Ok(Material::WetSponge { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GLASS" => Ok(Material::Glass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TINTED_GLASS" => Ok(Material::TintedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LAPIS_BLOCK" => Ok(Material::LapisBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SANDSTONE" => Ok(Material::Sandstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHISELED_SANDSTONE" => Ok(Material::ChiseledSandstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CUT_SANDSTONE" => Ok(Material::CutSandstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COBWEB" => Ok(Material::Cobweb { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SHORT_GRASS" => Ok(Material::ShortGrass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FERN" => Ok(Material::Fern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "AZALEA" => Ok(Material::Azalea { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FLOWERING_AZALEA" => Ok(Material::FloweringAzalea { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_BUSH" => Ok(Material::DeadBush { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SEAGRASS" => Ok(Material::Seagrass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SEA_PICKLE" => Ok(Material::SeaPickle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_WOOL" => Ok(Material::WhiteWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_WOOL" => Ok(Material::OrangeWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_WOOL" => Ok(Material::MagentaWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_WOOL" => Ok(Material::LightBlueWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_WOOL" => Ok(Material::YellowWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_WOOL" => Ok(Material::LimeWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_WOOL" => Ok(Material::PinkWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_WOOL" => Ok(Material::GrayWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_WOOL" => Ok(Material::LightGrayWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_WOOL" => Ok(Material::CyanWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_WOOL" => Ok(Material::PurpleWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_WOOL" => Ok(Material::BlueWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_WOOL" => Ok(Material::BrownWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_WOOL" => Ok(Material::GreenWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_WOOL" => Ok(Material::RedWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_WOOL" => Ok(Material::BlackWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DANDELION" => Ok(Material::Dandelion { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POPPY" => Ok(Material::Poppy { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_ORCHID" => Ok(Material::BlueOrchid { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ALLIUM" => Ok(Material::Allium { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "AZURE_BLUET" => Ok(Material::AzureBluet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_TULIP" => Ok(Material::RedTulip { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_TULIP" => Ok(Material::OrangeTulip { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_TULIP" => Ok(Material::WhiteTulip { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_TULIP" => Ok(Material::PinkTulip { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OXEYE_DAISY" => Ok(Material::OxeyeDaisy { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CORNFLOWER" => Ok(Material::Cornflower { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LILY_OF_THE_VALLEY" => Ok(Material::LilyOfTheValley { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WITHER_ROSE" => Ok(Material::WitherRose { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TORCHFLOWER" => Ok(Material::Torchflower { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PITCHER_PLANT" => Ok(Material::PitcherPlant { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPORE_BLOSSOM" => Ok(Material::SporeBlossom { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_MUSHROOM" => Ok(Material::BrownMushroom { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_MUSHROOM" => Ok(Material::RedMushroom { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_FUNGUS" => Ok(Material::CrimsonFungus { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_FUNGUS" => Ok(Material::WarpedFungus { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_ROOTS" => Ok(Material::CrimsonRoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_ROOTS" => Ok(Material::WarpedRoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_SPROUTS" => Ok(Material::NetherSprouts { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WEEPING_VINES" => Ok(Material::WeepingVines { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TWISTING_VINES" => Ok(Material::TwistingVines { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SUGAR_CANE" => Ok(Material::SugarCane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "KELP" => Ok(Material::Kelp { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOSS_CARPET" => Ok(Material::MossCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_PETALS" => Ok(Material::PinkPetals { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOSS_BLOCK" => Ok(Material::MossBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HANGING_ROOTS" => Ok(Material::HangingRoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIG_DRIPLEAF" => Ok(Material::BigDripleaf { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMALL_DRIPLEAF" => Ok(Material::SmallDripleaf { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO" => Ok(Material::Bamboo { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_SLAB" => Ok(Material::OakSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_SLAB" => Ok(Material::SpruceSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_SLAB" => Ok(Material::BirchSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_SLAB" => Ok(Material::JungleSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_SLAB" => Ok(Material::AcaciaSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_SLAB" => Ok(Material::CherrySlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_SLAB" => Ok(Material::DarkOakSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_SLAB" => Ok(Material::MangroveSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_SLAB" => Ok(Material::BambooSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_MOSAIC_SLAB" => Ok(Material::BambooMosaicSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_SLAB" => Ok(Material::CrimsonSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_SLAB" => Ok(Material::WarpedSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_SLAB" => Ok(Material::StoneSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOOTH_STONE_SLAB" => Ok(Material::SmoothStoneSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SANDSTONE_SLAB" => Ok(Material::SandstoneSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CUT_SANDSTONE_SLAB" => Ok(Material::CutSandstoneSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PETRIFIED_OAK_SLAB" => Ok(Material::PetrifiedOakSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COBBLESTONE_SLAB" => Ok(Material::CobblestoneSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BRICK_SLAB" => Ok(Material::BrickSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_BRICK_SLAB" => Ok(Material::StoneBrickSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUD_BRICK_SLAB" => Ok(Material::MudBrickSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_BRICK_SLAB" => Ok(Material::NetherBrickSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "QUARTZ_SLAB" => Ok(Material::QuartzSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_SANDSTONE_SLAB" => Ok(Material::RedSandstoneSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CUT_RED_SANDSTONE_SLAB" => Ok(Material::CutRedSandstoneSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPUR_SLAB" => Ok(Material::PurpurSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PRISMARINE_SLAB" => Ok(Material::PrismarineSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PRISMARINE_BRICK_SLAB" => Ok(Material::PrismarineBrickSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_PRISMARINE_SLAB" => Ok(Material::DarkPrismarineSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOOTH_QUARTZ" => Ok(Material::SmoothQuartz { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOOTH_RED_SANDSTONE" => Ok(Material::SmoothRedSandstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOOTH_SANDSTONE" => Ok(Material::SmoothSandstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOOTH_STONE" => Ok(Material::SmoothStone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BRICKS" => Ok(Material::Bricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BOOKSHELF" => Ok(Material::Bookshelf { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHISELED_BOOKSHELF" => Ok(Material::ChiseledBookshelf { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DECORATED_POT" => Ok(Material::DecoratedPot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOSSY_COBBLESTONE" => Ok(Material::MossyCobblestone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OBSIDIAN" => Ok(Material::Obsidian { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TORCH" => Ok(Material::Torch { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "END_ROD" => Ok(Material::EndRod { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHORUS_PLANT" => Ok(Material::ChorusPlant { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHORUS_FLOWER" => Ok(Material::ChorusFlower { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPUR_BLOCK" => Ok(Material::PurpurBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPUR_PILLAR" => Ok(Material::PurpurPillar { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPUR_STAIRS" => Ok(Material::PurpurStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPAWNER" => Ok(Material::Spawner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHEST" => Ok(Material::Chest { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRAFTING_TABLE" => Ok(Material::CraftingTable { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FARMLAND" => Ok(Material::Farmland { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FURNACE" => Ok(Material::Furnace { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LADDER" => Ok(Material::Ladder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COBBLESTONE_STAIRS" => Ok(Material::CobblestoneStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SNOW" => Ok(Material::Snow { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ICE" => Ok(Material::Ice { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SNOW_BLOCK" => Ok(Material::SnowBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CACTUS" => Ok(Material::Cactus { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CLAY" => Ok(Material::Clay { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUKEBOX" => Ok(Material::Jukebox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_FENCE" => Ok(Material::OakFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_FENCE" => Ok(Material::SpruceFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_FENCE" => Ok(Material::BirchFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_FENCE" => Ok(Material::JungleFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_FENCE" => Ok(Material::AcaciaFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_FENCE" => Ok(Material::CherryFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_FENCE" => Ok(Material::DarkOakFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_FENCE" => Ok(Material::MangroveFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_FENCE" => Ok(Material::BambooFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_FENCE" => Ok(Material::CrimsonFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_FENCE" => Ok(Material::WarpedFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PUMPKIN" => Ok(Material::Pumpkin { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CARVED_PUMPKIN" => Ok(Material::CarvedPumpkin { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JACK_O_LANTERN" => Ok(Material::JackOLantern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERRACK" => Ok(Material::Netherrack { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SOUL_SAND" => Ok(Material::SoulSand { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SOUL_SOIL" => Ok(Material::SoulSoil { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BASALT" => Ok(Material::Basalt { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_BASALT" => Ok(Material::PolishedBasalt { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOOTH_BASALT" => Ok(Material::SmoothBasalt { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SOUL_TORCH" => Ok(Material::SoulTorch { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GLOWSTONE" => Ok(Material::Glowstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "INFESTED_STONE" => Ok(Material::InfestedStone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "INFESTED_COBBLESTONE" => Ok(Material::InfestedCobblestone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "INFESTED_STONE_BRICKS" => Ok(Material::InfestedStoneBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "INFESTED_MOSSY_STONE_BRICKS" => Ok(Material::InfestedMossyStoneBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "INFESTED_CRACKED_STONE_BRICKS" => Ok(Material::InfestedCrackedStoneBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "INFESTED_CHISELED_STONE_BRICKS" => Ok(Material::InfestedChiseledStoneBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "INFESTED_DEEPSLATE" => Ok(Material::InfestedDeepslate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_BRICKS" => Ok(Material::StoneBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOSSY_STONE_BRICKS" => Ok(Material::MossyStoneBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRACKED_STONE_BRICKS" => Ok(Material::CrackedStoneBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHISELED_STONE_BRICKS" => Ok(Material::ChiseledStoneBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PACKED_MUD" => Ok(Material::PackedMud { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUD_BRICKS" => Ok(Material::MudBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_BRICKS" => Ok(Material::DeepslateBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRACKED_DEEPSLATE_BRICKS" => Ok(Material::CrackedDeepslateBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_TILES" => Ok(Material::DeepslateTiles { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRACKED_DEEPSLATE_TILES" => Ok(Material::CrackedDeepslateTiles { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHISELED_DEEPSLATE" => Ok(Material::ChiseledDeepslate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "REINFORCED_DEEPSLATE" => Ok(Material::ReinforcedDeepslate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_MUSHROOM_BLOCK" => Ok(Material::BrownMushroomBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_MUSHROOM_BLOCK" => Ok(Material::RedMushroomBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSHROOM_STEM" => Ok(Material::MushroomStem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_BARS" => Ok(Material::IronBars { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHAIN" => Ok(Material::Chain { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GLASS_PANE" => Ok(Material::GlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MELON" => Ok(Material::Melon { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "VINE" => Ok(Material::Vine { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GLOW_LICHEN" => Ok(Material::GlowLichen { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BRICK_STAIRS" => Ok(Material::BrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_BRICK_STAIRS" => Ok(Material::StoneBrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUD_BRICK_STAIRS" => Ok(Material::MudBrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MYCELIUM" => Ok(Material::Mycelium { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LILY_PAD" => Ok(Material::LilyPad { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_BRICKS" => Ok(Material::NetherBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRACKED_NETHER_BRICKS" => Ok(Material::CrackedNetherBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHISELED_NETHER_BRICKS" => Ok(Material::ChiseledNetherBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_BRICK_FENCE" => Ok(Material::NetherBrickFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_BRICK_STAIRS" => Ok(Material::NetherBrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SCULK" => Ok(Material::Sculk { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SCULK_VEIN" => Ok(Material::SculkVein { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SCULK_CATALYST" => Ok(Material::SculkCatalyst { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SCULK_SHRIEKER" => Ok(Material::SculkShrieker { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ENCHANTING_TABLE" => Ok(Material::EnchantingTable { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "END_PORTAL_FRAME" => Ok(Material::EndPortalFrame { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "END_STONE" => Ok(Material::EndStone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "END_STONE_BRICKS" => Ok(Material::EndStoneBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DRAGON_EGG" => Ok(Material::DragonEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SANDSTONE_STAIRS" => Ok(Material::SandstoneStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ENDER_CHEST" => Ok(Material::EnderChest { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EMERALD_BLOCK" => Ok(Material::EmeraldBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_STAIRS" => Ok(Material::OakStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_STAIRS" => Ok(Material::SpruceStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_STAIRS" => Ok(Material::BirchStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_STAIRS" => Ok(Material::JungleStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_STAIRS" => Ok(Material::AcaciaStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_STAIRS" => Ok(Material::CherryStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_STAIRS" => Ok(Material::DarkOakStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_STAIRS" => Ok(Material::MangroveStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_STAIRS" => Ok(Material::BambooStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_MOSAIC_STAIRS" => Ok(Material::BambooMosaicStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_STAIRS" => Ok(Material::CrimsonStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_STAIRS" => Ok(Material::WarpedStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COMMAND_BLOCK" => Ok(Material::CommandBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BEACON" => Ok(Material::Beacon { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COBBLESTONE_WALL" => Ok(Material::CobblestoneWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOSSY_COBBLESTONE_WALL" => Ok(Material::MossyCobblestoneWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BRICK_WALL" => Ok(Material::BrickWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PRISMARINE_WALL" => Ok(Material::PrismarineWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_SANDSTONE_WALL" => Ok(Material::RedSandstoneWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOSSY_STONE_BRICK_WALL" => Ok(Material::MossyStoneBrickWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRANITE_WALL" => Ok(Material::GraniteWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_BRICK_WALL" => Ok(Material::StoneBrickWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUD_BRICK_WALL" => Ok(Material::MudBrickWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_BRICK_WALL" => Ok(Material::NetherBrickWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ANDESITE_WALL" => Ok(Material::AndesiteWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_NETHER_BRICK_WALL" => Ok(Material::RedNetherBrickWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SANDSTONE_WALL" => Ok(Material::SandstoneWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "END_STONE_BRICK_WALL" => Ok(Material::EndStoneBrickWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIORITE_WALL" => Ok(Material::DioriteWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACKSTONE_WALL" => Ok(Material::BlackstoneWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_BLACKSTONE_WALL" => Ok(Material::PolishedBlackstoneWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_BLACKSTONE_BRICK_WALL" => Ok(Material::PolishedBlackstoneBrickWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COBBLED_DEEPSLATE_WALL" => Ok(Material::CobbledDeepslateWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_DEEPSLATE_WALL" => Ok(Material::PolishedDeepslateWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_BRICK_WALL" => Ok(Material::DeepslateBrickWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_TILE_WALL" => Ok(Material::DeepslateTileWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ANVIL" => Ok(Material::Anvil { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHIPPED_ANVIL" => Ok(Material::ChippedAnvil { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DAMAGED_ANVIL" => Ok(Material::DamagedAnvil { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHISELED_QUARTZ_BLOCK" => Ok(Material::ChiseledQuartzBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "QUARTZ_BLOCK" => Ok(Material::QuartzBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "QUARTZ_BRICKS" => Ok(Material::QuartzBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "QUARTZ_PILLAR" => Ok(Material::QuartzPillar { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "QUARTZ_STAIRS" => Ok(Material::QuartzStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_TERRACOTTA" => Ok(Material::WhiteTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_TERRACOTTA" => Ok(Material::OrangeTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_TERRACOTTA" => Ok(Material::MagentaTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_TERRACOTTA" => Ok(Material::LightBlueTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_TERRACOTTA" => Ok(Material::YellowTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_TERRACOTTA" => Ok(Material::LimeTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_TERRACOTTA" => Ok(Material::PinkTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_TERRACOTTA" => Ok(Material::GrayTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_TERRACOTTA" => Ok(Material::LightGrayTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_TERRACOTTA" => Ok(Material::CyanTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_TERRACOTTA" => Ok(Material::PurpleTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_TERRACOTTA" => Ok(Material::BlueTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_TERRACOTTA" => Ok(Material::BrownTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_TERRACOTTA" => Ok(Material::GreenTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_TERRACOTTA" => Ok(Material::RedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_TERRACOTTA" => Ok(Material::BlackTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BARRIER" => Ok(Material::Barrier { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT" => Ok(Material::Light { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HAY_BLOCK" => Ok(Material::HayBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_CARPET" => Ok(Material::WhiteCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_CARPET" => Ok(Material::OrangeCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_CARPET" => Ok(Material::MagentaCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_CARPET" => Ok(Material::LightBlueCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_CARPET" => Ok(Material::YellowCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_CARPET" => Ok(Material::LimeCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_CARPET" => Ok(Material::PinkCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_CARPET" => Ok(Material::GrayCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_CARPET" => Ok(Material::LightGrayCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_CARPET" => Ok(Material::CyanCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_CARPET" => Ok(Material::PurpleCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_CARPET" => Ok(Material::BlueCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_CARPET" => Ok(Material::BrownCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_CARPET" => Ok(Material::GreenCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_CARPET" => Ok(Material::RedCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_CARPET" => Ok(Material::BlackCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TERRACOTTA" => Ok(Material::Terracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PACKED_ICE" => Ok(Material::PackedIce { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIRT_PATH" => Ok(Material::DirtPath { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SUNFLOWER" => Ok(Material::Sunflower { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LILAC" => Ok(Material::Lilac { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ROSE_BUSH" => Ok(Material::RoseBush { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PEONY" => Ok(Material::Peony { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TALL_GRASS" => Ok(Material::TallGrass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LARGE_FERN" => Ok(Material::LargeFern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_STAINED_GLASS" => Ok(Material::WhiteStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_STAINED_GLASS" => Ok(Material::OrangeStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_STAINED_GLASS" => Ok(Material::MagentaStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_STAINED_GLASS" => Ok(Material::LightBlueStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_STAINED_GLASS" => Ok(Material::YellowStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_STAINED_GLASS" => Ok(Material::LimeStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_STAINED_GLASS" => Ok(Material::PinkStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_STAINED_GLASS" => Ok(Material::GrayStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_STAINED_GLASS" => Ok(Material::LightGrayStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_STAINED_GLASS" => Ok(Material::CyanStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_STAINED_GLASS" => Ok(Material::PurpleStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_STAINED_GLASS" => Ok(Material::BlueStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_STAINED_GLASS" => Ok(Material::BrownStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_STAINED_GLASS" => Ok(Material::GreenStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_STAINED_GLASS" => Ok(Material::RedStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_STAINED_GLASS" => Ok(Material::BlackStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_STAINED_GLASS_PANE" => Ok(Material::WhiteStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_STAINED_GLASS_PANE" => Ok(Material::OrangeStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_STAINED_GLASS_PANE" => Ok(Material::MagentaStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_STAINED_GLASS_PANE" => Ok(Material::LightBlueStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_STAINED_GLASS_PANE" => Ok(Material::YellowStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_STAINED_GLASS_PANE" => Ok(Material::LimeStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_STAINED_GLASS_PANE" => Ok(Material::PinkStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_STAINED_GLASS_PANE" => Ok(Material::GrayStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_STAINED_GLASS_PANE" => Ok(Material::LightGrayStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_STAINED_GLASS_PANE" => Ok(Material::CyanStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_STAINED_GLASS_PANE" => Ok(Material::PurpleStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_STAINED_GLASS_PANE" => Ok(Material::BlueStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_STAINED_GLASS_PANE" => Ok(Material::BrownStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_STAINED_GLASS_PANE" => Ok(Material::GreenStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_STAINED_GLASS_PANE" => Ok(Material::RedStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_STAINED_GLASS_PANE" => Ok(Material::BlackStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PRISMARINE" => Ok(Material::Prismarine { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PRISMARINE_BRICKS" => Ok(Material::PrismarineBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_PRISMARINE" => Ok(Material::DarkPrismarine { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PRISMARINE_STAIRS" => Ok(Material::PrismarineStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PRISMARINE_BRICK_STAIRS" => Ok(Material::PrismarineBrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_PRISMARINE_STAIRS" => Ok(Material::DarkPrismarineStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SEA_LANTERN" => Ok(Material::SeaLantern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_SANDSTONE" => Ok(Material::RedSandstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHISELED_RED_SANDSTONE" => Ok(Material::ChiseledRedSandstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CUT_RED_SANDSTONE" => Ok(Material::CutRedSandstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_SANDSTONE_STAIRS" => Ok(Material::RedSandstoneStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "REPEATING_COMMAND_BLOCK" => Ok(Material::RepeatingCommandBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHAIN_COMMAND_BLOCK" => Ok(Material::ChainCommandBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGMA_BLOCK" => Ok(Material::MagmaBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_WART_BLOCK" => Ok(Material::NetherWartBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_WART_BLOCK" => Ok(Material::WarpedWartBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_NETHER_BRICKS" => Ok(Material::RedNetherBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BONE_BLOCK" => Ok(Material::BoneBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRUCTURE_VOID" => Ok(Material::StructureVoid { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SHULKER_BOX" => Ok(Material::ShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_SHULKER_BOX" => Ok(Material::WhiteShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_SHULKER_BOX" => Ok(Material::OrangeShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_SHULKER_BOX" => Ok(Material::MagentaShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_SHULKER_BOX" => Ok(Material::LightBlueShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_SHULKER_BOX" => Ok(Material::YellowShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_SHULKER_BOX" => Ok(Material::LimeShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_SHULKER_BOX" => Ok(Material::PinkShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_SHULKER_BOX" => Ok(Material::GrayShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_SHULKER_BOX" => Ok(Material::LightGrayShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_SHULKER_BOX" => Ok(Material::CyanShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_SHULKER_BOX" => Ok(Material::PurpleShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_SHULKER_BOX" => Ok(Material::BlueShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_SHULKER_BOX" => Ok(Material::BrownShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_SHULKER_BOX" => Ok(Material::GreenShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_SHULKER_BOX" => Ok(Material::RedShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_SHULKER_BOX" => Ok(Material::BlackShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_GLAZED_TERRACOTTA" => Ok(Material::WhiteGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_GLAZED_TERRACOTTA" => Ok(Material::OrangeGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_GLAZED_TERRACOTTA" => Ok(Material::MagentaGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_GLAZED_TERRACOTTA" => Ok(Material::LightBlueGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_GLAZED_TERRACOTTA" => Ok(Material::YellowGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_GLAZED_TERRACOTTA" => Ok(Material::LimeGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_GLAZED_TERRACOTTA" => Ok(Material::PinkGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_GLAZED_TERRACOTTA" => Ok(Material::GrayGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_GLAZED_TERRACOTTA" => Ok(Material::LightGrayGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_GLAZED_TERRACOTTA" => Ok(Material::CyanGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_GLAZED_TERRACOTTA" => Ok(Material::PurpleGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_GLAZED_TERRACOTTA" => Ok(Material::BlueGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_GLAZED_TERRACOTTA" => Ok(Material::BrownGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_GLAZED_TERRACOTTA" => Ok(Material::GreenGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_GLAZED_TERRACOTTA" => Ok(Material::RedGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_GLAZED_TERRACOTTA" => Ok(Material::BlackGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_CONCRETE" => Ok(Material::WhiteConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_CONCRETE" => Ok(Material::OrangeConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_CONCRETE" => Ok(Material::MagentaConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_CONCRETE" => Ok(Material::LightBlueConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_CONCRETE" => Ok(Material::YellowConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_CONCRETE" => Ok(Material::LimeConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_CONCRETE" => Ok(Material::PinkConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_CONCRETE" => Ok(Material::GrayConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_CONCRETE" => Ok(Material::LightGrayConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_CONCRETE" => Ok(Material::CyanConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_CONCRETE" => Ok(Material::PurpleConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_CONCRETE" => Ok(Material::BlueConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_CONCRETE" => Ok(Material::BrownConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_CONCRETE" => Ok(Material::GreenConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_CONCRETE" => Ok(Material::RedConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_CONCRETE" => Ok(Material::BlackConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_CONCRETE_POWDER" => Ok(Material::WhiteConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_CONCRETE_POWDER" => Ok(Material::OrangeConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_CONCRETE_POWDER" => Ok(Material::MagentaConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_CONCRETE_POWDER" => Ok(Material::LightBlueConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_CONCRETE_POWDER" => Ok(Material::YellowConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_CONCRETE_POWDER" => Ok(Material::LimeConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_CONCRETE_POWDER" => Ok(Material::PinkConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_CONCRETE_POWDER" => Ok(Material::GrayConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_CONCRETE_POWDER" => Ok(Material::LightGrayConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_CONCRETE_POWDER" => Ok(Material::CyanConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_CONCRETE_POWDER" => Ok(Material::PurpleConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_CONCRETE_POWDER" => Ok(Material::BlueConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_CONCRETE_POWDER" => Ok(Material::BrownConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_CONCRETE_POWDER" => Ok(Material::GreenConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_CONCRETE_POWDER" => Ok(Material::RedConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_CONCRETE_POWDER" => Ok(Material::BlackConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TURTLE_EGG" => Ok(Material::TurtleEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SNIFFER_EGG" => Ok(Material::SnifferEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_TUBE_CORAL_BLOCK" => Ok(Material::DeadTubeCoralBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_BRAIN_CORAL_BLOCK" => Ok(Material::DeadBrainCoralBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_BUBBLE_CORAL_BLOCK" => Ok(Material::DeadBubbleCoralBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_FIRE_CORAL_BLOCK" => Ok(Material::DeadFireCoralBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_HORN_CORAL_BLOCK" => Ok(Material::DeadHornCoralBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TUBE_CORAL_BLOCK" => Ok(Material::TubeCoralBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BRAIN_CORAL_BLOCK" => Ok(Material::BrainCoralBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BUBBLE_CORAL_BLOCK" => Ok(Material::BubbleCoralBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FIRE_CORAL_BLOCK" => Ok(Material::FireCoralBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HORN_CORAL_BLOCK" => Ok(Material::HornCoralBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TUBE_CORAL" => Ok(Material::TubeCoral { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BRAIN_CORAL" => Ok(Material::BrainCoral { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BUBBLE_CORAL" => Ok(Material::BubbleCoral { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FIRE_CORAL" => Ok(Material::FireCoral { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HORN_CORAL" => Ok(Material::HornCoral { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_BRAIN_CORAL" => Ok(Material::DeadBrainCoral { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_BUBBLE_CORAL" => Ok(Material::DeadBubbleCoral { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_FIRE_CORAL" => Ok(Material::DeadFireCoral { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_HORN_CORAL" => Ok(Material::DeadHornCoral { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_TUBE_CORAL" => Ok(Material::DeadTubeCoral { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TUBE_CORAL_FAN" => Ok(Material::TubeCoralFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BRAIN_CORAL_FAN" => Ok(Material::BrainCoralFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BUBBLE_CORAL_FAN" => Ok(Material::BubbleCoralFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FIRE_CORAL_FAN" => Ok(Material::FireCoralFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HORN_CORAL_FAN" => Ok(Material::HornCoralFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_TUBE_CORAL_FAN" => Ok(Material::DeadTubeCoralFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_BRAIN_CORAL_FAN" => Ok(Material::DeadBrainCoralFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_BUBBLE_CORAL_FAN" => Ok(Material::DeadBubbleCoralFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_FIRE_CORAL_FAN" => Ok(Material::DeadFireCoralFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_HORN_CORAL_FAN" => Ok(Material::DeadHornCoralFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_ICE" => Ok(Material::BlueIce { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CONDUIT" => Ok(Material::Conduit { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_GRANITE_STAIRS" => Ok(Material::PolishedGraniteStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOOTH_RED_SANDSTONE_STAIRS" => Ok(Material::SmoothRedSandstoneStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOSSY_STONE_BRICK_STAIRS" => Ok(Material::MossyStoneBrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_DIORITE_STAIRS" => Ok(Material::PolishedDioriteStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOSSY_COBBLESTONE_STAIRS" => Ok(Material::MossyCobblestoneStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "END_STONE_BRICK_STAIRS" => Ok(Material::EndStoneBrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_STAIRS" => Ok(Material::StoneStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOOTH_SANDSTONE_STAIRS" => Ok(Material::SmoothSandstoneStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOOTH_QUARTZ_STAIRS" => Ok(Material::SmoothQuartzStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRANITE_STAIRS" => Ok(Material::GraniteStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ANDESITE_STAIRS" => Ok(Material::AndesiteStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_NETHER_BRICK_STAIRS" => Ok(Material::RedNetherBrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_ANDESITE_STAIRS" => Ok(Material::PolishedAndesiteStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIORITE_STAIRS" => Ok(Material::DioriteStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COBBLED_DEEPSLATE_STAIRS" => Ok(Material::CobbledDeepslateStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_DEEPSLATE_STAIRS" => Ok(Material::PolishedDeepslateStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_BRICK_STAIRS" => Ok(Material::DeepslateBrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_TILE_STAIRS" => Ok(Material::DeepslateTileStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_GRANITE_SLAB" => Ok(Material::PolishedGraniteSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOOTH_RED_SANDSTONE_SLAB" => Ok(Material::SmoothRedSandstoneSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOSSY_STONE_BRICK_SLAB" => Ok(Material::MossyStoneBrickSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_DIORITE_SLAB" => Ok(Material::PolishedDioriteSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOSSY_COBBLESTONE_SLAB" => Ok(Material::MossyCobblestoneSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "END_STONE_BRICK_SLAB" => Ok(Material::EndStoneBrickSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOOTH_SANDSTONE_SLAB" => Ok(Material::SmoothSandstoneSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOOTH_QUARTZ_SLAB" => Ok(Material::SmoothQuartzSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRANITE_SLAB" => Ok(Material::GraniteSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ANDESITE_SLAB" => Ok(Material::AndesiteSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_NETHER_BRICK_SLAB" => Ok(Material::RedNetherBrickSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_ANDESITE_SLAB" => Ok(Material::PolishedAndesiteSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIORITE_SLAB" => Ok(Material::DioriteSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COBBLED_DEEPSLATE_SLAB" => Ok(Material::CobbledDeepslateSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_DEEPSLATE_SLAB" => Ok(Material::PolishedDeepslateSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_BRICK_SLAB" => Ok(Material::DeepslateBrickSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_TILE_SLAB" => Ok(Material::DeepslateTileSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SCAFFOLDING" => Ok(Material::Scaffolding { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "REDSTONE" => Ok(Material::Redstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "REDSTONE_TORCH" => Ok(Material::RedstoneTorch { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "REDSTONE_BLOCK" => Ok(Material::RedstoneBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "REPEATER" => Ok(Material::Repeater { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COMPARATOR" => Ok(Material::Comparator { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PISTON" => Ok(Material::Piston { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STICKY_PISTON" => Ok(Material::StickyPiston { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SLIME_BLOCK" => Ok(Material::SlimeBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HONEY_BLOCK" => Ok(Material::HoneyBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OBSERVER" => Ok(Material::Observer { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HOPPER" => Ok(Material::Hopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DISPENSER" => Ok(Material::Dispenser { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DROPPER" => Ok(Material::Dropper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LECTERN" => Ok(Material::Lectern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TARGET" => Ok(Material::Target { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEVER" => Ok(Material::Lever { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHTNING_ROD" => Ok(Material::LightningRod { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DAYLIGHT_DETECTOR" => Ok(Material::DaylightDetector { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SCULK_SENSOR" => Ok(Material::SculkSensor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CALIBRATED_SCULK_SENSOR" => Ok(Material::CalibratedSculkSensor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TRIPWIRE_HOOK" => Ok(Material::TripwireHook { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TRAPPED_CHEST" => Ok(Material::TrappedChest { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TNT" => Ok(Material::Tnt { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "REDSTONE_LAMP" => Ok(Material::RedstoneLamp { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NOTE_BLOCK" => Ok(Material::NoteBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_BUTTON" => Ok(Material::StoneButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_BLACKSTONE_BUTTON" => Ok(Material::PolishedBlackstoneButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_BUTTON" => Ok(Material::OakButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_BUTTON" => Ok(Material::SpruceButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_BUTTON" => Ok(Material::BirchButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_BUTTON" => Ok(Material::JungleButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_BUTTON" => Ok(Material::AcaciaButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_BUTTON" => Ok(Material::CherryButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_BUTTON" => Ok(Material::DarkOakButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_BUTTON" => Ok(Material::MangroveButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_BUTTON" => Ok(Material::BambooButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_BUTTON" => Ok(Material::CrimsonButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_BUTTON" => Ok(Material::WarpedButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_PRESSURE_PLATE" => Ok(Material::StonePressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_BLACKSTONE_PRESSURE_PLATE" => Ok(Material::PolishedBlackstonePressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_WEIGHTED_PRESSURE_PLATE" => Ok(Material::LightWeightedPressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HEAVY_WEIGHTED_PRESSURE_PLATE" => Ok(Material::HeavyWeightedPressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_PRESSURE_PLATE" => Ok(Material::OakPressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_PRESSURE_PLATE" => Ok(Material::SprucePressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_PRESSURE_PLATE" => Ok(Material::BirchPressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_PRESSURE_PLATE" => Ok(Material::JunglePressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_PRESSURE_PLATE" => Ok(Material::AcaciaPressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_PRESSURE_PLATE" => Ok(Material::CherryPressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_PRESSURE_PLATE" => Ok(Material::DarkOakPressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_PRESSURE_PLATE" => Ok(Material::MangrovePressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_PRESSURE_PLATE" => Ok(Material::BambooPressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_PRESSURE_PLATE" => Ok(Material::CrimsonPressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_PRESSURE_PLATE" => Ok(Material::WarpedPressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_DOOR" => Ok(Material::IronDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_DOOR" => Ok(Material::OakDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_DOOR" => Ok(Material::SpruceDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_DOOR" => Ok(Material::BirchDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_DOOR" => Ok(Material::JungleDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_DOOR" => Ok(Material::AcaciaDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_DOOR" => Ok(Material::CherryDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_DOOR" => Ok(Material::DarkOakDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_DOOR" => Ok(Material::MangroveDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_DOOR" => Ok(Material::BambooDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_DOOR" => Ok(Material::CrimsonDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_DOOR" => Ok(Material::WarpedDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COPPER_DOOR" => Ok(Material::CopperDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EXPOSED_COPPER_DOOR" => Ok(Material::ExposedCopperDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WEATHERED_COPPER_DOOR" => Ok(Material::WeatheredCopperDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OXIDIZED_COPPER_DOOR" => Ok(Material::OxidizedCopperDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_COPPER_DOOR" => Ok(Material::WaxedCopperDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_EXPOSED_COPPER_DOOR" => Ok(Material::WaxedExposedCopperDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_WEATHERED_COPPER_DOOR" => Ok(Material::WaxedWeatheredCopperDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_OXIDIZED_COPPER_DOOR" => Ok(Material::WaxedOxidizedCopperDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_TRAPDOOR" => Ok(Material::IronTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_TRAPDOOR" => Ok(Material::OakTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_TRAPDOOR" => Ok(Material::SpruceTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_TRAPDOOR" => Ok(Material::BirchTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_TRAPDOOR" => Ok(Material::JungleTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_TRAPDOOR" => Ok(Material::AcaciaTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_TRAPDOOR" => Ok(Material::CherryTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_TRAPDOOR" => Ok(Material::DarkOakTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_TRAPDOOR" => Ok(Material::MangroveTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_TRAPDOOR" => Ok(Material::BambooTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_TRAPDOOR" => Ok(Material::CrimsonTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_TRAPDOOR" => Ok(Material::WarpedTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COPPER_TRAPDOOR" => Ok(Material::CopperTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EXPOSED_COPPER_TRAPDOOR" => Ok(Material::ExposedCopperTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WEATHERED_COPPER_TRAPDOOR" => Ok(Material::WeatheredCopperTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OXIDIZED_COPPER_TRAPDOOR" => Ok(Material::OxidizedCopperTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_COPPER_TRAPDOOR" => Ok(Material::WaxedCopperTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_EXPOSED_COPPER_TRAPDOOR" => Ok(Material::WaxedExposedCopperTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_WEATHERED_COPPER_TRAPDOOR" => Ok(Material::WaxedWeatheredCopperTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_OXIDIZED_COPPER_TRAPDOOR" => Ok(Material::WaxedOxidizedCopperTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_FENCE_GATE" => Ok(Material::OakFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_FENCE_GATE" => Ok(Material::SpruceFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_FENCE_GATE" => Ok(Material::BirchFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_FENCE_GATE" => Ok(Material::JungleFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_FENCE_GATE" => Ok(Material::AcaciaFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_FENCE_GATE" => Ok(Material::CherryFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_FENCE_GATE" => Ok(Material::DarkOakFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_FENCE_GATE" => Ok(Material::MangroveFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_FENCE_GATE" => Ok(Material::BambooFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_FENCE_GATE" => Ok(Material::CrimsonFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_FENCE_GATE" => Ok(Material::WarpedFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POWERED_RAIL" => Ok(Material::PoweredRail { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DETECTOR_RAIL" => Ok(Material::DetectorRail { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RAIL" => Ok(Material::Rail { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACTIVATOR_RAIL" => Ok(Material::ActivatorRail { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SADDLE" => Ok(Material::Saddle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MINECART" => Ok(Material::Minecart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHEST_MINECART" => Ok(Material::ChestMinecart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FURNACE_MINECART" => Ok(Material::FurnaceMinecart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TNT_MINECART" => Ok(Material::TntMinecart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HOPPER_MINECART" => Ok(Material::HopperMinecart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CARROT_ON_A_STICK" => Ok(Material::CarrotOnAStick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_FUNGUS_ON_A_STICK" => Ok(Material::WarpedFungusOnAStick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ELYTRA" => Ok(Material::Elytra { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_BOAT" => Ok(Material::OakBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_CHEST_BOAT" => Ok(Material::OakChestBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_BOAT" => Ok(Material::SpruceBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_CHEST_BOAT" => Ok(Material::SpruceChestBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_BOAT" => Ok(Material::BirchBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_CHEST_BOAT" => Ok(Material::BirchChestBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_BOAT" => Ok(Material::JungleBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_CHEST_BOAT" => Ok(Material::JungleChestBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_BOAT" => Ok(Material::AcaciaBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_CHEST_BOAT" => Ok(Material::AcaciaChestBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_BOAT" => Ok(Material::CherryBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_CHEST_BOAT" => Ok(Material::CherryChestBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_BOAT" => Ok(Material::DarkOakBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_CHEST_BOAT" => Ok(Material::DarkOakChestBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_BOAT" => Ok(Material::MangroveBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_CHEST_BOAT" => Ok(Material::MangroveChestBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_RAFT" => Ok(Material::BambooRaft { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_CHEST_RAFT" => Ok(Material::BambooChestRaft { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRUCTURE_BLOCK" => Ok(Material::StructureBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JIGSAW" => Ok(Material::Jigsaw { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TURTLE_HELMET" => Ok(Material::TurtleHelmet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TURTLE_SCUTE" => Ok(Material::TurtleScute { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ARMADILLO_SCUTE" => Ok(Material::ArmadilloScute { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WOLF_ARMOR" => Ok(Material::WolfArmor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FLINT_AND_STEEL" => Ok(Material::FlintAndSteel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BOWL" => Ok(Material::Bowl { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "APPLE" => Ok(Material::Apple { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BOW" => Ok(Material::Bow { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ARROW" => Ok(Material::Arrow { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COAL" => Ok(Material::Coal { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHARCOAL" => Ok(Material::Charcoal { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND" => Ok(Material::Diamond { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EMERALD" => Ok(Material::Emerald { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LAPIS_LAZULI" => Ok(Material::LapisLazuli { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "QUARTZ" => Ok(Material::Quartz { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "AMETHYST_SHARD" => Ok(Material::AmethystShard { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RAW_IRON" => Ok(Material::RawIron { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_INGOT" => Ok(Material::IronIngot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RAW_COPPER" => Ok(Material::RawCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COPPER_INGOT" => Ok(Material::CopperIngot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RAW_GOLD" => Ok(Material::RawGold { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLD_INGOT" => Ok(Material::GoldIngot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_INGOT" => Ok(Material::NetheriteIngot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_SCRAP" => Ok(Material::NetheriteScrap { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WOODEN_SWORD" => Ok(Material::WoodenSword { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WOODEN_SHOVEL" => Ok(Material::WoodenShovel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WOODEN_PICKAXE" => Ok(Material::WoodenPickaxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WOODEN_AXE" => Ok(Material::WoodenAxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WOODEN_HOE" => Ok(Material::WoodenHoe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_SWORD" => Ok(Material::StoneSword { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_SHOVEL" => Ok(Material::StoneShovel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_PICKAXE" => Ok(Material::StonePickaxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_AXE" => Ok(Material::StoneAxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_HOE" => Ok(Material::StoneHoe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLDEN_SWORD" => Ok(Material::GoldenSword { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLDEN_SHOVEL" => Ok(Material::GoldenShovel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLDEN_PICKAXE" => Ok(Material::GoldenPickaxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLDEN_AXE" => Ok(Material::GoldenAxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLDEN_HOE" => Ok(Material::GoldenHoe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_SWORD" => Ok(Material::IronSword { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_SHOVEL" => Ok(Material::IronShovel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_PICKAXE" => Ok(Material::IronPickaxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_AXE" => Ok(Material::IronAxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_HOE" => Ok(Material::IronHoe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND_SWORD" => Ok(Material::DiamondSword { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND_SHOVEL" => Ok(Material::DiamondShovel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND_PICKAXE" => Ok(Material::DiamondPickaxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND_AXE" => Ok(Material::DiamondAxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND_HOE" => Ok(Material::DiamondHoe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_SWORD" => Ok(Material::NetheriteSword { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_SHOVEL" => Ok(Material::NetheriteShovel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_PICKAXE" => Ok(Material::NetheritePickaxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_AXE" => Ok(Material::NetheriteAxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_HOE" => Ok(Material::NetheriteHoe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STICK" => Ok(Material::Stick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSHROOM_STEW" => Ok(Material::MushroomStew { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRING" => Ok(Material::String { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FEATHER" => Ok(Material::Feather { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GUNPOWDER" => Ok(Material::Gunpowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHEAT_SEEDS" => Ok(Material::WheatSeeds { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHEAT" => Ok(Material::Wheat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BREAD" => Ok(Material::Bread { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEATHER_HELMET" => Ok(Material::LeatherHelmet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEATHER_CHESTPLATE" => Ok(Material::LeatherChestplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEATHER_LEGGINGS" => Ok(Material::LeatherLeggings { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEATHER_BOOTS" => Ok(Material::LeatherBoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHAINMAIL_HELMET" => Ok(Material::ChainmailHelmet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHAINMAIL_CHESTPLATE" => Ok(Material::ChainmailChestplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHAINMAIL_LEGGINGS" => Ok(Material::ChainmailLeggings { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHAINMAIL_BOOTS" => Ok(Material::ChainmailBoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_HELMET" => Ok(Material::IronHelmet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_CHESTPLATE" => Ok(Material::IronChestplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_LEGGINGS" => Ok(Material::IronLeggings { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_BOOTS" => Ok(Material::IronBoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND_HELMET" => Ok(Material::DiamondHelmet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND_CHESTPLATE" => Ok(Material::DiamondChestplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND_LEGGINGS" => Ok(Material::DiamondLeggings { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND_BOOTS" => Ok(Material::DiamondBoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLDEN_HELMET" => Ok(Material::GoldenHelmet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLDEN_CHESTPLATE" => Ok(Material::GoldenChestplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLDEN_LEGGINGS" => Ok(Material::GoldenLeggings { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLDEN_BOOTS" => Ok(Material::GoldenBoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_HELMET" => Ok(Material::NetheriteHelmet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_CHESTPLATE" => Ok(Material::NetheriteChestplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_LEGGINGS" => Ok(Material::NetheriteLeggings { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_BOOTS" => Ok(Material::NetheriteBoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FLINT" => Ok(Material::Flint { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PORKCHOP" => Ok(Material::Porkchop { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COOKED_PORKCHOP" => Ok(Material::CookedPorkchop { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PAINTING" => Ok(Material::Painting { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLDEN_APPLE" => Ok(Material::GoldenApple { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ENCHANTED_GOLDEN_APPLE" => Ok(Material::EnchantedGoldenApple { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_SIGN" => Ok(Material::OakSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_SIGN" => Ok(Material::SpruceSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_SIGN" => Ok(Material::BirchSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_SIGN" => Ok(Material::JungleSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_SIGN" => Ok(Material::AcaciaSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_SIGN" => Ok(Material::CherrySign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_SIGN" => Ok(Material::DarkOakSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_SIGN" => Ok(Material::MangroveSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_SIGN" => Ok(Material::BambooSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_SIGN" => Ok(Material::CrimsonSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_SIGN" => Ok(Material::WarpedSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_HANGING_SIGN" => Ok(Material::OakHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_HANGING_SIGN" => Ok(Material::SpruceHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_HANGING_SIGN" => Ok(Material::BirchHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_HANGING_SIGN" => Ok(Material::JungleHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_HANGING_SIGN" => Ok(Material::AcaciaHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_HANGING_SIGN" => Ok(Material::CherryHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_HANGING_SIGN" => Ok(Material::DarkOakHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_HANGING_SIGN" => Ok(Material::MangroveHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_HANGING_SIGN" => Ok(Material::BambooHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_HANGING_SIGN" => Ok(Material::CrimsonHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_HANGING_SIGN" => Ok(Material::WarpedHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BUCKET" => Ok(Material::Bucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WATER_BUCKET" => Ok(Material::WaterBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LAVA_BUCKET" => Ok(Material::LavaBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POWDER_SNOW_BUCKET" => Ok(Material::PowderSnowBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SNOWBALL" => Ok(Material::Snowball { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEATHER" => Ok(Material::Leather { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MILK_BUCKET" => Ok(Material::MilkBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PUFFERFISH_BUCKET" => Ok(Material::PufferfishBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SALMON_BUCKET" => Ok(Material::SalmonBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COD_BUCKET" => Ok(Material::CodBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TROPICAL_FISH_BUCKET" => Ok(Material::TropicalFishBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "AXOLOTL_BUCKET" => Ok(Material::AxolotlBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TADPOLE_BUCKET" => Ok(Material::TadpoleBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BRICK" => Ok(Material::Brick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CLAY_BALL" => Ok(Material::ClayBall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DRIED_KELP_BLOCK" => Ok(Material::DriedKelpBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PAPER" => Ok(Material::Paper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BOOK" => Ok(Material::Book { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SLIME_BALL" => Ok(Material::SlimeBall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EGG" => Ok(Material::Egg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COMPASS" => Ok(Material::Compass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RECOVERY_COMPASS" => Ok(Material::RecoveryCompass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BUNDLE" => Ok(Material::Bundle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FISHING_ROD" => Ok(Material::FishingRod { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CLOCK" => Ok(Material::Clock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPYGLASS" => Ok(Material::Spyglass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GLOWSTONE_DUST" => Ok(Material::GlowstoneDust { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COD" => Ok(Material::Cod { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SALMON" => Ok(Material::Salmon { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TROPICAL_FISH" => Ok(Material::TropicalFish { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PUFFERFISH" => Ok(Material::Pufferfish { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COOKED_COD" => Ok(Material::CookedCod { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COOKED_SALMON" => Ok(Material::CookedSalmon { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "INK_SAC" => Ok(Material::InkSac { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GLOW_INK_SAC" => Ok(Material::GlowInkSac { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COCOA_BEANS" => Ok(Material::CocoaBeans { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_DYE" => Ok(Material::WhiteDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_DYE" => Ok(Material::OrangeDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_DYE" => Ok(Material::MagentaDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_DYE" => Ok(Material::LightBlueDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_DYE" => Ok(Material::YellowDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_DYE" => Ok(Material::LimeDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_DYE" => Ok(Material::PinkDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_DYE" => Ok(Material::GrayDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_DYE" => Ok(Material::LightGrayDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_DYE" => Ok(Material::CyanDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_DYE" => Ok(Material::PurpleDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_DYE" => Ok(Material::BlueDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_DYE" => Ok(Material::BrownDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_DYE" => Ok(Material::GreenDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_DYE" => Ok(Material::RedDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_DYE" => Ok(Material::BlackDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BONE_MEAL" => Ok(Material::BoneMeal { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BONE" => Ok(Material::Bone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SUGAR" => Ok(Material::Sugar { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CAKE" => Ok(Material::Cake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_BED" => Ok(Material::WhiteBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_BED" => Ok(Material::OrangeBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_BED" => Ok(Material::MagentaBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_BED" => Ok(Material::LightBlueBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_BED" => Ok(Material::YellowBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_BED" => Ok(Material::LimeBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_BED" => Ok(Material::PinkBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_BED" => Ok(Material::GrayBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_BED" => Ok(Material::LightGrayBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_BED" => Ok(Material::CyanBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_BED" => Ok(Material::PurpleBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_BED" => Ok(Material::BlueBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_BED" => Ok(Material::BrownBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_BED" => Ok(Material::GreenBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_BED" => Ok(Material::RedBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_BED" => Ok(Material::BlackBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COOKIE" => Ok(Material::Cookie { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRAFTER" => Ok(Material::Crafter { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FILLED_MAP" => Ok(Material::FilledMap { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SHEARS" => Ok(Material::Shears { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MELON_SLICE" => Ok(Material::MelonSlice { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DRIED_KELP" => Ok(Material::DriedKelp { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PUMPKIN_SEEDS" => Ok(Material::PumpkinSeeds { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MELON_SEEDS" => Ok(Material::MelonSeeds { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BEEF" => Ok(Material::Beef { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COOKED_BEEF" => Ok(Material::CookedBeef { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHICKEN" => Ok(Material::Chicken { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COOKED_CHICKEN" => Ok(Material::CookedChicken { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ROTTEN_FLESH" => Ok(Material::RottenFlesh { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ENDER_PEARL" => Ok(Material::EnderPearl { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLAZE_ROD" => Ok(Material::BlazeRod { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GHAST_TEAR" => Ok(Material::GhastTear { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLD_NUGGET" => Ok(Material::GoldNugget { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_WART" => Ok(Material::NetherWart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTION" => Ok(Material::Potion { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GLASS_BOTTLE" => Ok(Material::GlassBottle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPIDER_EYE" => Ok(Material::SpiderEye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FERMENTED_SPIDER_EYE" => Ok(Material::FermentedSpiderEye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLAZE_POWDER" => Ok(Material::BlazePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGMA_CREAM" => Ok(Material::MagmaCream { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BREWING_STAND" => Ok(Material::BrewingStand { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CAULDRON" => Ok(Material::Cauldron { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ENDER_EYE" => Ok(Material::EnderEye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GLISTERING_MELON_SLICE" => Ok(Material::GlisteringMelonSlice { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ARMADILLO_SPAWN_EGG" => Ok(Material::ArmadilloSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ALLAY_SPAWN_EGG" => Ok(Material::AllaySpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "AXOLOTL_SPAWN_EGG" => Ok(Material::AxolotlSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAT_SPAWN_EGG" => Ok(Material::BatSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BEE_SPAWN_EGG" => Ok(Material::BeeSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLAZE_SPAWN_EGG" => Ok(Material::BlazeSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BOGGED_SPAWN_EGG" => Ok(Material::BoggedSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BREEZE_SPAWN_EGG" => Ok(Material::BreezeSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CAT_SPAWN_EGG" => Ok(Material::CatSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CAMEL_SPAWN_EGG" => Ok(Material::CamelSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CAVE_SPIDER_SPAWN_EGG" => Ok(Material::CaveSpiderSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHICKEN_SPAWN_EGG" => Ok(Material::ChickenSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COD_SPAWN_EGG" => Ok(Material::CodSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COW_SPAWN_EGG" => Ok(Material::CowSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CREEPER_SPAWN_EGG" => Ok(Material::CreeperSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DOLPHIN_SPAWN_EGG" => Ok(Material::DolphinSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DONKEY_SPAWN_EGG" => Ok(Material::DonkeySpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DROWNED_SPAWN_EGG" => Ok(Material::DrownedSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ELDER_GUARDIAN_SPAWN_EGG" => Ok(Material::ElderGuardianSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ENDER_DRAGON_SPAWN_EGG" => Ok(Material::EnderDragonSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ENDERMAN_SPAWN_EGG" => Ok(Material::EndermanSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ENDERMITE_SPAWN_EGG" => Ok(Material::EndermiteSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EVOKER_SPAWN_EGG" => Ok(Material::EvokerSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FOX_SPAWN_EGG" => Ok(Material::FoxSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FROG_SPAWN_EGG" => Ok(Material::FrogSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GHAST_SPAWN_EGG" => Ok(Material::GhastSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GLOW_SQUID_SPAWN_EGG" => Ok(Material::GlowSquidSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOAT_SPAWN_EGG" => Ok(Material::GoatSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GUARDIAN_SPAWN_EGG" => Ok(Material::GuardianSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HOGLIN_SPAWN_EGG" => Ok(Material::HoglinSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HORSE_SPAWN_EGG" => Ok(Material::HorseSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HUSK_SPAWN_EGG" => Ok(Material::HuskSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_GOLEM_SPAWN_EGG" => Ok(Material::IronGolemSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LLAMA_SPAWN_EGG" => Ok(Material::LlamaSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGMA_CUBE_SPAWN_EGG" => Ok(Material::MagmaCubeSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOOSHROOM_SPAWN_EGG" => Ok(Material::MooshroomSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MULE_SPAWN_EGG" => Ok(Material::MuleSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OCELOT_SPAWN_EGG" => Ok(Material::OcelotSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PANDA_SPAWN_EGG" => Ok(Material::PandaSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PARROT_SPAWN_EGG" => Ok(Material::ParrotSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PHANTOM_SPAWN_EGG" => Ok(Material::PhantomSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PIG_SPAWN_EGG" => Ok(Material::PigSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PIGLIN_SPAWN_EGG" => Ok(Material::PiglinSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PIGLIN_BRUTE_SPAWN_EGG" => Ok(Material::PiglinBruteSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PILLAGER_SPAWN_EGG" => Ok(Material::PillagerSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLAR_BEAR_SPAWN_EGG" => Ok(Material::PolarBearSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PUFFERFISH_SPAWN_EGG" => Ok(Material::PufferfishSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RABBIT_SPAWN_EGG" => Ok(Material::RabbitSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RAVAGER_SPAWN_EGG" => Ok(Material::RavagerSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SALMON_SPAWN_EGG" => Ok(Material::SalmonSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SHEEP_SPAWN_EGG" => Ok(Material::SheepSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SHULKER_SPAWN_EGG" => Ok(Material::ShulkerSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SILVERFISH_SPAWN_EGG" => Ok(Material::SilverfishSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SKELETON_SPAWN_EGG" => Ok(Material::SkeletonSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SKELETON_HORSE_SPAWN_EGG" => Ok(Material::SkeletonHorseSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SLIME_SPAWN_EGG" => Ok(Material::SlimeSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SNIFFER_SPAWN_EGG" => Ok(Material::SnifferSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SNOW_GOLEM_SPAWN_EGG" => Ok(Material::SnowGolemSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPIDER_SPAWN_EGG" => Ok(Material::SpiderSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SQUID_SPAWN_EGG" => Ok(Material::SquidSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRAY_SPAWN_EGG" => Ok(Material::StraySpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIDER_SPAWN_EGG" => Ok(Material::StriderSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TADPOLE_SPAWN_EGG" => Ok(Material::TadpoleSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TRADER_LLAMA_SPAWN_EGG" => Ok(Material::TraderLlamaSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TROPICAL_FISH_SPAWN_EGG" => Ok(Material::TropicalFishSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TURTLE_SPAWN_EGG" => Ok(Material::TurtleSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "VEX_SPAWN_EGG" => Ok(Material::VexSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "VILLAGER_SPAWN_EGG" => Ok(Material::VillagerSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "VINDICATOR_SPAWN_EGG" => Ok(Material::VindicatorSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WANDERING_TRADER_SPAWN_EGG" => Ok(Material::WanderingTraderSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARDEN_SPAWN_EGG" => Ok(Material::WardenSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WITCH_SPAWN_EGG" => Ok(Material::WitchSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WITHER_SPAWN_EGG" => Ok(Material::WitherSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WITHER_SKELETON_SPAWN_EGG" => Ok(Material::WitherSkeletonSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WOLF_SPAWN_EGG" => Ok(Material::WolfSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ZOGLIN_SPAWN_EGG" => Ok(Material::ZoglinSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ZOMBIE_SPAWN_EGG" => Ok(Material::ZombieSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ZOMBIE_HORSE_SPAWN_EGG" => Ok(Material::ZombieHorseSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ZOMBIE_VILLAGER_SPAWN_EGG" => Ok(Material::ZombieVillagerSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ZOMBIFIED_PIGLIN_SPAWN_EGG" => Ok(Material::ZombifiedPiglinSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EXPERIENCE_BOTTLE" => Ok(Material::ExperienceBottle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FIRE_CHARGE" => Ok(Material::FireCharge { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WIND_CHARGE" => Ok(Material::WindCharge { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WRITABLE_BOOK" => Ok(Material::WritableBook { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WRITTEN_BOOK" => Ok(Material::WrittenBook { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MACE" => Ok(Material::Mace { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ITEM_FRAME" => Ok(Material::ItemFrame { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GLOW_ITEM_FRAME" => Ok(Material::GlowItemFrame { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FLOWER_POT" => Ok(Material::FlowerPot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CARROT" => Ok(Material::Carrot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTATO" => Ok(Material::Potato { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAKED_POTATO" => Ok(Material::BakedPotato { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POISONOUS_POTATO" => Ok(Material::PoisonousPotato { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAP" => Ok(Material::Map { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLDEN_CARROT" => Ok(Material::GoldenCarrot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SKELETON_SKULL" => Ok(Material::SkeletonSkull { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WITHER_SKELETON_SKULL" => Ok(Material::WitherSkeletonSkull { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PLAYER_HEAD" => Ok(Material::PlayerHead { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ZOMBIE_HEAD" => Ok(Material::ZombieHead { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CREEPER_HEAD" => Ok(Material::CreeperHead { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DRAGON_HEAD" => Ok(Material::DragonHead { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PIGLIN_HEAD" => Ok(Material::PiglinHead { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_STAR" => Ok(Material::NetherStar { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PUMPKIN_PIE" => Ok(Material::PumpkinPie { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FIREWORK_ROCKET" => Ok(Material::FireworkRocket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FIREWORK_STAR" => Ok(Material::FireworkStar { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ENCHANTED_BOOK" => Ok(Material::EnchantedBook { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_BRICK" => Ok(Material::NetherBrick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PRISMARINE_SHARD" => Ok(Material::PrismarineShard { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PRISMARINE_CRYSTALS" => Ok(Material::PrismarineCrystals { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RABBIT" => Ok(Material::Rabbit { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COOKED_RABBIT" => Ok(Material::CookedRabbit { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RABBIT_STEW" => Ok(Material::RabbitStew { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RABBIT_FOOT" => Ok(Material::RabbitFoot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RABBIT_HIDE" => Ok(Material::RabbitHide { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ARMOR_STAND" => Ok(Material::ArmorStand { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_HORSE_ARMOR" => Ok(Material::IronHorseArmor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLDEN_HORSE_ARMOR" => Ok(Material::GoldenHorseArmor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND_HORSE_ARMOR" => Ok(Material::DiamondHorseArmor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEATHER_HORSE_ARMOR" => Ok(Material::LeatherHorseArmor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEAD" => Ok(Material::Lead { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NAME_TAG" => Ok(Material::NameTag { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COMMAND_BLOCK_MINECART" => Ok(Material::CommandBlockMinecart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUTTON" => Ok(Material::Mutton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COOKED_MUTTON" => Ok(Material::CookedMutton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_BANNER" => Ok(Material::WhiteBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_BANNER" => Ok(Material::OrangeBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_BANNER" => Ok(Material::MagentaBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_BANNER" => Ok(Material::LightBlueBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_BANNER" => Ok(Material::YellowBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_BANNER" => Ok(Material::LimeBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_BANNER" => Ok(Material::PinkBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_BANNER" => Ok(Material::GrayBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_BANNER" => Ok(Material::LightGrayBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_BANNER" => Ok(Material::CyanBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_BANNER" => Ok(Material::PurpleBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_BANNER" => Ok(Material::BlueBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_BANNER" => Ok(Material::BrownBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_BANNER" => Ok(Material::GreenBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_BANNER" => Ok(Material::RedBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_BANNER" => Ok(Material::BlackBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "END_CRYSTAL" => Ok(Material::EndCrystal { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHORUS_FRUIT" => Ok(Material::ChorusFruit { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POPPED_CHORUS_FRUIT" => Ok(Material::PoppedChorusFruit { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TORCHFLOWER_SEEDS" => Ok(Material::TorchflowerSeeds { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PITCHER_POD" => Ok(Material::PitcherPod { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BEETROOT" => Ok(Material::Beetroot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BEETROOT_SEEDS" => Ok(Material::BeetrootSeeds { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BEETROOT_SOUP" => Ok(Material::BeetrootSoup { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DRAGON_BREATH" => Ok(Material::DragonBreath { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPLASH_POTION" => Ok(Material::SplashPotion { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPECTRAL_ARROW" => Ok(Material::SpectralArrow { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TIPPED_ARROW" => Ok(Material::TippedArrow { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LINGERING_POTION" => Ok(Material::LingeringPotion { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SHIELD" => Ok(Material::Shield { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TOTEM_OF_UNDYING" => Ok(Material::TotemOfUndying { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SHULKER_SHELL" => Ok(Material::ShulkerShell { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_NUGGET" => Ok(Material::IronNugget { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "KNOWLEDGE_BOOK" => Ok(Material::KnowledgeBook { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEBUG_STICK" => Ok(Material::DebugStick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_13" => Ok(Material::MusicDisc13 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_CAT" => Ok(Material::MusicDiscCat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_BLOCKS" => Ok(Material::MusicDiscBlocks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_CHIRP" => Ok(Material::MusicDiscChirp { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_CREATOR" => Ok(Material::MusicDiscCreator { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_CREATOR_MUSIC_BOX" => Ok(Material::MusicDiscCreatorMusicBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_FAR" => Ok(Material::MusicDiscFar { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_MALL" => Ok(Material::MusicDiscMall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_MELLOHI" => Ok(Material::MusicDiscMellohi { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_STAL" => Ok(Material::MusicDiscStal { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_STRAD" => Ok(Material::MusicDiscStrad { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_WARD" => Ok(Material::MusicDiscWard { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_11" => Ok(Material::MusicDisc11 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_WAIT" => Ok(Material::MusicDiscWait { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_OTHERSIDE" => Ok(Material::MusicDiscOtherside { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_RELIC" => Ok(Material::MusicDiscRelic { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_5" => Ok(Material::MusicDisc5 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_PIGSTEP" => Ok(Material::MusicDiscPigstep { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_PRECIPICE" => Ok(Material::MusicDiscPrecipice { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DISC_FRAGMENT_5" => Ok(Material::DiscFragment5 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TRIDENT" => Ok(Material::Trident { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PHANTOM_MEMBRANE" => Ok(Material::PhantomMembrane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NAUTILUS_SHELL" => Ok(Material::NautilusShell { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HEART_OF_THE_SEA" => Ok(Material::HeartOfTheSea { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CROSSBOW" => Ok(Material::Crossbow { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SUSPICIOUS_STEW" => Ok(Material::SuspiciousStew { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LOOM" => Ok(Material::Loom { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FLOWER_BANNER_PATTERN" => Ok(Material::FlowerBannerPattern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CREEPER_BANNER_PATTERN" => Ok(Material::CreeperBannerPattern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SKULL_BANNER_PATTERN" => Ok(Material::SkullBannerPattern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOJANG_BANNER_PATTERN" => Ok(Material::MojangBannerPattern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GLOBE_BANNER_PATTERN" => Ok(Material::GlobeBannerPattern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PIGLIN_BANNER_PATTERN" => Ok(Material::PiglinBannerPattern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FLOW_BANNER_PATTERN" => Ok(Material::FlowBannerPattern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GUSTER_BANNER_PATTERN" => Ok(Material::GusterBannerPattern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOAT_HORN" => Ok(Material::GoatHorn { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COMPOSTER" => Ok(Material::Composter { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BARREL" => Ok(Material::Barrel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOKER" => Ok(Material::Smoker { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLAST_FURNACE" => Ok(Material::BlastFurnace { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CARTOGRAPHY_TABLE" => Ok(Material::CartographyTable { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FLETCHING_TABLE" => Ok(Material::FletchingTable { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRINDSTONE" => Ok(Material::Grindstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMITHING_TABLE" => Ok(Material::SmithingTable { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONECUTTER" => Ok(Material::Stonecutter { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BELL" => Ok(Material::Bell { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LANTERN" => Ok(Material::Lantern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SOUL_LANTERN" => Ok(Material::SoulLantern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SWEET_BERRIES" => Ok(Material::SweetBerries { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GLOW_BERRIES" => Ok(Material::GlowBerries { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CAMPFIRE" => Ok(Material::Campfire { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SOUL_CAMPFIRE" => Ok(Material::SoulCampfire { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SHROOMLIGHT" => Ok(Material::Shroomlight { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HONEYCOMB" => Ok(Material::Honeycomb { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BEE_NEST" => Ok(Material::BeeNest { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BEEHIVE" => Ok(Material::Beehive { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HONEY_BOTTLE" => Ok(Material::HoneyBottle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HONEYCOMB_BLOCK" => Ok(Material::HoneycombBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LODESTONE" => Ok(Material::Lodestone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRYING_OBSIDIAN" => Ok(Material::CryingObsidian { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACKSTONE" => Ok(Material::Blackstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACKSTONE_SLAB" => Ok(Material::BlackstoneSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACKSTONE_STAIRS" => Ok(Material::BlackstoneStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GILDED_BLACKSTONE" => Ok(Material::GildedBlackstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_BLACKSTONE" => Ok(Material::PolishedBlackstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_BLACKSTONE_SLAB" => Ok(Material::PolishedBlackstoneSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_BLACKSTONE_STAIRS" => Ok(Material::PolishedBlackstoneStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHISELED_POLISHED_BLACKSTONE" => Ok(Material::ChiseledPolishedBlackstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_BLACKSTONE_BRICKS" => Ok(Material::PolishedBlackstoneBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_BLACKSTONE_BRICK_SLAB" => Ok(Material::PolishedBlackstoneBrickSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_BLACKSTONE_BRICK_STAIRS" => Ok(Material::PolishedBlackstoneBrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRACKED_POLISHED_BLACKSTONE_BRICKS" => Ok(Material::CrackedPolishedBlackstoneBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RESPAWN_ANCHOR" => Ok(Material::RespawnAnchor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CANDLE" => Ok(Material::Candle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_CANDLE" => Ok(Material::WhiteCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_CANDLE" => Ok(Material::OrangeCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_CANDLE" => Ok(Material::MagentaCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_CANDLE" => Ok(Material::LightBlueCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_CANDLE" => Ok(Material::YellowCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_CANDLE" => Ok(Material::LimeCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_CANDLE" => Ok(Material::PinkCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_CANDLE" => Ok(Material::GrayCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_CANDLE" => Ok(Material::LightGrayCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_CANDLE" => Ok(Material::CyanCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_CANDLE" => Ok(Material::PurpleCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_CANDLE" => Ok(Material::BlueCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_CANDLE" => Ok(Material::BrownCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_CANDLE" => Ok(Material::GreenCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_CANDLE" => Ok(Material::RedCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_CANDLE" => Ok(Material::BlackCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMALL_AMETHYST_BUD" => Ok(Material::SmallAmethystBud { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MEDIUM_AMETHYST_BUD" => Ok(Material::MediumAmethystBud { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LARGE_AMETHYST_BUD" => Ok(Material::LargeAmethystBud { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "AMETHYST_CLUSTER" => Ok(Material::AmethystCluster { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POINTED_DRIPSTONE" => Ok(Material::PointedDripstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OCHRE_FROGLIGHT" => Ok(Material::OchreFroglight { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "VERDANT_FROGLIGHT" => Ok(Material::VerdantFroglight { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PEARLESCENT_FROGLIGHT" => Ok(Material::PearlescentFroglight { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FROGSPAWN" => Ok(Material::Frogspawn { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ECHO_SHARD" => Ok(Material::EchoShard { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BRUSH" => Ok(Material::Brush { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_UPGRADE_SMITHING_TEMPLATE" => { + Ok(Material::NetheriteUpgradeSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "SENTRY_ARMOR_TRIM_SMITHING_TEMPLATE" => { + Ok(Material::SentryArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "DUNE_ARMOR_TRIM_SMITHING_TEMPLATE" => Ok(Material::DuneArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COAST_ARMOR_TRIM_SMITHING_TEMPLATE" => Ok(Material::CoastArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WILD_ARMOR_TRIM_SMITHING_TEMPLATE" => Ok(Material::WildArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARD_ARMOR_TRIM_SMITHING_TEMPLATE" => Ok(Material::WardArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EYE_ARMOR_TRIM_SMITHING_TEMPLATE" => Ok(Material::EyeArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "VEX_ARMOR_TRIM_SMITHING_TEMPLATE" => Ok(Material::VexArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TIDE_ARMOR_TRIM_SMITHING_TEMPLATE" => Ok(Material::TideArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SNOUT_ARMOR_TRIM_SMITHING_TEMPLATE" => Ok(Material::SnoutArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RIB_ARMOR_TRIM_SMITHING_TEMPLATE" => Ok(Material::RibArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPIRE_ARMOR_TRIM_SMITHING_TEMPLATE" => Ok(Material::SpireArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAYFINDER_ARMOR_TRIM_SMITHING_TEMPLATE" => { + Ok(Material::WayfinderArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "SHAPER_ARMOR_TRIM_SMITHING_TEMPLATE" => { + Ok(Material::ShaperArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "SILENCE_ARMOR_TRIM_SMITHING_TEMPLATE" => { + Ok(Material::SilenceArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "RAISER_ARMOR_TRIM_SMITHING_TEMPLATE" => { + Ok(Material::RaiserArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "HOST_ARMOR_TRIM_SMITHING_TEMPLATE" => Ok(Material::HostArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FLOW_ARMOR_TRIM_SMITHING_TEMPLATE" => Ok(Material::FlowArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BOLT_ARMOR_TRIM_SMITHING_TEMPLATE" => Ok(Material::BoltArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ANGLER_POTTERY_SHERD" => Ok(Material::AnglerPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ARCHER_POTTERY_SHERD" => Ok(Material::ArcherPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ARMS_UP_POTTERY_SHERD" => Ok(Material::ArmsUpPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLADE_POTTERY_SHERD" => Ok(Material::BladePotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BREWER_POTTERY_SHERD" => Ok(Material::BrewerPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BURN_POTTERY_SHERD" => Ok(Material::BurnPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DANGER_POTTERY_SHERD" => Ok(Material::DangerPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EXPLORER_POTTERY_SHERD" => Ok(Material::ExplorerPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FLOW_POTTERY_SHERD" => Ok(Material::FlowPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FRIEND_POTTERY_SHERD" => Ok(Material::FriendPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GUSTER_POTTERY_SHERD" => Ok(Material::GusterPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HEART_POTTERY_SHERD" => Ok(Material::HeartPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HEARTBREAK_POTTERY_SHERD" => Ok(Material::HeartbreakPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HOWL_POTTERY_SHERD" => Ok(Material::HowlPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MINER_POTTERY_SHERD" => Ok(Material::MinerPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOURNER_POTTERY_SHERD" => Ok(Material::MournerPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PLENTY_POTTERY_SHERD" => Ok(Material::PlentyPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PRIZE_POTTERY_SHERD" => Ok(Material::PrizePotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SCRAPE_POTTERY_SHERD" => Ok(Material::ScrapePotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SHEAF_POTTERY_SHERD" => Ok(Material::SheafPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SHELTER_POTTERY_SHERD" => Ok(Material::ShelterPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SKULL_POTTERY_SHERD" => Ok(Material::SkullPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SNORT_POTTERY_SHERD" => Ok(Material::SnortPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COPPER_GRATE" => Ok(Material::CopperGrate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EXPOSED_COPPER_GRATE" => Ok(Material::ExposedCopperGrate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WEATHERED_COPPER_GRATE" => Ok(Material::WeatheredCopperGrate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OXIDIZED_COPPER_GRATE" => Ok(Material::OxidizedCopperGrate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_COPPER_GRATE" => Ok(Material::WaxedCopperGrate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_EXPOSED_COPPER_GRATE" => Ok(Material::WaxedExposedCopperGrate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_WEATHERED_COPPER_GRATE" => Ok(Material::WaxedWeatheredCopperGrate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_OXIDIZED_COPPER_GRATE" => Ok(Material::WaxedOxidizedCopperGrate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COPPER_BULB" => Ok(Material::CopperBulb { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EXPOSED_COPPER_BULB" => Ok(Material::ExposedCopperBulb { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WEATHERED_COPPER_BULB" => Ok(Material::WeatheredCopperBulb { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OXIDIZED_COPPER_BULB" => Ok(Material::OxidizedCopperBulb { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_COPPER_BULB" => Ok(Material::WaxedCopperBulb { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_EXPOSED_COPPER_BULB" => Ok(Material::WaxedExposedCopperBulb { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_WEATHERED_COPPER_BULB" => Ok(Material::WaxedWeatheredCopperBulb { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_OXIDIZED_COPPER_BULB" => Ok(Material::WaxedOxidizedCopperBulb { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TRIAL_SPAWNER" => Ok(Material::TrialSpawner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TRIAL_KEY" => Ok(Material::TrialKey { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OMINOUS_TRIAL_KEY" => Ok(Material::OminousTrialKey { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "VAULT" => Ok(Material::Vault { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OMINOUS_BOTTLE" => Ok(Material::OminousBottle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BREEZE_ROD" => Ok(Material::BreezeRod { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WATER" => Ok(Material::Water { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LAVA" => Ok(Material::Lava { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TALL_SEAGRASS" => Ok(Material::TallSeagrass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PISTON_HEAD" => Ok(Material::PistonHead { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOVING_PISTON" => Ok(Material::MovingPiston { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WALL_TORCH" => Ok(Material::WallTorch { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FIRE" => Ok(Material::Fire { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SOUL_FIRE" => Ok(Material::SoulFire { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "REDSTONE_WIRE" => Ok(Material::RedstoneWire { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_WALL_SIGN" => Ok(Material::OakWallSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_WALL_SIGN" => Ok(Material::SpruceWallSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_WALL_SIGN" => Ok(Material::BirchWallSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_WALL_SIGN" => Ok(Material::AcaciaWallSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_WALL_SIGN" => Ok(Material::CherryWallSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_WALL_SIGN" => Ok(Material::JungleWallSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_WALL_SIGN" => Ok(Material::DarkOakWallSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_WALL_SIGN" => Ok(Material::MangroveWallSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_WALL_SIGN" => Ok(Material::BambooWallSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_WALL_HANGING_SIGN" => Ok(Material::OakWallHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_WALL_HANGING_SIGN" => Ok(Material::SpruceWallHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_WALL_HANGING_SIGN" => Ok(Material::BirchWallHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_WALL_HANGING_SIGN" => Ok(Material::AcaciaWallHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_WALL_HANGING_SIGN" => Ok(Material::CherryWallHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_WALL_HANGING_SIGN" => Ok(Material::JungleWallHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_WALL_HANGING_SIGN" => Ok(Material::DarkOakWallHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_WALL_HANGING_SIGN" => Ok(Material::MangroveWallHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_WALL_HANGING_SIGN" => Ok(Material::CrimsonWallHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_WALL_HANGING_SIGN" => Ok(Material::WarpedWallHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_WALL_HANGING_SIGN" => Ok(Material::BambooWallHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "REDSTONE_WALL_TORCH" => Ok(Material::RedstoneWallTorch { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SOUL_WALL_TORCH" => Ok(Material::SoulWallTorch { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_PORTAL" => Ok(Material::NetherPortal { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ATTACHED_PUMPKIN_STEM" => Ok(Material::AttachedPumpkinStem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ATTACHED_MELON_STEM" => Ok(Material::AttachedMelonStem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PUMPKIN_STEM" => Ok(Material::PumpkinStem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MELON_STEM" => Ok(Material::MelonStem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WATER_CAULDRON" => Ok(Material::WaterCauldron { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LAVA_CAULDRON" => Ok(Material::LavaCauldron { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POWDER_SNOW_CAULDRON" => Ok(Material::PowderSnowCauldron { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "END_PORTAL" => Ok(Material::EndPortal { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COCOA" => Ok(Material::Cocoa { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TRIPWIRE" => Ok(Material::Tripwire { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_TORCHFLOWER" => Ok(Material::PottedTorchflower { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_OAK_SAPLING" => Ok(Material::PottedOakSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_SPRUCE_SAPLING" => Ok(Material::PottedSpruceSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_BIRCH_SAPLING" => Ok(Material::PottedBirchSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_JUNGLE_SAPLING" => Ok(Material::PottedJungleSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_ACACIA_SAPLING" => Ok(Material::PottedAcaciaSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_CHERRY_SAPLING" => Ok(Material::PottedCherrySapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_DARK_OAK_SAPLING" => Ok(Material::PottedDarkOakSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_MANGROVE_PROPAGULE" => Ok(Material::PottedMangrovePropagule { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_FERN" => Ok(Material::PottedFern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_DANDELION" => Ok(Material::PottedDandelion { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_POPPY" => Ok(Material::PottedPoppy { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_BLUE_ORCHID" => Ok(Material::PottedBlueOrchid { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_ALLIUM" => Ok(Material::PottedAllium { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_AZURE_BLUET" => Ok(Material::PottedAzureBluet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_RED_TULIP" => Ok(Material::PottedRedTulip { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_ORANGE_TULIP" => Ok(Material::PottedOrangeTulip { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_WHITE_TULIP" => Ok(Material::PottedWhiteTulip { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_PINK_TULIP" => Ok(Material::PottedPinkTulip { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_OXEYE_DAISY" => Ok(Material::PottedOxeyeDaisy { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_CORNFLOWER" => Ok(Material::PottedCornflower { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_LILY_OF_THE_VALLEY" => Ok(Material::PottedLilyOfTheValley { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_WITHER_ROSE" => Ok(Material::PottedWitherRose { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_RED_MUSHROOM" => Ok(Material::PottedRedMushroom { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_BROWN_MUSHROOM" => Ok(Material::PottedBrownMushroom { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_DEAD_BUSH" => Ok(Material::PottedDeadBush { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_CACTUS" => Ok(Material::PottedCactus { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CARROTS" => Ok(Material::Carrots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTATOES" => Ok(Material::Potatoes { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SKELETON_WALL_SKULL" => Ok(Material::SkeletonWallSkull { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WITHER_SKELETON_WALL_SKULL" => Ok(Material::WitherSkeletonWallSkull { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ZOMBIE_WALL_HEAD" => Ok(Material::ZombieWallHead { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PLAYER_WALL_HEAD" => Ok(Material::PlayerWallHead { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CREEPER_WALL_HEAD" => Ok(Material::CreeperWallHead { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DRAGON_WALL_HEAD" => Ok(Material::DragonWallHead { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PIGLIN_WALL_HEAD" => Ok(Material::PiglinWallHead { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_WALL_BANNER" => Ok(Material::WhiteWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_WALL_BANNER" => Ok(Material::OrangeWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_WALL_BANNER" => Ok(Material::MagentaWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_WALL_BANNER" => Ok(Material::LightBlueWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_WALL_BANNER" => Ok(Material::YellowWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_WALL_BANNER" => Ok(Material::LimeWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_WALL_BANNER" => Ok(Material::PinkWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_WALL_BANNER" => Ok(Material::GrayWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_WALL_BANNER" => Ok(Material::LightGrayWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_WALL_BANNER" => Ok(Material::CyanWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_WALL_BANNER" => Ok(Material::PurpleWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_WALL_BANNER" => Ok(Material::BlueWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_WALL_BANNER" => Ok(Material::BrownWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_WALL_BANNER" => Ok(Material::GreenWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_WALL_BANNER" => Ok(Material::RedWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_WALL_BANNER" => Ok(Material::BlackWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TORCHFLOWER_CROP" => Ok(Material::TorchflowerCrop { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PITCHER_CROP" => Ok(Material::PitcherCrop { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BEETROOTS" => Ok(Material::Beetroots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "END_GATEWAY" => Ok(Material::EndGateway { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FROSTED_ICE" => Ok(Material::FrostedIce { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "KELP_PLANT" => Ok(Material::KelpPlant { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_TUBE_CORAL_WALL_FAN" => Ok(Material::DeadTubeCoralWallFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_BRAIN_CORAL_WALL_FAN" => Ok(Material::DeadBrainCoralWallFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_BUBBLE_CORAL_WALL_FAN" => Ok(Material::DeadBubbleCoralWallFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_FIRE_CORAL_WALL_FAN" => Ok(Material::DeadFireCoralWallFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_HORN_CORAL_WALL_FAN" => Ok(Material::DeadHornCoralWallFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TUBE_CORAL_WALL_FAN" => Ok(Material::TubeCoralWallFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BRAIN_CORAL_WALL_FAN" => Ok(Material::BrainCoralWallFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BUBBLE_CORAL_WALL_FAN" => Ok(Material::BubbleCoralWallFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FIRE_CORAL_WALL_FAN" => Ok(Material::FireCoralWallFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HORN_CORAL_WALL_FAN" => Ok(Material::HornCoralWallFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_SAPLING" => Ok(Material::BambooSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_BAMBOO" => Ok(Material::PottedBamboo { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "VOID_AIR" => Ok(Material::VoidAir { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CAVE_AIR" => Ok(Material::CaveAir { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BUBBLE_COLUMN" => Ok(Material::BubbleColumn { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SWEET_BERRY_BUSH" => Ok(Material::SweetBerryBush { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WEEPING_VINES_PLANT" => Ok(Material::WeepingVinesPlant { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TWISTING_VINES_PLANT" => Ok(Material::TwistingVinesPlant { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_WALL_SIGN" => Ok(Material::CrimsonWallSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_WALL_SIGN" => Ok(Material::WarpedWallSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_CRIMSON_FUNGUS" => Ok(Material::PottedCrimsonFungus { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_WARPED_FUNGUS" => Ok(Material::PottedWarpedFungus { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_CRIMSON_ROOTS" => Ok(Material::PottedCrimsonRoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_WARPED_ROOTS" => Ok(Material::PottedWarpedRoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CANDLE_CAKE" => Ok(Material::CandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_CANDLE_CAKE" => Ok(Material::WhiteCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_CANDLE_CAKE" => Ok(Material::OrangeCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_CANDLE_CAKE" => Ok(Material::MagentaCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_CANDLE_CAKE" => Ok(Material::LightBlueCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_CANDLE_CAKE" => Ok(Material::YellowCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_CANDLE_CAKE" => Ok(Material::LimeCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_CANDLE_CAKE" => Ok(Material::PinkCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_CANDLE_CAKE" => Ok(Material::GrayCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_CANDLE_CAKE" => Ok(Material::LightGrayCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_CANDLE_CAKE" => Ok(Material::CyanCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_CANDLE_CAKE" => Ok(Material::PurpleCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_CANDLE_CAKE" => Ok(Material::BlueCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_CANDLE_CAKE" => Ok(Material::BrownCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_CANDLE_CAKE" => Ok(Material::GreenCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_CANDLE_CAKE" => Ok(Material::RedCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_CANDLE_CAKE" => Ok(Material::BlackCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POWDER_SNOW" => Ok(Material::PowderSnow { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CAVE_VINES" => Ok(Material::CaveVines { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CAVE_VINES_PLANT" => Ok(Material::CaveVinesPlant { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIG_DRIPLEAF_STEM" => Ok(Material::BigDripleafStem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_AZALEA_BUSH" => Ok(Material::PottedAzaleaBush { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_FLOWERING_AZALEA_BUSH" => Ok(Material::PottedFloweringAzaleaBush { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_AIR" => Ok(Material::LegacyAir { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STONE" => Ok(Material::LegacyStone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GRASS" => Ok(Material::LegacyGrass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIRT" => Ok(Material::LegacyDirt { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COBBLESTONE" => Ok(Material::LegacyCobblestone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOD" => Ok(Material::LegacyWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SAPLING" => Ok(Material::LegacySapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BEDROCK" => Ok(Material::LegacyBedrock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WATER" => Ok(Material::LegacyWater { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STATIONARY_WATER" => Ok(Material::LegacyStationaryWater { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LAVA" => Ok(Material::LegacyLava { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STATIONARY_LAVA" => Ok(Material::LegacyStationaryLava { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SAND" => Ok(Material::LegacySand { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GRAVEL" => Ok(Material::LegacyGravel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_ORE" => Ok(Material::LegacyGoldOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_ORE" => Ok(Material::LegacyIronOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COAL_ORE" => Ok(Material::LegacyCoalOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LOG" => Ok(Material::LegacyLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LEAVES" => Ok(Material::LegacyLeaves { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SPONGE" => Ok(Material::LegacySponge { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GLASS" => Ok(Material::LegacyGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LAPIS_ORE" => Ok(Material::LegacyLapisOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LAPIS_BLOCK" => Ok(Material::LegacyLapisBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DISPENSER" => Ok(Material::LegacyDispenser { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SANDSTONE" => Ok(Material::LegacySandstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_NOTE_BLOCK" => Ok(Material::LegacyNoteBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BED_BLOCK" => Ok(Material::LegacyBedBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_POWERED_RAIL" => Ok(Material::LegacyPoweredRail { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DETECTOR_RAIL" => Ok(Material::LegacyDetectorRail { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PISTON_STICKY_BASE" => Ok(Material::LegacyPistonStickyBase { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WEB" => Ok(Material::LegacyWeb { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LONG_GRASS" => Ok(Material::LegacyLongGrass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DEAD_BUSH" => Ok(Material::LegacyDeadBush { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PISTON_BASE" => Ok(Material::LegacyPistonBase { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PISTON_EXTENSION" => Ok(Material::LegacyPistonExtension { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOL" => Ok(Material::LegacyWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PISTON_MOVING_PIECE" => Ok(Material::LegacyPistonMovingPiece { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_YELLOW_FLOWER" => Ok(Material::LegacyYellowFlower { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RED_ROSE" => Ok(Material::LegacyRedRose { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BROWN_MUSHROOM" => Ok(Material::LegacyBrownMushroom { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RED_MUSHROOM" => Ok(Material::LegacyRedMushroom { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_BLOCK" => Ok(Material::LegacyGoldBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_BLOCK" => Ok(Material::LegacyIronBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DOUBLE_STEP" => Ok(Material::LegacyDoubleStep { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STEP" => Ok(Material::LegacyStep { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BRICK" => Ok(Material::LegacyBrick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_TNT" => Ok(Material::LegacyTnt { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BOOKSHELF" => Ok(Material::LegacyBookshelf { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MOSSY_COBBLESTONE" => Ok(Material::LegacyMossyCobblestone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_OBSIDIAN" => Ok(Material::LegacyObsidian { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_TORCH" => Ok(Material::LegacyTorch { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FIRE" => Ok(Material::LegacyFire { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MOB_SPAWNER" => Ok(Material::LegacyMobSpawner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOD_STAIRS" => Ok(Material::LegacyWoodStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CHEST" => Ok(Material::LegacyChest { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_REDSTONE_WIRE" => Ok(Material::LegacyRedstoneWire { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND_ORE" => Ok(Material::LegacyDiamondOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND_BLOCK" => Ok(Material::LegacyDiamondBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WORKBENCH" => Ok(Material::LegacyWorkbench { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CROPS" => Ok(Material::LegacyCrops { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SOIL" => Ok(Material::LegacySoil { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FURNACE" => Ok(Material::LegacyFurnace { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BURNING_FURNACE" => Ok(Material::LegacyBurningFurnace { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SIGN_POST" => Ok(Material::LegacySignPost { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOODEN_DOOR" => Ok(Material::LegacyWoodenDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LADDER" => Ok(Material::LegacyLadder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RAILS" => Ok(Material::LegacyRails { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COBBLESTONE_STAIRS" => Ok(Material::LegacyCobblestoneStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WALL_SIGN" => Ok(Material::LegacyWallSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LEVER" => Ok(Material::LegacyLever { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STONE_PLATE" => Ok(Material::LegacyStonePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_DOOR_BLOCK" => Ok(Material::LegacyIronDoorBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOD_PLATE" => Ok(Material::LegacyWoodPlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_REDSTONE_ORE" => Ok(Material::LegacyRedstoneOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GLOWING_REDSTONE_ORE" => Ok(Material::LegacyGlowingRedstoneOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_REDSTONE_TORCH_OFF" => Ok(Material::LegacyRedstoneTorchOff { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_REDSTONE_TORCH_ON" => Ok(Material::LegacyRedstoneTorchOn { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STONE_BUTTON" => Ok(Material::LegacyStoneButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SNOW" => Ok(Material::LegacySnow { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ICE" => Ok(Material::LegacyIce { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SNOW_BLOCK" => Ok(Material::LegacySnowBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CACTUS" => Ok(Material::LegacyCactus { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CLAY" => Ok(Material::LegacyClay { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SUGAR_CANE_BLOCK" => Ok(Material::LegacySugarCaneBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_JUKEBOX" => Ok(Material::LegacyJukebox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FENCE" => Ok(Material::LegacyFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PUMPKIN" => Ok(Material::LegacyPumpkin { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_NETHERRACK" => Ok(Material::LegacyNetherrack { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SOUL_SAND" => Ok(Material::LegacySoulSand { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GLOWSTONE" => Ok(Material::LegacyGlowstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PORTAL" => Ok(Material::LegacyPortal { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_JACK_O_LANTERN" => Ok(Material::LegacyJackOLantern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CAKE_BLOCK" => Ok(Material::LegacyCakeBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIODE_BLOCK_OFF" => Ok(Material::LegacyDiodeBlockOff { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIODE_BLOCK_ON" => Ok(Material::LegacyDiodeBlockOn { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STAINED_GLASS" => Ok(Material::LegacyStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_TRAP_DOOR" => Ok(Material::LegacyTrapDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MONSTER_EGGS" => Ok(Material::LegacyMonsterEggs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SMOOTH_BRICK" => Ok(Material::LegacySmoothBrick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_HUGE_MUSHROOM_1" => Ok(Material::LegacyHugeMushroom1 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_HUGE_MUSHROOM_2" => Ok(Material::LegacyHugeMushroom2 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_FENCE" => Ok(Material::LegacyIronFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_THIN_GLASS" => Ok(Material::LegacyThinGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MELON_BLOCK" => Ok(Material::LegacyMelonBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PUMPKIN_STEM" => Ok(Material::LegacyPumpkinStem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MELON_STEM" => Ok(Material::LegacyMelonStem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_VINE" => Ok(Material::LegacyVine { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FENCE_GATE" => Ok(Material::LegacyFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BRICK_STAIRS" => Ok(Material::LegacyBrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SMOOTH_STAIRS" => Ok(Material::LegacySmoothStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MYCEL" => Ok(Material::LegacyMycel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WATER_LILY" => Ok(Material::LegacyWaterLily { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_NETHER_BRICK" => Ok(Material::LegacyNetherBrick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_NETHER_FENCE" => Ok(Material::LegacyNetherFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_NETHER_BRICK_STAIRS" => Ok(Material::LegacyNetherBrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_NETHER_WARTS" => Ok(Material::LegacyNetherWarts { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ENCHANTMENT_TABLE" => Ok(Material::LegacyEnchantmentTable { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BREWING_STAND" => Ok(Material::LegacyBrewingStand { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CAULDRON" => Ok(Material::LegacyCauldron { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ENDER_PORTAL" => Ok(Material::LegacyEnderPortal { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ENDER_PORTAL_FRAME" => Ok(Material::LegacyEnderPortalFrame { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ENDER_STONE" => Ok(Material::LegacyEnderStone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DRAGON_EGG" => Ok(Material::LegacyDragonEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_REDSTONE_LAMP_OFF" => Ok(Material::LegacyRedstoneLampOff { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_REDSTONE_LAMP_ON" => Ok(Material::LegacyRedstoneLampOn { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOD_DOUBLE_STEP" => Ok(Material::LegacyWoodDoubleStep { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOD_STEP" => Ok(Material::LegacyWoodStep { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COCOA" => Ok(Material::LegacyCocoa { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SANDSTONE_STAIRS" => Ok(Material::LegacySandstoneStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_EMERALD_ORE" => Ok(Material::LegacyEmeraldOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ENDER_CHEST" => Ok(Material::LegacyEnderChest { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_TRIPWIRE_HOOK" => Ok(Material::LegacyTripwireHook { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_TRIPWIRE" => Ok(Material::LegacyTripwire { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_EMERALD_BLOCK" => Ok(Material::LegacyEmeraldBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SPRUCE_WOOD_STAIRS" => Ok(Material::LegacySpruceWoodStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BIRCH_WOOD_STAIRS" => Ok(Material::LegacyBirchWoodStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_JUNGLE_WOOD_STAIRS" => Ok(Material::LegacyJungleWoodStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COMMAND" => Ok(Material::LegacyCommand { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BEACON" => Ok(Material::LegacyBeacon { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COBBLE_WALL" => Ok(Material::LegacyCobbleWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FLOWER_POT" => Ok(Material::LegacyFlowerPot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CARROT" => Ok(Material::LegacyCarrot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_POTATO" => Ok(Material::LegacyPotato { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOD_BUTTON" => Ok(Material::LegacyWoodButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SKULL" => Ok(Material::LegacySkull { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ANVIL" => Ok(Material::LegacyAnvil { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_TRAPPED_CHEST" => Ok(Material::LegacyTrappedChest { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_PLATE" => Ok(Material::LegacyGoldPlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_PLATE" => Ok(Material::LegacyIronPlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_REDSTONE_COMPARATOR_OFF" => Ok(Material::LegacyRedstoneComparatorOff { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_REDSTONE_COMPARATOR_ON" => Ok(Material::LegacyRedstoneComparatorOn { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DAYLIGHT_DETECTOR" => Ok(Material::LegacyDaylightDetector { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_REDSTONE_BLOCK" => Ok(Material::LegacyRedstoneBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_QUARTZ_ORE" => Ok(Material::LegacyQuartzOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_HOPPER" => Ok(Material::LegacyHopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_QUARTZ_BLOCK" => Ok(Material::LegacyQuartzBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_QUARTZ_STAIRS" => Ok(Material::LegacyQuartzStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ACTIVATOR_RAIL" => Ok(Material::LegacyActivatorRail { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DROPPER" => Ok(Material::LegacyDropper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STAINED_CLAY" => Ok(Material::LegacyStainedClay { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STAINED_GLASS_PANE" => Ok(Material::LegacyStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LEAVES_2" => Ok(Material::LegacyLeaves2 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LOG_2" => Ok(Material::LegacyLog2 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ACACIA_STAIRS" => Ok(Material::LegacyAcaciaStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DARK_OAK_STAIRS" => Ok(Material::LegacyDarkOakStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SLIME_BLOCK" => Ok(Material::LegacySlimeBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BARRIER" => Ok(Material::LegacyBarrier { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_TRAPDOOR" => Ok(Material::LegacyIronTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PRISMARINE" => Ok(Material::LegacyPrismarine { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SEA_LANTERN" => Ok(Material::LegacySeaLantern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_HAY_BLOCK" => Ok(Material::LegacyHayBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CARPET" => Ok(Material::LegacyCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_HARD_CLAY" => Ok(Material::LegacyHardClay { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COAL_BLOCK" => Ok(Material::LegacyCoalBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PACKED_ICE" => Ok(Material::LegacyPackedIce { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DOUBLE_PLANT" => Ok(Material::LegacyDoublePlant { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STANDING_BANNER" => Ok(Material::LegacyStandingBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WALL_BANNER" => Ok(Material::LegacyWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DAYLIGHT_DETECTOR_INVERTED" => Ok(Material::LegacyDaylightDetectorInverted { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RED_SANDSTONE" => Ok(Material::LegacyRedSandstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RED_SANDSTONE_STAIRS" => Ok(Material::LegacyRedSandstoneStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DOUBLE_STONE_SLAB2" => Ok(Material::LegacyDoubleStoneSlab2 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STONE_SLAB2" => Ok(Material::LegacyStoneSlab2 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SPRUCE_FENCE_GATE" => Ok(Material::LegacySpruceFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BIRCH_FENCE_GATE" => Ok(Material::LegacyBirchFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_JUNGLE_FENCE_GATE" => Ok(Material::LegacyJungleFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DARK_OAK_FENCE_GATE" => Ok(Material::LegacyDarkOakFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ACACIA_FENCE_GATE" => Ok(Material::LegacyAcaciaFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SPRUCE_FENCE" => Ok(Material::LegacySpruceFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BIRCH_FENCE" => Ok(Material::LegacyBirchFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_JUNGLE_FENCE" => Ok(Material::LegacyJungleFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DARK_OAK_FENCE" => Ok(Material::LegacyDarkOakFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ACACIA_FENCE" => Ok(Material::LegacyAcaciaFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SPRUCE_DOOR" => Ok(Material::LegacySpruceDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BIRCH_DOOR" => Ok(Material::LegacyBirchDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_JUNGLE_DOOR" => Ok(Material::LegacyJungleDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ACACIA_DOOR" => Ok(Material::LegacyAcaciaDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DARK_OAK_DOOR" => Ok(Material::LegacyDarkOakDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_END_ROD" => Ok(Material::LegacyEndRod { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CHORUS_PLANT" => Ok(Material::LegacyChorusPlant { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CHORUS_FLOWER" => Ok(Material::LegacyChorusFlower { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PURPUR_BLOCK" => Ok(Material::LegacyPurpurBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PURPUR_PILLAR" => Ok(Material::LegacyPurpurPillar { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PURPUR_STAIRS" => Ok(Material::LegacyPurpurStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PURPUR_DOUBLE_SLAB" => Ok(Material::LegacyPurpurDoubleSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PURPUR_SLAB" => Ok(Material::LegacyPurpurSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_END_BRICKS" => Ok(Material::LegacyEndBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BEETROOT_BLOCK" => Ok(Material::LegacyBeetrootBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GRASS_PATH" => Ok(Material::LegacyGrassPath { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_END_GATEWAY" => Ok(Material::LegacyEndGateway { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COMMAND_REPEATING" => Ok(Material::LegacyCommandRepeating { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COMMAND_CHAIN" => Ok(Material::LegacyCommandChain { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FROSTED_ICE" => Ok(Material::LegacyFrostedIce { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MAGMA" => Ok(Material::LegacyMagma { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_NETHER_WART_BLOCK" => Ok(Material::LegacyNetherWartBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RED_NETHER_BRICK" => Ok(Material::LegacyRedNetherBrick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BONE_BLOCK" => Ok(Material::LegacyBoneBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STRUCTURE_VOID" => Ok(Material::LegacyStructureVoid { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_OBSERVER" => Ok(Material::LegacyObserver { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WHITE_SHULKER_BOX" => Ok(Material::LegacyWhiteShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ORANGE_SHULKER_BOX" => Ok(Material::LegacyOrangeShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MAGENTA_SHULKER_BOX" => Ok(Material::LegacyMagentaShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LIGHT_BLUE_SHULKER_BOX" => Ok(Material::LegacyLightBlueShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_YELLOW_SHULKER_BOX" => Ok(Material::LegacyYellowShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LIME_SHULKER_BOX" => Ok(Material::LegacyLimeShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PINK_SHULKER_BOX" => Ok(Material::LegacyPinkShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GRAY_SHULKER_BOX" => Ok(Material::LegacyGrayShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SILVER_SHULKER_BOX" => Ok(Material::LegacySilverShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CYAN_SHULKER_BOX" => Ok(Material::LegacyCyanShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PURPLE_SHULKER_BOX" => Ok(Material::LegacyPurpleShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BLUE_SHULKER_BOX" => Ok(Material::LegacyBlueShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BROWN_SHULKER_BOX" => Ok(Material::LegacyBrownShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GREEN_SHULKER_BOX" => Ok(Material::LegacyGreenShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RED_SHULKER_BOX" => Ok(Material::LegacyRedShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BLACK_SHULKER_BOX" => Ok(Material::LegacyBlackShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WHITE_GLAZED_TERRACOTTA" => Ok(Material::LegacyWhiteGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ORANGE_GLAZED_TERRACOTTA" => Ok(Material::LegacyOrangeGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MAGENTA_GLAZED_TERRACOTTA" => Ok(Material::LegacyMagentaGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LIGHT_BLUE_GLAZED_TERRACOTTA" => { + Ok(Material::LegacyLightBlueGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "LEGACY_YELLOW_GLAZED_TERRACOTTA" => Ok(Material::LegacyYellowGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LIME_GLAZED_TERRACOTTA" => Ok(Material::LegacyLimeGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PINK_GLAZED_TERRACOTTA" => Ok(Material::LegacyPinkGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GRAY_GLAZED_TERRACOTTA" => Ok(Material::LegacyGrayGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SILVER_GLAZED_TERRACOTTA" => Ok(Material::LegacySilverGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CYAN_GLAZED_TERRACOTTA" => Ok(Material::LegacyCyanGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PURPLE_GLAZED_TERRACOTTA" => Ok(Material::LegacyPurpleGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BLUE_GLAZED_TERRACOTTA" => Ok(Material::LegacyBlueGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BROWN_GLAZED_TERRACOTTA" => Ok(Material::LegacyBrownGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GREEN_GLAZED_TERRACOTTA" => Ok(Material::LegacyGreenGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RED_GLAZED_TERRACOTTA" => Ok(Material::LegacyRedGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BLACK_GLAZED_TERRACOTTA" => Ok(Material::LegacyBlackGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CONCRETE" => Ok(Material::LegacyConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CONCRETE_POWDER" => Ok(Material::LegacyConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STRUCTURE_BLOCK" => Ok(Material::LegacyStructureBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_SPADE" => Ok(Material::LegacyIronSpade { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_PICKAXE" => Ok(Material::LegacyIronPickaxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_AXE" => Ok(Material::LegacyIronAxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FLINT_AND_STEEL" => Ok(Material::LegacyFlintAndSteel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_APPLE" => Ok(Material::LegacyApple { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BOW" => Ok(Material::LegacyBow { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ARROW" => Ok(Material::LegacyArrow { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COAL" => Ok(Material::LegacyCoal { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND" => Ok(Material::LegacyDiamond { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_INGOT" => Ok(Material::LegacyIronIngot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_INGOT" => Ok(Material::LegacyGoldIngot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_SWORD" => Ok(Material::LegacyIronSword { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOD_SWORD" => Ok(Material::LegacyWoodSword { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOD_SPADE" => Ok(Material::LegacyWoodSpade { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOD_PICKAXE" => Ok(Material::LegacyWoodPickaxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOD_AXE" => Ok(Material::LegacyWoodAxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STONE_SWORD" => Ok(Material::LegacyStoneSword { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STONE_SPADE" => Ok(Material::LegacyStoneSpade { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STONE_PICKAXE" => Ok(Material::LegacyStonePickaxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STONE_AXE" => Ok(Material::LegacyStoneAxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND_SWORD" => Ok(Material::LegacyDiamondSword { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND_SPADE" => Ok(Material::LegacyDiamondSpade { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND_PICKAXE" => Ok(Material::LegacyDiamondPickaxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND_AXE" => Ok(Material::LegacyDiamondAxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STICK" => Ok(Material::LegacyStick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BOWL" => Ok(Material::LegacyBowl { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MUSHROOM_SOUP" => Ok(Material::LegacyMushroomSoup { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_SWORD" => Ok(Material::LegacyGoldSword { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_SPADE" => Ok(Material::LegacyGoldSpade { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_PICKAXE" => Ok(Material::LegacyGoldPickaxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_AXE" => Ok(Material::LegacyGoldAxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STRING" => Ok(Material::LegacyString { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FEATHER" => Ok(Material::LegacyFeather { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SULPHUR" => Ok(Material::LegacySulphur { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOD_HOE" => Ok(Material::LegacyWoodHoe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STONE_HOE" => Ok(Material::LegacyStoneHoe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_HOE" => Ok(Material::LegacyIronHoe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND_HOE" => Ok(Material::LegacyDiamondHoe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_HOE" => Ok(Material::LegacyGoldHoe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SEEDS" => Ok(Material::LegacySeeds { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WHEAT" => Ok(Material::LegacyWheat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BREAD" => Ok(Material::LegacyBread { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LEATHER_HELMET" => Ok(Material::LegacyLeatherHelmet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LEATHER_CHESTPLATE" => Ok(Material::LegacyLeatherChestplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LEATHER_LEGGINGS" => Ok(Material::LegacyLeatherLeggings { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LEATHER_BOOTS" => Ok(Material::LegacyLeatherBoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CHAINMAIL_HELMET" => Ok(Material::LegacyChainmailHelmet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CHAINMAIL_CHESTPLATE" => Ok(Material::LegacyChainmailChestplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CHAINMAIL_LEGGINGS" => Ok(Material::LegacyChainmailLeggings { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CHAINMAIL_BOOTS" => Ok(Material::LegacyChainmailBoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_HELMET" => Ok(Material::LegacyIronHelmet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_CHESTPLATE" => Ok(Material::LegacyIronChestplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_LEGGINGS" => Ok(Material::LegacyIronLeggings { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_BOOTS" => Ok(Material::LegacyIronBoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND_HELMET" => Ok(Material::LegacyDiamondHelmet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND_CHESTPLATE" => Ok(Material::LegacyDiamondChestplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND_LEGGINGS" => Ok(Material::LegacyDiamondLeggings { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND_BOOTS" => Ok(Material::LegacyDiamondBoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_HELMET" => Ok(Material::LegacyGoldHelmet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_CHESTPLATE" => Ok(Material::LegacyGoldChestplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_LEGGINGS" => Ok(Material::LegacyGoldLeggings { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_BOOTS" => Ok(Material::LegacyGoldBoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FLINT" => Ok(Material::LegacyFlint { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PORK" => Ok(Material::LegacyPork { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GRILLED_PORK" => Ok(Material::LegacyGrilledPork { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PAINTING" => Ok(Material::LegacyPainting { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLDEN_APPLE" => Ok(Material::LegacyGoldenApple { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SIGN" => Ok(Material::LegacySign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOD_DOOR" => Ok(Material::LegacyWoodDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BUCKET" => Ok(Material::LegacyBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WATER_BUCKET" => Ok(Material::LegacyWaterBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LAVA_BUCKET" => Ok(Material::LegacyLavaBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MINECART" => Ok(Material::LegacyMinecart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SADDLE" => Ok(Material::LegacySaddle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_DOOR" => Ok(Material::LegacyIronDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_REDSTONE" => Ok(Material::LegacyRedstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SNOW_BALL" => Ok(Material::LegacySnowBall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BOAT" => Ok(Material::LegacyBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LEATHER" => Ok(Material::LegacyLeather { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MILK_BUCKET" => Ok(Material::LegacyMilkBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CLAY_BRICK" => Ok(Material::LegacyClayBrick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CLAY_BALL" => Ok(Material::LegacyClayBall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SUGAR_CANE" => Ok(Material::LegacySugarCane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PAPER" => Ok(Material::LegacyPaper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BOOK" => Ok(Material::LegacyBook { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SLIME_BALL" => Ok(Material::LegacySlimeBall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STORAGE_MINECART" => Ok(Material::LegacyStorageMinecart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_POWERED_MINECART" => Ok(Material::LegacyPoweredMinecart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_EGG" => Ok(Material::LegacyEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COMPASS" => Ok(Material::LegacyCompass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FISHING_ROD" => Ok(Material::LegacyFishingRod { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WATCH" => Ok(Material::LegacyWatch { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GLOWSTONE_DUST" => Ok(Material::LegacyGlowstoneDust { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RAW_FISH" => Ok(Material::LegacyRawFish { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COOKED_FISH" => Ok(Material::LegacyCookedFish { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_INK_SACK" => Ok(Material::LegacyInkSack { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BONE" => Ok(Material::LegacyBone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SUGAR" => Ok(Material::LegacySugar { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CAKE" => Ok(Material::LegacyCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BED" => Ok(Material::LegacyBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIODE" => Ok(Material::LegacyDiode { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COOKIE" => Ok(Material::LegacyCookie { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MAP" => Ok(Material::LegacyMap { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SHEARS" => Ok(Material::LegacyShears { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MELON" => Ok(Material::LegacyMelon { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PUMPKIN_SEEDS" => Ok(Material::LegacyPumpkinSeeds { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MELON_SEEDS" => Ok(Material::LegacyMelonSeeds { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RAW_BEEF" => Ok(Material::LegacyRawBeef { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COOKED_BEEF" => Ok(Material::LegacyCookedBeef { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RAW_CHICKEN" => Ok(Material::LegacyRawChicken { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COOKED_CHICKEN" => Ok(Material::LegacyCookedChicken { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ROTTEN_FLESH" => Ok(Material::LegacyRottenFlesh { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ENDER_PEARL" => Ok(Material::LegacyEnderPearl { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BLAZE_ROD" => Ok(Material::LegacyBlazeRod { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GHAST_TEAR" => Ok(Material::LegacyGhastTear { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_NUGGET" => Ok(Material::LegacyGoldNugget { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_NETHER_STALK" => Ok(Material::LegacyNetherStalk { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_POTION" => Ok(Material::LegacyPotion { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GLASS_BOTTLE" => Ok(Material::LegacyGlassBottle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SPIDER_EYE" => Ok(Material::LegacySpiderEye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FERMENTED_SPIDER_EYE" => Ok(Material::LegacyFermentedSpiderEye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BLAZE_POWDER" => Ok(Material::LegacyBlazePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MAGMA_CREAM" => Ok(Material::LegacyMagmaCream { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BREWING_STAND_ITEM" => Ok(Material::LegacyBrewingStandItem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CAULDRON_ITEM" => Ok(Material::LegacyCauldronItem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_EYE_OF_ENDER" => Ok(Material::LegacyEyeOfEnder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SPECKLED_MELON" => Ok(Material::LegacySpeckledMelon { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MONSTER_EGG" => Ok(Material::LegacyMonsterEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_EXP_BOTTLE" => Ok(Material::LegacyExpBottle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FIREBALL" => Ok(Material::LegacyFireball { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BOOK_AND_QUILL" => Ok(Material::LegacyBookAndQuill { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WRITTEN_BOOK" => Ok(Material::LegacyWrittenBook { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_EMERALD" => Ok(Material::LegacyEmerald { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ITEM_FRAME" => Ok(Material::LegacyItemFrame { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FLOWER_POT_ITEM" => Ok(Material::LegacyFlowerPotItem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CARROT_ITEM" => Ok(Material::LegacyCarrotItem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_POTATO_ITEM" => Ok(Material::LegacyPotatoItem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BAKED_POTATO" => Ok(Material::LegacyBakedPotato { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_POISONOUS_POTATO" => Ok(Material::LegacyPoisonousPotato { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_EMPTY_MAP" => Ok(Material::LegacyEmptyMap { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLDEN_CARROT" => Ok(Material::LegacyGoldenCarrot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SKULL_ITEM" => Ok(Material::LegacySkullItem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CARROT_STICK" => Ok(Material::LegacyCarrotStick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_NETHER_STAR" => Ok(Material::LegacyNetherStar { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PUMPKIN_PIE" => Ok(Material::LegacyPumpkinPie { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FIREWORK" => Ok(Material::LegacyFirework { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FIREWORK_CHARGE" => Ok(Material::LegacyFireworkCharge { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ENCHANTED_BOOK" => Ok(Material::LegacyEnchantedBook { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_REDSTONE_COMPARATOR" => Ok(Material::LegacyRedstoneComparator { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_NETHER_BRICK_ITEM" => Ok(Material::LegacyNetherBrickItem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_QUARTZ" => Ok(Material::LegacyQuartz { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_EXPLOSIVE_MINECART" => Ok(Material::LegacyExplosiveMinecart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_HOPPER_MINECART" => Ok(Material::LegacyHopperMinecart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PRISMARINE_SHARD" => Ok(Material::LegacyPrismarineShard { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PRISMARINE_CRYSTALS" => Ok(Material::LegacyPrismarineCrystals { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RABBIT" => Ok(Material::LegacyRabbit { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COOKED_RABBIT" => Ok(Material::LegacyCookedRabbit { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RABBIT_STEW" => Ok(Material::LegacyRabbitStew { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RABBIT_FOOT" => Ok(Material::LegacyRabbitFoot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RABBIT_HIDE" => Ok(Material::LegacyRabbitHide { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ARMOR_STAND" => Ok(Material::LegacyArmorStand { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_BARDING" => Ok(Material::LegacyIronBarding { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_BARDING" => Ok(Material::LegacyGoldBarding { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND_BARDING" => Ok(Material::LegacyDiamondBarding { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LEASH" => Ok(Material::LegacyLeash { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_NAME_TAG" => Ok(Material::LegacyNameTag { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COMMAND_MINECART" => Ok(Material::LegacyCommandMinecart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MUTTON" => Ok(Material::LegacyMutton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COOKED_MUTTON" => Ok(Material::LegacyCookedMutton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BANNER" => Ok(Material::LegacyBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_END_CRYSTAL" => Ok(Material::LegacyEndCrystal { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SPRUCE_DOOR_ITEM" => Ok(Material::LegacySpruceDoorItem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BIRCH_DOOR_ITEM" => Ok(Material::LegacyBirchDoorItem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_JUNGLE_DOOR_ITEM" => Ok(Material::LegacyJungleDoorItem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ACACIA_DOOR_ITEM" => Ok(Material::LegacyAcaciaDoorItem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DARK_OAK_DOOR_ITEM" => Ok(Material::LegacyDarkOakDoorItem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CHORUS_FRUIT" => Ok(Material::LegacyChorusFruit { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CHORUS_FRUIT_POPPED" => Ok(Material::LegacyChorusFruitPopped { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BEETROOT" => Ok(Material::LegacyBeetroot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BEETROOT_SEEDS" => Ok(Material::LegacyBeetrootSeeds { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BEETROOT_SOUP" => Ok(Material::LegacyBeetrootSoup { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DRAGONS_BREATH" => Ok(Material::LegacyDragonsBreath { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SPLASH_POTION" => Ok(Material::LegacySplashPotion { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SPECTRAL_ARROW" => Ok(Material::LegacySpectralArrow { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_TIPPED_ARROW" => Ok(Material::LegacyTippedArrow { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LINGERING_POTION" => Ok(Material::LegacyLingeringPotion { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SHIELD" => Ok(Material::LegacyShield { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ELYTRA" => Ok(Material::LegacyElytra { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BOAT_SPRUCE" => Ok(Material::LegacyBoatSpruce { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BOAT_BIRCH" => Ok(Material::LegacyBoatBirch { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BOAT_JUNGLE" => Ok(Material::LegacyBoatJungle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BOAT_ACACIA" => Ok(Material::LegacyBoatAcacia { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BOAT_DARK_OAK" => Ok(Material::LegacyBoatDarkOak { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_TOTEM" => Ok(Material::LegacyTotem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SHULKER_SHELL" => Ok(Material::LegacyShulkerShell { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_NUGGET" => Ok(Material::LegacyIronNugget { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_KNOWLEDGE_BOOK" => Ok(Material::LegacyKnowledgeBook { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_RECORD" => Ok(Material::LegacyGoldRecord { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GREEN_RECORD" => Ok(Material::LegacyGreenRecord { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RECORD_3" => Ok(Material::LegacyRecord3 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RECORD_4" => Ok(Material::LegacyRecord4 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RECORD_5" => Ok(Material::LegacyRecord5 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RECORD_6" => Ok(Material::LegacyRecord6 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RECORD_7" => Ok(Material::LegacyRecord7 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RECORD_8" => Ok(Material::LegacyRecord8 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RECORD_9" => Ok(Material::LegacyRecord9 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RECORD_10" => Ok(Material::LegacyRecord10 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RECORD_11" => Ok(Material::LegacyRecord11 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RECORD_12" => Ok(Material::LegacyRecord12 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct MaterialStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Material<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Air { inner } => inner.0.clone(), + Self::Stone { inner } => inner.0.clone(), + Self::Granite { inner } => inner.0.clone(), + Self::PolishedGranite { inner } => inner.0.clone(), + Self::Diorite { inner } => inner.0.clone(), + Self::PolishedDiorite { inner } => inner.0.clone(), + Self::Andesite { inner } => inner.0.clone(), + Self::PolishedAndesite { inner } => inner.0.clone(), + Self::Deepslate { inner } => inner.0.clone(), + Self::CobbledDeepslate { inner } => inner.0.clone(), + Self::PolishedDeepslate { inner } => inner.0.clone(), + Self::Calcite { inner } => inner.0.clone(), + Self::Tuff { inner } => inner.0.clone(), + Self::TuffSlab { inner } => inner.0.clone(), + Self::TuffStairs { inner } => inner.0.clone(), + Self::TuffWall { inner } => inner.0.clone(), + Self::ChiseledTuff { inner } => inner.0.clone(), + Self::PolishedTuff { inner } => inner.0.clone(), + Self::PolishedTuffSlab { inner } => inner.0.clone(), + Self::PolishedTuffStairs { inner } => inner.0.clone(), + Self::PolishedTuffWall { inner } => inner.0.clone(), + Self::TuffBricks { inner } => inner.0.clone(), + Self::TuffBrickSlab { inner } => inner.0.clone(), + Self::TuffBrickStairs { inner } => inner.0.clone(), + Self::TuffBrickWall { inner } => inner.0.clone(), + Self::ChiseledTuffBricks { inner } => inner.0.clone(), + Self::DripstoneBlock { inner } => inner.0.clone(), + Self::GrassBlock { inner } => inner.0.clone(), + Self::Dirt { inner } => inner.0.clone(), + Self::CoarseDirt { inner } => inner.0.clone(), + Self::Podzol { inner } => inner.0.clone(), + Self::RootedDirt { inner } => inner.0.clone(), + Self::Mud { inner } => inner.0.clone(), + Self::CrimsonNylium { inner } => inner.0.clone(), + Self::WarpedNylium { inner } => inner.0.clone(), + Self::Cobblestone { inner } => inner.0.clone(), + Self::OakPlanks { inner } => inner.0.clone(), + Self::SprucePlanks { inner } => inner.0.clone(), + Self::BirchPlanks { inner } => inner.0.clone(), + Self::JunglePlanks { inner } => inner.0.clone(), + Self::AcaciaPlanks { inner } => inner.0.clone(), + Self::CherryPlanks { inner } => inner.0.clone(), + Self::DarkOakPlanks { inner } => inner.0.clone(), + Self::MangrovePlanks { inner } => inner.0.clone(), + Self::BambooPlanks { inner } => inner.0.clone(), + Self::CrimsonPlanks { inner } => inner.0.clone(), + Self::WarpedPlanks { inner } => inner.0.clone(), + Self::BambooMosaic { inner } => inner.0.clone(), + Self::OakSapling { inner } => inner.0.clone(), + Self::SpruceSapling { inner } => inner.0.clone(), + Self::BirchSapling { inner } => inner.0.clone(), + Self::JungleSapling { inner } => inner.0.clone(), + Self::AcaciaSapling { inner } => inner.0.clone(), + Self::CherrySapling { inner } => inner.0.clone(), + Self::DarkOakSapling { inner } => inner.0.clone(), + Self::MangrovePropagule { inner } => inner.0.clone(), + Self::Bedrock { inner } => inner.0.clone(), + Self::Sand { inner } => inner.0.clone(), + Self::SuspiciousSand { inner } => inner.0.clone(), + Self::SuspiciousGravel { inner } => inner.0.clone(), + Self::RedSand { inner } => inner.0.clone(), + Self::Gravel { inner } => inner.0.clone(), + Self::CoalOre { inner } => inner.0.clone(), + Self::DeepslateCoalOre { inner } => inner.0.clone(), + Self::IronOre { inner } => inner.0.clone(), + Self::DeepslateIronOre { inner } => inner.0.clone(), + Self::CopperOre { inner } => inner.0.clone(), + Self::DeepslateCopperOre { inner } => inner.0.clone(), + Self::GoldOre { inner } => inner.0.clone(), + Self::DeepslateGoldOre { inner } => inner.0.clone(), + Self::RedstoneOre { inner } => inner.0.clone(), + Self::DeepslateRedstoneOre { inner } => inner.0.clone(), + Self::EmeraldOre { inner } => inner.0.clone(), + Self::DeepslateEmeraldOre { inner } => inner.0.clone(), + Self::LapisOre { inner } => inner.0.clone(), + Self::DeepslateLapisOre { inner } => inner.0.clone(), + Self::DiamondOre { inner } => inner.0.clone(), + Self::DeepslateDiamondOre { inner } => inner.0.clone(), + Self::NetherGoldOre { inner } => inner.0.clone(), + Self::NetherQuartzOre { inner } => inner.0.clone(), + Self::AncientDebris { inner } => inner.0.clone(), + Self::CoalBlock { inner } => inner.0.clone(), + Self::RawIronBlock { inner } => inner.0.clone(), + Self::RawCopperBlock { inner } => inner.0.clone(), + Self::RawGoldBlock { inner } => inner.0.clone(), + Self::HeavyCore { inner } => inner.0.clone(), + Self::AmethystBlock { inner } => inner.0.clone(), + Self::BuddingAmethyst { inner } => inner.0.clone(), + Self::IronBlock { inner } => inner.0.clone(), + Self::CopperBlock { inner } => inner.0.clone(), + Self::GoldBlock { inner } => inner.0.clone(), + Self::DiamondBlock { inner } => inner.0.clone(), + Self::NetheriteBlock { inner } => inner.0.clone(), + Self::ExposedCopper { inner } => inner.0.clone(), + Self::WeatheredCopper { inner } => inner.0.clone(), + Self::OxidizedCopper { inner } => inner.0.clone(), + Self::ChiseledCopper { inner } => inner.0.clone(), + Self::ExposedChiseledCopper { inner } => inner.0.clone(), + Self::WeatheredChiseledCopper { inner } => inner.0.clone(), + Self::OxidizedChiseledCopper { inner } => inner.0.clone(), + Self::CutCopper { inner } => inner.0.clone(), + Self::ExposedCutCopper { inner } => inner.0.clone(), + Self::WeatheredCutCopper { inner } => inner.0.clone(), + Self::OxidizedCutCopper { inner } => inner.0.clone(), + Self::CutCopperStairs { inner } => inner.0.clone(), + Self::ExposedCutCopperStairs { inner } => inner.0.clone(), + Self::WeatheredCutCopperStairs { inner } => inner.0.clone(), + Self::OxidizedCutCopperStairs { inner } => inner.0.clone(), + Self::CutCopperSlab { inner } => inner.0.clone(), + Self::ExposedCutCopperSlab { inner } => inner.0.clone(), + Self::WeatheredCutCopperSlab { inner } => inner.0.clone(), + Self::OxidizedCutCopperSlab { inner } => inner.0.clone(), + Self::WaxedCopperBlock { inner } => inner.0.clone(), + Self::WaxedExposedCopper { inner } => inner.0.clone(), + Self::WaxedWeatheredCopper { inner } => inner.0.clone(), + Self::WaxedOxidizedCopper { inner } => inner.0.clone(), + Self::WaxedChiseledCopper { inner } => inner.0.clone(), + Self::WaxedExposedChiseledCopper { inner } => inner.0.clone(), + Self::WaxedWeatheredChiseledCopper { inner } => inner.0.clone(), + Self::WaxedOxidizedChiseledCopper { inner } => inner.0.clone(), + Self::WaxedCutCopper { inner } => inner.0.clone(), + Self::WaxedExposedCutCopper { inner } => inner.0.clone(), + Self::WaxedWeatheredCutCopper { inner } => inner.0.clone(), + Self::WaxedOxidizedCutCopper { inner } => inner.0.clone(), + Self::WaxedCutCopperStairs { inner } => inner.0.clone(), + Self::WaxedExposedCutCopperStairs { inner } => inner.0.clone(), + Self::WaxedWeatheredCutCopperStairs { inner } => inner.0.clone(), + Self::WaxedOxidizedCutCopperStairs { inner } => inner.0.clone(), + Self::WaxedCutCopperSlab { inner } => inner.0.clone(), + Self::WaxedExposedCutCopperSlab { inner } => inner.0.clone(), + Self::WaxedWeatheredCutCopperSlab { inner } => inner.0.clone(), + Self::WaxedOxidizedCutCopperSlab { inner } => inner.0.clone(), + Self::OakLog { inner } => inner.0.clone(), + Self::SpruceLog { inner } => inner.0.clone(), + Self::BirchLog { inner } => inner.0.clone(), + Self::JungleLog { inner } => inner.0.clone(), + Self::AcaciaLog { inner } => inner.0.clone(), + Self::CherryLog { inner } => inner.0.clone(), + Self::DarkOakLog { inner } => inner.0.clone(), + Self::MangroveLog { inner } => inner.0.clone(), + Self::MangroveRoots { inner } => inner.0.clone(), + Self::MuddyMangroveRoots { inner } => inner.0.clone(), + Self::CrimsonStem { inner } => inner.0.clone(), + Self::WarpedStem { inner } => inner.0.clone(), + Self::BambooBlock { inner } => inner.0.clone(), + Self::StrippedOakLog { inner } => inner.0.clone(), + Self::StrippedSpruceLog { inner } => inner.0.clone(), + Self::StrippedBirchLog { inner } => inner.0.clone(), + Self::StrippedJungleLog { inner } => inner.0.clone(), + Self::StrippedAcaciaLog { inner } => inner.0.clone(), + Self::StrippedCherryLog { inner } => inner.0.clone(), + Self::StrippedDarkOakLog { inner } => inner.0.clone(), + Self::StrippedMangroveLog { inner } => inner.0.clone(), + Self::StrippedCrimsonStem { inner } => inner.0.clone(), + Self::StrippedWarpedStem { inner } => inner.0.clone(), + Self::StrippedOakWood { inner } => inner.0.clone(), + Self::StrippedSpruceWood { inner } => inner.0.clone(), + Self::StrippedBirchWood { inner } => inner.0.clone(), + Self::StrippedJungleWood { inner } => inner.0.clone(), + Self::StrippedAcaciaWood { inner } => inner.0.clone(), + Self::StrippedCherryWood { inner } => inner.0.clone(), + Self::StrippedDarkOakWood { inner } => inner.0.clone(), + Self::StrippedMangroveWood { inner } => inner.0.clone(), + Self::StrippedCrimsonHyphae { inner } => inner.0.clone(), + Self::StrippedWarpedHyphae { inner } => inner.0.clone(), + Self::StrippedBambooBlock { inner } => inner.0.clone(), + Self::OakWood { inner } => inner.0.clone(), + Self::SpruceWood { inner } => inner.0.clone(), + Self::BirchWood { inner } => inner.0.clone(), + Self::JungleWood { inner } => inner.0.clone(), + Self::AcaciaWood { inner } => inner.0.clone(), + Self::CherryWood { inner } => inner.0.clone(), + Self::DarkOakWood { inner } => inner.0.clone(), + Self::MangroveWood { inner } => inner.0.clone(), + Self::CrimsonHyphae { inner } => inner.0.clone(), + Self::WarpedHyphae { inner } => inner.0.clone(), + Self::OakLeaves { inner } => inner.0.clone(), + Self::SpruceLeaves { inner } => inner.0.clone(), + Self::BirchLeaves { inner } => inner.0.clone(), + Self::JungleLeaves { inner } => inner.0.clone(), + Self::AcaciaLeaves { inner } => inner.0.clone(), + Self::CherryLeaves { inner } => inner.0.clone(), + Self::DarkOakLeaves { inner } => inner.0.clone(), + Self::MangroveLeaves { inner } => inner.0.clone(), + Self::AzaleaLeaves { inner } => inner.0.clone(), + Self::FloweringAzaleaLeaves { inner } => inner.0.clone(), + Self::Sponge { inner } => inner.0.clone(), + Self::WetSponge { inner } => inner.0.clone(), + Self::Glass { inner } => inner.0.clone(), + Self::TintedGlass { inner } => inner.0.clone(), + Self::LapisBlock { inner } => inner.0.clone(), + Self::Sandstone { inner } => inner.0.clone(), + Self::ChiseledSandstone { inner } => inner.0.clone(), + Self::CutSandstone { inner } => inner.0.clone(), + Self::Cobweb { inner } => inner.0.clone(), + Self::ShortGrass { inner } => inner.0.clone(), + Self::Fern { inner } => inner.0.clone(), + Self::Azalea { inner } => inner.0.clone(), + Self::FloweringAzalea { inner } => inner.0.clone(), + Self::DeadBush { inner } => inner.0.clone(), + Self::Seagrass { inner } => inner.0.clone(), + Self::SeaPickle { inner } => inner.0.clone(), + Self::WhiteWool { inner } => inner.0.clone(), + Self::OrangeWool { inner } => inner.0.clone(), + Self::MagentaWool { inner } => inner.0.clone(), + Self::LightBlueWool { inner } => inner.0.clone(), + Self::YellowWool { inner } => inner.0.clone(), + Self::LimeWool { inner } => inner.0.clone(), + Self::PinkWool { inner } => inner.0.clone(), + Self::GrayWool { inner } => inner.0.clone(), + Self::LightGrayWool { inner } => inner.0.clone(), + Self::CyanWool { inner } => inner.0.clone(), + Self::PurpleWool { inner } => inner.0.clone(), + Self::BlueWool { inner } => inner.0.clone(), + Self::BrownWool { inner } => inner.0.clone(), + Self::GreenWool { inner } => inner.0.clone(), + Self::RedWool { inner } => inner.0.clone(), + Self::BlackWool { inner } => inner.0.clone(), + Self::Dandelion { inner } => inner.0.clone(), + Self::Poppy { inner } => inner.0.clone(), + Self::BlueOrchid { inner } => inner.0.clone(), + Self::Allium { inner } => inner.0.clone(), + Self::AzureBluet { inner } => inner.0.clone(), + Self::RedTulip { inner } => inner.0.clone(), + Self::OrangeTulip { inner } => inner.0.clone(), + Self::WhiteTulip { inner } => inner.0.clone(), + Self::PinkTulip { inner } => inner.0.clone(), + Self::OxeyeDaisy { inner } => inner.0.clone(), + Self::Cornflower { inner } => inner.0.clone(), + Self::LilyOfTheValley { inner } => inner.0.clone(), + Self::WitherRose { inner } => inner.0.clone(), + Self::Torchflower { inner } => inner.0.clone(), + Self::PitcherPlant { inner } => inner.0.clone(), + Self::SporeBlossom { inner } => inner.0.clone(), + Self::BrownMushroom { inner } => inner.0.clone(), + Self::RedMushroom { inner } => inner.0.clone(), + Self::CrimsonFungus { inner } => inner.0.clone(), + Self::WarpedFungus { inner } => inner.0.clone(), + Self::CrimsonRoots { inner } => inner.0.clone(), + Self::WarpedRoots { inner } => inner.0.clone(), + Self::NetherSprouts { inner } => inner.0.clone(), + Self::WeepingVines { inner } => inner.0.clone(), + Self::TwistingVines { inner } => inner.0.clone(), + Self::SugarCane { inner } => inner.0.clone(), + Self::Kelp { inner } => inner.0.clone(), + Self::MossCarpet { inner } => inner.0.clone(), + Self::PinkPetals { inner } => inner.0.clone(), + Self::MossBlock { inner } => inner.0.clone(), + Self::HangingRoots { inner } => inner.0.clone(), + Self::BigDripleaf { inner } => inner.0.clone(), + Self::SmallDripleaf { inner } => inner.0.clone(), + Self::Bamboo { inner } => inner.0.clone(), + Self::OakSlab { inner } => inner.0.clone(), + Self::SpruceSlab { inner } => inner.0.clone(), + Self::BirchSlab { inner } => inner.0.clone(), + Self::JungleSlab { inner } => inner.0.clone(), + Self::AcaciaSlab { inner } => inner.0.clone(), + Self::CherrySlab { inner } => inner.0.clone(), + Self::DarkOakSlab { inner } => inner.0.clone(), + Self::MangroveSlab { inner } => inner.0.clone(), + Self::BambooSlab { inner } => inner.0.clone(), + Self::BambooMosaicSlab { inner } => inner.0.clone(), + Self::CrimsonSlab { inner } => inner.0.clone(), + Self::WarpedSlab { inner } => inner.0.clone(), + Self::StoneSlab { inner } => inner.0.clone(), + Self::SmoothStoneSlab { inner } => inner.0.clone(), + Self::SandstoneSlab { inner } => inner.0.clone(), + Self::CutSandstoneSlab { inner } => inner.0.clone(), + Self::PetrifiedOakSlab { inner } => inner.0.clone(), + Self::CobblestoneSlab { inner } => inner.0.clone(), + Self::BrickSlab { inner } => inner.0.clone(), + Self::StoneBrickSlab { inner } => inner.0.clone(), + Self::MudBrickSlab { inner } => inner.0.clone(), + Self::NetherBrickSlab { inner } => inner.0.clone(), + Self::QuartzSlab { inner } => inner.0.clone(), + Self::RedSandstoneSlab { inner } => inner.0.clone(), + Self::CutRedSandstoneSlab { inner } => inner.0.clone(), + Self::PurpurSlab { inner } => inner.0.clone(), + Self::PrismarineSlab { inner } => inner.0.clone(), + Self::PrismarineBrickSlab { inner } => inner.0.clone(), + Self::DarkPrismarineSlab { inner } => inner.0.clone(), + Self::SmoothQuartz { inner } => inner.0.clone(), + Self::SmoothRedSandstone { inner } => inner.0.clone(), + Self::SmoothSandstone { inner } => inner.0.clone(), + Self::SmoothStone { inner } => inner.0.clone(), + Self::Bricks { inner } => inner.0.clone(), + Self::Bookshelf { inner } => inner.0.clone(), + Self::ChiseledBookshelf { inner } => inner.0.clone(), + Self::DecoratedPot { inner } => inner.0.clone(), + Self::MossyCobblestone { inner } => inner.0.clone(), + Self::Obsidian { inner } => inner.0.clone(), + Self::Torch { inner } => inner.0.clone(), + Self::EndRod { inner } => inner.0.clone(), + Self::ChorusPlant { inner } => inner.0.clone(), + Self::ChorusFlower { inner } => inner.0.clone(), + Self::PurpurBlock { inner } => inner.0.clone(), + Self::PurpurPillar { inner } => inner.0.clone(), + Self::PurpurStairs { inner } => inner.0.clone(), + Self::Spawner { inner } => inner.0.clone(), + Self::Chest { inner } => inner.0.clone(), + Self::CraftingTable { inner } => inner.0.clone(), + Self::Farmland { inner } => inner.0.clone(), + Self::Furnace { inner } => inner.0.clone(), + Self::Ladder { inner } => inner.0.clone(), + Self::CobblestoneStairs { inner } => inner.0.clone(), + Self::Snow { inner } => inner.0.clone(), + Self::Ice { inner } => inner.0.clone(), + Self::SnowBlock { inner } => inner.0.clone(), + Self::Cactus { inner } => inner.0.clone(), + Self::Clay { inner } => inner.0.clone(), + Self::Jukebox { inner } => inner.0.clone(), + Self::OakFence { inner } => inner.0.clone(), + Self::SpruceFence { inner } => inner.0.clone(), + Self::BirchFence { inner } => inner.0.clone(), + Self::JungleFence { inner } => inner.0.clone(), + Self::AcaciaFence { inner } => inner.0.clone(), + Self::CherryFence { inner } => inner.0.clone(), + Self::DarkOakFence { inner } => inner.0.clone(), + Self::MangroveFence { inner } => inner.0.clone(), + Self::BambooFence { inner } => inner.0.clone(), + Self::CrimsonFence { inner } => inner.0.clone(), + Self::WarpedFence { inner } => inner.0.clone(), + Self::Pumpkin { inner } => inner.0.clone(), + Self::CarvedPumpkin { inner } => inner.0.clone(), + Self::JackOLantern { inner } => inner.0.clone(), + Self::Netherrack { inner } => inner.0.clone(), + Self::SoulSand { inner } => inner.0.clone(), + Self::SoulSoil { inner } => inner.0.clone(), + Self::Basalt { inner } => inner.0.clone(), + Self::PolishedBasalt { inner } => inner.0.clone(), + Self::SmoothBasalt { inner } => inner.0.clone(), + Self::SoulTorch { inner } => inner.0.clone(), + Self::Glowstone { inner } => inner.0.clone(), + Self::InfestedStone { inner } => inner.0.clone(), + Self::InfestedCobblestone { inner } => inner.0.clone(), + Self::InfestedStoneBricks { inner } => inner.0.clone(), + Self::InfestedMossyStoneBricks { inner } => inner.0.clone(), + Self::InfestedCrackedStoneBricks { inner } => inner.0.clone(), + Self::InfestedChiseledStoneBricks { inner } => inner.0.clone(), + Self::InfestedDeepslate { inner } => inner.0.clone(), + Self::StoneBricks { inner } => inner.0.clone(), + Self::MossyStoneBricks { inner } => inner.0.clone(), + Self::CrackedStoneBricks { inner } => inner.0.clone(), + Self::ChiseledStoneBricks { inner } => inner.0.clone(), + Self::PackedMud { inner } => inner.0.clone(), + Self::MudBricks { inner } => inner.0.clone(), + Self::DeepslateBricks { inner } => inner.0.clone(), + Self::CrackedDeepslateBricks { inner } => inner.0.clone(), + Self::DeepslateTiles { inner } => inner.0.clone(), + Self::CrackedDeepslateTiles { inner } => inner.0.clone(), + Self::ChiseledDeepslate { inner } => inner.0.clone(), + Self::ReinforcedDeepslate { inner } => inner.0.clone(), + Self::BrownMushroomBlock { inner } => inner.0.clone(), + Self::RedMushroomBlock { inner } => inner.0.clone(), + Self::MushroomStem { inner } => inner.0.clone(), + Self::IronBars { inner } => inner.0.clone(), + Self::Chain { inner } => inner.0.clone(), + Self::GlassPane { inner } => inner.0.clone(), + Self::Melon { inner } => inner.0.clone(), + Self::Vine { inner } => inner.0.clone(), + Self::GlowLichen { inner } => inner.0.clone(), + Self::BrickStairs { inner } => inner.0.clone(), + Self::StoneBrickStairs { inner } => inner.0.clone(), + Self::MudBrickStairs { inner } => inner.0.clone(), + Self::Mycelium { inner } => inner.0.clone(), + Self::LilyPad { inner } => inner.0.clone(), + Self::NetherBricks { inner } => inner.0.clone(), + Self::CrackedNetherBricks { inner } => inner.0.clone(), + Self::ChiseledNetherBricks { inner } => inner.0.clone(), + Self::NetherBrickFence { inner } => inner.0.clone(), + Self::NetherBrickStairs { inner } => inner.0.clone(), + Self::Sculk { inner } => inner.0.clone(), + Self::SculkVein { inner } => inner.0.clone(), + Self::SculkCatalyst { inner } => inner.0.clone(), + Self::SculkShrieker { inner } => inner.0.clone(), + Self::EnchantingTable { inner } => inner.0.clone(), + Self::EndPortalFrame { inner } => inner.0.clone(), + Self::EndStone { inner } => inner.0.clone(), + Self::EndStoneBricks { inner } => inner.0.clone(), + Self::DragonEgg { inner } => inner.0.clone(), + Self::SandstoneStairs { inner } => inner.0.clone(), + Self::EnderChest { inner } => inner.0.clone(), + Self::EmeraldBlock { inner } => inner.0.clone(), + Self::OakStairs { inner } => inner.0.clone(), + Self::SpruceStairs { inner } => inner.0.clone(), + Self::BirchStairs { inner } => inner.0.clone(), + Self::JungleStairs { inner } => inner.0.clone(), + Self::AcaciaStairs { inner } => inner.0.clone(), + Self::CherryStairs { inner } => inner.0.clone(), + Self::DarkOakStairs { inner } => inner.0.clone(), + Self::MangroveStairs { inner } => inner.0.clone(), + Self::BambooStairs { inner } => inner.0.clone(), + Self::BambooMosaicStairs { inner } => inner.0.clone(), + Self::CrimsonStairs { inner } => inner.0.clone(), + Self::WarpedStairs { inner } => inner.0.clone(), + Self::CommandBlock { inner } => inner.0.clone(), + Self::Beacon { inner } => inner.0.clone(), + Self::CobblestoneWall { inner } => inner.0.clone(), + Self::MossyCobblestoneWall { inner } => inner.0.clone(), + Self::BrickWall { inner } => inner.0.clone(), + Self::PrismarineWall { inner } => inner.0.clone(), + Self::RedSandstoneWall { inner } => inner.0.clone(), + Self::MossyStoneBrickWall { inner } => inner.0.clone(), + Self::GraniteWall { inner } => inner.0.clone(), + Self::StoneBrickWall { inner } => inner.0.clone(), + Self::MudBrickWall { inner } => inner.0.clone(), + Self::NetherBrickWall { inner } => inner.0.clone(), + Self::AndesiteWall { inner } => inner.0.clone(), + Self::RedNetherBrickWall { inner } => inner.0.clone(), + Self::SandstoneWall { inner } => inner.0.clone(), + Self::EndStoneBrickWall { inner } => inner.0.clone(), + Self::DioriteWall { inner } => inner.0.clone(), + Self::BlackstoneWall { inner } => inner.0.clone(), + Self::PolishedBlackstoneWall { inner } => inner.0.clone(), + Self::PolishedBlackstoneBrickWall { inner } => inner.0.clone(), + Self::CobbledDeepslateWall { inner } => inner.0.clone(), + Self::PolishedDeepslateWall { inner } => inner.0.clone(), + Self::DeepslateBrickWall { inner } => inner.0.clone(), + Self::DeepslateTileWall { inner } => inner.0.clone(), + Self::Anvil { inner } => inner.0.clone(), + Self::ChippedAnvil { inner } => inner.0.clone(), + Self::DamagedAnvil { inner } => inner.0.clone(), + Self::ChiseledQuartzBlock { inner } => inner.0.clone(), + Self::QuartzBlock { inner } => inner.0.clone(), + Self::QuartzBricks { inner } => inner.0.clone(), + Self::QuartzPillar { inner } => inner.0.clone(), + Self::QuartzStairs { inner } => inner.0.clone(), + Self::WhiteTerracotta { inner } => inner.0.clone(), + Self::OrangeTerracotta { inner } => inner.0.clone(), + Self::MagentaTerracotta { inner } => inner.0.clone(), + Self::LightBlueTerracotta { inner } => inner.0.clone(), + Self::YellowTerracotta { inner } => inner.0.clone(), + Self::LimeTerracotta { inner } => inner.0.clone(), + Self::PinkTerracotta { inner } => inner.0.clone(), + Self::GrayTerracotta { inner } => inner.0.clone(), + Self::LightGrayTerracotta { inner } => inner.0.clone(), + Self::CyanTerracotta { inner } => inner.0.clone(), + Self::PurpleTerracotta { inner } => inner.0.clone(), + Self::BlueTerracotta { inner } => inner.0.clone(), + Self::BrownTerracotta { inner } => inner.0.clone(), + Self::GreenTerracotta { inner } => inner.0.clone(), + Self::RedTerracotta { inner } => inner.0.clone(), + Self::BlackTerracotta { inner } => inner.0.clone(), + Self::Barrier { inner } => inner.0.clone(), + Self::Light { inner } => inner.0.clone(), + Self::HayBlock { inner } => inner.0.clone(), + Self::WhiteCarpet { inner } => inner.0.clone(), + Self::OrangeCarpet { inner } => inner.0.clone(), + Self::MagentaCarpet { inner } => inner.0.clone(), + Self::LightBlueCarpet { inner } => inner.0.clone(), + Self::YellowCarpet { inner } => inner.0.clone(), + Self::LimeCarpet { inner } => inner.0.clone(), + Self::PinkCarpet { inner } => inner.0.clone(), + Self::GrayCarpet { inner } => inner.0.clone(), + Self::LightGrayCarpet { inner } => inner.0.clone(), + Self::CyanCarpet { inner } => inner.0.clone(), + Self::PurpleCarpet { inner } => inner.0.clone(), + Self::BlueCarpet { inner } => inner.0.clone(), + Self::BrownCarpet { inner } => inner.0.clone(), + Self::GreenCarpet { inner } => inner.0.clone(), + Self::RedCarpet { inner } => inner.0.clone(), + Self::BlackCarpet { inner } => inner.0.clone(), + Self::Terracotta { inner } => inner.0.clone(), + Self::PackedIce { inner } => inner.0.clone(), + Self::DirtPath { inner } => inner.0.clone(), + Self::Sunflower { inner } => inner.0.clone(), + Self::Lilac { inner } => inner.0.clone(), + Self::RoseBush { inner } => inner.0.clone(), + Self::Peony { inner } => inner.0.clone(), + Self::TallGrass { inner } => inner.0.clone(), + Self::LargeFern { inner } => inner.0.clone(), + Self::WhiteStainedGlass { inner } => inner.0.clone(), + Self::OrangeStainedGlass { inner } => inner.0.clone(), + Self::MagentaStainedGlass { inner } => inner.0.clone(), + Self::LightBlueStainedGlass { inner } => inner.0.clone(), + Self::YellowStainedGlass { inner } => inner.0.clone(), + Self::LimeStainedGlass { inner } => inner.0.clone(), + Self::PinkStainedGlass { inner } => inner.0.clone(), + Self::GrayStainedGlass { inner } => inner.0.clone(), + Self::LightGrayStainedGlass { inner } => inner.0.clone(), + Self::CyanStainedGlass { inner } => inner.0.clone(), + Self::PurpleStainedGlass { inner } => inner.0.clone(), + Self::BlueStainedGlass { inner } => inner.0.clone(), + Self::BrownStainedGlass { inner } => inner.0.clone(), + Self::GreenStainedGlass { inner } => inner.0.clone(), + Self::RedStainedGlass { inner } => inner.0.clone(), + Self::BlackStainedGlass { inner } => inner.0.clone(), + Self::WhiteStainedGlassPane { inner } => inner.0.clone(), + Self::OrangeStainedGlassPane { inner } => inner.0.clone(), + Self::MagentaStainedGlassPane { inner } => inner.0.clone(), + Self::LightBlueStainedGlassPane { inner } => inner.0.clone(), + Self::YellowStainedGlassPane { inner } => inner.0.clone(), + Self::LimeStainedGlassPane { inner } => inner.0.clone(), + Self::PinkStainedGlassPane { inner } => inner.0.clone(), + Self::GrayStainedGlassPane { inner } => inner.0.clone(), + Self::LightGrayStainedGlassPane { inner } => inner.0.clone(), + Self::CyanStainedGlassPane { inner } => inner.0.clone(), + Self::PurpleStainedGlassPane { inner } => inner.0.clone(), + Self::BlueStainedGlassPane { inner } => inner.0.clone(), + Self::BrownStainedGlassPane { inner } => inner.0.clone(), + Self::GreenStainedGlassPane { inner } => inner.0.clone(), + Self::RedStainedGlassPane { inner } => inner.0.clone(), + Self::BlackStainedGlassPane { inner } => inner.0.clone(), + Self::Prismarine { inner } => inner.0.clone(), + Self::PrismarineBricks { inner } => inner.0.clone(), + Self::DarkPrismarine { inner } => inner.0.clone(), + Self::PrismarineStairs { inner } => inner.0.clone(), + Self::PrismarineBrickStairs { inner } => inner.0.clone(), + Self::DarkPrismarineStairs { inner } => inner.0.clone(), + Self::SeaLantern { inner } => inner.0.clone(), + Self::RedSandstone { inner } => inner.0.clone(), + Self::ChiseledRedSandstone { inner } => inner.0.clone(), + Self::CutRedSandstone { inner } => inner.0.clone(), + Self::RedSandstoneStairs { inner } => inner.0.clone(), + Self::RepeatingCommandBlock { inner } => inner.0.clone(), + Self::ChainCommandBlock { inner } => inner.0.clone(), + Self::MagmaBlock { inner } => inner.0.clone(), + Self::NetherWartBlock { inner } => inner.0.clone(), + Self::WarpedWartBlock { inner } => inner.0.clone(), + Self::RedNetherBricks { inner } => inner.0.clone(), + Self::BoneBlock { inner } => inner.0.clone(), + Self::StructureVoid { inner } => inner.0.clone(), + Self::ShulkerBox { inner } => inner.0.clone(), + Self::WhiteShulkerBox { inner } => inner.0.clone(), + Self::OrangeShulkerBox { inner } => inner.0.clone(), + Self::MagentaShulkerBox { inner } => inner.0.clone(), + Self::LightBlueShulkerBox { inner } => inner.0.clone(), + Self::YellowShulkerBox { inner } => inner.0.clone(), + Self::LimeShulkerBox { inner } => inner.0.clone(), + Self::PinkShulkerBox { inner } => inner.0.clone(), + Self::GrayShulkerBox { inner } => inner.0.clone(), + Self::LightGrayShulkerBox { inner } => inner.0.clone(), + Self::CyanShulkerBox { inner } => inner.0.clone(), + Self::PurpleShulkerBox { inner } => inner.0.clone(), + Self::BlueShulkerBox { inner } => inner.0.clone(), + Self::BrownShulkerBox { inner } => inner.0.clone(), + Self::GreenShulkerBox { inner } => inner.0.clone(), + Self::RedShulkerBox { inner } => inner.0.clone(), + Self::BlackShulkerBox { inner } => inner.0.clone(), + Self::WhiteGlazedTerracotta { inner } => inner.0.clone(), + Self::OrangeGlazedTerracotta { inner } => inner.0.clone(), + Self::MagentaGlazedTerracotta { inner } => inner.0.clone(), + Self::LightBlueGlazedTerracotta { inner } => inner.0.clone(), + Self::YellowGlazedTerracotta { inner } => inner.0.clone(), + Self::LimeGlazedTerracotta { inner } => inner.0.clone(), + Self::PinkGlazedTerracotta { inner } => inner.0.clone(), + Self::GrayGlazedTerracotta { inner } => inner.0.clone(), + Self::LightGrayGlazedTerracotta { inner } => inner.0.clone(), + Self::CyanGlazedTerracotta { inner } => inner.0.clone(), + Self::PurpleGlazedTerracotta { inner } => inner.0.clone(), + Self::BlueGlazedTerracotta { inner } => inner.0.clone(), + Self::BrownGlazedTerracotta { inner } => inner.0.clone(), + Self::GreenGlazedTerracotta { inner } => inner.0.clone(), + Self::RedGlazedTerracotta { inner } => inner.0.clone(), + Self::BlackGlazedTerracotta { inner } => inner.0.clone(), + Self::WhiteConcrete { inner } => inner.0.clone(), + Self::OrangeConcrete { inner } => inner.0.clone(), + Self::MagentaConcrete { inner } => inner.0.clone(), + Self::LightBlueConcrete { inner } => inner.0.clone(), + Self::YellowConcrete { inner } => inner.0.clone(), + Self::LimeConcrete { inner } => inner.0.clone(), + Self::PinkConcrete { inner } => inner.0.clone(), + Self::GrayConcrete { inner } => inner.0.clone(), + Self::LightGrayConcrete { inner } => inner.0.clone(), + Self::CyanConcrete { inner } => inner.0.clone(), + Self::PurpleConcrete { inner } => inner.0.clone(), + Self::BlueConcrete { inner } => inner.0.clone(), + Self::BrownConcrete { inner } => inner.0.clone(), + Self::GreenConcrete { inner } => inner.0.clone(), + Self::RedConcrete { inner } => inner.0.clone(), + Self::BlackConcrete { inner } => inner.0.clone(), + Self::WhiteConcretePowder { inner } => inner.0.clone(), + Self::OrangeConcretePowder { inner } => inner.0.clone(), + Self::MagentaConcretePowder { inner } => inner.0.clone(), + Self::LightBlueConcretePowder { inner } => inner.0.clone(), + Self::YellowConcretePowder { inner } => inner.0.clone(), + Self::LimeConcretePowder { inner } => inner.0.clone(), + Self::PinkConcretePowder { inner } => inner.0.clone(), + Self::GrayConcretePowder { inner } => inner.0.clone(), + Self::LightGrayConcretePowder { inner } => inner.0.clone(), + Self::CyanConcretePowder { inner } => inner.0.clone(), + Self::PurpleConcretePowder { inner } => inner.0.clone(), + Self::BlueConcretePowder { inner } => inner.0.clone(), + Self::BrownConcretePowder { inner } => inner.0.clone(), + Self::GreenConcretePowder { inner } => inner.0.clone(), + Self::RedConcretePowder { inner } => inner.0.clone(), + Self::BlackConcretePowder { inner } => inner.0.clone(), + Self::TurtleEgg { inner } => inner.0.clone(), + Self::SnifferEgg { inner } => inner.0.clone(), + Self::DeadTubeCoralBlock { inner } => inner.0.clone(), + Self::DeadBrainCoralBlock { inner } => inner.0.clone(), + Self::DeadBubbleCoralBlock { inner } => inner.0.clone(), + Self::DeadFireCoralBlock { inner } => inner.0.clone(), + Self::DeadHornCoralBlock { inner } => inner.0.clone(), + Self::TubeCoralBlock { inner } => inner.0.clone(), + Self::BrainCoralBlock { inner } => inner.0.clone(), + Self::BubbleCoralBlock { inner } => inner.0.clone(), + Self::FireCoralBlock { inner } => inner.0.clone(), + Self::HornCoralBlock { inner } => inner.0.clone(), + Self::TubeCoral { inner } => inner.0.clone(), + Self::BrainCoral { inner } => inner.0.clone(), + Self::BubbleCoral { inner } => inner.0.clone(), + Self::FireCoral { inner } => inner.0.clone(), + Self::HornCoral { inner } => inner.0.clone(), + Self::DeadBrainCoral { inner } => inner.0.clone(), + Self::DeadBubbleCoral { inner } => inner.0.clone(), + Self::DeadFireCoral { inner } => inner.0.clone(), + Self::DeadHornCoral { inner } => inner.0.clone(), + Self::DeadTubeCoral { inner } => inner.0.clone(), + Self::TubeCoralFan { inner } => inner.0.clone(), + Self::BrainCoralFan { inner } => inner.0.clone(), + Self::BubbleCoralFan { inner } => inner.0.clone(), + Self::FireCoralFan { inner } => inner.0.clone(), + Self::HornCoralFan { inner } => inner.0.clone(), + Self::DeadTubeCoralFan { inner } => inner.0.clone(), + Self::DeadBrainCoralFan { inner } => inner.0.clone(), + Self::DeadBubbleCoralFan { inner } => inner.0.clone(), + Self::DeadFireCoralFan { inner } => inner.0.clone(), + Self::DeadHornCoralFan { inner } => inner.0.clone(), + Self::BlueIce { inner } => inner.0.clone(), + Self::Conduit { inner } => inner.0.clone(), + Self::PolishedGraniteStairs { inner } => inner.0.clone(), + Self::SmoothRedSandstoneStairs { inner } => inner.0.clone(), + Self::MossyStoneBrickStairs { inner } => inner.0.clone(), + Self::PolishedDioriteStairs { inner } => inner.0.clone(), + Self::MossyCobblestoneStairs { inner } => inner.0.clone(), + Self::EndStoneBrickStairs { inner } => inner.0.clone(), + Self::StoneStairs { inner } => inner.0.clone(), + Self::SmoothSandstoneStairs { inner } => inner.0.clone(), + Self::SmoothQuartzStairs { inner } => inner.0.clone(), + Self::GraniteStairs { inner } => inner.0.clone(), + Self::AndesiteStairs { inner } => inner.0.clone(), + Self::RedNetherBrickStairs { inner } => inner.0.clone(), + Self::PolishedAndesiteStairs { inner } => inner.0.clone(), + Self::DioriteStairs { inner } => inner.0.clone(), + Self::CobbledDeepslateStairs { inner } => inner.0.clone(), + Self::PolishedDeepslateStairs { inner } => inner.0.clone(), + Self::DeepslateBrickStairs { inner } => inner.0.clone(), + Self::DeepslateTileStairs { inner } => inner.0.clone(), + Self::PolishedGraniteSlab { inner } => inner.0.clone(), + Self::SmoothRedSandstoneSlab { inner } => inner.0.clone(), + Self::MossyStoneBrickSlab { inner } => inner.0.clone(), + Self::PolishedDioriteSlab { inner } => inner.0.clone(), + Self::MossyCobblestoneSlab { inner } => inner.0.clone(), + Self::EndStoneBrickSlab { inner } => inner.0.clone(), + Self::SmoothSandstoneSlab { inner } => inner.0.clone(), + Self::SmoothQuartzSlab { inner } => inner.0.clone(), + Self::GraniteSlab { inner } => inner.0.clone(), + Self::AndesiteSlab { inner } => inner.0.clone(), + Self::RedNetherBrickSlab { inner } => inner.0.clone(), + Self::PolishedAndesiteSlab { inner } => inner.0.clone(), + Self::DioriteSlab { inner } => inner.0.clone(), + Self::CobbledDeepslateSlab { inner } => inner.0.clone(), + Self::PolishedDeepslateSlab { inner } => inner.0.clone(), + Self::DeepslateBrickSlab { inner } => inner.0.clone(), + Self::DeepslateTileSlab { inner } => inner.0.clone(), + Self::Scaffolding { inner } => inner.0.clone(), + Self::Redstone { inner } => inner.0.clone(), + Self::RedstoneTorch { inner } => inner.0.clone(), + Self::RedstoneBlock { inner } => inner.0.clone(), + Self::Repeater { inner } => inner.0.clone(), + Self::Comparator { inner } => inner.0.clone(), + Self::Piston { inner } => inner.0.clone(), + Self::StickyPiston { inner } => inner.0.clone(), + Self::SlimeBlock { inner } => inner.0.clone(), + Self::HoneyBlock { inner } => inner.0.clone(), + Self::Observer { inner } => inner.0.clone(), + Self::Hopper { inner } => inner.0.clone(), + Self::Dispenser { inner } => inner.0.clone(), + Self::Dropper { inner } => inner.0.clone(), + Self::Lectern { inner } => inner.0.clone(), + Self::Target { inner } => inner.0.clone(), + Self::Lever { inner } => inner.0.clone(), + Self::LightningRod { inner } => inner.0.clone(), + Self::DaylightDetector { inner } => inner.0.clone(), + Self::SculkSensor { inner } => inner.0.clone(), + Self::CalibratedSculkSensor { inner } => inner.0.clone(), + Self::TripwireHook { inner } => inner.0.clone(), + Self::TrappedChest { inner } => inner.0.clone(), + Self::Tnt { inner } => inner.0.clone(), + Self::RedstoneLamp { inner } => inner.0.clone(), + Self::NoteBlock { inner } => inner.0.clone(), + Self::StoneButton { inner } => inner.0.clone(), + Self::PolishedBlackstoneButton { inner } => inner.0.clone(), + Self::OakButton { inner } => inner.0.clone(), + Self::SpruceButton { inner } => inner.0.clone(), + Self::BirchButton { inner } => inner.0.clone(), + Self::JungleButton { inner } => inner.0.clone(), + Self::AcaciaButton { inner } => inner.0.clone(), + Self::CherryButton { inner } => inner.0.clone(), + Self::DarkOakButton { inner } => inner.0.clone(), + Self::MangroveButton { inner } => inner.0.clone(), + Self::BambooButton { inner } => inner.0.clone(), + Self::CrimsonButton { inner } => inner.0.clone(), + Self::WarpedButton { inner } => inner.0.clone(), + Self::StonePressurePlate { inner } => inner.0.clone(), + Self::PolishedBlackstonePressurePlate { inner } => inner.0.clone(), + Self::LightWeightedPressurePlate { inner } => inner.0.clone(), + Self::HeavyWeightedPressurePlate { inner } => inner.0.clone(), + Self::OakPressurePlate { inner } => inner.0.clone(), + Self::SprucePressurePlate { inner } => inner.0.clone(), + Self::BirchPressurePlate { inner } => inner.0.clone(), + Self::JunglePressurePlate { inner } => inner.0.clone(), + Self::AcaciaPressurePlate { inner } => inner.0.clone(), + Self::CherryPressurePlate { inner } => inner.0.clone(), + Self::DarkOakPressurePlate { inner } => inner.0.clone(), + Self::MangrovePressurePlate { inner } => inner.0.clone(), + Self::BambooPressurePlate { inner } => inner.0.clone(), + Self::CrimsonPressurePlate { inner } => inner.0.clone(), + Self::WarpedPressurePlate { inner } => inner.0.clone(), + Self::IronDoor { inner } => inner.0.clone(), + Self::OakDoor { inner } => inner.0.clone(), + Self::SpruceDoor { inner } => inner.0.clone(), + Self::BirchDoor { inner } => inner.0.clone(), + Self::JungleDoor { inner } => inner.0.clone(), + Self::AcaciaDoor { inner } => inner.0.clone(), + Self::CherryDoor { inner } => inner.0.clone(), + Self::DarkOakDoor { inner } => inner.0.clone(), + Self::MangroveDoor { inner } => inner.0.clone(), + Self::BambooDoor { inner } => inner.0.clone(), + Self::CrimsonDoor { inner } => inner.0.clone(), + Self::WarpedDoor { inner } => inner.0.clone(), + Self::CopperDoor { inner } => inner.0.clone(), + Self::ExposedCopperDoor { inner } => inner.0.clone(), + Self::WeatheredCopperDoor { inner } => inner.0.clone(), + Self::OxidizedCopperDoor { inner } => inner.0.clone(), + Self::WaxedCopperDoor { inner } => inner.0.clone(), + Self::WaxedExposedCopperDoor { inner } => inner.0.clone(), + Self::WaxedWeatheredCopperDoor { inner } => inner.0.clone(), + Self::WaxedOxidizedCopperDoor { inner } => inner.0.clone(), + Self::IronTrapdoor { inner } => inner.0.clone(), + Self::OakTrapdoor { inner } => inner.0.clone(), + Self::SpruceTrapdoor { inner } => inner.0.clone(), + Self::BirchTrapdoor { inner } => inner.0.clone(), + Self::JungleTrapdoor { inner } => inner.0.clone(), + Self::AcaciaTrapdoor { inner } => inner.0.clone(), + Self::CherryTrapdoor { inner } => inner.0.clone(), + Self::DarkOakTrapdoor { inner } => inner.0.clone(), + Self::MangroveTrapdoor { inner } => inner.0.clone(), + Self::BambooTrapdoor { inner } => inner.0.clone(), + Self::CrimsonTrapdoor { inner } => inner.0.clone(), + Self::WarpedTrapdoor { inner } => inner.0.clone(), + Self::CopperTrapdoor { inner } => inner.0.clone(), + Self::ExposedCopperTrapdoor { inner } => inner.0.clone(), + Self::WeatheredCopperTrapdoor { inner } => inner.0.clone(), + Self::OxidizedCopperTrapdoor { inner } => inner.0.clone(), + Self::WaxedCopperTrapdoor { inner } => inner.0.clone(), + Self::WaxedExposedCopperTrapdoor { inner } => inner.0.clone(), + Self::WaxedWeatheredCopperTrapdoor { inner } => inner.0.clone(), + Self::WaxedOxidizedCopperTrapdoor { inner } => inner.0.clone(), + Self::OakFenceGate { inner } => inner.0.clone(), + Self::SpruceFenceGate { inner } => inner.0.clone(), + Self::BirchFenceGate { inner } => inner.0.clone(), + Self::JungleFenceGate { inner } => inner.0.clone(), + Self::AcaciaFenceGate { inner } => inner.0.clone(), + Self::CherryFenceGate { inner } => inner.0.clone(), + Self::DarkOakFenceGate { inner } => inner.0.clone(), + Self::MangroveFenceGate { inner } => inner.0.clone(), + Self::BambooFenceGate { inner } => inner.0.clone(), + Self::CrimsonFenceGate { inner } => inner.0.clone(), + Self::WarpedFenceGate { inner } => inner.0.clone(), + Self::PoweredRail { inner } => inner.0.clone(), + Self::DetectorRail { inner } => inner.0.clone(), + Self::Rail { inner } => inner.0.clone(), + Self::ActivatorRail { inner } => inner.0.clone(), + Self::Saddle { inner } => inner.0.clone(), + Self::Minecart { inner } => inner.0.clone(), + Self::ChestMinecart { inner } => inner.0.clone(), + Self::FurnaceMinecart { inner } => inner.0.clone(), + Self::TntMinecart { inner } => inner.0.clone(), + Self::HopperMinecart { inner } => inner.0.clone(), + Self::CarrotOnAStick { inner } => inner.0.clone(), + Self::WarpedFungusOnAStick { inner } => inner.0.clone(), + Self::Elytra { inner } => inner.0.clone(), + Self::OakBoat { inner } => inner.0.clone(), + Self::OakChestBoat { inner } => inner.0.clone(), + Self::SpruceBoat { inner } => inner.0.clone(), + Self::SpruceChestBoat { inner } => inner.0.clone(), + Self::BirchBoat { inner } => inner.0.clone(), + Self::BirchChestBoat { inner } => inner.0.clone(), + Self::JungleBoat { inner } => inner.0.clone(), + Self::JungleChestBoat { inner } => inner.0.clone(), + Self::AcaciaBoat { inner } => inner.0.clone(), + Self::AcaciaChestBoat { inner } => inner.0.clone(), + Self::CherryBoat { inner } => inner.0.clone(), + Self::CherryChestBoat { inner } => inner.0.clone(), + Self::DarkOakBoat { inner } => inner.0.clone(), + Self::DarkOakChestBoat { inner } => inner.0.clone(), + Self::MangroveBoat { inner } => inner.0.clone(), + Self::MangroveChestBoat { inner } => inner.0.clone(), + Self::BambooRaft { inner } => inner.0.clone(), + Self::BambooChestRaft { inner } => inner.0.clone(), + Self::StructureBlock { inner } => inner.0.clone(), + Self::Jigsaw { inner } => inner.0.clone(), + Self::TurtleHelmet { inner } => inner.0.clone(), + Self::TurtleScute { inner } => inner.0.clone(), + Self::ArmadilloScute { inner } => inner.0.clone(), + Self::WolfArmor { inner } => inner.0.clone(), + Self::FlintAndSteel { inner } => inner.0.clone(), + Self::Bowl { inner } => inner.0.clone(), + Self::Apple { inner } => inner.0.clone(), + Self::Bow { inner } => inner.0.clone(), + Self::Arrow { inner } => inner.0.clone(), + Self::Coal { inner } => inner.0.clone(), + Self::Charcoal { inner } => inner.0.clone(), + Self::Diamond { inner } => inner.0.clone(), + Self::Emerald { inner } => inner.0.clone(), + Self::LapisLazuli { inner } => inner.0.clone(), + Self::Quartz { inner } => inner.0.clone(), + Self::AmethystShard { inner } => inner.0.clone(), + Self::RawIron { inner } => inner.0.clone(), + Self::IronIngot { inner } => inner.0.clone(), + Self::RawCopper { inner } => inner.0.clone(), + Self::CopperIngot { inner } => inner.0.clone(), + Self::RawGold { inner } => inner.0.clone(), + Self::GoldIngot { inner } => inner.0.clone(), + Self::NetheriteIngot { inner } => inner.0.clone(), + Self::NetheriteScrap { inner } => inner.0.clone(), + Self::WoodenSword { inner } => inner.0.clone(), + Self::WoodenShovel { inner } => inner.0.clone(), + Self::WoodenPickaxe { inner } => inner.0.clone(), + Self::WoodenAxe { inner } => inner.0.clone(), + Self::WoodenHoe { inner } => inner.0.clone(), + Self::StoneSword { inner } => inner.0.clone(), + Self::StoneShovel { inner } => inner.0.clone(), + Self::StonePickaxe { inner } => inner.0.clone(), + Self::StoneAxe { inner } => inner.0.clone(), + Self::StoneHoe { inner } => inner.0.clone(), + Self::GoldenSword { inner } => inner.0.clone(), + Self::GoldenShovel { inner } => inner.0.clone(), + Self::GoldenPickaxe { inner } => inner.0.clone(), + Self::GoldenAxe { inner } => inner.0.clone(), + Self::GoldenHoe { inner } => inner.0.clone(), + Self::IronSword { inner } => inner.0.clone(), + Self::IronShovel { inner } => inner.0.clone(), + Self::IronPickaxe { inner } => inner.0.clone(), + Self::IronAxe { inner } => inner.0.clone(), + Self::IronHoe { inner } => inner.0.clone(), + Self::DiamondSword { inner } => inner.0.clone(), + Self::DiamondShovel { inner } => inner.0.clone(), + Self::DiamondPickaxe { inner } => inner.0.clone(), + Self::DiamondAxe { inner } => inner.0.clone(), + Self::DiamondHoe { inner } => inner.0.clone(), + Self::NetheriteSword { inner } => inner.0.clone(), + Self::NetheriteShovel { inner } => inner.0.clone(), + Self::NetheritePickaxe { inner } => inner.0.clone(), + Self::NetheriteAxe { inner } => inner.0.clone(), + Self::NetheriteHoe { inner } => inner.0.clone(), + Self::Stick { inner } => inner.0.clone(), + Self::MushroomStew { inner } => inner.0.clone(), + Self::String { inner } => inner.0.clone(), + Self::Feather { inner } => inner.0.clone(), + Self::Gunpowder { inner } => inner.0.clone(), + Self::WheatSeeds { inner } => inner.0.clone(), + Self::Wheat { inner } => inner.0.clone(), + Self::Bread { inner } => inner.0.clone(), + Self::LeatherHelmet { inner } => inner.0.clone(), + Self::LeatherChestplate { inner } => inner.0.clone(), + Self::LeatherLeggings { inner } => inner.0.clone(), + Self::LeatherBoots { inner } => inner.0.clone(), + Self::ChainmailHelmet { inner } => inner.0.clone(), + Self::ChainmailChestplate { inner } => inner.0.clone(), + Self::ChainmailLeggings { inner } => inner.0.clone(), + Self::ChainmailBoots { inner } => inner.0.clone(), + Self::IronHelmet { inner } => inner.0.clone(), + Self::IronChestplate { inner } => inner.0.clone(), + Self::IronLeggings { inner } => inner.0.clone(), + Self::IronBoots { inner } => inner.0.clone(), + Self::DiamondHelmet { inner } => inner.0.clone(), + Self::DiamondChestplate { inner } => inner.0.clone(), + Self::DiamondLeggings { inner } => inner.0.clone(), + Self::DiamondBoots { inner } => inner.0.clone(), + Self::GoldenHelmet { inner } => inner.0.clone(), + Self::GoldenChestplate { inner } => inner.0.clone(), + Self::GoldenLeggings { inner } => inner.0.clone(), + Self::GoldenBoots { inner } => inner.0.clone(), + Self::NetheriteHelmet { inner } => inner.0.clone(), + Self::NetheriteChestplate { inner } => inner.0.clone(), + Self::NetheriteLeggings { inner } => inner.0.clone(), + Self::NetheriteBoots { inner } => inner.0.clone(), + Self::Flint { inner } => inner.0.clone(), + Self::Porkchop { inner } => inner.0.clone(), + Self::CookedPorkchop { inner } => inner.0.clone(), + Self::Painting { inner } => inner.0.clone(), + Self::GoldenApple { inner } => inner.0.clone(), + Self::EnchantedGoldenApple { inner } => inner.0.clone(), + Self::OakSign { inner } => inner.0.clone(), + Self::SpruceSign { inner } => inner.0.clone(), + Self::BirchSign { inner } => inner.0.clone(), + Self::JungleSign { inner } => inner.0.clone(), + Self::AcaciaSign { inner } => inner.0.clone(), + Self::CherrySign { inner } => inner.0.clone(), + Self::DarkOakSign { inner } => inner.0.clone(), + Self::MangroveSign { inner } => inner.0.clone(), + Self::BambooSign { inner } => inner.0.clone(), + Self::CrimsonSign { inner } => inner.0.clone(), + Self::WarpedSign { inner } => inner.0.clone(), + Self::OakHangingSign { inner } => inner.0.clone(), + Self::SpruceHangingSign { inner } => inner.0.clone(), + Self::BirchHangingSign { inner } => inner.0.clone(), + Self::JungleHangingSign { inner } => inner.0.clone(), + Self::AcaciaHangingSign { inner } => inner.0.clone(), + Self::CherryHangingSign { inner } => inner.0.clone(), + Self::DarkOakHangingSign { inner } => inner.0.clone(), + Self::MangroveHangingSign { inner } => inner.0.clone(), + Self::BambooHangingSign { inner } => inner.0.clone(), + Self::CrimsonHangingSign { inner } => inner.0.clone(), + Self::WarpedHangingSign { inner } => inner.0.clone(), + Self::Bucket { inner } => inner.0.clone(), + Self::WaterBucket { inner } => inner.0.clone(), + Self::LavaBucket { inner } => inner.0.clone(), + Self::PowderSnowBucket { inner } => inner.0.clone(), + Self::Snowball { inner } => inner.0.clone(), + Self::Leather { inner } => inner.0.clone(), + Self::MilkBucket { inner } => inner.0.clone(), + Self::PufferfishBucket { inner } => inner.0.clone(), + Self::SalmonBucket { inner } => inner.0.clone(), + Self::CodBucket { inner } => inner.0.clone(), + Self::TropicalFishBucket { inner } => inner.0.clone(), + Self::AxolotlBucket { inner } => inner.0.clone(), + Self::TadpoleBucket { inner } => inner.0.clone(), + Self::Brick { inner } => inner.0.clone(), + Self::ClayBall { inner } => inner.0.clone(), + Self::DriedKelpBlock { inner } => inner.0.clone(), + Self::Paper { inner } => inner.0.clone(), + Self::Book { inner } => inner.0.clone(), + Self::SlimeBall { inner } => inner.0.clone(), + Self::Egg { inner } => inner.0.clone(), + Self::Compass { inner } => inner.0.clone(), + Self::RecoveryCompass { inner } => inner.0.clone(), + Self::Bundle { inner } => inner.0.clone(), + Self::FishingRod { inner } => inner.0.clone(), + Self::Clock { inner } => inner.0.clone(), + Self::Spyglass { inner } => inner.0.clone(), + Self::GlowstoneDust { inner } => inner.0.clone(), + Self::Cod { inner } => inner.0.clone(), + Self::Salmon { inner } => inner.0.clone(), + Self::TropicalFish { inner } => inner.0.clone(), + Self::Pufferfish { inner } => inner.0.clone(), + Self::CookedCod { inner } => inner.0.clone(), + Self::CookedSalmon { inner } => inner.0.clone(), + Self::InkSac { inner } => inner.0.clone(), + Self::GlowInkSac { inner } => inner.0.clone(), + Self::CocoaBeans { inner } => inner.0.clone(), + Self::WhiteDye { inner } => inner.0.clone(), + Self::OrangeDye { inner } => inner.0.clone(), + Self::MagentaDye { inner } => inner.0.clone(), + Self::LightBlueDye { inner } => inner.0.clone(), + Self::YellowDye { inner } => inner.0.clone(), + Self::LimeDye { inner } => inner.0.clone(), + Self::PinkDye { inner } => inner.0.clone(), + Self::GrayDye { inner } => inner.0.clone(), + Self::LightGrayDye { inner } => inner.0.clone(), + Self::CyanDye { inner } => inner.0.clone(), + Self::PurpleDye { inner } => inner.0.clone(), + Self::BlueDye { inner } => inner.0.clone(), + Self::BrownDye { inner } => inner.0.clone(), + Self::GreenDye { inner } => inner.0.clone(), + Self::RedDye { inner } => inner.0.clone(), + Self::BlackDye { inner } => inner.0.clone(), + Self::BoneMeal { inner } => inner.0.clone(), + Self::Bone { inner } => inner.0.clone(), + Self::Sugar { inner } => inner.0.clone(), + Self::Cake { inner } => inner.0.clone(), + Self::WhiteBed { inner } => inner.0.clone(), + Self::OrangeBed { inner } => inner.0.clone(), + Self::MagentaBed { inner } => inner.0.clone(), + Self::LightBlueBed { inner } => inner.0.clone(), + Self::YellowBed { inner } => inner.0.clone(), + Self::LimeBed { inner } => inner.0.clone(), + Self::PinkBed { inner } => inner.0.clone(), + Self::GrayBed { inner } => inner.0.clone(), + Self::LightGrayBed { inner } => inner.0.clone(), + Self::CyanBed { inner } => inner.0.clone(), + Self::PurpleBed { inner } => inner.0.clone(), + Self::BlueBed { inner } => inner.0.clone(), + Self::BrownBed { inner } => inner.0.clone(), + Self::GreenBed { inner } => inner.0.clone(), + Self::RedBed { inner } => inner.0.clone(), + Self::BlackBed { inner } => inner.0.clone(), + Self::Cookie { inner } => inner.0.clone(), + Self::Crafter { inner } => inner.0.clone(), + Self::FilledMap { inner } => inner.0.clone(), + Self::Shears { inner } => inner.0.clone(), + Self::MelonSlice { inner } => inner.0.clone(), + Self::DriedKelp { inner } => inner.0.clone(), + Self::PumpkinSeeds { inner } => inner.0.clone(), + Self::MelonSeeds { inner } => inner.0.clone(), + Self::Beef { inner } => inner.0.clone(), + Self::CookedBeef { inner } => inner.0.clone(), + Self::Chicken { inner } => inner.0.clone(), + Self::CookedChicken { inner } => inner.0.clone(), + Self::RottenFlesh { inner } => inner.0.clone(), + Self::EnderPearl { inner } => inner.0.clone(), + Self::BlazeRod { inner } => inner.0.clone(), + Self::GhastTear { inner } => inner.0.clone(), + Self::GoldNugget { inner } => inner.0.clone(), + Self::NetherWart { inner } => inner.0.clone(), + Self::Potion { inner } => inner.0.clone(), + Self::GlassBottle { inner } => inner.0.clone(), + Self::SpiderEye { inner } => inner.0.clone(), + Self::FermentedSpiderEye { inner } => inner.0.clone(), + Self::BlazePowder { inner } => inner.0.clone(), + Self::MagmaCream { inner } => inner.0.clone(), + Self::BrewingStand { inner } => inner.0.clone(), + Self::Cauldron { inner } => inner.0.clone(), + Self::EnderEye { inner } => inner.0.clone(), + Self::GlisteringMelonSlice { inner } => inner.0.clone(), + Self::ArmadilloSpawnEgg { inner } => inner.0.clone(), + Self::AllaySpawnEgg { inner } => inner.0.clone(), + Self::AxolotlSpawnEgg { inner } => inner.0.clone(), + Self::BatSpawnEgg { inner } => inner.0.clone(), + Self::BeeSpawnEgg { inner } => inner.0.clone(), + Self::BlazeSpawnEgg { inner } => inner.0.clone(), + Self::BoggedSpawnEgg { inner } => inner.0.clone(), + Self::BreezeSpawnEgg { inner } => inner.0.clone(), + Self::CatSpawnEgg { inner } => inner.0.clone(), + Self::CamelSpawnEgg { inner } => inner.0.clone(), + Self::CaveSpiderSpawnEgg { inner } => inner.0.clone(), + Self::ChickenSpawnEgg { inner } => inner.0.clone(), + Self::CodSpawnEgg { inner } => inner.0.clone(), + Self::CowSpawnEgg { inner } => inner.0.clone(), + Self::CreeperSpawnEgg { inner } => inner.0.clone(), + Self::DolphinSpawnEgg { inner } => inner.0.clone(), + Self::DonkeySpawnEgg { inner } => inner.0.clone(), + Self::DrownedSpawnEgg { inner } => inner.0.clone(), + Self::ElderGuardianSpawnEgg { inner } => inner.0.clone(), + Self::EnderDragonSpawnEgg { inner } => inner.0.clone(), + Self::EndermanSpawnEgg { inner } => inner.0.clone(), + Self::EndermiteSpawnEgg { inner } => inner.0.clone(), + Self::EvokerSpawnEgg { inner } => inner.0.clone(), + Self::FoxSpawnEgg { inner } => inner.0.clone(), + Self::FrogSpawnEgg { inner } => inner.0.clone(), + Self::GhastSpawnEgg { inner } => inner.0.clone(), + Self::GlowSquidSpawnEgg { inner } => inner.0.clone(), + Self::GoatSpawnEgg { inner } => inner.0.clone(), + Self::GuardianSpawnEgg { inner } => inner.0.clone(), + Self::HoglinSpawnEgg { inner } => inner.0.clone(), + Self::HorseSpawnEgg { inner } => inner.0.clone(), + Self::HuskSpawnEgg { inner } => inner.0.clone(), + Self::IronGolemSpawnEgg { inner } => inner.0.clone(), + Self::LlamaSpawnEgg { inner } => inner.0.clone(), + Self::MagmaCubeSpawnEgg { inner } => inner.0.clone(), + Self::MooshroomSpawnEgg { inner } => inner.0.clone(), + Self::MuleSpawnEgg { inner } => inner.0.clone(), + Self::OcelotSpawnEgg { inner } => inner.0.clone(), + Self::PandaSpawnEgg { inner } => inner.0.clone(), + Self::ParrotSpawnEgg { inner } => inner.0.clone(), + Self::PhantomSpawnEgg { inner } => inner.0.clone(), + Self::PigSpawnEgg { inner } => inner.0.clone(), + Self::PiglinSpawnEgg { inner } => inner.0.clone(), + Self::PiglinBruteSpawnEgg { inner } => inner.0.clone(), + Self::PillagerSpawnEgg { inner } => inner.0.clone(), + Self::PolarBearSpawnEgg { inner } => inner.0.clone(), + Self::PufferfishSpawnEgg { inner } => inner.0.clone(), + Self::RabbitSpawnEgg { inner } => inner.0.clone(), + Self::RavagerSpawnEgg { inner } => inner.0.clone(), + Self::SalmonSpawnEgg { inner } => inner.0.clone(), + Self::SheepSpawnEgg { inner } => inner.0.clone(), + Self::ShulkerSpawnEgg { inner } => inner.0.clone(), + Self::SilverfishSpawnEgg { inner } => inner.0.clone(), + Self::SkeletonSpawnEgg { inner } => inner.0.clone(), + Self::SkeletonHorseSpawnEgg { inner } => inner.0.clone(), + Self::SlimeSpawnEgg { inner } => inner.0.clone(), + Self::SnifferSpawnEgg { inner } => inner.0.clone(), + Self::SnowGolemSpawnEgg { inner } => inner.0.clone(), + Self::SpiderSpawnEgg { inner } => inner.0.clone(), + Self::SquidSpawnEgg { inner } => inner.0.clone(), + Self::StraySpawnEgg { inner } => inner.0.clone(), + Self::StriderSpawnEgg { inner } => inner.0.clone(), + Self::TadpoleSpawnEgg { inner } => inner.0.clone(), + Self::TraderLlamaSpawnEgg { inner } => inner.0.clone(), + Self::TropicalFishSpawnEgg { inner } => inner.0.clone(), + Self::TurtleSpawnEgg { inner } => inner.0.clone(), + Self::VexSpawnEgg { inner } => inner.0.clone(), + Self::VillagerSpawnEgg { inner } => inner.0.clone(), + Self::VindicatorSpawnEgg { inner } => inner.0.clone(), + Self::WanderingTraderSpawnEgg { inner } => inner.0.clone(), + Self::WardenSpawnEgg { inner } => inner.0.clone(), + Self::WitchSpawnEgg { inner } => inner.0.clone(), + Self::WitherSpawnEgg { inner } => inner.0.clone(), + Self::WitherSkeletonSpawnEgg { inner } => inner.0.clone(), + Self::WolfSpawnEgg { inner } => inner.0.clone(), + Self::ZoglinSpawnEgg { inner } => inner.0.clone(), + Self::ZombieSpawnEgg { inner } => inner.0.clone(), + Self::ZombieHorseSpawnEgg { inner } => inner.0.clone(), + Self::ZombieVillagerSpawnEgg { inner } => inner.0.clone(), + Self::ZombifiedPiglinSpawnEgg { inner } => inner.0.clone(), + Self::ExperienceBottle { inner } => inner.0.clone(), + Self::FireCharge { inner } => inner.0.clone(), + Self::WindCharge { inner } => inner.0.clone(), + Self::WritableBook { inner } => inner.0.clone(), + Self::WrittenBook { inner } => inner.0.clone(), + Self::Mace { inner } => inner.0.clone(), + Self::ItemFrame { inner } => inner.0.clone(), + Self::GlowItemFrame { inner } => inner.0.clone(), + Self::FlowerPot { inner } => inner.0.clone(), + Self::Carrot { inner } => inner.0.clone(), + Self::Potato { inner } => inner.0.clone(), + Self::BakedPotato { inner } => inner.0.clone(), + Self::PoisonousPotato { inner } => inner.0.clone(), + Self::Map { inner } => inner.0.clone(), + Self::GoldenCarrot { inner } => inner.0.clone(), + Self::SkeletonSkull { inner } => inner.0.clone(), + Self::WitherSkeletonSkull { inner } => inner.0.clone(), + Self::PlayerHead { inner } => inner.0.clone(), + Self::ZombieHead { inner } => inner.0.clone(), + Self::CreeperHead { inner } => inner.0.clone(), + Self::DragonHead { inner } => inner.0.clone(), + Self::PiglinHead { inner } => inner.0.clone(), + Self::NetherStar { inner } => inner.0.clone(), + Self::PumpkinPie { inner } => inner.0.clone(), + Self::FireworkRocket { inner } => inner.0.clone(), + Self::FireworkStar { inner } => inner.0.clone(), + Self::EnchantedBook { inner } => inner.0.clone(), + Self::NetherBrick { inner } => inner.0.clone(), + Self::PrismarineShard { inner } => inner.0.clone(), + Self::PrismarineCrystals { inner } => inner.0.clone(), + Self::Rabbit { inner } => inner.0.clone(), + Self::CookedRabbit { inner } => inner.0.clone(), + Self::RabbitStew { inner } => inner.0.clone(), + Self::RabbitFoot { inner } => inner.0.clone(), + Self::RabbitHide { inner } => inner.0.clone(), + Self::ArmorStand { inner } => inner.0.clone(), + Self::IronHorseArmor { inner } => inner.0.clone(), + Self::GoldenHorseArmor { inner } => inner.0.clone(), + Self::DiamondHorseArmor { inner } => inner.0.clone(), + Self::LeatherHorseArmor { inner } => inner.0.clone(), + Self::Lead { inner } => inner.0.clone(), + Self::NameTag { inner } => inner.0.clone(), + Self::CommandBlockMinecart { inner } => inner.0.clone(), + Self::Mutton { inner } => inner.0.clone(), + Self::CookedMutton { inner } => inner.0.clone(), + Self::WhiteBanner { inner } => inner.0.clone(), + Self::OrangeBanner { inner } => inner.0.clone(), + Self::MagentaBanner { inner } => inner.0.clone(), + Self::LightBlueBanner { inner } => inner.0.clone(), + Self::YellowBanner { inner } => inner.0.clone(), + Self::LimeBanner { inner } => inner.0.clone(), + Self::PinkBanner { inner } => inner.0.clone(), + Self::GrayBanner { inner } => inner.0.clone(), + Self::LightGrayBanner { inner } => inner.0.clone(), + Self::CyanBanner { inner } => inner.0.clone(), + Self::PurpleBanner { inner } => inner.0.clone(), + Self::BlueBanner { inner } => inner.0.clone(), + Self::BrownBanner { inner } => inner.0.clone(), + Self::GreenBanner { inner } => inner.0.clone(), + Self::RedBanner { inner } => inner.0.clone(), + Self::BlackBanner { inner } => inner.0.clone(), + Self::EndCrystal { inner } => inner.0.clone(), + Self::ChorusFruit { inner } => inner.0.clone(), + Self::PoppedChorusFruit { inner } => inner.0.clone(), + Self::TorchflowerSeeds { inner } => inner.0.clone(), + Self::PitcherPod { inner } => inner.0.clone(), + Self::Beetroot { inner } => inner.0.clone(), + Self::BeetrootSeeds { inner } => inner.0.clone(), + Self::BeetrootSoup { inner } => inner.0.clone(), + Self::DragonBreath { inner } => inner.0.clone(), + Self::SplashPotion { inner } => inner.0.clone(), + Self::SpectralArrow { inner } => inner.0.clone(), + Self::TippedArrow { inner } => inner.0.clone(), + Self::LingeringPotion { inner } => inner.0.clone(), + Self::Shield { inner } => inner.0.clone(), + Self::TotemOfUndying { inner } => inner.0.clone(), + Self::ShulkerShell { inner } => inner.0.clone(), + Self::IronNugget { inner } => inner.0.clone(), + Self::KnowledgeBook { inner } => inner.0.clone(), + Self::DebugStick { inner } => inner.0.clone(), + Self::MusicDisc13 { inner } => inner.0.clone(), + Self::MusicDiscCat { inner } => inner.0.clone(), + Self::MusicDiscBlocks { inner } => inner.0.clone(), + Self::MusicDiscChirp { inner } => inner.0.clone(), + Self::MusicDiscCreator { inner } => inner.0.clone(), + Self::MusicDiscCreatorMusicBox { inner } => inner.0.clone(), + Self::MusicDiscFar { inner } => inner.0.clone(), + Self::MusicDiscMall { inner } => inner.0.clone(), + Self::MusicDiscMellohi { inner } => inner.0.clone(), + Self::MusicDiscStal { inner } => inner.0.clone(), + Self::MusicDiscStrad { inner } => inner.0.clone(), + Self::MusicDiscWard { inner } => inner.0.clone(), + Self::MusicDisc11 { inner } => inner.0.clone(), + Self::MusicDiscWait { inner } => inner.0.clone(), + Self::MusicDiscOtherside { inner } => inner.0.clone(), + Self::MusicDiscRelic { inner } => inner.0.clone(), + Self::MusicDisc5 { inner } => inner.0.clone(), + Self::MusicDiscPigstep { inner } => inner.0.clone(), + Self::MusicDiscPrecipice { inner } => inner.0.clone(), + Self::DiscFragment5 { inner } => inner.0.clone(), + Self::Trident { inner } => inner.0.clone(), + Self::PhantomMembrane { inner } => inner.0.clone(), + Self::NautilusShell { inner } => inner.0.clone(), + Self::HeartOfTheSea { inner } => inner.0.clone(), + Self::Crossbow { inner } => inner.0.clone(), + Self::SuspiciousStew { inner } => inner.0.clone(), + Self::Loom { inner } => inner.0.clone(), + Self::FlowerBannerPattern { inner } => inner.0.clone(), + Self::CreeperBannerPattern { inner } => inner.0.clone(), + Self::SkullBannerPattern { inner } => inner.0.clone(), + Self::MojangBannerPattern { inner } => inner.0.clone(), + Self::GlobeBannerPattern { inner } => inner.0.clone(), + Self::PiglinBannerPattern { inner } => inner.0.clone(), + Self::FlowBannerPattern { inner } => inner.0.clone(), + Self::GusterBannerPattern { inner } => inner.0.clone(), + Self::GoatHorn { inner } => inner.0.clone(), + Self::Composter { inner } => inner.0.clone(), + Self::Barrel { inner } => inner.0.clone(), + Self::Smoker { inner } => inner.0.clone(), + Self::BlastFurnace { inner } => inner.0.clone(), + Self::CartographyTable { inner } => inner.0.clone(), + Self::FletchingTable { inner } => inner.0.clone(), + Self::Grindstone { inner } => inner.0.clone(), + Self::SmithingTable { inner } => inner.0.clone(), + Self::Stonecutter { inner } => inner.0.clone(), + Self::Bell { inner } => inner.0.clone(), + Self::Lantern { inner } => inner.0.clone(), + Self::SoulLantern { inner } => inner.0.clone(), + Self::SweetBerries { inner } => inner.0.clone(), + Self::GlowBerries { inner } => inner.0.clone(), + Self::Campfire { inner } => inner.0.clone(), + Self::SoulCampfire { inner } => inner.0.clone(), + Self::Shroomlight { inner } => inner.0.clone(), + Self::Honeycomb { inner } => inner.0.clone(), + Self::BeeNest { inner } => inner.0.clone(), + Self::Beehive { inner } => inner.0.clone(), + Self::HoneyBottle { inner } => inner.0.clone(), + Self::HoneycombBlock { inner } => inner.0.clone(), + Self::Lodestone { inner } => inner.0.clone(), + Self::CryingObsidian { inner } => inner.0.clone(), + Self::Blackstone { inner } => inner.0.clone(), + Self::BlackstoneSlab { inner } => inner.0.clone(), + Self::BlackstoneStairs { inner } => inner.0.clone(), + Self::GildedBlackstone { inner } => inner.0.clone(), + Self::PolishedBlackstone { inner } => inner.0.clone(), + Self::PolishedBlackstoneSlab { inner } => inner.0.clone(), + Self::PolishedBlackstoneStairs { inner } => inner.0.clone(), + Self::ChiseledPolishedBlackstone { inner } => inner.0.clone(), + Self::PolishedBlackstoneBricks { inner } => inner.0.clone(), + Self::PolishedBlackstoneBrickSlab { inner } => inner.0.clone(), + Self::PolishedBlackstoneBrickStairs { inner } => inner.0.clone(), + Self::CrackedPolishedBlackstoneBricks { inner } => inner.0.clone(), + Self::RespawnAnchor { inner } => inner.0.clone(), + Self::Candle { inner } => inner.0.clone(), + Self::WhiteCandle { inner } => inner.0.clone(), + Self::OrangeCandle { inner } => inner.0.clone(), + Self::MagentaCandle { inner } => inner.0.clone(), + Self::LightBlueCandle { inner } => inner.0.clone(), + Self::YellowCandle { inner } => inner.0.clone(), + Self::LimeCandle { inner } => inner.0.clone(), + Self::PinkCandle { inner } => inner.0.clone(), + Self::GrayCandle { inner } => inner.0.clone(), + Self::LightGrayCandle { inner } => inner.0.clone(), + Self::CyanCandle { inner } => inner.0.clone(), + Self::PurpleCandle { inner } => inner.0.clone(), + Self::BlueCandle { inner } => inner.0.clone(), + Self::BrownCandle { inner } => inner.0.clone(), + Self::GreenCandle { inner } => inner.0.clone(), + Self::RedCandle { inner } => inner.0.clone(), + Self::BlackCandle { inner } => inner.0.clone(), + Self::SmallAmethystBud { inner } => inner.0.clone(), + Self::MediumAmethystBud { inner } => inner.0.clone(), + Self::LargeAmethystBud { inner } => inner.0.clone(), + Self::AmethystCluster { inner } => inner.0.clone(), + Self::PointedDripstone { inner } => inner.0.clone(), + Self::OchreFroglight { inner } => inner.0.clone(), + Self::VerdantFroglight { inner } => inner.0.clone(), + Self::PearlescentFroglight { inner } => inner.0.clone(), + Self::Frogspawn { inner } => inner.0.clone(), + Self::EchoShard { inner } => inner.0.clone(), + Self::Brush { inner } => inner.0.clone(), + Self::NetheriteUpgradeSmithingTemplate { inner } => inner.0.clone(), + Self::SentryArmorTrimSmithingTemplate { inner } => inner.0.clone(), + Self::DuneArmorTrimSmithingTemplate { inner } => inner.0.clone(), + Self::CoastArmorTrimSmithingTemplate { inner } => inner.0.clone(), + Self::WildArmorTrimSmithingTemplate { inner } => inner.0.clone(), + Self::WardArmorTrimSmithingTemplate { inner } => inner.0.clone(), + Self::EyeArmorTrimSmithingTemplate { inner } => inner.0.clone(), + Self::VexArmorTrimSmithingTemplate { inner } => inner.0.clone(), + Self::TideArmorTrimSmithingTemplate { inner } => inner.0.clone(), + Self::SnoutArmorTrimSmithingTemplate { inner } => inner.0.clone(), + Self::RibArmorTrimSmithingTemplate { inner } => inner.0.clone(), + Self::SpireArmorTrimSmithingTemplate { inner } => inner.0.clone(), + Self::WayfinderArmorTrimSmithingTemplate { inner } => inner.0.clone(), + Self::ShaperArmorTrimSmithingTemplate { inner } => inner.0.clone(), + Self::SilenceArmorTrimSmithingTemplate { inner } => inner.0.clone(), + Self::RaiserArmorTrimSmithingTemplate { inner } => inner.0.clone(), + Self::HostArmorTrimSmithingTemplate { inner } => inner.0.clone(), + Self::FlowArmorTrimSmithingTemplate { inner } => inner.0.clone(), + Self::BoltArmorTrimSmithingTemplate { inner } => inner.0.clone(), + Self::AnglerPotterySherd { inner } => inner.0.clone(), + Self::ArcherPotterySherd { inner } => inner.0.clone(), + Self::ArmsUpPotterySherd { inner } => inner.0.clone(), + Self::BladePotterySherd { inner } => inner.0.clone(), + Self::BrewerPotterySherd { inner } => inner.0.clone(), + Self::BurnPotterySherd { inner } => inner.0.clone(), + Self::DangerPotterySherd { inner } => inner.0.clone(), + Self::ExplorerPotterySherd { inner } => inner.0.clone(), + Self::FlowPotterySherd { inner } => inner.0.clone(), + Self::FriendPotterySherd { inner } => inner.0.clone(), + Self::GusterPotterySherd { inner } => inner.0.clone(), + Self::HeartPotterySherd { inner } => inner.0.clone(), + Self::HeartbreakPotterySherd { inner } => inner.0.clone(), + Self::HowlPotterySherd { inner } => inner.0.clone(), + Self::MinerPotterySherd { inner } => inner.0.clone(), + Self::MournerPotterySherd { inner } => inner.0.clone(), + Self::PlentyPotterySherd { inner } => inner.0.clone(), + Self::PrizePotterySherd { inner } => inner.0.clone(), + Self::ScrapePotterySherd { inner } => inner.0.clone(), + Self::SheafPotterySherd { inner } => inner.0.clone(), + Self::ShelterPotterySherd { inner } => inner.0.clone(), + Self::SkullPotterySherd { inner } => inner.0.clone(), + Self::SnortPotterySherd { inner } => inner.0.clone(), + Self::CopperGrate { inner } => inner.0.clone(), + Self::ExposedCopperGrate { inner } => inner.0.clone(), + Self::WeatheredCopperGrate { inner } => inner.0.clone(), + Self::OxidizedCopperGrate { inner } => inner.0.clone(), + Self::WaxedCopperGrate { inner } => inner.0.clone(), + Self::WaxedExposedCopperGrate { inner } => inner.0.clone(), + Self::WaxedWeatheredCopperGrate { inner } => inner.0.clone(), + Self::WaxedOxidizedCopperGrate { inner } => inner.0.clone(), + Self::CopperBulb { inner } => inner.0.clone(), + Self::ExposedCopperBulb { inner } => inner.0.clone(), + Self::WeatheredCopperBulb { inner } => inner.0.clone(), + Self::OxidizedCopperBulb { inner } => inner.0.clone(), + Self::WaxedCopperBulb { inner } => inner.0.clone(), + Self::WaxedExposedCopperBulb { inner } => inner.0.clone(), + Self::WaxedWeatheredCopperBulb { inner } => inner.0.clone(), + Self::WaxedOxidizedCopperBulb { inner } => inner.0.clone(), + Self::TrialSpawner { inner } => inner.0.clone(), + Self::TrialKey { inner } => inner.0.clone(), + Self::OminousTrialKey { inner } => inner.0.clone(), + Self::Vault { inner } => inner.0.clone(), + Self::OminousBottle { inner } => inner.0.clone(), + Self::BreezeRod { inner } => inner.0.clone(), + Self::Water { inner } => inner.0.clone(), + Self::Lava { inner } => inner.0.clone(), + Self::TallSeagrass { inner } => inner.0.clone(), + Self::PistonHead { inner } => inner.0.clone(), + Self::MovingPiston { inner } => inner.0.clone(), + Self::WallTorch { inner } => inner.0.clone(), + Self::Fire { inner } => inner.0.clone(), + Self::SoulFire { inner } => inner.0.clone(), + Self::RedstoneWire { inner } => inner.0.clone(), + Self::OakWallSign { inner } => inner.0.clone(), + Self::SpruceWallSign { inner } => inner.0.clone(), + Self::BirchWallSign { inner } => inner.0.clone(), + Self::AcaciaWallSign { inner } => inner.0.clone(), + Self::CherryWallSign { inner } => inner.0.clone(), + Self::JungleWallSign { inner } => inner.0.clone(), + Self::DarkOakWallSign { inner } => inner.0.clone(), + Self::MangroveWallSign { inner } => inner.0.clone(), + Self::BambooWallSign { inner } => inner.0.clone(), + Self::OakWallHangingSign { inner } => inner.0.clone(), + Self::SpruceWallHangingSign { inner } => inner.0.clone(), + Self::BirchWallHangingSign { inner } => inner.0.clone(), + Self::AcaciaWallHangingSign { inner } => inner.0.clone(), + Self::CherryWallHangingSign { inner } => inner.0.clone(), + Self::JungleWallHangingSign { inner } => inner.0.clone(), + Self::DarkOakWallHangingSign { inner } => inner.0.clone(), + Self::MangroveWallHangingSign { inner } => inner.0.clone(), + Self::CrimsonWallHangingSign { inner } => inner.0.clone(), + Self::WarpedWallHangingSign { inner } => inner.0.clone(), + Self::BambooWallHangingSign { inner } => inner.0.clone(), + Self::RedstoneWallTorch { inner } => inner.0.clone(), + Self::SoulWallTorch { inner } => inner.0.clone(), + Self::NetherPortal { inner } => inner.0.clone(), + Self::AttachedPumpkinStem { inner } => inner.0.clone(), + Self::AttachedMelonStem { inner } => inner.0.clone(), + Self::PumpkinStem { inner } => inner.0.clone(), + Self::MelonStem { inner } => inner.0.clone(), + Self::WaterCauldron { inner } => inner.0.clone(), + Self::LavaCauldron { inner } => inner.0.clone(), + Self::PowderSnowCauldron { inner } => inner.0.clone(), + Self::EndPortal { inner } => inner.0.clone(), + Self::Cocoa { inner } => inner.0.clone(), + Self::Tripwire { inner } => inner.0.clone(), + Self::PottedTorchflower { inner } => inner.0.clone(), + Self::PottedOakSapling { inner } => inner.0.clone(), + Self::PottedSpruceSapling { inner } => inner.0.clone(), + Self::PottedBirchSapling { inner } => inner.0.clone(), + Self::PottedJungleSapling { inner } => inner.0.clone(), + Self::PottedAcaciaSapling { inner } => inner.0.clone(), + Self::PottedCherrySapling { inner } => inner.0.clone(), + Self::PottedDarkOakSapling { inner } => inner.0.clone(), + Self::PottedMangrovePropagule { inner } => inner.0.clone(), + Self::PottedFern { inner } => inner.0.clone(), + Self::PottedDandelion { inner } => inner.0.clone(), + Self::PottedPoppy { inner } => inner.0.clone(), + Self::PottedBlueOrchid { inner } => inner.0.clone(), + Self::PottedAllium { inner } => inner.0.clone(), + Self::PottedAzureBluet { inner } => inner.0.clone(), + Self::PottedRedTulip { inner } => inner.0.clone(), + Self::PottedOrangeTulip { inner } => inner.0.clone(), + Self::PottedWhiteTulip { inner } => inner.0.clone(), + Self::PottedPinkTulip { inner } => inner.0.clone(), + Self::PottedOxeyeDaisy { inner } => inner.0.clone(), + Self::PottedCornflower { inner } => inner.0.clone(), + Self::PottedLilyOfTheValley { inner } => inner.0.clone(), + Self::PottedWitherRose { inner } => inner.0.clone(), + Self::PottedRedMushroom { inner } => inner.0.clone(), + Self::PottedBrownMushroom { inner } => inner.0.clone(), + Self::PottedDeadBush { inner } => inner.0.clone(), + Self::PottedCactus { inner } => inner.0.clone(), + Self::Carrots { inner } => inner.0.clone(), + Self::Potatoes { inner } => inner.0.clone(), + Self::SkeletonWallSkull { inner } => inner.0.clone(), + Self::WitherSkeletonWallSkull { inner } => inner.0.clone(), + Self::ZombieWallHead { inner } => inner.0.clone(), + Self::PlayerWallHead { inner } => inner.0.clone(), + Self::CreeperWallHead { inner } => inner.0.clone(), + Self::DragonWallHead { inner } => inner.0.clone(), + Self::PiglinWallHead { inner } => inner.0.clone(), + Self::WhiteWallBanner { inner } => inner.0.clone(), + Self::OrangeWallBanner { inner } => inner.0.clone(), + Self::MagentaWallBanner { inner } => inner.0.clone(), + Self::LightBlueWallBanner { inner } => inner.0.clone(), + Self::YellowWallBanner { inner } => inner.0.clone(), + Self::LimeWallBanner { inner } => inner.0.clone(), + Self::PinkWallBanner { inner } => inner.0.clone(), + Self::GrayWallBanner { inner } => inner.0.clone(), + Self::LightGrayWallBanner { inner } => inner.0.clone(), + Self::CyanWallBanner { inner } => inner.0.clone(), + Self::PurpleWallBanner { inner } => inner.0.clone(), + Self::BlueWallBanner { inner } => inner.0.clone(), + Self::BrownWallBanner { inner } => inner.0.clone(), + Self::GreenWallBanner { inner } => inner.0.clone(), + Self::RedWallBanner { inner } => inner.0.clone(), + Self::BlackWallBanner { inner } => inner.0.clone(), + Self::TorchflowerCrop { inner } => inner.0.clone(), + Self::PitcherCrop { inner } => inner.0.clone(), + Self::Beetroots { inner } => inner.0.clone(), + Self::EndGateway { inner } => inner.0.clone(), + Self::FrostedIce { inner } => inner.0.clone(), + Self::KelpPlant { inner } => inner.0.clone(), + Self::DeadTubeCoralWallFan { inner } => inner.0.clone(), + Self::DeadBrainCoralWallFan { inner } => inner.0.clone(), + Self::DeadBubbleCoralWallFan { inner } => inner.0.clone(), + Self::DeadFireCoralWallFan { inner } => inner.0.clone(), + Self::DeadHornCoralWallFan { inner } => inner.0.clone(), + Self::TubeCoralWallFan { inner } => inner.0.clone(), + Self::BrainCoralWallFan { inner } => inner.0.clone(), + Self::BubbleCoralWallFan { inner } => inner.0.clone(), + Self::FireCoralWallFan { inner } => inner.0.clone(), + Self::HornCoralWallFan { inner } => inner.0.clone(), + Self::BambooSapling { inner } => inner.0.clone(), + Self::PottedBamboo { inner } => inner.0.clone(), + Self::VoidAir { inner } => inner.0.clone(), + Self::CaveAir { inner } => inner.0.clone(), + Self::BubbleColumn { inner } => inner.0.clone(), + Self::SweetBerryBush { inner } => inner.0.clone(), + Self::WeepingVinesPlant { inner } => inner.0.clone(), + Self::TwistingVinesPlant { inner } => inner.0.clone(), + Self::CrimsonWallSign { inner } => inner.0.clone(), + Self::WarpedWallSign { inner } => inner.0.clone(), + Self::PottedCrimsonFungus { inner } => inner.0.clone(), + Self::PottedWarpedFungus { inner } => inner.0.clone(), + Self::PottedCrimsonRoots { inner } => inner.0.clone(), + Self::PottedWarpedRoots { inner } => inner.0.clone(), + Self::CandleCake { inner } => inner.0.clone(), + Self::WhiteCandleCake { inner } => inner.0.clone(), + Self::OrangeCandleCake { inner } => inner.0.clone(), + Self::MagentaCandleCake { inner } => inner.0.clone(), + Self::LightBlueCandleCake { inner } => inner.0.clone(), + Self::YellowCandleCake { inner } => inner.0.clone(), + Self::LimeCandleCake { inner } => inner.0.clone(), + Self::PinkCandleCake { inner } => inner.0.clone(), + Self::GrayCandleCake { inner } => inner.0.clone(), + Self::LightGrayCandleCake { inner } => inner.0.clone(), + Self::CyanCandleCake { inner } => inner.0.clone(), + Self::PurpleCandleCake { inner } => inner.0.clone(), + Self::BlueCandleCake { inner } => inner.0.clone(), + Self::BrownCandleCake { inner } => inner.0.clone(), + Self::GreenCandleCake { inner } => inner.0.clone(), + Self::RedCandleCake { inner } => inner.0.clone(), + Self::BlackCandleCake { inner } => inner.0.clone(), + Self::PowderSnow { inner } => inner.0.clone(), + Self::CaveVines { inner } => inner.0.clone(), + Self::CaveVinesPlant { inner } => inner.0.clone(), + Self::BigDripleafStem { inner } => inner.0.clone(), + Self::PottedAzaleaBush { inner } => inner.0.clone(), + Self::PottedFloweringAzaleaBush { inner } => inner.0.clone(), + Self::LegacyAir { inner } => inner.0.clone(), + Self::LegacyStone { inner } => inner.0.clone(), + Self::LegacyGrass { inner } => inner.0.clone(), + Self::LegacyDirt { inner } => inner.0.clone(), + Self::LegacyCobblestone { inner } => inner.0.clone(), + Self::LegacyWood { inner } => inner.0.clone(), + Self::LegacySapling { inner } => inner.0.clone(), + Self::LegacyBedrock { inner } => inner.0.clone(), + Self::LegacyWater { inner } => inner.0.clone(), + Self::LegacyStationaryWater { inner } => inner.0.clone(), + Self::LegacyLava { inner } => inner.0.clone(), + Self::LegacyStationaryLava { inner } => inner.0.clone(), + Self::LegacySand { inner } => inner.0.clone(), + Self::LegacyGravel { inner } => inner.0.clone(), + Self::LegacyGoldOre { inner } => inner.0.clone(), + Self::LegacyIronOre { inner } => inner.0.clone(), + Self::LegacyCoalOre { inner } => inner.0.clone(), + Self::LegacyLog { inner } => inner.0.clone(), + Self::LegacyLeaves { inner } => inner.0.clone(), + Self::LegacySponge { inner } => inner.0.clone(), + Self::LegacyGlass { inner } => inner.0.clone(), + Self::LegacyLapisOre { inner } => inner.0.clone(), + Self::LegacyLapisBlock { inner } => inner.0.clone(), + Self::LegacyDispenser { inner } => inner.0.clone(), + Self::LegacySandstone { inner } => inner.0.clone(), + Self::LegacyNoteBlock { inner } => inner.0.clone(), + Self::LegacyBedBlock { inner } => inner.0.clone(), + Self::LegacyPoweredRail { inner } => inner.0.clone(), + Self::LegacyDetectorRail { inner } => inner.0.clone(), + Self::LegacyPistonStickyBase { inner } => inner.0.clone(), + Self::LegacyWeb { inner } => inner.0.clone(), + Self::LegacyLongGrass { inner } => inner.0.clone(), + Self::LegacyDeadBush { inner } => inner.0.clone(), + Self::LegacyPistonBase { inner } => inner.0.clone(), + Self::LegacyPistonExtension { inner } => inner.0.clone(), + Self::LegacyWool { inner } => inner.0.clone(), + Self::LegacyPistonMovingPiece { inner } => inner.0.clone(), + Self::LegacyYellowFlower { inner } => inner.0.clone(), + Self::LegacyRedRose { inner } => inner.0.clone(), + Self::LegacyBrownMushroom { inner } => inner.0.clone(), + Self::LegacyRedMushroom { inner } => inner.0.clone(), + Self::LegacyGoldBlock { inner } => inner.0.clone(), + Self::LegacyIronBlock { inner } => inner.0.clone(), + Self::LegacyDoubleStep { inner } => inner.0.clone(), + Self::LegacyStep { inner } => inner.0.clone(), + Self::LegacyBrick { inner } => inner.0.clone(), + Self::LegacyTnt { inner } => inner.0.clone(), + Self::LegacyBookshelf { inner } => inner.0.clone(), + Self::LegacyMossyCobblestone { inner } => inner.0.clone(), + Self::LegacyObsidian { inner } => inner.0.clone(), + Self::LegacyTorch { inner } => inner.0.clone(), + Self::LegacyFire { inner } => inner.0.clone(), + Self::LegacyMobSpawner { inner } => inner.0.clone(), + Self::LegacyWoodStairs { inner } => inner.0.clone(), + Self::LegacyChest { inner } => inner.0.clone(), + Self::LegacyRedstoneWire { inner } => inner.0.clone(), + Self::LegacyDiamondOre { inner } => inner.0.clone(), + Self::LegacyDiamondBlock { inner } => inner.0.clone(), + Self::LegacyWorkbench { inner } => inner.0.clone(), + Self::LegacyCrops { inner } => inner.0.clone(), + Self::LegacySoil { inner } => inner.0.clone(), + Self::LegacyFurnace { inner } => inner.0.clone(), + Self::LegacyBurningFurnace { inner } => inner.0.clone(), + Self::LegacySignPost { inner } => inner.0.clone(), + Self::LegacyWoodenDoor { inner } => inner.0.clone(), + Self::LegacyLadder { inner } => inner.0.clone(), + Self::LegacyRails { inner } => inner.0.clone(), + Self::LegacyCobblestoneStairs { inner } => inner.0.clone(), + Self::LegacyWallSign { inner } => inner.0.clone(), + Self::LegacyLever { inner } => inner.0.clone(), + Self::LegacyStonePlate { inner } => inner.0.clone(), + Self::LegacyIronDoorBlock { inner } => inner.0.clone(), + Self::LegacyWoodPlate { inner } => inner.0.clone(), + Self::LegacyRedstoneOre { inner } => inner.0.clone(), + Self::LegacyGlowingRedstoneOre { inner } => inner.0.clone(), + Self::LegacyRedstoneTorchOff { inner } => inner.0.clone(), + Self::LegacyRedstoneTorchOn { inner } => inner.0.clone(), + Self::LegacyStoneButton { inner } => inner.0.clone(), + Self::LegacySnow { inner } => inner.0.clone(), + Self::LegacyIce { inner } => inner.0.clone(), + Self::LegacySnowBlock { inner } => inner.0.clone(), + Self::LegacyCactus { inner } => inner.0.clone(), + Self::LegacyClay { inner } => inner.0.clone(), + Self::LegacySugarCaneBlock { inner } => inner.0.clone(), + Self::LegacyJukebox { inner } => inner.0.clone(), + Self::LegacyFence { inner } => inner.0.clone(), + Self::LegacyPumpkin { inner } => inner.0.clone(), + Self::LegacyNetherrack { inner } => inner.0.clone(), + Self::LegacySoulSand { inner } => inner.0.clone(), + Self::LegacyGlowstone { inner } => inner.0.clone(), + Self::LegacyPortal { inner } => inner.0.clone(), + Self::LegacyJackOLantern { inner } => inner.0.clone(), + Self::LegacyCakeBlock { inner } => inner.0.clone(), + Self::LegacyDiodeBlockOff { inner } => inner.0.clone(), + Self::LegacyDiodeBlockOn { inner } => inner.0.clone(), + Self::LegacyStainedGlass { inner } => inner.0.clone(), + Self::LegacyTrapDoor { inner } => inner.0.clone(), + Self::LegacyMonsterEggs { inner } => inner.0.clone(), + Self::LegacySmoothBrick { inner } => inner.0.clone(), + Self::LegacyHugeMushroom1 { inner } => inner.0.clone(), + Self::LegacyHugeMushroom2 { inner } => inner.0.clone(), + Self::LegacyIronFence { inner } => inner.0.clone(), + Self::LegacyThinGlass { inner } => inner.0.clone(), + Self::LegacyMelonBlock { inner } => inner.0.clone(), + Self::LegacyPumpkinStem { inner } => inner.0.clone(), + Self::LegacyMelonStem { inner } => inner.0.clone(), + Self::LegacyVine { inner } => inner.0.clone(), + Self::LegacyFenceGate { inner } => inner.0.clone(), + Self::LegacyBrickStairs { inner } => inner.0.clone(), + Self::LegacySmoothStairs { inner } => inner.0.clone(), + Self::LegacyMycel { inner } => inner.0.clone(), + Self::LegacyWaterLily { inner } => inner.0.clone(), + Self::LegacyNetherBrick { inner } => inner.0.clone(), + Self::LegacyNetherFence { inner } => inner.0.clone(), + Self::LegacyNetherBrickStairs { inner } => inner.0.clone(), + Self::LegacyNetherWarts { inner } => inner.0.clone(), + Self::LegacyEnchantmentTable { inner } => inner.0.clone(), + Self::LegacyBrewingStand { inner } => inner.0.clone(), + Self::LegacyCauldron { inner } => inner.0.clone(), + Self::LegacyEnderPortal { inner } => inner.0.clone(), + Self::LegacyEnderPortalFrame { inner } => inner.0.clone(), + Self::LegacyEnderStone { inner } => inner.0.clone(), + Self::LegacyDragonEgg { inner } => inner.0.clone(), + Self::LegacyRedstoneLampOff { inner } => inner.0.clone(), + Self::LegacyRedstoneLampOn { inner } => inner.0.clone(), + Self::LegacyWoodDoubleStep { inner } => inner.0.clone(), + Self::LegacyWoodStep { inner } => inner.0.clone(), + Self::LegacyCocoa { inner } => inner.0.clone(), + Self::LegacySandstoneStairs { inner } => inner.0.clone(), + Self::LegacyEmeraldOre { inner } => inner.0.clone(), + Self::LegacyEnderChest { inner } => inner.0.clone(), + Self::LegacyTripwireHook { inner } => inner.0.clone(), + Self::LegacyTripwire { inner } => inner.0.clone(), + Self::LegacyEmeraldBlock { inner } => inner.0.clone(), + Self::LegacySpruceWoodStairs { inner } => inner.0.clone(), + Self::LegacyBirchWoodStairs { inner } => inner.0.clone(), + Self::LegacyJungleWoodStairs { inner } => inner.0.clone(), + Self::LegacyCommand { inner } => inner.0.clone(), + Self::LegacyBeacon { inner } => inner.0.clone(), + Self::LegacyCobbleWall { inner } => inner.0.clone(), + Self::LegacyFlowerPot { inner } => inner.0.clone(), + Self::LegacyCarrot { inner } => inner.0.clone(), + Self::LegacyPotato { inner } => inner.0.clone(), + Self::LegacyWoodButton { inner } => inner.0.clone(), + Self::LegacySkull { inner } => inner.0.clone(), + Self::LegacyAnvil { inner } => inner.0.clone(), + Self::LegacyTrappedChest { inner } => inner.0.clone(), + Self::LegacyGoldPlate { inner } => inner.0.clone(), + Self::LegacyIronPlate { inner } => inner.0.clone(), + Self::LegacyRedstoneComparatorOff { inner } => inner.0.clone(), + Self::LegacyRedstoneComparatorOn { inner } => inner.0.clone(), + Self::LegacyDaylightDetector { inner } => inner.0.clone(), + Self::LegacyRedstoneBlock { inner } => inner.0.clone(), + Self::LegacyQuartzOre { inner } => inner.0.clone(), + Self::LegacyHopper { inner } => inner.0.clone(), + Self::LegacyQuartzBlock { inner } => inner.0.clone(), + Self::LegacyQuartzStairs { inner } => inner.0.clone(), + Self::LegacyActivatorRail { inner } => inner.0.clone(), + Self::LegacyDropper { inner } => inner.0.clone(), + Self::LegacyStainedClay { inner } => inner.0.clone(), + Self::LegacyStainedGlassPane { inner } => inner.0.clone(), + Self::LegacyLeaves2 { inner } => inner.0.clone(), + Self::LegacyLog2 { inner } => inner.0.clone(), + Self::LegacyAcaciaStairs { inner } => inner.0.clone(), + Self::LegacyDarkOakStairs { inner } => inner.0.clone(), + Self::LegacySlimeBlock { inner } => inner.0.clone(), + Self::LegacyBarrier { inner } => inner.0.clone(), + Self::LegacyIronTrapdoor { inner } => inner.0.clone(), + Self::LegacyPrismarine { inner } => inner.0.clone(), + Self::LegacySeaLantern { inner } => inner.0.clone(), + Self::LegacyHayBlock { inner } => inner.0.clone(), + Self::LegacyCarpet { inner } => inner.0.clone(), + Self::LegacyHardClay { inner } => inner.0.clone(), + Self::LegacyCoalBlock { inner } => inner.0.clone(), + Self::LegacyPackedIce { inner } => inner.0.clone(), + Self::LegacyDoublePlant { inner } => inner.0.clone(), + Self::LegacyStandingBanner { inner } => inner.0.clone(), + Self::LegacyWallBanner { inner } => inner.0.clone(), + Self::LegacyDaylightDetectorInverted { inner } => inner.0.clone(), + Self::LegacyRedSandstone { inner } => inner.0.clone(), + Self::LegacyRedSandstoneStairs { inner } => inner.0.clone(), + Self::LegacyDoubleStoneSlab2 { inner } => inner.0.clone(), + Self::LegacyStoneSlab2 { inner } => inner.0.clone(), + Self::LegacySpruceFenceGate { inner } => inner.0.clone(), + Self::LegacyBirchFenceGate { inner } => inner.0.clone(), + Self::LegacyJungleFenceGate { inner } => inner.0.clone(), + Self::LegacyDarkOakFenceGate { inner } => inner.0.clone(), + Self::LegacyAcaciaFenceGate { inner } => inner.0.clone(), + Self::LegacySpruceFence { inner } => inner.0.clone(), + Self::LegacyBirchFence { inner } => inner.0.clone(), + Self::LegacyJungleFence { inner } => inner.0.clone(), + Self::LegacyDarkOakFence { inner } => inner.0.clone(), + Self::LegacyAcaciaFence { inner } => inner.0.clone(), + Self::LegacySpruceDoor { inner } => inner.0.clone(), + Self::LegacyBirchDoor { inner } => inner.0.clone(), + Self::LegacyJungleDoor { inner } => inner.0.clone(), + Self::LegacyAcaciaDoor { inner } => inner.0.clone(), + Self::LegacyDarkOakDoor { inner } => inner.0.clone(), + Self::LegacyEndRod { inner } => inner.0.clone(), + Self::LegacyChorusPlant { inner } => inner.0.clone(), + Self::LegacyChorusFlower { inner } => inner.0.clone(), + Self::LegacyPurpurBlock { inner } => inner.0.clone(), + Self::LegacyPurpurPillar { inner } => inner.0.clone(), + Self::LegacyPurpurStairs { inner } => inner.0.clone(), + Self::LegacyPurpurDoubleSlab { inner } => inner.0.clone(), + Self::LegacyPurpurSlab { inner } => inner.0.clone(), + Self::LegacyEndBricks { inner } => inner.0.clone(), + Self::LegacyBeetrootBlock { inner } => inner.0.clone(), + Self::LegacyGrassPath { inner } => inner.0.clone(), + Self::LegacyEndGateway { inner } => inner.0.clone(), + Self::LegacyCommandRepeating { inner } => inner.0.clone(), + Self::LegacyCommandChain { inner } => inner.0.clone(), + Self::LegacyFrostedIce { inner } => inner.0.clone(), + Self::LegacyMagma { inner } => inner.0.clone(), + Self::LegacyNetherWartBlock { inner } => inner.0.clone(), + Self::LegacyRedNetherBrick { inner } => inner.0.clone(), + Self::LegacyBoneBlock { inner } => inner.0.clone(), + Self::LegacyStructureVoid { inner } => inner.0.clone(), + Self::LegacyObserver { inner } => inner.0.clone(), + Self::LegacyWhiteShulkerBox { inner } => inner.0.clone(), + Self::LegacyOrangeShulkerBox { inner } => inner.0.clone(), + Self::LegacyMagentaShulkerBox { inner } => inner.0.clone(), + Self::LegacyLightBlueShulkerBox { inner } => inner.0.clone(), + Self::LegacyYellowShulkerBox { inner } => inner.0.clone(), + Self::LegacyLimeShulkerBox { inner } => inner.0.clone(), + Self::LegacyPinkShulkerBox { inner } => inner.0.clone(), + Self::LegacyGrayShulkerBox { inner } => inner.0.clone(), + Self::LegacySilverShulkerBox { inner } => inner.0.clone(), + Self::LegacyCyanShulkerBox { inner } => inner.0.clone(), + Self::LegacyPurpleShulkerBox { inner } => inner.0.clone(), + Self::LegacyBlueShulkerBox { inner } => inner.0.clone(), + Self::LegacyBrownShulkerBox { inner } => inner.0.clone(), + Self::LegacyGreenShulkerBox { inner } => inner.0.clone(), + Self::LegacyRedShulkerBox { inner } => inner.0.clone(), + Self::LegacyBlackShulkerBox { inner } => inner.0.clone(), + Self::LegacyWhiteGlazedTerracotta { inner } => inner.0.clone(), + Self::LegacyOrangeGlazedTerracotta { inner } => inner.0.clone(), + Self::LegacyMagentaGlazedTerracotta { inner } => inner.0.clone(), + Self::LegacyLightBlueGlazedTerracotta { inner } => inner.0.clone(), + Self::LegacyYellowGlazedTerracotta { inner } => inner.0.clone(), + Self::LegacyLimeGlazedTerracotta { inner } => inner.0.clone(), + Self::LegacyPinkGlazedTerracotta { inner } => inner.0.clone(), + Self::LegacyGrayGlazedTerracotta { inner } => inner.0.clone(), + Self::LegacySilverGlazedTerracotta { inner } => inner.0.clone(), + Self::LegacyCyanGlazedTerracotta { inner } => inner.0.clone(), + Self::LegacyPurpleGlazedTerracotta { inner } => inner.0.clone(), + Self::LegacyBlueGlazedTerracotta { inner } => inner.0.clone(), + Self::LegacyBrownGlazedTerracotta { inner } => inner.0.clone(), + Self::LegacyGreenGlazedTerracotta { inner } => inner.0.clone(), + Self::LegacyRedGlazedTerracotta { inner } => inner.0.clone(), + Self::LegacyBlackGlazedTerracotta { inner } => inner.0.clone(), + Self::LegacyConcrete { inner } => inner.0.clone(), + Self::LegacyConcretePowder { inner } => inner.0.clone(), + Self::LegacyStructureBlock { inner } => inner.0.clone(), + Self::LegacyIronSpade { inner } => inner.0.clone(), + Self::LegacyIronPickaxe { inner } => inner.0.clone(), + Self::LegacyIronAxe { inner } => inner.0.clone(), + Self::LegacyFlintAndSteel { inner } => inner.0.clone(), + Self::LegacyApple { inner } => inner.0.clone(), + Self::LegacyBow { inner } => inner.0.clone(), + Self::LegacyArrow { inner } => inner.0.clone(), + Self::LegacyCoal { inner } => inner.0.clone(), + Self::LegacyDiamond { inner } => inner.0.clone(), + Self::LegacyIronIngot { inner } => inner.0.clone(), + Self::LegacyGoldIngot { inner } => inner.0.clone(), + Self::LegacyIronSword { inner } => inner.0.clone(), + Self::LegacyWoodSword { inner } => inner.0.clone(), + Self::LegacyWoodSpade { inner } => inner.0.clone(), + Self::LegacyWoodPickaxe { inner } => inner.0.clone(), + Self::LegacyWoodAxe { inner } => inner.0.clone(), + Self::LegacyStoneSword { inner } => inner.0.clone(), + Self::LegacyStoneSpade { inner } => inner.0.clone(), + Self::LegacyStonePickaxe { inner } => inner.0.clone(), + Self::LegacyStoneAxe { inner } => inner.0.clone(), + Self::LegacyDiamondSword { inner } => inner.0.clone(), + Self::LegacyDiamondSpade { inner } => inner.0.clone(), + Self::LegacyDiamondPickaxe { inner } => inner.0.clone(), + Self::LegacyDiamondAxe { inner } => inner.0.clone(), + Self::LegacyStick { inner } => inner.0.clone(), + Self::LegacyBowl { inner } => inner.0.clone(), + Self::LegacyMushroomSoup { inner } => inner.0.clone(), + Self::LegacyGoldSword { inner } => inner.0.clone(), + Self::LegacyGoldSpade { inner } => inner.0.clone(), + Self::LegacyGoldPickaxe { inner } => inner.0.clone(), + Self::LegacyGoldAxe { inner } => inner.0.clone(), + Self::LegacyString { inner } => inner.0.clone(), + Self::LegacyFeather { inner } => inner.0.clone(), + Self::LegacySulphur { inner } => inner.0.clone(), + Self::LegacyWoodHoe { inner } => inner.0.clone(), + Self::LegacyStoneHoe { inner } => inner.0.clone(), + Self::LegacyIronHoe { inner } => inner.0.clone(), + Self::LegacyDiamondHoe { inner } => inner.0.clone(), + Self::LegacyGoldHoe { inner } => inner.0.clone(), + Self::LegacySeeds { inner } => inner.0.clone(), + Self::LegacyWheat { inner } => inner.0.clone(), + Self::LegacyBread { inner } => inner.0.clone(), + Self::LegacyLeatherHelmet { inner } => inner.0.clone(), + Self::LegacyLeatherChestplate { inner } => inner.0.clone(), + Self::LegacyLeatherLeggings { inner } => inner.0.clone(), + Self::LegacyLeatherBoots { inner } => inner.0.clone(), + Self::LegacyChainmailHelmet { inner } => inner.0.clone(), + Self::LegacyChainmailChestplate { inner } => inner.0.clone(), + Self::LegacyChainmailLeggings { inner } => inner.0.clone(), + Self::LegacyChainmailBoots { inner } => inner.0.clone(), + Self::LegacyIronHelmet { inner } => inner.0.clone(), + Self::LegacyIronChestplate { inner } => inner.0.clone(), + Self::LegacyIronLeggings { inner } => inner.0.clone(), + Self::LegacyIronBoots { inner } => inner.0.clone(), + Self::LegacyDiamondHelmet { inner } => inner.0.clone(), + Self::LegacyDiamondChestplate { inner } => inner.0.clone(), + Self::LegacyDiamondLeggings { inner } => inner.0.clone(), + Self::LegacyDiamondBoots { inner } => inner.0.clone(), + Self::LegacyGoldHelmet { inner } => inner.0.clone(), + Self::LegacyGoldChestplate { inner } => inner.0.clone(), + Self::LegacyGoldLeggings { inner } => inner.0.clone(), + Self::LegacyGoldBoots { inner } => inner.0.clone(), + Self::LegacyFlint { inner } => inner.0.clone(), + Self::LegacyPork { inner } => inner.0.clone(), + Self::LegacyGrilledPork { inner } => inner.0.clone(), + Self::LegacyPainting { inner } => inner.0.clone(), + Self::LegacyGoldenApple { inner } => inner.0.clone(), + Self::LegacySign { inner } => inner.0.clone(), + Self::LegacyWoodDoor { inner } => inner.0.clone(), + Self::LegacyBucket { inner } => inner.0.clone(), + Self::LegacyWaterBucket { inner } => inner.0.clone(), + Self::LegacyLavaBucket { inner } => inner.0.clone(), + Self::LegacyMinecart { inner } => inner.0.clone(), + Self::LegacySaddle { inner } => inner.0.clone(), + Self::LegacyIronDoor { inner } => inner.0.clone(), + Self::LegacyRedstone { inner } => inner.0.clone(), + Self::LegacySnowBall { inner } => inner.0.clone(), + Self::LegacyBoat { inner } => inner.0.clone(), + Self::LegacyLeather { inner } => inner.0.clone(), + Self::LegacyMilkBucket { inner } => inner.0.clone(), + Self::LegacyClayBrick { inner } => inner.0.clone(), + Self::LegacyClayBall { inner } => inner.0.clone(), + Self::LegacySugarCane { inner } => inner.0.clone(), + Self::LegacyPaper { inner } => inner.0.clone(), + Self::LegacyBook { inner } => inner.0.clone(), + Self::LegacySlimeBall { inner } => inner.0.clone(), + Self::LegacyStorageMinecart { inner } => inner.0.clone(), + Self::LegacyPoweredMinecart { inner } => inner.0.clone(), + Self::LegacyEgg { inner } => inner.0.clone(), + Self::LegacyCompass { inner } => inner.0.clone(), + Self::LegacyFishingRod { inner } => inner.0.clone(), + Self::LegacyWatch { inner } => inner.0.clone(), + Self::LegacyGlowstoneDust { inner } => inner.0.clone(), + Self::LegacyRawFish { inner } => inner.0.clone(), + Self::LegacyCookedFish { inner } => inner.0.clone(), + Self::LegacyInkSack { inner } => inner.0.clone(), + Self::LegacyBone { inner } => inner.0.clone(), + Self::LegacySugar { inner } => inner.0.clone(), + Self::LegacyCake { inner } => inner.0.clone(), + Self::LegacyBed { inner } => inner.0.clone(), + Self::LegacyDiode { inner } => inner.0.clone(), + Self::LegacyCookie { inner } => inner.0.clone(), + Self::LegacyMap { inner } => inner.0.clone(), + Self::LegacyShears { inner } => inner.0.clone(), + Self::LegacyMelon { inner } => inner.0.clone(), + Self::LegacyPumpkinSeeds { inner } => inner.0.clone(), + Self::LegacyMelonSeeds { inner } => inner.0.clone(), + Self::LegacyRawBeef { inner } => inner.0.clone(), + Self::LegacyCookedBeef { inner } => inner.0.clone(), + Self::LegacyRawChicken { inner } => inner.0.clone(), + Self::LegacyCookedChicken { inner } => inner.0.clone(), + Self::LegacyRottenFlesh { inner } => inner.0.clone(), + Self::LegacyEnderPearl { inner } => inner.0.clone(), + Self::LegacyBlazeRod { inner } => inner.0.clone(), + Self::LegacyGhastTear { inner } => inner.0.clone(), + Self::LegacyGoldNugget { inner } => inner.0.clone(), + Self::LegacyNetherStalk { inner } => inner.0.clone(), + Self::LegacyPotion { inner } => inner.0.clone(), + Self::LegacyGlassBottle { inner } => inner.0.clone(), + Self::LegacySpiderEye { inner } => inner.0.clone(), + Self::LegacyFermentedSpiderEye { inner } => inner.0.clone(), + Self::LegacyBlazePowder { inner } => inner.0.clone(), + Self::LegacyMagmaCream { inner } => inner.0.clone(), + Self::LegacyBrewingStandItem { inner } => inner.0.clone(), + Self::LegacyCauldronItem { inner } => inner.0.clone(), + Self::LegacyEyeOfEnder { inner } => inner.0.clone(), + Self::LegacySpeckledMelon { inner } => inner.0.clone(), + Self::LegacyMonsterEgg { inner } => inner.0.clone(), + Self::LegacyExpBottle { inner } => inner.0.clone(), + Self::LegacyFireball { inner } => inner.0.clone(), + Self::LegacyBookAndQuill { inner } => inner.0.clone(), + Self::LegacyWrittenBook { inner } => inner.0.clone(), + Self::LegacyEmerald { inner } => inner.0.clone(), + Self::LegacyItemFrame { inner } => inner.0.clone(), + Self::LegacyFlowerPotItem { inner } => inner.0.clone(), + Self::LegacyCarrotItem { inner } => inner.0.clone(), + Self::LegacyPotatoItem { inner } => inner.0.clone(), + Self::LegacyBakedPotato { inner } => inner.0.clone(), + Self::LegacyPoisonousPotato { inner } => inner.0.clone(), + Self::LegacyEmptyMap { inner } => inner.0.clone(), + Self::LegacyGoldenCarrot { inner } => inner.0.clone(), + Self::LegacySkullItem { inner } => inner.0.clone(), + Self::LegacyCarrotStick { inner } => inner.0.clone(), + Self::LegacyNetherStar { inner } => inner.0.clone(), + Self::LegacyPumpkinPie { inner } => inner.0.clone(), + Self::LegacyFirework { inner } => inner.0.clone(), + Self::LegacyFireworkCharge { inner } => inner.0.clone(), + Self::LegacyEnchantedBook { inner } => inner.0.clone(), + Self::LegacyRedstoneComparator { inner } => inner.0.clone(), + Self::LegacyNetherBrickItem { inner } => inner.0.clone(), + Self::LegacyQuartz { inner } => inner.0.clone(), + Self::LegacyExplosiveMinecart { inner } => inner.0.clone(), + Self::LegacyHopperMinecart { inner } => inner.0.clone(), + Self::LegacyPrismarineShard { inner } => inner.0.clone(), + Self::LegacyPrismarineCrystals { inner } => inner.0.clone(), + Self::LegacyRabbit { inner } => inner.0.clone(), + Self::LegacyCookedRabbit { inner } => inner.0.clone(), + Self::LegacyRabbitStew { inner } => inner.0.clone(), + Self::LegacyRabbitFoot { inner } => inner.0.clone(), + Self::LegacyRabbitHide { inner } => inner.0.clone(), + Self::LegacyArmorStand { inner } => inner.0.clone(), + Self::LegacyIronBarding { inner } => inner.0.clone(), + Self::LegacyGoldBarding { inner } => inner.0.clone(), + Self::LegacyDiamondBarding { inner } => inner.0.clone(), + Self::LegacyLeash { inner } => inner.0.clone(), + Self::LegacyNameTag { inner } => inner.0.clone(), + Self::LegacyCommandMinecart { inner } => inner.0.clone(), + Self::LegacyMutton { inner } => inner.0.clone(), + Self::LegacyCookedMutton { inner } => inner.0.clone(), + Self::LegacyBanner { inner } => inner.0.clone(), + Self::LegacyEndCrystal { inner } => inner.0.clone(), + Self::LegacySpruceDoorItem { inner } => inner.0.clone(), + Self::LegacyBirchDoorItem { inner } => inner.0.clone(), + Self::LegacyJungleDoorItem { inner } => inner.0.clone(), + Self::LegacyAcaciaDoorItem { inner } => inner.0.clone(), + Self::LegacyDarkOakDoorItem { inner } => inner.0.clone(), + Self::LegacyChorusFruit { inner } => inner.0.clone(), + Self::LegacyChorusFruitPopped { inner } => inner.0.clone(), + Self::LegacyBeetroot { inner } => inner.0.clone(), + Self::LegacyBeetrootSeeds { inner } => inner.0.clone(), + Self::LegacyBeetrootSoup { inner } => inner.0.clone(), + Self::LegacyDragonsBreath { inner } => inner.0.clone(), + Self::LegacySplashPotion { inner } => inner.0.clone(), + Self::LegacySpectralArrow { inner } => inner.0.clone(), + Self::LegacyTippedArrow { inner } => inner.0.clone(), + Self::LegacyLingeringPotion { inner } => inner.0.clone(), + Self::LegacyShield { inner } => inner.0.clone(), + Self::LegacyElytra { inner } => inner.0.clone(), + Self::LegacyBoatSpruce { inner } => inner.0.clone(), + Self::LegacyBoatBirch { inner } => inner.0.clone(), + Self::LegacyBoatJungle { inner } => inner.0.clone(), + Self::LegacyBoatAcacia { inner } => inner.0.clone(), + Self::LegacyBoatDarkOak { inner } => inner.0.clone(), + Self::LegacyTotem { inner } => inner.0.clone(), + Self::LegacyShulkerShell { inner } => inner.0.clone(), + Self::LegacyIronNugget { inner } => inner.0.clone(), + Self::LegacyKnowledgeBook { inner } => inner.0.clone(), + Self::LegacyGoldRecord { inner } => inner.0.clone(), + Self::LegacyGreenRecord { inner } => inner.0.clone(), + Self::LegacyRecord3 { inner } => inner.0.clone(), + Self::LegacyRecord4 { inner } => inner.0.clone(), + Self::LegacyRecord5 { inner } => inner.0.clone(), + Self::LegacyRecord6 { inner } => inner.0.clone(), + Self::LegacyRecord7 { inner } => inner.0.clone(), + Self::LegacyRecord8 { inner } => inner.0.clone(), + Self::LegacyRecord9 { inner } => inner.0.clone(), + Self::LegacyRecord10 { inner } => inner.0.clone(), + Self::LegacyRecord11 { inner } => inner.0.clone(), + Self::LegacyRecord12 { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Air { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Stone { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Granite { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PolishedGranite { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Diorite { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PolishedDiorite { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Andesite { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PolishedAndesite { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Deepslate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CobbledDeepslate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PolishedDeepslate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Calcite { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Tuff { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::TuffSlab { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::TuffStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TuffWall { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ChiseledTuff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PolishedTuff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PolishedTuffSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PolishedTuffStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PolishedTuffWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TuffBricks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TuffBrickSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TuffBrickStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TuffBrickWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChiseledTuffBricks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DripstoneBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GrassBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Dirt { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CoarseDirt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Podzol { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::RootedDirt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Mud { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CrimsonNylium { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WarpedNylium { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Cobblestone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OakPlanks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SprucePlanks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BirchPlanks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::JunglePlanks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AcaciaPlanks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CherryPlanks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DarkOakPlanks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MangrovePlanks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BambooPlanks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrimsonPlanks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WarpedPlanks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BambooMosaic { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OakSapling { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SpruceSapling { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BirchSapling { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::JungleSapling { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AcaciaSapling { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CherrySapling { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DarkOakSapling { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MangrovePropagule { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Bedrock { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Sand { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SuspiciousSand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SuspiciousGravel { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedSand { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Gravel { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CoalOre { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DeepslateCoalOre { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronOre { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DeepslateIronOre { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CopperOre { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeepslateCopperOre { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GoldOre { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DeepslateGoldOre { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedstoneOre { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeepslateRedstoneOre { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EmeraldOre { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeepslateEmeraldOre { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LapisOre { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DeepslateLapisOre { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DiamondOre { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeepslateDiamondOre { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetherGoldOre { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetherQuartzOre { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AncientDebris { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CoalBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RawIronBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RawCopperBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RawGoldBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HeavyCore { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AmethystBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BuddingAmethyst { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CopperBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GoldBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DiamondBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetheriteBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ExposedCopper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WeatheredCopper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OxidizedCopper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChiseledCopper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ExposedChiseledCopper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WeatheredChiseledCopper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OxidizedChiseledCopper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CutCopper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ExposedCutCopper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WeatheredCutCopper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OxidizedCutCopper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CutCopperStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ExposedCutCopperStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WeatheredCutCopperStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OxidizedCutCopperStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CutCopperSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ExposedCutCopperSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WeatheredCutCopperSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OxidizedCutCopperSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedCopperBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedExposedCopper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedWeatheredCopper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedOxidizedCopper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedChiseledCopper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedExposedChiseledCopper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedWeatheredChiseledCopper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedOxidizedChiseledCopper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedCutCopper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedExposedCutCopper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedWeatheredCutCopper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedOxidizedCutCopper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedCutCopperStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedExposedCutCopperStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedWeatheredCutCopperStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedOxidizedCutCopperStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedCutCopperSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedExposedCutCopperSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedWeatheredCutCopperSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedOxidizedCutCopperSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OakLog { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SpruceLog { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BirchLog { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::JungleLog { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AcaciaLog { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CherryLog { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DarkOakLog { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MangroveLog { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MangroveRoots { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MuddyMangroveRoots { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrimsonStem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WarpedStem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BambooBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrippedOakLog { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrippedSpruceLog { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrippedBirchLog { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrippedJungleLog { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrippedAcaciaLog { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrippedCherryLog { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrippedDarkOakLog { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrippedMangroveLog { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrippedCrimsonStem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrippedWarpedStem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrippedOakWood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrippedSpruceWood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrippedBirchWood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrippedJungleWood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrippedAcaciaWood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrippedCherryWood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrippedDarkOakWood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrippedMangroveWood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrippedCrimsonHyphae { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrippedWarpedHyphae { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrippedBambooBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OakWood { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SpruceWood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BirchWood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::JungleWood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AcaciaWood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CherryWood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DarkOakWood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MangroveWood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrimsonHyphae { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WarpedHyphae { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OakLeaves { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SpruceLeaves { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BirchLeaves { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::JungleLeaves { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AcaciaLeaves { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CherryLeaves { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DarkOakLeaves { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MangroveLeaves { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AzaleaLeaves { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FloweringAzaleaLeaves { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Sponge { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::WetSponge { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Glass { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::TintedGlass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LapisBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Sandstone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChiseledSandstone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CutSandstone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Cobweb { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ShortGrass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Fern { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Azalea { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::FloweringAzalea { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeadBush { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Seagrass { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SeaPickle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WhiteWool { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OrangeWool { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MagentaWool { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightBlueWool { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::YellowWool { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LimeWool { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PinkWool { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::GrayWool { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::LightGrayWool { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CyanWool { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PurpleWool { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlueWool { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BrownWool { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GreenWool { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedWool { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BlackWool { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Dandelion { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Poppy { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BlueOrchid { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Allium { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::AzureBluet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedTulip { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::OrangeTulip { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WhiteTulip { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PinkTulip { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OxeyeDaisy { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Cornflower { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LilyOfTheValley { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WitherRose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Torchflower { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PitcherPlant { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SporeBlossom { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrownMushroom { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedMushroom { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrimsonFungus { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WarpedFungus { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrimsonRoots { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WarpedRoots { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetherSprouts { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WeepingVines { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TwistingVines { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SugarCane { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Kelp { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::MossCarpet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PinkPetals { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MossBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HangingRoots { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BigDripleaf { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SmallDripleaf { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Bamboo { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::OakSlab { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SpruceSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BirchSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::JungleSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AcaciaSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CherrySlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DarkOakSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MangroveSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BambooSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BambooMosaicSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrimsonSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WarpedSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StoneSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SmoothStoneSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SandstoneSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CutSandstoneSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PetrifiedOakSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CobblestoneSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrickSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StoneBrickSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MudBrickSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetherBrickSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::QuartzSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedSandstoneSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CutRedSandstoneSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PurpurSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PrismarineSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PrismarineBrickSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DarkPrismarineSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SmoothQuartz { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SmoothRedSandstone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SmoothSandstone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SmoothStone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Bricks { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Bookshelf { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChiseledBookshelf { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DecoratedPot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MossyCobblestone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Obsidian { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Torch { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::EndRod { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ChorusPlant { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChorusFlower { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PurpurBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PurpurPillar { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PurpurStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Spawner { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Chest { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CraftingTable { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Farmland { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Furnace { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Ladder { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CobblestoneStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Snow { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Ice { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SnowBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Cactus { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Clay { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Jukebox { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::OakFence { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SpruceFence { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BirchFence { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::JungleFence { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AcaciaFence { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CherryFence { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DarkOakFence { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MangroveFence { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BambooFence { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrimsonFence { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WarpedFence { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Pumpkin { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CarvedPumpkin { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::JackOLantern { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Netherrack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SoulSand { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SoulSoil { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Basalt { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PolishedBasalt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SmoothBasalt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SoulTorch { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Glowstone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::InfestedStone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::InfestedCobblestone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::InfestedStoneBricks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::InfestedMossyStoneBricks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::InfestedCrackedStoneBricks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::InfestedChiseledStoneBricks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::InfestedDeepslate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StoneBricks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MossyStoneBricks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrackedStoneBricks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChiseledStoneBricks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PackedMud { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MudBricks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeepslateBricks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrackedDeepslateBricks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeepslateTiles { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrackedDeepslateTiles { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChiseledDeepslate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ReinforcedDeepslate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrownMushroomBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedMushroomBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MushroomStem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronBars { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Chain { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::GlassPane { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Melon { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Vine { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::GlowLichen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrickStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StoneBrickStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MudBrickStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Mycelium { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::LilyPad { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::NetherBricks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrackedNetherBricks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChiseledNetherBricks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetherBrickFence { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetherBrickStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Sculk { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SculkVein { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SculkCatalyst { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SculkShrieker { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnchantingTable { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EndPortalFrame { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EndStone { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::EndStoneBricks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DragonEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SandstoneStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnderChest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EmeraldBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OakStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SpruceStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BirchStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::JungleStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AcaciaStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CherryStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DarkOakStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MangroveStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BambooStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BambooMosaicStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrimsonStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WarpedStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CommandBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Beacon { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CobblestoneWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MossyCobblestoneWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrickWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PrismarineWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedSandstoneWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MossyStoneBrickWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GraniteWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StoneBrickWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MudBrickWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetherBrickWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AndesiteWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedNetherBrickWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SandstoneWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EndStoneBrickWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DioriteWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlackstoneWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PolishedBlackstoneWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PolishedBlackstoneBrickWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CobbledDeepslateWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PolishedDeepslateWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeepslateBrickWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeepslateTileWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Anvil { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ChippedAnvil { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DamagedAnvil { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChiseledQuartzBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::QuartzBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::QuartzBricks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::QuartzPillar { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::QuartzStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WhiteTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OrangeTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MagentaTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightBlueTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::YellowTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LimeTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PinkTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GrayTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightGrayTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CyanTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PurpleTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlueTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrownTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GreenTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlackTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Barrier { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Light { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::HayBlock { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::WhiteCarpet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OrangeCarpet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MagentaCarpet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightBlueCarpet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::YellowCarpet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LimeCarpet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PinkCarpet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GrayCarpet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightGrayCarpet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CyanCarpet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PurpleCarpet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlueCarpet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrownCarpet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GreenCarpet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedCarpet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlackCarpet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Terracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PackedIce { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DirtPath { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Sunflower { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Lilac { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::RoseBush { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Peony { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::TallGrass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LargeFern { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WhiteStainedGlass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OrangeStainedGlass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MagentaStainedGlass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightBlueStainedGlass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::YellowStainedGlass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LimeStainedGlass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PinkStainedGlass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GrayStainedGlass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightGrayStainedGlass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CyanStainedGlass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PurpleStainedGlass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlueStainedGlass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrownStainedGlass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GreenStainedGlass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedStainedGlass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlackStainedGlass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WhiteStainedGlassPane { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OrangeStainedGlassPane { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MagentaStainedGlassPane { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightBlueStainedGlassPane { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::YellowStainedGlassPane { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LimeStainedGlassPane { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PinkStainedGlassPane { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GrayStainedGlassPane { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightGrayStainedGlassPane { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CyanStainedGlassPane { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PurpleStainedGlassPane { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlueStainedGlassPane { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrownStainedGlassPane { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GreenStainedGlassPane { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedStainedGlassPane { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlackStainedGlassPane { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Prismarine { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PrismarineBricks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DarkPrismarine { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PrismarineStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PrismarineBrickStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DarkPrismarineStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SeaLantern { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedSandstone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChiseledRedSandstone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CutRedSandstone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedSandstoneStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RepeatingCommandBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChainCommandBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MagmaBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetherWartBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WarpedWartBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedNetherBricks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BoneBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StructureVoid { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WhiteShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OrangeShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MagentaShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightBlueShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::YellowShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LimeShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PinkShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GrayShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightGrayShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CyanShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PurpleShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlueShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrownShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GreenShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlackShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WhiteGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OrangeGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MagentaGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightBlueGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::YellowGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LimeGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PinkGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GrayGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightGrayGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CyanGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PurpleGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlueGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrownGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GreenGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlackGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WhiteConcrete { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OrangeConcrete { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MagentaConcrete { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightBlueConcrete { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::YellowConcrete { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LimeConcrete { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PinkConcrete { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GrayConcrete { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightGrayConcrete { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CyanConcrete { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PurpleConcrete { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlueConcrete { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrownConcrete { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GreenConcrete { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedConcrete { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlackConcrete { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WhiteConcretePowder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OrangeConcretePowder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MagentaConcretePowder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightBlueConcretePowder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::YellowConcretePowder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LimeConcretePowder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PinkConcretePowder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GrayConcretePowder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightGrayConcretePowder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CyanConcretePowder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PurpleConcretePowder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlueConcretePowder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrownConcretePowder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GreenConcretePowder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedConcretePowder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlackConcretePowder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TurtleEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SnifferEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeadTubeCoralBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeadBrainCoralBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeadBubbleCoralBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeadFireCoralBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeadHornCoralBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TubeCoralBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrainCoralBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BubbleCoralBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FireCoralBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HornCoralBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TubeCoral { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrainCoral { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BubbleCoral { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FireCoral { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HornCoral { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeadBrainCoral { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeadBubbleCoral { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeadFireCoral { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeadHornCoral { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeadTubeCoral { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TubeCoralFan { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrainCoralFan { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BubbleCoralFan { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FireCoralFan { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HornCoralFan { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeadTubeCoralFan { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeadBrainCoralFan { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeadBubbleCoralFan { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeadFireCoralFan { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeadHornCoralFan { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlueIce { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Conduit { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PolishedGraniteStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SmoothRedSandstoneStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MossyStoneBrickStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PolishedDioriteStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MossyCobblestoneStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EndStoneBrickStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StoneStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SmoothSandstoneStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SmoothQuartzStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GraniteStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AndesiteStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedNetherBrickStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PolishedAndesiteStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DioriteStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CobbledDeepslateStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PolishedDeepslateStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeepslateBrickStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeepslateTileStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PolishedGraniteSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SmoothRedSandstoneSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MossyStoneBrickSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PolishedDioriteSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MossyCobblestoneSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EndStoneBrickSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SmoothSandstoneSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SmoothQuartzSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GraniteSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AndesiteSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedNetherBrickSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PolishedAndesiteSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DioriteSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CobbledDeepslateSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PolishedDeepslateSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeepslateBrickSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeepslateTileSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Scaffolding { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Redstone { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::RedstoneTorch { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedstoneBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Repeater { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Comparator { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Piston { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::StickyPiston { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SlimeBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HoneyBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Observer { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Hopper { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Dispenser { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Dropper { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Lectern { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Target { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Lever { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::LightningRod { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DaylightDetector { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SculkSensor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CalibratedSculkSensor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TripwireHook { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrappedChest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Tnt { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::RedstoneLamp { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NoteBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StoneButton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PolishedBlackstoneButton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OakButton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SpruceButton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BirchButton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::JungleButton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AcaciaButton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CherryButton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DarkOakButton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MangroveButton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BambooButton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrimsonButton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WarpedButton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StonePressurePlate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PolishedBlackstonePressurePlate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightWeightedPressurePlate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HeavyWeightedPressurePlate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OakPressurePlate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SprucePressurePlate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BirchPressurePlate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::JunglePressurePlate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AcaciaPressurePlate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CherryPressurePlate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DarkOakPressurePlate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MangrovePressurePlate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BambooPressurePlate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrimsonPressurePlate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WarpedPressurePlate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronDoor { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::OakDoor { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SpruceDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BirchDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::JungleDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AcaciaDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CherryDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DarkOakDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MangroveDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BambooDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrimsonDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WarpedDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CopperDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ExposedCopperDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WeatheredCopperDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OxidizedCopperDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedCopperDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedExposedCopperDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedWeatheredCopperDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedOxidizedCopperDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronTrapdoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OakTrapdoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SpruceTrapdoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BirchTrapdoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::JungleTrapdoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AcaciaTrapdoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CherryTrapdoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DarkOakTrapdoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MangroveTrapdoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BambooTrapdoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrimsonTrapdoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WarpedTrapdoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CopperTrapdoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ExposedCopperTrapdoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WeatheredCopperTrapdoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OxidizedCopperTrapdoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedCopperTrapdoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedExposedCopperTrapdoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedWeatheredCopperTrapdoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedOxidizedCopperTrapdoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OakFenceGate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SpruceFenceGate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BirchFenceGate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::JungleFenceGate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AcaciaFenceGate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CherryFenceGate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DarkOakFenceGate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MangroveFenceGate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BambooFenceGate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrimsonFenceGate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WarpedFenceGate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PoweredRail { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DetectorRail { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Rail { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ActivatorRail { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Saddle { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Minecart { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ChestMinecart { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FurnaceMinecart { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TntMinecart { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HopperMinecart { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CarrotOnAStick { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WarpedFungusOnAStick { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Elytra { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::OakBoat { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::OakChestBoat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SpruceBoat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SpruceChestBoat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BirchBoat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BirchChestBoat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::JungleBoat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::JungleChestBoat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AcaciaBoat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AcaciaChestBoat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CherryBoat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CherryChestBoat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DarkOakBoat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DarkOakChestBoat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MangroveBoat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MangroveChestBoat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BambooRaft { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BambooChestRaft { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StructureBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Jigsaw { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::TurtleHelmet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TurtleScute { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ArmadilloScute { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WolfArmor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FlintAndSteel { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Bowl { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Apple { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Bow { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Arrow { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Coal { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Charcoal { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Diamond { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Emerald { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::LapisLazuli { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Quartz { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::AmethystShard { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RawIron { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::IronIngot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RawCopper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CopperIngot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RawGold { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::GoldIngot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetheriteIngot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetheriteScrap { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WoodenSword { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WoodenShovel { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WoodenPickaxe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WoodenAxe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WoodenHoe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StoneSword { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StoneShovel { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StonePickaxe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StoneAxe { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::StoneHoe { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::GoldenSword { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GoldenShovel { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GoldenPickaxe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GoldenAxe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GoldenHoe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronSword { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronShovel { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronPickaxe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronAxe { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::IronHoe { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DiamondSword { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DiamondShovel { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DiamondPickaxe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DiamondAxe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DiamondHoe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetheriteSword { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetheriteShovel { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetheritePickaxe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetheriteAxe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetheriteHoe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Stick { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::MushroomStew { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::String { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Feather { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Gunpowder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WheatSeeds { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Wheat { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Bread { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::LeatherHelmet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LeatherChestplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LeatherLeggings { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LeatherBoots { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChainmailHelmet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChainmailChestplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChainmailLeggings { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChainmailBoots { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronHelmet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronChestplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronLeggings { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronBoots { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DiamondHelmet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DiamondChestplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DiamondLeggings { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DiamondBoots { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GoldenHelmet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GoldenChestplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GoldenLeggings { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GoldenBoots { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetheriteHelmet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetheriteChestplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetheriteLeggings { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetheriteBoots { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Flint { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Porkchop { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CookedPorkchop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Painting { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::GoldenApple { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnchantedGoldenApple { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OakSign { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SpruceSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BirchSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::JungleSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AcaciaSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CherrySign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DarkOakSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MangroveSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BambooSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrimsonSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WarpedSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OakHangingSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SpruceHangingSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BirchHangingSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::JungleHangingSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AcaciaHangingSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CherryHangingSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DarkOakHangingSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MangroveHangingSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BambooHangingSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrimsonHangingSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WarpedHangingSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Bucket { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::WaterBucket { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LavaBucket { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PowderSnowBucket { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Snowball { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Leather { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::MilkBucket { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PufferfishBucket { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SalmonBucket { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CodBucket { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TropicalFishBucket { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AxolotlBucket { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TadpoleBucket { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Brick { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ClayBall { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DriedKelpBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Paper { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Book { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SlimeBall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Egg { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Compass { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::RecoveryCompass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Bundle { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::FishingRod { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Clock { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Spyglass { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::GlowstoneDust { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Cod { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Salmon { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::TropicalFish { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Pufferfish { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CookedCod { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CookedSalmon { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::InkSac { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::GlowInkSac { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CocoaBeans { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WhiteDye { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::OrangeDye { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MagentaDye { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightBlueDye { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::YellowDye { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LimeDye { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PinkDye { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::GrayDye { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::LightGrayDye { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CyanDye { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PurpleDye { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlueDye { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BrownDye { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::GreenDye { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::RedDye { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BlackDye { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BoneMeal { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Bone { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Sugar { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Cake { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::WhiteBed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::OrangeBed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MagentaBed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightBlueBed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::YellowBed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LimeBed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PinkBed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::GrayBed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::LightGrayBed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CyanBed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PurpleBed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlueBed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BrownBed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::GreenBed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::RedBed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BlackBed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Cookie { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Crafter { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::FilledMap { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Shears { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::MelonSlice { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DriedKelp { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PumpkinSeeds { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MelonSeeds { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Beef { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CookedBeef { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Chicken { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CookedChicken { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RottenFlesh { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnderPearl { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlazeRod { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::GhastTear { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GoldNugget { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetherWart { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Potion { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::GlassBottle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SpiderEye { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FermentedSpiderEye { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlazePowder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MagmaCream { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrewingStand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Cauldron { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::EnderEye { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::GlisteringMelonSlice { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ArmadilloSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AllaySpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AxolotlSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BatSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BeeSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlazeSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BoggedSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BreezeSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CatSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CamelSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CaveSpiderSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChickenSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CodSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CowSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CreeperSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DolphinSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DonkeySpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DrownedSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ElderGuardianSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnderDragonSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EndermanSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EndermiteSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EvokerSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FoxSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FrogSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GhastSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GlowSquidSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GoatSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GuardianSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HoglinSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HorseSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HuskSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronGolemSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LlamaSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MagmaCubeSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MooshroomSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MuleSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OcelotSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PandaSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ParrotSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PhantomSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PigSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PiglinSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PiglinBruteSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PillagerSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PolarBearSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PufferfishSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RabbitSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RavagerSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SalmonSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SheepSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ShulkerSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SilverfishSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SkeletonSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SkeletonHorseSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SlimeSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SnifferSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SnowGolemSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SpiderSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SquidSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StraySpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StriderSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TadpoleSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TraderLlamaSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TropicalFishSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TurtleSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VexSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VillagerSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VindicatorSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WanderingTraderSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WardenSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WitchSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WitherSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WitherSkeletonSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WolfSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ZoglinSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ZombieSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ZombieHorseSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ZombieVillagerSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ZombifiedPiglinSpawnEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ExperienceBottle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FireCharge { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WindCharge { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WritableBook { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WrittenBook { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Mace { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ItemFrame { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GlowItemFrame { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FlowerPot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Carrot { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Potato { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BakedPotato { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PoisonousPotato { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Map { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::GoldenCarrot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SkeletonSkull { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WitherSkeletonSkull { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PlayerHead { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ZombieHead { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CreeperHead { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DragonHead { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PiglinHead { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetherStar { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PumpkinPie { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FireworkRocket { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FireworkStar { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnchantedBook { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetherBrick { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PrismarineShard { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PrismarineCrystals { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Rabbit { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CookedRabbit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RabbitStew { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RabbitFoot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RabbitHide { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ArmorStand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronHorseArmor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GoldenHorseArmor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DiamondHorseArmor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LeatherHorseArmor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Lead { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::NameTag { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CommandBlockMinecart { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Mutton { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CookedMutton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WhiteBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OrangeBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MagentaBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightBlueBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::YellowBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LimeBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PinkBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GrayBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightGrayBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CyanBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PurpleBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlueBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrownBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GreenBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlackBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EndCrystal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChorusFruit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PoppedChorusFruit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TorchflowerSeeds { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PitcherPod { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Beetroot { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BeetrootSeeds { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BeetrootSoup { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DragonBreath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SplashPotion { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SpectralArrow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TippedArrow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LingeringPotion { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Shield { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::TotemOfUndying { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ShulkerShell { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronNugget { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::KnowledgeBook { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DebugStick { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDisc13 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscCat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscBlocks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscChirp { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscCreator { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscCreatorMusicBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscFar { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscMall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscMellohi { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscStal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscStrad { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscWard { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDisc11 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscWait { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscOtherside { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscRelic { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDisc5 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscPigstep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MusicDiscPrecipice { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DiscFragment5 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Trident { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PhantomMembrane { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NautilusShell { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HeartOfTheSea { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Crossbow { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SuspiciousStew { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Loom { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::FlowerBannerPattern { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CreeperBannerPattern { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SkullBannerPattern { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MojangBannerPattern { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GlobeBannerPattern { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PiglinBannerPattern { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FlowBannerPattern { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GusterBannerPattern { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GoatHorn { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Composter { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Barrel { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Smoker { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BlastFurnace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CartographyTable { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FletchingTable { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Grindstone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SmithingTable { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Stonecutter { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Bell { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Lantern { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SoulLantern { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SweetBerries { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GlowBerries { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Campfire { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SoulCampfire { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Shroomlight { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Honeycomb { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BeeNest { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Beehive { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::HoneyBottle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HoneycombBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Lodestone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CryingObsidian { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Blackstone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlackstoneSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlackstoneStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GildedBlackstone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PolishedBlackstone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PolishedBlackstoneSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PolishedBlackstoneStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChiseledPolishedBlackstone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PolishedBlackstoneBricks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PolishedBlackstoneBrickSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PolishedBlackstoneBrickStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrackedPolishedBlackstoneBricks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RespawnAnchor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Candle { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::WhiteCandle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OrangeCandle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MagentaCandle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightBlueCandle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::YellowCandle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LimeCandle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PinkCandle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GrayCandle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightGrayCandle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CyanCandle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PurpleCandle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlueCandle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrownCandle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GreenCandle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedCandle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlackCandle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SmallAmethystBud { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MediumAmethystBud { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LargeAmethystBud { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AmethystCluster { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PointedDripstone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OchreFroglight { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VerdantFroglight { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PearlescentFroglight { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Frogspawn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EchoShard { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Brush { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::NetheriteUpgradeSmithingTemplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SentryArmorTrimSmithingTemplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DuneArmorTrimSmithingTemplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CoastArmorTrimSmithingTemplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WildArmorTrimSmithingTemplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WardArmorTrimSmithingTemplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EyeArmorTrimSmithingTemplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VexArmorTrimSmithingTemplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TideArmorTrimSmithingTemplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SnoutArmorTrimSmithingTemplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RibArmorTrimSmithingTemplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SpireArmorTrimSmithingTemplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WayfinderArmorTrimSmithingTemplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ShaperArmorTrimSmithingTemplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SilenceArmorTrimSmithingTemplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RaiserArmorTrimSmithingTemplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HostArmorTrimSmithingTemplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FlowArmorTrimSmithingTemplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BoltArmorTrimSmithingTemplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AnglerPotterySherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ArcherPotterySherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ArmsUpPotterySherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BladePotterySherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrewerPotterySherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BurnPotterySherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DangerPotterySherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ExplorerPotterySherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FlowPotterySherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FriendPotterySherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GusterPotterySherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HeartPotterySherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HeartbreakPotterySherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HowlPotterySherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MinerPotterySherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MournerPotterySherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PlentyPotterySherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PrizePotterySherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ScrapePotterySherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SheafPotterySherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ShelterPotterySherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SkullPotterySherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SnortPotterySherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CopperGrate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ExposedCopperGrate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WeatheredCopperGrate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OxidizedCopperGrate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedCopperGrate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedExposedCopperGrate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedWeatheredCopperGrate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedOxidizedCopperGrate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CopperBulb { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ExposedCopperBulb { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WeatheredCopperBulb { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OxidizedCopperBulb { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedCopperBulb { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedExposedCopperBulb { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedWeatheredCopperBulb { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaxedOxidizedCopperBulb { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrialSpawner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrialKey { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::OminousTrialKey { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Vault { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::OminousBottle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BreezeRod { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Water { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Lava { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::TallSeagrass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PistonHead { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MovingPiston { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WallTorch { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Fire { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SoulFire { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::RedstoneWire { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OakWallSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SpruceWallSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BirchWallSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AcaciaWallSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CherryWallSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::JungleWallSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DarkOakWallSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MangroveWallSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BambooWallSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OakWallHangingSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SpruceWallHangingSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BirchWallHangingSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AcaciaWallHangingSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CherryWallHangingSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::JungleWallHangingSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DarkOakWallHangingSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MangroveWallHangingSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrimsonWallHangingSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WarpedWallHangingSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BambooWallHangingSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedstoneWallTorch { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SoulWallTorch { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetherPortal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AttachedPumpkinStem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AttachedMelonStem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PumpkinStem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MelonStem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaterCauldron { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LavaCauldron { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PowderSnowCauldron { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EndPortal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Cocoa { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Tripwire { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PottedTorchflower { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedOakSapling { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedSpruceSapling { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedBirchSapling { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedJungleSapling { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedAcaciaSapling { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedCherrySapling { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedDarkOakSapling { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedMangrovePropagule { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedFern { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedDandelion { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedPoppy { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedBlueOrchid { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedAllium { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedAzureBluet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedRedTulip { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedOrangeTulip { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedWhiteTulip { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedPinkTulip { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedOxeyeDaisy { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedCornflower { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedLilyOfTheValley { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedWitherRose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedRedMushroom { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedBrownMushroom { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedDeadBush { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedCactus { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Carrots { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Potatoes { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SkeletonWallSkull { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WitherSkeletonWallSkull { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ZombieWallHead { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PlayerWallHead { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CreeperWallHead { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DragonWallHead { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PiglinWallHead { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WhiteWallBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OrangeWallBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MagentaWallBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightBlueWallBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::YellowWallBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LimeWallBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PinkWallBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GrayWallBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightGrayWallBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CyanWallBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PurpleWallBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlueWallBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrownWallBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GreenWallBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedWallBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlackWallBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TorchflowerCrop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PitcherCrop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Beetroots { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EndGateway { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FrostedIce { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::KelpPlant { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeadTubeCoralWallFan { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeadBrainCoralWallFan { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeadBubbleCoralWallFan { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeadFireCoralWallFan { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeadHornCoralWallFan { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TubeCoralWallFan { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrainCoralWallFan { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BubbleCoralWallFan { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FireCoralWallFan { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HornCoralWallFan { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BambooSapling { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedBamboo { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VoidAir { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CaveAir { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BubbleColumn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SweetBerryBush { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WeepingVinesPlant { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TwistingVinesPlant { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrimsonWallSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WarpedWallSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedCrimsonFungus { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedWarpedFungus { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedCrimsonRoots { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedWarpedRoots { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CandleCake { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WhiteCandleCake { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OrangeCandleCake { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MagentaCandleCake { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightBlueCandleCake { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::YellowCandleCake { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LimeCandleCake { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PinkCandleCake { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GrayCandleCake { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LightGrayCandleCake { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CyanCandleCake { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PurpleCandleCake { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlueCandleCake { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrownCandleCake { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GreenCandleCake { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedCandleCake { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlackCandleCake { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PowderSnow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CaveVines { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CaveVinesPlant { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BigDripleafStem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedAzaleaBush { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PottedFloweringAzaleaBush { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyAir { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyStone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGrass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDirt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCobblestone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySapling { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBedrock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyStationaryWater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyLava { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyStationaryLava { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGravel { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGoldOre { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyIronOre { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCoalOre { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyLog { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyLeaves { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySponge { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGlass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyLapisOre { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyLapisBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDispenser { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySandstone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyNoteBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBedBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPoweredRail { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDetectorRail { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPistonStickyBase { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWeb { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyLongGrass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDeadBush { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPistonBase { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPistonExtension { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWool { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPistonMovingPiece { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyYellowFlower { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRedRose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBrownMushroom { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRedMushroom { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGoldBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyIronBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDoubleStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBrick { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyTnt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBookshelf { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyMossyCobblestone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyObsidian { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyTorch { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyFire { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyMobSpawner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWoodStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyChest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRedstoneWire { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDiamondOre { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDiamondBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWorkbench { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCrops { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySoil { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyFurnace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBurningFurnace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySignPost { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWoodenDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyLadder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRails { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCobblestoneStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWallSign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyLever { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyStonePlate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyIronDoorBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWoodPlate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRedstoneOre { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGlowingRedstoneOre { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRedstoneTorchOff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRedstoneTorchOn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyStoneButton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySnow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyIce { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySnowBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCactus { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyClay { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySugarCaneBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyJukebox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyFence { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPumpkin { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyNetherrack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySoulSand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGlowstone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPortal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyJackOLantern { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCakeBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDiodeBlockOff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDiodeBlockOn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyStainedGlass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyTrapDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyMonsterEggs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySmoothBrick { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyHugeMushroom1 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyHugeMushroom2 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyIronFence { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyThinGlass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyMelonBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPumpkinStem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyMelonStem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyVine { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyFenceGate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBrickStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySmoothStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyMycel { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWaterLily { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyNetherBrick { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyNetherFence { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyNetherBrickStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyNetherWarts { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyEnchantmentTable { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBrewingStand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCauldron { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyEnderPortal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyEnderPortalFrame { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyEnderStone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDragonEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRedstoneLampOff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRedstoneLampOn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWoodDoubleStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWoodStep { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCocoa { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySandstoneStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyEmeraldOre { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyEnderChest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyTripwireHook { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyTripwire { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyEmeraldBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySpruceWoodStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBirchWoodStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyJungleWoodStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCommand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBeacon { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCobbleWall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyFlowerPot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCarrot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPotato { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWoodButton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySkull { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyAnvil { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyTrappedChest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGoldPlate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyIronPlate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRedstoneComparatorOff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRedstoneComparatorOn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDaylightDetector { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRedstoneBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyQuartzOre { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyHopper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyQuartzBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyQuartzStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyActivatorRail { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDropper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyStainedClay { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyStainedGlassPane { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyLeaves2 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyLog2 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyAcaciaStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDarkOakStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySlimeBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBarrier { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyIronTrapdoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPrismarine { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySeaLantern { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyHayBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCarpet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyHardClay { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCoalBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPackedIce { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDoublePlant { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyStandingBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWallBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDaylightDetectorInverted { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRedSandstone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRedSandstoneStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDoubleStoneSlab2 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyStoneSlab2 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySpruceFenceGate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBirchFenceGate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyJungleFenceGate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDarkOakFenceGate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyAcaciaFenceGate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySpruceFence { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBirchFence { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyJungleFence { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDarkOakFence { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyAcaciaFence { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySpruceDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBirchDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyJungleDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyAcaciaDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDarkOakDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyEndRod { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyChorusPlant { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyChorusFlower { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPurpurBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPurpurPillar { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPurpurStairs { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPurpurDoubleSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPurpurSlab { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyEndBricks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBeetrootBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGrassPath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyEndGateway { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCommandRepeating { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCommandChain { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyFrostedIce { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyMagma { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyNetherWartBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRedNetherBrick { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBoneBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyStructureVoid { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyObserver { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWhiteShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyOrangeShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyMagentaShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyLightBlueShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyYellowShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyLimeShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPinkShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGrayShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySilverShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCyanShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPurpleShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBlueShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBrownShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGreenShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRedShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBlackShulkerBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWhiteGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyOrangeGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyMagentaGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyLightBlueGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyYellowGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyLimeGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPinkGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGrayGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySilverGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCyanGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPurpleGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBlueGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBrownGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGreenGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRedGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBlackGlazedTerracotta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyConcrete { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyConcretePowder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyStructureBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyIronSpade { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyIronPickaxe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyIronAxe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyFlintAndSteel { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyApple { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyArrow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCoal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDiamond { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyIronIngot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGoldIngot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyIronSword { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWoodSword { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWoodSpade { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWoodPickaxe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWoodAxe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyStoneSword { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyStoneSpade { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyStonePickaxe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyStoneAxe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDiamondSword { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDiamondSpade { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDiamondPickaxe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDiamondAxe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyStick { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBowl { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyMushroomSoup { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGoldSword { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGoldSpade { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGoldPickaxe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGoldAxe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyString { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyFeather { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySulphur { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWoodHoe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyStoneHoe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyIronHoe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDiamondHoe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGoldHoe { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySeeds { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWheat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBread { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyLeatherHelmet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyLeatherChestplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyLeatherLeggings { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyLeatherBoots { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyChainmailHelmet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyChainmailChestplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyChainmailLeggings { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyChainmailBoots { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyIronHelmet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyIronChestplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyIronLeggings { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyIronBoots { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDiamondHelmet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDiamondChestplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDiamondLeggings { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDiamondBoots { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGoldHelmet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGoldChestplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGoldLeggings { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGoldBoots { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyFlint { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPork { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGrilledPork { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPainting { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGoldenApple { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySign { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWoodDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBucket { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWaterBucket { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyLavaBucket { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyMinecart { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySaddle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyIronDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRedstone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySnowBall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBoat { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyLeather { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyMilkBucket { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyClayBrick { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyClayBall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySugarCane { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPaper { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBook { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySlimeBall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyStorageMinecart { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPoweredMinecart { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCompass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyFishingRod { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWatch { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGlowstoneDust { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRawFish { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCookedFish { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyInkSack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySugar { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCake { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDiode { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCookie { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyMap { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyShears { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyMelon { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPumpkinSeeds { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyMelonSeeds { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRawBeef { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCookedBeef { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRawChicken { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCookedChicken { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRottenFlesh { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyEnderPearl { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBlazeRod { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGhastTear { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGoldNugget { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyNetherStalk { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPotion { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGlassBottle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySpiderEye { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyFermentedSpiderEye { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBlazePowder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyMagmaCream { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBrewingStandItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCauldronItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyEyeOfEnder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySpeckledMelon { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyMonsterEgg { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyExpBottle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyFireball { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBookAndQuill { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyWrittenBook { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyEmerald { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyItemFrame { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyFlowerPotItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCarrotItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPotatoItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBakedPotato { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPoisonousPotato { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyEmptyMap { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGoldenCarrot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySkullItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCarrotStick { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyNetherStar { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPumpkinPie { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyFirework { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyFireworkCharge { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyEnchantedBook { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRedstoneComparator { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyNetherBrickItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyQuartz { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyExplosiveMinecart { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyHopperMinecart { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPrismarineShard { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyPrismarineCrystals { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRabbit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCookedRabbit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRabbitStew { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRabbitFoot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRabbitHide { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyArmorStand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyIronBarding { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGoldBarding { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDiamondBarding { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyLeash { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyNameTag { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCommandMinecart { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyMutton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyCookedMutton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBanner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyEndCrystal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySpruceDoorItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBirchDoorItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyJungleDoorItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyAcaciaDoorItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDarkOakDoorItem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyChorusFruit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyChorusFruitPopped { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBeetroot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBeetrootSeeds { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBeetrootSoup { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyDragonsBreath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySplashPotion { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacySpectralArrow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyTippedArrow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyLingeringPotion { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyShield { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyElytra { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBoatSpruce { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBoatBirch { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBoatJungle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBoatAcacia { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyBoatDarkOak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyTotem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyShulkerShell { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyIronNugget { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyKnowledgeBook { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGoldRecord { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyGreenRecord { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRecord3 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRecord4 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRecord5 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRecord6 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRecord7 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRecord8 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRecord9 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRecord10 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRecord11 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LegacyRecord12 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for Material<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Material from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Material")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Material object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "AIR" => Ok(Material::Air { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE" => Ok(Material::Stone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRANITE" => Ok(Material::Granite { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_GRANITE" => Ok(Material::PolishedGranite { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIORITE" => Ok(Material::Diorite { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_DIORITE" => Ok(Material::PolishedDiorite { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ANDESITE" => Ok(Material::Andesite { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_ANDESITE" => Ok(Material::PolishedAndesite { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE" => Ok(Material::Deepslate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COBBLED_DEEPSLATE" => Ok(Material::CobbledDeepslate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_DEEPSLATE" => Ok(Material::PolishedDeepslate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CALCITE" => Ok(Material::Calcite { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TUFF" => Ok(Material::Tuff { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TUFF_SLAB" => Ok(Material::TuffSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TUFF_STAIRS" => Ok(Material::TuffStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TUFF_WALL" => Ok(Material::TuffWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHISELED_TUFF" => Ok(Material::ChiseledTuff { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_TUFF" => Ok(Material::PolishedTuff { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_TUFF_SLAB" => Ok(Material::PolishedTuffSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_TUFF_STAIRS" => Ok(Material::PolishedTuffStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_TUFF_WALL" => Ok(Material::PolishedTuffWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TUFF_BRICKS" => Ok(Material::TuffBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TUFF_BRICK_SLAB" => Ok(Material::TuffBrickSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TUFF_BRICK_STAIRS" => Ok(Material::TuffBrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TUFF_BRICK_WALL" => Ok(Material::TuffBrickWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHISELED_TUFF_BRICKS" => Ok(Material::ChiseledTuffBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DRIPSTONE_BLOCK" => Ok(Material::DripstoneBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRASS_BLOCK" => Ok(Material::GrassBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIRT" => Ok(Material::Dirt { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COARSE_DIRT" => Ok(Material::CoarseDirt { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PODZOL" => Ok(Material::Podzol { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ROOTED_DIRT" => Ok(Material::RootedDirt { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUD" => Ok(Material::Mud { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_NYLIUM" => Ok(Material::CrimsonNylium { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_NYLIUM" => Ok(Material::WarpedNylium { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COBBLESTONE" => Ok(Material::Cobblestone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_PLANKS" => Ok(Material::OakPlanks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_PLANKS" => Ok(Material::SprucePlanks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_PLANKS" => Ok(Material::BirchPlanks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_PLANKS" => Ok(Material::JunglePlanks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_PLANKS" => Ok(Material::AcaciaPlanks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_PLANKS" => Ok(Material::CherryPlanks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_PLANKS" => Ok(Material::DarkOakPlanks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_PLANKS" => Ok(Material::MangrovePlanks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_PLANKS" => Ok(Material::BambooPlanks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_PLANKS" => Ok(Material::CrimsonPlanks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_PLANKS" => Ok(Material::WarpedPlanks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_MOSAIC" => Ok(Material::BambooMosaic { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_SAPLING" => Ok(Material::OakSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_SAPLING" => Ok(Material::SpruceSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_SAPLING" => Ok(Material::BirchSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_SAPLING" => Ok(Material::JungleSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_SAPLING" => Ok(Material::AcaciaSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_SAPLING" => Ok(Material::CherrySapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_SAPLING" => Ok(Material::DarkOakSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_PROPAGULE" => Ok(Material::MangrovePropagule { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BEDROCK" => Ok(Material::Bedrock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SAND" => Ok(Material::Sand { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SUSPICIOUS_SAND" => Ok(Material::SuspiciousSand { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SUSPICIOUS_GRAVEL" => Ok(Material::SuspiciousGravel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_SAND" => Ok(Material::RedSand { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAVEL" => Ok(Material::Gravel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COAL_ORE" => Ok(Material::CoalOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_COAL_ORE" => Ok(Material::DeepslateCoalOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_ORE" => Ok(Material::IronOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_IRON_ORE" => Ok(Material::DeepslateIronOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COPPER_ORE" => Ok(Material::CopperOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_COPPER_ORE" => Ok(Material::DeepslateCopperOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLD_ORE" => Ok(Material::GoldOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_GOLD_ORE" => Ok(Material::DeepslateGoldOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "REDSTONE_ORE" => Ok(Material::RedstoneOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_REDSTONE_ORE" => Ok(Material::DeepslateRedstoneOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EMERALD_ORE" => Ok(Material::EmeraldOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_EMERALD_ORE" => Ok(Material::DeepslateEmeraldOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LAPIS_ORE" => Ok(Material::LapisOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_LAPIS_ORE" => Ok(Material::DeepslateLapisOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND_ORE" => Ok(Material::DiamondOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_DIAMOND_ORE" => Ok(Material::DeepslateDiamondOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_GOLD_ORE" => Ok(Material::NetherGoldOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_QUARTZ_ORE" => Ok(Material::NetherQuartzOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ANCIENT_DEBRIS" => Ok(Material::AncientDebris { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COAL_BLOCK" => Ok(Material::CoalBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RAW_IRON_BLOCK" => Ok(Material::RawIronBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RAW_COPPER_BLOCK" => Ok(Material::RawCopperBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RAW_GOLD_BLOCK" => Ok(Material::RawGoldBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HEAVY_CORE" => Ok(Material::HeavyCore { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "AMETHYST_BLOCK" => Ok(Material::AmethystBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BUDDING_AMETHYST" => Ok(Material::BuddingAmethyst { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_BLOCK" => Ok(Material::IronBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COPPER_BLOCK" => Ok(Material::CopperBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLD_BLOCK" => Ok(Material::GoldBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND_BLOCK" => Ok(Material::DiamondBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_BLOCK" => Ok(Material::NetheriteBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EXPOSED_COPPER" => Ok(Material::ExposedCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WEATHERED_COPPER" => Ok(Material::WeatheredCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OXIDIZED_COPPER" => Ok(Material::OxidizedCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHISELED_COPPER" => Ok(Material::ChiseledCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EXPOSED_CHISELED_COPPER" => Ok(Material::ExposedChiseledCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WEATHERED_CHISELED_COPPER" => Ok(Material::WeatheredChiseledCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OXIDIZED_CHISELED_COPPER" => Ok(Material::OxidizedChiseledCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CUT_COPPER" => Ok(Material::CutCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EXPOSED_CUT_COPPER" => Ok(Material::ExposedCutCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WEATHERED_CUT_COPPER" => Ok(Material::WeatheredCutCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OXIDIZED_CUT_COPPER" => Ok(Material::OxidizedCutCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CUT_COPPER_STAIRS" => Ok(Material::CutCopperStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EXPOSED_CUT_COPPER_STAIRS" => Ok(Material::ExposedCutCopperStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WEATHERED_CUT_COPPER_STAIRS" => Ok(Material::WeatheredCutCopperStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OXIDIZED_CUT_COPPER_STAIRS" => Ok(Material::OxidizedCutCopperStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CUT_COPPER_SLAB" => Ok(Material::CutCopperSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EXPOSED_CUT_COPPER_SLAB" => Ok(Material::ExposedCutCopperSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WEATHERED_CUT_COPPER_SLAB" => Ok(Material::WeatheredCutCopperSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OXIDIZED_CUT_COPPER_SLAB" => Ok(Material::OxidizedCutCopperSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_COPPER_BLOCK" => Ok(Material::WaxedCopperBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_EXPOSED_COPPER" => Ok(Material::WaxedExposedCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_WEATHERED_COPPER" => Ok(Material::WaxedWeatheredCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_OXIDIZED_COPPER" => Ok(Material::WaxedOxidizedCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_CHISELED_COPPER" => Ok(Material::WaxedChiseledCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_EXPOSED_CHISELED_COPPER" => Ok(Material::WaxedExposedChiseledCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_WEATHERED_CHISELED_COPPER" => Ok(Material::WaxedWeatheredChiseledCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_OXIDIZED_CHISELED_COPPER" => Ok(Material::WaxedOxidizedChiseledCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_CUT_COPPER" => Ok(Material::WaxedCutCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_EXPOSED_CUT_COPPER" => Ok(Material::WaxedExposedCutCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_WEATHERED_CUT_COPPER" => Ok(Material::WaxedWeatheredCutCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_OXIDIZED_CUT_COPPER" => Ok(Material::WaxedOxidizedCutCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_CUT_COPPER_STAIRS" => Ok(Material::WaxedCutCopperStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_EXPOSED_CUT_COPPER_STAIRS" => Ok(Material::WaxedExposedCutCopperStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_WEATHERED_CUT_COPPER_STAIRS" => { + Ok(Material::WaxedWeatheredCutCopperStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "WAXED_OXIDIZED_CUT_COPPER_STAIRS" => Ok(Material::WaxedOxidizedCutCopperStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_CUT_COPPER_SLAB" => Ok(Material::WaxedCutCopperSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_EXPOSED_CUT_COPPER_SLAB" => Ok(Material::WaxedExposedCutCopperSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_WEATHERED_CUT_COPPER_SLAB" => Ok(Material::WaxedWeatheredCutCopperSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_OXIDIZED_CUT_COPPER_SLAB" => Ok(Material::WaxedOxidizedCutCopperSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_LOG" => Ok(Material::OakLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_LOG" => Ok(Material::SpruceLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_LOG" => Ok(Material::BirchLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_LOG" => Ok(Material::JungleLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_LOG" => Ok(Material::AcaciaLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_LOG" => Ok(Material::CherryLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_LOG" => Ok(Material::DarkOakLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_LOG" => Ok(Material::MangroveLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_ROOTS" => Ok(Material::MangroveRoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUDDY_MANGROVE_ROOTS" => Ok(Material::MuddyMangroveRoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_STEM" => Ok(Material::CrimsonStem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_STEM" => Ok(Material::WarpedStem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_BLOCK" => Ok(Material::BambooBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_OAK_LOG" => Ok(Material::StrippedOakLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_SPRUCE_LOG" => Ok(Material::StrippedSpruceLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_BIRCH_LOG" => Ok(Material::StrippedBirchLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_JUNGLE_LOG" => Ok(Material::StrippedJungleLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_ACACIA_LOG" => Ok(Material::StrippedAcaciaLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_CHERRY_LOG" => Ok(Material::StrippedCherryLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_DARK_OAK_LOG" => Ok(Material::StrippedDarkOakLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_MANGROVE_LOG" => Ok(Material::StrippedMangroveLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_CRIMSON_STEM" => Ok(Material::StrippedCrimsonStem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_WARPED_STEM" => Ok(Material::StrippedWarpedStem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_OAK_WOOD" => Ok(Material::StrippedOakWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_SPRUCE_WOOD" => Ok(Material::StrippedSpruceWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_BIRCH_WOOD" => Ok(Material::StrippedBirchWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_JUNGLE_WOOD" => Ok(Material::StrippedJungleWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_ACACIA_WOOD" => Ok(Material::StrippedAcaciaWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_CHERRY_WOOD" => Ok(Material::StrippedCherryWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_DARK_OAK_WOOD" => Ok(Material::StrippedDarkOakWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_MANGROVE_WOOD" => Ok(Material::StrippedMangroveWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_CRIMSON_HYPHAE" => Ok(Material::StrippedCrimsonHyphae { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_WARPED_HYPHAE" => Ok(Material::StrippedWarpedHyphae { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIPPED_BAMBOO_BLOCK" => Ok(Material::StrippedBambooBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_WOOD" => Ok(Material::OakWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_WOOD" => Ok(Material::SpruceWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_WOOD" => Ok(Material::BirchWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_WOOD" => Ok(Material::JungleWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_WOOD" => Ok(Material::AcaciaWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_WOOD" => Ok(Material::CherryWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_WOOD" => Ok(Material::DarkOakWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_WOOD" => Ok(Material::MangroveWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_HYPHAE" => Ok(Material::CrimsonHyphae { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_HYPHAE" => Ok(Material::WarpedHyphae { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_LEAVES" => Ok(Material::OakLeaves { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_LEAVES" => Ok(Material::SpruceLeaves { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_LEAVES" => Ok(Material::BirchLeaves { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_LEAVES" => Ok(Material::JungleLeaves { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_LEAVES" => Ok(Material::AcaciaLeaves { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_LEAVES" => Ok(Material::CherryLeaves { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_LEAVES" => Ok(Material::DarkOakLeaves { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_LEAVES" => Ok(Material::MangroveLeaves { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "AZALEA_LEAVES" => Ok(Material::AzaleaLeaves { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FLOWERING_AZALEA_LEAVES" => Ok(Material::FloweringAzaleaLeaves { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPONGE" => Ok(Material::Sponge { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WET_SPONGE" => Ok(Material::WetSponge { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GLASS" => Ok(Material::Glass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TINTED_GLASS" => Ok(Material::TintedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LAPIS_BLOCK" => Ok(Material::LapisBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SANDSTONE" => Ok(Material::Sandstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHISELED_SANDSTONE" => Ok(Material::ChiseledSandstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CUT_SANDSTONE" => Ok(Material::CutSandstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COBWEB" => Ok(Material::Cobweb { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SHORT_GRASS" => Ok(Material::ShortGrass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FERN" => Ok(Material::Fern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "AZALEA" => Ok(Material::Azalea { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FLOWERING_AZALEA" => Ok(Material::FloweringAzalea { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_BUSH" => Ok(Material::DeadBush { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SEAGRASS" => Ok(Material::Seagrass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SEA_PICKLE" => Ok(Material::SeaPickle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_WOOL" => Ok(Material::WhiteWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_WOOL" => Ok(Material::OrangeWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_WOOL" => Ok(Material::MagentaWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_WOOL" => Ok(Material::LightBlueWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_WOOL" => Ok(Material::YellowWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_WOOL" => Ok(Material::LimeWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_WOOL" => Ok(Material::PinkWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_WOOL" => Ok(Material::GrayWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_WOOL" => Ok(Material::LightGrayWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_WOOL" => Ok(Material::CyanWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_WOOL" => Ok(Material::PurpleWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_WOOL" => Ok(Material::BlueWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_WOOL" => Ok(Material::BrownWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_WOOL" => Ok(Material::GreenWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_WOOL" => Ok(Material::RedWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_WOOL" => Ok(Material::BlackWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DANDELION" => Ok(Material::Dandelion { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POPPY" => Ok(Material::Poppy { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_ORCHID" => Ok(Material::BlueOrchid { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ALLIUM" => Ok(Material::Allium { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "AZURE_BLUET" => Ok(Material::AzureBluet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_TULIP" => Ok(Material::RedTulip { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_TULIP" => Ok(Material::OrangeTulip { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_TULIP" => Ok(Material::WhiteTulip { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_TULIP" => Ok(Material::PinkTulip { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OXEYE_DAISY" => Ok(Material::OxeyeDaisy { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CORNFLOWER" => Ok(Material::Cornflower { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LILY_OF_THE_VALLEY" => Ok(Material::LilyOfTheValley { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WITHER_ROSE" => Ok(Material::WitherRose { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TORCHFLOWER" => Ok(Material::Torchflower { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PITCHER_PLANT" => Ok(Material::PitcherPlant { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPORE_BLOSSOM" => Ok(Material::SporeBlossom { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_MUSHROOM" => Ok(Material::BrownMushroom { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_MUSHROOM" => Ok(Material::RedMushroom { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_FUNGUS" => Ok(Material::CrimsonFungus { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_FUNGUS" => Ok(Material::WarpedFungus { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_ROOTS" => Ok(Material::CrimsonRoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_ROOTS" => Ok(Material::WarpedRoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_SPROUTS" => Ok(Material::NetherSprouts { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WEEPING_VINES" => Ok(Material::WeepingVines { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TWISTING_VINES" => Ok(Material::TwistingVines { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SUGAR_CANE" => Ok(Material::SugarCane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "KELP" => Ok(Material::Kelp { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOSS_CARPET" => Ok(Material::MossCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_PETALS" => Ok(Material::PinkPetals { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOSS_BLOCK" => Ok(Material::MossBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HANGING_ROOTS" => Ok(Material::HangingRoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIG_DRIPLEAF" => Ok(Material::BigDripleaf { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMALL_DRIPLEAF" => Ok(Material::SmallDripleaf { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO" => Ok(Material::Bamboo { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_SLAB" => Ok(Material::OakSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_SLAB" => Ok(Material::SpruceSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_SLAB" => Ok(Material::BirchSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_SLAB" => Ok(Material::JungleSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_SLAB" => Ok(Material::AcaciaSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_SLAB" => Ok(Material::CherrySlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_SLAB" => Ok(Material::DarkOakSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_SLAB" => Ok(Material::MangroveSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_SLAB" => Ok(Material::BambooSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_MOSAIC_SLAB" => Ok(Material::BambooMosaicSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_SLAB" => Ok(Material::CrimsonSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_SLAB" => Ok(Material::WarpedSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_SLAB" => Ok(Material::StoneSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOOTH_STONE_SLAB" => Ok(Material::SmoothStoneSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SANDSTONE_SLAB" => Ok(Material::SandstoneSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CUT_SANDSTONE_SLAB" => Ok(Material::CutSandstoneSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PETRIFIED_OAK_SLAB" => Ok(Material::PetrifiedOakSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COBBLESTONE_SLAB" => Ok(Material::CobblestoneSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BRICK_SLAB" => Ok(Material::BrickSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_BRICK_SLAB" => Ok(Material::StoneBrickSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUD_BRICK_SLAB" => Ok(Material::MudBrickSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_BRICK_SLAB" => Ok(Material::NetherBrickSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "QUARTZ_SLAB" => Ok(Material::QuartzSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_SANDSTONE_SLAB" => Ok(Material::RedSandstoneSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CUT_RED_SANDSTONE_SLAB" => Ok(Material::CutRedSandstoneSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPUR_SLAB" => Ok(Material::PurpurSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PRISMARINE_SLAB" => Ok(Material::PrismarineSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PRISMARINE_BRICK_SLAB" => Ok(Material::PrismarineBrickSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_PRISMARINE_SLAB" => Ok(Material::DarkPrismarineSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOOTH_QUARTZ" => Ok(Material::SmoothQuartz { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOOTH_RED_SANDSTONE" => Ok(Material::SmoothRedSandstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOOTH_SANDSTONE" => Ok(Material::SmoothSandstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOOTH_STONE" => Ok(Material::SmoothStone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BRICKS" => Ok(Material::Bricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BOOKSHELF" => Ok(Material::Bookshelf { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHISELED_BOOKSHELF" => Ok(Material::ChiseledBookshelf { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DECORATED_POT" => Ok(Material::DecoratedPot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOSSY_COBBLESTONE" => Ok(Material::MossyCobblestone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OBSIDIAN" => Ok(Material::Obsidian { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TORCH" => Ok(Material::Torch { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "END_ROD" => Ok(Material::EndRod { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHORUS_PLANT" => Ok(Material::ChorusPlant { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHORUS_FLOWER" => Ok(Material::ChorusFlower { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPUR_BLOCK" => Ok(Material::PurpurBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPUR_PILLAR" => Ok(Material::PurpurPillar { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPUR_STAIRS" => Ok(Material::PurpurStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPAWNER" => Ok(Material::Spawner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHEST" => Ok(Material::Chest { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRAFTING_TABLE" => Ok(Material::CraftingTable { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FARMLAND" => Ok(Material::Farmland { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FURNACE" => Ok(Material::Furnace { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LADDER" => Ok(Material::Ladder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COBBLESTONE_STAIRS" => Ok(Material::CobblestoneStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SNOW" => Ok(Material::Snow { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ICE" => Ok(Material::Ice { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SNOW_BLOCK" => Ok(Material::SnowBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CACTUS" => Ok(Material::Cactus { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CLAY" => Ok(Material::Clay { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUKEBOX" => Ok(Material::Jukebox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_FENCE" => Ok(Material::OakFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_FENCE" => Ok(Material::SpruceFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_FENCE" => Ok(Material::BirchFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_FENCE" => Ok(Material::JungleFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_FENCE" => Ok(Material::AcaciaFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_FENCE" => Ok(Material::CherryFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_FENCE" => Ok(Material::DarkOakFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_FENCE" => Ok(Material::MangroveFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_FENCE" => Ok(Material::BambooFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_FENCE" => Ok(Material::CrimsonFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_FENCE" => Ok(Material::WarpedFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PUMPKIN" => Ok(Material::Pumpkin { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CARVED_PUMPKIN" => Ok(Material::CarvedPumpkin { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JACK_O_LANTERN" => Ok(Material::JackOLantern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERRACK" => Ok(Material::Netherrack { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SOUL_SAND" => Ok(Material::SoulSand { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SOUL_SOIL" => Ok(Material::SoulSoil { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BASALT" => Ok(Material::Basalt { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_BASALT" => Ok(Material::PolishedBasalt { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOOTH_BASALT" => Ok(Material::SmoothBasalt { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SOUL_TORCH" => Ok(Material::SoulTorch { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GLOWSTONE" => Ok(Material::Glowstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "INFESTED_STONE" => Ok(Material::InfestedStone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "INFESTED_COBBLESTONE" => Ok(Material::InfestedCobblestone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "INFESTED_STONE_BRICKS" => Ok(Material::InfestedStoneBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "INFESTED_MOSSY_STONE_BRICKS" => Ok(Material::InfestedMossyStoneBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "INFESTED_CRACKED_STONE_BRICKS" => Ok(Material::InfestedCrackedStoneBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "INFESTED_CHISELED_STONE_BRICKS" => Ok(Material::InfestedChiseledStoneBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "INFESTED_DEEPSLATE" => Ok(Material::InfestedDeepslate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_BRICKS" => Ok(Material::StoneBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOSSY_STONE_BRICKS" => Ok(Material::MossyStoneBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRACKED_STONE_BRICKS" => Ok(Material::CrackedStoneBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHISELED_STONE_BRICKS" => Ok(Material::ChiseledStoneBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PACKED_MUD" => Ok(Material::PackedMud { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUD_BRICKS" => Ok(Material::MudBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_BRICKS" => Ok(Material::DeepslateBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRACKED_DEEPSLATE_BRICKS" => Ok(Material::CrackedDeepslateBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_TILES" => Ok(Material::DeepslateTiles { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRACKED_DEEPSLATE_TILES" => Ok(Material::CrackedDeepslateTiles { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHISELED_DEEPSLATE" => Ok(Material::ChiseledDeepslate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "REINFORCED_DEEPSLATE" => Ok(Material::ReinforcedDeepslate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_MUSHROOM_BLOCK" => Ok(Material::BrownMushroomBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_MUSHROOM_BLOCK" => Ok(Material::RedMushroomBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSHROOM_STEM" => Ok(Material::MushroomStem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_BARS" => Ok(Material::IronBars { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHAIN" => Ok(Material::Chain { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GLASS_PANE" => Ok(Material::GlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MELON" => Ok(Material::Melon { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "VINE" => Ok(Material::Vine { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GLOW_LICHEN" => Ok(Material::GlowLichen { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BRICK_STAIRS" => Ok(Material::BrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_BRICK_STAIRS" => Ok(Material::StoneBrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUD_BRICK_STAIRS" => Ok(Material::MudBrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MYCELIUM" => Ok(Material::Mycelium { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LILY_PAD" => Ok(Material::LilyPad { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_BRICKS" => Ok(Material::NetherBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRACKED_NETHER_BRICKS" => Ok(Material::CrackedNetherBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHISELED_NETHER_BRICKS" => Ok(Material::ChiseledNetherBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_BRICK_FENCE" => Ok(Material::NetherBrickFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_BRICK_STAIRS" => Ok(Material::NetherBrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SCULK" => Ok(Material::Sculk { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SCULK_VEIN" => Ok(Material::SculkVein { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SCULK_CATALYST" => Ok(Material::SculkCatalyst { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SCULK_SHRIEKER" => Ok(Material::SculkShrieker { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ENCHANTING_TABLE" => Ok(Material::EnchantingTable { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "END_PORTAL_FRAME" => Ok(Material::EndPortalFrame { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "END_STONE" => Ok(Material::EndStone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "END_STONE_BRICKS" => Ok(Material::EndStoneBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DRAGON_EGG" => Ok(Material::DragonEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SANDSTONE_STAIRS" => Ok(Material::SandstoneStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ENDER_CHEST" => Ok(Material::EnderChest { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EMERALD_BLOCK" => Ok(Material::EmeraldBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_STAIRS" => Ok(Material::OakStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_STAIRS" => Ok(Material::SpruceStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_STAIRS" => Ok(Material::BirchStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_STAIRS" => Ok(Material::JungleStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_STAIRS" => Ok(Material::AcaciaStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_STAIRS" => Ok(Material::CherryStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_STAIRS" => Ok(Material::DarkOakStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_STAIRS" => Ok(Material::MangroveStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_STAIRS" => Ok(Material::BambooStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_MOSAIC_STAIRS" => Ok(Material::BambooMosaicStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_STAIRS" => Ok(Material::CrimsonStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_STAIRS" => Ok(Material::WarpedStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COMMAND_BLOCK" => Ok(Material::CommandBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BEACON" => Ok(Material::Beacon { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COBBLESTONE_WALL" => Ok(Material::CobblestoneWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOSSY_COBBLESTONE_WALL" => Ok(Material::MossyCobblestoneWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BRICK_WALL" => Ok(Material::BrickWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PRISMARINE_WALL" => Ok(Material::PrismarineWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_SANDSTONE_WALL" => Ok(Material::RedSandstoneWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOSSY_STONE_BRICK_WALL" => Ok(Material::MossyStoneBrickWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRANITE_WALL" => Ok(Material::GraniteWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_BRICK_WALL" => Ok(Material::StoneBrickWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUD_BRICK_WALL" => Ok(Material::MudBrickWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_BRICK_WALL" => Ok(Material::NetherBrickWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ANDESITE_WALL" => Ok(Material::AndesiteWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_NETHER_BRICK_WALL" => Ok(Material::RedNetherBrickWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SANDSTONE_WALL" => Ok(Material::SandstoneWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "END_STONE_BRICK_WALL" => Ok(Material::EndStoneBrickWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIORITE_WALL" => Ok(Material::DioriteWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACKSTONE_WALL" => Ok(Material::BlackstoneWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_BLACKSTONE_WALL" => Ok(Material::PolishedBlackstoneWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_BLACKSTONE_BRICK_WALL" => Ok(Material::PolishedBlackstoneBrickWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COBBLED_DEEPSLATE_WALL" => Ok(Material::CobbledDeepslateWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_DEEPSLATE_WALL" => Ok(Material::PolishedDeepslateWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_BRICK_WALL" => Ok(Material::DeepslateBrickWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_TILE_WALL" => Ok(Material::DeepslateTileWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ANVIL" => Ok(Material::Anvil { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHIPPED_ANVIL" => Ok(Material::ChippedAnvil { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DAMAGED_ANVIL" => Ok(Material::DamagedAnvil { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHISELED_QUARTZ_BLOCK" => Ok(Material::ChiseledQuartzBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "QUARTZ_BLOCK" => Ok(Material::QuartzBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "QUARTZ_BRICKS" => Ok(Material::QuartzBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "QUARTZ_PILLAR" => Ok(Material::QuartzPillar { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "QUARTZ_STAIRS" => Ok(Material::QuartzStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_TERRACOTTA" => Ok(Material::WhiteTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_TERRACOTTA" => Ok(Material::OrangeTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_TERRACOTTA" => Ok(Material::MagentaTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_TERRACOTTA" => Ok(Material::LightBlueTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_TERRACOTTA" => Ok(Material::YellowTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_TERRACOTTA" => Ok(Material::LimeTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_TERRACOTTA" => Ok(Material::PinkTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_TERRACOTTA" => Ok(Material::GrayTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_TERRACOTTA" => Ok(Material::LightGrayTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_TERRACOTTA" => Ok(Material::CyanTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_TERRACOTTA" => Ok(Material::PurpleTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_TERRACOTTA" => Ok(Material::BlueTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_TERRACOTTA" => Ok(Material::BrownTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_TERRACOTTA" => Ok(Material::GreenTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_TERRACOTTA" => Ok(Material::RedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_TERRACOTTA" => Ok(Material::BlackTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BARRIER" => Ok(Material::Barrier { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT" => Ok(Material::Light { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HAY_BLOCK" => Ok(Material::HayBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_CARPET" => Ok(Material::WhiteCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_CARPET" => Ok(Material::OrangeCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_CARPET" => Ok(Material::MagentaCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_CARPET" => Ok(Material::LightBlueCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_CARPET" => Ok(Material::YellowCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_CARPET" => Ok(Material::LimeCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_CARPET" => Ok(Material::PinkCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_CARPET" => Ok(Material::GrayCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_CARPET" => Ok(Material::LightGrayCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_CARPET" => Ok(Material::CyanCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_CARPET" => Ok(Material::PurpleCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_CARPET" => Ok(Material::BlueCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_CARPET" => Ok(Material::BrownCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_CARPET" => Ok(Material::GreenCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_CARPET" => Ok(Material::RedCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_CARPET" => Ok(Material::BlackCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TERRACOTTA" => Ok(Material::Terracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PACKED_ICE" => Ok(Material::PackedIce { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIRT_PATH" => Ok(Material::DirtPath { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SUNFLOWER" => Ok(Material::Sunflower { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LILAC" => Ok(Material::Lilac { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ROSE_BUSH" => Ok(Material::RoseBush { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PEONY" => Ok(Material::Peony { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TALL_GRASS" => Ok(Material::TallGrass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LARGE_FERN" => Ok(Material::LargeFern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_STAINED_GLASS" => Ok(Material::WhiteStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_STAINED_GLASS" => Ok(Material::OrangeStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_STAINED_GLASS" => Ok(Material::MagentaStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_STAINED_GLASS" => Ok(Material::LightBlueStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_STAINED_GLASS" => Ok(Material::YellowStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_STAINED_GLASS" => Ok(Material::LimeStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_STAINED_GLASS" => Ok(Material::PinkStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_STAINED_GLASS" => Ok(Material::GrayStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_STAINED_GLASS" => Ok(Material::LightGrayStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_STAINED_GLASS" => Ok(Material::CyanStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_STAINED_GLASS" => Ok(Material::PurpleStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_STAINED_GLASS" => Ok(Material::BlueStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_STAINED_GLASS" => Ok(Material::BrownStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_STAINED_GLASS" => Ok(Material::GreenStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_STAINED_GLASS" => Ok(Material::RedStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_STAINED_GLASS" => Ok(Material::BlackStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_STAINED_GLASS_PANE" => Ok(Material::WhiteStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_STAINED_GLASS_PANE" => Ok(Material::OrangeStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_STAINED_GLASS_PANE" => Ok(Material::MagentaStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_STAINED_GLASS_PANE" => Ok(Material::LightBlueStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_STAINED_GLASS_PANE" => Ok(Material::YellowStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_STAINED_GLASS_PANE" => Ok(Material::LimeStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_STAINED_GLASS_PANE" => Ok(Material::PinkStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_STAINED_GLASS_PANE" => Ok(Material::GrayStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_STAINED_GLASS_PANE" => Ok(Material::LightGrayStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_STAINED_GLASS_PANE" => Ok(Material::CyanStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_STAINED_GLASS_PANE" => Ok(Material::PurpleStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_STAINED_GLASS_PANE" => Ok(Material::BlueStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_STAINED_GLASS_PANE" => Ok(Material::BrownStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_STAINED_GLASS_PANE" => Ok(Material::GreenStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_STAINED_GLASS_PANE" => Ok(Material::RedStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_STAINED_GLASS_PANE" => Ok(Material::BlackStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PRISMARINE" => Ok(Material::Prismarine { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PRISMARINE_BRICKS" => Ok(Material::PrismarineBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_PRISMARINE" => Ok(Material::DarkPrismarine { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PRISMARINE_STAIRS" => Ok(Material::PrismarineStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PRISMARINE_BRICK_STAIRS" => Ok(Material::PrismarineBrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_PRISMARINE_STAIRS" => Ok(Material::DarkPrismarineStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SEA_LANTERN" => Ok(Material::SeaLantern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_SANDSTONE" => Ok(Material::RedSandstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHISELED_RED_SANDSTONE" => Ok(Material::ChiseledRedSandstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CUT_RED_SANDSTONE" => Ok(Material::CutRedSandstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_SANDSTONE_STAIRS" => Ok(Material::RedSandstoneStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "REPEATING_COMMAND_BLOCK" => Ok(Material::RepeatingCommandBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHAIN_COMMAND_BLOCK" => Ok(Material::ChainCommandBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGMA_BLOCK" => Ok(Material::MagmaBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_WART_BLOCK" => Ok(Material::NetherWartBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_WART_BLOCK" => Ok(Material::WarpedWartBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_NETHER_BRICKS" => Ok(Material::RedNetherBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BONE_BLOCK" => Ok(Material::BoneBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRUCTURE_VOID" => Ok(Material::StructureVoid { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SHULKER_BOX" => Ok(Material::ShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_SHULKER_BOX" => Ok(Material::WhiteShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_SHULKER_BOX" => Ok(Material::OrangeShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_SHULKER_BOX" => Ok(Material::MagentaShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_SHULKER_BOX" => Ok(Material::LightBlueShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_SHULKER_BOX" => Ok(Material::YellowShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_SHULKER_BOX" => Ok(Material::LimeShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_SHULKER_BOX" => Ok(Material::PinkShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_SHULKER_BOX" => Ok(Material::GrayShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_SHULKER_BOX" => Ok(Material::LightGrayShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_SHULKER_BOX" => Ok(Material::CyanShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_SHULKER_BOX" => Ok(Material::PurpleShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_SHULKER_BOX" => Ok(Material::BlueShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_SHULKER_BOX" => Ok(Material::BrownShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_SHULKER_BOX" => Ok(Material::GreenShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_SHULKER_BOX" => Ok(Material::RedShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_SHULKER_BOX" => Ok(Material::BlackShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_GLAZED_TERRACOTTA" => Ok(Material::WhiteGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_GLAZED_TERRACOTTA" => Ok(Material::OrangeGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_GLAZED_TERRACOTTA" => Ok(Material::MagentaGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_GLAZED_TERRACOTTA" => Ok(Material::LightBlueGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_GLAZED_TERRACOTTA" => Ok(Material::YellowGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_GLAZED_TERRACOTTA" => Ok(Material::LimeGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_GLAZED_TERRACOTTA" => Ok(Material::PinkGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_GLAZED_TERRACOTTA" => Ok(Material::GrayGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_GLAZED_TERRACOTTA" => Ok(Material::LightGrayGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_GLAZED_TERRACOTTA" => Ok(Material::CyanGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_GLAZED_TERRACOTTA" => Ok(Material::PurpleGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_GLAZED_TERRACOTTA" => Ok(Material::BlueGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_GLAZED_TERRACOTTA" => Ok(Material::BrownGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_GLAZED_TERRACOTTA" => Ok(Material::GreenGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_GLAZED_TERRACOTTA" => Ok(Material::RedGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_GLAZED_TERRACOTTA" => Ok(Material::BlackGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_CONCRETE" => Ok(Material::WhiteConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_CONCRETE" => Ok(Material::OrangeConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_CONCRETE" => Ok(Material::MagentaConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_CONCRETE" => Ok(Material::LightBlueConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_CONCRETE" => Ok(Material::YellowConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_CONCRETE" => Ok(Material::LimeConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_CONCRETE" => Ok(Material::PinkConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_CONCRETE" => Ok(Material::GrayConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_CONCRETE" => Ok(Material::LightGrayConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_CONCRETE" => Ok(Material::CyanConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_CONCRETE" => Ok(Material::PurpleConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_CONCRETE" => Ok(Material::BlueConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_CONCRETE" => Ok(Material::BrownConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_CONCRETE" => Ok(Material::GreenConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_CONCRETE" => Ok(Material::RedConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_CONCRETE" => Ok(Material::BlackConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_CONCRETE_POWDER" => Ok(Material::WhiteConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_CONCRETE_POWDER" => Ok(Material::OrangeConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_CONCRETE_POWDER" => Ok(Material::MagentaConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_CONCRETE_POWDER" => Ok(Material::LightBlueConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_CONCRETE_POWDER" => Ok(Material::YellowConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_CONCRETE_POWDER" => Ok(Material::LimeConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_CONCRETE_POWDER" => Ok(Material::PinkConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_CONCRETE_POWDER" => Ok(Material::GrayConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_CONCRETE_POWDER" => Ok(Material::LightGrayConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_CONCRETE_POWDER" => Ok(Material::CyanConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_CONCRETE_POWDER" => Ok(Material::PurpleConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_CONCRETE_POWDER" => Ok(Material::BlueConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_CONCRETE_POWDER" => Ok(Material::BrownConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_CONCRETE_POWDER" => Ok(Material::GreenConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_CONCRETE_POWDER" => Ok(Material::RedConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_CONCRETE_POWDER" => Ok(Material::BlackConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TURTLE_EGG" => Ok(Material::TurtleEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SNIFFER_EGG" => Ok(Material::SnifferEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_TUBE_CORAL_BLOCK" => Ok(Material::DeadTubeCoralBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_BRAIN_CORAL_BLOCK" => Ok(Material::DeadBrainCoralBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_BUBBLE_CORAL_BLOCK" => Ok(Material::DeadBubbleCoralBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_FIRE_CORAL_BLOCK" => Ok(Material::DeadFireCoralBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_HORN_CORAL_BLOCK" => Ok(Material::DeadHornCoralBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TUBE_CORAL_BLOCK" => Ok(Material::TubeCoralBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BRAIN_CORAL_BLOCK" => Ok(Material::BrainCoralBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BUBBLE_CORAL_BLOCK" => Ok(Material::BubbleCoralBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FIRE_CORAL_BLOCK" => Ok(Material::FireCoralBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HORN_CORAL_BLOCK" => Ok(Material::HornCoralBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TUBE_CORAL" => Ok(Material::TubeCoral { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BRAIN_CORAL" => Ok(Material::BrainCoral { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BUBBLE_CORAL" => Ok(Material::BubbleCoral { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FIRE_CORAL" => Ok(Material::FireCoral { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HORN_CORAL" => Ok(Material::HornCoral { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_BRAIN_CORAL" => Ok(Material::DeadBrainCoral { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_BUBBLE_CORAL" => Ok(Material::DeadBubbleCoral { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_FIRE_CORAL" => Ok(Material::DeadFireCoral { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_HORN_CORAL" => Ok(Material::DeadHornCoral { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_TUBE_CORAL" => Ok(Material::DeadTubeCoral { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TUBE_CORAL_FAN" => Ok(Material::TubeCoralFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BRAIN_CORAL_FAN" => Ok(Material::BrainCoralFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BUBBLE_CORAL_FAN" => Ok(Material::BubbleCoralFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FIRE_CORAL_FAN" => Ok(Material::FireCoralFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HORN_CORAL_FAN" => Ok(Material::HornCoralFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_TUBE_CORAL_FAN" => Ok(Material::DeadTubeCoralFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_BRAIN_CORAL_FAN" => Ok(Material::DeadBrainCoralFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_BUBBLE_CORAL_FAN" => Ok(Material::DeadBubbleCoralFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_FIRE_CORAL_FAN" => Ok(Material::DeadFireCoralFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_HORN_CORAL_FAN" => Ok(Material::DeadHornCoralFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_ICE" => Ok(Material::BlueIce { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CONDUIT" => Ok(Material::Conduit { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_GRANITE_STAIRS" => Ok(Material::PolishedGraniteStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOOTH_RED_SANDSTONE_STAIRS" => Ok(Material::SmoothRedSandstoneStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOSSY_STONE_BRICK_STAIRS" => Ok(Material::MossyStoneBrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_DIORITE_STAIRS" => Ok(Material::PolishedDioriteStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOSSY_COBBLESTONE_STAIRS" => Ok(Material::MossyCobblestoneStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "END_STONE_BRICK_STAIRS" => Ok(Material::EndStoneBrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_STAIRS" => Ok(Material::StoneStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOOTH_SANDSTONE_STAIRS" => Ok(Material::SmoothSandstoneStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOOTH_QUARTZ_STAIRS" => Ok(Material::SmoothQuartzStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRANITE_STAIRS" => Ok(Material::GraniteStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ANDESITE_STAIRS" => Ok(Material::AndesiteStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_NETHER_BRICK_STAIRS" => Ok(Material::RedNetherBrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_ANDESITE_STAIRS" => Ok(Material::PolishedAndesiteStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIORITE_STAIRS" => Ok(Material::DioriteStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COBBLED_DEEPSLATE_STAIRS" => Ok(Material::CobbledDeepslateStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_DEEPSLATE_STAIRS" => Ok(Material::PolishedDeepslateStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_BRICK_STAIRS" => Ok(Material::DeepslateBrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_TILE_STAIRS" => Ok(Material::DeepslateTileStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_GRANITE_SLAB" => Ok(Material::PolishedGraniteSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOOTH_RED_SANDSTONE_SLAB" => Ok(Material::SmoothRedSandstoneSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOSSY_STONE_BRICK_SLAB" => Ok(Material::MossyStoneBrickSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_DIORITE_SLAB" => Ok(Material::PolishedDioriteSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOSSY_COBBLESTONE_SLAB" => Ok(Material::MossyCobblestoneSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "END_STONE_BRICK_SLAB" => Ok(Material::EndStoneBrickSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOOTH_SANDSTONE_SLAB" => Ok(Material::SmoothSandstoneSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOOTH_QUARTZ_SLAB" => Ok(Material::SmoothQuartzSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRANITE_SLAB" => Ok(Material::GraniteSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ANDESITE_SLAB" => Ok(Material::AndesiteSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_NETHER_BRICK_SLAB" => Ok(Material::RedNetherBrickSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_ANDESITE_SLAB" => Ok(Material::PolishedAndesiteSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIORITE_SLAB" => Ok(Material::DioriteSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COBBLED_DEEPSLATE_SLAB" => Ok(Material::CobbledDeepslateSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_DEEPSLATE_SLAB" => Ok(Material::PolishedDeepslateSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_BRICK_SLAB" => Ok(Material::DeepslateBrickSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEEPSLATE_TILE_SLAB" => Ok(Material::DeepslateTileSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SCAFFOLDING" => Ok(Material::Scaffolding { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "REDSTONE" => Ok(Material::Redstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "REDSTONE_TORCH" => Ok(Material::RedstoneTorch { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "REDSTONE_BLOCK" => Ok(Material::RedstoneBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "REPEATER" => Ok(Material::Repeater { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COMPARATOR" => Ok(Material::Comparator { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PISTON" => Ok(Material::Piston { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STICKY_PISTON" => Ok(Material::StickyPiston { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SLIME_BLOCK" => Ok(Material::SlimeBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HONEY_BLOCK" => Ok(Material::HoneyBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OBSERVER" => Ok(Material::Observer { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HOPPER" => Ok(Material::Hopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DISPENSER" => Ok(Material::Dispenser { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DROPPER" => Ok(Material::Dropper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LECTERN" => Ok(Material::Lectern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TARGET" => Ok(Material::Target { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEVER" => Ok(Material::Lever { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHTNING_ROD" => Ok(Material::LightningRod { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DAYLIGHT_DETECTOR" => Ok(Material::DaylightDetector { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SCULK_SENSOR" => Ok(Material::SculkSensor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CALIBRATED_SCULK_SENSOR" => Ok(Material::CalibratedSculkSensor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TRIPWIRE_HOOK" => Ok(Material::TripwireHook { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TRAPPED_CHEST" => Ok(Material::TrappedChest { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TNT" => Ok(Material::Tnt { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "REDSTONE_LAMP" => Ok(Material::RedstoneLamp { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NOTE_BLOCK" => Ok(Material::NoteBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_BUTTON" => Ok(Material::StoneButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_BLACKSTONE_BUTTON" => Ok(Material::PolishedBlackstoneButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_BUTTON" => Ok(Material::OakButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_BUTTON" => Ok(Material::SpruceButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_BUTTON" => Ok(Material::BirchButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_BUTTON" => Ok(Material::JungleButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_BUTTON" => Ok(Material::AcaciaButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_BUTTON" => Ok(Material::CherryButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_BUTTON" => Ok(Material::DarkOakButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_BUTTON" => Ok(Material::MangroveButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_BUTTON" => Ok(Material::BambooButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_BUTTON" => Ok(Material::CrimsonButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_BUTTON" => Ok(Material::WarpedButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_PRESSURE_PLATE" => Ok(Material::StonePressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_BLACKSTONE_PRESSURE_PLATE" => { + Ok(Material::PolishedBlackstonePressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "LIGHT_WEIGHTED_PRESSURE_PLATE" => Ok(Material::LightWeightedPressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HEAVY_WEIGHTED_PRESSURE_PLATE" => Ok(Material::HeavyWeightedPressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_PRESSURE_PLATE" => Ok(Material::OakPressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_PRESSURE_PLATE" => Ok(Material::SprucePressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_PRESSURE_PLATE" => Ok(Material::BirchPressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_PRESSURE_PLATE" => Ok(Material::JunglePressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_PRESSURE_PLATE" => Ok(Material::AcaciaPressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_PRESSURE_PLATE" => Ok(Material::CherryPressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_PRESSURE_PLATE" => Ok(Material::DarkOakPressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_PRESSURE_PLATE" => Ok(Material::MangrovePressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_PRESSURE_PLATE" => Ok(Material::BambooPressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_PRESSURE_PLATE" => Ok(Material::CrimsonPressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_PRESSURE_PLATE" => Ok(Material::WarpedPressurePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_DOOR" => Ok(Material::IronDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_DOOR" => Ok(Material::OakDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_DOOR" => Ok(Material::SpruceDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_DOOR" => Ok(Material::BirchDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_DOOR" => Ok(Material::JungleDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_DOOR" => Ok(Material::AcaciaDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_DOOR" => Ok(Material::CherryDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_DOOR" => Ok(Material::DarkOakDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_DOOR" => Ok(Material::MangroveDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_DOOR" => Ok(Material::BambooDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_DOOR" => Ok(Material::CrimsonDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_DOOR" => Ok(Material::WarpedDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COPPER_DOOR" => Ok(Material::CopperDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EXPOSED_COPPER_DOOR" => Ok(Material::ExposedCopperDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WEATHERED_COPPER_DOOR" => Ok(Material::WeatheredCopperDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OXIDIZED_COPPER_DOOR" => Ok(Material::OxidizedCopperDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_COPPER_DOOR" => Ok(Material::WaxedCopperDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_EXPOSED_COPPER_DOOR" => Ok(Material::WaxedExposedCopperDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_WEATHERED_COPPER_DOOR" => Ok(Material::WaxedWeatheredCopperDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_OXIDIZED_COPPER_DOOR" => Ok(Material::WaxedOxidizedCopperDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_TRAPDOOR" => Ok(Material::IronTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_TRAPDOOR" => Ok(Material::OakTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_TRAPDOOR" => Ok(Material::SpruceTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_TRAPDOOR" => Ok(Material::BirchTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_TRAPDOOR" => Ok(Material::JungleTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_TRAPDOOR" => Ok(Material::AcaciaTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_TRAPDOOR" => Ok(Material::CherryTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_TRAPDOOR" => Ok(Material::DarkOakTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_TRAPDOOR" => Ok(Material::MangroveTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_TRAPDOOR" => Ok(Material::BambooTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_TRAPDOOR" => Ok(Material::CrimsonTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_TRAPDOOR" => Ok(Material::WarpedTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COPPER_TRAPDOOR" => Ok(Material::CopperTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EXPOSED_COPPER_TRAPDOOR" => Ok(Material::ExposedCopperTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WEATHERED_COPPER_TRAPDOOR" => Ok(Material::WeatheredCopperTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OXIDIZED_COPPER_TRAPDOOR" => Ok(Material::OxidizedCopperTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_COPPER_TRAPDOOR" => Ok(Material::WaxedCopperTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_EXPOSED_COPPER_TRAPDOOR" => Ok(Material::WaxedExposedCopperTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_WEATHERED_COPPER_TRAPDOOR" => Ok(Material::WaxedWeatheredCopperTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_OXIDIZED_COPPER_TRAPDOOR" => Ok(Material::WaxedOxidizedCopperTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_FENCE_GATE" => Ok(Material::OakFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_FENCE_GATE" => Ok(Material::SpruceFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_FENCE_GATE" => Ok(Material::BirchFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_FENCE_GATE" => Ok(Material::JungleFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_FENCE_GATE" => Ok(Material::AcaciaFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_FENCE_GATE" => Ok(Material::CherryFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_FENCE_GATE" => Ok(Material::DarkOakFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_FENCE_GATE" => Ok(Material::MangroveFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_FENCE_GATE" => Ok(Material::BambooFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_FENCE_GATE" => Ok(Material::CrimsonFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_FENCE_GATE" => Ok(Material::WarpedFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POWERED_RAIL" => Ok(Material::PoweredRail { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DETECTOR_RAIL" => Ok(Material::DetectorRail { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RAIL" => Ok(Material::Rail { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACTIVATOR_RAIL" => Ok(Material::ActivatorRail { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SADDLE" => Ok(Material::Saddle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MINECART" => Ok(Material::Minecart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHEST_MINECART" => Ok(Material::ChestMinecart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FURNACE_MINECART" => Ok(Material::FurnaceMinecart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TNT_MINECART" => Ok(Material::TntMinecart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HOPPER_MINECART" => Ok(Material::HopperMinecart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CARROT_ON_A_STICK" => Ok(Material::CarrotOnAStick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_FUNGUS_ON_A_STICK" => Ok(Material::WarpedFungusOnAStick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ELYTRA" => Ok(Material::Elytra { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_BOAT" => Ok(Material::OakBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_CHEST_BOAT" => Ok(Material::OakChestBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_BOAT" => Ok(Material::SpruceBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_CHEST_BOAT" => Ok(Material::SpruceChestBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_BOAT" => Ok(Material::BirchBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_CHEST_BOAT" => Ok(Material::BirchChestBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_BOAT" => Ok(Material::JungleBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_CHEST_BOAT" => Ok(Material::JungleChestBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_BOAT" => Ok(Material::AcaciaBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_CHEST_BOAT" => Ok(Material::AcaciaChestBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_BOAT" => Ok(Material::CherryBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_CHEST_BOAT" => Ok(Material::CherryChestBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_BOAT" => Ok(Material::DarkOakBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_CHEST_BOAT" => Ok(Material::DarkOakChestBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_BOAT" => Ok(Material::MangroveBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_CHEST_BOAT" => Ok(Material::MangroveChestBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_RAFT" => Ok(Material::BambooRaft { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_CHEST_RAFT" => Ok(Material::BambooChestRaft { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRUCTURE_BLOCK" => Ok(Material::StructureBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JIGSAW" => Ok(Material::Jigsaw { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TURTLE_HELMET" => Ok(Material::TurtleHelmet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TURTLE_SCUTE" => Ok(Material::TurtleScute { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ARMADILLO_SCUTE" => Ok(Material::ArmadilloScute { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WOLF_ARMOR" => Ok(Material::WolfArmor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FLINT_AND_STEEL" => Ok(Material::FlintAndSteel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BOWL" => Ok(Material::Bowl { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "APPLE" => Ok(Material::Apple { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BOW" => Ok(Material::Bow { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ARROW" => Ok(Material::Arrow { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COAL" => Ok(Material::Coal { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHARCOAL" => Ok(Material::Charcoal { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND" => Ok(Material::Diamond { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EMERALD" => Ok(Material::Emerald { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LAPIS_LAZULI" => Ok(Material::LapisLazuli { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "QUARTZ" => Ok(Material::Quartz { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "AMETHYST_SHARD" => Ok(Material::AmethystShard { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RAW_IRON" => Ok(Material::RawIron { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_INGOT" => Ok(Material::IronIngot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RAW_COPPER" => Ok(Material::RawCopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COPPER_INGOT" => Ok(Material::CopperIngot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RAW_GOLD" => Ok(Material::RawGold { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLD_INGOT" => Ok(Material::GoldIngot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_INGOT" => Ok(Material::NetheriteIngot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_SCRAP" => Ok(Material::NetheriteScrap { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WOODEN_SWORD" => Ok(Material::WoodenSword { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WOODEN_SHOVEL" => Ok(Material::WoodenShovel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WOODEN_PICKAXE" => Ok(Material::WoodenPickaxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WOODEN_AXE" => Ok(Material::WoodenAxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WOODEN_HOE" => Ok(Material::WoodenHoe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_SWORD" => Ok(Material::StoneSword { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_SHOVEL" => Ok(Material::StoneShovel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_PICKAXE" => Ok(Material::StonePickaxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_AXE" => Ok(Material::StoneAxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONE_HOE" => Ok(Material::StoneHoe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLDEN_SWORD" => Ok(Material::GoldenSword { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLDEN_SHOVEL" => Ok(Material::GoldenShovel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLDEN_PICKAXE" => Ok(Material::GoldenPickaxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLDEN_AXE" => Ok(Material::GoldenAxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLDEN_HOE" => Ok(Material::GoldenHoe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_SWORD" => Ok(Material::IronSword { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_SHOVEL" => Ok(Material::IronShovel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_PICKAXE" => Ok(Material::IronPickaxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_AXE" => Ok(Material::IronAxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_HOE" => Ok(Material::IronHoe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND_SWORD" => Ok(Material::DiamondSword { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND_SHOVEL" => Ok(Material::DiamondShovel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND_PICKAXE" => Ok(Material::DiamondPickaxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND_AXE" => Ok(Material::DiamondAxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND_HOE" => Ok(Material::DiamondHoe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_SWORD" => Ok(Material::NetheriteSword { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_SHOVEL" => Ok(Material::NetheriteShovel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_PICKAXE" => Ok(Material::NetheritePickaxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_AXE" => Ok(Material::NetheriteAxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_HOE" => Ok(Material::NetheriteHoe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STICK" => Ok(Material::Stick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSHROOM_STEW" => Ok(Material::MushroomStew { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRING" => Ok(Material::String { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FEATHER" => Ok(Material::Feather { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GUNPOWDER" => Ok(Material::Gunpowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHEAT_SEEDS" => Ok(Material::WheatSeeds { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHEAT" => Ok(Material::Wheat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BREAD" => Ok(Material::Bread { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEATHER_HELMET" => Ok(Material::LeatherHelmet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEATHER_CHESTPLATE" => Ok(Material::LeatherChestplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEATHER_LEGGINGS" => Ok(Material::LeatherLeggings { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEATHER_BOOTS" => Ok(Material::LeatherBoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHAINMAIL_HELMET" => Ok(Material::ChainmailHelmet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHAINMAIL_CHESTPLATE" => Ok(Material::ChainmailChestplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHAINMAIL_LEGGINGS" => Ok(Material::ChainmailLeggings { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHAINMAIL_BOOTS" => Ok(Material::ChainmailBoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_HELMET" => Ok(Material::IronHelmet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_CHESTPLATE" => Ok(Material::IronChestplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_LEGGINGS" => Ok(Material::IronLeggings { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_BOOTS" => Ok(Material::IronBoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND_HELMET" => Ok(Material::DiamondHelmet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND_CHESTPLATE" => Ok(Material::DiamondChestplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND_LEGGINGS" => Ok(Material::DiamondLeggings { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND_BOOTS" => Ok(Material::DiamondBoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLDEN_HELMET" => Ok(Material::GoldenHelmet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLDEN_CHESTPLATE" => Ok(Material::GoldenChestplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLDEN_LEGGINGS" => Ok(Material::GoldenLeggings { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLDEN_BOOTS" => Ok(Material::GoldenBoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_HELMET" => Ok(Material::NetheriteHelmet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_CHESTPLATE" => Ok(Material::NetheriteChestplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_LEGGINGS" => Ok(Material::NetheriteLeggings { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_BOOTS" => Ok(Material::NetheriteBoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FLINT" => Ok(Material::Flint { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PORKCHOP" => Ok(Material::Porkchop { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COOKED_PORKCHOP" => Ok(Material::CookedPorkchop { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PAINTING" => Ok(Material::Painting { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLDEN_APPLE" => Ok(Material::GoldenApple { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ENCHANTED_GOLDEN_APPLE" => Ok(Material::EnchantedGoldenApple { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_SIGN" => Ok(Material::OakSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_SIGN" => Ok(Material::SpruceSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_SIGN" => Ok(Material::BirchSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_SIGN" => Ok(Material::JungleSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_SIGN" => Ok(Material::AcaciaSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_SIGN" => Ok(Material::CherrySign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_SIGN" => Ok(Material::DarkOakSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_SIGN" => Ok(Material::MangroveSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_SIGN" => Ok(Material::BambooSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_SIGN" => Ok(Material::CrimsonSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_SIGN" => Ok(Material::WarpedSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_HANGING_SIGN" => Ok(Material::OakHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_HANGING_SIGN" => Ok(Material::SpruceHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_HANGING_SIGN" => Ok(Material::BirchHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_HANGING_SIGN" => Ok(Material::JungleHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_HANGING_SIGN" => Ok(Material::AcaciaHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_HANGING_SIGN" => Ok(Material::CherryHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_HANGING_SIGN" => Ok(Material::DarkOakHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_HANGING_SIGN" => Ok(Material::MangroveHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_HANGING_SIGN" => Ok(Material::BambooHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_HANGING_SIGN" => Ok(Material::CrimsonHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_HANGING_SIGN" => Ok(Material::WarpedHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BUCKET" => Ok(Material::Bucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WATER_BUCKET" => Ok(Material::WaterBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LAVA_BUCKET" => Ok(Material::LavaBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POWDER_SNOW_BUCKET" => Ok(Material::PowderSnowBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SNOWBALL" => Ok(Material::Snowball { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEATHER" => Ok(Material::Leather { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MILK_BUCKET" => Ok(Material::MilkBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PUFFERFISH_BUCKET" => Ok(Material::PufferfishBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SALMON_BUCKET" => Ok(Material::SalmonBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COD_BUCKET" => Ok(Material::CodBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TROPICAL_FISH_BUCKET" => Ok(Material::TropicalFishBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "AXOLOTL_BUCKET" => Ok(Material::AxolotlBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TADPOLE_BUCKET" => Ok(Material::TadpoleBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BRICK" => Ok(Material::Brick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CLAY_BALL" => Ok(Material::ClayBall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DRIED_KELP_BLOCK" => Ok(Material::DriedKelpBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PAPER" => Ok(Material::Paper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BOOK" => Ok(Material::Book { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SLIME_BALL" => Ok(Material::SlimeBall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EGG" => Ok(Material::Egg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COMPASS" => Ok(Material::Compass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RECOVERY_COMPASS" => Ok(Material::RecoveryCompass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BUNDLE" => Ok(Material::Bundle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FISHING_ROD" => Ok(Material::FishingRod { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CLOCK" => Ok(Material::Clock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPYGLASS" => Ok(Material::Spyglass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GLOWSTONE_DUST" => Ok(Material::GlowstoneDust { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COD" => Ok(Material::Cod { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SALMON" => Ok(Material::Salmon { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TROPICAL_FISH" => Ok(Material::TropicalFish { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PUFFERFISH" => Ok(Material::Pufferfish { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COOKED_COD" => Ok(Material::CookedCod { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COOKED_SALMON" => Ok(Material::CookedSalmon { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "INK_SAC" => Ok(Material::InkSac { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GLOW_INK_SAC" => Ok(Material::GlowInkSac { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COCOA_BEANS" => Ok(Material::CocoaBeans { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_DYE" => Ok(Material::WhiteDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_DYE" => Ok(Material::OrangeDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_DYE" => Ok(Material::MagentaDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_DYE" => Ok(Material::LightBlueDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_DYE" => Ok(Material::YellowDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_DYE" => Ok(Material::LimeDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_DYE" => Ok(Material::PinkDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_DYE" => Ok(Material::GrayDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_DYE" => Ok(Material::LightGrayDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_DYE" => Ok(Material::CyanDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_DYE" => Ok(Material::PurpleDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_DYE" => Ok(Material::BlueDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_DYE" => Ok(Material::BrownDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_DYE" => Ok(Material::GreenDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_DYE" => Ok(Material::RedDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_DYE" => Ok(Material::BlackDye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BONE_MEAL" => Ok(Material::BoneMeal { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BONE" => Ok(Material::Bone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SUGAR" => Ok(Material::Sugar { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CAKE" => Ok(Material::Cake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_BED" => Ok(Material::WhiteBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_BED" => Ok(Material::OrangeBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_BED" => Ok(Material::MagentaBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_BED" => Ok(Material::LightBlueBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_BED" => Ok(Material::YellowBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_BED" => Ok(Material::LimeBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_BED" => Ok(Material::PinkBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_BED" => Ok(Material::GrayBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_BED" => Ok(Material::LightGrayBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_BED" => Ok(Material::CyanBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_BED" => Ok(Material::PurpleBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_BED" => Ok(Material::BlueBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_BED" => Ok(Material::BrownBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_BED" => Ok(Material::GreenBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_BED" => Ok(Material::RedBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_BED" => Ok(Material::BlackBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COOKIE" => Ok(Material::Cookie { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRAFTER" => Ok(Material::Crafter { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FILLED_MAP" => Ok(Material::FilledMap { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SHEARS" => Ok(Material::Shears { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MELON_SLICE" => Ok(Material::MelonSlice { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DRIED_KELP" => Ok(Material::DriedKelp { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PUMPKIN_SEEDS" => Ok(Material::PumpkinSeeds { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MELON_SEEDS" => Ok(Material::MelonSeeds { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BEEF" => Ok(Material::Beef { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COOKED_BEEF" => Ok(Material::CookedBeef { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHICKEN" => Ok(Material::Chicken { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COOKED_CHICKEN" => Ok(Material::CookedChicken { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ROTTEN_FLESH" => Ok(Material::RottenFlesh { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ENDER_PEARL" => Ok(Material::EnderPearl { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLAZE_ROD" => Ok(Material::BlazeRod { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GHAST_TEAR" => Ok(Material::GhastTear { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLD_NUGGET" => Ok(Material::GoldNugget { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_WART" => Ok(Material::NetherWart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTION" => Ok(Material::Potion { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GLASS_BOTTLE" => Ok(Material::GlassBottle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPIDER_EYE" => Ok(Material::SpiderEye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FERMENTED_SPIDER_EYE" => Ok(Material::FermentedSpiderEye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLAZE_POWDER" => Ok(Material::BlazePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGMA_CREAM" => Ok(Material::MagmaCream { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BREWING_STAND" => Ok(Material::BrewingStand { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CAULDRON" => Ok(Material::Cauldron { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ENDER_EYE" => Ok(Material::EnderEye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GLISTERING_MELON_SLICE" => Ok(Material::GlisteringMelonSlice { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ARMADILLO_SPAWN_EGG" => Ok(Material::ArmadilloSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ALLAY_SPAWN_EGG" => Ok(Material::AllaySpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "AXOLOTL_SPAWN_EGG" => Ok(Material::AxolotlSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAT_SPAWN_EGG" => Ok(Material::BatSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BEE_SPAWN_EGG" => Ok(Material::BeeSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLAZE_SPAWN_EGG" => Ok(Material::BlazeSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BOGGED_SPAWN_EGG" => Ok(Material::BoggedSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BREEZE_SPAWN_EGG" => Ok(Material::BreezeSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CAT_SPAWN_EGG" => Ok(Material::CatSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CAMEL_SPAWN_EGG" => Ok(Material::CamelSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CAVE_SPIDER_SPAWN_EGG" => Ok(Material::CaveSpiderSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHICKEN_SPAWN_EGG" => Ok(Material::ChickenSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COD_SPAWN_EGG" => Ok(Material::CodSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COW_SPAWN_EGG" => Ok(Material::CowSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CREEPER_SPAWN_EGG" => Ok(Material::CreeperSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DOLPHIN_SPAWN_EGG" => Ok(Material::DolphinSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DONKEY_SPAWN_EGG" => Ok(Material::DonkeySpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DROWNED_SPAWN_EGG" => Ok(Material::DrownedSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ELDER_GUARDIAN_SPAWN_EGG" => Ok(Material::ElderGuardianSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ENDER_DRAGON_SPAWN_EGG" => Ok(Material::EnderDragonSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ENDERMAN_SPAWN_EGG" => Ok(Material::EndermanSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ENDERMITE_SPAWN_EGG" => Ok(Material::EndermiteSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EVOKER_SPAWN_EGG" => Ok(Material::EvokerSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FOX_SPAWN_EGG" => Ok(Material::FoxSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FROG_SPAWN_EGG" => Ok(Material::FrogSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GHAST_SPAWN_EGG" => Ok(Material::GhastSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GLOW_SQUID_SPAWN_EGG" => Ok(Material::GlowSquidSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOAT_SPAWN_EGG" => Ok(Material::GoatSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GUARDIAN_SPAWN_EGG" => Ok(Material::GuardianSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HOGLIN_SPAWN_EGG" => Ok(Material::HoglinSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HORSE_SPAWN_EGG" => Ok(Material::HorseSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HUSK_SPAWN_EGG" => Ok(Material::HuskSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_GOLEM_SPAWN_EGG" => Ok(Material::IronGolemSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LLAMA_SPAWN_EGG" => Ok(Material::LlamaSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGMA_CUBE_SPAWN_EGG" => Ok(Material::MagmaCubeSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOOSHROOM_SPAWN_EGG" => Ok(Material::MooshroomSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MULE_SPAWN_EGG" => Ok(Material::MuleSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OCELOT_SPAWN_EGG" => Ok(Material::OcelotSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PANDA_SPAWN_EGG" => Ok(Material::PandaSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PARROT_SPAWN_EGG" => Ok(Material::ParrotSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PHANTOM_SPAWN_EGG" => Ok(Material::PhantomSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PIG_SPAWN_EGG" => Ok(Material::PigSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PIGLIN_SPAWN_EGG" => Ok(Material::PiglinSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PIGLIN_BRUTE_SPAWN_EGG" => Ok(Material::PiglinBruteSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PILLAGER_SPAWN_EGG" => Ok(Material::PillagerSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLAR_BEAR_SPAWN_EGG" => Ok(Material::PolarBearSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PUFFERFISH_SPAWN_EGG" => Ok(Material::PufferfishSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RABBIT_SPAWN_EGG" => Ok(Material::RabbitSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RAVAGER_SPAWN_EGG" => Ok(Material::RavagerSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SALMON_SPAWN_EGG" => Ok(Material::SalmonSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SHEEP_SPAWN_EGG" => Ok(Material::SheepSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SHULKER_SPAWN_EGG" => Ok(Material::ShulkerSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SILVERFISH_SPAWN_EGG" => Ok(Material::SilverfishSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SKELETON_SPAWN_EGG" => Ok(Material::SkeletonSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SKELETON_HORSE_SPAWN_EGG" => Ok(Material::SkeletonHorseSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SLIME_SPAWN_EGG" => Ok(Material::SlimeSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SNIFFER_SPAWN_EGG" => Ok(Material::SnifferSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SNOW_GOLEM_SPAWN_EGG" => Ok(Material::SnowGolemSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPIDER_SPAWN_EGG" => Ok(Material::SpiderSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SQUID_SPAWN_EGG" => Ok(Material::SquidSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRAY_SPAWN_EGG" => Ok(Material::StraySpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STRIDER_SPAWN_EGG" => Ok(Material::StriderSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TADPOLE_SPAWN_EGG" => Ok(Material::TadpoleSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TRADER_LLAMA_SPAWN_EGG" => Ok(Material::TraderLlamaSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TROPICAL_FISH_SPAWN_EGG" => Ok(Material::TropicalFishSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TURTLE_SPAWN_EGG" => Ok(Material::TurtleSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "VEX_SPAWN_EGG" => Ok(Material::VexSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "VILLAGER_SPAWN_EGG" => Ok(Material::VillagerSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "VINDICATOR_SPAWN_EGG" => Ok(Material::VindicatorSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WANDERING_TRADER_SPAWN_EGG" => Ok(Material::WanderingTraderSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARDEN_SPAWN_EGG" => Ok(Material::WardenSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WITCH_SPAWN_EGG" => Ok(Material::WitchSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WITHER_SPAWN_EGG" => Ok(Material::WitherSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WITHER_SKELETON_SPAWN_EGG" => Ok(Material::WitherSkeletonSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WOLF_SPAWN_EGG" => Ok(Material::WolfSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ZOGLIN_SPAWN_EGG" => Ok(Material::ZoglinSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ZOMBIE_SPAWN_EGG" => Ok(Material::ZombieSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ZOMBIE_HORSE_SPAWN_EGG" => Ok(Material::ZombieHorseSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ZOMBIE_VILLAGER_SPAWN_EGG" => Ok(Material::ZombieVillagerSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ZOMBIFIED_PIGLIN_SPAWN_EGG" => Ok(Material::ZombifiedPiglinSpawnEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EXPERIENCE_BOTTLE" => Ok(Material::ExperienceBottle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FIRE_CHARGE" => Ok(Material::FireCharge { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WIND_CHARGE" => Ok(Material::WindCharge { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WRITABLE_BOOK" => Ok(Material::WritableBook { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WRITTEN_BOOK" => Ok(Material::WrittenBook { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MACE" => Ok(Material::Mace { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ITEM_FRAME" => Ok(Material::ItemFrame { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GLOW_ITEM_FRAME" => Ok(Material::GlowItemFrame { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FLOWER_POT" => Ok(Material::FlowerPot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CARROT" => Ok(Material::Carrot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTATO" => Ok(Material::Potato { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAKED_POTATO" => Ok(Material::BakedPotato { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POISONOUS_POTATO" => Ok(Material::PoisonousPotato { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAP" => Ok(Material::Map { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLDEN_CARROT" => Ok(Material::GoldenCarrot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SKELETON_SKULL" => Ok(Material::SkeletonSkull { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WITHER_SKELETON_SKULL" => Ok(Material::WitherSkeletonSkull { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PLAYER_HEAD" => Ok(Material::PlayerHead { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ZOMBIE_HEAD" => Ok(Material::ZombieHead { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CREEPER_HEAD" => Ok(Material::CreeperHead { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DRAGON_HEAD" => Ok(Material::DragonHead { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PIGLIN_HEAD" => Ok(Material::PiglinHead { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_STAR" => Ok(Material::NetherStar { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PUMPKIN_PIE" => Ok(Material::PumpkinPie { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FIREWORK_ROCKET" => Ok(Material::FireworkRocket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FIREWORK_STAR" => Ok(Material::FireworkStar { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ENCHANTED_BOOK" => Ok(Material::EnchantedBook { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_BRICK" => Ok(Material::NetherBrick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PRISMARINE_SHARD" => Ok(Material::PrismarineShard { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PRISMARINE_CRYSTALS" => Ok(Material::PrismarineCrystals { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RABBIT" => Ok(Material::Rabbit { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COOKED_RABBIT" => Ok(Material::CookedRabbit { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RABBIT_STEW" => Ok(Material::RabbitStew { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RABBIT_FOOT" => Ok(Material::RabbitFoot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RABBIT_HIDE" => Ok(Material::RabbitHide { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ARMOR_STAND" => Ok(Material::ArmorStand { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_HORSE_ARMOR" => Ok(Material::IronHorseArmor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOLDEN_HORSE_ARMOR" => Ok(Material::GoldenHorseArmor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DIAMOND_HORSE_ARMOR" => Ok(Material::DiamondHorseArmor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEATHER_HORSE_ARMOR" => Ok(Material::LeatherHorseArmor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEAD" => Ok(Material::Lead { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NAME_TAG" => Ok(Material::NameTag { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COMMAND_BLOCK_MINECART" => Ok(Material::CommandBlockMinecart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUTTON" => Ok(Material::Mutton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COOKED_MUTTON" => Ok(Material::CookedMutton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_BANNER" => Ok(Material::WhiteBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_BANNER" => Ok(Material::OrangeBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_BANNER" => Ok(Material::MagentaBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_BANNER" => Ok(Material::LightBlueBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_BANNER" => Ok(Material::YellowBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_BANNER" => Ok(Material::LimeBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_BANNER" => Ok(Material::PinkBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_BANNER" => Ok(Material::GrayBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_BANNER" => Ok(Material::LightGrayBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_BANNER" => Ok(Material::CyanBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_BANNER" => Ok(Material::PurpleBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_BANNER" => Ok(Material::BlueBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_BANNER" => Ok(Material::BrownBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_BANNER" => Ok(Material::GreenBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_BANNER" => Ok(Material::RedBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_BANNER" => Ok(Material::BlackBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "END_CRYSTAL" => Ok(Material::EndCrystal { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHORUS_FRUIT" => Ok(Material::ChorusFruit { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POPPED_CHORUS_FRUIT" => Ok(Material::PoppedChorusFruit { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TORCHFLOWER_SEEDS" => Ok(Material::TorchflowerSeeds { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PITCHER_POD" => Ok(Material::PitcherPod { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BEETROOT" => Ok(Material::Beetroot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BEETROOT_SEEDS" => Ok(Material::BeetrootSeeds { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BEETROOT_SOUP" => Ok(Material::BeetrootSoup { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DRAGON_BREATH" => Ok(Material::DragonBreath { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPLASH_POTION" => Ok(Material::SplashPotion { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPECTRAL_ARROW" => Ok(Material::SpectralArrow { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TIPPED_ARROW" => Ok(Material::TippedArrow { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LINGERING_POTION" => Ok(Material::LingeringPotion { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SHIELD" => Ok(Material::Shield { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TOTEM_OF_UNDYING" => Ok(Material::TotemOfUndying { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SHULKER_SHELL" => Ok(Material::ShulkerShell { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "IRON_NUGGET" => Ok(Material::IronNugget { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "KNOWLEDGE_BOOK" => Ok(Material::KnowledgeBook { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEBUG_STICK" => Ok(Material::DebugStick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_13" => Ok(Material::MusicDisc13 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_CAT" => Ok(Material::MusicDiscCat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_BLOCKS" => Ok(Material::MusicDiscBlocks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_CHIRP" => Ok(Material::MusicDiscChirp { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_CREATOR" => Ok(Material::MusicDiscCreator { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_CREATOR_MUSIC_BOX" => Ok(Material::MusicDiscCreatorMusicBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_FAR" => Ok(Material::MusicDiscFar { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_MALL" => Ok(Material::MusicDiscMall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_MELLOHI" => Ok(Material::MusicDiscMellohi { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_STAL" => Ok(Material::MusicDiscStal { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_STRAD" => Ok(Material::MusicDiscStrad { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_WARD" => Ok(Material::MusicDiscWard { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_11" => Ok(Material::MusicDisc11 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_WAIT" => Ok(Material::MusicDiscWait { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_OTHERSIDE" => Ok(Material::MusicDiscOtherside { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_RELIC" => Ok(Material::MusicDiscRelic { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_5" => Ok(Material::MusicDisc5 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_PIGSTEP" => Ok(Material::MusicDiscPigstep { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MUSIC_DISC_PRECIPICE" => Ok(Material::MusicDiscPrecipice { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DISC_FRAGMENT_5" => Ok(Material::DiscFragment5 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TRIDENT" => Ok(Material::Trident { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PHANTOM_MEMBRANE" => Ok(Material::PhantomMembrane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NAUTILUS_SHELL" => Ok(Material::NautilusShell { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HEART_OF_THE_SEA" => Ok(Material::HeartOfTheSea { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CROSSBOW" => Ok(Material::Crossbow { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SUSPICIOUS_STEW" => Ok(Material::SuspiciousStew { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LOOM" => Ok(Material::Loom { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FLOWER_BANNER_PATTERN" => Ok(Material::FlowerBannerPattern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CREEPER_BANNER_PATTERN" => Ok(Material::CreeperBannerPattern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SKULL_BANNER_PATTERN" => Ok(Material::SkullBannerPattern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOJANG_BANNER_PATTERN" => Ok(Material::MojangBannerPattern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GLOBE_BANNER_PATTERN" => Ok(Material::GlobeBannerPattern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PIGLIN_BANNER_PATTERN" => Ok(Material::PiglinBannerPattern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FLOW_BANNER_PATTERN" => Ok(Material::FlowBannerPattern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GUSTER_BANNER_PATTERN" => Ok(Material::GusterBannerPattern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GOAT_HORN" => Ok(Material::GoatHorn { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COMPOSTER" => Ok(Material::Composter { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BARREL" => Ok(Material::Barrel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMOKER" => Ok(Material::Smoker { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLAST_FURNACE" => Ok(Material::BlastFurnace { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CARTOGRAPHY_TABLE" => Ok(Material::CartographyTable { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FLETCHING_TABLE" => Ok(Material::FletchingTable { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRINDSTONE" => Ok(Material::Grindstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMITHING_TABLE" => Ok(Material::SmithingTable { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "STONECUTTER" => Ok(Material::Stonecutter { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BELL" => Ok(Material::Bell { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LANTERN" => Ok(Material::Lantern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SOUL_LANTERN" => Ok(Material::SoulLantern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SWEET_BERRIES" => Ok(Material::SweetBerries { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GLOW_BERRIES" => Ok(Material::GlowBerries { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CAMPFIRE" => Ok(Material::Campfire { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SOUL_CAMPFIRE" => Ok(Material::SoulCampfire { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SHROOMLIGHT" => Ok(Material::Shroomlight { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HONEYCOMB" => Ok(Material::Honeycomb { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BEE_NEST" => Ok(Material::BeeNest { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BEEHIVE" => Ok(Material::Beehive { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HONEY_BOTTLE" => Ok(Material::HoneyBottle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HONEYCOMB_BLOCK" => Ok(Material::HoneycombBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LODESTONE" => Ok(Material::Lodestone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRYING_OBSIDIAN" => Ok(Material::CryingObsidian { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACKSTONE" => Ok(Material::Blackstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACKSTONE_SLAB" => Ok(Material::BlackstoneSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACKSTONE_STAIRS" => Ok(Material::BlackstoneStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GILDED_BLACKSTONE" => Ok(Material::GildedBlackstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_BLACKSTONE" => Ok(Material::PolishedBlackstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_BLACKSTONE_SLAB" => Ok(Material::PolishedBlackstoneSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_BLACKSTONE_STAIRS" => Ok(Material::PolishedBlackstoneStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHISELED_POLISHED_BLACKSTONE" => Ok(Material::ChiseledPolishedBlackstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_BLACKSTONE_BRICKS" => Ok(Material::PolishedBlackstoneBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_BLACKSTONE_BRICK_SLAB" => Ok(Material::PolishedBlackstoneBrickSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POLISHED_BLACKSTONE_BRICK_STAIRS" => Ok(Material::PolishedBlackstoneBrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRACKED_POLISHED_BLACKSTONE_BRICKS" => { + Ok(Material::CrackedPolishedBlackstoneBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "RESPAWN_ANCHOR" => Ok(Material::RespawnAnchor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CANDLE" => Ok(Material::Candle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_CANDLE" => Ok(Material::WhiteCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_CANDLE" => Ok(Material::OrangeCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_CANDLE" => Ok(Material::MagentaCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_CANDLE" => Ok(Material::LightBlueCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_CANDLE" => Ok(Material::YellowCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_CANDLE" => Ok(Material::LimeCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_CANDLE" => Ok(Material::PinkCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_CANDLE" => Ok(Material::GrayCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_CANDLE" => Ok(Material::LightGrayCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_CANDLE" => Ok(Material::CyanCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_CANDLE" => Ok(Material::PurpleCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_CANDLE" => Ok(Material::BlueCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_CANDLE" => Ok(Material::BrownCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_CANDLE" => Ok(Material::GreenCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_CANDLE" => Ok(Material::RedCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_CANDLE" => Ok(Material::BlackCandle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SMALL_AMETHYST_BUD" => Ok(Material::SmallAmethystBud { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MEDIUM_AMETHYST_BUD" => Ok(Material::MediumAmethystBud { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LARGE_AMETHYST_BUD" => Ok(Material::LargeAmethystBud { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "AMETHYST_CLUSTER" => Ok(Material::AmethystCluster { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POINTED_DRIPSTONE" => Ok(Material::PointedDripstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OCHRE_FROGLIGHT" => Ok(Material::OchreFroglight { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "VERDANT_FROGLIGHT" => Ok(Material::VerdantFroglight { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PEARLESCENT_FROGLIGHT" => Ok(Material::PearlescentFroglight { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FROGSPAWN" => Ok(Material::Frogspawn { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ECHO_SHARD" => Ok(Material::EchoShard { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BRUSH" => Ok(Material::Brush { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHERITE_UPGRADE_SMITHING_TEMPLATE" => { + Ok(Material::NetheriteUpgradeSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "SENTRY_ARMOR_TRIM_SMITHING_TEMPLATE" => { + Ok(Material::SentryArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "DUNE_ARMOR_TRIM_SMITHING_TEMPLATE" => { + Ok(Material::DuneArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "COAST_ARMOR_TRIM_SMITHING_TEMPLATE" => { + Ok(Material::CoastArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "WILD_ARMOR_TRIM_SMITHING_TEMPLATE" => { + Ok(Material::WildArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "WARD_ARMOR_TRIM_SMITHING_TEMPLATE" => { + Ok(Material::WardArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "EYE_ARMOR_TRIM_SMITHING_TEMPLATE" => Ok(Material::EyeArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "VEX_ARMOR_TRIM_SMITHING_TEMPLATE" => Ok(Material::VexArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TIDE_ARMOR_TRIM_SMITHING_TEMPLATE" => { + Ok(Material::TideArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "SNOUT_ARMOR_TRIM_SMITHING_TEMPLATE" => { + Ok(Material::SnoutArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "RIB_ARMOR_TRIM_SMITHING_TEMPLATE" => Ok(Material::RibArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPIRE_ARMOR_TRIM_SMITHING_TEMPLATE" => { + Ok(Material::SpireArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "WAYFINDER_ARMOR_TRIM_SMITHING_TEMPLATE" => { + Ok(Material::WayfinderArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "SHAPER_ARMOR_TRIM_SMITHING_TEMPLATE" => { + Ok(Material::ShaperArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "SILENCE_ARMOR_TRIM_SMITHING_TEMPLATE" => { + Ok(Material::SilenceArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "RAISER_ARMOR_TRIM_SMITHING_TEMPLATE" => { + Ok(Material::RaiserArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "HOST_ARMOR_TRIM_SMITHING_TEMPLATE" => { + Ok(Material::HostArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "FLOW_ARMOR_TRIM_SMITHING_TEMPLATE" => { + Ok(Material::FlowArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "BOLT_ARMOR_TRIM_SMITHING_TEMPLATE" => { + Ok(Material::BoltArmorTrimSmithingTemplate { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "ANGLER_POTTERY_SHERD" => Ok(Material::AnglerPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ARCHER_POTTERY_SHERD" => Ok(Material::ArcherPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ARMS_UP_POTTERY_SHERD" => Ok(Material::ArmsUpPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLADE_POTTERY_SHERD" => Ok(Material::BladePotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BREWER_POTTERY_SHERD" => Ok(Material::BrewerPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BURN_POTTERY_SHERD" => Ok(Material::BurnPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DANGER_POTTERY_SHERD" => Ok(Material::DangerPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EXPLORER_POTTERY_SHERD" => Ok(Material::ExplorerPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FLOW_POTTERY_SHERD" => Ok(Material::FlowPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FRIEND_POTTERY_SHERD" => Ok(Material::FriendPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GUSTER_POTTERY_SHERD" => Ok(Material::GusterPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HEART_POTTERY_SHERD" => Ok(Material::HeartPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HEARTBREAK_POTTERY_SHERD" => Ok(Material::HeartbreakPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HOWL_POTTERY_SHERD" => Ok(Material::HowlPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MINER_POTTERY_SHERD" => Ok(Material::MinerPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOURNER_POTTERY_SHERD" => Ok(Material::MournerPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PLENTY_POTTERY_SHERD" => Ok(Material::PlentyPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PRIZE_POTTERY_SHERD" => Ok(Material::PrizePotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SCRAPE_POTTERY_SHERD" => Ok(Material::ScrapePotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SHEAF_POTTERY_SHERD" => Ok(Material::SheafPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SHELTER_POTTERY_SHERD" => Ok(Material::ShelterPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SKULL_POTTERY_SHERD" => Ok(Material::SkullPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SNORT_POTTERY_SHERD" => Ok(Material::SnortPotterySherd { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COPPER_GRATE" => Ok(Material::CopperGrate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EXPOSED_COPPER_GRATE" => Ok(Material::ExposedCopperGrate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WEATHERED_COPPER_GRATE" => Ok(Material::WeatheredCopperGrate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OXIDIZED_COPPER_GRATE" => Ok(Material::OxidizedCopperGrate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_COPPER_GRATE" => Ok(Material::WaxedCopperGrate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_EXPOSED_COPPER_GRATE" => Ok(Material::WaxedExposedCopperGrate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_WEATHERED_COPPER_GRATE" => Ok(Material::WaxedWeatheredCopperGrate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_OXIDIZED_COPPER_GRATE" => Ok(Material::WaxedOxidizedCopperGrate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COPPER_BULB" => Ok(Material::CopperBulb { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "EXPOSED_COPPER_BULB" => Ok(Material::ExposedCopperBulb { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WEATHERED_COPPER_BULB" => Ok(Material::WeatheredCopperBulb { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OXIDIZED_COPPER_BULB" => Ok(Material::OxidizedCopperBulb { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_COPPER_BULB" => Ok(Material::WaxedCopperBulb { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_EXPOSED_COPPER_BULB" => Ok(Material::WaxedExposedCopperBulb { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_WEATHERED_COPPER_BULB" => Ok(Material::WaxedWeatheredCopperBulb { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WAXED_OXIDIZED_COPPER_BULB" => Ok(Material::WaxedOxidizedCopperBulb { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TRIAL_SPAWNER" => Ok(Material::TrialSpawner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TRIAL_KEY" => Ok(Material::TrialKey { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OMINOUS_TRIAL_KEY" => Ok(Material::OminousTrialKey { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "VAULT" => Ok(Material::Vault { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OMINOUS_BOTTLE" => Ok(Material::OminousBottle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BREEZE_ROD" => Ok(Material::BreezeRod { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WATER" => Ok(Material::Water { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LAVA" => Ok(Material::Lava { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TALL_SEAGRASS" => Ok(Material::TallSeagrass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PISTON_HEAD" => Ok(Material::PistonHead { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MOVING_PISTON" => Ok(Material::MovingPiston { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WALL_TORCH" => Ok(Material::WallTorch { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FIRE" => Ok(Material::Fire { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SOUL_FIRE" => Ok(Material::SoulFire { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "REDSTONE_WIRE" => Ok(Material::RedstoneWire { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_WALL_SIGN" => Ok(Material::OakWallSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_WALL_SIGN" => Ok(Material::SpruceWallSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_WALL_SIGN" => Ok(Material::BirchWallSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_WALL_SIGN" => Ok(Material::AcaciaWallSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_WALL_SIGN" => Ok(Material::CherryWallSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_WALL_SIGN" => Ok(Material::JungleWallSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_WALL_SIGN" => Ok(Material::DarkOakWallSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_WALL_SIGN" => Ok(Material::MangroveWallSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_WALL_SIGN" => Ok(Material::BambooWallSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "OAK_WALL_HANGING_SIGN" => Ok(Material::OakWallHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SPRUCE_WALL_HANGING_SIGN" => Ok(Material::SpruceWallHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIRCH_WALL_HANGING_SIGN" => Ok(Material::BirchWallHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ACACIA_WALL_HANGING_SIGN" => Ok(Material::AcaciaWallHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CHERRY_WALL_HANGING_SIGN" => Ok(Material::CherryWallHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "JUNGLE_WALL_HANGING_SIGN" => Ok(Material::JungleWallHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DARK_OAK_WALL_HANGING_SIGN" => Ok(Material::DarkOakWallHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MANGROVE_WALL_HANGING_SIGN" => Ok(Material::MangroveWallHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_WALL_HANGING_SIGN" => Ok(Material::CrimsonWallHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_WALL_HANGING_SIGN" => Ok(Material::WarpedWallHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_WALL_HANGING_SIGN" => Ok(Material::BambooWallHangingSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "REDSTONE_WALL_TORCH" => Ok(Material::RedstoneWallTorch { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SOUL_WALL_TORCH" => Ok(Material::SoulWallTorch { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "NETHER_PORTAL" => Ok(Material::NetherPortal { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ATTACHED_PUMPKIN_STEM" => Ok(Material::AttachedPumpkinStem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ATTACHED_MELON_STEM" => Ok(Material::AttachedMelonStem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PUMPKIN_STEM" => Ok(Material::PumpkinStem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MELON_STEM" => Ok(Material::MelonStem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WATER_CAULDRON" => Ok(Material::WaterCauldron { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LAVA_CAULDRON" => Ok(Material::LavaCauldron { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POWDER_SNOW_CAULDRON" => Ok(Material::PowderSnowCauldron { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "END_PORTAL" => Ok(Material::EndPortal { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "COCOA" => Ok(Material::Cocoa { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TRIPWIRE" => Ok(Material::Tripwire { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_TORCHFLOWER" => Ok(Material::PottedTorchflower { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_OAK_SAPLING" => Ok(Material::PottedOakSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_SPRUCE_SAPLING" => Ok(Material::PottedSpruceSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_BIRCH_SAPLING" => Ok(Material::PottedBirchSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_JUNGLE_SAPLING" => Ok(Material::PottedJungleSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_ACACIA_SAPLING" => Ok(Material::PottedAcaciaSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_CHERRY_SAPLING" => Ok(Material::PottedCherrySapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_DARK_OAK_SAPLING" => Ok(Material::PottedDarkOakSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_MANGROVE_PROPAGULE" => Ok(Material::PottedMangrovePropagule { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_FERN" => Ok(Material::PottedFern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_DANDELION" => Ok(Material::PottedDandelion { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_POPPY" => Ok(Material::PottedPoppy { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_BLUE_ORCHID" => Ok(Material::PottedBlueOrchid { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_ALLIUM" => Ok(Material::PottedAllium { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_AZURE_BLUET" => Ok(Material::PottedAzureBluet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_RED_TULIP" => Ok(Material::PottedRedTulip { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_ORANGE_TULIP" => Ok(Material::PottedOrangeTulip { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_WHITE_TULIP" => Ok(Material::PottedWhiteTulip { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_PINK_TULIP" => Ok(Material::PottedPinkTulip { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_OXEYE_DAISY" => Ok(Material::PottedOxeyeDaisy { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_CORNFLOWER" => Ok(Material::PottedCornflower { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_LILY_OF_THE_VALLEY" => Ok(Material::PottedLilyOfTheValley { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_WITHER_ROSE" => Ok(Material::PottedWitherRose { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_RED_MUSHROOM" => Ok(Material::PottedRedMushroom { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_BROWN_MUSHROOM" => Ok(Material::PottedBrownMushroom { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_DEAD_BUSH" => Ok(Material::PottedDeadBush { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_CACTUS" => Ok(Material::PottedCactus { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CARROTS" => Ok(Material::Carrots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTATOES" => Ok(Material::Potatoes { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SKELETON_WALL_SKULL" => Ok(Material::SkeletonWallSkull { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WITHER_SKELETON_WALL_SKULL" => Ok(Material::WitherSkeletonWallSkull { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ZOMBIE_WALL_HEAD" => Ok(Material::ZombieWallHead { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PLAYER_WALL_HEAD" => Ok(Material::PlayerWallHead { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CREEPER_WALL_HEAD" => Ok(Material::CreeperWallHead { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DRAGON_WALL_HEAD" => Ok(Material::DragonWallHead { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PIGLIN_WALL_HEAD" => Ok(Material::PiglinWallHead { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_WALL_BANNER" => Ok(Material::WhiteWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_WALL_BANNER" => Ok(Material::OrangeWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_WALL_BANNER" => Ok(Material::MagentaWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_WALL_BANNER" => Ok(Material::LightBlueWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_WALL_BANNER" => Ok(Material::YellowWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_WALL_BANNER" => Ok(Material::LimeWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_WALL_BANNER" => Ok(Material::PinkWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_WALL_BANNER" => Ok(Material::GrayWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_WALL_BANNER" => Ok(Material::LightGrayWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_WALL_BANNER" => Ok(Material::CyanWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_WALL_BANNER" => Ok(Material::PurpleWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_WALL_BANNER" => Ok(Material::BlueWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_WALL_BANNER" => Ok(Material::BrownWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_WALL_BANNER" => Ok(Material::GreenWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_WALL_BANNER" => Ok(Material::RedWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_WALL_BANNER" => Ok(Material::BlackWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TORCHFLOWER_CROP" => Ok(Material::TorchflowerCrop { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PITCHER_CROP" => Ok(Material::PitcherCrop { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BEETROOTS" => Ok(Material::Beetroots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "END_GATEWAY" => Ok(Material::EndGateway { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FROSTED_ICE" => Ok(Material::FrostedIce { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "KELP_PLANT" => Ok(Material::KelpPlant { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_TUBE_CORAL_WALL_FAN" => Ok(Material::DeadTubeCoralWallFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_BRAIN_CORAL_WALL_FAN" => Ok(Material::DeadBrainCoralWallFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_BUBBLE_CORAL_WALL_FAN" => Ok(Material::DeadBubbleCoralWallFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_FIRE_CORAL_WALL_FAN" => Ok(Material::DeadFireCoralWallFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "DEAD_HORN_CORAL_WALL_FAN" => Ok(Material::DeadHornCoralWallFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TUBE_CORAL_WALL_FAN" => Ok(Material::TubeCoralWallFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BRAIN_CORAL_WALL_FAN" => Ok(Material::BrainCoralWallFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BUBBLE_CORAL_WALL_FAN" => Ok(Material::BubbleCoralWallFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "FIRE_CORAL_WALL_FAN" => Ok(Material::FireCoralWallFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "HORN_CORAL_WALL_FAN" => Ok(Material::HornCoralWallFan { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BAMBOO_SAPLING" => Ok(Material::BambooSapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_BAMBOO" => Ok(Material::PottedBamboo { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "VOID_AIR" => Ok(Material::VoidAir { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CAVE_AIR" => Ok(Material::CaveAir { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BUBBLE_COLUMN" => Ok(Material::BubbleColumn { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "SWEET_BERRY_BUSH" => Ok(Material::SweetBerryBush { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WEEPING_VINES_PLANT" => Ok(Material::WeepingVinesPlant { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "TWISTING_VINES_PLANT" => Ok(Material::TwistingVinesPlant { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CRIMSON_WALL_SIGN" => Ok(Material::CrimsonWallSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WARPED_WALL_SIGN" => Ok(Material::WarpedWallSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_CRIMSON_FUNGUS" => Ok(Material::PottedCrimsonFungus { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_WARPED_FUNGUS" => Ok(Material::PottedWarpedFungus { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_CRIMSON_ROOTS" => Ok(Material::PottedCrimsonRoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_WARPED_ROOTS" => Ok(Material::PottedWarpedRoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CANDLE_CAKE" => Ok(Material::CandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "WHITE_CANDLE_CAKE" => Ok(Material::WhiteCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "ORANGE_CANDLE_CAKE" => Ok(Material::OrangeCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "MAGENTA_CANDLE_CAKE" => Ok(Material::MagentaCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE_CANDLE_CAKE" => Ok(Material::LightBlueCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "YELLOW_CANDLE_CAKE" => Ok(Material::YellowCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIME_CANDLE_CAKE" => Ok(Material::LimeCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PINK_CANDLE_CAKE" => Ok(Material::PinkCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GRAY_CANDLE_CAKE" => Ok(Material::GrayCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY_CANDLE_CAKE" => Ok(Material::LightGrayCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CYAN_CANDLE_CAKE" => Ok(Material::CyanCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "PURPLE_CANDLE_CAKE" => Ok(Material::PurpleCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLUE_CANDLE_CAKE" => Ok(Material::BlueCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BROWN_CANDLE_CAKE" => Ok(Material::BrownCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "GREEN_CANDLE_CAKE" => Ok(Material::GreenCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "RED_CANDLE_CAKE" => Ok(Material::RedCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BLACK_CANDLE_CAKE" => Ok(Material::BlackCandleCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POWDER_SNOW" => Ok(Material::PowderSnow { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CAVE_VINES" => Ok(Material::CaveVines { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "CAVE_VINES_PLANT" => Ok(Material::CaveVinesPlant { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "BIG_DRIPLEAF_STEM" => Ok(Material::BigDripleafStem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_AZALEA_BUSH" => Ok(Material::PottedAzaleaBush { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "POTTED_FLOWERING_AZALEA_BUSH" => Ok(Material::PottedFloweringAzaleaBush { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_AIR" => Ok(Material::LegacyAir { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STONE" => Ok(Material::LegacyStone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GRASS" => Ok(Material::LegacyGrass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIRT" => Ok(Material::LegacyDirt { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COBBLESTONE" => Ok(Material::LegacyCobblestone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOD" => Ok(Material::LegacyWood { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SAPLING" => Ok(Material::LegacySapling { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BEDROCK" => Ok(Material::LegacyBedrock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WATER" => Ok(Material::LegacyWater { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STATIONARY_WATER" => Ok(Material::LegacyStationaryWater { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LAVA" => Ok(Material::LegacyLava { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STATIONARY_LAVA" => Ok(Material::LegacyStationaryLava { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SAND" => Ok(Material::LegacySand { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GRAVEL" => Ok(Material::LegacyGravel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_ORE" => Ok(Material::LegacyGoldOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_ORE" => Ok(Material::LegacyIronOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COAL_ORE" => Ok(Material::LegacyCoalOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LOG" => Ok(Material::LegacyLog { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LEAVES" => Ok(Material::LegacyLeaves { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SPONGE" => Ok(Material::LegacySponge { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GLASS" => Ok(Material::LegacyGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LAPIS_ORE" => Ok(Material::LegacyLapisOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LAPIS_BLOCK" => Ok(Material::LegacyLapisBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DISPENSER" => Ok(Material::LegacyDispenser { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SANDSTONE" => Ok(Material::LegacySandstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_NOTE_BLOCK" => Ok(Material::LegacyNoteBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BED_BLOCK" => Ok(Material::LegacyBedBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_POWERED_RAIL" => Ok(Material::LegacyPoweredRail { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DETECTOR_RAIL" => Ok(Material::LegacyDetectorRail { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PISTON_STICKY_BASE" => Ok(Material::LegacyPistonStickyBase { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WEB" => Ok(Material::LegacyWeb { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LONG_GRASS" => Ok(Material::LegacyLongGrass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DEAD_BUSH" => Ok(Material::LegacyDeadBush { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PISTON_BASE" => Ok(Material::LegacyPistonBase { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PISTON_EXTENSION" => Ok(Material::LegacyPistonExtension { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOL" => Ok(Material::LegacyWool { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PISTON_MOVING_PIECE" => Ok(Material::LegacyPistonMovingPiece { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_YELLOW_FLOWER" => Ok(Material::LegacyYellowFlower { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RED_ROSE" => Ok(Material::LegacyRedRose { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BROWN_MUSHROOM" => Ok(Material::LegacyBrownMushroom { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RED_MUSHROOM" => Ok(Material::LegacyRedMushroom { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_BLOCK" => Ok(Material::LegacyGoldBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_BLOCK" => Ok(Material::LegacyIronBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DOUBLE_STEP" => Ok(Material::LegacyDoubleStep { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STEP" => Ok(Material::LegacyStep { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BRICK" => Ok(Material::LegacyBrick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_TNT" => Ok(Material::LegacyTnt { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BOOKSHELF" => Ok(Material::LegacyBookshelf { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MOSSY_COBBLESTONE" => Ok(Material::LegacyMossyCobblestone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_OBSIDIAN" => Ok(Material::LegacyObsidian { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_TORCH" => Ok(Material::LegacyTorch { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FIRE" => Ok(Material::LegacyFire { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MOB_SPAWNER" => Ok(Material::LegacyMobSpawner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOD_STAIRS" => Ok(Material::LegacyWoodStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CHEST" => Ok(Material::LegacyChest { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_REDSTONE_WIRE" => Ok(Material::LegacyRedstoneWire { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND_ORE" => Ok(Material::LegacyDiamondOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND_BLOCK" => Ok(Material::LegacyDiamondBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WORKBENCH" => Ok(Material::LegacyWorkbench { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CROPS" => Ok(Material::LegacyCrops { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SOIL" => Ok(Material::LegacySoil { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FURNACE" => Ok(Material::LegacyFurnace { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BURNING_FURNACE" => Ok(Material::LegacyBurningFurnace { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SIGN_POST" => Ok(Material::LegacySignPost { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOODEN_DOOR" => Ok(Material::LegacyWoodenDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LADDER" => Ok(Material::LegacyLadder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RAILS" => Ok(Material::LegacyRails { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COBBLESTONE_STAIRS" => Ok(Material::LegacyCobblestoneStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WALL_SIGN" => Ok(Material::LegacyWallSign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LEVER" => Ok(Material::LegacyLever { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STONE_PLATE" => Ok(Material::LegacyStonePlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_DOOR_BLOCK" => Ok(Material::LegacyIronDoorBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOD_PLATE" => Ok(Material::LegacyWoodPlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_REDSTONE_ORE" => Ok(Material::LegacyRedstoneOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GLOWING_REDSTONE_ORE" => Ok(Material::LegacyGlowingRedstoneOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_REDSTONE_TORCH_OFF" => Ok(Material::LegacyRedstoneTorchOff { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_REDSTONE_TORCH_ON" => Ok(Material::LegacyRedstoneTorchOn { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STONE_BUTTON" => Ok(Material::LegacyStoneButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SNOW" => Ok(Material::LegacySnow { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ICE" => Ok(Material::LegacyIce { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SNOW_BLOCK" => Ok(Material::LegacySnowBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CACTUS" => Ok(Material::LegacyCactus { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CLAY" => Ok(Material::LegacyClay { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SUGAR_CANE_BLOCK" => Ok(Material::LegacySugarCaneBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_JUKEBOX" => Ok(Material::LegacyJukebox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FENCE" => Ok(Material::LegacyFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PUMPKIN" => Ok(Material::LegacyPumpkin { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_NETHERRACK" => Ok(Material::LegacyNetherrack { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SOUL_SAND" => Ok(Material::LegacySoulSand { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GLOWSTONE" => Ok(Material::LegacyGlowstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PORTAL" => Ok(Material::LegacyPortal { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_JACK_O_LANTERN" => Ok(Material::LegacyJackOLantern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CAKE_BLOCK" => Ok(Material::LegacyCakeBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIODE_BLOCK_OFF" => Ok(Material::LegacyDiodeBlockOff { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIODE_BLOCK_ON" => Ok(Material::LegacyDiodeBlockOn { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STAINED_GLASS" => Ok(Material::LegacyStainedGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_TRAP_DOOR" => Ok(Material::LegacyTrapDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MONSTER_EGGS" => Ok(Material::LegacyMonsterEggs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SMOOTH_BRICK" => Ok(Material::LegacySmoothBrick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_HUGE_MUSHROOM_1" => Ok(Material::LegacyHugeMushroom1 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_HUGE_MUSHROOM_2" => Ok(Material::LegacyHugeMushroom2 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_FENCE" => Ok(Material::LegacyIronFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_THIN_GLASS" => Ok(Material::LegacyThinGlass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MELON_BLOCK" => Ok(Material::LegacyMelonBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PUMPKIN_STEM" => Ok(Material::LegacyPumpkinStem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MELON_STEM" => Ok(Material::LegacyMelonStem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_VINE" => Ok(Material::LegacyVine { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FENCE_GATE" => Ok(Material::LegacyFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BRICK_STAIRS" => Ok(Material::LegacyBrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SMOOTH_STAIRS" => Ok(Material::LegacySmoothStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MYCEL" => Ok(Material::LegacyMycel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WATER_LILY" => Ok(Material::LegacyWaterLily { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_NETHER_BRICK" => Ok(Material::LegacyNetherBrick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_NETHER_FENCE" => Ok(Material::LegacyNetherFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_NETHER_BRICK_STAIRS" => Ok(Material::LegacyNetherBrickStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_NETHER_WARTS" => Ok(Material::LegacyNetherWarts { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ENCHANTMENT_TABLE" => Ok(Material::LegacyEnchantmentTable { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BREWING_STAND" => Ok(Material::LegacyBrewingStand { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CAULDRON" => Ok(Material::LegacyCauldron { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ENDER_PORTAL" => Ok(Material::LegacyEnderPortal { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ENDER_PORTAL_FRAME" => Ok(Material::LegacyEnderPortalFrame { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ENDER_STONE" => Ok(Material::LegacyEnderStone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DRAGON_EGG" => Ok(Material::LegacyDragonEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_REDSTONE_LAMP_OFF" => Ok(Material::LegacyRedstoneLampOff { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_REDSTONE_LAMP_ON" => Ok(Material::LegacyRedstoneLampOn { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOD_DOUBLE_STEP" => Ok(Material::LegacyWoodDoubleStep { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOD_STEP" => Ok(Material::LegacyWoodStep { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COCOA" => Ok(Material::LegacyCocoa { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SANDSTONE_STAIRS" => Ok(Material::LegacySandstoneStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_EMERALD_ORE" => Ok(Material::LegacyEmeraldOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ENDER_CHEST" => Ok(Material::LegacyEnderChest { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_TRIPWIRE_HOOK" => Ok(Material::LegacyTripwireHook { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_TRIPWIRE" => Ok(Material::LegacyTripwire { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_EMERALD_BLOCK" => Ok(Material::LegacyEmeraldBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SPRUCE_WOOD_STAIRS" => Ok(Material::LegacySpruceWoodStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BIRCH_WOOD_STAIRS" => Ok(Material::LegacyBirchWoodStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_JUNGLE_WOOD_STAIRS" => Ok(Material::LegacyJungleWoodStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COMMAND" => Ok(Material::LegacyCommand { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BEACON" => Ok(Material::LegacyBeacon { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COBBLE_WALL" => Ok(Material::LegacyCobbleWall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FLOWER_POT" => Ok(Material::LegacyFlowerPot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CARROT" => Ok(Material::LegacyCarrot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_POTATO" => Ok(Material::LegacyPotato { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOD_BUTTON" => Ok(Material::LegacyWoodButton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SKULL" => Ok(Material::LegacySkull { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ANVIL" => Ok(Material::LegacyAnvil { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_TRAPPED_CHEST" => Ok(Material::LegacyTrappedChest { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_PLATE" => Ok(Material::LegacyGoldPlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_PLATE" => Ok(Material::LegacyIronPlate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_REDSTONE_COMPARATOR_OFF" => Ok(Material::LegacyRedstoneComparatorOff { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_REDSTONE_COMPARATOR_ON" => Ok(Material::LegacyRedstoneComparatorOn { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DAYLIGHT_DETECTOR" => Ok(Material::LegacyDaylightDetector { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_REDSTONE_BLOCK" => Ok(Material::LegacyRedstoneBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_QUARTZ_ORE" => Ok(Material::LegacyQuartzOre { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_HOPPER" => Ok(Material::LegacyHopper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_QUARTZ_BLOCK" => Ok(Material::LegacyQuartzBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_QUARTZ_STAIRS" => Ok(Material::LegacyQuartzStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ACTIVATOR_RAIL" => Ok(Material::LegacyActivatorRail { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DROPPER" => Ok(Material::LegacyDropper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STAINED_CLAY" => Ok(Material::LegacyStainedClay { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STAINED_GLASS_PANE" => Ok(Material::LegacyStainedGlassPane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LEAVES_2" => Ok(Material::LegacyLeaves2 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LOG_2" => Ok(Material::LegacyLog2 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ACACIA_STAIRS" => Ok(Material::LegacyAcaciaStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DARK_OAK_STAIRS" => Ok(Material::LegacyDarkOakStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SLIME_BLOCK" => Ok(Material::LegacySlimeBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BARRIER" => Ok(Material::LegacyBarrier { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_TRAPDOOR" => Ok(Material::LegacyIronTrapdoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PRISMARINE" => Ok(Material::LegacyPrismarine { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SEA_LANTERN" => Ok(Material::LegacySeaLantern { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_HAY_BLOCK" => Ok(Material::LegacyHayBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CARPET" => Ok(Material::LegacyCarpet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_HARD_CLAY" => Ok(Material::LegacyHardClay { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COAL_BLOCK" => Ok(Material::LegacyCoalBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PACKED_ICE" => Ok(Material::LegacyPackedIce { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DOUBLE_PLANT" => Ok(Material::LegacyDoublePlant { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STANDING_BANNER" => Ok(Material::LegacyStandingBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WALL_BANNER" => Ok(Material::LegacyWallBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DAYLIGHT_DETECTOR_INVERTED" => { + Ok(Material::LegacyDaylightDetectorInverted { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "LEGACY_RED_SANDSTONE" => Ok(Material::LegacyRedSandstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RED_SANDSTONE_STAIRS" => Ok(Material::LegacyRedSandstoneStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DOUBLE_STONE_SLAB2" => Ok(Material::LegacyDoubleStoneSlab2 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STONE_SLAB2" => Ok(Material::LegacyStoneSlab2 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SPRUCE_FENCE_GATE" => Ok(Material::LegacySpruceFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BIRCH_FENCE_GATE" => Ok(Material::LegacyBirchFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_JUNGLE_FENCE_GATE" => Ok(Material::LegacyJungleFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DARK_OAK_FENCE_GATE" => Ok(Material::LegacyDarkOakFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ACACIA_FENCE_GATE" => Ok(Material::LegacyAcaciaFenceGate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SPRUCE_FENCE" => Ok(Material::LegacySpruceFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BIRCH_FENCE" => Ok(Material::LegacyBirchFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_JUNGLE_FENCE" => Ok(Material::LegacyJungleFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DARK_OAK_FENCE" => Ok(Material::LegacyDarkOakFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ACACIA_FENCE" => Ok(Material::LegacyAcaciaFence { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SPRUCE_DOOR" => Ok(Material::LegacySpruceDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BIRCH_DOOR" => Ok(Material::LegacyBirchDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_JUNGLE_DOOR" => Ok(Material::LegacyJungleDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ACACIA_DOOR" => Ok(Material::LegacyAcaciaDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DARK_OAK_DOOR" => Ok(Material::LegacyDarkOakDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_END_ROD" => Ok(Material::LegacyEndRod { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CHORUS_PLANT" => Ok(Material::LegacyChorusPlant { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CHORUS_FLOWER" => Ok(Material::LegacyChorusFlower { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PURPUR_BLOCK" => Ok(Material::LegacyPurpurBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PURPUR_PILLAR" => Ok(Material::LegacyPurpurPillar { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PURPUR_STAIRS" => Ok(Material::LegacyPurpurStairs { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PURPUR_DOUBLE_SLAB" => Ok(Material::LegacyPurpurDoubleSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PURPUR_SLAB" => Ok(Material::LegacyPurpurSlab { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_END_BRICKS" => Ok(Material::LegacyEndBricks { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BEETROOT_BLOCK" => Ok(Material::LegacyBeetrootBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GRASS_PATH" => Ok(Material::LegacyGrassPath { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_END_GATEWAY" => Ok(Material::LegacyEndGateway { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COMMAND_REPEATING" => Ok(Material::LegacyCommandRepeating { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COMMAND_CHAIN" => Ok(Material::LegacyCommandChain { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FROSTED_ICE" => Ok(Material::LegacyFrostedIce { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MAGMA" => Ok(Material::LegacyMagma { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_NETHER_WART_BLOCK" => Ok(Material::LegacyNetherWartBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RED_NETHER_BRICK" => Ok(Material::LegacyRedNetherBrick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BONE_BLOCK" => Ok(Material::LegacyBoneBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STRUCTURE_VOID" => Ok(Material::LegacyStructureVoid { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_OBSERVER" => Ok(Material::LegacyObserver { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WHITE_SHULKER_BOX" => Ok(Material::LegacyWhiteShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ORANGE_SHULKER_BOX" => Ok(Material::LegacyOrangeShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MAGENTA_SHULKER_BOX" => Ok(Material::LegacyMagentaShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LIGHT_BLUE_SHULKER_BOX" => Ok(Material::LegacyLightBlueShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_YELLOW_SHULKER_BOX" => Ok(Material::LegacyYellowShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LIME_SHULKER_BOX" => Ok(Material::LegacyLimeShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PINK_SHULKER_BOX" => Ok(Material::LegacyPinkShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GRAY_SHULKER_BOX" => Ok(Material::LegacyGrayShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SILVER_SHULKER_BOX" => Ok(Material::LegacySilverShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CYAN_SHULKER_BOX" => Ok(Material::LegacyCyanShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PURPLE_SHULKER_BOX" => Ok(Material::LegacyPurpleShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BLUE_SHULKER_BOX" => Ok(Material::LegacyBlueShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BROWN_SHULKER_BOX" => Ok(Material::LegacyBrownShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GREEN_SHULKER_BOX" => Ok(Material::LegacyGreenShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RED_SHULKER_BOX" => Ok(Material::LegacyRedShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BLACK_SHULKER_BOX" => Ok(Material::LegacyBlackShulkerBox { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WHITE_GLAZED_TERRACOTTA" => Ok(Material::LegacyWhiteGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ORANGE_GLAZED_TERRACOTTA" => Ok(Material::LegacyOrangeGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MAGENTA_GLAZED_TERRACOTTA" => Ok(Material::LegacyMagentaGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LIGHT_BLUE_GLAZED_TERRACOTTA" => { + Ok(Material::LegacyLightBlueGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }) + } + "LEGACY_YELLOW_GLAZED_TERRACOTTA" => Ok(Material::LegacyYellowGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LIME_GLAZED_TERRACOTTA" => Ok(Material::LegacyLimeGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PINK_GLAZED_TERRACOTTA" => Ok(Material::LegacyPinkGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GRAY_GLAZED_TERRACOTTA" => Ok(Material::LegacyGrayGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SILVER_GLAZED_TERRACOTTA" => Ok(Material::LegacySilverGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CYAN_GLAZED_TERRACOTTA" => Ok(Material::LegacyCyanGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PURPLE_GLAZED_TERRACOTTA" => Ok(Material::LegacyPurpleGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BLUE_GLAZED_TERRACOTTA" => Ok(Material::LegacyBlueGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BROWN_GLAZED_TERRACOTTA" => Ok(Material::LegacyBrownGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GREEN_GLAZED_TERRACOTTA" => Ok(Material::LegacyGreenGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RED_GLAZED_TERRACOTTA" => Ok(Material::LegacyRedGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BLACK_GLAZED_TERRACOTTA" => Ok(Material::LegacyBlackGlazedTerracotta { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CONCRETE" => Ok(Material::LegacyConcrete { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CONCRETE_POWDER" => Ok(Material::LegacyConcretePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STRUCTURE_BLOCK" => Ok(Material::LegacyStructureBlock { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_SPADE" => Ok(Material::LegacyIronSpade { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_PICKAXE" => Ok(Material::LegacyIronPickaxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_AXE" => Ok(Material::LegacyIronAxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FLINT_AND_STEEL" => Ok(Material::LegacyFlintAndSteel { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_APPLE" => Ok(Material::LegacyApple { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BOW" => Ok(Material::LegacyBow { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ARROW" => Ok(Material::LegacyArrow { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COAL" => Ok(Material::LegacyCoal { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND" => Ok(Material::LegacyDiamond { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_INGOT" => Ok(Material::LegacyIronIngot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_INGOT" => Ok(Material::LegacyGoldIngot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_SWORD" => Ok(Material::LegacyIronSword { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOD_SWORD" => Ok(Material::LegacyWoodSword { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOD_SPADE" => Ok(Material::LegacyWoodSpade { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOD_PICKAXE" => Ok(Material::LegacyWoodPickaxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOD_AXE" => Ok(Material::LegacyWoodAxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STONE_SWORD" => Ok(Material::LegacyStoneSword { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STONE_SPADE" => Ok(Material::LegacyStoneSpade { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STONE_PICKAXE" => Ok(Material::LegacyStonePickaxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STONE_AXE" => Ok(Material::LegacyStoneAxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND_SWORD" => Ok(Material::LegacyDiamondSword { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND_SPADE" => Ok(Material::LegacyDiamondSpade { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND_PICKAXE" => Ok(Material::LegacyDiamondPickaxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND_AXE" => Ok(Material::LegacyDiamondAxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STICK" => Ok(Material::LegacyStick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BOWL" => Ok(Material::LegacyBowl { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MUSHROOM_SOUP" => Ok(Material::LegacyMushroomSoup { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_SWORD" => Ok(Material::LegacyGoldSword { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_SPADE" => Ok(Material::LegacyGoldSpade { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_PICKAXE" => Ok(Material::LegacyGoldPickaxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_AXE" => Ok(Material::LegacyGoldAxe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STRING" => Ok(Material::LegacyString { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FEATHER" => Ok(Material::LegacyFeather { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SULPHUR" => Ok(Material::LegacySulphur { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOD_HOE" => Ok(Material::LegacyWoodHoe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STONE_HOE" => Ok(Material::LegacyStoneHoe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_HOE" => Ok(Material::LegacyIronHoe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND_HOE" => Ok(Material::LegacyDiamondHoe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_HOE" => Ok(Material::LegacyGoldHoe { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SEEDS" => Ok(Material::LegacySeeds { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WHEAT" => Ok(Material::LegacyWheat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BREAD" => Ok(Material::LegacyBread { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LEATHER_HELMET" => Ok(Material::LegacyLeatherHelmet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LEATHER_CHESTPLATE" => Ok(Material::LegacyLeatherChestplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LEATHER_LEGGINGS" => Ok(Material::LegacyLeatherLeggings { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LEATHER_BOOTS" => Ok(Material::LegacyLeatherBoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CHAINMAIL_HELMET" => Ok(Material::LegacyChainmailHelmet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CHAINMAIL_CHESTPLATE" => Ok(Material::LegacyChainmailChestplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CHAINMAIL_LEGGINGS" => Ok(Material::LegacyChainmailLeggings { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CHAINMAIL_BOOTS" => Ok(Material::LegacyChainmailBoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_HELMET" => Ok(Material::LegacyIronHelmet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_CHESTPLATE" => Ok(Material::LegacyIronChestplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_LEGGINGS" => Ok(Material::LegacyIronLeggings { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_BOOTS" => Ok(Material::LegacyIronBoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND_HELMET" => Ok(Material::LegacyDiamondHelmet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND_CHESTPLATE" => Ok(Material::LegacyDiamondChestplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND_LEGGINGS" => Ok(Material::LegacyDiamondLeggings { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND_BOOTS" => Ok(Material::LegacyDiamondBoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_HELMET" => Ok(Material::LegacyGoldHelmet { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_CHESTPLATE" => Ok(Material::LegacyGoldChestplate { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_LEGGINGS" => Ok(Material::LegacyGoldLeggings { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_BOOTS" => Ok(Material::LegacyGoldBoots { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FLINT" => Ok(Material::LegacyFlint { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PORK" => Ok(Material::LegacyPork { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GRILLED_PORK" => Ok(Material::LegacyGrilledPork { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PAINTING" => Ok(Material::LegacyPainting { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLDEN_APPLE" => Ok(Material::LegacyGoldenApple { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SIGN" => Ok(Material::LegacySign { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WOOD_DOOR" => Ok(Material::LegacyWoodDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BUCKET" => Ok(Material::LegacyBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WATER_BUCKET" => Ok(Material::LegacyWaterBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LAVA_BUCKET" => Ok(Material::LegacyLavaBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MINECART" => Ok(Material::LegacyMinecart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SADDLE" => Ok(Material::LegacySaddle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_DOOR" => Ok(Material::LegacyIronDoor { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_REDSTONE" => Ok(Material::LegacyRedstone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SNOW_BALL" => Ok(Material::LegacySnowBall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BOAT" => Ok(Material::LegacyBoat { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LEATHER" => Ok(Material::LegacyLeather { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MILK_BUCKET" => Ok(Material::LegacyMilkBucket { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CLAY_BRICK" => Ok(Material::LegacyClayBrick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CLAY_BALL" => Ok(Material::LegacyClayBall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SUGAR_CANE" => Ok(Material::LegacySugarCane { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PAPER" => Ok(Material::LegacyPaper { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BOOK" => Ok(Material::LegacyBook { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SLIME_BALL" => Ok(Material::LegacySlimeBall { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_STORAGE_MINECART" => Ok(Material::LegacyStorageMinecart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_POWERED_MINECART" => Ok(Material::LegacyPoweredMinecart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_EGG" => Ok(Material::LegacyEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COMPASS" => Ok(Material::LegacyCompass { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FISHING_ROD" => Ok(Material::LegacyFishingRod { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WATCH" => Ok(Material::LegacyWatch { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GLOWSTONE_DUST" => Ok(Material::LegacyGlowstoneDust { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RAW_FISH" => Ok(Material::LegacyRawFish { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COOKED_FISH" => Ok(Material::LegacyCookedFish { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_INK_SACK" => Ok(Material::LegacyInkSack { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BONE" => Ok(Material::LegacyBone { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SUGAR" => Ok(Material::LegacySugar { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CAKE" => Ok(Material::LegacyCake { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BED" => Ok(Material::LegacyBed { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIODE" => Ok(Material::LegacyDiode { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COOKIE" => Ok(Material::LegacyCookie { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MAP" => Ok(Material::LegacyMap { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SHEARS" => Ok(Material::LegacyShears { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MELON" => Ok(Material::LegacyMelon { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PUMPKIN_SEEDS" => Ok(Material::LegacyPumpkinSeeds { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MELON_SEEDS" => Ok(Material::LegacyMelonSeeds { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RAW_BEEF" => Ok(Material::LegacyRawBeef { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COOKED_BEEF" => Ok(Material::LegacyCookedBeef { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RAW_CHICKEN" => Ok(Material::LegacyRawChicken { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COOKED_CHICKEN" => Ok(Material::LegacyCookedChicken { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ROTTEN_FLESH" => Ok(Material::LegacyRottenFlesh { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ENDER_PEARL" => Ok(Material::LegacyEnderPearl { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BLAZE_ROD" => Ok(Material::LegacyBlazeRod { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GHAST_TEAR" => Ok(Material::LegacyGhastTear { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_NUGGET" => Ok(Material::LegacyGoldNugget { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_NETHER_STALK" => Ok(Material::LegacyNetherStalk { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_POTION" => Ok(Material::LegacyPotion { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GLASS_BOTTLE" => Ok(Material::LegacyGlassBottle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SPIDER_EYE" => Ok(Material::LegacySpiderEye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FERMENTED_SPIDER_EYE" => Ok(Material::LegacyFermentedSpiderEye { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BLAZE_POWDER" => Ok(Material::LegacyBlazePowder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MAGMA_CREAM" => Ok(Material::LegacyMagmaCream { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BREWING_STAND_ITEM" => Ok(Material::LegacyBrewingStandItem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CAULDRON_ITEM" => Ok(Material::LegacyCauldronItem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_EYE_OF_ENDER" => Ok(Material::LegacyEyeOfEnder { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SPECKLED_MELON" => Ok(Material::LegacySpeckledMelon { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MONSTER_EGG" => Ok(Material::LegacyMonsterEgg { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_EXP_BOTTLE" => Ok(Material::LegacyExpBottle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FIREBALL" => Ok(Material::LegacyFireball { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BOOK_AND_QUILL" => Ok(Material::LegacyBookAndQuill { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_WRITTEN_BOOK" => Ok(Material::LegacyWrittenBook { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_EMERALD" => Ok(Material::LegacyEmerald { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ITEM_FRAME" => Ok(Material::LegacyItemFrame { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FLOWER_POT_ITEM" => Ok(Material::LegacyFlowerPotItem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CARROT_ITEM" => Ok(Material::LegacyCarrotItem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_POTATO_ITEM" => Ok(Material::LegacyPotatoItem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BAKED_POTATO" => Ok(Material::LegacyBakedPotato { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_POISONOUS_POTATO" => Ok(Material::LegacyPoisonousPotato { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_EMPTY_MAP" => Ok(Material::LegacyEmptyMap { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLDEN_CARROT" => Ok(Material::LegacyGoldenCarrot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SKULL_ITEM" => Ok(Material::LegacySkullItem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CARROT_STICK" => Ok(Material::LegacyCarrotStick { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_NETHER_STAR" => Ok(Material::LegacyNetherStar { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PUMPKIN_PIE" => Ok(Material::LegacyPumpkinPie { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FIREWORK" => Ok(Material::LegacyFirework { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_FIREWORK_CHARGE" => Ok(Material::LegacyFireworkCharge { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ENCHANTED_BOOK" => Ok(Material::LegacyEnchantedBook { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_REDSTONE_COMPARATOR" => Ok(Material::LegacyRedstoneComparator { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_NETHER_BRICK_ITEM" => Ok(Material::LegacyNetherBrickItem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_QUARTZ" => Ok(Material::LegacyQuartz { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_EXPLOSIVE_MINECART" => Ok(Material::LegacyExplosiveMinecart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_HOPPER_MINECART" => Ok(Material::LegacyHopperMinecart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PRISMARINE_SHARD" => Ok(Material::LegacyPrismarineShard { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_PRISMARINE_CRYSTALS" => Ok(Material::LegacyPrismarineCrystals { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RABBIT" => Ok(Material::LegacyRabbit { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COOKED_RABBIT" => Ok(Material::LegacyCookedRabbit { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RABBIT_STEW" => Ok(Material::LegacyRabbitStew { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RABBIT_FOOT" => Ok(Material::LegacyRabbitFoot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RABBIT_HIDE" => Ok(Material::LegacyRabbitHide { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ARMOR_STAND" => Ok(Material::LegacyArmorStand { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_BARDING" => Ok(Material::LegacyIronBarding { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_BARDING" => Ok(Material::LegacyGoldBarding { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DIAMOND_BARDING" => Ok(Material::LegacyDiamondBarding { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LEASH" => Ok(Material::LegacyLeash { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_NAME_TAG" => Ok(Material::LegacyNameTag { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COMMAND_MINECART" => Ok(Material::LegacyCommandMinecart { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_MUTTON" => Ok(Material::LegacyMutton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_COOKED_MUTTON" => Ok(Material::LegacyCookedMutton { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BANNER" => Ok(Material::LegacyBanner { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_END_CRYSTAL" => Ok(Material::LegacyEndCrystal { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SPRUCE_DOOR_ITEM" => Ok(Material::LegacySpruceDoorItem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BIRCH_DOOR_ITEM" => Ok(Material::LegacyBirchDoorItem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_JUNGLE_DOOR_ITEM" => Ok(Material::LegacyJungleDoorItem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ACACIA_DOOR_ITEM" => Ok(Material::LegacyAcaciaDoorItem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DARK_OAK_DOOR_ITEM" => Ok(Material::LegacyDarkOakDoorItem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CHORUS_FRUIT" => Ok(Material::LegacyChorusFruit { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_CHORUS_FRUIT_POPPED" => Ok(Material::LegacyChorusFruitPopped { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BEETROOT" => Ok(Material::LegacyBeetroot { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BEETROOT_SEEDS" => Ok(Material::LegacyBeetrootSeeds { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BEETROOT_SOUP" => Ok(Material::LegacyBeetrootSoup { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_DRAGONS_BREATH" => Ok(Material::LegacyDragonsBreath { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SPLASH_POTION" => Ok(Material::LegacySplashPotion { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SPECTRAL_ARROW" => Ok(Material::LegacySpectralArrow { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_TIPPED_ARROW" => Ok(Material::LegacyTippedArrow { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_LINGERING_POTION" => Ok(Material::LegacyLingeringPotion { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SHIELD" => Ok(Material::LegacyShield { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_ELYTRA" => Ok(Material::LegacyElytra { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BOAT_SPRUCE" => Ok(Material::LegacyBoatSpruce { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BOAT_BIRCH" => Ok(Material::LegacyBoatBirch { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BOAT_JUNGLE" => Ok(Material::LegacyBoatJungle { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BOAT_ACACIA" => Ok(Material::LegacyBoatAcacia { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_BOAT_DARK_OAK" => Ok(Material::LegacyBoatDarkOak { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_TOTEM" => Ok(Material::LegacyTotem { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_SHULKER_SHELL" => Ok(Material::LegacyShulkerShell { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_IRON_NUGGET" => Ok(Material::LegacyIronNugget { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_KNOWLEDGE_BOOK" => Ok(Material::LegacyKnowledgeBook { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GOLD_RECORD" => Ok(Material::LegacyGoldRecord { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_GREEN_RECORD" => Ok(Material::LegacyGreenRecord { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RECORD_3" => Ok(Material::LegacyRecord3 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RECORD_4" => Ok(Material::LegacyRecord4 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RECORD_5" => Ok(Material::LegacyRecord5 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RECORD_6" => Ok(Material::LegacyRecord6 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RECORD_7" => Ok(Material::LegacyRecord7 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RECORD_8" => Ok(Material::LegacyRecord8 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RECORD_9" => Ok(Material::LegacyRecord9 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RECORD_10" => Ok(Material::LegacyRecord10 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RECORD_11" => Ok(Material::LegacyRecord11 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + "LEGACY_RECORD_12" => Ok(Material::LegacyRecord12 { + inner: MaterialStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } - let obj = res.l()?; - Ok(Some(crate::map::MapView::from_raw(&jni, obj)?)) } - /// Create a new map with an automatically assigned ID. - pub fn create_map( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - world: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/World;)Lorg/bukkit/map/MapView;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "createMap", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::map::MapView::from_raw(&jni, obj) +} + +impl<'mc> JNIRaw<'mc> for MaterialStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Create a new explorer map targeting the closest nearby structure of a - /// given {@link StructureType}. - /// - /// This method uses implementation default values for radius and - /// findUnexplored (usually 100, true). - pub fn create_explorer_map( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - world: impl Into>, - location: impl Into>, - structure_type: impl Into>, - radius: std::option::Option, - find_unexplored: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/World;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/Location;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - args.push(val_2); - sig += "Lorg/bukkit/StructureType;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(structure_type.into().jni_object().clone()) - }); - args.push(val_3); - if let Some(a) = radius { - sig += "I"; - let val_4 = jni::objects::JValueGen::Int(a); - args.push(val_4); + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for MaterialStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate MaterialStruct from null object.").into(), + ); } - if let Some(a) = find_unexplored { - sig += "Z"; - let val_5 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_5); + let (valid, name) = env.validate_name(&obj, "org/bukkit/Material")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a MaterialStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - sig += ")Lorg/bukkit/inventory/ItemStack;"; - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "createExplorerMap", sig.as_str(), args); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::inventory::ItemStack::from_raw(&jni, obj) - } - /// Reloads the server, refreshing settings and plugin information. - pub fn reload( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result<(), Box> { - let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "reload", sig.as_str(), vec![]); - jni.translate_error(res)?; - Ok(()) - } - /// Reload only the Minecraft data for the server. This includes custom - /// advancements and loot tables. - pub fn reload_data( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result<(), Box> { - let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "reloadData", sig.as_str(), vec![]); - jni.translate_error(res)?; - Ok(()) - } - /// Returns the primary logger associated with this server instance. - pub fn logger( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/logging/Logger;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getLogger", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - blackboxmc_java::util::logging::JavaLogger::from_raw(&jni, obj) } - /// Gets a {@link PluginCommand} with the given name or alias. - pub fn get_plugin_command( +} + +impl<'mc> MaterialStruct<'mc> { + pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - name: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/command/PluginCommand;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(name.into())?, - )); - let cls = jni.find_class("org/bukkit/Bukkit"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let cls = jni.find_class("org/bukkit/Material"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getPluginCommand", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } let obj = res.l()?; - Ok(Some(crate::command::PluginCommand::from_raw(&jni, obj)?)) - } - /// Writes loaded players to disk. - pub fn save_players( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result<(), Box> { - let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "savePlayers", sig.as_str(), vec![]); - jni.translate_error(res)?; - Ok(()) + crate::Material::from_raw(&jni, obj) } - /// Dispatches a command on this server, and executes it if found. - pub fn dispatch_command( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - sender: impl Into>, - command_line: impl Into, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/command/CommandSender;Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(command_line.into())?, - )); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "dispatchCommand", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = jni.translate_error(res)?; - Ok(res.z()?) + #[deprecated] + /// Do not use for any reason. + pub fn id(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Adds a recipe to the crafting manager. - pub fn add_recipe( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - recipe: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/inventory/Recipe;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "addRecipe", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; + #[deprecated] + /// Do not use for any reason. + pub fn is_legacy(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isLegacy", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Get a list of all recipes for a given item. The stack size is ignored - /// in comparisons. If the durability is -1, it will match any data value. - pub fn get_recipes_for( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - result: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(result.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getRecipesFor", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&jni, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::inventory::Recipe::from_raw(&jni, obj)?); - } - Ok(new_vec) + + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get the {@link Recipe} for the given key. - pub fn get_recipe( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - recipe_key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/inventory/Recipe;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(recipe_key.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getRecipe", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::inventory::Recipe::from_raw(&jni, obj)?)) + /// Gets the maximum amount of this material that can be held in a stack. + /// + /// Note that this is the default maximum size for this Material. + /// {@link ItemStack ItemStacks} are able to change their maximum stack size per + /// stack with {@link ItemMeta#setMaxStackSize(Integer)}. If an ItemStack instance + /// is available, {@link ItemStack#getMaxStackSize()} may be preferred. + pub fn max_stack_size(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxStackSize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Get the {@link Recipe} for the list of ItemStacks provided. - /// The list is formatted as a crafting matrix where the index follow - /// the pattern below: - ///
    -    /// [ 0 1 2 ]
    -    /// [ 3 4 5 ]
    -    /// [ 6 7 8 ]
    -    /// 
    - /// NOTE: This method will not modify the provided ItemStack array, for that, use - /// {@link #craftItem(ItemStack[], World, Player)}. - pub fn get_crafting_recipe( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - crafting_matrix: impl Into>, - world: impl Into>, - ) -> Result>, Box> { - let sig = String::from( - "(Lorg/bukkit/inventory/ItemStack;Lorg/bukkit/World;)Lorg/bukkit/inventory/Recipe;", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(crafting_matrix.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getCraftingRecipe", + /// Gets the maximum durability of this material + pub fn max_durability(&self) -> Result> { + let sig = String::from("()S"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaxDurability", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![], ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::inventory::Recipe::from_raw(&jni, obj)?)) - } - /// Get the crafted item using the list of {@link ItemStack} provided. - /// The list is formatted as a crafting matrix where the index follow - /// the pattern below: - ///
    -    /// [ 0 1 2 ]
    -    /// [ 3 4 5 ]
    -    /// [ 6 7 8 ]
    -    /// 
    - /// The {@link World} and {@link Player} arguments are required to fulfill the Bukkit Crafting - /// events. - /// Calls {@link org.bukkit.event.inventory.PrepareItemCraftEvent} to imitate the {@link Player} - /// initiating the crafting event. - pub fn craft_item_result( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - crafting_matrix: impl Into>, - world: impl Into>, - player: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(crafting_matrix.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/World;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); - args.push(val_2); - if let Some(a) = player { - sig += "Lorg/bukkit/entity/Player;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_3); - } - sig += ")Lorg/bukkit/inventory/ItemCraftResult;"; - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "craftItemResult", sig.as_str(), args); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::inventory::ItemCraftResult::from_raw(&jni, obj) + let res = self.jni_ref().translate_error(res)?; + Ok(res.s()?) } - /// Get the crafted item using the list of {@link ItemStack} provided. - /// The list is formatted as a crafting matrix where the index follow - /// the pattern below: - ///
    -    /// [ 0 1 2 ]
    -    /// [ 3 4 5 ]
    -    /// [ 6 7 8 ]
    -    /// 
    - /// The {@link World} and {@link Player} arguments are required to fulfill the Bukkit Crafting - /// events. - /// Calls {@link org.bukkit.event.inventory.PrepareItemCraftEvent} to imitate the {@link Player} - /// initiating the crafting event. - pub fn craft_item( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - crafting_matrix: impl Into>, - world: impl Into>, - player: std::option::Option>>, - ) -> Result, Box> { + /// Creates a new {@link BlockData} instance for this Material, with all + /// properties initialized to unspecified defaults, except for those provided + /// in data. + pub fn create_block_data( + &self, + data: std::option::Option>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(crafting_matrix.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/World;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); - args.push(val_2); - if let Some(a) = player { - sig += "Lorg/bukkit/entity/Player;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_3); + if let Some(a) = data { + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_1); } - sig += ")Lorg/bukkit/inventory/ItemStack;"; - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "craftItem", sig.as_str(), args); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::inventory::ItemStack::from_raw(&jni, obj) - } - /// Get an iterator through the list of crafting recipes. - pub fn recipe_iterator( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Iterator;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "recipeIterator", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - blackboxmc_java::util::JavaIterator::from_raw(&jni, obj) - } - /// Clears the list of crafting recipes. - pub fn clear_recipes( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result<(), Box> { - let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "clearRecipes", sig.as_str(), vec![]); - jni.translate_error(res)?; - Ok(()) - } - /// Resets the list of crafting recipes to the default. - pub fn reset_recipes( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result<(), Box> { - let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "resetRecipes", sig.as_str(), vec![]); - jni.translate_error(res)?; - Ok(()) - } - /// Remove a recipe from the server. - /// Note that removing a recipe may cause permanent loss of data - /// associated with that recipe (eg whether it has been discovered by - /// players). - pub fn remove_recipe( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - key: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "removeRecipe", + sig += ")Lorg/bukkit/block/data/BlockData;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createBlockData", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the MaterialData class associated with this Material + pub fn data(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/Class;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(unsafe { jni::objects::JClass::from_raw(res.as_jni().l) }) + } + #[deprecated] + /// Constructs a new MaterialData relevant for this Material, with the given initial data + pub fn get_new_data( + &self, + raw: i8, + ) -> Result, Box> { + let sig = String::from("(B)Lorg/bukkit/material/MaterialData;"); + let val_1 = jni::objects::JValueGen::Byte(raw); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getNewData", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error(res)?; + let res = self.jni_ref().translate_error(res)?; + crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Checks if this Material is a placable block + pub fn is_block(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isBlock", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets a list of command aliases defined in the server properties. - pub fn command_aliases( + /// Checks if this Material is edible. + pub fn is_edible(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEdible", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Attempts to get the Material with the given name. + /// + /// This is a normal lookup, names must be the precise name they are given in + /// the enum (but optionally including the LEGACY_PREFIX if legacyName is + /// true). + /// + /// If legacyName is true, then the lookup will be against legacy materials, + /// but the returned Material will be a modern material (ie this method is + /// useful for updating stored data). + pub fn get_material( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let cls = jni.find_class("org/bukkit/Bukkit"); + name: impl Into, + legacy_name: std::option::Option, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(name.into())?, + )); + args.push(val_1); + if let Some(a) = legacy_name { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Lorg/bukkit/Material;"; + let cls = jni.find_class("org/bukkit/Material"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getCommandAliases", sig.as_str(), vec![]); + let res = jni.call_static_method(cls, "getMaterial", sig.as_str(), args); let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } let obj = res.l()?; - blackboxmc_java::util::JavaMap::from_raw(&jni, obj) + Ok(Some(crate::Material::from_raw(&jni, obj)?)) } - /// Gets the radius, in blocks, around each worlds spawn point to protect. - pub fn spawn_radius( + /// Attempts to match the Material with the given name. + /// + /// This is a match lookup; names will be stripped of the "minecraft:" + /// namespace, converted to uppercase, then stripped of special characters in + /// an attempt to format it like the enum. + pub fn match_material( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()I"); - let cls = jni.find_class("org/bukkit/Bukkit"); + name: impl Into, + legacy_name: std::option::Option, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(name.into())?, + )); + args.push(val_1); + if let Some(a) = legacy_name { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")Lorg/bukkit/Material;"; + let cls = jni.find_class("org/bukkit/Material"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getSpawnRadius", sig.as_str(), vec![]); + let res = jni.call_static_method(cls, "matchMaterial", sig.as_str(), args); let res = jni.translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::Material::from_raw(&jni, obj)?)) } - /// Sets the radius, in blocks, around each worlds spawn point to protect. - pub fn set_spawn_radius( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - value: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(value); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "setSpawnRadius", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - jni.translate_error(res)?; - Ok(()) + + pub fn is_record(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isRecord", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Check if the material is a block and solid (can be built upon) + pub fn is_solid(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSolid", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Check if the material is an air block. + pub fn is_air(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isAir", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } #[deprecated] - /// Gets whether the server should send a preview of the player's chat message to the client when the player sends a message - pub fn should_send_chat_previews( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { + /// Check if the material is a block and does not block any light + pub fn is_transparent(&self) -> Result> { let sig = String::from("()Z"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "shouldSendChatPreviews", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isTransparent", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets whether the server only allow players with Mojang-signed public key - /// to join - pub fn is_enforcing_secure_profiles( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { + /// Check if the material is a block and can catch fire + pub fn is_flammable(&self) -> Result> { let sig = String::from("()Z"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "isEnforcingSecureProfiles", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isFlammable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets whether this server is allowing connections transferred from other - /// servers. - pub fn is_accepting_transfers( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { + /// Check if the material is a block and can burn away + pub fn is_burnable(&self) -> Result> { let sig = String::from("()Z"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "isAcceptingTransfers", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isBurnable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets whether the Server hide online players in server status. - pub fn hide_online_players( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { + /// Checks if this Material can be used as fuel in a Furnace + pub fn is_fuel(&self) -> Result> { let sig = String::from("()Z"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHideOnlinePlayers", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFuel", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets whether the Server is in online mode or not. - pub fn online_mode( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { + /// Check if the material is a block and occludes light in the lighting engine. + /// + /// Generally speaking, most full blocks will occlude light. Non-full blocks are + /// not occluding (e.g. anvils, chests, tall grass, stairs, etc.), nor are specific + /// full blocks such as barriers or spawners which block light despite their texture. + /// + /// An occluding block will have the following effects: + ///
      + ///
    • Chests cannot be opened if an occluding block is above it. + ///
    • Mobs cannot spawn inside of occluding blocks. + ///
    • Only occluding blocks can be "powered" ({@link Block#isBlockPowered()}). + ///
    + /// This list may be inconclusive. For a full list of the side effects of an occluding + /// block, see the Minecraft Wiki. + pub fn is_occluding(&self) -> Result> { let sig = String::from("()Z"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getOnlineMode", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isOccluding", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets whether this server allows flying or not. - pub fn allow_flight( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { + + pub fn has_gravity(&self) -> Result> { let sig = String::from("()Z"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getAllowFlight", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasGravity", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets whether the server is in hardcore mode or not. - pub fn is_hardcore( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { + /// Checks if this Material is an obtainable item. + pub fn is_item(&self) -> Result> { let sig = String::from("()Z"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "isHardcore", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isItem", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Shutdowns the server, stopping everything. - pub fn shutdown( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result<(), Box> { - let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "shutdown", sig.as_str(), vec![]); - jni.translate_error(res)?; - Ok(()) + /// Checks if this Material can be interacted with. + /// Interactable materials include those with functionality when they are + /// interacted with by a player such as chests, furnaces, etc. + /// Some blocks such as piston heads and stairs are considered interactable + /// though may not perform any additional functionality. + /// Note that the interactability of some materials may be dependant on their + /// state as well. This method will return true if there is at least one + /// state in which additional interact handling is performed for the + /// material. + pub fn is_interactable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInteractable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Broadcasts the specified message to every user with the given - /// permission name. - pub fn broadcast( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - message: impl Into, - permission: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;Ljava/lang/String;)I"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(message.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(permission.into())?, - )); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "broadcast", + /// Obtains the block's hardness level (also known as "strength"). + /// + /// This number is used to calculate the time required to break each block. + /// + /// Only available when {@link #isBlock()} is true. + pub fn hardness(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHardness", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Obtains the blast resistance value (also known as block "durability"). + /// + /// This value is used in explosions to calculate whether a block should be + /// broken or not. + /// + /// Only available when {@link #isBlock()} is true. + pub fn blast_resistance(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBlastResistance", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![], ); - let res = jni.translate_error(res)?; - Ok(res.i()?) + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) } - /// Gets the player by the given UUID, regardless if they are offline or - /// online. - /// - /// This will return an object even if the player does not exist. To this - /// method, all players will exist. - pub fn get_offline_player( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - id: impl Into>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(id.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Lorg/bukkit/OfflinePlayer;"; - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getOfflinePlayer", sig.as_str(), args); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::OfflinePlayer::from_raw(&jni, obj) + /// Returns a value that represents how 'slippery' the block is. + /// Blocks with higher slipperiness, like {@link Material#ICE} can be slid on + /// further by the player and other entities. + /// Most blocks have a default slipperiness of {@code 0.6f}. + /// Only available when {@link #isBlock()} is true. + pub fn slipperiness(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSlipperiness", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) } - /// Creates a new {@link PlayerProfile}. - pub fn create_player_profile( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - unique_id: impl Into>, - name: std::option::Option>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/util/UUID;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(unique_id.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = name { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(a.into())?, - )); - args.push(val_2); + /// Determines the remaining item in a crafting grid after crafting with this + /// ingredient. + /// + /// Only available when {@link #isItem()} is true. + pub fn crafting_remaining_item( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCraftingRemainingItem", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - sig += ")Lorg/bukkit/profile/PlayerProfile;"; - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "createPlayerProfile", sig.as_str(), args); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::profile::PlayerProfile::from_raw(&jni, obj) - } - /// Gets a set containing all current IPs that are banned. - pub fn ipbans( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getIPBans", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - blackboxmc_java::util::JavaSet::from_raw(&jni, obj) - } - /// Bans the specified address from the server. - pub fn ban_ip( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - address: jni::objects::JObject<'mc>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/net/InetAddress;"; - let val_1 = jni::objects::JValueGen::Object(address); - args.push(val_1); - sig += ")V"; - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "banIP", sig.as_str(), args); - jni.translate_error(res)?; - Ok(()) - } - /// Unbans the specified address from the server. - pub fn unban_ip( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - address: jni::objects::JObject<'mc>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/net/InetAddress;"; - let val_1 = jni::objects::JValueGen::Object(address); - args.push(val_1); - sig += ")V"; - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "unbanIP", sig.as_str(), args); - jni.translate_error(res)?; - Ok(()) + Ok(Some(crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Gets a set containing all banned players. - pub fn banned_players( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getBannedPlayers", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - blackboxmc_java::util::JavaSet::from_raw(&jni, obj) + /// Get the best suitable slot for this Material. + /// For most items this will be {@link EquipmentSlot#HAND}. + pub fn equipment_slot( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/EquipmentSlot;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getEquipmentSlot", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::EquipmentSlot::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets a ban list for the supplied type. - pub fn get_ban_list( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: impl Into>, + /// Return an immutable copy of all default {@link Attribute}s and their + /// {@link AttributeModifier}s for a given {@link EquipmentSlot}. + /// Default attributes are those that are always preset on some items, such + /// as the attack damage on weapons or the armor value on armor. + /// Only available when {@link #isItem()} is true. + pub fn get_default_attribute_modifiers( + &self, + slot: impl Into>, ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/BanList/Type;)LT;"); + let sig = String::from( + "(Lorg/bukkit/inventory/EquipmentSlot;)Lcom/google/common/collect/Multimap;", + ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(slot.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getBanList", + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDefaultAttributeModifiers", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error(res)?; + let res = self.jni_ref().translate_error(res)?; Ok(res.l()?) } - /// Gets a set containing all player operators. - pub fn operators( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getOperators", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - blackboxmc_java::util::JavaSet::from_raw(&jni, obj) - } - /// Gets the default {@link GameMode} for new players. - pub fn default_game_mode( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/GameMode;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getDefaultGameMode", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::GameMode::from_raw(&jni, obj) - } - /// Sets the default {@link GameMode} for new players. - pub fn set_default_game_mode( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - mode: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/GameMode;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(mode.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "setDefaultGameMode", + /// Get the {@link CreativeCategory} to which this material belongs. + pub fn creative_category( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/CreativeCategory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCreativeCategory", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - jni.translate_error(res)?; - Ok(()) - } - /// Gets a {@link ConsoleCommandSender} that may be used as an input source - /// for this server. - pub fn console_sender( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/command/ConsoleCommandSender;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getConsoleSender", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::command::ConsoleCommandSender::from_raw(&jni, obj) - } - /// Gets every player that has ever played on this server. - pub fn offline_players( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/OfflinePlayer;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getOfflinePlayers", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::OfflinePlayer::from_raw(&jni, obj) - } - /// Gets the {@link Messenger} responsible for this server. - pub fn messenger( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/plugin/messaging/Messenger;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getMessenger", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::plugin::messaging::Messenger::from_raw(&jni, obj) - } - /// Gets the {@link HelpMap} providing help topics for this server. - pub fn help_map( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/help/HelpMap;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getHelpMap", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::help::HelpMap::from_raw(&jni, obj) - } - /// Creates an empty inventory of type {@link InventoryType#CHEST} with the - /// specified size and title. - pub fn create_inventory( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - owner: impl Into>, - size: i32, - title: std::option::Option>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/inventory/InventoryHolder;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owner.into().jni_object().clone()) - }); - args.push(val_1); - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(size); - args.push(val_2); - if let Some(a) = title { - sig += "Ljava/lang/String;"; - let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(a.into())?, - )); - args.push(val_3); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - sig += ")Lorg/bukkit/inventory/Inventory;"; - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "createInventory", sig.as_str(), args); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::inventory::Inventory::from_raw(&jni, obj) + Ok(Some(crate::inventory::CreativeCategory::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Creates an empty merchant. - pub fn create_merchant( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - title: impl Into, - ) -> Result, Box> { - let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/inventory/Merchant;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(title.into())?, - )); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "createMerchant", + /// Get the translation key of the item or block associated with this + /// material. + /// If this material has both an item and a block form, the item form is + /// used. + pub fn translation_key(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTranslationKey", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::inventory::Merchant::from_raw(&jni, obj) - } - /// Gets the amount of consecutive neighbor updates before skipping - /// additional ones. - pub fn max_chained_neighbor_updates( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()I"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getMaxChainedNeighborUpdates", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(res.i()?) - } - #[deprecated] - /// Gets user-specified limit for number of monsters that can spawn in a chunk. - pub fn monster_spawn_limit( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()I"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getMonsterSpawnLimit", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(res.i()?) - } - #[deprecated] - /// Gets user-specified limit for number of animals that can spawn in a chunk. - pub fn animal_spawn_limit( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()I"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getAnimalSpawnLimit", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(res.i()?) - } - #[deprecated] - /// Gets user-specified limit for number of water animals that can spawn in a chunk. - pub fn water_animal_spawn_limit( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()I"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getWaterAnimalSpawnLimit", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(res.i()?) - } - #[deprecated] - /// Gets user-specified limit for number of water ambient mobs that can spawn in a chunk. - pub fn water_ambient_spawn_limit( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()I"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getWaterAmbientSpawnLimit", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(res.i()?) + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - #[deprecated] - /// Get user-specified limit for number of water creature underground that can spawn in a chunk. - pub fn water_underground_creature_spawn_limit( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()I"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getWaterUndergroundCreatureSpawnLimit", + /// Get the translation key of the block associated with this material, or + /// null if this material does not have an associated block. + pub fn block_translation_key(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBlockTranslationKey", sig.as_str(), vec![], ); - let res = jni.translate_error(res)?; - Ok(res.i()?) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - #[deprecated] - /// Gets user-specified limit for number of ambient mobs that can spawn in a chunk. - pub fn ambient_spawn_limit( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()I"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getAmbientSpawnLimit", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(res.i()?) + /// Get the translation key of the item associated with this material, or + /// null if this material does not have an associated item. + pub fn item_translation_key(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItemTranslationKey", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Gets user-specified limit for number of {@link SpawnCategory} mobs that can spawn in - /// a chunk. - /// Note: the {@link SpawnCategory#MISC} are not consider. - pub fn get_spawn_limit( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - spawn_category: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/SpawnCategory;)I"); + /// Gets if the Material is enabled by the features in a world. + pub fn is_enabled_by_feature( + &self, + world: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/World;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(spawn_category.into().jni_object().clone()) + jni::objects::JObject::from_raw(world.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getSpawnLimit", + let res = self.jni_ref().call_method( + &self.jni_object(), + "isEnabledByFeature", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error(res)?; - Ok(res.i()?) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Checks the current thread against the expected primary thread for the - /// server. - /// - /// Note: this method should not be used to indicate the current - /// synchronized state of the runtime. A current thread matching the main - /// thread indicates that it is synchronized, but a mismatch does not - /// preclude the same assumption. - pub fn is_primary_thread( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { + /// Checks whether this material is compostable (can be inserted into a + /// composter). + pub fn is_compostable(&self) -> Result> { let sig = String::from("()Z"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "isPrimaryThread", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCompostable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the message that is displayed on the server list. - pub fn motd( + /// Get the chance that this material will successfully compost. The returned + /// value is between 0 and 1 (inclusive). + /// Materials with a compost chance of 1 will always raise the composter's + /// level, while materials with a compost chance of 0 will never raise it. + /// Plugins should check that {@link #isCompostable} returns true before + /// calling this method. + pub fn compost_chance(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCompostChance", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Tries to convert this Material to an item type + pub fn as_item_type( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemType;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "asItemType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::inventory::ItemType::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Tries to convert this Material to a block type + pub fn as_block_type( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockType;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "asBlockType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::block::BlockType::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct Location<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Location<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Location<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Location from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Location")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Location object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Location<'mc> { + /// Constructs a new Location with the given coordinates and direction + pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let cls = jni.find_class("org/bukkit/Bukkit"); + world: impl Into>, + x: f64, + y: f64, + z: f64, + yaw: std::option::Option, + pitch: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/World;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(world.into().jni_object().clone()) + }); + args.push(val_1); + sig += "D"; + let val_2 = jni::objects::JValueGen::Double(x); + args.push(val_2); + sig += "D"; + let val_3 = jni::objects::JValueGen::Double(y); + args.push(val_3); + sig += "D"; + let val_4 = jni::objects::JValueGen::Double(z); + args.push(val_4); + if let Some(a) = yaw { + sig += "F"; + let val_5 = jni::objects::JValueGen::Float(a); + args.push(val_5); + } + if let Some(a) = pitch { + sig += "F"; + let val_6 = jni::objects::JValueGen::Float(a); + args.push(val_6); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/Location"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getMotd", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(jni - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::Location::from_raw(&jni, res) } - /// Set the message that is displayed on the server list. - pub fn set_motd( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - motd: impl Into, + /// Sets the world that this location resides in + pub fn set_world( + &self, + world: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(motd.into())?, - )); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "setMotd", + let sig = String::from("(Lorg/bukkit/World;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(world.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setWorld", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - jni.translate_error(res)?; + self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the default message that is displayed when the server is stopped. - pub fn shutdown_message( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getShutdownMessage", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; + /// Checks if world in this location is present and loaded. + pub fn is_world_loaded(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isWorldLoaded", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the world that this location resides in + pub fn world(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some( - jni.get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// Gets the current warning state for the server. - pub fn warning_state( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Warning/WarningState;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getWarningState", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::WarningWarningState::from_raw(&jni, obj) - } - /// Gets the instance of the item factory (for {@link ItemMeta}). - pub fn item_factory( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/inventory/ItemFactory;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getItemFactory", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::inventory::ItemFactory::from_raw(&jni, obj) + Ok(Some(crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Gets the instance of the entity factory (for {@link EntitySnapshot}). - pub fn entity_factory( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityFactory;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getEntityFactory", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::entity::EntityFactory::from_raw(&jni, obj) + /// Gets the chunk at the represented location + pub fn chunk(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Chunk;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getChunk", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Chunk::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the instance of the scoreboard manager. - /// - /// This will only exist after the first world has loaded. - pub fn scoreboard_manager( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/scoreboard/ScoreboardManager;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getScoreboardManager", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::scoreboard::ScoreboardManager::from_raw( - &jni, obj, - )?)) + /// Gets the block at the represented location + pub fn block(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get (or create) a new {@link Criteria} by its name. - pub fn get_scoreboard_criteria( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - name: impl Into, - ) -> Result, Box> { - let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/scoreboard/Criteria;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(name.into())?, - )); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getScoreboardCriteria", + /// Sets the x-coordinate of this location + pub fn set_x(&self, x: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(x); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setX", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::scoreboard::Criteria::from_raw(&jni, obj) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets an instance of the server's default server-icon. - pub fn server_icon( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/util/CachedServerIcon;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getServerIcon", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::util::CachedServerIcon::from_raw(&jni, obj)?)) + /// Gets the x-coordinate of this location + pub fn x(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } - /// Creates a cached server-icon for the specific image. - /// - /// Size and type are implementation defined. An incompatible file is - /// guaranteed to throw an implementation-defined {@link Exception}. - pub fn load_server_icon( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - image: jni::objects::JObject<'mc>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/awt/image/BufferedImage;"; - let val_1 = jni::objects::JValueGen::Object(image); - args.push(val_1); - sig += ")Lorg/bukkit/util/CachedServerIcon;"; - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "loadServerIcon", sig.as_str(), args); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::util::CachedServerIcon::from_raw(&jni, obj) + /// Gets the floored value of the X component, indicating the block that + /// this location is contained with. + pub fn block_x(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBlockX", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Set the idle kick timeout. Any players idle for the specified amount of - /// time will be automatically kicked. - /// - /// A value of 0 will disable the idle kick timeout. - pub fn set_idle_timeout( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - threshold: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(threshold); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "setIdleTimeout", + /// Sets the y-coordinate of this location + pub fn set_y(&self, y: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(y); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setY", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - jni.translate_error(res)?; + self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the idle kick timeout. - pub fn idle_timeout( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { + /// Gets the y-coordinate of this location + pub fn y(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the floored value of the Y component, indicating the block that + /// this location is contained with. + pub fn block_y(&self) -> Result> { let sig = String::from("()I"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getIdleTimeout", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBlockY", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Create a ChunkData for use in a generator. - /// See {@link ChunkGenerator#generateChunkData(org.bukkit.World, java.util.Random, int, int, org.bukkit.generator.ChunkGenerator.BiomeGrid)} - pub fn create_chunk_data( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - world: impl Into>, - ) -> Result, Box> { - let sig = - String::from("(Lorg/bukkit/World;)Lorg/bukkit/generator/ChunkGenerator/ChunkData;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "createChunkData", + /// Sets the z-coordinate of this location + pub fn set_z(&self, z: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(z); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setZ", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::generator::ChunkGeneratorChunkData::from_raw(&jni, obj) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Creates a boss bar instance to display to players. The progress defaults - /// to 1.0. - /// - /// This instance is added to the persistent storage of the server and will - /// be editable by commands and restored after restart. - pub fn create_boss_bar( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - key: impl Into>, - title: impl Into, - color: impl Into>, - style: impl Into>, - flags: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/NamespacedKey;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(title.into())?, - )); - args.push(val_2); - sig += "Lorg/bukkit/boss/BarColor;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) - }); - args.push(val_3); - sig += "Lorg/bukkit/boss/BarStyle;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(style.into().jni_object().clone()) - }); - args.push(val_4); - if let Some(a) = flags { - sig += "Lorg/bukkit/boss/BarFlag;"; - let val_5 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_5); - } - sig += ")Lorg/bukkit/boss/KeyedBossBar;"; - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "createBossBar", sig.as_str(), args); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::boss::KeyedBossBar::from_raw(&jni, obj) + /// Gets the z-coordinate of this location + pub fn z(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } - /// Gets an unmodifiable iterator through all persistent bossbars. - ///
      - ///
    • not bound to a {@link org.bukkit.entity.Boss}
    • - ///
    • - /// not created using - /// {@link #createBossBar(String, BarColor, BarStyle, BarFlag...)} - ///
    • - ///
    - /// e.g. bossbars created using the bossbar command - pub fn boss_bars( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Iterator;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getBossBars", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - blackboxmc_java::util::JavaIterator::from_raw(&jni, obj) + /// Gets the floored value of the Z component, indicating the block that + /// this location is contained with. + pub fn block_z(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBlockZ", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Gets the {@link KeyedBossBar} specified by this key. + /// Sets the yaw of this location, measured in degrees. ///
      - ///
    • not bound to a {@link org.bukkit.entity.Boss}
    • - ///
    • - /// not created using - /// {@link #createBossBar(String, BarColor, BarStyle, BarFlag...)} - ///
    • + ///
    • A yaw of 0 or 360 represents the positive z direction. + ///
    • A yaw of 180 represents the negative z direction. + ///
    • A yaw of 90 represents the negative x direction. + ///
    • A yaw of 270 represents the positive x direction. ///
    - /// e.g. bossbars created using the bossbar command - pub fn get_boss_bar( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/boss/KeyedBossBar;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getBossBar", + /// Increasing yaw values are the equivalent of turning to your + /// right-facing, increasing the scale of the next respective axis, and + /// decreasing the scale of the previous axis. + pub fn set_yaw(&self, yaw: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(yaw); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setYaw", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::boss::KeyedBossBar::from_raw(&jni, obj)?)) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Removes a {@link KeyedBossBar} specified by this key. + /// Gets the yaw of this location, measured in degrees. ///
      - ///
    • not bound to a {@link org.bukkit.entity.Boss}
    • - ///
    • - /// not created using - /// {@link #createBossBar(String, BarColor, BarStyle, BarFlag...)} - ///
    • + ///
    • A yaw of 0 or 360 represents the positive z direction. + ///
    • A yaw of 180 represents the negative z direction. + ///
    • A yaw of 90 represents the negative x direction. + ///
    • A yaw of 270 represents the positive x direction. ///
    - /// e.g. bossbars created using the bossbar command - pub fn remove_boss_bar( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - key: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "removeBossBar", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - Ok(res.z()?) + /// Increasing yaw values are the equivalent of turning to your + /// right-facing, increasing the scale of the next respective axis, and + /// decreasing the scale of the previous axis. + pub fn yaw(&self) -> Result> { + let sig = String::from("()F"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getYaw", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) } - /// Gets an entity on the server by its UUID - pub fn get_entity( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - uuid: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Ljava/util/UUID;)Lorg/bukkit/entity/Entity;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getEntity", + /// Sets the pitch of this location, measured in degrees. + ///
      + ///
    • A pitch of 0 represents level forward facing. + ///
    • A pitch of 90 represents downward facing, or negative y + /// direction. + ///
    • A pitch of -90 represents upward facing, or positive y direction. + ///
    + /// Increasing pitch values the equivalent of looking down. + pub fn set_pitch(&self, pitch: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(pitch); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPitch", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::entity::Entity::from_raw(&jni, obj)?)) + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the pitch of this location, measured in degrees. + ///
      + ///
    • A pitch of 0 represents level forward facing. + ///
    • A pitch of 90 represents downward facing, or negative y + /// direction. + ///
    • A pitch of -90 represents upward facing, or positive y direction. + ///
    + /// Increasing pitch values the equivalent of looking down. + pub fn pitch(&self) -> Result> { + let sig = String::from("()F"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPitch", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Gets a unit-vector pointing in the direction that this Location is + /// facing. + pub fn direction(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get the advancement specified by this key. - pub fn get_advancement( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/advancement/Advancement;"); + /// Sets the {@link #getYaw() yaw} and {@link #getPitch() pitch} to point + /// in the direction of the vector. + pub fn set_direction( + &self, + vector: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)Lorg/bukkit/Location;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) + jni::objects::JObject::from_raw(vector.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getAdvancement", + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDirection", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::advancement::Advancement::from_raw(&jni, obj)?)) - } - /// Get an iterator through all advancements. Advancements cannot be removed - /// from this iterator, - pub fn advancement_iterator( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Iterator;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "advancementIterator", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - blackboxmc_java::util::JavaIterator::from_raw(&jni, obj) + let res = self.jni_ref().translate_error(res)?; + crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Creates a new {@link BlockData} instance for the specified Material, with - /// all properties initialized to unspecified defaults, except for those - /// provided in data. - pub fn create_block_data( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - material: impl Into>, - data: std::option::Option>, - ) -> Result, Box> { + /// Adds the location by another. Not world-aware. + pub fn add( + &self, + x: f64, + y: std::option::Option, + z: std::option::Option, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(x); args.push(val_1); - if let Some(a) = data { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(a.into())?, - )); + if let Some(a) = y { + sig += "D"; + let val_2 = jni::objects::JValueGen::Double(a); args.push(val_2); } - sig += ")Lorg/bukkit/block/data/BlockData;"; - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "createBlockData", sig.as_str(), args); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::block::data::BlockData::from_raw(&jni, obj) + if let Some(a) = z { + sig += "D"; + let val_3 = jni::objects::JValueGen::Double(a); + args.push(val_3); + } + sig += ")Lorg/bukkit/Location;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "add", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets a tag which has already been defined within the server. Plugins are - /// suggested to use the concrete tags in {@link Tag} rather than this method - /// which makes no guarantees about which tags are available, and may also be - /// less performant due to lack of caching. - /// - /// Tags will be searched for in an implementation specific manner, but a - /// path consisting of namespace/tags/registry/key is expected. - /// - /// Server implementations are allowed to handle only the registries - /// indicated in {@link Tag}. - pub fn get_tag( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - registry: impl Into, - tag: impl Into>, - clazz: jni::objects::JClass<'mc>, - ) -> Result>, Box> { - let sig = String::from( - "(Ljava/lang/String;Lorg/bukkit/NamespacedKey;Ljava/lang/Class;)Lorg/bukkit/Tag;", - ); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(registry.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tag.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(clazz.into()); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getTag", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + /// Subtracts the location by another. Not world-aware and + /// orientation independent. + pub fn subtract( + &self, + x: f64, + y: std::option::Option, + z: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(x); + args.push(val_1); + if let Some(a) = y { + sig += "D"; + let val_2 = jni::objects::JValueGen::Double(a); + args.push(val_2); } - let obj = res.l()?; - Ok(Some(crate::Tag::from_raw(&jni, obj)?)) + if let Some(a) = z { + sig += "D"; + let val_3 = jni::objects::JValueGen::Double(a); + args.push(val_3); + } + sig += ")Lorg/bukkit/Location;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "subtract", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the specified {@link LootTable}. - pub fn get_loot_table( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/loot/LootTable;"); + /// Gets the magnitude of the location, defined as sqrt(x^2+y^2+z^2). The + /// value of this method is not cached and uses a costly square-root + /// function, so do not repeatedly call this method to get the location's + /// magnitude. NaN will be returned if the inner result of the sqrt() + /// function overflows, which will be caused if the length is too long. Not + /// world-aware and orientation independent. + pub fn length(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "length", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the magnitude of the location squared. Not world-aware and + /// orientation independent. + pub fn length_squared(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "lengthSquared", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Get the distance between this location and another. The value of this + /// method is not cached and uses a costly square-root function, so do not + /// repeatedly call this method to get the location's magnitude. NaN will + /// be returned if the inner result of the sqrt() function overflows, which + /// will be caused if the distance is too long. + pub fn distance( + &self, + o: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/Location;)D"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) + jni::objects::JObject::from_raw(o.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getLootTable", + let res = self.jni_ref().call_method( + &self.jni_object(), + "distance", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::loot::LootTable::from_raw(&jni, obj)?)) + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } - /// Selects entities using the given Vanilla selector. - /// - /// No guarantees are made about the selector format, other than they match - /// the Vanilla format for the active Minecraft version. - /// - /// Usually a selector will start with '@', unless selecting a Player in - /// which case it may simply be the Player's name or UUID. - /// - /// Note that in Vanilla, elevated permissions are usually required to use - /// '@' selectors, but this method should not check such permissions from the - /// sender. - pub fn select_entities( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - sender: impl Into>, - selector: impl Into, - ) -> Result>, Box> { - let sig = - String::from("(Lorg/bukkit/command/CommandSender;Ljava/lang/String;)Ljava/util/List;"); + /// Get the squared distance between this location and another. + pub fn distance_squared( + &self, + o: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/Location;)D"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + jni::objects::JObject::from_raw(o.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(selector.into())?, - )); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "selectEntities", + let res = self.jni_ref().call_method( + &self.jni_object(), + "distanceSquared", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&jni, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&jni, obj)?); - } - Ok(new_vec) - } - /// Gets the structure manager for loading and saving structures. - pub fn structure_manager( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/structure/StructureManager;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getStructureManager", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::structure::StructureManager::from_raw(&jni, obj) + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } - /// Returns the registry for the given class. - /// - /// If no registry is present for the given class null will be returned. - /// - /// Depending on the implementation not every registry present in - /// {@link Registry} will be returned by this method. - pub fn get_registry( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - t_class: jni::objects::JClass<'mc>, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/Class;)Lorg/bukkit/Registry;"); - let val_1 = jni::objects::JValueGen::Object(t_class.into()); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getRegistry", + /// Performs scalar multiplication, multiplying all components with a + /// scalar. Not world-aware. + pub fn multiply(&self, m: f64) -> Result, Box> { + let sig = String::from("(D)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Double(m); + let res = self.jni_ref().call_method( + &self.jni_object(), + "multiply", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::Registry::from_raw(&jni, obj)?)) - } - #[deprecated] - - pub fn get_unsafe( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/UnsafeValues;"); - let cls = jni.find_class("org/bukkit/Bukkit"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getUnsafe", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::UnsafeValues::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + let res = self.jni_ref().translate_error(res)?; + crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -pub enum Sound<'mc> {} -impl<'mc> std::fmt::Display for Sound<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + /// Zero this location's components. Not world-aware. + pub fn zero(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "zero", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> Sound<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/Sound"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/Sound;", + pub fn equals( + &self, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(Ljava/lang/Object;)Z"); + let val_1 = jni::objects::JValueGen::Object(obj); + let res = self.jni_ref().call_method( + &self.jni_object(), + "equals", + sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -#[repr(C)] -pub struct SoundStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Sound<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for Sound<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Sound from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Sound")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Sound object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } + pub fn hash_code(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} -impl<'mc> JNIRaw<'mc> for SoundStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } -} -impl<'mc> JNIInstantiatable<'mc> for SoundStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate SoundStruct from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Sound")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a SoundStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Constructs a new {@link Vector} based on this Location + pub fn to_vector(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "toVector", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> SoundStruct<'mc> { - pub fn values( + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Check if each component of this Location is finite. + pub fn check_finite(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "checkFinite", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Safely converts a double (location coordinate) to an int (block + /// coordinate) + pub fn loc_to_block( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let cls = jni.find_class("org/bukkit/Sound"); + loc: f64, + ) -> Result> { + let sig = String::from("(D)I"); + let val_1 = jni::objects::JValueGen::Double(loc); + let cls = jni.find_class("org/bukkit/Location"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.call_static_method( + cls, + "locToBlock", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::Sound::from_raw(&jni, obj) + Ok(res.i()?) } - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + pub fn serialize( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Map;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -pub enum CoalType<'mc> {} -impl<'mc> std::fmt::Display for CoalType<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> CoalType<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/CoalType"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( + /// Required method for deserialization + pub fn deserialize( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + val_args: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Ljava/util/Map;)Lorg/bukkit/Location;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_args.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/Location"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/CoalType;", + "deserialize", + sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = env.translate_error(res)?; + let res = jni.translate_error(res)?; let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct CoalTypeStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for CoalType<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for CoalType<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate CoalType from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/CoalType")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a CoalType object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for CoalTypeStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for CoalTypeStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate CoalTypeStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/CoalType")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a CoalTypeStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + crate::Location::from_raw(&jni, obj) } -} - -impl<'mc> CoalTypeStruct<'mc> { - pub fn values( + /// Normalizes the given yaw angle to a value between +/-180 + /// degrees. + pub fn normalize_yaw( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/CoalType;"); - let cls = jni.find_class("org/bukkit/CoalType"); + yaw: f32, + ) -> Result> { + let sig = String::from("(F)F"); + let val_1 = jni::objects::JValueGen::Float(yaw); + let cls = jni.find_class("org/bukkit/Location"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.call_static_method( + cls, + "normalizeYaw", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::CoalType::from_raw(&jni, obj) - } - #[deprecated] - /// Gets the associated data value representing this type of coal - pub fn data(&self) -> Result> { - let sig = String::from("()B"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) + Ok(res.f()?) } - #[deprecated] - /// Gets the type of coal with the given data value - pub fn get_by_data( + /// Normalizes the given pitch angle to a value between +/-90 + /// degrees. + pub fn normalize_pitch( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - data: i8, - ) -> Result>, Box> { - let sig = String::from("(B)Lorg/bukkit/CoalType;"); - let val_1 = jni::objects::JValueGen::Byte(data); - let cls = jni.find_class("org/bukkit/CoalType"); + pitch: f32, + ) -> Result> { + let sig = String::from("(F)F"); + let val_1 = jni::objects::JValueGen::Float(pitch); + let cls = jni.find_class("org/bukkit/Location"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method( cls, - "getByData", + "normalizePitch", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::CoalType::from_raw(&jni, obj)?)) + Ok(res.f()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -7395,152 +57705,120 @@ impl<'mc> CoalTypeStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum SoundCategory<'mc> {} -impl<'mc> std::fmt::Display for SoundCategory<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} -impl<'mc> SoundCategory<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/SoundCategory"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/SoundCategory;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), +impl<'mc> std::string::ToString for Location<'mc> { + fn to_string(&self) -> String { + match &self.internal_to_string() { + Ok(a) => a.clone(), + Err(err) => format!("Error calling Location.toString: {}", err), } } } -#[repr(C)] -pub struct SoundCategoryStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for SoundCategory<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for SoundCategory<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate SoundCategory from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/SoundCategory")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a SoundCategory object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } +impl<'mc> Into> + for Location<'mc> +{ + fn into(self) -> crate::configuration::serialization::ConfigurationSerializable<'mc> { + crate::configuration::serialization::ConfigurationSerializable::from_raw(&self.jni_ref(), self.1).expect("Error converting Location into crate::configuration::serialization::ConfigurationSerializable") } } - -impl<'mc> JNIRaw<'mc> for SoundCategoryStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } +pub enum Instrument<'mc> { + Piano { inner: InstrumentStruct<'mc> }, + BassDrum { inner: InstrumentStruct<'mc> }, + SnareDrum { inner: InstrumentStruct<'mc> }, + Sticks { inner: InstrumentStruct<'mc> }, + BassGuitar { inner: InstrumentStruct<'mc> }, + Flute { inner: InstrumentStruct<'mc> }, + Bell { inner: InstrumentStruct<'mc> }, + Guitar { inner: InstrumentStruct<'mc> }, + Chime { inner: InstrumentStruct<'mc> }, + Xylophone { inner: InstrumentStruct<'mc> }, + IronXylophone { inner: InstrumentStruct<'mc> }, + CowBell { inner: InstrumentStruct<'mc> }, + Didgeridoo { inner: InstrumentStruct<'mc> }, + Bit { inner: InstrumentStruct<'mc> }, + Banjo { inner: InstrumentStruct<'mc> }, + Pling { inner: InstrumentStruct<'mc> }, + Zombie { inner: InstrumentStruct<'mc> }, + Skeleton { inner: InstrumentStruct<'mc> }, + Creeper { inner: InstrumentStruct<'mc> }, + Dragon { inner: InstrumentStruct<'mc> }, + WitherSkeleton { inner: InstrumentStruct<'mc> }, + Piglin { inner: InstrumentStruct<'mc> }, + CustomHead { inner: InstrumentStruct<'mc> }, } -impl<'mc> JNIInstantiatable<'mc> for SoundCategoryStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate SoundCategoryStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/SoundCategory")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a SoundCategoryStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) +impl<'mc> std::fmt::Display for Instrument<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Instrument::Piano { .. } => f.write_str("PIANO"), + Instrument::BassDrum { .. } => f.write_str("BASS_DRUM"), + Instrument::SnareDrum { .. } => f.write_str("SNARE_DRUM"), + Instrument::Sticks { .. } => f.write_str("STICKS"), + Instrument::BassGuitar { .. } => f.write_str("BASS_GUITAR"), + Instrument::Flute { .. } => f.write_str("FLUTE"), + Instrument::Bell { .. } => f.write_str("BELL"), + Instrument::Guitar { .. } => f.write_str("GUITAR"), + Instrument::Chime { .. } => f.write_str("CHIME"), + Instrument::Xylophone { .. } => f.write_str("XYLOPHONE"), + Instrument::IronXylophone { .. } => f.write_str("IRON_XYLOPHONE"), + Instrument::CowBell { .. } => f.write_str("COW_BELL"), + Instrument::Didgeridoo { .. } => f.write_str("DIDGERIDOO"), + Instrument::Bit { .. } => f.write_str("BIT"), + Instrument::Banjo { .. } => f.write_str("BANJO"), + Instrument::Pling { .. } => f.write_str("PLING"), + Instrument::Zombie { .. } => f.write_str("ZOMBIE"), + Instrument::Skeleton { .. } => f.write_str("SKELETON"), + Instrument::Creeper { .. } => f.write_str("CREEPER"), + Instrument::Dragon { .. } => f.write_str("DRAGON"), + Instrument::WitherSkeleton { .. } => f.write_str("WITHER_SKELETON"), + Instrument::Piglin { .. } => f.write_str("PIGLIN"), + Instrument::CustomHead { .. } => f.write_str("CUSTOM_HEAD"), } } } - -impl<'mc> SoundCategoryStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/SoundCategory;"); - let cls = jni.find_class("org/bukkit/SoundCategory"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::SoundCategory::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -pub enum CropState<'mc> {} -impl<'mc> std::fmt::Display for CropState<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} +impl<'mc> std::ops::Deref for Instrument<'mc> { + type Target = InstrumentStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + Instrument::Piano { inner } => inner, + Instrument::BassDrum { inner } => inner, + Instrument::SnareDrum { inner } => inner, + Instrument::Sticks { inner } => inner, + Instrument::BassGuitar { inner } => inner, + Instrument::Flute { inner } => inner, + Instrument::Bell { inner } => inner, + Instrument::Guitar { inner } => inner, + Instrument::Chime { inner } => inner, + Instrument::Xylophone { inner } => inner, + Instrument::IronXylophone { inner } => inner, + Instrument::CowBell { inner } => inner, + Instrument::Didgeridoo { inner } => inner, + Instrument::Bit { inner } => inner, + Instrument::Banjo { inner } => inner, + Instrument::Pling { inner } => inner, + Instrument::Zombie { inner } => inner, + Instrument::Skeleton { inner } => inner, + Instrument::Creeper { inner } => inner, + Instrument::Dragon { inner } => inner, + Instrument::WitherSkeleton { inner } => inner, + Instrument::Piglin { inner } => inner, + Instrument::CustomHead { inner } => inner, + } } } -impl<'mc> CropState<'mc> { +impl<'mc> Instrument<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/CropState"); + let cls = env.find_class("org/bukkit/Instrument"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/CropState;", + "(Ljava/lang/String;)Lorg/bukkit/Instrument;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -7552,37 +57830,169 @@ impl<'mc> CropState<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "PIANO" => Ok(Instrument::Piano { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "BASS_DRUM" => Ok(Instrument::BassDrum { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "SNARE_DRUM" => Ok(Instrument::SnareDrum { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "STICKS" => Ok(Instrument::Sticks { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "BASS_GUITAR" => Ok(Instrument::BassGuitar { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "FLUTE" => Ok(Instrument::Flute { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "BELL" => Ok(Instrument::Bell { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "GUITAR" => Ok(Instrument::Guitar { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "CHIME" => Ok(Instrument::Chime { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "XYLOPHONE" => Ok(Instrument::Xylophone { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "IRON_XYLOPHONE" => Ok(Instrument::IronXylophone { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "COW_BELL" => Ok(Instrument::CowBell { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "DIDGERIDOO" => Ok(Instrument::Didgeridoo { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "BIT" => Ok(Instrument::Bit { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "BANJO" => Ok(Instrument::Banjo { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "PLING" => Ok(Instrument::Pling { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "ZOMBIE" => Ok(Instrument::Zombie { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "SKELETON" => Ok(Instrument::Skeleton { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "CREEPER" => Ok(Instrument::Creeper { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "DRAGON" => Ok(Instrument::Dragon { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "WITHER_SKELETON" => Ok(Instrument::WitherSkeleton { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "PIGLIN" => Ok(Instrument::Piglin { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "CUSTOM_HEAD" => Ok(Instrument::CustomHead { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct CropStateStruct<'mc>( +pub struct InstrumentStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for CropState<'mc> { +impl<'mc> JNIRaw<'mc> for Instrument<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Piano { inner } => inner.0.clone(), + Self::BassDrum { inner } => inner.0.clone(), + Self::SnareDrum { inner } => inner.0.clone(), + Self::Sticks { inner } => inner.0.clone(), + Self::BassGuitar { inner } => inner.0.clone(), + Self::Flute { inner } => inner.0.clone(), + Self::Bell { inner } => inner.0.clone(), + Self::Guitar { inner } => inner.0.clone(), + Self::Chime { inner } => inner.0.clone(), + Self::Xylophone { inner } => inner.0.clone(), + Self::IronXylophone { inner } => inner.0.clone(), + Self::CowBell { inner } => inner.0.clone(), + Self::Didgeridoo { inner } => inner.0.clone(), + Self::Bit { inner } => inner.0.clone(), + Self::Banjo { inner } => inner.0.clone(), + Self::Pling { inner } => inner.0.clone(), + Self::Zombie { inner } => inner.0.clone(), + Self::Skeleton { inner } => inner.0.clone(), + Self::Creeper { inner } => inner.0.clone(), + Self::Dragon { inner } => inner.0.clone(), + Self::WitherSkeleton { inner } => inner.0.clone(), + Self::Piglin { inner } => inner.0.clone(), + Self::CustomHead { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Piano { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BassDrum { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SnareDrum { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Sticks { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BassGuitar { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Flute { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Bell { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Guitar { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Chime { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Xylophone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronXylophone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CowBell { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Didgeridoo { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Bit { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Banjo { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Pling { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Zombie { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Skeleton { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Creeper { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Dragon { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::WitherSkeleton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Piglin { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CustomHead { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } -impl<'mc> JNIInstantiatable<'mc> for CropState<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Instrument<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate CropState from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Instrument from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/CropState")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/Instrument")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a CropState object, got {}", + "Invalid argument passed. Expected a Instrument object, got {}", name ) .into()) @@ -7594,13 +58004,82 @@ impl<'mc> JNIInstantiatable<'mc> for CropState<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "PIANO" => Ok(Instrument::Piano { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "BASS_DRUM" => Ok(Instrument::BassDrum { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "SNARE_DRUM" => Ok(Instrument::SnareDrum { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "STICKS" => Ok(Instrument::Sticks { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "BASS_GUITAR" => Ok(Instrument::BassGuitar { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "FLUTE" => Ok(Instrument::Flute { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "BELL" => Ok(Instrument::Bell { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "GUITAR" => Ok(Instrument::Guitar { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "CHIME" => Ok(Instrument::Chime { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "XYLOPHONE" => Ok(Instrument::Xylophone { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "IRON_XYLOPHONE" => Ok(Instrument::IronXylophone { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "COW_BELL" => Ok(Instrument::CowBell { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "DIDGERIDOO" => Ok(Instrument::Didgeridoo { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "BIT" => Ok(Instrument::Bit { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "BANJO" => Ok(Instrument::Banjo { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "PLING" => Ok(Instrument::Pling { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "ZOMBIE" => Ok(Instrument::Zombie { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "SKELETON" => Ok(Instrument::Skeleton { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "CREEPER" => Ok(Instrument::Creeper { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "DRAGON" => Ok(Instrument::Dragon { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "WITHER_SKELETON" => Ok(Instrument::WitherSkeleton { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "PIGLIN" => Ok(Instrument::Piglin { + inner: InstrumentStruct::from_raw(env, obj)?, + }), + "CUSTOM_HEAD" => Ok(Instrument::CustomHead { + inner: InstrumentStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for CropStateStruct<'mc> { +impl<'mc> JNIRaw<'mc> for InstrumentStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -7608,20 +58087,20 @@ impl<'mc> JNIRaw<'mc> for CropStateStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for CropStateStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for InstrumentStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate CropStateStruct from null object.").into(), + eyre::eyre!("Tried to instantiate InstrumentStruct from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/CropState")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/Instrument")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a CropStateStruct object, got {}", + "Invalid argument passed. Expected a InstrumentStruct object, got {}", name ) .into()) @@ -7631,41 +58110,57 @@ impl<'mc> JNIInstantiatable<'mc> for CropStateStruct<'mc> { } } -impl<'mc> CropStateStruct<'mc> { +impl<'mc> InstrumentStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/CropState;"); - let cls = jni.find_class("org/bukkit/CropState"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Instrument;"); + let cls = jni.find_class("org/bukkit/Instrument"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::CropState::from_raw(&jni, obj) + crate::Instrument::from_raw(&jni, obj) + } + /// Gets the sound associated with this instrument. + /// + /// Will be null for {@link Instrument#CUSTOM_HEAD} + pub fn sound(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } #[deprecated] - /// Gets the associated data value representing this growth state - pub fn data(&self) -> Result> { + + pub fn get_type(&self) -> Result> { let sig = String::from("()B"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.b()?) } #[deprecated] - /// Gets the CropState with the given data value - pub fn get_by_data( + /// Get an instrument by its type ID. + pub fn get_by_type( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - data: i8, - ) -> Result>, Box> { - let sig = String::from("(B)Lorg/bukkit/CropState;"); - let val_1 = jni::objects::JValueGen::Byte(data); - let cls = jni.find_class("org/bukkit/CropState"); + val_type: i8, + ) -> Result>, Box> { + let sig = String::from("(B)Lorg/bukkit/Instrument;"); + let val_1 = jni::objects::JValueGen::Byte(val_type); + let cls = jni.find_class("org/bukkit/Instrument"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method( cls, - "getByData", + "getByType", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -7674,7 +58169,7 @@ impl<'mc> CropStateStruct<'mc> { return Ok(None); } let obj = res.l()?; - Ok(Some(crate::CropState::from_raw(&jni, obj)?)) + Ok(Some(crate::Instrument::from_raw(&jni, obj)?)) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -7682,25 +58177,43 @@ impl<'mc> CropStateStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum Effect<'mc> {} -impl<'mc> std::fmt::Display for Effect<'mc> { +pub enum GrassSpecies<'mc> { + Dead { inner: GrassSpeciesStruct<'mc> }, + Normal { inner: GrassSpeciesStruct<'mc> }, + FernLike { inner: GrassSpeciesStruct<'mc> }, +} +impl<'mc> std::fmt::Display for GrassSpecies<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + GrassSpecies::Dead { .. } => f.write_str("DEAD"), + GrassSpecies::Normal { .. } => f.write_str("NORMAL"), + GrassSpecies::FernLike { .. } => f.write_str("FERN_LIKE"), + } + } +} +impl<'mc> std::ops::Deref for GrassSpecies<'mc> { + type Target = GrassSpeciesStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + GrassSpecies::Dead { inner } => inner, + GrassSpecies::Normal { inner } => inner, + GrassSpecies::FernLike { inner } => inner, + } } } -impl<'mc> Effect<'mc> { +impl<'mc> GrassSpecies<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/Effect"); + let cls = env.find_class("org/bukkit/GrassSpecies"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/Effect;", + "(Ljava/lang/String;)Lorg/bukkit/GrassSpecies;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -7712,37 +58225,55 @@ impl<'mc> Effect<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "DEAD" => Ok(GrassSpecies::Dead { + inner: GrassSpeciesStruct::from_raw(env, obj)?, + }), + "NORMAL" => Ok(GrassSpecies::Normal { + inner: GrassSpeciesStruct::from_raw(env, obj)?, + }), + "FERN_LIKE" => Ok(GrassSpecies::FernLike { + inner: GrassSpeciesStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct EffectStruct<'mc>( +pub struct GrassSpeciesStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Effect<'mc> { +impl<'mc> JNIRaw<'mc> for GrassSpecies<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Dead { inner } => inner.0.clone(), + Self::Normal { inner } => inner.0.clone(), + Self::FernLike { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Dead { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Normal { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::FernLike { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for Effect<'mc> { +impl<'mc> JNIInstantiatable<'mc> for GrassSpecies<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Effect from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate GrassSpecies from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Effect")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/GrassSpecies")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Effect object, got {}", + "Invalid argument passed. Expected a GrassSpecies object, got {}", name ) .into()) @@ -7754,13 +58285,22 @@ impl<'mc> JNIInstantiatable<'mc> for Effect<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "DEAD" => Ok(GrassSpecies::Dead { + inner: GrassSpeciesStruct::from_raw(env, obj)?, + }), + "NORMAL" => Ok(GrassSpecies::Normal { + inner: GrassSpeciesStruct::from_raw(env, obj)?, + }), + "FERN_LIKE" => Ok(GrassSpecies::FernLike { + inner: GrassSpeciesStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for EffectStruct<'mc> { +impl<'mc> JNIRaw<'mc> for GrassSpeciesStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -7768,18 +58308,20 @@ impl<'mc> JNIRaw<'mc> for EffectStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EffectStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for GrassSpeciesStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate EffectStruct from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate GrassSpeciesStruct from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Effect")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/GrassSpecies")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EffectStruct object, got {}", + "Invalid argument passed. Expected a GrassSpeciesStruct object, got {}", name ) .into()) @@ -7789,52 +58331,41 @@ impl<'mc> JNIInstantiatable<'mc> for EffectStruct<'mc> { } } -impl<'mc> EffectStruct<'mc> { +impl<'mc> GrassSpeciesStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Effect;"); - let cls = jni.find_class("org/bukkit/Effect"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/GrassSpecies;"); + let cls = jni.find_class("org/bukkit/GrassSpecies"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::Effect::from_raw(&jni, obj) + crate::GrassSpecies::from_raw(&jni, obj) } #[deprecated] - /// Gets the ID for this effect. - pub fn id(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Effect/Type;"); + /// Gets the associated data value representing this species + pub fn data(&self) -> Result> { + let sig = String::from("()B"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::EffectType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.b()?) } #[deprecated] - /// Gets the Effect associated with the given ID. - pub fn get_by_id( + /// Gets the GrassSpecies with the given data value + pub fn get_by_data( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - id: i32, - ) -> Result>, Box> { - let sig = String::from("(I)Lorg/bukkit/Effect;"); - let val_1 = jni::objects::JValueGen::Int(id); - let cls = jni.find_class("org/bukkit/Effect"); + data: i8, + ) -> Result>, Box> { + let sig = String::from("(B)Lorg/bukkit/GrassSpecies;"); + let val_1 = jni::objects::JValueGen::Byte(data); + let cls = jni.find_class("org/bukkit/GrassSpecies"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method( cls, - "getById", + "getByData", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -7843,7 +58374,7 @@ impl<'mc> EffectStruct<'mc> { return Ok(None); } let obj = res.l()?; - Ok(Some(crate::Effect::from_raw(&jni, obj)?)) + Ok(Some(crate::GrassSpecies::from_raw(&jni, obj)?)) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -7851,25 +58382,201 @@ impl<'mc> EffectStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum EffectType<'mc> {} -impl<'mc> std::fmt::Display for EffectType<'mc> { +pub enum GameRule<'mc> { + AnnounceAdvancements { inner: GameRuleStruct<'mc> }, + CommandBlockOutput { inner: GameRuleStruct<'mc> }, + DisableElytraMovementCheck { inner: GameRuleStruct<'mc> }, + DoDaylightCycle { inner: GameRuleStruct<'mc> }, + DoEntityDrops { inner: GameRuleStruct<'mc> }, + DoFireTick { inner: GameRuleStruct<'mc> }, + DoLimitedCrafting { inner: GameRuleStruct<'mc> }, + DoMobLoot { inner: GameRuleStruct<'mc> }, + ProjectilesCanBreakBlocks { inner: GameRuleStruct<'mc> }, + DoMobSpawning { inner: GameRuleStruct<'mc> }, + DoTileDrops { inner: GameRuleStruct<'mc> }, + DoWeatherCycle { inner: GameRuleStruct<'mc> }, + KeepInventory { inner: GameRuleStruct<'mc> }, + LogAdminCommands { inner: GameRuleStruct<'mc> }, + MobGriefing { inner: GameRuleStruct<'mc> }, + NaturalRegeneration { inner: GameRuleStruct<'mc> }, + ReducedDebugInfo { inner: GameRuleStruct<'mc> }, + SendCommandFeedback { inner: GameRuleStruct<'mc> }, + ShowDeathMessages { inner: GameRuleStruct<'mc> }, + SpectatorsGenerateChunks { inner: GameRuleStruct<'mc> }, + DisableRaids { inner: GameRuleStruct<'mc> }, + DoInsomnia { inner: GameRuleStruct<'mc> }, + DoImmediateRespawn { inner: GameRuleStruct<'mc> }, + DrowningDamage { inner: GameRuleStruct<'mc> }, + FallDamage { inner: GameRuleStruct<'mc> }, + FireDamage { inner: GameRuleStruct<'mc> }, + FreezeDamage { inner: GameRuleStruct<'mc> }, + DoPatrolSpawning { inner: GameRuleStruct<'mc> }, + DoTraderSpawning { inner: GameRuleStruct<'mc> }, + DoWardenSpawning { inner: GameRuleStruct<'mc> }, + ForgiveDeadPlayers { inner: GameRuleStruct<'mc> }, + UniversalAnger { inner: GameRuleStruct<'mc> }, + BlockExplosionDropDecay { inner: GameRuleStruct<'mc> }, + MobExplosionDropDecay { inner: GameRuleStruct<'mc> }, + TntExplosionDropDecay { inner: GameRuleStruct<'mc> }, + WaterSourceConversion { inner: GameRuleStruct<'mc> }, + LavaSourceConversion { inner: GameRuleStruct<'mc> }, + GlobalSoundEvents { inner: GameRuleStruct<'mc> }, + DoVinesSpread { inner: GameRuleStruct<'mc> }, + EnderPearlsVanishOnDeath { inner: GameRuleStruct<'mc> }, + RandomTickSpeed { inner: GameRuleStruct<'mc> }, + SpawnRadius { inner: GameRuleStruct<'mc> }, + MaxEntityCramming { inner: GameRuleStruct<'mc> }, + MaxCommandChainLength { inner: GameRuleStruct<'mc> }, + MaxCommandForkCount { inner: GameRuleStruct<'mc> }, + CommandModificationBlockLimit { inner: GameRuleStruct<'mc> }, + PlayersSleepingPercentage { inner: GameRuleStruct<'mc> }, + SnowAccumulationHeight { inner: GameRuleStruct<'mc> }, + PlayersNetherPortalDefaultDelay { inner: GameRuleStruct<'mc> }, + PlayersNetherPortalCreativeDelay { inner: GameRuleStruct<'mc> }, + SpawnChunkRadius { inner: GameRuleStruct<'mc> }, +} +impl<'mc> std::fmt::Display for GameRule<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + GameRule::AnnounceAdvancements { .. } => f.write_str("ANNOUNCE_ADVANCEMENTS"), + GameRule::CommandBlockOutput { .. } => f.write_str("COMMAND_BLOCK_OUTPUT"), + GameRule::DisableElytraMovementCheck { .. } => { + f.write_str("DISABLE_ELYTRA_MOVEMENT_CHECK") + } + GameRule::DoDaylightCycle { .. } => f.write_str("DO_DAYLIGHT_CYCLE"), + GameRule::DoEntityDrops { .. } => f.write_str("DO_ENTITY_DROPS"), + GameRule::DoFireTick { .. } => f.write_str("DO_FIRE_TICK"), + GameRule::DoLimitedCrafting { .. } => f.write_str("DO_LIMITED_CRAFTING"), + GameRule::DoMobLoot { .. } => f.write_str("DO_MOB_LOOT"), + GameRule::ProjectilesCanBreakBlocks { .. } => { + f.write_str("PROJECTILES_CAN_BREAK_BLOCKS") + } + GameRule::DoMobSpawning { .. } => f.write_str("DO_MOB_SPAWNING"), + GameRule::DoTileDrops { .. } => f.write_str("DO_TILE_DROPS"), + GameRule::DoWeatherCycle { .. } => f.write_str("DO_WEATHER_CYCLE"), + GameRule::KeepInventory { .. } => f.write_str("KEEP_INVENTORY"), + GameRule::LogAdminCommands { .. } => f.write_str("LOG_ADMIN_COMMANDS"), + GameRule::MobGriefing { .. } => f.write_str("MOB_GRIEFING"), + GameRule::NaturalRegeneration { .. } => f.write_str("NATURAL_REGENERATION"), + GameRule::ReducedDebugInfo { .. } => f.write_str("REDUCED_DEBUG_INFO"), + GameRule::SendCommandFeedback { .. } => f.write_str("SEND_COMMAND_FEEDBACK"), + GameRule::ShowDeathMessages { .. } => f.write_str("SHOW_DEATH_MESSAGES"), + GameRule::SpectatorsGenerateChunks { .. } => f.write_str("SPECTATORS_GENERATE_CHUNKS"), + GameRule::DisableRaids { .. } => f.write_str("DISABLE_RAIDS"), + GameRule::DoInsomnia { .. } => f.write_str("DO_INSOMNIA"), + GameRule::DoImmediateRespawn { .. } => f.write_str("DO_IMMEDIATE_RESPAWN"), + GameRule::DrowningDamage { .. } => f.write_str("DROWNING_DAMAGE"), + GameRule::FallDamage { .. } => f.write_str("FALL_DAMAGE"), + GameRule::FireDamage { .. } => f.write_str("FIRE_DAMAGE"), + GameRule::FreezeDamage { .. } => f.write_str("FREEZE_DAMAGE"), + GameRule::DoPatrolSpawning { .. } => f.write_str("DO_PATROL_SPAWNING"), + GameRule::DoTraderSpawning { .. } => f.write_str("DO_TRADER_SPAWNING"), + GameRule::DoWardenSpawning { .. } => f.write_str("DO_WARDEN_SPAWNING"), + GameRule::ForgiveDeadPlayers { .. } => f.write_str("FORGIVE_DEAD_PLAYERS"), + GameRule::UniversalAnger { .. } => f.write_str("UNIVERSAL_ANGER"), + GameRule::BlockExplosionDropDecay { .. } => f.write_str("BLOCK_EXPLOSION_DROP_DECAY"), + GameRule::MobExplosionDropDecay { .. } => f.write_str("MOB_EXPLOSION_DROP_DECAY"), + GameRule::TntExplosionDropDecay { .. } => f.write_str("TNT_EXPLOSION_DROP_DECAY"), + GameRule::WaterSourceConversion { .. } => f.write_str("WATER_SOURCE_CONVERSION"), + GameRule::LavaSourceConversion { .. } => f.write_str("LAVA_SOURCE_CONVERSION"), + GameRule::GlobalSoundEvents { .. } => f.write_str("GLOBAL_SOUND_EVENTS"), + GameRule::DoVinesSpread { .. } => f.write_str("DO_VINES_SPREAD"), + GameRule::EnderPearlsVanishOnDeath { .. } => { + f.write_str("ENDER_PEARLS_VANISH_ON_DEATH") + } + GameRule::RandomTickSpeed { .. } => f.write_str("RANDOM_TICK_SPEED"), + GameRule::SpawnRadius { .. } => f.write_str("SPAWN_RADIUS"), + GameRule::MaxEntityCramming { .. } => f.write_str("MAX_ENTITY_CRAMMING"), + GameRule::MaxCommandChainLength { .. } => f.write_str("MAX_COMMAND_CHAIN_LENGTH"), + GameRule::MaxCommandForkCount { .. } => f.write_str("MAX_COMMAND_FORK_COUNT"), + GameRule::CommandModificationBlockLimit { .. } => { + f.write_str("COMMAND_MODIFICATION_BLOCK_LIMIT") + } + GameRule::PlayersSleepingPercentage { .. } => { + f.write_str("PLAYERS_SLEEPING_PERCENTAGE") + } + GameRule::SnowAccumulationHeight { .. } => f.write_str("SNOW_ACCUMULATION_HEIGHT"), + GameRule::PlayersNetherPortalDefaultDelay { .. } => { + f.write_str("PLAYERS_NETHER_PORTAL_DEFAULT_DELAY") + } + GameRule::PlayersNetherPortalCreativeDelay { .. } => { + f.write_str("PLAYERS_NETHER_PORTAL_CREATIVE_DELAY") + } + GameRule::SpawnChunkRadius { .. } => f.write_str("SPAWN_CHUNK_RADIUS"), + } + } +} +impl<'mc> std::ops::Deref for GameRule<'mc> { + type Target = GameRuleStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + GameRule::AnnounceAdvancements { inner } => inner, + GameRule::CommandBlockOutput { inner } => inner, + GameRule::DisableElytraMovementCheck { inner } => inner, + GameRule::DoDaylightCycle { inner } => inner, + GameRule::DoEntityDrops { inner } => inner, + GameRule::DoFireTick { inner } => inner, + GameRule::DoLimitedCrafting { inner } => inner, + GameRule::DoMobLoot { inner } => inner, + GameRule::ProjectilesCanBreakBlocks { inner } => inner, + GameRule::DoMobSpawning { inner } => inner, + GameRule::DoTileDrops { inner } => inner, + GameRule::DoWeatherCycle { inner } => inner, + GameRule::KeepInventory { inner } => inner, + GameRule::LogAdminCommands { inner } => inner, + GameRule::MobGriefing { inner } => inner, + GameRule::NaturalRegeneration { inner } => inner, + GameRule::ReducedDebugInfo { inner } => inner, + GameRule::SendCommandFeedback { inner } => inner, + GameRule::ShowDeathMessages { inner } => inner, + GameRule::SpectatorsGenerateChunks { inner } => inner, + GameRule::DisableRaids { inner } => inner, + GameRule::DoInsomnia { inner } => inner, + GameRule::DoImmediateRespawn { inner } => inner, + GameRule::DrowningDamage { inner } => inner, + GameRule::FallDamage { inner } => inner, + GameRule::FireDamage { inner } => inner, + GameRule::FreezeDamage { inner } => inner, + GameRule::DoPatrolSpawning { inner } => inner, + GameRule::DoTraderSpawning { inner } => inner, + GameRule::DoWardenSpawning { inner } => inner, + GameRule::ForgiveDeadPlayers { inner } => inner, + GameRule::UniversalAnger { inner } => inner, + GameRule::BlockExplosionDropDecay { inner } => inner, + GameRule::MobExplosionDropDecay { inner } => inner, + GameRule::TntExplosionDropDecay { inner } => inner, + GameRule::WaterSourceConversion { inner } => inner, + GameRule::LavaSourceConversion { inner } => inner, + GameRule::GlobalSoundEvents { inner } => inner, + GameRule::DoVinesSpread { inner } => inner, + GameRule::EnderPearlsVanishOnDeath { inner } => inner, + GameRule::RandomTickSpeed { inner } => inner, + GameRule::SpawnRadius { inner } => inner, + GameRule::MaxEntityCramming { inner } => inner, + GameRule::MaxCommandChainLength { inner } => inner, + GameRule::MaxCommandForkCount { inner } => inner, + GameRule::CommandModificationBlockLimit { inner } => inner, + GameRule::PlayersSleepingPercentage { inner } => inner, + GameRule::SnowAccumulationHeight { inner } => inner, + GameRule::PlayersNetherPortalDefaultDelay { inner } => inner, + GameRule::PlayersNetherPortalCreativeDelay { inner } => inner, + GameRule::SpawnChunkRadius { inner } => inner, + } } } -impl<'mc> EffectType<'mc> { +impl<'mc> GameRule<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/Effect/Type"); + let cls = env.find_class("org/bukkit/GameRule"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/Effect/Type;", + "(Ljava/lang/String;)Lorg/bukkit/GameRule;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -7881,37 +58588,401 @@ impl<'mc> EffectType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "ANNOUNCE_ADVANCEMENTS" => Ok(GameRule::AnnounceAdvancements { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "COMMAND_BLOCK_OUTPUT" => Ok(GameRule::CommandBlockOutput { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DISABLE_ELYTRA_MOVEMENT_CHECK" => Ok(GameRule::DisableElytraMovementCheck { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_DAYLIGHT_CYCLE" => Ok(GameRule::DoDaylightCycle { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_ENTITY_DROPS" => Ok(GameRule::DoEntityDrops { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_FIRE_TICK" => Ok(GameRule::DoFireTick { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_LIMITED_CRAFTING" => Ok(GameRule::DoLimitedCrafting { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_MOB_LOOT" => Ok(GameRule::DoMobLoot { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "PROJECTILES_CAN_BREAK_BLOCKS" => Ok(GameRule::ProjectilesCanBreakBlocks { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_MOB_SPAWNING" => Ok(GameRule::DoMobSpawning { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_TILE_DROPS" => Ok(GameRule::DoTileDrops { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_WEATHER_CYCLE" => Ok(GameRule::DoWeatherCycle { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "KEEP_INVENTORY" => Ok(GameRule::KeepInventory { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "LOG_ADMIN_COMMANDS" => Ok(GameRule::LogAdminCommands { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "MOB_GRIEFING" => Ok(GameRule::MobGriefing { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "NATURAL_REGENERATION" => Ok(GameRule::NaturalRegeneration { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "REDUCED_DEBUG_INFO" => Ok(GameRule::ReducedDebugInfo { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "SEND_COMMAND_FEEDBACK" => Ok(GameRule::SendCommandFeedback { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "SHOW_DEATH_MESSAGES" => Ok(GameRule::ShowDeathMessages { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "SPECTATORS_GENERATE_CHUNKS" => Ok(GameRule::SpectatorsGenerateChunks { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DISABLE_RAIDS" => Ok(GameRule::DisableRaids { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_INSOMNIA" => Ok(GameRule::DoInsomnia { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_IMMEDIATE_RESPAWN" => Ok(GameRule::DoImmediateRespawn { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DROWNING_DAMAGE" => Ok(GameRule::DrowningDamage { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "FALL_DAMAGE" => Ok(GameRule::FallDamage { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "FIRE_DAMAGE" => Ok(GameRule::FireDamage { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "FREEZE_DAMAGE" => Ok(GameRule::FreezeDamage { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_PATROL_SPAWNING" => Ok(GameRule::DoPatrolSpawning { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_TRADER_SPAWNING" => Ok(GameRule::DoTraderSpawning { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_WARDEN_SPAWNING" => Ok(GameRule::DoWardenSpawning { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "FORGIVE_DEAD_PLAYERS" => Ok(GameRule::ForgiveDeadPlayers { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "UNIVERSAL_ANGER" => Ok(GameRule::UniversalAnger { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "BLOCK_EXPLOSION_DROP_DECAY" => Ok(GameRule::BlockExplosionDropDecay { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "MOB_EXPLOSION_DROP_DECAY" => Ok(GameRule::MobExplosionDropDecay { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "TNT_EXPLOSION_DROP_DECAY" => Ok(GameRule::TntExplosionDropDecay { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "WATER_SOURCE_CONVERSION" => Ok(GameRule::WaterSourceConversion { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "LAVA_SOURCE_CONVERSION" => Ok(GameRule::LavaSourceConversion { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "GLOBAL_SOUND_EVENTS" => Ok(GameRule::GlobalSoundEvents { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_VINES_SPREAD" => Ok(GameRule::DoVinesSpread { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "ENDER_PEARLS_VANISH_ON_DEATH" => Ok(GameRule::EnderPearlsVanishOnDeath { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "RANDOM_TICK_SPEED" => Ok(GameRule::RandomTickSpeed { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "SPAWN_RADIUS" => Ok(GameRule::SpawnRadius { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "MAX_ENTITY_CRAMMING" => Ok(GameRule::MaxEntityCramming { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "MAX_COMMAND_CHAIN_LENGTH" => Ok(GameRule::MaxCommandChainLength { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "MAX_COMMAND_FORK_COUNT" => Ok(GameRule::MaxCommandForkCount { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "COMMAND_MODIFICATION_BLOCK_LIMIT" => Ok(GameRule::CommandModificationBlockLimit { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "PLAYERS_SLEEPING_PERCENTAGE" => Ok(GameRule::PlayersSleepingPercentage { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "SNOW_ACCUMULATION_HEIGHT" => Ok(GameRule::SnowAccumulationHeight { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "PLAYERS_NETHER_PORTAL_DEFAULT_DELAY" => { + Ok(GameRule::PlayersNetherPortalDefaultDelay { + inner: GameRuleStruct::from_raw(env, obj)?, + }) + } + "PLAYERS_NETHER_PORTAL_CREATIVE_DELAY" => { + Ok(GameRule::PlayersNetherPortalCreativeDelay { + inner: GameRuleStruct::from_raw(env, obj)?, + }) + } + "SPAWN_CHUNK_RADIUS" => Ok(GameRule::SpawnChunkRadius { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } - -#[repr(C)] -pub struct EffectTypeStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for EffectType<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for EffectType<'mc> { + +#[repr(C)] +pub struct GameRuleStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for GameRule<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::AnnounceAdvancements { inner } => inner.0.clone(), + Self::CommandBlockOutput { inner } => inner.0.clone(), + Self::DisableElytraMovementCheck { inner } => inner.0.clone(), + Self::DoDaylightCycle { inner } => inner.0.clone(), + Self::DoEntityDrops { inner } => inner.0.clone(), + Self::DoFireTick { inner } => inner.0.clone(), + Self::DoLimitedCrafting { inner } => inner.0.clone(), + Self::DoMobLoot { inner } => inner.0.clone(), + Self::ProjectilesCanBreakBlocks { inner } => inner.0.clone(), + Self::DoMobSpawning { inner } => inner.0.clone(), + Self::DoTileDrops { inner } => inner.0.clone(), + Self::DoWeatherCycle { inner } => inner.0.clone(), + Self::KeepInventory { inner } => inner.0.clone(), + Self::LogAdminCommands { inner } => inner.0.clone(), + Self::MobGriefing { inner } => inner.0.clone(), + Self::NaturalRegeneration { inner } => inner.0.clone(), + Self::ReducedDebugInfo { inner } => inner.0.clone(), + Self::SendCommandFeedback { inner } => inner.0.clone(), + Self::ShowDeathMessages { inner } => inner.0.clone(), + Self::SpectatorsGenerateChunks { inner } => inner.0.clone(), + Self::DisableRaids { inner } => inner.0.clone(), + Self::DoInsomnia { inner } => inner.0.clone(), + Self::DoImmediateRespawn { inner } => inner.0.clone(), + Self::DrowningDamage { inner } => inner.0.clone(), + Self::FallDamage { inner } => inner.0.clone(), + Self::FireDamage { inner } => inner.0.clone(), + Self::FreezeDamage { inner } => inner.0.clone(), + Self::DoPatrolSpawning { inner } => inner.0.clone(), + Self::DoTraderSpawning { inner } => inner.0.clone(), + Self::DoWardenSpawning { inner } => inner.0.clone(), + Self::ForgiveDeadPlayers { inner } => inner.0.clone(), + Self::UniversalAnger { inner } => inner.0.clone(), + Self::BlockExplosionDropDecay { inner } => inner.0.clone(), + Self::MobExplosionDropDecay { inner } => inner.0.clone(), + Self::TntExplosionDropDecay { inner } => inner.0.clone(), + Self::WaterSourceConversion { inner } => inner.0.clone(), + Self::LavaSourceConversion { inner } => inner.0.clone(), + Self::GlobalSoundEvents { inner } => inner.0.clone(), + Self::DoVinesSpread { inner } => inner.0.clone(), + Self::EnderPearlsVanishOnDeath { inner } => inner.0.clone(), + Self::RandomTickSpeed { inner } => inner.0.clone(), + Self::SpawnRadius { inner } => inner.0.clone(), + Self::MaxEntityCramming { inner } => inner.0.clone(), + Self::MaxCommandChainLength { inner } => inner.0.clone(), + Self::MaxCommandForkCount { inner } => inner.0.clone(), + Self::CommandModificationBlockLimit { inner } => inner.0.clone(), + Self::PlayersSleepingPercentage { inner } => inner.0.clone(), + Self::SnowAccumulationHeight { inner } => inner.0.clone(), + Self::PlayersNetherPortalDefaultDelay { inner } => inner.0.clone(), + Self::PlayersNetherPortalCreativeDelay { inner } => inner.0.clone(), + Self::SpawnChunkRadius { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::AnnounceAdvancements { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CommandBlockOutput { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DisableElytraMovementCheck { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DoDaylightCycle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DoEntityDrops { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DoFireTick { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DoLimitedCrafting { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DoMobLoot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ProjectilesCanBreakBlocks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DoMobSpawning { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DoTileDrops { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DoWeatherCycle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::KeepInventory { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LogAdminCommands { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MobGriefing { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NaturalRegeneration { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ReducedDebugInfo { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SendCommandFeedback { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ShowDeathMessages { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SpectatorsGenerateChunks { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DisableRaids { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DoInsomnia { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DoImmediateRespawn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DrowningDamage { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FallDamage { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FireDamage { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FreezeDamage { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DoPatrolSpawning { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DoTraderSpawning { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DoWardenSpawning { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ForgiveDeadPlayers { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::UniversalAnger { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlockExplosionDropDecay { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MobExplosionDropDecay { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TntExplosionDropDecay { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaterSourceConversion { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LavaSourceConversion { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GlobalSoundEvents { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DoVinesSpread { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnderPearlsVanishOnDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RandomTickSpeed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SpawnRadius { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MaxEntityCramming { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MaxCommandChainLength { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MaxCommandForkCount { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CommandModificationBlockLimit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PlayersSleepingPercentage { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SnowAccumulationHeight { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PlayersNetherPortalDefaultDelay { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PlayersNetherPortalCreativeDelay { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SpawnChunkRadius { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for GameRule<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate EffectType from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate GameRule from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Effect/Type")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/GameRule")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EffectType object, got {}", + "Invalid argument passed. Expected a GameRule object, got {}", name ) .into()) @@ -7923,13 +58994,170 @@ impl<'mc> JNIInstantiatable<'mc> for EffectType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "ANNOUNCE_ADVANCEMENTS" => Ok(GameRule::AnnounceAdvancements { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "COMMAND_BLOCK_OUTPUT" => Ok(GameRule::CommandBlockOutput { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DISABLE_ELYTRA_MOVEMENT_CHECK" => Ok(GameRule::DisableElytraMovementCheck { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_DAYLIGHT_CYCLE" => Ok(GameRule::DoDaylightCycle { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_ENTITY_DROPS" => Ok(GameRule::DoEntityDrops { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_FIRE_TICK" => Ok(GameRule::DoFireTick { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_LIMITED_CRAFTING" => Ok(GameRule::DoLimitedCrafting { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_MOB_LOOT" => Ok(GameRule::DoMobLoot { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "PROJECTILES_CAN_BREAK_BLOCKS" => Ok(GameRule::ProjectilesCanBreakBlocks { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_MOB_SPAWNING" => Ok(GameRule::DoMobSpawning { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_TILE_DROPS" => Ok(GameRule::DoTileDrops { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_WEATHER_CYCLE" => Ok(GameRule::DoWeatherCycle { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "KEEP_INVENTORY" => Ok(GameRule::KeepInventory { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "LOG_ADMIN_COMMANDS" => Ok(GameRule::LogAdminCommands { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "MOB_GRIEFING" => Ok(GameRule::MobGriefing { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "NATURAL_REGENERATION" => Ok(GameRule::NaturalRegeneration { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "REDUCED_DEBUG_INFO" => Ok(GameRule::ReducedDebugInfo { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "SEND_COMMAND_FEEDBACK" => Ok(GameRule::SendCommandFeedback { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "SHOW_DEATH_MESSAGES" => Ok(GameRule::ShowDeathMessages { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "SPECTATORS_GENERATE_CHUNKS" => Ok(GameRule::SpectatorsGenerateChunks { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DISABLE_RAIDS" => Ok(GameRule::DisableRaids { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_INSOMNIA" => Ok(GameRule::DoInsomnia { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_IMMEDIATE_RESPAWN" => Ok(GameRule::DoImmediateRespawn { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DROWNING_DAMAGE" => Ok(GameRule::DrowningDamage { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "FALL_DAMAGE" => Ok(GameRule::FallDamage { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "FIRE_DAMAGE" => Ok(GameRule::FireDamage { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "FREEZE_DAMAGE" => Ok(GameRule::FreezeDamage { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_PATROL_SPAWNING" => Ok(GameRule::DoPatrolSpawning { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_TRADER_SPAWNING" => Ok(GameRule::DoTraderSpawning { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_WARDEN_SPAWNING" => Ok(GameRule::DoWardenSpawning { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "FORGIVE_DEAD_PLAYERS" => Ok(GameRule::ForgiveDeadPlayers { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "UNIVERSAL_ANGER" => Ok(GameRule::UniversalAnger { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "BLOCK_EXPLOSION_DROP_DECAY" => Ok(GameRule::BlockExplosionDropDecay { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "MOB_EXPLOSION_DROP_DECAY" => Ok(GameRule::MobExplosionDropDecay { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "TNT_EXPLOSION_DROP_DECAY" => Ok(GameRule::TntExplosionDropDecay { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "WATER_SOURCE_CONVERSION" => Ok(GameRule::WaterSourceConversion { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "LAVA_SOURCE_CONVERSION" => Ok(GameRule::LavaSourceConversion { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "GLOBAL_SOUND_EVENTS" => Ok(GameRule::GlobalSoundEvents { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "DO_VINES_SPREAD" => Ok(GameRule::DoVinesSpread { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "ENDER_PEARLS_VANISH_ON_DEATH" => Ok(GameRule::EnderPearlsVanishOnDeath { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "RANDOM_TICK_SPEED" => Ok(GameRule::RandomTickSpeed { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "SPAWN_RADIUS" => Ok(GameRule::SpawnRadius { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "MAX_ENTITY_CRAMMING" => Ok(GameRule::MaxEntityCramming { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "MAX_COMMAND_CHAIN_LENGTH" => Ok(GameRule::MaxCommandChainLength { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "MAX_COMMAND_FORK_COUNT" => Ok(GameRule::MaxCommandForkCount { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "COMMAND_MODIFICATION_BLOCK_LIMIT" => Ok(GameRule::CommandModificationBlockLimit { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "PLAYERS_SLEEPING_PERCENTAGE" => Ok(GameRule::PlayersSleepingPercentage { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "SNOW_ACCUMULATION_HEIGHT" => Ok(GameRule::SnowAccumulationHeight { + inner: GameRuleStruct::from_raw(env, obj)?, + }), + "PLAYERS_NETHER_PORTAL_DEFAULT_DELAY" => { + Ok(GameRule::PlayersNetherPortalDefaultDelay { + inner: GameRuleStruct::from_raw(env, obj)?, + }) + } + "PLAYERS_NETHER_PORTAL_CREATIVE_DELAY" => { + Ok(GameRule::PlayersNetherPortalCreativeDelay { + inner: GameRuleStruct::from_raw(env, obj)?, + }) + } + "SPAWN_CHUNK_RADIUS" => Ok(GameRule::SpawnChunkRadius { + inner: GameRuleStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for EffectTypeStruct<'mc> { +impl<'mc> JNIRaw<'mc> for GameRuleStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -7937,20 +59165,20 @@ impl<'mc> JNIRaw<'mc> for EffectTypeStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EffectTypeStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for GameRuleStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate EffectTypeStruct from null object.").into(), + eyre::eyre!("Tried to instantiate GameRuleStruct from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Effect/Type")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/GameRule")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EffectTypeStruct object, got {}", + "Invalid argument passed. Expected a GameRuleStruct object, got {}", name ) .into()) @@ -7960,17 +59188,58 @@ impl<'mc> JNIInstantiatable<'mc> for EffectTypeStruct<'mc> { } } -impl<'mc> EffectTypeStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Effect/Type;"); - let cls = jni.find_class("org/bukkit/Effect/Type"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::EffectType::from_raw(&jni, obj) +impl<'mc> GameRuleStruct<'mc> { + /// Get the name of this GameRule. + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Get the type of this rule. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/Class;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(unsafe { jni::objects::JClass::from_raw(res.as_jni().l) }) + } + + pub fn equals( + &self, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(Ljava/lang/Object;)Z"); + let val_1 = jni::objects::JValueGen::Object(obj); + let res = self.jni_ref().call_method( + &self.jni_object(), + "equals", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -7978,25 +59247,46 @@ impl<'mc> EffectTypeStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum NetherWartsState<'mc> {} -impl<'mc> std::fmt::Display for NetherWartsState<'mc> { +pub enum GameMode<'mc> { + Creative { inner: GameModeStruct<'mc> }, + Survival { inner: GameModeStruct<'mc> }, + Adventure { inner: GameModeStruct<'mc> }, + Spectator { inner: GameModeStruct<'mc> }, +} +impl<'mc> std::fmt::Display for GameMode<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + GameMode::Creative { .. } => f.write_str("CREATIVE"), + GameMode::Survival { .. } => f.write_str("SURVIVAL"), + GameMode::Adventure { .. } => f.write_str("ADVENTURE"), + GameMode::Spectator { .. } => f.write_str("SPECTATOR"), + } + } +} +impl<'mc> std::ops::Deref for GameMode<'mc> { + type Target = GameModeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + GameMode::Creative { inner } => inner, + GameMode::Survival { inner } => inner, + GameMode::Adventure { inner } => inner, + GameMode::Spectator { inner } => inner, + } } } -impl<'mc> NetherWartsState<'mc> { +impl<'mc> GameMode<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/NetherWartsState"); + let cls = env.find_class("org/bukkit/GameMode"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/NetherWartsState;", + "(Ljava/lang/String;)Lorg/bukkit/GameMode;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -8008,39 +59298,64 @@ impl<'mc> NetherWartsState<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "CREATIVE" => Ok(GameMode::Creative { + inner: GameModeStruct::from_raw(env, obj)?, + }), + "SURVIVAL" => Ok(GameMode::Survival { + inner: GameModeStruct::from_raw(env, obj)?, + }), + "ADVENTURE" => Ok(GameMode::Adventure { + inner: GameModeStruct::from_raw(env, obj)?, + }), + "SPECTATOR" => Ok(GameMode::Spectator { + inner: GameModeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct NetherWartsStateStruct<'mc>( +pub struct GameModeStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for NetherWartsState<'mc> { +impl<'mc> JNIRaw<'mc> for GameMode<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Creative { inner } => inner.0.clone(), + Self::Survival { inner } => inner.0.clone(), + Self::Adventure { inner } => inner.0.clone(), + Self::Spectator { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Creative { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Survival { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Adventure { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Spectator { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } -impl<'mc> JNIInstantiatable<'mc> for NetherWartsState<'mc> { +impl<'mc> JNIInstantiatable<'mc> for GameMode<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate NetherWartsState from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate GameMode from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/NetherWartsState")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/GameMode")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a NetherWartsState object, got {}", + "Invalid argument passed. Expected a GameMode object, got {}", name ) .into()) @@ -8052,13 +59367,25 @@ impl<'mc> JNIInstantiatable<'mc> for NetherWartsState<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "CREATIVE" => Ok(GameMode::Creative { + inner: GameModeStruct::from_raw(env, obj)?, + }), + "SURVIVAL" => Ok(GameMode::Survival { + inner: GameModeStruct::from_raw(env, obj)?, + }), + "ADVENTURE" => Ok(GameMode::Adventure { + inner: GameModeStruct::from_raw(env, obj)?, + }), + "SPECTATOR" => Ok(GameMode::Spectator { + inner: GameModeStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for NetherWartsStateStruct<'mc> { +impl<'mc> JNIRaw<'mc> for GameModeStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -8066,21 +59393,20 @@ impl<'mc> JNIRaw<'mc> for NetherWartsStateStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for NetherWartsStateStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for GameModeStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate NetherWartsStateStruct from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate GameModeStruct from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/NetherWartsState")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/GameMode")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a NetherWartsStateStruct object, got {}", + "Invalid argument passed. Expected a GameModeStruct object, got {}", name ) .into()) @@ -8090,113 +59416,52 @@ impl<'mc> JNIInstantiatable<'mc> for NetherWartsStateStruct<'mc> { } } -impl<'mc> NetherWartsStateStruct<'mc> { +impl<'mc> GameModeStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NetherWartsState;"); - let cls = jni.find_class("org/bukkit/NetherWartsState"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/GameMode;"); + let cls = jni.find_class("org/bukkit/GameMode"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::NetherWartsState::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct Keyed<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Keyed<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Keyed<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Keyed from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Keyed")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Keyed object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + crate::GameMode::from_raw(&jni, obj) } -} - -impl<'mc> Keyed<'mc> { - /// Return the namespaced identifier for this object. - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + #[deprecated] + /// Gets the mode value associated with this GameMode + pub fn value(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getValue", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct Utility<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Utility<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + Ok(res.i()?) } -} -impl<'mc> JNIInstantiatable<'mc> for Utility<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Utility from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Utility")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Utility object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + #[deprecated] + /// Gets the GameMode represented by the specified value + pub fn get_by_value( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + value: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/GameMode;"); + let val_1 = jni::objects::JValueGen::Int(value); + let cls = jni.find_class("org/bukkit/GameMode"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getByValue", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + let obj = res.l()?; + Ok(Some(crate::GameMode::from_raw(&jni, obj)?)) } -} -impl<'mc> Utility<'mc> { pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) @@ -8414,10 +59679,44 @@ impl<'mc> Into {} +pub enum FireworkEffectType<'mc> { + Ball { + inner: FireworkEffectTypeStruct<'mc>, + }, + BallLarge { + inner: FireworkEffectTypeStruct<'mc>, + }, + Star { + inner: FireworkEffectTypeStruct<'mc>, + }, + Burst { + inner: FireworkEffectTypeStruct<'mc>, + }, + Creeper { + inner: FireworkEffectTypeStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for FireworkEffectType<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + FireworkEffectType::Ball { .. } => f.write_str("BALL"), + FireworkEffectType::BallLarge { .. } => f.write_str("BALL_LARGE"), + FireworkEffectType::Star { .. } => f.write_str("STAR"), + FireworkEffectType::Burst { .. } => f.write_str("BURST"), + FireworkEffectType::Creeper { .. } => f.write_str("CREEPER"), + } + } +} +impl<'mc> std::ops::Deref for FireworkEffectType<'mc> { + type Target = FireworkEffectTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + FireworkEffectType::Ball { inner } => inner, + FireworkEffectType::BallLarge { inner } => inner, + FireworkEffectType::Star { inner } => inner, + FireworkEffectType::Burst { inner } => inner, + FireworkEffectType::Creeper { inner } => inner, + } } } @@ -8444,6 +59743,22 @@ impl<'mc> FireworkEffectType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "BALL" => Ok(FireworkEffectType::Ball { + inner: FireworkEffectTypeStruct::from_raw(env, obj)?, + }), + "BALL_LARGE" => Ok(FireworkEffectType::BallLarge { + inner: FireworkEffectTypeStruct::from_raw(env, obj)?, + }), + "STAR" => Ok(FireworkEffectType::Star { + inner: FireworkEffectTypeStruct::from_raw(env, obj)?, + }), + "BURST" => Ok(FireworkEffectType::Burst { + inner: FireworkEffectTypeStruct::from_raw(env, obj)?, + }), + "CREEPER" => Ok(FireworkEffectType::Creeper { + inner: FireworkEffectTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -8457,10 +59772,24 @@ pub struct FireworkEffectTypeStruct<'mc>( impl<'mc> JNIRaw<'mc> for FireworkEffectType<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Ball { inner } => inner.0.clone(), + Self::BallLarge { inner } => inner.0.clone(), + Self::Star { inner } => inner.0.clone(), + Self::Burst { inner } => inner.0.clone(), + Self::Creeper { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Ball { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BallLarge { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Star { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Burst { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Creeper { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for FireworkEffectType<'mc> { @@ -8488,13 +59817,1140 @@ impl<'mc> JNIInstantiatable<'mc> for FireworkEffectType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "BALL" => Ok(FireworkEffectType::Ball { + inner: FireworkEffectTypeStruct::from_raw(env, obj)?, + }), + "BALL_LARGE" => Ok(FireworkEffectType::BallLarge { + inner: FireworkEffectTypeStruct::from_raw(env, obj)?, + }), + "STAR" => Ok(FireworkEffectType::Star { + inner: FireworkEffectTypeStruct::from_raw(env, obj)?, + }), + "BURST" => Ok(FireworkEffectType::Burst { + inner: FireworkEffectTypeStruct::from_raw(env, obj)?, + }), + "CREEPER" => Ok(FireworkEffectType::Creeper { + inner: FireworkEffectTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for FireworkEffectTypeStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for FireworkEffectTypeStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate FireworkEffectTypeStruct from null object." + ) + .into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/FireworkEffect/Type")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a FireworkEffectTypeStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> FireworkEffectTypeStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/FireworkEffect/Type;"); + let cls = jni.find_class("org/bukkit/FireworkEffect/Type"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::FireworkEffectType::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct FireworkEffectBuilder<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for FireworkEffectBuilder<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for FireworkEffectBuilder<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate FireworkEffectBuilder from null object." + ) + .into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/FireworkEffect/Builder")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a FireworkEffectBuilder object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> FireworkEffectBuilder<'mc> { + /// Specify the type of the firework effect. + pub fn with( + &self, + val_type: impl Into>, + ) -> Result, Box> { + let sig = + String::from("(Lorg/bukkit/FireworkEffect/Type;)Lorg/bukkit/FireworkEffect/Builder;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "with", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::FireworkEffectBuilder::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Add a flicker to the firework effect. + pub fn with_flicker( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/FireworkEffect/Builder;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "withFlicker", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::FireworkEffectBuilder::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Set whether the firework effect should flicker. + pub fn flicker( + &self, + flicker: bool, + ) -> Result, Box> { + let sig = String::from("(Z)Lorg/bukkit/FireworkEffect/Builder;"); + let val_1 = jni::objects::JValueGen::Bool(flicker.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "flicker", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::FireworkEffectBuilder::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Add a trail to the firework effect. + pub fn with_trail( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/FireworkEffect/Builder;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "withTrail", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::FireworkEffectBuilder::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Set whether the firework effect should have a trail. + pub fn trail( + &self, + trail: bool, + ) -> Result, Box> { + let sig = String::from("(Z)Lorg/bukkit/FireworkEffect/Builder;"); + let val_1 = jni::objects::JValueGen::Bool(trail.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "trail", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::FireworkEffectBuilder::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Create a {@link FireworkEffect} from the current contents of this + /// builder. + /// + /// To successfully build, you must have specified at least one color. + pub fn build(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/FireworkEffect;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "build", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::FireworkEffect::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +pub enum EntityEffect<'mc> { + ArrowParticles { inner: EntityEffectStruct<'mc> }, + RabbitJump { inner: EntityEffectStruct<'mc> }, + ResetSpawnerMinecartDelay { inner: EntityEffectStruct<'mc> }, + Hurt { inner: EntityEffectStruct<'mc> }, + Death { inner: EntityEffectStruct<'mc> }, + EggBreak { inner: EntityEffectStruct<'mc> }, + SnowballBreak { inner: EntityEffectStruct<'mc> }, + EntityDeath { inner: EntityEffectStruct<'mc> }, + FangAttack { inner: EntityEffectStruct<'mc> }, + HoglinAttack { inner: EntityEffectStruct<'mc> }, + IronGolenAttack { inner: EntityEffectStruct<'mc> }, + RavagerAttack { inner: EntityEffectStruct<'mc> }, + WardenAttack { inner: EntityEffectStruct<'mc> }, + ZoglinAttack { inner: EntityEffectStruct<'mc> }, + WolfSmoke { inner: EntityEffectStruct<'mc> }, + WolfHearts { inner: EntityEffectStruct<'mc> }, + WolfShake { inner: EntityEffectStruct<'mc> }, + SheepEat { inner: EntityEffectStruct<'mc> }, + SheepEatGrass { inner: EntityEffectStruct<'mc> }, + TntMinecartIgnite { inner: EntityEffectStruct<'mc> }, + IronGolemRose { inner: EntityEffectStruct<'mc> }, + VillagerHeart { inner: EntityEffectStruct<'mc> }, + VillagerAngry { inner: EntityEffectStruct<'mc> }, + VillagerHappy { inner: EntityEffectStruct<'mc> }, + WitchMagic { inner: EntityEffectStruct<'mc> }, + ZombieTransform { inner: EntityEffectStruct<'mc> }, + FireworkExplode { inner: EntityEffectStruct<'mc> }, + LoveHearts { inner: EntityEffectStruct<'mc> }, + SquidRotate { inner: EntityEffectStruct<'mc> }, + EntityPoof { inner: EntityEffectStruct<'mc> }, + GuardianTarget { inner: EntityEffectStruct<'mc> }, + ShieldBlock { inner: EntityEffectStruct<'mc> }, + ShieldBreak { inner: EntityEffectStruct<'mc> }, + ArmorStandHit { inner: EntityEffectStruct<'mc> }, + ThornsHurt { inner: EntityEffectStruct<'mc> }, + IronGolemSheath { inner: EntityEffectStruct<'mc> }, + TotemResurrect { inner: EntityEffectStruct<'mc> }, + HurtDrown { inner: EntityEffectStruct<'mc> }, + HurtExplosion { inner: EntityEffectStruct<'mc> }, + DolphinFed { inner: EntityEffectStruct<'mc> }, + RavagerStunned { inner: EntityEffectStruct<'mc> }, + CatTameFail { inner: EntityEffectStruct<'mc> }, + CatTameSuccess { inner: EntityEffectStruct<'mc> }, + VillagerSplash { inner: EntityEffectStruct<'mc> }, + PlayerBadOmenRaid { inner: EntityEffectStruct<'mc> }, + HurtBerryBush { inner: EntityEffectStruct<'mc> }, + FoxChew { inner: EntityEffectStruct<'mc> }, + TeleportEnder { inner: EntityEffectStruct<'mc> }, + BreakEquipmentMainHand { inner: EntityEffectStruct<'mc> }, + BreakEquipmentOffHand { inner: EntityEffectStruct<'mc> }, + BreakEquipmentHelmet { inner: EntityEffectStruct<'mc> }, + BreakEquipmentChestplate { inner: EntityEffectStruct<'mc> }, + BreakEquipmentLeggings { inner: EntityEffectStruct<'mc> }, + BreakEquipmentBoots { inner: EntityEffectStruct<'mc> }, + HoneyBlockSlideParticles { inner: EntityEffectStruct<'mc> }, + HoneyBlockFallParticles { inner: EntityEffectStruct<'mc> }, + SwapHandItems { inner: EntityEffectStruct<'mc> }, + WolfShakeStop { inner: EntityEffectStruct<'mc> }, + GoatLowerHead { inner: EntityEffectStruct<'mc> }, + GoatRaiseHead { inner: EntityEffectStruct<'mc> }, + SpawnDeathSmoke { inner: EntityEffectStruct<'mc> }, + WardenTendrilShake { inner: EntityEffectStruct<'mc> }, + WardenSonicAttack { inner: EntityEffectStruct<'mc> }, + SnifferDig { inner: EntityEffectStruct<'mc> }, +} +impl<'mc> std::fmt::Display for EntityEffect<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + EntityEffect::ArrowParticles { .. } => f.write_str("ARROW_PARTICLES"), + EntityEffect::RabbitJump { .. } => f.write_str("RABBIT_JUMP"), + EntityEffect::ResetSpawnerMinecartDelay { .. } => { + f.write_str("RESET_SPAWNER_MINECART_DELAY") + } + EntityEffect::Hurt { .. } => f.write_str("HURT"), + EntityEffect::Death { .. } => f.write_str("DEATH"), + EntityEffect::EggBreak { .. } => f.write_str("EGG_BREAK"), + EntityEffect::SnowballBreak { .. } => f.write_str("SNOWBALL_BREAK"), + EntityEffect::EntityDeath { .. } => f.write_str("ENTITY_DEATH"), + EntityEffect::FangAttack { .. } => f.write_str("FANG_ATTACK"), + EntityEffect::HoglinAttack { .. } => f.write_str("HOGLIN_ATTACK"), + EntityEffect::IronGolenAttack { .. } => f.write_str("IRON_GOLEN_ATTACK"), + EntityEffect::RavagerAttack { .. } => f.write_str("RAVAGER_ATTACK"), + EntityEffect::WardenAttack { .. } => f.write_str("WARDEN_ATTACK"), + EntityEffect::ZoglinAttack { .. } => f.write_str("ZOGLIN_ATTACK"), + EntityEffect::WolfSmoke { .. } => f.write_str("WOLF_SMOKE"), + EntityEffect::WolfHearts { .. } => f.write_str("WOLF_HEARTS"), + EntityEffect::WolfShake { .. } => f.write_str("WOLF_SHAKE"), + EntityEffect::SheepEat { .. } => f.write_str("SHEEP_EAT"), + EntityEffect::SheepEatGrass { .. } => f.write_str("SHEEP_EAT_GRASS"), + EntityEffect::TntMinecartIgnite { .. } => f.write_str("TNT_MINECART_IGNITE"), + EntityEffect::IronGolemRose { .. } => f.write_str("IRON_GOLEM_ROSE"), + EntityEffect::VillagerHeart { .. } => f.write_str("VILLAGER_HEART"), + EntityEffect::VillagerAngry { .. } => f.write_str("VILLAGER_ANGRY"), + EntityEffect::VillagerHappy { .. } => f.write_str("VILLAGER_HAPPY"), + EntityEffect::WitchMagic { .. } => f.write_str("WITCH_MAGIC"), + EntityEffect::ZombieTransform { .. } => f.write_str("ZOMBIE_TRANSFORM"), + EntityEffect::FireworkExplode { .. } => f.write_str("FIREWORK_EXPLODE"), + EntityEffect::LoveHearts { .. } => f.write_str("LOVE_HEARTS"), + EntityEffect::SquidRotate { .. } => f.write_str("SQUID_ROTATE"), + EntityEffect::EntityPoof { .. } => f.write_str("ENTITY_POOF"), + EntityEffect::GuardianTarget { .. } => f.write_str("GUARDIAN_TARGET"), + EntityEffect::ShieldBlock { .. } => f.write_str("SHIELD_BLOCK"), + EntityEffect::ShieldBreak { .. } => f.write_str("SHIELD_BREAK"), + EntityEffect::ArmorStandHit { .. } => f.write_str("ARMOR_STAND_HIT"), + EntityEffect::ThornsHurt { .. } => f.write_str("THORNS_HURT"), + EntityEffect::IronGolemSheath { .. } => f.write_str("IRON_GOLEM_SHEATH"), + EntityEffect::TotemResurrect { .. } => f.write_str("TOTEM_RESURRECT"), + EntityEffect::HurtDrown { .. } => f.write_str("HURT_DROWN"), + EntityEffect::HurtExplosion { .. } => f.write_str("HURT_EXPLOSION"), + EntityEffect::DolphinFed { .. } => f.write_str("DOLPHIN_FED"), + EntityEffect::RavagerStunned { .. } => f.write_str("RAVAGER_STUNNED"), + EntityEffect::CatTameFail { .. } => f.write_str("CAT_TAME_FAIL"), + EntityEffect::CatTameSuccess { .. } => f.write_str("CAT_TAME_SUCCESS"), + EntityEffect::VillagerSplash { .. } => f.write_str("VILLAGER_SPLASH"), + EntityEffect::PlayerBadOmenRaid { .. } => f.write_str("PLAYER_BAD_OMEN_RAID"), + EntityEffect::HurtBerryBush { .. } => f.write_str("HURT_BERRY_BUSH"), + EntityEffect::FoxChew { .. } => f.write_str("FOX_CHEW"), + EntityEffect::TeleportEnder { .. } => f.write_str("TELEPORT_ENDER"), + EntityEffect::BreakEquipmentMainHand { .. } => f.write_str("BREAK_EQUIPMENT_MAIN_HAND"), + EntityEffect::BreakEquipmentOffHand { .. } => f.write_str("BREAK_EQUIPMENT_OFF_HAND"), + EntityEffect::BreakEquipmentHelmet { .. } => f.write_str("BREAK_EQUIPMENT_HELMET"), + EntityEffect::BreakEquipmentChestplate { .. } => { + f.write_str("BREAK_EQUIPMENT_CHESTPLATE") + } + EntityEffect::BreakEquipmentLeggings { .. } => f.write_str("BREAK_EQUIPMENT_LEGGINGS"), + EntityEffect::BreakEquipmentBoots { .. } => f.write_str("BREAK_EQUIPMENT_BOOTS"), + EntityEffect::HoneyBlockSlideParticles { .. } => { + f.write_str("HONEY_BLOCK_SLIDE_PARTICLES") + } + EntityEffect::HoneyBlockFallParticles { .. } => { + f.write_str("HONEY_BLOCK_FALL_PARTICLES") + } + EntityEffect::SwapHandItems { .. } => f.write_str("SWAP_HAND_ITEMS"), + EntityEffect::WolfShakeStop { .. } => f.write_str("WOLF_SHAKE_STOP"), + EntityEffect::GoatLowerHead { .. } => f.write_str("GOAT_LOWER_HEAD"), + EntityEffect::GoatRaiseHead { .. } => f.write_str("GOAT_RAISE_HEAD"), + EntityEffect::SpawnDeathSmoke { .. } => f.write_str("SPAWN_DEATH_SMOKE"), + EntityEffect::WardenTendrilShake { .. } => f.write_str("WARDEN_TENDRIL_SHAKE"), + EntityEffect::WardenSonicAttack { .. } => f.write_str("WARDEN_SONIC_ATTACK"), + EntityEffect::SnifferDig { .. } => f.write_str("SNIFFER_DIG"), + } + } +} +impl<'mc> std::ops::Deref for EntityEffect<'mc> { + type Target = EntityEffectStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + EntityEffect::ArrowParticles { inner } => inner, + EntityEffect::RabbitJump { inner } => inner, + EntityEffect::ResetSpawnerMinecartDelay { inner } => inner, + EntityEffect::Hurt { inner } => inner, + EntityEffect::Death { inner } => inner, + EntityEffect::EggBreak { inner } => inner, + EntityEffect::SnowballBreak { inner } => inner, + EntityEffect::EntityDeath { inner } => inner, + EntityEffect::FangAttack { inner } => inner, + EntityEffect::HoglinAttack { inner } => inner, + EntityEffect::IronGolenAttack { inner } => inner, + EntityEffect::RavagerAttack { inner } => inner, + EntityEffect::WardenAttack { inner } => inner, + EntityEffect::ZoglinAttack { inner } => inner, + EntityEffect::WolfSmoke { inner } => inner, + EntityEffect::WolfHearts { inner } => inner, + EntityEffect::WolfShake { inner } => inner, + EntityEffect::SheepEat { inner } => inner, + EntityEffect::SheepEatGrass { inner } => inner, + EntityEffect::TntMinecartIgnite { inner } => inner, + EntityEffect::IronGolemRose { inner } => inner, + EntityEffect::VillagerHeart { inner } => inner, + EntityEffect::VillagerAngry { inner } => inner, + EntityEffect::VillagerHappy { inner } => inner, + EntityEffect::WitchMagic { inner } => inner, + EntityEffect::ZombieTransform { inner } => inner, + EntityEffect::FireworkExplode { inner } => inner, + EntityEffect::LoveHearts { inner } => inner, + EntityEffect::SquidRotate { inner } => inner, + EntityEffect::EntityPoof { inner } => inner, + EntityEffect::GuardianTarget { inner } => inner, + EntityEffect::ShieldBlock { inner } => inner, + EntityEffect::ShieldBreak { inner } => inner, + EntityEffect::ArmorStandHit { inner } => inner, + EntityEffect::ThornsHurt { inner } => inner, + EntityEffect::IronGolemSheath { inner } => inner, + EntityEffect::TotemResurrect { inner } => inner, + EntityEffect::HurtDrown { inner } => inner, + EntityEffect::HurtExplosion { inner } => inner, + EntityEffect::DolphinFed { inner } => inner, + EntityEffect::RavagerStunned { inner } => inner, + EntityEffect::CatTameFail { inner } => inner, + EntityEffect::CatTameSuccess { inner } => inner, + EntityEffect::VillagerSplash { inner } => inner, + EntityEffect::PlayerBadOmenRaid { inner } => inner, + EntityEffect::HurtBerryBush { inner } => inner, + EntityEffect::FoxChew { inner } => inner, + EntityEffect::TeleportEnder { inner } => inner, + EntityEffect::BreakEquipmentMainHand { inner } => inner, + EntityEffect::BreakEquipmentOffHand { inner } => inner, + EntityEffect::BreakEquipmentHelmet { inner } => inner, + EntityEffect::BreakEquipmentChestplate { inner } => inner, + EntityEffect::BreakEquipmentLeggings { inner } => inner, + EntityEffect::BreakEquipmentBoots { inner } => inner, + EntityEffect::HoneyBlockSlideParticles { inner } => inner, + EntityEffect::HoneyBlockFallParticles { inner } => inner, + EntityEffect::SwapHandItems { inner } => inner, + EntityEffect::WolfShakeStop { inner } => inner, + EntityEffect::GoatLowerHead { inner } => inner, + EntityEffect::GoatRaiseHead { inner } => inner, + EntityEffect::SpawnDeathSmoke { inner } => inner, + EntityEffect::WardenTendrilShake { inner } => inner, + EntityEffect::WardenSonicAttack { inner } => inner, + EntityEffect::SnifferDig { inner } => inner, + } + } +} + +impl<'mc> EntityEffect<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/EntityEffect"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/EntityEffect;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "ARROW_PARTICLES" => Ok(EntityEffect::ArrowParticles { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "RABBIT_JUMP" => Ok(EntityEffect::RabbitJump { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "RESET_SPAWNER_MINECART_DELAY" => Ok(EntityEffect::ResetSpawnerMinecartDelay { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "HURT" => Ok(EntityEffect::Hurt { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "DEATH" => Ok(EntityEffect::Death { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "EGG_BREAK" => Ok(EntityEffect::EggBreak { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "SNOWBALL_BREAK" => Ok(EntityEffect::SnowballBreak { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "ENTITY_DEATH" => Ok(EntityEffect::EntityDeath { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "FANG_ATTACK" => Ok(EntityEffect::FangAttack { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "HOGLIN_ATTACK" => Ok(EntityEffect::HoglinAttack { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "IRON_GOLEN_ATTACK" => Ok(EntityEffect::IronGolenAttack { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "RAVAGER_ATTACK" => Ok(EntityEffect::RavagerAttack { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "WARDEN_ATTACK" => Ok(EntityEffect::WardenAttack { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "ZOGLIN_ATTACK" => Ok(EntityEffect::ZoglinAttack { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "WOLF_SMOKE" => Ok(EntityEffect::WolfSmoke { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "WOLF_HEARTS" => Ok(EntityEffect::WolfHearts { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "WOLF_SHAKE" => Ok(EntityEffect::WolfShake { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "SHEEP_EAT" => Ok(EntityEffect::SheepEat { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "SHEEP_EAT_GRASS" => Ok(EntityEffect::SheepEatGrass { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "TNT_MINECART_IGNITE" => Ok(EntityEffect::TntMinecartIgnite { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "IRON_GOLEM_ROSE" => Ok(EntityEffect::IronGolemRose { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "VILLAGER_HEART" => Ok(EntityEffect::VillagerHeart { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "VILLAGER_ANGRY" => Ok(EntityEffect::VillagerAngry { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "VILLAGER_HAPPY" => Ok(EntityEffect::VillagerHappy { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "WITCH_MAGIC" => Ok(EntityEffect::WitchMagic { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "ZOMBIE_TRANSFORM" => Ok(EntityEffect::ZombieTransform { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "FIREWORK_EXPLODE" => Ok(EntityEffect::FireworkExplode { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "LOVE_HEARTS" => Ok(EntityEffect::LoveHearts { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "SQUID_ROTATE" => Ok(EntityEffect::SquidRotate { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "ENTITY_POOF" => Ok(EntityEffect::EntityPoof { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "GUARDIAN_TARGET" => Ok(EntityEffect::GuardianTarget { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "SHIELD_BLOCK" => Ok(EntityEffect::ShieldBlock { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "SHIELD_BREAK" => Ok(EntityEffect::ShieldBreak { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "ARMOR_STAND_HIT" => Ok(EntityEffect::ArmorStandHit { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "THORNS_HURT" => Ok(EntityEffect::ThornsHurt { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "IRON_GOLEM_SHEATH" => Ok(EntityEffect::IronGolemSheath { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "TOTEM_RESURRECT" => Ok(EntityEffect::TotemResurrect { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "HURT_DROWN" => Ok(EntityEffect::HurtDrown { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "HURT_EXPLOSION" => Ok(EntityEffect::HurtExplosion { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "DOLPHIN_FED" => Ok(EntityEffect::DolphinFed { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "RAVAGER_STUNNED" => Ok(EntityEffect::RavagerStunned { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "CAT_TAME_FAIL" => Ok(EntityEffect::CatTameFail { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "CAT_TAME_SUCCESS" => Ok(EntityEffect::CatTameSuccess { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "VILLAGER_SPLASH" => Ok(EntityEffect::VillagerSplash { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "PLAYER_BAD_OMEN_RAID" => Ok(EntityEffect::PlayerBadOmenRaid { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "HURT_BERRY_BUSH" => Ok(EntityEffect::HurtBerryBush { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "FOX_CHEW" => Ok(EntityEffect::FoxChew { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "TELEPORT_ENDER" => Ok(EntityEffect::TeleportEnder { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "BREAK_EQUIPMENT_MAIN_HAND" => Ok(EntityEffect::BreakEquipmentMainHand { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "BREAK_EQUIPMENT_OFF_HAND" => Ok(EntityEffect::BreakEquipmentOffHand { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "BREAK_EQUIPMENT_HELMET" => Ok(EntityEffect::BreakEquipmentHelmet { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "BREAK_EQUIPMENT_CHESTPLATE" => Ok(EntityEffect::BreakEquipmentChestplate { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "BREAK_EQUIPMENT_LEGGINGS" => Ok(EntityEffect::BreakEquipmentLeggings { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "BREAK_EQUIPMENT_BOOTS" => Ok(EntityEffect::BreakEquipmentBoots { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "HONEY_BLOCK_SLIDE_PARTICLES" => Ok(EntityEffect::HoneyBlockSlideParticles { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "HONEY_BLOCK_FALL_PARTICLES" => Ok(EntityEffect::HoneyBlockFallParticles { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "SWAP_HAND_ITEMS" => Ok(EntityEffect::SwapHandItems { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "WOLF_SHAKE_STOP" => Ok(EntityEffect::WolfShakeStop { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "GOAT_LOWER_HEAD" => Ok(EntityEffect::GoatLowerHead { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "GOAT_RAISE_HEAD" => Ok(EntityEffect::GoatRaiseHead { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "SPAWN_DEATH_SMOKE" => Ok(EntityEffect::SpawnDeathSmoke { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "WARDEN_TENDRIL_SHAKE" => Ok(EntityEffect::WardenTendrilShake { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "WARDEN_SONIC_ATTACK" => Ok(EntityEffect::WardenSonicAttack { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "SNIFFER_DIG" => Ok(EntityEffect::SnifferDig { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct EntityEffectStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for EntityEffect<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::ArrowParticles { inner } => inner.0.clone(), + Self::RabbitJump { inner } => inner.0.clone(), + Self::ResetSpawnerMinecartDelay { inner } => inner.0.clone(), + Self::Hurt { inner } => inner.0.clone(), + Self::Death { inner } => inner.0.clone(), + Self::EggBreak { inner } => inner.0.clone(), + Self::SnowballBreak { inner } => inner.0.clone(), + Self::EntityDeath { inner } => inner.0.clone(), + Self::FangAttack { inner } => inner.0.clone(), + Self::HoglinAttack { inner } => inner.0.clone(), + Self::IronGolenAttack { inner } => inner.0.clone(), + Self::RavagerAttack { inner } => inner.0.clone(), + Self::WardenAttack { inner } => inner.0.clone(), + Self::ZoglinAttack { inner } => inner.0.clone(), + Self::WolfSmoke { inner } => inner.0.clone(), + Self::WolfHearts { inner } => inner.0.clone(), + Self::WolfShake { inner } => inner.0.clone(), + Self::SheepEat { inner } => inner.0.clone(), + Self::SheepEatGrass { inner } => inner.0.clone(), + Self::TntMinecartIgnite { inner } => inner.0.clone(), + Self::IronGolemRose { inner } => inner.0.clone(), + Self::VillagerHeart { inner } => inner.0.clone(), + Self::VillagerAngry { inner } => inner.0.clone(), + Self::VillagerHappy { inner } => inner.0.clone(), + Self::WitchMagic { inner } => inner.0.clone(), + Self::ZombieTransform { inner } => inner.0.clone(), + Self::FireworkExplode { inner } => inner.0.clone(), + Self::LoveHearts { inner } => inner.0.clone(), + Self::SquidRotate { inner } => inner.0.clone(), + Self::EntityPoof { inner } => inner.0.clone(), + Self::GuardianTarget { inner } => inner.0.clone(), + Self::ShieldBlock { inner } => inner.0.clone(), + Self::ShieldBreak { inner } => inner.0.clone(), + Self::ArmorStandHit { inner } => inner.0.clone(), + Self::ThornsHurt { inner } => inner.0.clone(), + Self::IronGolemSheath { inner } => inner.0.clone(), + Self::TotemResurrect { inner } => inner.0.clone(), + Self::HurtDrown { inner } => inner.0.clone(), + Self::HurtExplosion { inner } => inner.0.clone(), + Self::DolphinFed { inner } => inner.0.clone(), + Self::RavagerStunned { inner } => inner.0.clone(), + Self::CatTameFail { inner } => inner.0.clone(), + Self::CatTameSuccess { inner } => inner.0.clone(), + Self::VillagerSplash { inner } => inner.0.clone(), + Self::PlayerBadOmenRaid { inner } => inner.0.clone(), + Self::HurtBerryBush { inner } => inner.0.clone(), + Self::FoxChew { inner } => inner.0.clone(), + Self::TeleportEnder { inner } => inner.0.clone(), + Self::BreakEquipmentMainHand { inner } => inner.0.clone(), + Self::BreakEquipmentOffHand { inner } => inner.0.clone(), + Self::BreakEquipmentHelmet { inner } => inner.0.clone(), + Self::BreakEquipmentChestplate { inner } => inner.0.clone(), + Self::BreakEquipmentLeggings { inner } => inner.0.clone(), + Self::BreakEquipmentBoots { inner } => inner.0.clone(), + Self::HoneyBlockSlideParticles { inner } => inner.0.clone(), + Self::HoneyBlockFallParticles { inner } => inner.0.clone(), + Self::SwapHandItems { inner } => inner.0.clone(), + Self::WolfShakeStop { inner } => inner.0.clone(), + Self::GoatLowerHead { inner } => inner.0.clone(), + Self::GoatRaiseHead { inner } => inner.0.clone(), + Self::SpawnDeathSmoke { inner } => inner.0.clone(), + Self::WardenTendrilShake { inner } => inner.0.clone(), + Self::WardenSonicAttack { inner } => inner.0.clone(), + Self::SnifferDig { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::ArrowParticles { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RabbitJump { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ResetSpawnerMinecartDelay { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Hurt { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Death { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::EggBreak { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SnowballBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FangAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HoglinAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronGolenAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RavagerAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WardenAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ZoglinAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WolfSmoke { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WolfHearts { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WolfShake { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SheepEat { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SheepEatGrass { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TntMinecartIgnite { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronGolemRose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VillagerHeart { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VillagerAngry { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VillagerHappy { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WitchMagic { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ZombieTransform { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FireworkExplode { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LoveHearts { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SquidRotate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EntityPoof { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GuardianTarget { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ShieldBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ShieldBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ArmorStandHit { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ThornsHurt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronGolemSheath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TotemResurrect { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HurtDrown { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HurtExplosion { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DolphinFed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RavagerStunned { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CatTameFail { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CatTameSuccess { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VillagerSplash { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PlayerBadOmenRaid { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HurtBerryBush { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FoxChew { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::TeleportEnder { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BreakEquipmentMainHand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BreakEquipmentOffHand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BreakEquipmentHelmet { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BreakEquipmentChestplate { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BreakEquipmentLeggings { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BreakEquipmentBoots { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HoneyBlockSlideParticles { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HoneyBlockFallParticles { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SwapHandItems { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WolfShakeStop { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GoatLowerHead { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GoatRaiseHead { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SpawnDeathSmoke { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WardenTendrilShake { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WardenSonicAttack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SnifferDig { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for EntityEffect<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate EntityEffect from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/EntityEffect")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EntityEffect object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "ARROW_PARTICLES" => Ok(EntityEffect::ArrowParticles { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "RABBIT_JUMP" => Ok(EntityEffect::RabbitJump { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "RESET_SPAWNER_MINECART_DELAY" => Ok(EntityEffect::ResetSpawnerMinecartDelay { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "HURT" => Ok(EntityEffect::Hurt { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "DEATH" => Ok(EntityEffect::Death { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "EGG_BREAK" => Ok(EntityEffect::EggBreak { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "SNOWBALL_BREAK" => Ok(EntityEffect::SnowballBreak { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "ENTITY_DEATH" => Ok(EntityEffect::EntityDeath { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "FANG_ATTACK" => Ok(EntityEffect::FangAttack { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "HOGLIN_ATTACK" => Ok(EntityEffect::HoglinAttack { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "IRON_GOLEN_ATTACK" => Ok(EntityEffect::IronGolenAttack { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "RAVAGER_ATTACK" => Ok(EntityEffect::RavagerAttack { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "WARDEN_ATTACK" => Ok(EntityEffect::WardenAttack { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "ZOGLIN_ATTACK" => Ok(EntityEffect::ZoglinAttack { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "WOLF_SMOKE" => Ok(EntityEffect::WolfSmoke { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "WOLF_HEARTS" => Ok(EntityEffect::WolfHearts { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "WOLF_SHAKE" => Ok(EntityEffect::WolfShake { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "SHEEP_EAT" => Ok(EntityEffect::SheepEat { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "SHEEP_EAT_GRASS" => Ok(EntityEffect::SheepEatGrass { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "TNT_MINECART_IGNITE" => Ok(EntityEffect::TntMinecartIgnite { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "IRON_GOLEM_ROSE" => Ok(EntityEffect::IronGolemRose { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "VILLAGER_HEART" => Ok(EntityEffect::VillagerHeart { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "VILLAGER_ANGRY" => Ok(EntityEffect::VillagerAngry { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "VILLAGER_HAPPY" => Ok(EntityEffect::VillagerHappy { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "WITCH_MAGIC" => Ok(EntityEffect::WitchMagic { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "ZOMBIE_TRANSFORM" => Ok(EntityEffect::ZombieTransform { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "FIREWORK_EXPLODE" => Ok(EntityEffect::FireworkExplode { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "LOVE_HEARTS" => Ok(EntityEffect::LoveHearts { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "SQUID_ROTATE" => Ok(EntityEffect::SquidRotate { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "ENTITY_POOF" => Ok(EntityEffect::EntityPoof { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "GUARDIAN_TARGET" => Ok(EntityEffect::GuardianTarget { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "SHIELD_BLOCK" => Ok(EntityEffect::ShieldBlock { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "SHIELD_BREAK" => Ok(EntityEffect::ShieldBreak { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "ARMOR_STAND_HIT" => Ok(EntityEffect::ArmorStandHit { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "THORNS_HURT" => Ok(EntityEffect::ThornsHurt { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "IRON_GOLEM_SHEATH" => Ok(EntityEffect::IronGolemSheath { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "TOTEM_RESURRECT" => Ok(EntityEffect::TotemResurrect { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "HURT_DROWN" => Ok(EntityEffect::HurtDrown { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "HURT_EXPLOSION" => Ok(EntityEffect::HurtExplosion { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "DOLPHIN_FED" => Ok(EntityEffect::DolphinFed { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "RAVAGER_STUNNED" => Ok(EntityEffect::RavagerStunned { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "CAT_TAME_FAIL" => Ok(EntityEffect::CatTameFail { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "CAT_TAME_SUCCESS" => Ok(EntityEffect::CatTameSuccess { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "VILLAGER_SPLASH" => Ok(EntityEffect::VillagerSplash { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "PLAYER_BAD_OMEN_RAID" => Ok(EntityEffect::PlayerBadOmenRaid { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "HURT_BERRY_BUSH" => Ok(EntityEffect::HurtBerryBush { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "FOX_CHEW" => Ok(EntityEffect::FoxChew { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "TELEPORT_ENDER" => Ok(EntityEffect::TeleportEnder { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "BREAK_EQUIPMENT_MAIN_HAND" => Ok(EntityEffect::BreakEquipmentMainHand { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "BREAK_EQUIPMENT_OFF_HAND" => Ok(EntityEffect::BreakEquipmentOffHand { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "BREAK_EQUIPMENT_HELMET" => Ok(EntityEffect::BreakEquipmentHelmet { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "BREAK_EQUIPMENT_CHESTPLATE" => Ok(EntityEffect::BreakEquipmentChestplate { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "BREAK_EQUIPMENT_LEGGINGS" => Ok(EntityEffect::BreakEquipmentLeggings { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "BREAK_EQUIPMENT_BOOTS" => Ok(EntityEffect::BreakEquipmentBoots { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "HONEY_BLOCK_SLIDE_PARTICLES" => Ok(EntityEffect::HoneyBlockSlideParticles { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "HONEY_BLOCK_FALL_PARTICLES" => Ok(EntityEffect::HoneyBlockFallParticles { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "SWAP_HAND_ITEMS" => Ok(EntityEffect::SwapHandItems { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "WOLF_SHAKE_STOP" => Ok(EntityEffect::WolfShakeStop { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "GOAT_LOWER_HEAD" => Ok(EntityEffect::GoatLowerHead { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "GOAT_RAISE_HEAD" => Ok(EntityEffect::GoatRaiseHead { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "SPAWN_DEATH_SMOKE" => Ok(EntityEffect::SpawnDeathSmoke { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "WARDEN_TENDRIL_SHAKE" => Ok(EntityEffect::WardenTendrilShake { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "WARDEN_SONIC_ATTACK" => Ok(EntityEffect::WardenSonicAttack { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), + "SNIFFER_DIG" => Ok(EntityEffect::SnifferDig { + inner: EntityEffectStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for FireworkEffectTypeStruct<'mc> { +impl<'mc> JNIRaw<'mc> for EntityEffectStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -8502,21 +60958,20 @@ impl<'mc> JNIRaw<'mc> for FireworkEffectTypeStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for FireworkEffectTypeStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EntityEffectStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate FireworkEffectTypeStruct from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate EntityEffectStruct from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/FireworkEffect/Type")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/EntityEffect")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a FireworkEffectTypeStruct object, got {}", + "Invalid argument passed. Expected a EntityEffectStruct object, got {}", name ) .into()) @@ -8526,159 +60981,53 @@ impl<'mc> JNIInstantiatable<'mc> for FireworkEffectTypeStruct<'mc> { } } -impl<'mc> FireworkEffectTypeStruct<'mc> { +impl<'mc> EntityEffectStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/FireworkEffect/Type;"); - let cls = jni.find_class("org/bukkit/FireworkEffect/Type"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/EntityEffect;"); + let cls = jni.find_class("org/bukkit/EntityEffect"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::FireworkEffectType::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct FireworkEffectBuilder<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for FireworkEffectBuilder<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for FireworkEffectBuilder<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate FireworkEffectBuilder from null object." - ) - .into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/FireworkEffect/Builder")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a FireworkEffectBuilder object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + crate::EntityEffect::from_raw(&jni, obj) } -} - -impl<'mc> FireworkEffectBuilder<'mc> { - /// Specify the type of the firework effect. - pub fn with( - &self, - val_type: impl Into>, - ) -> Result, Box> { - let sig = - String::from("(Lorg/bukkit/FireworkEffect/Type;)Lorg/bukkit/FireworkEffect/Builder;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "with", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + #[deprecated] + /// Gets the data value of this EntityEffect, may not be unique. + pub fn data(&self) -> Result> { + let sig = String::from("()B"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::FireworkEffectBuilder::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.b()?) } - /// Add a flicker to the firework effect. - pub fn with_flicker( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/FireworkEffect/Builder;"); + /// Gets entity superclass which this affect is applicable to. + pub fn applicable(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/Class;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "withFlicker", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::FireworkEffectBuilder::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Set whether the firework effect should flicker. - pub fn flicker( - &self, - flicker: bool, - ) -> Result, Box> { - let sig = String::from("(Z)Lorg/bukkit/FireworkEffect/Builder;"); - let val_1 = jni::objects::JValueGen::Bool(flicker.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "flicker", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::FireworkEffectBuilder::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Add a trail to the firework effect. - pub fn with_trail( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/FireworkEffect/Builder;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "withTrail", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getApplicable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::FireworkEffectBuilder::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(unsafe { jni::objects::JClass::from_raw(res.as_jni().l) }) } - /// Set whether the firework effect should have a trail. - pub fn trail( + /// Checks if this effect is applicable to the given entity class. + pub fn is_applicable_to( &self, - trail: bool, - ) -> Result, Box> { - let sig = String::from("(Z)Lorg/bukkit/FireworkEffect/Builder;"); - let val_1 = jni::objects::JValueGen::Bool(trail.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "trail", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::FireworkEffectBuilder::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Create a {@link FireworkEffect} from the current contents of this - /// builder. - /// - /// To successfully build, you must have specified at least one color. - pub fn build(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/FireworkEffect;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "build", sig.as_str(), vec![]); + clazz: jni::objects::JClass<'mc>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(clazz.into()); + args.push(val_1); + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isApplicableTo", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::FireworkEffect::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -8686,25 +61035,242 @@ impl<'mc> FireworkEffectBuilder<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum GrassSpecies<'mc> {} -impl<'mc> std::fmt::Display for GrassSpecies<'mc> { +pub enum Effect<'mc> { + Click2 { inner: EffectStruct<'mc> }, + Click1 { inner: EffectStruct<'mc> }, + BowFire { inner: EffectStruct<'mc> }, + DoorToggle { inner: EffectStruct<'mc> }, + IronDoorToggle { inner: EffectStruct<'mc> }, + TrapdoorToggle { inner: EffectStruct<'mc> }, + IronTrapdoorToggle { inner: EffectStruct<'mc> }, + FenceGateToggle { inner: EffectStruct<'mc> }, + DoorClose { inner: EffectStruct<'mc> }, + IronDoorClose { inner: EffectStruct<'mc> }, + TrapdoorClose { inner: EffectStruct<'mc> }, + IronTrapdoorClose { inner: EffectStruct<'mc> }, + FenceGateClose { inner: EffectStruct<'mc> }, + Extinguish { inner: EffectStruct<'mc> }, + RecordPlay { inner: EffectStruct<'mc> }, + GhastShriek { inner: EffectStruct<'mc> }, + GhastShoot { inner: EffectStruct<'mc> }, + BlazeShoot { inner: EffectStruct<'mc> }, + ZombieChewWoodenDoor { inner: EffectStruct<'mc> }, + ZombieChewIronDoor { inner: EffectStruct<'mc> }, + ZombieDestroyDoor { inner: EffectStruct<'mc> }, + Smoke { inner: EffectStruct<'mc> }, + StepSound { inner: EffectStruct<'mc> }, + PotionBreak { inner: EffectStruct<'mc> }, + InstantPotionBreak { inner: EffectStruct<'mc> }, + EnderSignal { inner: EffectStruct<'mc> }, + MobspawnerFlames { inner: EffectStruct<'mc> }, + BrewingStandBrew { inner: EffectStruct<'mc> }, + ChorusFlowerGrow { inner: EffectStruct<'mc> }, + ChorusFlowerDeath { inner: EffectStruct<'mc> }, + PortalTravel { inner: EffectStruct<'mc> }, + EndereyeLaunch { inner: EffectStruct<'mc> }, + FireworkShoot { inner: EffectStruct<'mc> }, + VillagerPlantGrow { inner: EffectStruct<'mc> }, + DragonBreath { inner: EffectStruct<'mc> }, + AnvilBreak { inner: EffectStruct<'mc> }, + AnvilUse { inner: EffectStruct<'mc> }, + AnvilLand { inner: EffectStruct<'mc> }, + EnderdragonShoot { inner: EffectStruct<'mc> }, + WitherBreakBlock { inner: EffectStruct<'mc> }, + WitherShoot { inner: EffectStruct<'mc> }, + ZombieInfect { inner: EffectStruct<'mc> }, + ZombieConvertedVillager { inner: EffectStruct<'mc> }, + BatTakeoff { inner: EffectStruct<'mc> }, + EndGatewaySpawn { inner: EffectStruct<'mc> }, + EnderdragonGrowl { inner: EffectStruct<'mc> }, + PhantomBite { inner: EffectStruct<'mc> }, + ZombieConvertedToDrowned { inner: EffectStruct<'mc> }, + HuskConvertedToZombie { inner: EffectStruct<'mc> }, + GrindstoneUse { inner: EffectStruct<'mc> }, + BookPageTurn { inner: EffectStruct<'mc> }, + SmithingTableUse { inner: EffectStruct<'mc> }, + PointedDripstoneLand { inner: EffectStruct<'mc> }, + PointedDripstoneDripLavaIntoCauldron { inner: EffectStruct<'mc> }, + PointedDripstoneDripWaterIntoCauldron { inner: EffectStruct<'mc> }, + SkeletonConvertedToStray { inner: EffectStruct<'mc> }, + ComposterFillAttempt { inner: EffectStruct<'mc> }, + LavaInteract { inner: EffectStruct<'mc> }, + RedstoneTorchBurnout { inner: EffectStruct<'mc> }, + EndPortalFrameFill { inner: EffectStruct<'mc> }, + DrippingDripstone { inner: EffectStruct<'mc> }, + BoneMealUse { inner: EffectStruct<'mc> }, + EnderDragonDestroyBlock { inner: EffectStruct<'mc> }, + SpongeDry { inner: EffectStruct<'mc> }, + ElectricSpark { inner: EffectStruct<'mc> }, + CopperWaxOn { inner: EffectStruct<'mc> }, + CopperWaxOff { inner: EffectStruct<'mc> }, + OxidisedCopperScrape { inner: EffectStruct<'mc> }, +} +impl<'mc> std::fmt::Display for Effect<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + Effect::Click2 { .. } => f.write_str("CLICK2"), + Effect::Click1 { .. } => f.write_str("CLICK1"), + Effect::BowFire { .. } => f.write_str("BOW_FIRE"), + Effect::DoorToggle { .. } => f.write_str("DOOR_TOGGLE"), + Effect::IronDoorToggle { .. } => f.write_str("IRON_DOOR_TOGGLE"), + Effect::TrapdoorToggle { .. } => f.write_str("TRAPDOOR_TOGGLE"), + Effect::IronTrapdoorToggle { .. } => f.write_str("IRON_TRAPDOOR_TOGGLE"), + Effect::FenceGateToggle { .. } => f.write_str("FENCE_GATE_TOGGLE"), + Effect::DoorClose { .. } => f.write_str("DOOR_CLOSE"), + Effect::IronDoorClose { .. } => f.write_str("IRON_DOOR_CLOSE"), + Effect::TrapdoorClose { .. } => f.write_str("TRAPDOOR_CLOSE"), + Effect::IronTrapdoorClose { .. } => f.write_str("IRON_TRAPDOOR_CLOSE"), + Effect::FenceGateClose { .. } => f.write_str("FENCE_GATE_CLOSE"), + Effect::Extinguish { .. } => f.write_str("EXTINGUISH"), + Effect::RecordPlay { .. } => f.write_str("RECORD_PLAY"), + Effect::GhastShriek { .. } => f.write_str("GHAST_SHRIEK"), + Effect::GhastShoot { .. } => f.write_str("GHAST_SHOOT"), + Effect::BlazeShoot { .. } => f.write_str("BLAZE_SHOOT"), + Effect::ZombieChewWoodenDoor { .. } => f.write_str("ZOMBIE_CHEW_WOODEN_DOOR"), + Effect::ZombieChewIronDoor { .. } => f.write_str("ZOMBIE_CHEW_IRON_DOOR"), + Effect::ZombieDestroyDoor { .. } => f.write_str("ZOMBIE_DESTROY_DOOR"), + Effect::Smoke { .. } => f.write_str("SMOKE"), + Effect::StepSound { .. } => f.write_str("STEP_SOUND"), + Effect::PotionBreak { .. } => f.write_str("POTION_BREAK"), + Effect::InstantPotionBreak { .. } => f.write_str("INSTANT_POTION_BREAK"), + Effect::EnderSignal { .. } => f.write_str("ENDER_SIGNAL"), + Effect::MobspawnerFlames { .. } => f.write_str("MOBSPAWNER_FLAMES"), + Effect::BrewingStandBrew { .. } => f.write_str("BREWING_STAND_BREW"), + Effect::ChorusFlowerGrow { .. } => f.write_str("CHORUS_FLOWER_GROW"), + Effect::ChorusFlowerDeath { .. } => f.write_str("CHORUS_FLOWER_DEATH"), + Effect::PortalTravel { .. } => f.write_str("PORTAL_TRAVEL"), + Effect::EndereyeLaunch { .. } => f.write_str("ENDEREYE_LAUNCH"), + Effect::FireworkShoot { .. } => f.write_str("FIREWORK_SHOOT"), + Effect::VillagerPlantGrow { .. } => f.write_str("VILLAGER_PLANT_GROW"), + Effect::DragonBreath { .. } => f.write_str("DRAGON_BREATH"), + Effect::AnvilBreak { .. } => f.write_str("ANVIL_BREAK"), + Effect::AnvilUse { .. } => f.write_str("ANVIL_USE"), + Effect::AnvilLand { .. } => f.write_str("ANVIL_LAND"), + Effect::EnderdragonShoot { .. } => f.write_str("ENDERDRAGON_SHOOT"), + Effect::WitherBreakBlock { .. } => f.write_str("WITHER_BREAK_BLOCK"), + Effect::WitherShoot { .. } => f.write_str("WITHER_SHOOT"), + Effect::ZombieInfect { .. } => f.write_str("ZOMBIE_INFECT"), + Effect::ZombieConvertedVillager { .. } => f.write_str("ZOMBIE_CONVERTED_VILLAGER"), + Effect::BatTakeoff { .. } => f.write_str("BAT_TAKEOFF"), + Effect::EndGatewaySpawn { .. } => f.write_str("END_GATEWAY_SPAWN"), + Effect::EnderdragonGrowl { .. } => f.write_str("ENDERDRAGON_GROWL"), + Effect::PhantomBite { .. } => f.write_str("PHANTOM_BITE"), + Effect::ZombieConvertedToDrowned { .. } => f.write_str("ZOMBIE_CONVERTED_TO_DROWNED"), + Effect::HuskConvertedToZombie { .. } => f.write_str("HUSK_CONVERTED_TO_ZOMBIE"), + Effect::GrindstoneUse { .. } => f.write_str("GRINDSTONE_USE"), + Effect::BookPageTurn { .. } => f.write_str("BOOK_PAGE_TURN"), + Effect::SmithingTableUse { .. } => f.write_str("SMITHING_TABLE_USE"), + Effect::PointedDripstoneLand { .. } => f.write_str("POINTED_DRIPSTONE_LAND"), + Effect::PointedDripstoneDripLavaIntoCauldron { .. } => { + f.write_str("POINTED_DRIPSTONE_DRIP_LAVA_INTO_CAULDRON") + } + Effect::PointedDripstoneDripWaterIntoCauldron { .. } => { + f.write_str("POINTED_DRIPSTONE_DRIP_WATER_INTO_CAULDRON") + } + Effect::SkeletonConvertedToStray { .. } => f.write_str("SKELETON_CONVERTED_TO_STRAY"), + Effect::ComposterFillAttempt { .. } => f.write_str("COMPOSTER_FILL_ATTEMPT"), + Effect::LavaInteract { .. } => f.write_str("LAVA_INTERACT"), + Effect::RedstoneTorchBurnout { .. } => f.write_str("REDSTONE_TORCH_BURNOUT"), + Effect::EndPortalFrameFill { .. } => f.write_str("END_PORTAL_FRAME_FILL"), + Effect::DrippingDripstone { .. } => f.write_str("DRIPPING_DRIPSTONE"), + Effect::BoneMealUse { .. } => f.write_str("BONE_MEAL_USE"), + Effect::EnderDragonDestroyBlock { .. } => f.write_str("ENDER_DRAGON_DESTROY_BLOCK"), + Effect::SpongeDry { .. } => f.write_str("SPONGE_DRY"), + Effect::ElectricSpark { .. } => f.write_str("ELECTRIC_SPARK"), + Effect::CopperWaxOn { .. } => f.write_str("COPPER_WAX_ON"), + Effect::CopperWaxOff { .. } => f.write_str("COPPER_WAX_OFF"), + Effect::OxidisedCopperScrape { .. } => f.write_str("OXIDISED_COPPER_SCRAPE"), + } + } +} +impl<'mc> std::ops::Deref for Effect<'mc> { + type Target = EffectStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + Effect::Click2 { inner } => inner, + Effect::Click1 { inner } => inner, + Effect::BowFire { inner } => inner, + Effect::DoorToggle { inner } => inner, + Effect::IronDoorToggle { inner } => inner, + Effect::TrapdoorToggle { inner } => inner, + Effect::IronTrapdoorToggle { inner } => inner, + Effect::FenceGateToggle { inner } => inner, + Effect::DoorClose { inner } => inner, + Effect::IronDoorClose { inner } => inner, + Effect::TrapdoorClose { inner } => inner, + Effect::IronTrapdoorClose { inner } => inner, + Effect::FenceGateClose { inner } => inner, + Effect::Extinguish { inner } => inner, + Effect::RecordPlay { inner } => inner, + Effect::GhastShriek { inner } => inner, + Effect::GhastShoot { inner } => inner, + Effect::BlazeShoot { inner } => inner, + Effect::ZombieChewWoodenDoor { inner } => inner, + Effect::ZombieChewIronDoor { inner } => inner, + Effect::ZombieDestroyDoor { inner } => inner, + Effect::Smoke { inner } => inner, + Effect::StepSound { inner } => inner, + Effect::PotionBreak { inner } => inner, + Effect::InstantPotionBreak { inner } => inner, + Effect::EnderSignal { inner } => inner, + Effect::MobspawnerFlames { inner } => inner, + Effect::BrewingStandBrew { inner } => inner, + Effect::ChorusFlowerGrow { inner } => inner, + Effect::ChorusFlowerDeath { inner } => inner, + Effect::PortalTravel { inner } => inner, + Effect::EndereyeLaunch { inner } => inner, + Effect::FireworkShoot { inner } => inner, + Effect::VillagerPlantGrow { inner } => inner, + Effect::DragonBreath { inner } => inner, + Effect::AnvilBreak { inner } => inner, + Effect::AnvilUse { inner } => inner, + Effect::AnvilLand { inner } => inner, + Effect::EnderdragonShoot { inner } => inner, + Effect::WitherBreakBlock { inner } => inner, + Effect::WitherShoot { inner } => inner, + Effect::ZombieInfect { inner } => inner, + Effect::ZombieConvertedVillager { inner } => inner, + Effect::BatTakeoff { inner } => inner, + Effect::EndGatewaySpawn { inner } => inner, + Effect::EnderdragonGrowl { inner } => inner, + Effect::PhantomBite { inner } => inner, + Effect::ZombieConvertedToDrowned { inner } => inner, + Effect::HuskConvertedToZombie { inner } => inner, + Effect::GrindstoneUse { inner } => inner, + Effect::BookPageTurn { inner } => inner, + Effect::SmithingTableUse { inner } => inner, + Effect::PointedDripstoneLand { inner } => inner, + Effect::PointedDripstoneDripLavaIntoCauldron { inner } => inner, + Effect::PointedDripstoneDripWaterIntoCauldron { inner } => inner, + Effect::SkeletonConvertedToStray { inner } => inner, + Effect::ComposterFillAttempt { inner } => inner, + Effect::LavaInteract { inner } => inner, + Effect::RedstoneTorchBurnout { inner } => inner, + Effect::EndPortalFrameFill { inner } => inner, + Effect::DrippingDripstone { inner } => inner, + Effect::BoneMealUse { inner } => inner, + Effect::EnderDragonDestroyBlock { inner } => inner, + Effect::SpongeDry { inner } => inner, + Effect::ElectricSpark { inner } => inner, + Effect::CopperWaxOn { inner } => inner, + Effect::CopperWaxOff { inner } => inner, + Effect::OxidisedCopperScrape { inner } => inner, + } } } -impl<'mc> GrassSpecies<'mc> { +impl<'mc> Effect<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/GrassSpecies"); + let cls = env.find_class("org/bukkit/Effect"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/GrassSpecies;", + "(Ljava/lang/String;)Lorg/bukkit/Effect;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -8716,37 +61282,510 @@ impl<'mc> GrassSpecies<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "CLICK2" => Ok(Effect::Click2 { + inner: EffectStruct::from_raw(env, obj)?, + }), + "CLICK1" => Ok(Effect::Click1 { + inner: EffectStruct::from_raw(env, obj)?, + }), + "BOW_FIRE" => Ok(Effect::BowFire { + inner: EffectStruct::from_raw(env, obj)?, + }), + "DOOR_TOGGLE" => Ok(Effect::DoorToggle { + inner: EffectStruct::from_raw(env, obj)?, + }), + "IRON_DOOR_TOGGLE" => Ok(Effect::IronDoorToggle { + inner: EffectStruct::from_raw(env, obj)?, + }), + "TRAPDOOR_TOGGLE" => Ok(Effect::TrapdoorToggle { + inner: EffectStruct::from_raw(env, obj)?, + }), + "IRON_TRAPDOOR_TOGGLE" => Ok(Effect::IronTrapdoorToggle { + inner: EffectStruct::from_raw(env, obj)?, + }), + "FENCE_GATE_TOGGLE" => Ok(Effect::FenceGateToggle { + inner: EffectStruct::from_raw(env, obj)?, + }), + "DOOR_CLOSE" => Ok(Effect::DoorClose { + inner: EffectStruct::from_raw(env, obj)?, + }), + "IRON_DOOR_CLOSE" => Ok(Effect::IronDoorClose { + inner: EffectStruct::from_raw(env, obj)?, + }), + "TRAPDOOR_CLOSE" => Ok(Effect::TrapdoorClose { + inner: EffectStruct::from_raw(env, obj)?, + }), + "IRON_TRAPDOOR_CLOSE" => Ok(Effect::IronTrapdoorClose { + inner: EffectStruct::from_raw(env, obj)?, + }), + "FENCE_GATE_CLOSE" => Ok(Effect::FenceGateClose { + inner: EffectStruct::from_raw(env, obj)?, + }), + "EXTINGUISH" => Ok(Effect::Extinguish { + inner: EffectStruct::from_raw(env, obj)?, + }), + "RECORD_PLAY" => Ok(Effect::RecordPlay { + inner: EffectStruct::from_raw(env, obj)?, + }), + "GHAST_SHRIEK" => Ok(Effect::GhastShriek { + inner: EffectStruct::from_raw(env, obj)?, + }), + "GHAST_SHOOT" => Ok(Effect::GhastShoot { + inner: EffectStruct::from_raw(env, obj)?, + }), + "BLAZE_SHOOT" => Ok(Effect::BlazeShoot { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ZOMBIE_CHEW_WOODEN_DOOR" => Ok(Effect::ZombieChewWoodenDoor { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ZOMBIE_CHEW_IRON_DOOR" => Ok(Effect::ZombieChewIronDoor { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ZOMBIE_DESTROY_DOOR" => Ok(Effect::ZombieDestroyDoor { + inner: EffectStruct::from_raw(env, obj)?, + }), + "SMOKE" => Ok(Effect::Smoke { + inner: EffectStruct::from_raw(env, obj)?, + }), + "STEP_SOUND" => Ok(Effect::StepSound { + inner: EffectStruct::from_raw(env, obj)?, + }), + "POTION_BREAK" => Ok(Effect::PotionBreak { + inner: EffectStruct::from_raw(env, obj)?, + }), + "INSTANT_POTION_BREAK" => Ok(Effect::InstantPotionBreak { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ENDER_SIGNAL" => Ok(Effect::EnderSignal { + inner: EffectStruct::from_raw(env, obj)?, + }), + "MOBSPAWNER_FLAMES" => Ok(Effect::MobspawnerFlames { + inner: EffectStruct::from_raw(env, obj)?, + }), + "BREWING_STAND_BREW" => Ok(Effect::BrewingStandBrew { + inner: EffectStruct::from_raw(env, obj)?, + }), + "CHORUS_FLOWER_GROW" => Ok(Effect::ChorusFlowerGrow { + inner: EffectStruct::from_raw(env, obj)?, + }), + "CHORUS_FLOWER_DEATH" => Ok(Effect::ChorusFlowerDeath { + inner: EffectStruct::from_raw(env, obj)?, + }), + "PORTAL_TRAVEL" => Ok(Effect::PortalTravel { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ENDEREYE_LAUNCH" => Ok(Effect::EndereyeLaunch { + inner: EffectStruct::from_raw(env, obj)?, + }), + "FIREWORK_SHOOT" => Ok(Effect::FireworkShoot { + inner: EffectStruct::from_raw(env, obj)?, + }), + "VILLAGER_PLANT_GROW" => Ok(Effect::VillagerPlantGrow { + inner: EffectStruct::from_raw(env, obj)?, + }), + "DRAGON_BREATH" => Ok(Effect::DragonBreath { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ANVIL_BREAK" => Ok(Effect::AnvilBreak { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ANVIL_USE" => Ok(Effect::AnvilUse { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ANVIL_LAND" => Ok(Effect::AnvilLand { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ENDERDRAGON_SHOOT" => Ok(Effect::EnderdragonShoot { + inner: EffectStruct::from_raw(env, obj)?, + }), + "WITHER_BREAK_BLOCK" => Ok(Effect::WitherBreakBlock { + inner: EffectStruct::from_raw(env, obj)?, + }), + "WITHER_SHOOT" => Ok(Effect::WitherShoot { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ZOMBIE_INFECT" => Ok(Effect::ZombieInfect { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ZOMBIE_CONVERTED_VILLAGER" => Ok(Effect::ZombieConvertedVillager { + inner: EffectStruct::from_raw(env, obj)?, + }), + "BAT_TAKEOFF" => Ok(Effect::BatTakeoff { + inner: EffectStruct::from_raw(env, obj)?, + }), + "END_GATEWAY_SPAWN" => Ok(Effect::EndGatewaySpawn { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ENDERDRAGON_GROWL" => Ok(Effect::EnderdragonGrowl { + inner: EffectStruct::from_raw(env, obj)?, + }), + "PHANTOM_BITE" => Ok(Effect::PhantomBite { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ZOMBIE_CONVERTED_TO_DROWNED" => Ok(Effect::ZombieConvertedToDrowned { + inner: EffectStruct::from_raw(env, obj)?, + }), + "HUSK_CONVERTED_TO_ZOMBIE" => Ok(Effect::HuskConvertedToZombie { + inner: EffectStruct::from_raw(env, obj)?, + }), + "GRINDSTONE_USE" => Ok(Effect::GrindstoneUse { + inner: EffectStruct::from_raw(env, obj)?, + }), + "BOOK_PAGE_TURN" => Ok(Effect::BookPageTurn { + inner: EffectStruct::from_raw(env, obj)?, + }), + "SMITHING_TABLE_USE" => Ok(Effect::SmithingTableUse { + inner: EffectStruct::from_raw(env, obj)?, + }), + "POINTED_DRIPSTONE_LAND" => Ok(Effect::PointedDripstoneLand { + inner: EffectStruct::from_raw(env, obj)?, + }), + "POINTED_DRIPSTONE_DRIP_LAVA_INTO_CAULDRON" => { + Ok(Effect::PointedDripstoneDripLavaIntoCauldron { + inner: EffectStruct::from_raw(env, obj)?, + }) + } + "POINTED_DRIPSTONE_DRIP_WATER_INTO_CAULDRON" => { + Ok(Effect::PointedDripstoneDripWaterIntoCauldron { + inner: EffectStruct::from_raw(env, obj)?, + }) + } + "SKELETON_CONVERTED_TO_STRAY" => Ok(Effect::SkeletonConvertedToStray { + inner: EffectStruct::from_raw(env, obj)?, + }), + "COMPOSTER_FILL_ATTEMPT" => Ok(Effect::ComposterFillAttempt { + inner: EffectStruct::from_raw(env, obj)?, + }), + "LAVA_INTERACT" => Ok(Effect::LavaInteract { + inner: EffectStruct::from_raw(env, obj)?, + }), + "REDSTONE_TORCH_BURNOUT" => Ok(Effect::RedstoneTorchBurnout { + inner: EffectStruct::from_raw(env, obj)?, + }), + "END_PORTAL_FRAME_FILL" => Ok(Effect::EndPortalFrameFill { + inner: EffectStruct::from_raw(env, obj)?, + }), + "DRIPPING_DRIPSTONE" => Ok(Effect::DrippingDripstone { + inner: EffectStruct::from_raw(env, obj)?, + }), + "BONE_MEAL_USE" => Ok(Effect::BoneMealUse { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ENDER_DRAGON_DESTROY_BLOCK" => Ok(Effect::EnderDragonDestroyBlock { + inner: EffectStruct::from_raw(env, obj)?, + }), + "SPONGE_DRY" => Ok(Effect::SpongeDry { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ELECTRIC_SPARK" => Ok(Effect::ElectricSpark { + inner: EffectStruct::from_raw(env, obj)?, + }), + "COPPER_WAX_ON" => Ok(Effect::CopperWaxOn { + inner: EffectStruct::from_raw(env, obj)?, + }), + "COPPER_WAX_OFF" => Ok(Effect::CopperWaxOff { + inner: EffectStruct::from_raw(env, obj)?, + }), + "OXIDISED_COPPER_SCRAPE" => Ok(Effect::OxidisedCopperScrape { + inner: EffectStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct GrassSpeciesStruct<'mc>( +pub struct EffectStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for GrassSpecies<'mc> { +impl<'mc> JNIRaw<'mc> for Effect<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Click2 { inner } => inner.0.clone(), + Self::Click1 { inner } => inner.0.clone(), + Self::BowFire { inner } => inner.0.clone(), + Self::DoorToggle { inner } => inner.0.clone(), + Self::IronDoorToggle { inner } => inner.0.clone(), + Self::TrapdoorToggle { inner } => inner.0.clone(), + Self::IronTrapdoorToggle { inner } => inner.0.clone(), + Self::FenceGateToggle { inner } => inner.0.clone(), + Self::DoorClose { inner } => inner.0.clone(), + Self::IronDoorClose { inner } => inner.0.clone(), + Self::TrapdoorClose { inner } => inner.0.clone(), + Self::IronTrapdoorClose { inner } => inner.0.clone(), + Self::FenceGateClose { inner } => inner.0.clone(), + Self::Extinguish { inner } => inner.0.clone(), + Self::RecordPlay { inner } => inner.0.clone(), + Self::GhastShriek { inner } => inner.0.clone(), + Self::GhastShoot { inner } => inner.0.clone(), + Self::BlazeShoot { inner } => inner.0.clone(), + Self::ZombieChewWoodenDoor { inner } => inner.0.clone(), + Self::ZombieChewIronDoor { inner } => inner.0.clone(), + Self::ZombieDestroyDoor { inner } => inner.0.clone(), + Self::Smoke { inner } => inner.0.clone(), + Self::StepSound { inner } => inner.0.clone(), + Self::PotionBreak { inner } => inner.0.clone(), + Self::InstantPotionBreak { inner } => inner.0.clone(), + Self::EnderSignal { inner } => inner.0.clone(), + Self::MobspawnerFlames { inner } => inner.0.clone(), + Self::BrewingStandBrew { inner } => inner.0.clone(), + Self::ChorusFlowerGrow { inner } => inner.0.clone(), + Self::ChorusFlowerDeath { inner } => inner.0.clone(), + Self::PortalTravel { inner } => inner.0.clone(), + Self::EndereyeLaunch { inner } => inner.0.clone(), + Self::FireworkShoot { inner } => inner.0.clone(), + Self::VillagerPlantGrow { inner } => inner.0.clone(), + Self::DragonBreath { inner } => inner.0.clone(), + Self::AnvilBreak { inner } => inner.0.clone(), + Self::AnvilUse { inner } => inner.0.clone(), + Self::AnvilLand { inner } => inner.0.clone(), + Self::EnderdragonShoot { inner } => inner.0.clone(), + Self::WitherBreakBlock { inner } => inner.0.clone(), + Self::WitherShoot { inner } => inner.0.clone(), + Self::ZombieInfect { inner } => inner.0.clone(), + Self::ZombieConvertedVillager { inner } => inner.0.clone(), + Self::BatTakeoff { inner } => inner.0.clone(), + Self::EndGatewaySpawn { inner } => inner.0.clone(), + Self::EnderdragonGrowl { inner } => inner.0.clone(), + Self::PhantomBite { inner } => inner.0.clone(), + Self::ZombieConvertedToDrowned { inner } => inner.0.clone(), + Self::HuskConvertedToZombie { inner } => inner.0.clone(), + Self::GrindstoneUse { inner } => inner.0.clone(), + Self::BookPageTurn { inner } => inner.0.clone(), + Self::SmithingTableUse { inner } => inner.0.clone(), + Self::PointedDripstoneLand { inner } => inner.0.clone(), + Self::PointedDripstoneDripLavaIntoCauldron { inner } => inner.0.clone(), + Self::PointedDripstoneDripWaterIntoCauldron { inner } => inner.0.clone(), + Self::SkeletonConvertedToStray { inner } => inner.0.clone(), + Self::ComposterFillAttempt { inner } => inner.0.clone(), + Self::LavaInteract { inner } => inner.0.clone(), + Self::RedstoneTorchBurnout { inner } => inner.0.clone(), + Self::EndPortalFrameFill { inner } => inner.0.clone(), + Self::DrippingDripstone { inner } => inner.0.clone(), + Self::BoneMealUse { inner } => inner.0.clone(), + Self::EnderDragonDestroyBlock { inner } => inner.0.clone(), + Self::SpongeDry { inner } => inner.0.clone(), + Self::ElectricSpark { inner } => inner.0.clone(), + Self::CopperWaxOn { inner } => inner.0.clone(), + Self::CopperWaxOff { inner } => inner.0.clone(), + Self::OxidisedCopperScrape { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Click2 { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Click1 { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BowFire { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DoorToggle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronDoorToggle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrapdoorToggle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronTrapdoorToggle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FenceGateToggle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DoorClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronDoorClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrapdoorClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronTrapdoorClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FenceGateClose { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Extinguish { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RecordPlay { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GhastShriek { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GhastShoot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BlazeShoot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ZombieChewWoodenDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ZombieChewIronDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ZombieDestroyDoor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Smoke { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::StepSound { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PotionBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::InstantPotionBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnderSignal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MobspawnerFlames { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrewingStandBrew { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChorusFlowerGrow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChorusFlowerDeath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PortalTravel { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EndereyeLaunch { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FireworkShoot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VillagerPlantGrow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DragonBreath { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AnvilBreak { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AnvilUse { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::AnvilLand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnderdragonShoot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WitherBreakBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WitherShoot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ZombieInfect { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ZombieConvertedVillager { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BatTakeoff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EndGatewaySpawn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnderdragonGrowl { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PhantomBite { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ZombieConvertedToDrowned { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HuskConvertedToZombie { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::GrindstoneUse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BookPageTurn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SmithingTableUse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PointedDripstoneLand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PointedDripstoneDripLavaIntoCauldron { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PointedDripstoneDripWaterIntoCauldron { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SkeletonConvertedToStray { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ComposterFillAttempt { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LavaInteract { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedstoneTorchBurnout { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EndPortalFrameFill { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DrippingDripstone { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BoneMealUse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnderDragonDestroyBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SpongeDry { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ElectricSpark { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CopperWaxOn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CopperWaxOff { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OxidisedCopperScrape { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } -impl<'mc> JNIInstantiatable<'mc> for GrassSpecies<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Effect<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate GrassSpecies from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Effect from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/GrassSpecies")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/Effect")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a GrassSpecies object, got {}", + "Invalid argument passed. Expected a Effect object, got {}", name ) .into()) @@ -8758,13 +61797,221 @@ impl<'mc> JNIInstantiatable<'mc> for GrassSpecies<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "CLICK2" => Ok(Effect::Click2 { + inner: EffectStruct::from_raw(env, obj)?, + }), + "CLICK1" => Ok(Effect::Click1 { + inner: EffectStruct::from_raw(env, obj)?, + }), + "BOW_FIRE" => Ok(Effect::BowFire { + inner: EffectStruct::from_raw(env, obj)?, + }), + "DOOR_TOGGLE" => Ok(Effect::DoorToggle { + inner: EffectStruct::from_raw(env, obj)?, + }), + "IRON_DOOR_TOGGLE" => Ok(Effect::IronDoorToggle { + inner: EffectStruct::from_raw(env, obj)?, + }), + "TRAPDOOR_TOGGLE" => Ok(Effect::TrapdoorToggle { + inner: EffectStruct::from_raw(env, obj)?, + }), + "IRON_TRAPDOOR_TOGGLE" => Ok(Effect::IronTrapdoorToggle { + inner: EffectStruct::from_raw(env, obj)?, + }), + "FENCE_GATE_TOGGLE" => Ok(Effect::FenceGateToggle { + inner: EffectStruct::from_raw(env, obj)?, + }), + "DOOR_CLOSE" => Ok(Effect::DoorClose { + inner: EffectStruct::from_raw(env, obj)?, + }), + "IRON_DOOR_CLOSE" => Ok(Effect::IronDoorClose { + inner: EffectStruct::from_raw(env, obj)?, + }), + "TRAPDOOR_CLOSE" => Ok(Effect::TrapdoorClose { + inner: EffectStruct::from_raw(env, obj)?, + }), + "IRON_TRAPDOOR_CLOSE" => Ok(Effect::IronTrapdoorClose { + inner: EffectStruct::from_raw(env, obj)?, + }), + "FENCE_GATE_CLOSE" => Ok(Effect::FenceGateClose { + inner: EffectStruct::from_raw(env, obj)?, + }), + "EXTINGUISH" => Ok(Effect::Extinguish { + inner: EffectStruct::from_raw(env, obj)?, + }), + "RECORD_PLAY" => Ok(Effect::RecordPlay { + inner: EffectStruct::from_raw(env, obj)?, + }), + "GHAST_SHRIEK" => Ok(Effect::GhastShriek { + inner: EffectStruct::from_raw(env, obj)?, + }), + "GHAST_SHOOT" => Ok(Effect::GhastShoot { + inner: EffectStruct::from_raw(env, obj)?, + }), + "BLAZE_SHOOT" => Ok(Effect::BlazeShoot { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ZOMBIE_CHEW_WOODEN_DOOR" => Ok(Effect::ZombieChewWoodenDoor { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ZOMBIE_CHEW_IRON_DOOR" => Ok(Effect::ZombieChewIronDoor { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ZOMBIE_DESTROY_DOOR" => Ok(Effect::ZombieDestroyDoor { + inner: EffectStruct::from_raw(env, obj)?, + }), + "SMOKE" => Ok(Effect::Smoke { + inner: EffectStruct::from_raw(env, obj)?, + }), + "STEP_SOUND" => Ok(Effect::StepSound { + inner: EffectStruct::from_raw(env, obj)?, + }), + "POTION_BREAK" => Ok(Effect::PotionBreak { + inner: EffectStruct::from_raw(env, obj)?, + }), + "INSTANT_POTION_BREAK" => Ok(Effect::InstantPotionBreak { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ENDER_SIGNAL" => Ok(Effect::EnderSignal { + inner: EffectStruct::from_raw(env, obj)?, + }), + "MOBSPAWNER_FLAMES" => Ok(Effect::MobspawnerFlames { + inner: EffectStruct::from_raw(env, obj)?, + }), + "BREWING_STAND_BREW" => Ok(Effect::BrewingStandBrew { + inner: EffectStruct::from_raw(env, obj)?, + }), + "CHORUS_FLOWER_GROW" => Ok(Effect::ChorusFlowerGrow { + inner: EffectStruct::from_raw(env, obj)?, + }), + "CHORUS_FLOWER_DEATH" => Ok(Effect::ChorusFlowerDeath { + inner: EffectStruct::from_raw(env, obj)?, + }), + "PORTAL_TRAVEL" => Ok(Effect::PortalTravel { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ENDEREYE_LAUNCH" => Ok(Effect::EndereyeLaunch { + inner: EffectStruct::from_raw(env, obj)?, + }), + "FIREWORK_SHOOT" => Ok(Effect::FireworkShoot { + inner: EffectStruct::from_raw(env, obj)?, + }), + "VILLAGER_PLANT_GROW" => Ok(Effect::VillagerPlantGrow { + inner: EffectStruct::from_raw(env, obj)?, + }), + "DRAGON_BREATH" => Ok(Effect::DragonBreath { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ANVIL_BREAK" => Ok(Effect::AnvilBreak { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ANVIL_USE" => Ok(Effect::AnvilUse { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ANVIL_LAND" => Ok(Effect::AnvilLand { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ENDERDRAGON_SHOOT" => Ok(Effect::EnderdragonShoot { + inner: EffectStruct::from_raw(env, obj)?, + }), + "WITHER_BREAK_BLOCK" => Ok(Effect::WitherBreakBlock { + inner: EffectStruct::from_raw(env, obj)?, + }), + "WITHER_SHOOT" => Ok(Effect::WitherShoot { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ZOMBIE_INFECT" => Ok(Effect::ZombieInfect { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ZOMBIE_CONVERTED_VILLAGER" => Ok(Effect::ZombieConvertedVillager { + inner: EffectStruct::from_raw(env, obj)?, + }), + "BAT_TAKEOFF" => Ok(Effect::BatTakeoff { + inner: EffectStruct::from_raw(env, obj)?, + }), + "END_GATEWAY_SPAWN" => Ok(Effect::EndGatewaySpawn { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ENDERDRAGON_GROWL" => Ok(Effect::EnderdragonGrowl { + inner: EffectStruct::from_raw(env, obj)?, + }), + "PHANTOM_BITE" => Ok(Effect::PhantomBite { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ZOMBIE_CONVERTED_TO_DROWNED" => Ok(Effect::ZombieConvertedToDrowned { + inner: EffectStruct::from_raw(env, obj)?, + }), + "HUSK_CONVERTED_TO_ZOMBIE" => Ok(Effect::HuskConvertedToZombie { + inner: EffectStruct::from_raw(env, obj)?, + }), + "GRINDSTONE_USE" => Ok(Effect::GrindstoneUse { + inner: EffectStruct::from_raw(env, obj)?, + }), + "BOOK_PAGE_TURN" => Ok(Effect::BookPageTurn { + inner: EffectStruct::from_raw(env, obj)?, + }), + "SMITHING_TABLE_USE" => Ok(Effect::SmithingTableUse { + inner: EffectStruct::from_raw(env, obj)?, + }), + "POINTED_DRIPSTONE_LAND" => Ok(Effect::PointedDripstoneLand { + inner: EffectStruct::from_raw(env, obj)?, + }), + "POINTED_DRIPSTONE_DRIP_LAVA_INTO_CAULDRON" => { + Ok(Effect::PointedDripstoneDripLavaIntoCauldron { + inner: EffectStruct::from_raw(env, obj)?, + }) + } + "POINTED_DRIPSTONE_DRIP_WATER_INTO_CAULDRON" => { + Ok(Effect::PointedDripstoneDripWaterIntoCauldron { + inner: EffectStruct::from_raw(env, obj)?, + }) + } + "SKELETON_CONVERTED_TO_STRAY" => Ok(Effect::SkeletonConvertedToStray { + inner: EffectStruct::from_raw(env, obj)?, + }), + "COMPOSTER_FILL_ATTEMPT" => Ok(Effect::ComposterFillAttempt { + inner: EffectStruct::from_raw(env, obj)?, + }), + "LAVA_INTERACT" => Ok(Effect::LavaInteract { + inner: EffectStruct::from_raw(env, obj)?, + }), + "REDSTONE_TORCH_BURNOUT" => Ok(Effect::RedstoneTorchBurnout { + inner: EffectStruct::from_raw(env, obj)?, + }), + "END_PORTAL_FRAME_FILL" => Ok(Effect::EndPortalFrameFill { + inner: EffectStruct::from_raw(env, obj)?, + }), + "DRIPPING_DRIPSTONE" => Ok(Effect::DrippingDripstone { + inner: EffectStruct::from_raw(env, obj)?, + }), + "BONE_MEAL_USE" => Ok(Effect::BoneMealUse { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ENDER_DRAGON_DESTROY_BLOCK" => Ok(Effect::EnderDragonDestroyBlock { + inner: EffectStruct::from_raw(env, obj)?, + }), + "SPONGE_DRY" => Ok(Effect::SpongeDry { + inner: EffectStruct::from_raw(env, obj)?, + }), + "ELECTRIC_SPARK" => Ok(Effect::ElectricSpark { + inner: EffectStruct::from_raw(env, obj)?, + }), + "COPPER_WAX_ON" => Ok(Effect::CopperWaxOn { + inner: EffectStruct::from_raw(env, obj)?, + }), + "COPPER_WAX_OFF" => Ok(Effect::CopperWaxOff { + inner: EffectStruct::from_raw(env, obj)?, + }), + "OXIDISED_COPPER_SCRAPE" => Ok(Effect::OxidisedCopperScrape { + inner: EffectStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for GrassSpeciesStruct<'mc> { +impl<'mc> JNIRaw<'mc> for EffectStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -8772,20 +62019,18 @@ impl<'mc> JNIRaw<'mc> for GrassSpeciesStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for GrassSpeciesStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EffectStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate GrassSpeciesStruct from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate EffectStruct from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/GrassSpecies")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/Effect")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a GrassSpeciesStruct object, got {}", + "Invalid argument passed. Expected a EffectStruct object, got {}", name ) .into()) @@ -8795,538 +62040,222 @@ impl<'mc> JNIInstantiatable<'mc> for GrassSpeciesStruct<'mc> { } } -impl<'mc> GrassSpeciesStruct<'mc> { +impl<'mc> EffectStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/GrassSpecies;"); - let cls = jni.find_class("org/bukkit/GrassSpecies"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Effect;"); + let cls = jni.find_class("org/bukkit/Effect"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::GrassSpecies::from_raw(&jni, obj) + crate::Effect::from_raw(&jni, obj) } #[deprecated] - /// Gets the associated data value representing this species - pub fn data(&self) -> Result> { - let sig = String::from("()B"); + /// Gets the ID for this effect. + pub fn id(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) - } - #[deprecated] - /// Gets the GrassSpecies with the given data value - pub fn get_by_data( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - data: i8, - ) -> Result>, Box> { - let sig = String::from("(B)Lorg/bukkit/GrassSpecies;"); - let val_1 = jni::objects::JValueGen::Byte(data); - let cls = jni.find_class("org/bukkit/GrassSpecies"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getByData", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::GrassSpecies::from_raw(&jni, obj)?)) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct UnsafeValues<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for UnsafeValues<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for UnsafeValues<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate UnsafeValues from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/UnsafeValues")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a UnsafeValues object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> UnsafeValues<'mc> { - pub fn to_legacy( - &self, - material: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/Material;)Lorg/bukkit/Material;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "toLegacy", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "getId", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - pub fn from_legacy( - &self, - material: impl Into>, - data: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = data { - sig += "B"; - let val_2 = jni::objects::JValueGen::Byte(a); - args.push(val_2); - } - sig += ")Lorg/bukkit/block/data/BlockData;"; + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Effect/Type;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "fromLegacy", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn get_material( - &self, - material: impl Into, - version: i32, - ) -> Result, Box> { - let sig = String::from("(Ljava/lang/String;I)Lorg/bukkit/Material;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(material.into())?, - )); - let val_2 = jni::objects::JValueGen::Int(version); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMaterial", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn data_version(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDataVersion", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - - pub fn modify_item_stack( - &self, - stack: impl Into>, - arguments: impl Into, - ) -> Result, Box> { - let sig = String::from( - "(Lorg/bukkit/inventory/ItemStack;Ljava/lang/String;)Lorg/bukkit/inventory/ItemStack;", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(stack.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(arguments.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "modifyItemStack", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn check_supported( - &self, - pdf: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/plugin/PluginDescriptionFile;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(pdf.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "checkSupported", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn process_class( - &self, - pdf: impl Into>, - path: impl Into, - clazz: i8, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/plugin/PluginDescriptionFile;Ljava/lang/String;B)B"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(pdf.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(path.into())?, - )); - let val_3 = jni::objects::JValueGen::Byte(clazz); - let res = self.jni_ref().call_method( - &self.jni_object(), - "processClass", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) - } - /// Load an advancement represented by the specified string into the server. - /// The advancement format is governed by Minecraft and has no specified - /// layout. - /// - /// It is currently a JSON object, as described by the Minecraft wiki. - /// - /// Loaded advancements will be stored and persisted across server restarts - /// and reloads. - /// - /// Callers should be prepared for {@link Exception} to be thrown. - pub fn load_advancement( - &self, - key: impl Into>, - advancement: impl Into, - ) -> Result, Box> { - let sig = String::from( - "(Lorg/bukkit/NamespacedKey;Ljava/lang/String;)Lorg/bukkit/advancement/Advancement;", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(advancement.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "loadAdvancement", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - crate::advancement::Advancement::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Delete an advancement which was loaded and saved by - /// {@link #loadAdvancement(org.bukkit.NamespacedKey, java.lang.String)}. - /// - /// This method will only remove advancement from persistent storage. It - /// should be accompanied by a call to {@link Server#reloadData()} in order - /// to fully remove it from the running instance. - pub fn remove_advancement( - &self, - key: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removeAdvancement", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn get_default_attribute_modifiers( - &self, - material: impl Into>, - slot: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/Material;Lorg/bukkit/inventory/EquipmentSlot;)Lcom/google/common/collect/Multimap;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(slot.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getDefaultAttributeModifiers", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) - } - - pub fn get_creative_category( - &self, - material: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/Material;)Lorg/bukkit/inventory/CreativeCategory;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCreativeCategory", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::CreativeCategory::from_raw(&self.jni_ref(), unsafe { + crate::EffectType::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn get_block_translation_key( - &self, - material: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/Material;)Ljava/lang/String;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getBlockTranslationKey", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - - pub fn get_item_translation_key( - &self, - material: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/Material;)Ljava/lang/String;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getItemTranslationKey", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - - pub fn get_translation_key( - &self, - attribute: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/attribute/Attribute;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Ljava/lang/String;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTranslationKey", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - - pub fn get_feature_flag( - &self, - key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/FeatureFlag;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFeatureFlag", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::FeatureFlag::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } #[deprecated] - /// Do not use, method will get removed, and the plugin won't run - pub fn get_internal_potion_data( - &self, - key: impl Into>, - ) -> Result, Box> { - let sig = String::from( - "(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/potion/PotionType/InternalPotionData;", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getInternalPotionData", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::potion::PotionTypeInternalPotionData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn get_damage_effect( - &self, - key: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/damage/DamageEffect;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(key.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getDamageEffect", + /// Gets the Effect associated with the given ID. + pub fn get_by_id( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + id: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/Effect;"); + let val_1 = jni::objects::JValueGen::Int(id); + let cls = jni.find_class("org/bukkit/Effect"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getById", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; + let res = jni.translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::damage::DamageEffect::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + let obj = res.l()?; + Ok(Some(crate::Effect::from_raw(&jni, obj)?)) } - /// Create a new {@link DamageSource.Builder}. - pub fn create_damage_source_builder( - &self, - damage_type: impl Into>, - ) -> Result, Box> { - let sig = String::from( - "(Lorg/bukkit/damage/DamageType;)Lorg/bukkit/damage/DamageSource/Builder;", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(damage_type.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "createDamageSourceBuilder", - sig.as_str(), + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +pub enum EffectType<'mc> { + Sound { inner: EffectTypeStruct<'mc> }, + Visual { inner: EffectTypeStruct<'mc> }, +} +impl<'mc> std::fmt::Display for EffectType<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + EffectType::Sound { .. } => f.write_str("SOUND"), + EffectType::Visual { .. } => f.write_str("VISUAL"), + } + } +} +impl<'mc> std::ops::Deref for EffectType<'mc> { + type Target = EffectTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + EffectType::Sound { inner } => inner, + EffectType::Visual { inner } => inner, + } + } +} + +impl<'mc> EffectType<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/Effect/Type"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/Effect/Type;", vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::damage::DamageSourceBuilder::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "SOUND" => Ok(EffectType::Sound { + inner: EffectTypeStruct::from_raw(env, obj)?, + }), + "VISUAL" => Ok(EffectType::Visual { + inner: EffectTypeStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } +} - pub fn get( - &self, - registry: impl Into>, - key: impl Into>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Registry;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(registry.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/NamespacedKey;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) - }); - args.push(val_2); - sig += ")LB;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "get", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) +#[repr(C)] +pub struct EffectTypeStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for EffectType<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Sound { inner } => inner.0.clone(), + Self::Visual { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Sound { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Visual { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for EffectType<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate EffectType from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Effect/Type")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EffectType object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "SOUND" => Ok(EffectType::Sound { + inner: EffectTypeStruct::from_raw(env, obj)?, + }), + "VISUAL" => Ok(EffectType::Visual { + inner: EffectTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for EffectTypeStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for EffectTypeStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate EffectTypeStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Effect/Type")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EffectTypeStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> EffectTypeStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Effect/Type;"); + let cls = jni.find_class("org/bukkit/Effect/Type"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::EffectType::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -9334,25 +62263,82 @@ impl<'mc> UnsafeValues<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum TreeSpecies<'mc> {} -impl<'mc> std::fmt::Display for TreeSpecies<'mc> { +pub enum DyeColor<'mc> { + White { inner: DyeColorStruct<'mc> }, + Orange { inner: DyeColorStruct<'mc> }, + Magenta { inner: DyeColorStruct<'mc> }, + LightBlue { inner: DyeColorStruct<'mc> }, + Yellow { inner: DyeColorStruct<'mc> }, + Lime { inner: DyeColorStruct<'mc> }, + Pink { inner: DyeColorStruct<'mc> }, + Gray { inner: DyeColorStruct<'mc> }, + LightGray { inner: DyeColorStruct<'mc> }, + Cyan { inner: DyeColorStruct<'mc> }, + Purple { inner: DyeColorStruct<'mc> }, + Blue { inner: DyeColorStruct<'mc> }, + Brown { inner: DyeColorStruct<'mc> }, + Green { inner: DyeColorStruct<'mc> }, + Red { inner: DyeColorStruct<'mc> }, + Black { inner: DyeColorStruct<'mc> }, +} +impl<'mc> std::fmt::Display for DyeColor<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + DyeColor::White { .. } => f.write_str("WHITE"), + DyeColor::Orange { .. } => f.write_str("ORANGE"), + DyeColor::Magenta { .. } => f.write_str("MAGENTA"), + DyeColor::LightBlue { .. } => f.write_str("LIGHT_BLUE"), + DyeColor::Yellow { .. } => f.write_str("YELLOW"), + DyeColor::Lime { .. } => f.write_str("LIME"), + DyeColor::Pink { .. } => f.write_str("PINK"), + DyeColor::Gray { .. } => f.write_str("GRAY"), + DyeColor::LightGray { .. } => f.write_str("LIGHT_GRAY"), + DyeColor::Cyan { .. } => f.write_str("CYAN"), + DyeColor::Purple { .. } => f.write_str("PURPLE"), + DyeColor::Blue { .. } => f.write_str("BLUE"), + DyeColor::Brown { .. } => f.write_str("BROWN"), + DyeColor::Green { .. } => f.write_str("GREEN"), + DyeColor::Red { .. } => f.write_str("RED"), + DyeColor::Black { .. } => f.write_str("BLACK"), + } + } +} +impl<'mc> std::ops::Deref for DyeColor<'mc> { + type Target = DyeColorStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + DyeColor::White { inner } => inner, + DyeColor::Orange { inner } => inner, + DyeColor::Magenta { inner } => inner, + DyeColor::LightBlue { inner } => inner, + DyeColor::Yellow { inner } => inner, + DyeColor::Lime { inner } => inner, + DyeColor::Pink { inner } => inner, + DyeColor::Gray { inner } => inner, + DyeColor::LightGray { inner } => inner, + DyeColor::Cyan { inner } => inner, + DyeColor::Purple { inner } => inner, + DyeColor::Blue { inner } => inner, + DyeColor::Brown { inner } => inner, + DyeColor::Green { inner } => inner, + DyeColor::Red { inner } => inner, + DyeColor::Black { inner } => inner, + } } } -impl<'mc> TreeSpecies<'mc> { +impl<'mc> DyeColor<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/TreeSpecies"); + let cls = env.find_class("org/bukkit/DyeColor"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/TreeSpecies;", + "(Ljava/lang/String;)Lorg/bukkit/DyeColor;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -9364,37 +62350,124 @@ impl<'mc> TreeSpecies<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "WHITE" => Ok(DyeColor::White { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "ORANGE" => Ok(DyeColor::Orange { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "MAGENTA" => Ok(DyeColor::Magenta { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE" => Ok(DyeColor::LightBlue { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "YELLOW" => Ok(DyeColor::Yellow { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "LIME" => Ok(DyeColor::Lime { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "PINK" => Ok(DyeColor::Pink { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "GRAY" => Ok(DyeColor::Gray { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY" => Ok(DyeColor::LightGray { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "CYAN" => Ok(DyeColor::Cyan { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "PURPLE" => Ok(DyeColor::Purple { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "BLUE" => Ok(DyeColor::Blue { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "BROWN" => Ok(DyeColor::Brown { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "GREEN" => Ok(DyeColor::Green { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "RED" => Ok(DyeColor::Red { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "BLACK" => Ok(DyeColor::Black { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct TreeSpeciesStruct<'mc>( +pub struct DyeColorStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for TreeSpecies<'mc> { +impl<'mc> JNIRaw<'mc> for DyeColor<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::White { inner } => inner.0.clone(), + Self::Orange { inner } => inner.0.clone(), + Self::Magenta { inner } => inner.0.clone(), + Self::LightBlue { inner } => inner.0.clone(), + Self::Yellow { inner } => inner.0.clone(), + Self::Lime { inner } => inner.0.clone(), + Self::Pink { inner } => inner.0.clone(), + Self::Gray { inner } => inner.0.clone(), + Self::LightGray { inner } => inner.0.clone(), + Self::Cyan { inner } => inner.0.clone(), + Self::Purple { inner } => inner.0.clone(), + Self::Blue { inner } => inner.0.clone(), + Self::Brown { inner } => inner.0.clone(), + Self::Green { inner } => inner.0.clone(), + Self::Red { inner } => inner.0.clone(), + Self::Black { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::White { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Orange { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Magenta { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::LightBlue { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Yellow { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Lime { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Pink { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Gray { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::LightGray { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Cyan { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Purple { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Blue { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Brown { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Green { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Red { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Black { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for TreeSpecies<'mc> { +impl<'mc> JNIInstantiatable<'mc> for DyeColor<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate TreeSpecies from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate DyeColor from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/TreeSpecies")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/DyeColor")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a TreeSpecies object, got {}", + "Invalid argument passed. Expected a DyeColor object, got {}", name ) .into()) @@ -9406,13 +62479,61 @@ impl<'mc> JNIInstantiatable<'mc> for TreeSpecies<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "WHITE" => Ok(DyeColor::White { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "ORANGE" => Ok(DyeColor::Orange { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "MAGENTA" => Ok(DyeColor::Magenta { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "LIGHT_BLUE" => Ok(DyeColor::LightBlue { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "YELLOW" => Ok(DyeColor::Yellow { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "LIME" => Ok(DyeColor::Lime { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "PINK" => Ok(DyeColor::Pink { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "GRAY" => Ok(DyeColor::Gray { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "LIGHT_GRAY" => Ok(DyeColor::LightGray { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "CYAN" => Ok(DyeColor::Cyan { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "PURPLE" => Ok(DyeColor::Purple { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "BLUE" => Ok(DyeColor::Blue { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "BROWN" => Ok(DyeColor::Brown { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "GREEN" => Ok(DyeColor::Green { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "RED" => Ok(DyeColor::Red { + inner: DyeColorStruct::from_raw(env, obj)?, + }), + "BLACK" => Ok(DyeColor::Black { + inner: DyeColorStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for TreeSpeciesStruct<'mc> { +impl<'mc> JNIRaw<'mc> for DyeColorStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -9420,20 +62541,20 @@ impl<'mc> JNIRaw<'mc> for TreeSpeciesStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for TreeSpeciesStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for DyeColorStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate TreeSpeciesStruct from null object.").into(), + eyre::eyre!("Tried to instantiate DyeColorStruct from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/TreeSpecies")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/DyeColor")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a TreeSpeciesStruct object, got {}", + "Invalid argument passed. Expected a DyeColorStruct object, got {}", name ) .into()) @@ -9443,41 +62564,76 @@ impl<'mc> JNIInstantiatable<'mc> for TreeSpeciesStruct<'mc> { } } -impl<'mc> TreeSpeciesStruct<'mc> { +impl<'mc> DyeColorStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/TreeSpecies;"); - let cls = jni.find_class("org/bukkit/TreeSpecies"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/DyeColor;"); + let cls = jni.find_class("org/bukkit/DyeColor"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::TreeSpecies::from_raw(&jni, obj) + crate::DyeColor::from_raw(&jni, obj) } #[deprecated] - /// Gets the associated data value representing this species - pub fn data(&self) -> Result> { + /// Gets the associated wool data value representing this color. + pub fn wool_data(&self) -> Result> { + let sig = String::from("()B"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getWoolData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.b()?) + } + #[deprecated] + /// Gets the associated dye data value representing this color. + pub fn dye_data(&self) -> Result> { let sig = String::from("()B"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDyeData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.b()?) + } + /// Gets the color that this dye represents. + pub fn color(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Color;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) + crate::Color::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the firework color that this dye represents. + pub fn firework_color(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Color;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getFireworkColor", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Color::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } #[deprecated] - /// Gets the TreeSpecies with the given data value - pub fn get_by_data( + /// Gets the DyeColor with the given wool data value. + pub fn get_by_wool_data( jni: &blackboxmc_general::SharedJNIEnv<'mc>, data: i8, - ) -> Result>, Box> { - let sig = String::from("(B)Lorg/bukkit/TreeSpecies;"); + ) -> Result>, Box> { + let sig = String::from("(B)Lorg/bukkit/DyeColor;"); let val_1 = jni::objects::JValueGen::Byte(data); - let cls = jni.find_class("org/bukkit/TreeSpecies"); + let cls = jni.find_class("org/bukkit/DyeColor"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method( cls, - "getByData", + "getByWoolData", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -9486,7 +62642,100 @@ impl<'mc> TreeSpeciesStruct<'mc> { return Ok(None); } let obj = res.l()?; - Ok(Some(crate::TreeSpecies::from_raw(&jni, obj)?)) + Ok(Some(crate::DyeColor::from_raw(&jni, obj)?)) + } + #[deprecated] + /// Gets the DyeColor with the given dye data value. + pub fn get_by_dye_data( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + data: i8, + ) -> Result>, Box> { + let sig = String::from("(B)Lorg/bukkit/DyeColor;"); + let val_1 = jni::objects::JValueGen::Byte(data); + let cls = jni.find_class("org/bukkit/DyeColor"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getByDyeData", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::DyeColor::from_raw(&jni, obj)?)) + } + /// Gets the DyeColor with the given color value. + pub fn get_by_color( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + color: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Color;)Lorg/bukkit/DyeColor;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(color.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/DyeColor"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getByColor", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::DyeColor::from_raw(&jni, obj)?)) + } + /// Gets the DyeColor with the given firework color value. + pub fn get_by_firework_color( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + color: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/Color;)Lorg/bukkit/DyeColor;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(color.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/DyeColor"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getByFireworkColor", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::DyeColor::from_raw(&jni, obj)?)) + } + #[deprecated] + /// Gets the DyeColor for the given name, possibly doing legacy transformations. + pub fn legacy_value_of( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + name: impl Into, + ) -> Result, Box> { + let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/DyeColor;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(name.into())?, + )); + let cls = jni.find_class("org/bukkit/DyeColor"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "legacyValueOf", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::DyeColor::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -9494,25 +62743,46 @@ impl<'mc> TreeSpeciesStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum HeightMap<'mc> {} -impl<'mc> std::fmt::Display for HeightMap<'mc> { +pub enum Difficulty<'mc> { + Peaceful { inner: DifficultyStruct<'mc> }, + Easy { inner: DifficultyStruct<'mc> }, + Normal { inner: DifficultyStruct<'mc> }, + Hard { inner: DifficultyStruct<'mc> }, +} +impl<'mc> std::fmt::Display for Difficulty<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + Difficulty::Peaceful { .. } => f.write_str("PEACEFUL"), + Difficulty::Easy { .. } => f.write_str("EASY"), + Difficulty::Normal { .. } => f.write_str("NORMAL"), + Difficulty::Hard { .. } => f.write_str("HARD"), + } + } +} +impl<'mc> std::ops::Deref for Difficulty<'mc> { + type Target = DifficultyStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + Difficulty::Peaceful { inner } => inner, + Difficulty::Easy { inner } => inner, + Difficulty::Normal { inner } => inner, + Difficulty::Hard { inner } => inner, + } } } -impl<'mc> HeightMap<'mc> { +impl<'mc> Difficulty<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/HeightMap"); + let cls = env.find_class("org/bukkit/Difficulty"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/HeightMap;", + "(Ljava/lang/String;)Lorg/bukkit/Difficulty;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -9524,37 +62794,60 @@ impl<'mc> HeightMap<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "PEACEFUL" => Ok(Difficulty::Peaceful { + inner: DifficultyStruct::from_raw(env, obj)?, + }), + "EASY" => Ok(Difficulty::Easy { + inner: DifficultyStruct::from_raw(env, obj)?, + }), + "NORMAL" => Ok(Difficulty::Normal { + inner: DifficultyStruct::from_raw(env, obj)?, + }), + "HARD" => Ok(Difficulty::Hard { + inner: DifficultyStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct HeightMapStruct<'mc>( +pub struct DifficultyStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for HeightMap<'mc> { +impl<'mc> JNIRaw<'mc> for Difficulty<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Peaceful { inner } => inner.0.clone(), + Self::Easy { inner } => inner.0.clone(), + Self::Normal { inner } => inner.0.clone(), + Self::Hard { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Peaceful { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Easy { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Normal { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Hard { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for HeightMap<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Difficulty<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate HeightMap from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Difficulty from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/HeightMap")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/Difficulty")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a HeightMap object, got {}", + "Invalid argument passed. Expected a Difficulty object, got {}", name ) .into()) @@ -9566,13 +62859,25 @@ impl<'mc> JNIInstantiatable<'mc> for HeightMap<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "PEACEFUL" => Ok(Difficulty::Peaceful { + inner: DifficultyStruct::from_raw(env, obj)?, + }), + "EASY" => Ok(Difficulty::Easy { + inner: DifficultyStruct::from_raw(env, obj)?, + }), + "NORMAL" => Ok(Difficulty::Normal { + inner: DifficultyStruct::from_raw(env, obj)?, + }), + "HARD" => Ok(Difficulty::Hard { + inner: DifficultyStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for HeightMapStruct<'mc> { +impl<'mc> JNIRaw<'mc> for DifficultyStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -9580,20 +62885,20 @@ impl<'mc> JNIRaw<'mc> for HeightMapStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for HeightMapStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for DifficultyStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate HeightMapStruct from null object.").into(), + eyre::eyre!("Tried to instantiate DifficultyStruct from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/HeightMap")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/Difficulty")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a HeightMapStruct object, got {}", + "Invalid argument passed. Expected a DifficultyStruct object, got {}", name ) .into()) @@ -9603,17 +62908,50 @@ impl<'mc> JNIInstantiatable<'mc> for HeightMapStruct<'mc> { } } -impl<'mc> HeightMapStruct<'mc> { +impl<'mc> DifficultyStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/HeightMap;"); - let cls = jni.find_class("org/bukkit/HeightMap"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Difficulty;"); + let cls = jni.find_class("org/bukkit/Difficulty"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::HeightMap::from_raw(&jni, obj) + crate::Difficulty::from_raw(&jni, obj) + } + #[deprecated] + /// Gets the difficulty value associated with this Difficulty. + pub fn value(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getValue", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + #[deprecated] + /// Gets the Difficulty represented by the specified value + pub fn get_by_value( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + value: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/Difficulty;"); + let val_1 = jni::objects::JValueGen::Int(value); + let cls = jni.find_class("org/bukkit/Difficulty"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getByValue", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::Difficulty::from_raw(&jni, obj)?)) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -9621,25 +62959,58 @@ impl<'mc> HeightMapStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum PortalType<'mc> {} -impl<'mc> std::fmt::Display for PortalType<'mc> { +pub enum CropState<'mc> { + Seeded { inner: CropStateStruct<'mc> }, + Germinated { inner: CropStateStruct<'mc> }, + VerySmall { inner: CropStateStruct<'mc> }, + Small { inner: CropStateStruct<'mc> }, + Medium { inner: CropStateStruct<'mc> }, + Tall { inner: CropStateStruct<'mc> }, + VeryTall { inner: CropStateStruct<'mc> }, + Ripe { inner: CropStateStruct<'mc> }, +} +impl<'mc> std::fmt::Display for CropState<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + CropState::Seeded { .. } => f.write_str("SEEDED"), + CropState::Germinated { .. } => f.write_str("GERMINATED"), + CropState::VerySmall { .. } => f.write_str("VERY_SMALL"), + CropState::Small { .. } => f.write_str("SMALL"), + CropState::Medium { .. } => f.write_str("MEDIUM"), + CropState::Tall { .. } => f.write_str("TALL"), + CropState::VeryTall { .. } => f.write_str("VERY_TALL"), + CropState::Ripe { .. } => f.write_str("RIPE"), + } + } +} +impl<'mc> std::ops::Deref for CropState<'mc> { + type Target = CropStateStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + CropState::Seeded { inner } => inner, + CropState::Germinated { inner } => inner, + CropState::VerySmall { inner } => inner, + CropState::Small { inner } => inner, + CropState::Medium { inner } => inner, + CropState::Tall { inner } => inner, + CropState::VeryTall { inner } => inner, + CropState::Ripe { inner } => inner, + } } } -impl<'mc> PortalType<'mc> { +impl<'mc> CropState<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/PortalType"); + let cls = env.find_class("org/bukkit/CropState"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/PortalType;", + "(Ljava/lang/String;)Lorg/bukkit/CropState;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -9651,37 +63022,84 @@ impl<'mc> PortalType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "SEEDED" => Ok(CropState::Seeded { + inner: CropStateStruct::from_raw(env, obj)?, + }), + "GERMINATED" => Ok(CropState::Germinated { + inner: CropStateStruct::from_raw(env, obj)?, + }), + "VERY_SMALL" => Ok(CropState::VerySmall { + inner: CropStateStruct::from_raw(env, obj)?, + }), + "SMALL" => Ok(CropState::Small { + inner: CropStateStruct::from_raw(env, obj)?, + }), + "MEDIUM" => Ok(CropState::Medium { + inner: CropStateStruct::from_raw(env, obj)?, + }), + "TALL" => Ok(CropState::Tall { + inner: CropStateStruct::from_raw(env, obj)?, + }), + "VERY_TALL" => Ok(CropState::VeryTall { + inner: CropStateStruct::from_raw(env, obj)?, + }), + "RIPE" => Ok(CropState::Ripe { + inner: CropStateStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct PortalTypeStruct<'mc>( +pub struct CropStateStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PortalType<'mc> { +impl<'mc> JNIRaw<'mc> for CropState<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Seeded { inner } => inner.0.clone(), + Self::Germinated { inner } => inner.0.clone(), + Self::VerySmall { inner } => inner.0.clone(), + Self::Small { inner } => inner.0.clone(), + Self::Medium { inner } => inner.0.clone(), + Self::Tall { inner } => inner.0.clone(), + Self::VeryTall { inner } => inner.0.clone(), + Self::Ripe { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Seeded { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Germinated { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VerySmall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Small { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Medium { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Tall { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::VeryTall { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Ripe { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for PortalType<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CropState<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate PortalType from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate CropState from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/PortalType")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/CropState")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PortalType object, got {}", + "Invalid argument passed. Expected a CropState object, got {}", name ) .into()) @@ -9693,13 +63111,37 @@ impl<'mc> JNIInstantiatable<'mc> for PortalType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "SEEDED" => Ok(CropState::Seeded { + inner: CropStateStruct::from_raw(env, obj)?, + }), + "GERMINATED" => Ok(CropState::Germinated { + inner: CropStateStruct::from_raw(env, obj)?, + }), + "VERY_SMALL" => Ok(CropState::VerySmall { + inner: CropStateStruct::from_raw(env, obj)?, + }), + "SMALL" => Ok(CropState::Small { + inner: CropStateStruct::from_raw(env, obj)?, + }), + "MEDIUM" => Ok(CropState::Medium { + inner: CropStateStruct::from_raw(env, obj)?, + }), + "TALL" => Ok(CropState::Tall { + inner: CropStateStruct::from_raw(env, obj)?, + }), + "VERY_TALL" => Ok(CropState::VeryTall { + inner: CropStateStruct::from_raw(env, obj)?, + }), + "RIPE" => Ok(CropState::Ripe { + inner: CropStateStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for PortalTypeStruct<'mc> { +impl<'mc> JNIRaw<'mc> for CropStateStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -9707,20 +63149,20 @@ impl<'mc> JNIRaw<'mc> for PortalTypeStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PortalTypeStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CropStateStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate PortalTypeStruct from null object.").into(), + eyre::eyre!("Tried to instantiate CropStateStruct from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/PortalType")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/CropState")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PortalTypeStruct object, got {}", + "Invalid argument passed. Expected a CropStateStruct object, got {}", name ) .into()) @@ -9730,17 +63172,50 @@ impl<'mc> JNIInstantiatable<'mc> for PortalTypeStruct<'mc> { } } -impl<'mc> PortalTypeStruct<'mc> { +impl<'mc> CropStateStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/PortalType;"); - let cls = jni.find_class("org/bukkit/PortalType"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/CropState;"); + let cls = jni.find_class("org/bukkit/CropState"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::PortalType::from_raw(&jni, obj) + crate::CropState::from_raw(&jni, obj) + } + #[deprecated] + /// Gets the associated data value representing this growth state + pub fn data(&self) -> Result> { + let sig = String::from("()B"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.b()?) + } + #[deprecated] + /// Gets the CropState with the given data value + pub fn get_by_data( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + data: i8, + ) -> Result>, Box> { + let sig = String::from("(B)Lorg/bukkit/CropState;"); + let val_1 = jni::objects::JValueGen::Byte(data); + let cls = jni.find_class("org/bukkit/CropState"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getByData", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::CropState::from_raw(&jni, obj)?)) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -9749,12 +63224,12 @@ impl<'mc> PortalTypeStruct<'mc> { } } #[repr(C)] -pub struct BanList<'mc>( +pub struct Color<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BanList<'mc> { +impl<'mc> JNIRaw<'mc> for Color<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -9762,18 +63237,18 @@ impl<'mc> JNIRaw<'mc> for BanList<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BanList<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Color<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate BanList from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Color from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/BanList")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/Color")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BanList object, got {}", + "Invalid argument passed. Expected a Color object, got {}", name ) .into()) @@ -9783,128 +63258,342 @@ impl<'mc> JNIInstantiatable<'mc> for BanList<'mc> { } } -impl<'mc> BanList<'mc> { - /// Gets a {@link BanEntry} by target. - pub fn get_ban_entry( - &self, - target: jni::objects::JObject<'mc>, - ) -> Result>, Box> { +impl<'mc> Color<'mc> { + /// Creates a new Color object from an alpha, red, green, and blue + pub fn from_argb( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + alpha: i32, + red: std::option::Option, + green: std::option::Option, + blue: std::option::Option, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "LT;"; - let val_1 = jni::objects::JValueGen::Object(target); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(alpha); args.push(val_1); - sig += ")Lorg/bukkit/BanEntry;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBanEntry", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + if let Some(a) = red { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); } - Ok(Some(crate::BanEntry::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + if let Some(a) = green { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + if let Some(a) = blue { + sig += "I"; + let val_4 = jni::objects::JValueGen::Int(a); + args.push(val_4); + } + sig += ")Lorg/bukkit/Color;"; + let cls = jni.find_class("org/bukkit/Color"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "fromARGB", sig.as_str(), args); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::Color::from_raw(&jni, obj) } - /// Adds a ban to this list. If a previous ban exists, this will - /// update the previous entry. - pub fn add_ban( - &self, - target: jni::objects::JObject<'mc>, - reason: impl Into, - duration: jni::objects::JObject<'mc>, - source: impl Into, - ) -> Result>, Box> { + /// Creates a new Color object from a red, green, and blue + pub fn from_rgb( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + red: i32, + green: std::option::Option, + blue: std::option::Option, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "LT;"; - let val_1 = jni::objects::JValueGen::Object(target); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(red); args.push(val_1); - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(reason.into())?, - )); - args.push(val_2); - sig += "Ljava/time/Duration;"; - let val_3 = jni::objects::JValueGen::Object(duration); - args.push(val_3); - sig += "Ljava/lang/String;"; - let val_4 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(source.into())?, - )); - args.push(val_4); - sig += ")Lorg/bukkit/BanEntry;"; + if let Some(a) = green { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + if let Some(a) = blue { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + sig += ")Lorg/bukkit/Color;"; + let cls = jni.find_class("org/bukkit/Color"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "fromRGB", sig.as_str(), args); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::Color::from_raw(&jni, obj) + } + /// Creates a new Color object from a blue, green, and red + pub fn from_bgr( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + blue: i32, + green: std::option::Option, + red: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(blue); + args.push(val_1); + if let Some(a) = green { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + if let Some(a) = red { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + sig += ")Lorg/bukkit/Color;"; + let cls = jni.find_class("org/bukkit/Color"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "fromBGR", sig.as_str(), args); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::Color::from_raw(&jni, obj) + } + /// Gets the alpha component + pub fn alpha(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "addBan", sig.as_str(), args); + .call_method(&self.jni_object(), "getAlpha", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::BanEntry::from_raw(&self.jni_ref(), unsafe { + Ok(res.i()?) + } + /// Creates a new Color object with specified component + pub fn set_alpha(&self, alpha: i32) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/Color;"); + let val_1 = jni::objects::JValueGen::Int(alpha); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAlpha", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Color::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + }) } - #[deprecated] - /// Gets a set containing every {@link BanEntry} in this list. - pub fn ban_entries( + /// Gets the red component + pub fn red(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getRed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Creates a new Color object with specified component + pub fn set_red(&self, red: i32) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/Color;"); + let val_1 = jni::objects::JValueGen::Int(red); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRed", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Color::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the green component + pub fn green(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getGreen", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Creates a new Color object with specified component + pub fn set_green(&self, green: i32) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/Color;"); + let val_1 = jni::objects::JValueGen::Int(green); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setGreen", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Color::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the blue component + pub fn blue(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBlue", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Creates a new Color object with specified component + pub fn set_blue(&self, blue: i32) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/Color;"); + let val_1 = jni::objects::JValueGen::Int(blue); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBlue", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Color::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the color as an RGB integer. + pub fn as_rgb(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "asRGB", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the color as an ARGB integer. + pub fn as_argb(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "asARGB", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the color as an BGR integer. + pub fn as_bgr(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "asBGR", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Creates a new color with its RGB components changed as if it was dyed + /// with the colors passed in, replicating vanilla workbench dyeing + pub fn mix_dyes( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBanEntries", sig.as_str(), vec![]); + colors: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/DyeColor;)Lorg/bukkit/Color;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(colors.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "mixDyes", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + crate::Color::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets a set containing every {@link BanEntry} in this list. - pub fn entries( + /// Creates a new color with its RGB components changed as if it was dyed + /// with the colors passed in, replicating vanilla workbench dyeing. + /// Note that this method does not currently take into account alpha + /// components. + pub fn mix_colors( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEntries", sig.as_str(), vec![]); + colors: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/Color;)Lorg/bukkit/Color;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(colors.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "mixColors", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + crate::Color::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - #[deprecated] - /// Gets if a {@link BanEntry} exists for the target, indicating an active ban status. - pub fn is_banned(&self, target: impl Into) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(target.into())?, - )); - args.push(val_1); - sig += ")Z"; + + pub fn equals( + &self, + o: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(Ljava/lang/Object;)Z"); + let val_1 = jni::objects::JValueGen::Object(o); + let res = self.jni_ref().call_method( + &self.jni_object(), + "equals", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn hash_code(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isBanned", sig.as_str(), args); + .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - #[deprecated] - /// Removes the specified target from this list, therefore indicating a "not banned" status. - pub fn pardon(&self, target: impl Into) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(target.into())?, - )); - args.push(val_1); - sig += ")V"; + + pub fn serialize( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Map;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn deserialize( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + map: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Ljava/util/Map;)Lorg/bukkit/Color;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(map.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/Color"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "deserialize", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::Color::from_raw(&jni, obj) + } + + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "pardon", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -9912,25 +63601,55 @@ impl<'mc> BanList<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum BanListType<'mc> {} -impl<'mc> std::fmt::Display for BanListType<'mc> { + +impl<'mc> std::string::ToString for Color<'mc> { + fn to_string(&self) -> String { + match &self.internal_to_string() { + Ok(a) => a.clone(), + Err(err) => format!("Error calling Color.toString: {}", err), + } + } +} + +impl<'mc> Into> for Color<'mc> { + fn into(self) -> crate::configuration::serialization::ConfigurationSerializable<'mc> { + crate::configuration::serialization::ConfigurationSerializable::from_raw(&self.jni_ref(), self.1).expect("Error converting Color into crate::configuration::serialization::ConfigurationSerializable") + } +} +pub enum CoalType<'mc> { + Coal { inner: CoalTypeStruct<'mc> }, + Charcoal { inner: CoalTypeStruct<'mc> }, +} +impl<'mc> std::fmt::Display for CoalType<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + CoalType::Coal { .. } => f.write_str("COAL"), + CoalType::Charcoal { .. } => f.write_str("CHARCOAL"), + } + } +} +impl<'mc> std::ops::Deref for CoalType<'mc> { + type Target = CoalTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + CoalType::Coal { inner } => inner, + CoalType::Charcoal { inner } => inner, + } } } -impl<'mc> BanListType<'mc> { +impl<'mc> CoalType<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/BanList/Type"); + let cls = env.find_class("org/bukkit/CoalType"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/BanList/Type;", + "(Ljava/lang/String;)Lorg/bukkit/CoalType;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -9942,37 +63661,50 @@ impl<'mc> BanListType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "COAL" => Ok(CoalType::Coal { + inner: CoalTypeStruct::from_raw(env, obj)?, + }), + "CHARCOAL" => Ok(CoalType::Charcoal { + inner: CoalTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct BanListTypeStruct<'mc>( +pub struct CoalTypeStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BanListType<'mc> { +impl<'mc> JNIRaw<'mc> for CoalType<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Coal { inner } => inner.0.clone(), + Self::Charcoal { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Coal { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Charcoal { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for BanListType<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CoalType<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate BanListType from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate CoalType from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/BanList/Type")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/CoalType")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BanListType object, got {}", + "Invalid argument passed. Expected a CoalType object, got {}", name ) .into()) @@ -9984,13 +63716,19 @@ impl<'mc> JNIInstantiatable<'mc> for BanListType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "COAL" => Ok(CoalType::Coal { + inner: CoalTypeStruct::from_raw(env, obj)?, + }), + "CHARCOAL" => Ok(CoalType::Charcoal { + inner: CoalTypeStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for BanListTypeStruct<'mc> { +impl<'mc> JNIRaw<'mc> for CoalTypeStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -9998,20 +63736,20 @@ impl<'mc> JNIRaw<'mc> for BanListTypeStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BanListTypeStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CoalTypeStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate BanListTypeStruct from null object.").into(), + eyre::eyre!("Tried to instantiate CoalTypeStruct from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/BanList/Type")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/CoalType")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BanListTypeStruct object, got {}", + "Invalid argument passed. Expected a CoalTypeStruct object, got {}", name ) .into()) @@ -10021,17 +63759,50 @@ impl<'mc> JNIInstantiatable<'mc> for BanListTypeStruct<'mc> { } } -impl<'mc> BanListTypeStruct<'mc> { +impl<'mc> CoalTypeStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/BanList/Type;"); - let cls = jni.find_class("org/bukkit/BanList/Type"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/CoalType;"); + let cls = jni.find_class("org/bukkit/CoalType"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::BanListType::from_raw(&jni, obj) + crate::CoalType::from_raw(&jni, obj) + } + #[deprecated] + /// Gets the associated data value representing this type of coal + pub fn data(&self) -> Result> { + let sig = String::from("()B"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.b()?) + } + #[deprecated] + /// Gets the type of coal with the given data value + pub fn get_by_data( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + data: i8, + ) -> Result>, Box> { + let sig = String::from("(B)Lorg/bukkit/CoalType;"); + let val_1 = jni::objects::JValueGen::Byte(data); + let cls = jni.find_class("org/bukkit/CoalType"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getByData", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::CoalType::from_raw(&jni, obj)?)) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -10039,43 +63810,100 @@ impl<'mc> BanListTypeStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum MusicInstrument<'mc> { - PonderGoatHorn { inner: MusicInstrumentStruct<'mc> }, - SingGoatHorn { inner: MusicInstrumentStruct<'mc> }, - SeekGoatHorn { inner: MusicInstrumentStruct<'mc> }, - FeelGoatHorn { inner: MusicInstrumentStruct<'mc> }, - AdmireGoatHorn { inner: MusicInstrumentStruct<'mc> }, - CallGoatHorn { inner: MusicInstrumentStruct<'mc> }, - YearnGoatHorn { inner: MusicInstrumentStruct<'mc> }, - DreamGoatHorn { inner: MusicInstrumentStruct<'mc> }, +pub enum ChatColor<'mc> { + Black { inner: ChatColorStruct<'mc> }, + DarkBlue { inner: ChatColorStruct<'mc> }, + DarkGreen { inner: ChatColorStruct<'mc> }, + DarkAqua { inner: ChatColorStruct<'mc> }, + DarkRed { inner: ChatColorStruct<'mc> }, + DarkPurple { inner: ChatColorStruct<'mc> }, + Gold { inner: ChatColorStruct<'mc> }, + Gray { inner: ChatColorStruct<'mc> }, + DarkGray { inner: ChatColorStruct<'mc> }, + Blue { inner: ChatColorStruct<'mc> }, + Green { inner: ChatColorStruct<'mc> }, + Aqua { inner: ChatColorStruct<'mc> }, + Red { inner: ChatColorStruct<'mc> }, + LightPurple { inner: ChatColorStruct<'mc> }, + Yellow { inner: ChatColorStruct<'mc> }, + White { inner: ChatColorStruct<'mc> }, + Magic { inner: ChatColorStruct<'mc> }, + Bold { inner: ChatColorStruct<'mc> }, + Strikethrough { inner: ChatColorStruct<'mc> }, + Underline { inner: ChatColorStruct<'mc> }, + Italic { inner: ChatColorStruct<'mc> }, + Reset { inner: ChatColorStruct<'mc> }, } -impl<'mc> std::fmt::Display for MusicInstrument<'mc> { +impl<'mc> std::fmt::Display for ChatColor<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - MusicInstrument::PonderGoatHorn { .. } => f.write_str("PONDER_GOAT_HORN"), - MusicInstrument::SingGoatHorn { .. } => f.write_str("SING_GOAT_HORN"), - MusicInstrument::SeekGoatHorn { .. } => f.write_str("SEEK_GOAT_HORN"), - MusicInstrument::FeelGoatHorn { .. } => f.write_str("FEEL_GOAT_HORN"), - MusicInstrument::AdmireGoatHorn { .. } => f.write_str("ADMIRE_GOAT_HORN"), - MusicInstrument::CallGoatHorn { .. } => f.write_str("CALL_GOAT_HORN"), - MusicInstrument::YearnGoatHorn { .. } => f.write_str("YEARN_GOAT_HORN"), - MusicInstrument::DreamGoatHorn { .. } => f.write_str("DREAM_GOAT_HORN"), + ChatColor::Black { .. } => f.write_str("BLACK"), + ChatColor::DarkBlue { .. } => f.write_str("DARK_BLUE"), + ChatColor::DarkGreen { .. } => f.write_str("DARK_GREEN"), + ChatColor::DarkAqua { .. } => f.write_str("DARK_AQUA"), + ChatColor::DarkRed { .. } => f.write_str("DARK_RED"), + ChatColor::DarkPurple { .. } => f.write_str("DARK_PURPLE"), + ChatColor::Gold { .. } => f.write_str("GOLD"), + ChatColor::Gray { .. } => f.write_str("GRAY"), + ChatColor::DarkGray { .. } => f.write_str("DARK_GRAY"), + ChatColor::Blue { .. } => f.write_str("BLUE"), + ChatColor::Green { .. } => f.write_str("GREEN"), + ChatColor::Aqua { .. } => f.write_str("AQUA"), + ChatColor::Red { .. } => f.write_str("RED"), + ChatColor::LightPurple { .. } => f.write_str("LIGHT_PURPLE"), + ChatColor::Yellow { .. } => f.write_str("YELLOW"), + ChatColor::White { .. } => f.write_str("WHITE"), + ChatColor::Magic { .. } => f.write_str("MAGIC"), + ChatColor::Bold { .. } => f.write_str("BOLD"), + ChatColor::Strikethrough { .. } => f.write_str("STRIKETHROUGH"), + ChatColor::Underline { .. } => f.write_str("UNDERLINE"), + ChatColor::Italic { .. } => f.write_str("ITALIC"), + ChatColor::Reset { .. } => f.write_str("RESET"), + } + } +} +impl<'mc> std::ops::Deref for ChatColor<'mc> { + type Target = ChatColorStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + ChatColor::Black { inner } => inner, + ChatColor::DarkBlue { inner } => inner, + ChatColor::DarkGreen { inner } => inner, + ChatColor::DarkAqua { inner } => inner, + ChatColor::DarkRed { inner } => inner, + ChatColor::DarkPurple { inner } => inner, + ChatColor::Gold { inner } => inner, + ChatColor::Gray { inner } => inner, + ChatColor::DarkGray { inner } => inner, + ChatColor::Blue { inner } => inner, + ChatColor::Green { inner } => inner, + ChatColor::Aqua { inner } => inner, + ChatColor::Red { inner } => inner, + ChatColor::LightPurple { inner } => inner, + ChatColor::Yellow { inner } => inner, + ChatColor::White { inner } => inner, + ChatColor::Magic { inner } => inner, + ChatColor::Bold { inner } => inner, + ChatColor::Strikethrough { inner } => inner, + ChatColor::Underline { inner } => inner, + ChatColor::Italic { inner } => inner, + ChatColor::Reset { inner } => inner, } } } -impl<'mc> MusicInstrument<'mc> { +impl<'mc> ChatColor<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/MusicInstrument"); + let cls = env.find_class("org/bukkit/ChatColor"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/MusicInstrument;", + "(Ljava/lang/String;)Lorg/bukkit/ChatColor;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -10087,29 +63915,71 @@ impl<'mc> MusicInstrument<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { - "PONDER_GOAT_HORN" => Ok(MusicInstrument::PonderGoatHorn { - inner: MusicInstrumentStruct::from_raw(env, obj)?, + "BLACK" => Ok(ChatColor::Black { + inner: ChatColorStruct::from_raw(env, obj)?, }), - "SING_GOAT_HORN" => Ok(MusicInstrument::SingGoatHorn { - inner: MusicInstrumentStruct::from_raw(env, obj)?, + "DARK_BLUE" => Ok(ChatColor::DarkBlue { + inner: ChatColorStruct::from_raw(env, obj)?, }), - "SEEK_GOAT_HORN" => Ok(MusicInstrument::SeekGoatHorn { - inner: MusicInstrumentStruct::from_raw(env, obj)?, + "DARK_GREEN" => Ok(ChatColor::DarkGreen { + inner: ChatColorStruct::from_raw(env, obj)?, }), - "FEEL_GOAT_HORN" => Ok(MusicInstrument::FeelGoatHorn { - inner: MusicInstrumentStruct::from_raw(env, obj)?, + "DARK_AQUA" => Ok(ChatColor::DarkAqua { + inner: ChatColorStruct::from_raw(env, obj)?, }), - "ADMIRE_GOAT_HORN" => Ok(MusicInstrument::AdmireGoatHorn { - inner: MusicInstrumentStruct::from_raw(env, obj)?, + "DARK_RED" => Ok(ChatColor::DarkRed { + inner: ChatColorStruct::from_raw(env, obj)?, }), - "CALL_GOAT_HORN" => Ok(MusicInstrument::CallGoatHorn { - inner: MusicInstrumentStruct::from_raw(env, obj)?, + "DARK_PURPLE" => Ok(ChatColor::DarkPurple { + inner: ChatColorStruct::from_raw(env, obj)?, }), - "YEARN_GOAT_HORN" => Ok(MusicInstrument::YearnGoatHorn { - inner: MusicInstrumentStruct::from_raw(env, obj)?, + "GOLD" => Ok(ChatColor::Gold { + inner: ChatColorStruct::from_raw(env, obj)?, }), - "DREAM_GOAT_HORN" => Ok(MusicInstrument::DreamGoatHorn { - inner: MusicInstrumentStruct::from_raw(env, obj)?, + "GRAY" => Ok(ChatColor::Gray { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "DARK_GRAY" => Ok(ChatColor::DarkGray { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "BLUE" => Ok(ChatColor::Blue { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "GREEN" => Ok(ChatColor::Green { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "AQUA" => Ok(ChatColor::Aqua { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "RED" => Ok(ChatColor::Red { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "LIGHT_PURPLE" => Ok(ChatColor::LightPurple { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "YELLOW" => Ok(ChatColor::Yellow { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "WHITE" => Ok(ChatColor::White { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "MAGIC" => Ok(ChatColor::Magic { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "BOLD" => Ok(ChatColor::Bold { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "STRIKETHROUGH" => Ok(ChatColor::Strikethrough { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "UNDERLINE" => Ok(ChatColor::Underline { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "ITALIC" => Ok(ChatColor::Italic { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "RESET" => Ok(ChatColor::Reset { + inner: ChatColorStruct::from_raw(env, obj)?, }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), @@ -10118,67 +63988,87 @@ impl<'mc> MusicInstrument<'mc> { } #[repr(C)] -pub struct MusicInstrumentStruct<'mc>( +pub struct ChatColorStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for MusicInstrument<'mc> { +impl<'mc> JNIRaw<'mc> for ChatColor<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { match self { - Self::PonderGoatHorn { inner } => inner.0.clone(), - Self::SingGoatHorn { inner } => inner.0.clone(), - Self::SeekGoatHorn { inner } => inner.0.clone(), - Self::FeelGoatHorn { inner } => inner.0.clone(), - Self::AdmireGoatHorn { inner } => inner.0.clone(), - Self::CallGoatHorn { inner } => inner.0.clone(), - Self::YearnGoatHorn { inner } => inner.0.clone(), - Self::DreamGoatHorn { inner } => inner.0.clone(), + Self::Black { inner } => inner.0.clone(), + Self::DarkBlue { inner } => inner.0.clone(), + Self::DarkGreen { inner } => inner.0.clone(), + Self::DarkAqua { inner } => inner.0.clone(), + Self::DarkRed { inner } => inner.0.clone(), + Self::DarkPurple { inner } => inner.0.clone(), + Self::Gold { inner } => inner.0.clone(), + Self::Gray { inner } => inner.0.clone(), + Self::DarkGray { inner } => inner.0.clone(), + Self::Blue { inner } => inner.0.clone(), + Self::Green { inner } => inner.0.clone(), + Self::Aqua { inner } => inner.0.clone(), + Self::Red { inner } => inner.0.clone(), + Self::LightPurple { inner } => inner.0.clone(), + Self::Yellow { inner } => inner.0.clone(), + Self::White { inner } => inner.0.clone(), + Self::Magic { inner } => inner.0.clone(), + Self::Bold { inner } => inner.0.clone(), + Self::Strikethrough { inner } => inner.0.clone(), + Self::Underline { inner } => inner.0.clone(), + Self::Italic { inner } => inner.0.clone(), + Self::Reset { inner } => inner.0.clone(), } } fn jni_object(&self) -> jni::objects::JObject<'mc> { match self { - Self::PonderGoatHorn { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::SingGoatHorn { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::SeekGoatHorn { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::FeelGoatHorn { inner } => unsafe { + Self::Black { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DarkBlue { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DarkGreen { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::AdmireGoatHorn { inner } => unsafe { + Self::DarkAqua { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DarkRed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DarkPurple { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::CallGoatHorn { inner } => unsafe { + Self::Gold { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Gray { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DarkGray { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Blue { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Green { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Aqua { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Red { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::LightPurple { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::YearnGoatHorn { inner } => unsafe { + Self::Yellow { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::White { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Magic { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Bold { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Strikethrough { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::DreamGoatHorn { inner } => unsafe { + Self::Underline { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Italic { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Reset { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, } } } -impl<'mc> JNIInstantiatable<'mc> for MusicInstrument<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ChatColor<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate MusicInstrument from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate ChatColor from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/MusicInstrument")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/ChatColor")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a MusicInstrument object, got {}", + "Invalid argument passed. Expected a ChatColor object, got {}", name ) .into()) @@ -10190,29 +64080,71 @@ impl<'mc> JNIInstantiatable<'mc> for MusicInstrument<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { - "PONDER_GOAT_HORN" => Ok(MusicInstrument::PonderGoatHorn { - inner: MusicInstrumentStruct::from_raw(env, obj)?, + "BLACK" => Ok(ChatColor::Black { + inner: ChatColorStruct::from_raw(env, obj)?, }), - "SING_GOAT_HORN" => Ok(MusicInstrument::SingGoatHorn { - inner: MusicInstrumentStruct::from_raw(env, obj)?, + "DARK_BLUE" => Ok(ChatColor::DarkBlue { + inner: ChatColorStruct::from_raw(env, obj)?, }), - "SEEK_GOAT_HORN" => Ok(MusicInstrument::SeekGoatHorn { - inner: MusicInstrumentStruct::from_raw(env, obj)?, + "DARK_GREEN" => Ok(ChatColor::DarkGreen { + inner: ChatColorStruct::from_raw(env, obj)?, }), - "FEEL_GOAT_HORN" => Ok(MusicInstrument::FeelGoatHorn { - inner: MusicInstrumentStruct::from_raw(env, obj)?, + "DARK_AQUA" => Ok(ChatColor::DarkAqua { + inner: ChatColorStruct::from_raw(env, obj)?, }), - "ADMIRE_GOAT_HORN" => Ok(MusicInstrument::AdmireGoatHorn { - inner: MusicInstrumentStruct::from_raw(env, obj)?, + "DARK_RED" => Ok(ChatColor::DarkRed { + inner: ChatColorStruct::from_raw(env, obj)?, }), - "CALL_GOAT_HORN" => Ok(MusicInstrument::CallGoatHorn { - inner: MusicInstrumentStruct::from_raw(env, obj)?, + "DARK_PURPLE" => Ok(ChatColor::DarkPurple { + inner: ChatColorStruct::from_raw(env, obj)?, }), - "YEARN_GOAT_HORN" => Ok(MusicInstrument::YearnGoatHorn { - inner: MusicInstrumentStruct::from_raw(env, obj)?, + "GOLD" => Ok(ChatColor::Gold { + inner: ChatColorStruct::from_raw(env, obj)?, }), - "DREAM_GOAT_HORN" => Ok(MusicInstrument::DreamGoatHorn { - inner: MusicInstrumentStruct::from_raw(env, obj)?, + "GRAY" => Ok(ChatColor::Gray { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "DARK_GRAY" => Ok(ChatColor::DarkGray { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "BLUE" => Ok(ChatColor::Blue { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "GREEN" => Ok(ChatColor::Green { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "AQUA" => Ok(ChatColor::Aqua { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "RED" => Ok(ChatColor::Red { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "LIGHT_PURPLE" => Ok(ChatColor::LightPurple { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "YELLOW" => Ok(ChatColor::Yellow { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "WHITE" => Ok(ChatColor::White { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "MAGIC" => Ok(ChatColor::Magic { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "BOLD" => Ok(ChatColor::Bold { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "STRIKETHROUGH" => Ok(ChatColor::Strikethrough { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "UNDERLINE" => Ok(ChatColor::Underline { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "ITALIC" => Ok(ChatColor::Italic { + inner: ChatColorStruct::from_raw(env, obj)?, + }), + "RESET" => Ok(ChatColor::Reset { + inner: ChatColorStruct::from_raw(env, obj)?, }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } @@ -10220,7 +64152,7 @@ impl<'mc> JNIInstantiatable<'mc> for MusicInstrument<'mc> { } } -impl<'mc> JNIRaw<'mc> for MusicInstrumentStruct<'mc> { +impl<'mc> JNIRaw<'mc> for ChatColorStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -10228,21 +64160,20 @@ impl<'mc> JNIRaw<'mc> for MusicInstrumentStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for MusicInstrumentStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ChatColorStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate MusicInstrumentStruct from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate ChatColorStruct from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/MusicInstrument")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/ChatColor")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a MusicInstrumentStruct object, got {}", + "Invalid argument passed. Expected a ChatColorStruct object, got {}", name ) .into()) @@ -10252,273 +64183,162 @@ impl<'mc> JNIInstantiatable<'mc> for MusicInstrumentStruct<'mc> { } } -impl<'mc> MusicInstrumentStruct<'mc> { - #[deprecated] - /// Returns a {@link MusicInstrument} by a {@link NamespacedKey}. - pub fn get_by_key( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - namespaced_key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/MusicInstrument;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(namespaced_key.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/MusicInstrument"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getByKey", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::MusicInstrument::from_raw(&jni, obj)?)) - } - #[deprecated] - /// Returns all known MusicInstruments. +impl<'mc> ChatColorStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); - let cls = jni.find_class("org/bukkit/MusicInstrument"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/ChatColor;"); + let cls = jni.find_class("org/bukkit/ChatColor"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&jni, res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::MusicInstrument::from_raw(&jni, obj)?); - } - Ok(new_vec) - } - /// Return the namespaced identifier for this object. - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct Warning<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Warning<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Warning<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Warning from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Warning")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Warning object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Warning<'mc> { - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -pub enum WarningWarningState<'mc> {} -impl<'mc> std::fmt::Display for WarningWarningState<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> WarningWarningState<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/Warning/WarningState"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/Warning/WarningState;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct WarningWarningStateStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for WarningWarningState<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for WarningWarningState<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate WarningWarningState from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Warning/WarningState")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a WarningWarningState object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for WarningWarningStateStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + crate::ChatColor::from_raw(&jni, obj) } -} -impl<'mc> JNIInstantiatable<'mc> for WarningWarningStateStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate WarningWarningStateStruct from null object." - ) - .into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Warning/WarningState")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a WarningWarningStateStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Gets the char value associated with this color + pub fn char(&self) -> Result> { + let sig = String::from("()C"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getChar", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.c()?) } -} -impl<'mc> WarningWarningStateStruct<'mc> { - pub fn values( + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Checks if this code is a format code as opposed to a color code. + pub fn is_format(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFormat", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks if this code is a color code as opposed to a format code. + pub fn is_color(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isColor", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the color represented by the specified color code + pub fn get_by_char( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Warning/WarningState;"); - let cls = jni.find_class("org/bukkit/Warning/WarningState"); + code: impl Into, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(code.into())?, + )); + args.push(val_1); + sig += ")Lorg/bukkit/ChatColor;"; + let cls = jni.find_class("org/bukkit/ChatColor"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.call_static_method(cls, "getByChar", sig.as_str(), args); let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } let obj = res.l()?; - crate::WarningWarningState::from_raw(&jni, obj) + Ok(Some(crate::ChatColor::from_raw(&jni, obj)?)) } - /// This method checks the provided warning should be printed for this - /// state - pub fn print_for( - &self, - warning: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/Warning;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(warning.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "printFor", + /// Strips the given message of all color codes + pub fn strip_color( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + input: impl Into, + ) -> Result, Box> { + let sig = String::from("(Ljava/lang/String;)Ljava/lang/String;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(input.into())?, + )); + let cls = jni.find_class("org/bukkit/ChatColor"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "stripColor", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + jni.get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// This method returns the corresponding warning state for the given - /// string value. - pub fn value( + /// Translates a string using an alternate color code character into a + /// string that uses the internal ChatColor.COLOR_CODE color code + /// character. The alternate color code character will only be replaced if + /// it is immediately followed by 0-9, A-F, a-f, K-O, k-o, R or r. + pub fn translate_alternate_color_codes( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - value: impl Into, - ) -> Result, Box> { - let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/Warning/WarningState;"); + alt_color_char: u16, + text_to_translate: impl Into, + ) -> Result> { + let sig = String::from("(CLjava/lang/String;)Ljava/lang/String;"); + let val_1 = jni::objects::JValueGen::Char(alt_color_char); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(text_to_translate.into())?, + )); + let cls = jni.find_class("org/bukkit/ChatColor"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "translateAlternateColorCodes", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = jni.translate_error(res)?; + Ok(jni + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gets the ChatColors used at the end of the given input string. + pub fn get_last_colors( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + input: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)Ljava/lang/String;"); let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(value.into())?, + jni.new_string(input.into())?, )); - let cls = jni.find_class("org/bukkit/Warning/WarningState"); + let cls = jni.find_class("org/bukkit/ChatColor"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method( cls, - "value", + "getLastColors", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::WarningWarningState::from_raw(&jni, obj) + Ok(jni + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -10527,12 +64347,12 @@ impl<'mc> WarningWarningStateStruct<'mc> { } } #[repr(C)] -pub struct Chunk<'mc>( +pub struct Bukkit<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Chunk<'mc> { +impl<'mc> JNIRaw<'mc> for Bukkit<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -10540,18 +64360,18 @@ impl<'mc> JNIRaw<'mc> for Chunk<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Chunk<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Bukkit<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Chunk from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Bukkit from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Chunk")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/Bukkit")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Chunk object, got {}", + "Invalid argument passed. Expected a Bukkit object, got {}", name ) .into()) @@ -10561,3376 +64381,4184 @@ impl<'mc> JNIInstantiatable<'mc> for Chunk<'mc> { } } -impl<'mc> Chunk<'mc> { - /// Gets the X-coordinate of this chunk - pub fn x(&self) -> Result> { +impl<'mc> Bukkit<'mc> { + /// Gets the current {@link Server} singleton + pub fn server( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Server;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getServer", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::Server::from_raw(&jni, obj) + } + /// Attempts to set the {@link Server} singleton. + /// + /// This cannot be done if the Server is already set. + pub fn set_server( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + server: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/Server;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(server.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "setServer", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + jni.translate_error(res)?; + Ok(()) + } + /// Gets the name of this server implementation. + pub fn name( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getName", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(jni + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gets the version string of this server implementation. + pub fn version( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getVersion", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(jni + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gets the Bukkit version that this server is running. + pub fn bukkit_version( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getBukkitVersion", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(jni + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gets a view of all currently logged in players. This {@linkplain + /// Collections#unmodifiableCollection(Collection) view} is a reused + /// object, making some operations like {@link Collection#size()} + /// zero-allocation. + /// + /// The collection is a view backed by the internal representation, such + /// that, changes to the internal state of the server will be reflected + /// immediately. However, the reuse of the returned collection (identity) + /// is not strictly guaranteed for future or all implementations. Casting + /// the collection, or relying on interface implementations (like {@link + /// Serializable} or {@link List}), is deprecated. + /// + /// Iteration behavior is undefined outside of self-contained main-thread + /// uses. Normal and immediate iterator use without consequences that + /// affect the collection are fully supported. The effects following + /// (non-exhaustive) {@link Entity#teleport(Location) teleportation}, + /// {@link Player#setHealth(double) death}, and {@link Player#kickPlayer( + /// String) kicking} are undefined. Any use of this collection from + /// asynchronous threads is unsafe. + /// + /// For safe consequential iteration or mimicking the old array behavior, + /// using {@link Collection#toArray(Object[])} is recommended. For making + /// snapshots, {@link ImmutableList#copyOf(Collection)} is recommended. + pub fn online_players( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getOnlinePlayers", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&jni, res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Player::from_raw(&jni, obj)?); + } + Ok(new_vec) + } + /// Get the maximum amount of players which can login to this server. + pub fn max_players( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getMaxPlayers", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; Ok(res.i()?) } - /// Gets the Z-coordinate of this chunk - pub fn z(&self) -> Result> { + /// Set the maximum amount of players allowed to be logged in at once. + pub fn set_max_players( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + max_players: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(max_players); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "setMaxPlayers", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + jni.translate_error(res)?; + Ok(()) + } + /// Get the game port that the server runs on. + pub fn port( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getPort", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; Ok(res.i()?) } - /// Gets the world containing this chunk - pub fn world(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::World::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Get the view distance from this server. + pub fn view_distance( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()I"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getViewDistance", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.i()?) } - /// Gets a block from this chunk - pub fn get_block( - &self, - x: i32, - y: i32, - z: i32, - ) -> Result, Box> { - let sig = String::from("(III)Lorg/bukkit/block/Block;"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(y); - let val_3 = jni::objects::JValueGen::Int(z); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getBlock", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Get the simulation distance from this server. + pub fn simulation_distance( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()I"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getSimulationDistance", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.i()?) } - /// Capture thread-safe read-only snapshot of chunk data - pub fn get_chunk_snapshot( - &self, - include_maxblocky: bool, - include_biome: bool, - include_biome_temp_rain: bool, - ) -> Result, Box> { - let sig = String::from("(ZZZ)Lorg/bukkit/ChunkSnapshot;"); - let val_1 = jni::objects::JValueGen::Bool(include_maxblocky.into()); - let val_2 = jni::objects::JValueGen::Bool(include_biome.into()); - let val_3 = jni::objects::JValueGen::Bool(include_biome_temp_rain.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getChunkSnapshot", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = self.jni_ref().translate_error(res)?; - crate::ChunkSnapshot::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Get the IP that this server is bound to, or empty string if not + /// specified. + pub fn ip( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getIp", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(jni + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Checks if entities in this chunk are loaded. - pub fn is_entities_loaded(&self) -> Result> { + /// Get world type (level-type setting) for default world. + pub fn world_type( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getWorldType", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(jni + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Get generate-structures setting. + pub fn generate_structures( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isEntitiesLoaded", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getGenerateStructures", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; Ok(res.z()?) } - /// Get a list of all entities in the chunk. - /// This will force load any entities, which are not loaded. - pub fn entities(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getEntities", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Get max world size. + pub fn max_world_size( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()I"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getMaxWorldSize", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.i()?) } - /// Get a list of all tile entities in the chunk. - pub fn tile_entities( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockState;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTileEntities", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Gets whether this server allows the End or not. + pub fn allow_end( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()Z"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getAllowEnd", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.z()?) } - /// Checks if the chunk is fully generated. - pub fn is_generated(&self) -> Result> { + /// Gets whether this server allows the Nether or not. + pub fn allow_nether( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isGenerated", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getAllowNether", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; Ok(res.z()?) } - /// Checks if the chunk is loaded. - pub fn is_loaded(&self) -> Result> { + /// Gets whether the server is logging the IP addresses of players. + pub fn is_logging_ips( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isLoaded", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "isLoggingIPs", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; Ok(res.z()?) } - /// Loads the chunk. - pub fn load( - &self, - generate: std::option::Option, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = generate { - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_1); + + pub fn initial_enabled_packs( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/List;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getInitialEnabledPacks", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&jni, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push( + jni.get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "load", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(new_vec) } - /// Unloads and optionally saves the Chunk - pub fn unload( - &self, - save: std::option::Option, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = save { - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_1); + + pub fn initial_disabled_packs( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/List;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getInitialDisabledPacks", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&jni, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push( + jni.get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "unload", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(new_vec) } - /// Checks if this chunk can spawn slimes without being a swamp biome. - pub fn is_slime_chunk(&self) -> Result> { + /// Get the DataPack Manager. + pub fn data_pack_manager( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/packs/DataPackManager;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getDataPackManager", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::packs::DataPackManager::from_raw(&jni, obj) + } + /// Gets the resource pack configured to be sent to clients by the server. + pub fn server_resource_pack( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/packs/ResourcePack;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getServerResourcePack", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::packs::ResourcePack::from_raw(&jni, obj)?)) + } + /// Get the ServerTick Manager. + pub fn server_tick_manager( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/ServerTickManager;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getServerTickManager", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::ServerTickManager::from_raw(&jni, obj) + } + /// Gets the server resource pack uri, or empty string if not specified. + pub fn resource_pack( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getResourcePack", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(jni + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gets the SHA-1 digest of the server resource pack, or empty string if + /// not specified. + pub fn resource_pack_hash( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getResourcePackHash", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(jni + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gets the custom prompt message to be shown when the server resource + /// pack is required, or empty string if not specified. + pub fn resource_pack_prompt( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getResourcePackPrompt", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(jni + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gets whether the server resource pack is enforced. + pub fn is_resource_pack_required( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isSlimeChunk", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "isResourcePackRequired", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; Ok(res.z()?) } - /// Gets whether the chunk at the specified chunk coordinates is force - /// loaded. - /// - /// A force loaded chunk will not be unloaded due to lack of player activity. - pub fn is_force_loaded(&self) -> Result> { + /// Gets whether this server has a whitelist or not. + pub fn has_whitelist( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isForceLoaded", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "hasWhitelist", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; Ok(res.z()?) } - /// Sets whether the chunk at the specified chunk coordinates is force - /// loaded. - /// - /// A force loaded chunk will not be unloaded due to lack of player activity. - pub fn set_force_loaded(&self, forced: bool) -> Result<(), Box> { + /// Sets if the server is whitelisted. + pub fn set_whitelist( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + value: bool, + ) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(forced.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setForceLoaded", + let val_1 = jni::objects::JValueGen::Bool(value.into()); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "setWhitelist", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; + jni.translate_error(res)?; Ok(()) } - /// Adds a plugin ticket for this chunk, loading this chunk if it is not - /// already loaded. - /// - /// A plugin ticket will prevent a chunk from unloading until it is - /// explicitly removed. A plugin instance may only have one ticket per chunk, - /// but each chunk can have multiple plugin tickets. - /// - pub fn add_plugin_chunk_ticket( - &self, - plugin: impl Into>, + /// Gets whether the server whitelist is enforced. + /// If the whitelist is enforced, non-whitelisted players will be + /// disconnected when the server whitelist is reloaded. + pub fn is_whitelist_enforced( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addPluginChunkTicket", + let sig = String::from("()Z"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "isWhitelistEnforced", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.z()?) + } + /// Sets if the server whitelist is enforced. + /// If the whitelist is enforced, non-whitelisted players will be + /// disconnected when the server whitelist is reloaded. + pub fn set_whitelist_enforced( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + value: bool, + ) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(value.into()); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "setWhitelistEnforced", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + jni.translate_error(res)?; + Ok(()) } - /// Removes the specified plugin's ticket for this chunk - /// - /// A plugin ticket will prevent a chunk from unloading until it is - /// explicitly removed. A plugin instance may only have one ticket per chunk, - /// but each chunk can have multiple plugin tickets. + /// Gets a list of whitelisted players. + pub fn whitelisted_players( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getWhitelistedPlayers", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + blackboxmc_java::util::JavaSet::from_raw(&jni, obj) + } + /// Reloads the whitelist from disk. + pub fn reload_whitelist( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result<(), Box> { + let sig = String::from("()V"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "reloadWhitelist", sig.as_str(), vec![]); + jni.translate_error(res)?; + Ok(()) + } + /// Broadcast a message to all players. /// - pub fn remove_plugin_chunk_ticket( - &self, - plugin: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removePluginChunkTicket", + /// This is the same as calling {@link #broadcast(java.lang.String, + /// java.lang.String)} to {@link Server#BROADCAST_CHANNEL_USERS} + pub fn broadcast_message( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + message: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)I"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(message.into())?, + )); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "broadcastMessage", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let res = jni.translate_error(res)?; + Ok(res.i()?) } - /// Retrieves a collection specifying which plugins have tickets for this - /// chunk. This collection is not updated when plugin tickets are added or - /// removed to this chunk. - /// - /// A plugin ticket will prevent a chunk from unloading until it is - /// explicitly removed. A plugin instance may only have one ticket per chunk, - /// but each chunk can have multiple plugin tickets. + /// Gets the name of the update folder. The update folder is used to safely + /// update plugins at the right moment on a plugin load. /// - pub fn plugin_chunk_tickets( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPluginChunkTickets", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::plugin::Plugin::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + /// The update folder name is relative to the plugins folder. + pub fn update_folder( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getUpdateFolder", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(jni + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Gets the amount of time in ticks that this chunk has been inhabited. - /// Note that the time is incremented once per tick per player within mob - /// spawning distance of this chunk. - pub fn inhabited_time(&self) -> Result> { + /// Gets the value of the connection throttle setting. + pub fn connection_throttle( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { let sig = String::from("()J"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getInhabitedTime", + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getConnectionThrottle", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.j()?) + } + #[deprecated] + /// Gets default ticks per animal spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn monsters every tick.
    • A value of 400 will mean the server will attempt to spawn monsters every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, animal spawning will be disabled. We recommend using spawn-animals to control this instead.Minecraft default: 400. + pub fn ticks_per_animal_spawns( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()I"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getTicksPerAnimalSpawns", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.i()?) + } + #[deprecated] + /// Gets the default ticks per monster spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn monsters every tick.
    • A value of 400 will mean the server will attempt to spawn monsters every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, monsters spawning will be disabled. We recommend using spawn-monsters to control this instead.Minecraft default: 1. + pub fn ticks_per_monster_spawns( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()I"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getTicksPerMonsterSpawns", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.i()?) + } + #[deprecated] + /// Gets the default ticks per water mob spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn water mobs every tick.
    • A value of 400 will mean the server will attempt to spawn water mobs every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, water mobs spawning will be disabled.Minecraft default: 1. + pub fn ticks_per_water_spawns( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()I"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getTicksPerWaterSpawns", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.i()?) + } + #[deprecated] + /// Gets the default ticks per ambient mob spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn ambient mobs every tick.
    • A value of 400 will mean the server will attempt to spawn ambient mobs every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, ambient mobs spawning will be disabled.Minecraft default: 1. + pub fn ticks_per_ambient_spawns( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()I"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getTicksPerAmbientSpawns", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.i()?) + } + #[deprecated] + /// Gets the default ticks per water ambient mob spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn water ambient mobs every tick.
    • A value of 400 will mean the server will attempt to spawn water ambient mobs every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, ambient mobs spawning will be disabled.Minecraft default: 1. + pub fn ticks_per_water_ambient_spawns( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()I"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = + jni.call_static_method(cls, "getTicksPerWaterAmbientSpawns", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.i()?) + } + #[deprecated] + /// Gets the default ticks per water underground creature spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn water underground creature every tick.
    • A value of 400 will mean the server will attempt to spawn water underground creature every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, water underground creature spawning will be disabled.Minecraft default: 1. + pub fn ticks_per_water_underground_creature_spawns( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()I"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getTicksPerWaterUndergroundCreatureSpawns", sig.as_str(), vec![], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + let res = jni.translate_error(res)?; + Ok(res.i()?) } - /// Sets the amount of time in ticks that this chunk has been inhabited. - pub fn set_inhabited_time(&self, ticks: i64) -> Result<(), Box> { - let sig = String::from("(J)V"); - let val_1 = jni::objects::JValueGen::Long(ticks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setInhabitedTime", + /// Gets the default ticks per {@link SpawnCategory} spawns value. + /// + /// Example Usage: + ///
      + ///
    • A value of 1 will mean the server will attempt to spawn {@link SpawnCategory} mobs + /// every tick. + ///
    • A value of 400 will mean the server will attempt to spawn {@link SpawnCategory} mobs + /// every 400th tick. + ///
    • A value below 0 will be reset back to Minecraft's default. + ///
    + /// + /// Note: If set to 0, {@link SpawnCategory} mobs spawning will be disabled. + /// + /// Minecraft default: 1. + /// + /// Note: the {@link SpawnCategory#MISC} are not consider. + pub fn get_ticks_per_spawns( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + spawn_category: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/SpawnCategory;)I"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(spawn_category.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getTicksPerSpawns", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Tests if this chunk contains the specified biome. - pub fn contains( - &self, - biome: impl Into>, - ) -> Result> { + let res = jni.translate_error(res)?; + Ok(res.i()?) + } + /// Gets the player with the given UUID. + pub fn get_player( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + id: impl Into>, + ) -> Result>, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/block/Biome;"; + sig += "Ljava/util/UUID;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(biome.into().jni_object().clone()) + jni::objects::JObject::from_raw(id.into().jni_object().clone()) }); args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "contains", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the load level of this chunk, which determines what game logic is - /// processed. - pub fn load_level(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Chunk/LoadLevel;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLoadLevel", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::ChunkLoadLevel::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + sig += ")Lorg/bukkit/entity/Player;"; + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getPlayer", sig.as_str(), args); + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::entity::Player::from_raw(&jni, obj)?)) } - /// Gets all generated structures of a given {@link Structure} that intersect - /// this chunk. - /// - /// If no structures are present an empty collection will be returned. - pub fn get_structures( - &self, - structure: impl Into>, - ) -> Result>, Box> - { - let sig = - String::from("(Lorg/bukkit/generator/structure/Structure;)Ljava/util/Collection;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(structure.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getStructures", + /// Gets the player with the exact given name, case insensitive. + pub fn get_player_exact( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + name: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/entity/Player;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(name.into())?, + )); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getPlayerExact", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::generator::structure::GeneratedStructure::from_raw( - &self.jni_ref(), - obj, - )?); + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - Ok(new_vec) + let obj = res.l()?; + Ok(Some(crate::entity::Player::from_raw(&jni, obj)?)) } - /// Get a list of all players who are can view the chunk from their client + /// Attempts to match any players with the given name, and returns a list + /// of all possibly matches. /// - /// This list will be empty if no players are viewing the chunk, or the chunk - /// is unloaded. - pub fn players_seeing_chunk( - &self, + /// This list is not sorted in any particular order. If an exact match is + /// found, the returned list will only contain a single result. + pub fn match_player( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + name: impl Into, ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPlayersSeeingChunk", + let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(name.into())?, + )); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "matchPlayer", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; + let res = jni.translate_error(res)?; let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; + let list = blackboxmc_java::util::JavaList::from_raw(&jni, res.l()?)?; + let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::entity::Player::from_raw(&self.jni_ref(), obj)?); + new_vec.push(crate::entity::Player::from_raw(&jni, obj)?); } Ok(new_vec) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( - &self, - ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPersistentDataContainer", - sig.as_str(), - args, - ); - let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Chunk<'mc> { - fn into(self) -> crate::persistence::PersistentDataHolder<'mc> { - crate::persistence::PersistentDataHolder::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Chunk into crate::persistence::PersistentDataHolder") - } -} -pub enum ChunkLoadLevel<'mc> {} -impl<'mc> std::fmt::Display for ChunkLoadLevel<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> ChunkLoadLevel<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/Chunk/LoadLevel"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/Chunk/LoadLevel;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; + /// Gets the plugin manager for interfacing with plugins. + pub fn plugin_manager( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/plugin/PluginManager;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getPluginManager", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct ChunkLoadLevelStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for ChunkLoadLevel<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for ChunkLoadLevel<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate ChunkLoadLevel from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Chunk/LoadLevel")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ChunkLoadLevel object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for ChunkLoadLevelStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for ChunkLoadLevelStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate ChunkLoadLevelStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Chunk/LoadLevel")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ChunkLoadLevelStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + crate::plugin::PluginManager::from_raw(&jni, obj) } -} - -impl<'mc> ChunkLoadLevelStruct<'mc> { - pub fn values( + /// Gets the scheduler for managing scheduled events. + pub fn scheduler( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Chunk/LoadLevel;"); - let cls = jni.find_class("org/bukkit/Chunk/LoadLevel"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/scheduler/BukkitScheduler;"); + let cls = jni.find_class("org/bukkit/Bukkit"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.call_static_method(cls, "getScheduler", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::ChunkLoadLevel::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct BlockChangeDelegate<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for BlockChangeDelegate<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for BlockChangeDelegate<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate BlockChangeDelegate from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/BlockChangeDelegate")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockChangeDelegate object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> BlockChangeDelegate<'mc> { - /// Set a block data at the specified coordinates. - pub fn set_block_data( - &self, - x: i32, - y: i32, - z: i32, - block_data: impl Into>, - ) -> Result> { - let sig = String::from("(IIILorg/bukkit/block/data/BlockData;)Z"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(y); - let val_3 = jni::objects::JValueGen::Int(z); - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block_data.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setBlockData", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - ], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the block data at the location. - pub fn get_block_data( - &self, - x: i32, - y: i32, - z: i32, - ) -> Result, Box> { - let sig = String::from("(III)Lorg/bukkit/block/data/BlockData;"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(y); - let val_3 = jni::objects::JValueGen::Int(z); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getBlockData", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the height of the world. - pub fn height(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Checks if the specified block is empty (air) or not. - pub fn is_empty(&self, x: i32, y: i32, z: i32) -> Result> { - let sig = String::from("(III)Z"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(y); - let val_3 = jni::objects::JValueGen::Int(z); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isEmpty", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct OfflinePlayer<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for OfflinePlayer<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for OfflinePlayer<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate OfflinePlayer from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/OfflinePlayer")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a OfflinePlayer object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> OfflinePlayer<'mc> { - /// Checks if this player is currently online - pub fn is_online(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isOnline", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::scheduler::BukkitScheduler::from_raw(&jni, obj) } - /// Returns the name of this player - /// - /// Names are no longer unique past a single game session. For persistent storage - /// it is recommended that you use {@link #getUniqueId()} instead. - pub fn name(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + /// Gets a services manager. + pub fn services_manager( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/plugin/ServicesManager;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getServicesManager", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::plugin::ServicesManager::from_raw(&jni, obj) } - /// Returns the UUID of this player - pub fn unique_id( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Gets a list of all worlds on this server. + pub fn worlds( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getWorlds", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&jni, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::World::from_raw(&jni, obj)?); + } + Ok(new_vec) } - /// Gets a copy of the player's profile. + /// Creates or loads a world with the given name using the specified + /// options. /// - /// If the player is online, the returned profile will be complete. - /// Otherwise, only the unique id is guaranteed to be present. You can use - /// {@link PlayerProfile#update()} to complete the returned profile. - pub fn player_profile( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/profile/PlayerProfile;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPlayerProfile", + /// If the world is already loaded, it will just return the equivalent of + /// getWorld(creator.name()). + pub fn create_world( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + creator: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/WorldCreator;)Lorg/bukkit/World;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(creator.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "createWorld", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::profile::PlayerProfile::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::World::from_raw(&jni, obj)?)) } - /// Checks if this player has had their profile banned. - pub fn is_banned(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isBanned", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; + /// Unloads the given world. + pub fn unload_world( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + world: impl Into>, + save: bool, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/World;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(world.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(save.into()); + args.push(val_2); + sig += ")Z"; + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "unloadWorld", sig.as_str(), args); + let res = jni.translate_error(res)?; Ok(res.z()?) } - /// Adds this user to the {@link ProfileBanList}. If a previous ban exists, this will - /// update the entry. - pub fn ban( - &self, - reason: impl Into, - duration: jni::objects::JObject<'mc>, - source: impl Into, - ) -> Result>, Box> { + /// Gets the world from the given Unique ID. + pub fn get_world( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + uid: impl Into>, + ) -> Result>, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(reason.into())?, - )); + sig += "Ljava/util/UUID;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(uid.into().jni_object().clone()) + }); args.push(val_1); - sig += "Ljava/time/Duration;"; - let val_2 = jni::objects::JValueGen::Object(duration); - args.push(val_2); - sig += "Ljava/lang/String;"; - let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(source.into())?, - )); - args.push(val_3); - sig += ")Lorg/bukkit/BanEntry;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "ban", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; + sig += ")Lorg/bukkit/World;"; + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getWorld", sig.as_str(), args); + let res = jni.translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::BanEntry::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + let obj = res.l()?; + Ok(Some(crate::World::from_raw(&jni, obj)?)) } - /// Checks if this player is whitelisted or not - pub fn is_whitelisted(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isWhitelisted", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Create a new virtual {@link WorldBorder}. + pub fn create_world_border( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/WorldBorder;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "createWorldBorder", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::WorldBorder::from_raw(&jni, obj) } - /// Sets if this player is whitelisted or not - pub fn set_whitelisted(&self, value: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(value.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setWhitelisted", + #[deprecated] + /// Gets the map from the given item ID. + pub fn get_map( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + id: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/map/MapView;"); + let val_1 = jni::objects::JValueGen::Int(id); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getMap", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets a {@link Player} object that this represents, if there is one - /// - /// If the player is online, this will return that player. Otherwise, - /// it will return null. - pub fn player(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/entity/Player;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; + let res = jni.translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::entity::Player::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + let obj = res.l()?; + Ok(Some(crate::map::MapView::from_raw(&jni, obj)?)) } - /// Gets the first date and time that this player was witnessed on this - /// server. - /// - /// If the player has never played before, this will return 0. Otherwise, - /// it will be the amount of milliseconds since midnight, January 1, 1970 - /// UTC. - pub fn first_played(&self) -> Result> { - let sig = String::from("()J"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFirstPlayed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + /// Create a new map with an automatically assigned ID. + pub fn create_map( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + world: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/World;)Lorg/bukkit/map/MapView;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(world.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "createMap", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::map::MapView::from_raw(&jni, obj) } - /// Gets the last date and time that this player was witnessed on this - /// server. + /// Create a new explorer map targeting the closest nearby structure of a + /// given {@link StructureType}. /// - /// If the player has never played before, this will return 0. Otherwise, - /// it will be the amount of milliseconds since midnight, January 1, 1970 - /// UTC. - pub fn last_played(&self) -> Result> { - let sig = String::from("()J"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLastPlayed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + /// This method uses implementation default values for radius and + /// findUnexplored (usually 100, true). + pub fn create_explorer_map( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + world: impl Into>, + location: impl Into>, + structure_type: impl Into>, + radius: std::option::Option, + find_unexplored: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/World;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(world.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Lorg/bukkit/Location;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_2); + sig += "Lorg/bukkit/StructureType;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(structure_type.into().jni_object().clone()) + }); + args.push(val_3); + if let Some(a) = radius { + sig += "I"; + let val_4 = jni::objects::JValueGen::Int(a); + args.push(val_4); + } + if let Some(a) = find_unexplored { + sig += "Z"; + let val_5 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_5); + } + sig += ")Lorg/bukkit/inventory/ItemStack;"; + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "createExplorerMap", sig.as_str(), args); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::inventory::ItemStack::from_raw(&jni, obj) } - /// Checks if this player has played on this server before. - pub fn has_played_before(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasPlayedBefore", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Reloads the server, refreshing settings and plugin information. + pub fn reload( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result<(), Box> { + let sig = String::from("()V"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "reload", sig.as_str(), vec![]); + jni.translate_error(res)?; + Ok(()) } - #[deprecated] - /// Gets the Location where the player will spawn at their bed, null if they have not slept in one or their current bed spawn is invalid. - pub fn bed_spawn_location( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getBedSpawnLocation", + /// Reload only the Minecraft data for the server. This includes custom + /// advancements and loot tables. + pub fn reload_data( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result<(), Box> { + let sig = String::from("()V"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "reloadData", sig.as_str(), vec![]); + jni.translate_error(res)?; + Ok(()) + } + /// Returns the primary logger associated with this server instance. + pub fn logger( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/logging/Logger;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getLogger", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + blackboxmc_java::util::logging::JavaLogger::from_raw(&jni, obj) + } + /// Gets a {@link PluginCommand} with the given name or alias. + pub fn get_plugin_command( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + name: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/command/PluginCommand;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(name.into())?, + )); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getPluginCommand", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; + let res = jni.translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + let obj = res.l()?; + Ok(Some(crate::command::PluginCommand::from_raw(&jni, obj)?)) } - /// Gets the Location where the player will spawn at, null if they - /// don't have a valid respawn point. - pub fn respawn_location( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getRespawnLocation", + /// Writes loaded players to disk. + pub fn save_players( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result<(), Box> { + let sig = String::from("()V"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "savePlayers", sig.as_str(), vec![]); + jni.translate_error(res)?; + Ok(()) + } + /// Dispatches a command on this server, and executes it if found. + pub fn dispatch_command( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + sender: impl Into>, + command_line: impl Into, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/command/CommandSender;Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(command_line.into())?, + )); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "dispatchCommand", sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + let res = jni.translate_error(res)?; + Ok(res.z()?) } - /// Increments the given statistic for this player for the given entity. - pub fn increment_statistic( - &self, - statistic: impl Into>, - entity_type: std::option::Option>>, - amount: std::option::Option, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Statistic;"; + /// Adds a recipe to the crafting manager. + pub fn add_recipe( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + recipe: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/Recipe;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(statistic.into().jni_object().clone()) + jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) }); - args.push(val_1); - if let Some(a) = entity_type { - sig += "Lorg/bukkit/entity/EntityType;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - if let Some(a) = amount { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "addRecipe", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + Ok(res.z()?) + } + /// Get a list of all recipes for a given item. The stack size is ignored + /// in comparisons. If the durability is -1, it will match any data value. + pub fn get_recipes_for( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + result: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(result.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getRecipesFor", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&jni, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::inventory::Recipe::from_raw(&jni, obj)?); } - sig += ")V"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "incrementStatistic", + Ok(new_vec) + } + /// Get the {@link Recipe} for the given key. + pub fn get_recipe( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + recipe_key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/inventory/Recipe;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(recipe_key.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getRecipe", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::inventory::Recipe::from_raw(&jni, obj)?)) } - /// Decrements the given statistic for this player for the given entity. - pub fn decrement_statistic( - &self, - statistic: impl Into>, - entity_type: std::option::Option>>, - amount: std::option::Option, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Statistic;"; + /// Get the {@link Recipe} for the list of ItemStacks provided. + /// The list is formatted as a crafting matrix where the index follow + /// the pattern below: + ///
    +    /// [ 0 1 2 ]
    +    /// [ 3 4 5 ]
    +    /// [ 6 7 8 ]
    +    /// 
    + /// NOTE: This method will not modify the provided ItemStack array, for that, use + /// {@link #craftItem(ItemStack[], World, Player)}. + pub fn get_crafting_recipe( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + crafting_matrix: impl Into>, + world: impl Into>, + ) -> Result>, Box> { + let sig = String::from( + "(Lorg/bukkit/inventory/ItemStack;Lorg/bukkit/World;)Lorg/bukkit/inventory/Recipe;", + ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(statistic.into().jni_object().clone()) + jni::objects::JObject::from_raw(crafting_matrix.into().jni_object().clone()) }); - args.push(val_1); - if let Some(a) = entity_type { - sig += "Lorg/bukkit/entity/EntityType;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - if let Some(a) = amount { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - sig += ")V"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "decrementStatistic", + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(world.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getCraftingRecipe", sig.as_str(), - args, + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::inventory::Recipe::from_raw(&jni, obj)?)) } - /// Sets the given statistic for this player for the given entity. - pub fn set_statistic( - &self, - statistic: impl Into>, - entity_type: impl Into>, - new_value: std::option::Option, - ) -> Result<(), Box> { + /// Get the crafted item using the list of {@link ItemStack} provided. + /// The list is formatted as a crafting matrix where the index follow + /// the pattern below: + ///
    +    /// [ 0 1 2 ]
    +    /// [ 3 4 5 ]
    +    /// [ 6 7 8 ]
    +    /// 
    + /// The {@link World} and {@link Player} arguments are required to fulfill the Bukkit Crafting + /// events. + /// Calls {@link org.bukkit.event.inventory.PrepareItemCraftEvent} to imitate the {@link Player} + /// initiating the crafting event. + pub fn craft_item_result( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + crafting_matrix: impl Into>, + world: impl Into>, + player: std::option::Option>>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Statistic;"; + sig += "Lorg/bukkit/inventory/ItemStack;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(statistic.into().jni_object().clone()) + jni::objects::JObject::from_raw(crafting_matrix.into().jni_object().clone()) }); args.push(val_1); - sig += "Lorg/bukkit/entity/EntityType;"; + sig += "Lorg/bukkit/World;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(world.into().jni_object().clone()) }); args.push(val_2); - if let Some(a) = new_value { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); + if let Some(a) = player { + sig += "Lorg/bukkit/entity/Player;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); args.push(val_3); } - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setStatistic", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + sig += ")Lorg/bukkit/inventory/ItemCraftResult;"; + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "craftItemResult", sig.as_str(), args); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::inventory::ItemCraftResult::from_raw(&jni, obj) } - /// Gets the value of the given statistic for this player. - pub fn get_statistic( - &self, - statistic: impl Into>, - entity_type: std::option::Option>>, - ) -> Result> { + /// Get the crafted item using the list of {@link ItemStack} provided. + /// The list is formatted as a crafting matrix where the index follow + /// the pattern below: + ///
    +    /// [ 0 1 2 ]
    +    /// [ 3 4 5 ]
    +    /// [ 6 7 8 ]
    +    /// 
    + /// The {@link World} and {@link Player} arguments are required to fulfill the Bukkit Crafting + /// events. + /// Calls {@link org.bukkit.event.inventory.PrepareItemCraftEvent} to imitate the {@link Player} + /// initiating the crafting event. + pub fn craft_item( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + crafting_matrix: impl Into>, + world: impl Into>, + player: std::option::Option>>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Statistic;"; + sig += "Lorg/bukkit/inventory/ItemStack;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(statistic.into().jni_object().clone()) + jni::objects::JObject::from_raw(crafting_matrix.into().jni_object().clone()) }); args.push(val_1); - if let Some(a) = entity_type { - sig += "Lorg/bukkit/entity/EntityType;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { + sig += "Lorg/bukkit/World;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(world.into().jni_object().clone()) + }); + args.push(val_2); + if let Some(a) = player { + sig += "Lorg/bukkit/entity/Player;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); - args.push(val_2); + args.push(val_3); } - sig += ")I"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getStatistic", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + sig += ")Lorg/bukkit/inventory/ItemStack;"; + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "craftItem", sig.as_str(), args); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::inventory::ItemStack::from_raw(&jni, obj) } - /// Gets the player's last death location. - pub fn last_death_location( - &self, - ) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Lorg/bukkit/Location;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLastDeathLocation", - sig.as_str(), - args, - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + /// Get an iterator through the list of crafting recipes. + pub fn recipe_iterator( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Iterator;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "recipeIterator", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + blackboxmc_java::util::JavaIterator::from_raw(&jni, obj) } - /// Gets the player's current location. - pub fn location(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + /// Clears the list of crafting recipes. + pub fn clear_recipes( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result<(), Box> { + let sig = String::from("()V"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "clearRecipes", sig.as_str(), vec![]); + jni.translate_error(res)?; + Ok(()) } - /// Checks if this object is a server operator - pub fn is_op(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isOp", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Resets the list of crafting recipes to the default. + pub fn reset_recipes( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result<(), Box> { + let sig = String::from("()V"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "resetRecipes", sig.as_str(), vec![]); + jni.translate_error(res)?; + Ok(()) } - /// Sets the operator status of this object - pub fn set_op(&self, value: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(value.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setOp", + /// Remove a recipe from the server. + /// Note that removing a recipe may cause permanent loss of data + /// associated with that recipe (eg whether it has been discovered by + /// players). + pub fn remove_recipe( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + key: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(key.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "removeRecipe", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = jni.translate_error(res)?; + Ok(res.z()?) } - /// Creates a Map representation of this class. - /// - /// This class must provide a method to restore this class, as defined in - /// the {@link ConfigurationSerializable} interface javadocs. - pub fn serialize( - &self, + /// Gets a list of command aliases defined in the server properties. + pub fn command_aliases( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/Map;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for OfflinePlayer<'mc> { - fn into(self) -> crate::permissions::ServerOperator<'mc> { - crate::permissions::ServerOperator::from_raw(&self.jni_ref(), self.1) - .expect("Error converting OfflinePlayer into crate::permissions::ServerOperator") - } -} -impl<'mc> Into> for OfflinePlayer<'mc> { - fn into(self) -> crate::entity::AnimalTamer<'mc> { - crate::entity::AnimalTamer::from_raw(&self.jni_ref(), self.1) - .expect("Error converting OfflinePlayer into crate::entity::AnimalTamer") - } -} -impl<'mc> Into> - for OfflinePlayer<'mc> -{ - fn into(self) -> crate::configuration::serialization::ConfigurationSerializable<'mc> { - crate::configuration::serialization::ConfigurationSerializable::from_raw(&self.jni_ref(), self.1).expect("Error converting OfflinePlayer into crate::configuration::serialization::ConfigurationSerializable") + let sig = String::from("()Ljava/util/Map;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getCommandAliases", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + blackboxmc_java::util::JavaMap::from_raw(&jni, obj) } -} -pub enum SandstoneType<'mc> {} -impl<'mc> std::fmt::Display for SandstoneType<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + /// Gets the radius, in blocks, around each worlds spawn point to protect. + pub fn spawn_radius( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()I"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getSpawnRadius", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.i()?) } -} - -impl<'mc> SandstoneType<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/SandstoneType"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( + /// Sets the radius, in blocks, around each worlds spawn point to protect. + pub fn set_spawn_radius( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + value: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(value); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/SandstoneType;", + "setSpawnRadius", + sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + jni.translate_error(res)?; + Ok(()) } -} - -#[repr(C)] -pub struct SandstoneTypeStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for SandstoneType<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + #[deprecated] + /// Gets whether the server should send a preview of the player's chat message to the client when the player sends a message + pub fn should_send_chat_previews( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()Z"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "shouldSendChatPreviews", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.z()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + /// Gets whether the server only allow players with Mojang-signed public key + /// to join + pub fn is_enforcing_secure_profiles( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()Z"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "isEnforcingSecureProfiles", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for SandstoneType<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate SandstoneType from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/SandstoneType")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a SandstoneType object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } + /// Gets whether this server is allowing connections transferred from other + /// servers. + pub fn is_accepting_transfers( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()Z"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "isAcceptingTransfers", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.z()?) } -} - -impl<'mc> JNIRaw<'mc> for SandstoneTypeStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Gets whether the Server hide online players in server status. + pub fn hide_online_players( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()Z"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHideOnlinePlayers", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.z()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets whether the Server is in online mode or not. + pub fn online_mode( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()Z"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getOnlineMode", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for SandstoneTypeStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate SandstoneTypeStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/SandstoneType")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a SandstoneTypeStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Gets whether this server allows flying or not. + pub fn allow_flight( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()Z"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getAllowFlight", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.z()?) } -} - -impl<'mc> SandstoneTypeStruct<'mc> { - pub fn values( + /// Gets whether the server is in hardcore mode or not. + pub fn is_hardcore( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/SandstoneType;"); - let cls = jni.find_class("org/bukkit/SandstoneType"); + ) -> Result> { + let sig = String::from("()Z"); + let cls = jni.find_class("org/bukkit/Bukkit"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.call_static_method(cls, "isHardcore", sig.as_str(), vec![]); let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::SandstoneType::from_raw(&jni, obj) + Ok(res.z()?) } - #[deprecated] - /// Gets the associated data value representing this type of sandstone - pub fn data(&self) -> Result> { - let sig = String::from("()B"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) + /// Shutdowns the server, stopping everything. + pub fn shutdown( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result<(), Box> { + let sig = String::from("()V"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "shutdown", sig.as_str(), vec![]); + jni.translate_error(res)?; + Ok(()) } - #[deprecated] - /// Gets the type of sandstone with the given data value - pub fn get_by_data( + /// Broadcasts the specified message to every user with the given + /// permission name. + pub fn broadcast( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - data: i8, - ) -> Result>, Box> { - let sig = String::from("(B)Lorg/bukkit/SandstoneType;"); - let val_1 = jni::objects::JValueGen::Byte(data); - let cls = jni.find_class("org/bukkit/SandstoneType"); + message: impl Into, + permission: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;Ljava/lang/String;)I"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(message.into())?, + )); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(permission.into())?, + )); + let cls = jni.find_class("org/bukkit/Bukkit"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method( cls, - "getByData", + "broadcast", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::SandstoneType::from_raw(&jni, obj)?)) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct World<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for World<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for World<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate World from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/World")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a World object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + Ok(res.i()?) } -} - -impl<'mc> World<'mc> { - /// Gets the {@link Block} at the given coordinates - pub fn get_block_at( - &self, - x: i32, - y: std::option::Option, - z: std::option::Option, - ) -> Result, Box> { + /// Gets the player by the given UUID, regardless if they are offline or + /// online. + /// + /// This will return an object even if the player does not exist. To this + /// method, all players will exist. + pub fn get_offline_player( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + id: impl Into>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); + sig += "Ljava/util/UUID;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(id.into().jni_object().clone()) + }); args.push(val_1); - if let Some(a) = y { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - if let Some(a) = z { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - sig += ")Lorg/bukkit/block/Block;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBlockAt", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + sig += ")Lorg/bukkit/OfflinePlayer;"; + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getOfflinePlayer", sig.as_str(), args); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::OfflinePlayer::from_raw(&jni, obj) } - /// Gets the highest block corresponding to the {@link HeightMap} at the - /// given coordinates. - pub fn get_highest_block_at( - &self, - location: impl Into>, - height_map: std::option::Option>>, - ) -> Result, Box> { + /// Creates a new {@link PlayerProfile}. + pub fn create_player_profile( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + unique_id: impl Into>, + name: std::option::Option>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; + sig += "Ljava/util/UUID;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) + jni::objects::JObject::from_raw(unique_id.into().jni_object().clone()) }); args.push(val_1); - if let Some(a) = height_map { - sig += "Lorg/bukkit/HeightMap;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); + if let Some(a) = name { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(a.into())?, + )); args.push(val_2); } - sig += ")Lorg/bukkit/block/Block;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHighestBlockAt", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + sig += ")Lorg/bukkit/profile/PlayerProfile;"; + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "createPlayerProfile", sig.as_str(), args); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::profile::PlayerProfile::from_raw(&jni, obj) } - /// Gets the {@link Chunk} at the given coordinates - pub fn get_chunk_at( - &self, - x: i32, - z: std::option::Option, - generate: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); - args.push(val_1); - if let Some(a) = z { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - if let Some(a) = generate { - sig += "Z"; - let val_3 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_3); - } - sig += ")Lorg/bukkit/Chunk;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getChunkAt", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::Chunk::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Gets a set containing all current IPs that are banned. + pub fn ipbans( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getIPBans", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + blackboxmc_java::util::JavaSet::from_raw(&jni, obj) } - /// Checks if the {@link Chunk} at the specified coordinates is loaded - pub fn is_chunk_loaded( - &self, - x: i32, - z: std::option::Option, - ) -> Result> { + /// Bans the specified address from the server. + pub fn ban_ip( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + address: jni::objects::JObject<'mc>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); + sig += "Ljava/net/InetAddress;"; + let val_1 = jni::objects::JValueGen::Object(address); args.push(val_1); - if let Some(a) = z { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isChunkLoaded", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets an array of all loaded {@link Chunk}s - pub fn loaded_chunks(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Chunk;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLoadedChunks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Chunk::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + sig += ")V"; + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "banIP", sig.as_str(), args); + jni.translate_error(res)?; + Ok(()) } - /// Loads the {@link Chunk} at the specified coordinates. - /// - /// This method will keep the specified chunk loaded until one of the - /// unload methods is manually called. Callers are advised to instead use - /// getChunkAt which will only temporarily load the requested chunk. - pub fn load_chunk( - &self, - x: i32, - z: std::option::Option, - generate: std::option::Option, - ) -> Result> { + /// Unbans the specified address from the server. + pub fn unban_ip( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + address: jni::objects::JObject<'mc>, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); + sig += "Ljava/net/InetAddress;"; + let val_1 = jni::objects::JValueGen::Object(address); args.push(val_1); - if let Some(a) = z { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - if let Some(a) = generate { - sig += "Z"; - let val_3 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_3); - } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "loadChunk", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + sig += ")V"; + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "unbanIP", sig.as_str(), args); + jni.translate_error(res)?; + Ok(()) } - /// Checks if the {@link Chunk} at the specified coordinates is generated - pub fn is_chunk_generated(&self, x: i32, z: i32) -> Result> { - let sig = String::from("(II)Z"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(z); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isChunkGenerated", + /// Gets a set containing all banned players. + pub fn banned_players( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getBannedPlayers", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + blackboxmc_java::util::JavaSet::from_raw(&jni, obj) + } + /// Gets a ban list for the supplied type. + pub fn get_ban_list( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + val_type: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/BanList/Type;)LT;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getBanList", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let res = jni.translate_error(res)?; + Ok(res.l()?) } - #[deprecated] - /// Checks if the {@link Chunk} at the specified coordinates is loaded and in use by one or more players - pub fn is_chunk_in_use(&self, x: i32, z: i32) -> Result> { - let sig = String::from("(II)Z"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(z); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isChunkInUse", + /// Gets a set containing all player operators. + pub fn operators( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getOperators", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + blackboxmc_java::util::JavaSet::from_raw(&jni, obj) + } + /// Gets the default {@link GameMode} for new players. + pub fn default_game_mode( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/GameMode;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getDefaultGameMode", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::GameMode::from_raw(&jni, obj) + } + /// Sets the default {@link GameMode} for new players. + pub fn set_default_game_mode( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + mode: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/GameMode;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(mode.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "setDefaultGameMode", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + jni.translate_error(res)?; + Ok(()) } - /// Safely unloads and optionally saves the {@link Chunk} at the specified - /// coordinates. - pub fn unload_chunk( - &self, - x: i32, - z: std::option::Option, - save: std::option::Option, - ) -> Result> { + /// Gets a {@link ConsoleCommandSender} that may be used as an input source + /// for this server. + pub fn console_sender( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/command/ConsoleCommandSender;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getConsoleSender", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::command::ConsoleCommandSender::from_raw(&jni, obj) + } + /// Gets every player that has ever played on this server. + pub fn offline_players( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/OfflinePlayer;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getOfflinePlayers", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::OfflinePlayer::from_raw(&jni, obj) + } + /// Gets the {@link Messenger} responsible for this server. + pub fn messenger( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/plugin/messaging/Messenger;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getMessenger", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::plugin::messaging::Messenger::from_raw(&jni, obj) + } + /// Gets the {@link HelpMap} providing help topics for this server. + pub fn help_map( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/help/HelpMap;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getHelpMap", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::help::HelpMap::from_raw(&jni, obj) + } + /// Creates an empty inventory of type {@link InventoryType#CHEST} with the + /// specified size and title. + pub fn create_inventory( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + owner: impl Into>, + size: i32, + title: std::option::Option>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); + sig += "Lorg/bukkit/inventory/InventoryHolder;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owner.into().jni_object().clone()) + }); args.push(val_1); - if let Some(a) = z { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - if let Some(a) = save { - sig += "Z"; - let val_3 = jni::objects::JValueGen::Bool(a.into()); + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(size); + args.push(val_2); + if let Some(a) = title { + sig += "Ljava/lang/String;"; + let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(a.into())?, + )); args.push(val_3); } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "unloadChunk", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + sig += ")Lorg/bukkit/inventory/Inventory;"; + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "createInventory", sig.as_str(), args); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::inventory::Inventory::from_raw(&jni, obj) } - /// Safely queues the {@link Chunk} at the specified coordinates for - /// unloading. - pub fn unload_chunk_request(&self, x: i32, z: i32) -> Result> { - let sig = String::from("(II)Z"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(z); - let res = self.jni_ref().call_method( - &self.jni_object(), - "unloadChunkRequest", + /// Creates an empty merchant. + pub fn create_merchant( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + title: impl Into, + ) -> Result, Box> { + let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/inventory/Merchant;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(title.into())?, + )); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "createMerchant", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::inventory::Merchant::from_raw(&jni, obj) + } + /// Gets the amount of consecutive neighbor updates before skipping + /// additional ones. + pub fn max_chained_neighbor_updates( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()I"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getMaxChainedNeighborUpdates", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.i()?) } #[deprecated] - /// Regenerates the {@link Chunk} at the specified coordinates - pub fn regenerate_chunk(&self, x: i32, z: i32) -> Result> { - let sig = String::from("(II)Z"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(z); - let res = self.jni_ref().call_method( - &self.jni_object(), - "regenerateChunk", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Gets user-specified limit for number of monsters that can spawn in a chunk. + pub fn monster_spawn_limit( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()I"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getMonsterSpawnLimit", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.i()?) } #[deprecated] - /// Resends the {@link Chunk} to all clients - pub fn refresh_chunk(&self, x: i32, z: i32) -> Result> { - let sig = String::from("(II)Z"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(z); - let res = self.jni_ref().call_method( - &self.jni_object(), - "refreshChunk", + /// Gets user-specified limit for number of animals that can spawn in a chunk. + pub fn animal_spawn_limit( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()I"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getAnimalSpawnLimit", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.i()?) + } + #[deprecated] + /// Gets user-specified limit for number of water animals that can spawn in a chunk. + pub fn water_animal_spawn_limit( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()I"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getWaterAnimalSpawnLimit", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.i()?) + } + #[deprecated] + /// Gets user-specified limit for number of water ambient mobs that can spawn in a chunk. + pub fn water_ambient_spawn_limit( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()I"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getWaterAmbientSpawnLimit", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.i()?) + } + #[deprecated] + /// Get user-specified limit for number of water creature underground that can spawn in a chunk. + pub fn water_underground_creature_spawn_limit( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()I"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getWaterUndergroundCreatureSpawnLimit", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let res = jni.translate_error(res)?; + Ok(res.i()?) } - /// Get a list of all players who are can view the specified chunk from their - /// client - /// - /// This list will be empty if no players are viewing the chunk, or the chunk - /// is unloaded. - pub fn get_players_seeing_chunk( - &self, - x: i32, - z: std::option::Option, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); - args.push(val_1); - if let Some(a) = z { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - sig += ")Ljava/util/Collection;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPlayersSeeingChunk", + #[deprecated] + /// Gets user-specified limit for number of ambient mobs that can spawn in a chunk. + pub fn ambient_spawn_limit( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()I"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getAmbientSpawnLimit", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.i()?) + } + /// Gets user-specified limit for number of {@link SpawnCategory} mobs that can spawn in + /// a chunk. + /// Note: the {@link SpawnCategory#MISC} are not consider. + pub fn get_spawn_limit( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + spawn_category: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/SpawnCategory;)I"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(spawn_category.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getSpawnLimit", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Player::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + let res = jni.translate_error(res)?; + Ok(res.i()?) } - /// Gets whether the chunk at the specified chunk coordinates is force - /// loaded. + /// Checks the current thread against the expected primary thread for the + /// server. /// - /// A force loaded chunk will not be unloaded due to lack of player activity. - pub fn is_chunk_force_loaded( - &self, - x: i32, - z: i32, + /// Note: this method should not be used to indicate the current + /// synchronized state of the runtime. A current thread matching the main + /// thread indicates that it is synchronized, but a mismatch does not + /// preclude the same assumption. + pub fn is_primary_thread( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, ) -> Result> { - let sig = String::from("(II)Z"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(z); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isChunkForceLoaded", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; + let sig = String::from("()Z"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "isPrimaryThread", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; Ok(res.z()?) } - /// Sets whether the chunk at the specified chunk coordinates is force - /// loaded. - /// - /// A force loaded chunk will not be unloaded due to lack of player activity. - pub fn set_chunk_force_loaded( - &self, - x: i32, - z: i32, - forced: bool, + /// Gets the message that is displayed on the server list. + pub fn motd( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getMotd", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(jni + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Set the message that is displayed on the server list. + pub fn set_motd( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + motd: impl Into, ) -> Result<(), Box> { - let sig = String::from("(IIZ)V"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(z); - let val_3 = jni::objects::JValueGen::Bool(forced.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setChunkForceLoaded", + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(motd.into())?, + )); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "setMotd", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; + jni.translate_error(res)?; Ok(()) } - /// Returns all force loaded chunks in this world. - /// - /// A force loaded chunk will not be unloaded due to lack of player activity. - pub fn force_loaded_chunks( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getForceLoadedChunks", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::Chunk::from_raw(&self.jni_ref(), obj)?); + /// Gets the server links which will be sent to clients + pub fn server_links( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/ServerLinks;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getServerLinks", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::ServerLinks::from_raw(&jni, obj) + } + /// Gets the default message that is displayed when the server is stopped. + pub fn shutdown_message( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getShutdownMessage", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - Ok(new_vec) + Ok(Some( + jni.get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Adds a plugin ticket for the specified chunk, loading the chunk if it is - /// not already loaded. - /// - /// A plugin ticket will prevent a chunk from unloading until it is - /// explicitly removed. A plugin instance may only have one ticket per chunk, - /// but each chunk can have multiple plugin tickets. - /// - pub fn add_plugin_chunk_ticket( - &self, - x: i32, - z: i32, - plugin: impl Into>, - ) -> Result> { - let sig = String::from("(IILorg/bukkit/plugin/Plugin;)Z"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(z); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addPluginChunkTicket", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Gets the current warning state for the server. + pub fn warning_state( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Warning/WarningState;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getWarningState", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::WarningWarningState::from_raw(&jni, obj) } - /// Removes the specified plugin's ticket for the specified chunk - /// - /// A plugin ticket will prevent a chunk from unloading until it is - /// explicitly removed. A plugin instance may only have one ticket per chunk, - /// but each chunk can have multiple plugin tickets. - /// - pub fn remove_plugin_chunk_ticket( - &self, - x: i32, - z: i32, - plugin: impl Into>, - ) -> Result> { - let sig = String::from("(IILorg/bukkit/plugin/Plugin;)Z"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(z); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removePluginChunkTicket", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Gets the instance of the item factory (for {@link ItemMeta}). + pub fn item_factory( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemFactory;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getItemFactory", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::inventory::ItemFactory::from_raw(&jni, obj) } - /// Removes all plugin tickets for the specified plugin - /// - /// A plugin ticket will prevent a chunk from unloading until it is - /// explicitly removed. A plugin instance may only have one ticket per chunk, - /// but each chunk can have multiple plugin tickets. + /// Gets the instance of the entity factory (for {@link EntitySnapshot}). + pub fn entity_factory( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityFactory;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getEntityFactory", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::entity::EntityFactory::from_raw(&jni, obj) + } + /// Gets the instance of the scoreboard manager. /// - pub fn remove_plugin_chunk_tickets( - &self, - plugin: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removePluginChunkTickets", + /// This will only exist after the first world has loaded. + pub fn scoreboard_manager( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/scoreboard/ScoreboardManager;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getScoreboardManager", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::scoreboard::ScoreboardManager::from_raw( + &jni, obj, + )?)) + } + /// Get (or create) a new {@link Criteria} by its name. + pub fn get_scoreboard_criteria( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + name: impl Into, + ) -> Result, Box> { + let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/scoreboard/Criteria;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(name.into())?, + )); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getScoreboardCriteria", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::scoreboard::Criteria::from_raw(&jni, obj) } - /// Returns a map of which plugins have tickets for what chunks. The returned - /// map is not updated when plugin tickets are added or removed to chunks. If - /// a plugin has no tickets, it will be absent from the map. + /// Gets an instance of the server's default server-icon. + pub fn server_icon( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/util/CachedServerIcon;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getServerIcon", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::util::CachedServerIcon::from_raw(&jni, obj)?)) + } + /// Creates a cached server-icon for the specific image. /// - /// A plugin ticket will prevent a chunk from unloading until it is - /// explicitly removed. A plugin instance may only have one ticket per chunk, - /// but each chunk can have multiple plugin tickets. + /// Size and type are implementation defined. An incompatible file is + /// guaranteed to throw an implementation-defined {@link Exception}. + pub fn load_server_icon( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + image: jni::objects::JObject<'mc>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/awt/image/BufferedImage;"; + let val_1 = jni::objects::JValueGen::Object(image); + args.push(val_1); + sig += ")Lorg/bukkit/util/CachedServerIcon;"; + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "loadServerIcon", sig.as_str(), args); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::util::CachedServerIcon::from_raw(&jni, obj) + } + /// Set the idle kick timeout. Any players idle for the specified amount of + /// time will be automatically kicked. /// - pub fn plugin_chunk_tickets( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPluginChunkTickets", + /// A value of 0 will disable the idle kick timeout. + pub fn set_idle_timeout( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + threshold: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(threshold); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "setIdleTimeout", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + jni.translate_error(res)?; + Ok(()) } - /// Gets all Chunks intersecting the given BoundingBox. - pub fn get_intersecting_chunks( - &self, - val_box: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/util/BoundingBox;)Ljava/util/Collection;"); + /// Gets the idle kick timeout. + pub fn idle_timeout( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()I"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getIdleTimeout", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.i()?) + } + /// Create a ChunkData for use in a generator. + /// See {@link ChunkGenerator#generateChunkData(org.bukkit.World, java.util.Random, int, int, org.bukkit.generator.ChunkGenerator.BiomeGrid)} + pub fn create_chunk_data( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + world: impl Into>, + ) -> Result, Box> { + let sig = + String::from("(Lorg/bukkit/World;)Lorg/bukkit/generator/ChunkGenerator/ChunkData;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_box.into().jni_object().clone()) + jni::objects::JObject::from_raw(world.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getIntersectingChunks", + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "createChunkData", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::Chunk::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::generator::ChunkGeneratorChunkData::from_raw(&jni, obj) } - /// Drops an item at the specified {@link Location} - /// Note that functions will run before the entity is spawned - pub fn drop_item( - &self, - location: impl Into>, - item: impl Into>, - function: std::option::Option< - impl Into>, - >, - ) -> Result, Box> { + /// Creates a boss bar instance to display to players. The progress defaults + /// to 1.0. + /// + /// This instance is added to the persistent storage of the server and will + /// be editable by commands and restored after restart. + pub fn create_boss_bar( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + key: impl Into>, + title: impl Into, + color: impl Into>, + style: impl Into>, + flags: std::option::Option>>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; + sig += "Lorg/bukkit/NamespacedKey;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) + jni::objects::JObject::from_raw(key.into().jni_object().clone()) }); args.push(val_1); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) - }); + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(title.into())?, + )); args.push(val_2); - if let Some(a) = function { - sig += "Ljava/util/function/Consumer;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_3); - } - sig += ")Lorg/bukkit/entity/Item;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "dropItem", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Item::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Drops an item at the specified {@link Location} with a random offset - /// Note that functions will run before the entity is spawned - pub fn drop_item_naturally( - &self, - location: impl Into>, - item: impl Into>, - function: std::option::Option< - impl Into>, - >, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) + sig += "Lorg/bukkit/boss/BarColor;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(color.into().jni_object().clone()) }); - args.push(val_1); - sig += "Lorg/bukkit/inventory/ItemStack;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(item.into().jni_object().clone()) + args.push(val_3); + sig += "Lorg/bukkit/boss/BarStyle;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(style.into().jni_object().clone()) }); - args.push(val_2); - if let Some(a) = function { - sig += "Ljava/util/function/Consumer;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { + args.push(val_4); + if let Some(a) = flags { + sig += "Lorg/bukkit/boss/BarFlag;"; + let val_5 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); - args.push(val_3); - } - sig += ")Lorg/bukkit/entity/Item;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "dropItemNaturally", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::entity::Item::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Creates an arrow entity of the given class at the given {@link Location} - pub fn spawn_arrow( - &self, - location: impl Into>, - direction: impl Into>, - speed: f32, - spread: f32, - clazz: std::option::Option>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/util/Vector;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(direction.into().jni_object().clone()) - }); - args.push(val_2); - sig += "F"; - let val_3 = jni::objects::JValueGen::Float(speed); - args.push(val_3); - sig += "F"; - let val_4 = jni::objects::JValueGen::Float(spread); - args.push(val_4); - if let Some(a) = clazz { - sig += "Ljava/lang/Class;"; - let val_5 = jni::objects::JValueGen::Object(a.into()); args.push(val_5); } - sig += ")LT;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "spawnArrow", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) + sig += ")Lorg/bukkit/boss/KeyedBossBar;"; + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "createBossBar", sig.as_str(), args); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::boss::KeyedBossBar::from_raw(&jni, obj) } - /// Creates a tree at the given {@link Location} - /// - /// The provided predicate gets called for every block which gets changed - /// as a result of the tree generation. When the predicate gets called no - /// modifications to the world are done yet. Which means, that calling - /// {@link #getBlockState(Location)} in the predicate will return the state - /// of the block before the generation. - /// - /// If the predicate returns {@code true} the block gets set in the world. - /// If it returns {@code false} the block won't get set in the world. - pub fn generate_tree( - &self, - location: impl Into>, - random: impl Into>, - val_type: std::option::Option>>, - state_predicate: std::option::Option< - impl Into>, - >, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Ljava/util/Random;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(random.into().jni_object().clone()) - }); - args.push(val_2); - if let Some(a) = val_type { - sig += "Lorg/bukkit/TreeType;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_3); - } - if let Some(a) = state_predicate { - sig += "Ljava/util/function/Predicate;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_4); - } - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "generateTree", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + /// Gets an unmodifiable iterator through all persistent bossbars. + ///
      + ///
    • not bound to a {@link org.bukkit.entity.Boss}
    • + ///
    • + /// not created using + /// {@link #createBossBar(String, BarColor, BarStyle, BarFlag...)} + ///
    • + ///
    + /// e.g. bossbars created using the bossbar command + pub fn boss_bars( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Iterator;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getBossBars", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + blackboxmc_java::util::JavaIterator::from_raw(&jni, obj) } - /// Strikes lightning at the given {@link Location} - pub fn strike_lightning( - &self, - loc: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/entity/LightningStrike;"); + /// Gets the {@link KeyedBossBar} specified by this key. + ///
      + ///
    • not bound to a {@link org.bukkit.entity.Boss}
    • + ///
    • + /// not created using + /// {@link #createBossBar(String, BarColor, BarStyle, BarFlag...)} + ///
    • + ///
    + /// e.g. bossbars created using the bossbar command + pub fn get_boss_bar( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/boss/KeyedBossBar;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + jni::objects::JObject::from_raw(key.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "strikeLightning", + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getBossBar", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::entity::LightningStrike::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::boss::KeyedBossBar::from_raw(&jni, obj)?)) } - /// Strikes lightning at the given {@link Location} without doing damage - pub fn strike_lightning_effect( - &self, - loc: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/Location;)Lorg/bukkit/entity/LightningStrike;"); + /// Removes a {@link KeyedBossBar} specified by this key. + ///
      + ///
    • not bound to a {@link org.bukkit.entity.Boss}
    • + ///
    • + /// not created using + /// {@link #createBossBar(String, BarColor, BarStyle, BarFlag...)} + ///
    • + ///
    + /// e.g. bossbars created using the bossbar command + pub fn remove_boss_bar( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + key: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + jni::objects::JObject::from_raw(key.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "strikeLightningEffect", + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "removeBossBar", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::entity::LightningStrike::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get a list of all entities in this RegionAccessor - pub fn entities(&self) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/List;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getEntities", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Get a list of all living entities in this RegionAccessor - pub fn living_entities( - &self, - ) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/List;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLivingEntities", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::LivingEntity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + let res = jni.translate_error(res)?; + Ok(res.z()?) } - /// Get a collection of all entities in this RegionAccessor matching the given - /// class/interface - pub fn get_entities_by_class( - &self, - cls: jni::objects::JClass<'mc>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/Class;"; - let val_1 = jni::objects::JValueGen::Object(cls.into()); - args.push(val_1); - sig += ")Ljava/util/Collection;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getEntitiesByClass", + /// Gets an entity on the server by its UUID + pub fn get_entity( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + uuid: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/UUID;)Lorg/bukkit/entity/Entity;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getEntity", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(obj); + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - Ok(new_vec) + let obj = res.l()?; + Ok(Some(crate::entity::Entity::from_raw(&jni, obj)?)) } - /// Get a collection of all entities in this RegionAccessor matching any of the - /// given classes/interfaces - pub fn get_entities_by_classes( - &self, - classes: jni::objects::JClass<'mc>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/Class;"; - let val_1 = jni::objects::JValueGen::Object(classes.into()); - args.push(val_1); - sig += ")Ljava/util/Collection;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getEntitiesByClasses", + /// Get the advancement specified by this key. + pub fn get_advancement( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/advancement/Advancement;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(key.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getAdvancement", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Get a list of all players in this World - pub fn players(&self) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPlayers", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Player::from_raw(&self.jni_ref(), obj)?); + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - Ok(new_vec) + let obj = res.l()?; + Ok(Some(crate::advancement::Advancement::from_raw(&jni, obj)?)) } - /// Returns a list of entities within a bounding box centered around a - /// Location. - /// - /// This may not consider entities in currently unloaded chunks. Some - /// implementations may impose artificial restrictions on the size of the - /// search bounding box. - pub fn get_nearby_entities( - &self, - location: impl Into>, - x: std::option::Option, - y: std::option::Option, - z: std::option::Option, - filter: std::option::Option>>, - ) -> Result>, Box> { + /// Get an iterator through all advancements. Advancements cannot be removed + /// from this iterator, + pub fn advancement_iterator( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Iterator;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "advancementIterator", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + blackboxmc_java::util::JavaIterator::from_raw(&jni, obj) + } + /// Creates a new {@link BlockData} instance for the specified Material, with + /// all properties initialized to unspecified defaults, except for those + /// provided in data. + pub fn create_block_data( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + material: impl Into>, + data: std::option::Option>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; + sig += "Lorg/bukkit/Material;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) + jni::objects::JObject::from_raw(material.into().jni_object().clone()) }); args.push(val_1); - if let Some(a) = x { - sig += "D"; - let val_2 = jni::objects::JValueGen::Double(a); + if let Some(a) = data { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(a.into())?, + )); args.push(val_2); } - if let Some(a) = y { - sig += "D"; - let val_3 = jni::objects::JValueGen::Double(a); - args.push(val_3); - } - if let Some(a) = z { - sig += "D"; - let val_4 = jni::objects::JValueGen::Double(a); - args.push(val_4); - } - if let Some(a) = filter { - sig += "Ljava/util/function/Predicate;"; - let val_5 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_5); - } - sig += ")Ljava/util/Collection;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getNearbyEntities", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + sig += ")Lorg/bukkit/block/data/BlockData;"; + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "createBlockData", sig.as_str(), args); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::block::data::BlockData::from_raw(&jni, obj) } - /// Performs a ray trace that checks for entity collisions. + /// Gets a tag which has already been defined within the server. Plugins are + /// suggested to use the concrete tags in {@link Tag} rather than this method + /// which makes no guarantees about which tags are available, and may also be + /// less performant due to lack of caching. /// - /// This may not consider entities in currently unloaded chunks. Some - /// implementations may impose artificial restrictions on the maximum - /// distance. - pub fn ray_trace_entities( - &self, - start: impl Into>, - direction: impl Into>, - max_distance: f64, - ray_size: std::option::Option, - filter: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(start.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/util/Vector;"; + /// Tags will be searched for in an implementation specific manner, but a + /// path consisting of namespace/tags/registry/key is expected. + /// + /// Server implementations are allowed to handle only the registries + /// indicated in {@link Tag}. + pub fn get_tag( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + registry: impl Into, + tag: impl Into>, + clazz: jni::objects::JClass<'mc>, + ) -> Result>, Box> { + let sig = String::from( + "(Ljava/lang/String;Lorg/bukkit/NamespacedKey;Ljava/lang/Class;)Lorg/bukkit/Tag;", + ); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(registry.into())?, + )); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(direction.into().jni_object().clone()) + jni::objects::JObject::from_raw(tag.into().jni_object().clone()) }); - args.push(val_2); - sig += "D"; - let val_3 = jni::objects::JValueGen::Double(max_distance); - args.push(val_3); - if let Some(a) = ray_size { - sig += "D"; - let val_4 = jni::objects::JValueGen::Double(a); - args.push(val_4); - } - if let Some(a) = filter { - sig += "Ljava/util/function/Predicate;"; - let val_5 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_5); - } - sig += ")Lorg/bukkit/util/RayTraceResult;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "rayTraceEntities", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; + let val_3 = jni::objects::JValueGen::Object(clazz.into()); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getTag", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = jni.translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::util::RayTraceResult::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + let obj = res.l()?; + Ok(Some(crate::Tag::from_raw(&jni, obj)?)) } - /// Performs a ray trace that checks for block collisions using the blocks' - /// precise collision shapes. - /// - /// If collisions with passable blocks are ignored, fluid collisions are - /// ignored as well regardless of the fluid collision mode. - /// - /// Portal blocks are only considered passable if the ray starts within - /// them. Apart from that collisions with portal blocks will be considered - /// even if collisions with passable blocks are otherwise ignored. - /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn ray_trace_blocks( - &self, - start: impl Into>, - direction: impl Into>, - max_distance: f64, - fluid_collision_mode: std::option::Option>>, - ignore_passable_blocks: std::option::Option, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; + /// Gets the specified {@link LootTable}. + pub fn get_loot_table( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/loot/LootTable;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(start.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/util/Vector;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(direction.into().jni_object().clone()) + jni::objects::JObject::from_raw(key.into().jni_object().clone()) }); - args.push(val_2); - sig += "D"; - let val_3 = jni::objects::JValueGen::Double(max_distance); - args.push(val_3); - if let Some(a) = fluid_collision_mode { - sig += "Lorg/bukkit/FluidCollisionMode;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_4); - } - if let Some(a) = ignore_passable_blocks { - sig += "Z"; - let val_5 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_5); - } - sig += ")Lorg/bukkit/util/RayTraceResult;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "rayTraceBlocks", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getLootTable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::util::RayTraceResult::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + let obj = res.l()?; + Ok(Some(crate::loot::LootTable::from_raw(&jni, obj)?)) } - /// Performs a ray trace that checks for both block and entity collisions. - /// - /// Block collisions use the blocks' precise collision shapes. The - /// raySize parameter is only taken into account for entity - /// collision checks. + /// Selects entities using the given Vanilla selector. /// - /// If collisions with passable blocks are ignored, fluid collisions are - /// ignored as well regardless of the fluid collision mode. + /// No guarantees are made about the selector format, other than they match + /// the Vanilla format for the active Minecraft version. /// - /// Portal blocks are only considered passable if the ray starts within them. - /// Apart from that collisions with portal blocks will be considered even if - /// collisions with passable blocks are otherwise ignored. + /// Usually a selector will start with '@', unless selecting a Player in + /// which case it may simply be the Player's name or UUID. /// - /// This may cause loading of chunks! Some implementations may impose - /// artificial restrictions on the maximum distance. - pub fn ray_trace( - &self, - start: impl Into>, - direction: impl Into>, - max_distance: f64, - fluid_collision_mode: impl Into>, - ignore_passable_blocks: bool, - ray_size: f64, - filter: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;Lorg/bukkit/util/Vector;DLorg/bukkit/FluidCollisionMode;ZDLjava/util/function/Predicate;)Lorg/bukkit/util/RayTraceResult;"); + /// Note that in Vanilla, elevated permissions are usually required to use + /// '@' selectors, but this method should not check such permissions from the + /// sender. + pub fn select_entities( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + sender: impl Into>, + selector: impl Into, + ) -> Result>, Box> { + let sig = + String::from("(Lorg/bukkit/command/CommandSender;Ljava/lang/String;)Ljava/util/List;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(start.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(direction.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Double(max_distance); - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(fluid_collision_mode.into().jni_object().clone()) - }); - let val_5 = jni::objects::JValueGen::Bool(ignore_passable_blocks.into()); - let val_6 = jni::objects::JValueGen::Double(ray_size); - let val_7 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(filter.into().jni_object().clone()) + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "rayTrace", + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(selector.into())?, + )); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "selectEntities", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - jni::objects::JValueGen::from(val_5), - jni::objects::JValueGen::from(val_6), - jni::objects::JValueGen::from(val_7), ], ); - let res = self.jni_ref().translate_error(res)?; + let res = jni.translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&jni, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&jni, obj)?); + } + Ok(new_vec) + } + /// Gets the structure manager for loading and saving structures. + pub fn structure_manager( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/structure/StructureManager;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getStructureManager", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::structure::StructureManager::from_raw(&jni, obj) + } + /// Returns the registry for the given class. + /// + /// If no registry is present for the given class null will be returned. + /// + /// Depending on the implementation not every registry present in + /// {@link Registry} will be returned by this method. + pub fn get_registry( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + t_class: jni::objects::JClass<'mc>, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/Class;)Lorg/bukkit/Registry;"); + let val_1 = jni::objects::JValueGen::Object(t_class.into()); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getRegistry", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::util::RayTraceResult::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + let obj = res.l()?; + Ok(Some(crate::Registry::from_raw(&jni, obj)?)) + } + #[deprecated] + + pub fn get_unsafe( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/UnsafeValues;"); + let cls = jni.find_class("org/bukkit/Bukkit"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getUnsafe", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::UnsafeValues::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +pub enum Art<'mc> { + Kebab { inner: ArtStruct<'mc> }, + Aztec { inner: ArtStruct<'mc> }, + Alban { inner: ArtStruct<'mc> }, + Aztec2 { inner: ArtStruct<'mc> }, + Bomb { inner: ArtStruct<'mc> }, + Plant { inner: ArtStruct<'mc> }, + Wasteland { inner: ArtStruct<'mc> }, + Pool { inner: ArtStruct<'mc> }, + Courbet { inner: ArtStruct<'mc> }, + Sea { inner: ArtStruct<'mc> }, + Sunset { inner: ArtStruct<'mc> }, + Creebet { inner: ArtStruct<'mc> }, + Wanderer { inner: ArtStruct<'mc> }, + Graham { inner: ArtStruct<'mc> }, + VariantMatch { inner: ArtStruct<'mc> }, + Bust { inner: ArtStruct<'mc> }, + Stage { inner: ArtStruct<'mc> }, + Void { inner: ArtStruct<'mc> }, + SkullAndRoses { inner: ArtStruct<'mc> }, + Wither { inner: ArtStruct<'mc> }, + Fighters { inner: ArtStruct<'mc> }, + Pointer { inner: ArtStruct<'mc> }, + Pigscene { inner: ArtStruct<'mc> }, + BurningSkull { inner: ArtStruct<'mc> }, + Skeleton { inner: ArtStruct<'mc> }, + DonkeyKong { inner: ArtStruct<'mc> }, + Earth { inner: ArtStruct<'mc> }, + Wind { inner: ArtStruct<'mc> }, + Water { inner: ArtStruct<'mc> }, + Fire { inner: ArtStruct<'mc> }, + Baroque { inner: ArtStruct<'mc> }, + Humble { inner: ArtStruct<'mc> }, + Meditative { inner: ArtStruct<'mc> }, + PrairieRide { inner: ArtStruct<'mc> }, + Unpacked { inner: ArtStruct<'mc> }, + Backyard { inner: ArtStruct<'mc> }, + Bouquet { inner: ArtStruct<'mc> }, + Cavebird { inner: ArtStruct<'mc> }, + Changing { inner: ArtStruct<'mc> }, + Cotan { inner: ArtStruct<'mc> }, + Endboss { inner: ArtStruct<'mc> }, + Fern { inner: ArtStruct<'mc> }, + Finding { inner: ArtStruct<'mc> }, + Lowmist { inner: ArtStruct<'mc> }, + Orb { inner: ArtStruct<'mc> }, + Owlemons { inner: ArtStruct<'mc> }, + Passage { inner: ArtStruct<'mc> }, + Pond { inner: ArtStruct<'mc> }, + Sunflowers { inner: ArtStruct<'mc> }, + Tides { inner: ArtStruct<'mc> }, +} +impl<'mc> std::fmt::Display for Art<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Art::Kebab { .. } => f.write_str("KEBAB"), + Art::Aztec { .. } => f.write_str("AZTEC"), + Art::Alban { .. } => f.write_str("ALBAN"), + Art::Aztec2 { .. } => f.write_str("AZTEC2"), + Art::Bomb { .. } => f.write_str("BOMB"), + Art::Plant { .. } => f.write_str("PLANT"), + Art::Wasteland { .. } => f.write_str("WASTELAND"), + Art::Pool { .. } => f.write_str("POOL"), + Art::Courbet { .. } => f.write_str("COURBET"), + Art::Sea { .. } => f.write_str("SEA"), + Art::Sunset { .. } => f.write_str("SUNSET"), + Art::Creebet { .. } => f.write_str("CREEBET"), + Art::Wanderer { .. } => f.write_str("WANDERER"), + Art::Graham { .. } => f.write_str("GRAHAM"), + Art::VariantMatch { .. } => f.write_str("MATCH"), + Art::Bust { .. } => f.write_str("BUST"), + Art::Stage { .. } => f.write_str("STAGE"), + Art::Void { .. } => f.write_str("VOID"), + Art::SkullAndRoses { .. } => f.write_str("SKULL_AND_ROSES"), + Art::Wither { .. } => f.write_str("WITHER"), + Art::Fighters { .. } => f.write_str("FIGHTERS"), + Art::Pointer { .. } => f.write_str("POINTER"), + Art::Pigscene { .. } => f.write_str("PIGSCENE"), + Art::BurningSkull { .. } => f.write_str("BURNING_SKULL"), + Art::Skeleton { .. } => f.write_str("SKELETON"), + Art::DonkeyKong { .. } => f.write_str("DONKEY_KONG"), + Art::Earth { .. } => f.write_str("EARTH"), + Art::Wind { .. } => f.write_str("WIND"), + Art::Water { .. } => f.write_str("WATER"), + Art::Fire { .. } => f.write_str("FIRE"), + Art::Baroque { .. } => f.write_str("BAROQUE"), + Art::Humble { .. } => f.write_str("HUMBLE"), + Art::Meditative { .. } => f.write_str("MEDITATIVE"), + Art::PrairieRide { .. } => f.write_str("PRAIRIE_RIDE"), + Art::Unpacked { .. } => f.write_str("UNPACKED"), + Art::Backyard { .. } => f.write_str("BACKYARD"), + Art::Bouquet { .. } => f.write_str("BOUQUET"), + Art::Cavebird { .. } => f.write_str("CAVEBIRD"), + Art::Changing { .. } => f.write_str("CHANGING"), + Art::Cotan { .. } => f.write_str("COTAN"), + Art::Endboss { .. } => f.write_str("ENDBOSS"), + Art::Fern { .. } => f.write_str("FERN"), + Art::Finding { .. } => f.write_str("FINDING"), + Art::Lowmist { .. } => f.write_str("LOWMIST"), + Art::Orb { .. } => f.write_str("ORB"), + Art::Owlemons { .. } => f.write_str("OWLEMONS"), + Art::Passage { .. } => f.write_str("PASSAGE"), + Art::Pond { .. } => f.write_str("POND"), + Art::Sunflowers { .. } => f.write_str("SUNFLOWERS"), + Art::Tides { .. } => f.write_str("TIDES"), + } + } +} +impl<'mc> std::ops::Deref for Art<'mc> { + type Target = ArtStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + Art::Kebab { inner } => inner, + Art::Aztec { inner } => inner, + Art::Alban { inner } => inner, + Art::Aztec2 { inner } => inner, + Art::Bomb { inner } => inner, + Art::Plant { inner } => inner, + Art::Wasteland { inner } => inner, + Art::Pool { inner } => inner, + Art::Courbet { inner } => inner, + Art::Sea { inner } => inner, + Art::Sunset { inner } => inner, + Art::Creebet { inner } => inner, + Art::Wanderer { inner } => inner, + Art::Graham { inner } => inner, + Art::VariantMatch { inner } => inner, + Art::Bust { inner } => inner, + Art::Stage { inner } => inner, + Art::Void { inner } => inner, + Art::SkullAndRoses { inner } => inner, + Art::Wither { inner } => inner, + Art::Fighters { inner } => inner, + Art::Pointer { inner } => inner, + Art::Pigscene { inner } => inner, + Art::BurningSkull { inner } => inner, + Art::Skeleton { inner } => inner, + Art::DonkeyKong { inner } => inner, + Art::Earth { inner } => inner, + Art::Wind { inner } => inner, + Art::Water { inner } => inner, + Art::Fire { inner } => inner, + Art::Baroque { inner } => inner, + Art::Humble { inner } => inner, + Art::Meditative { inner } => inner, + Art::PrairieRide { inner } => inner, + Art::Unpacked { inner } => inner, + Art::Backyard { inner } => inner, + Art::Bouquet { inner } => inner, + Art::Cavebird { inner } => inner, + Art::Changing { inner } => inner, + Art::Cotan { inner } => inner, + Art::Endboss { inner } => inner, + Art::Fern { inner } => inner, + Art::Finding { inner } => inner, + Art::Lowmist { inner } => inner, + Art::Orb { inner } => inner, + Art::Owlemons { inner } => inner, + Art::Passage { inner } => inner, + Art::Pond { inner } => inner, + Art::Sunflowers { inner } => inner, + Art::Tides { inner } => inner, + } + } +} + +impl<'mc> Art<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/Art"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/Art;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "KEBAB" => Ok(Art::Kebab { + inner: ArtStruct::from_raw(env, obj)?, + }), + "AZTEC" => Ok(Art::Aztec { + inner: ArtStruct::from_raw(env, obj)?, + }), + "ALBAN" => Ok(Art::Alban { + inner: ArtStruct::from_raw(env, obj)?, + }), + "AZTEC2" => Ok(Art::Aztec2 { + inner: ArtStruct::from_raw(env, obj)?, + }), + "BOMB" => Ok(Art::Bomb { + inner: ArtStruct::from_raw(env, obj)?, + }), + "PLANT" => Ok(Art::Plant { + inner: ArtStruct::from_raw(env, obj)?, + }), + "WASTELAND" => Ok(Art::Wasteland { + inner: ArtStruct::from_raw(env, obj)?, + }), + "POOL" => Ok(Art::Pool { + inner: ArtStruct::from_raw(env, obj)?, + }), + "COURBET" => Ok(Art::Courbet { + inner: ArtStruct::from_raw(env, obj)?, + }), + "SEA" => Ok(Art::Sea { + inner: ArtStruct::from_raw(env, obj)?, + }), + "SUNSET" => Ok(Art::Sunset { + inner: ArtStruct::from_raw(env, obj)?, + }), + "CREEBET" => Ok(Art::Creebet { + inner: ArtStruct::from_raw(env, obj)?, + }), + "WANDERER" => Ok(Art::Wanderer { + inner: ArtStruct::from_raw(env, obj)?, + }), + "GRAHAM" => Ok(Art::Graham { + inner: ArtStruct::from_raw(env, obj)?, + }), + "MATCH" => Ok(Art::VariantMatch { + inner: ArtStruct::from_raw(env, obj)?, + }), + "BUST" => Ok(Art::Bust { + inner: ArtStruct::from_raw(env, obj)?, + }), + "STAGE" => Ok(Art::Stage { + inner: ArtStruct::from_raw(env, obj)?, + }), + "VOID" => Ok(Art::Void { + inner: ArtStruct::from_raw(env, obj)?, + }), + "SKULL_AND_ROSES" => Ok(Art::SkullAndRoses { + inner: ArtStruct::from_raw(env, obj)?, + }), + "WITHER" => Ok(Art::Wither { + inner: ArtStruct::from_raw(env, obj)?, + }), + "FIGHTERS" => Ok(Art::Fighters { + inner: ArtStruct::from_raw(env, obj)?, + }), + "POINTER" => Ok(Art::Pointer { + inner: ArtStruct::from_raw(env, obj)?, + }), + "PIGSCENE" => Ok(Art::Pigscene { + inner: ArtStruct::from_raw(env, obj)?, + }), + "BURNING_SKULL" => Ok(Art::BurningSkull { + inner: ArtStruct::from_raw(env, obj)?, + }), + "SKELETON" => Ok(Art::Skeleton { + inner: ArtStruct::from_raw(env, obj)?, + }), + "DONKEY_KONG" => Ok(Art::DonkeyKong { + inner: ArtStruct::from_raw(env, obj)?, + }), + "EARTH" => Ok(Art::Earth { + inner: ArtStruct::from_raw(env, obj)?, + }), + "WIND" => Ok(Art::Wind { + inner: ArtStruct::from_raw(env, obj)?, + }), + "WATER" => Ok(Art::Water { + inner: ArtStruct::from_raw(env, obj)?, + }), + "FIRE" => Ok(Art::Fire { + inner: ArtStruct::from_raw(env, obj)?, + }), + "BAROQUE" => Ok(Art::Baroque { + inner: ArtStruct::from_raw(env, obj)?, + }), + "HUMBLE" => Ok(Art::Humble { + inner: ArtStruct::from_raw(env, obj)?, + }), + "MEDITATIVE" => Ok(Art::Meditative { + inner: ArtStruct::from_raw(env, obj)?, + }), + "PRAIRIE_RIDE" => Ok(Art::PrairieRide { + inner: ArtStruct::from_raw(env, obj)?, + }), + "UNPACKED" => Ok(Art::Unpacked { + inner: ArtStruct::from_raw(env, obj)?, + }), + "BACKYARD" => Ok(Art::Backyard { + inner: ArtStruct::from_raw(env, obj)?, + }), + "BOUQUET" => Ok(Art::Bouquet { + inner: ArtStruct::from_raw(env, obj)?, + }), + "CAVEBIRD" => Ok(Art::Cavebird { + inner: ArtStruct::from_raw(env, obj)?, + }), + "CHANGING" => Ok(Art::Changing { + inner: ArtStruct::from_raw(env, obj)?, + }), + "COTAN" => Ok(Art::Cotan { + inner: ArtStruct::from_raw(env, obj)?, + }), + "ENDBOSS" => Ok(Art::Endboss { + inner: ArtStruct::from_raw(env, obj)?, + }), + "FERN" => Ok(Art::Fern { + inner: ArtStruct::from_raw(env, obj)?, + }), + "FINDING" => Ok(Art::Finding { + inner: ArtStruct::from_raw(env, obj)?, + }), + "LOWMIST" => Ok(Art::Lowmist { + inner: ArtStruct::from_raw(env, obj)?, + }), + "ORB" => Ok(Art::Orb { + inner: ArtStruct::from_raw(env, obj)?, + }), + "OWLEMONS" => Ok(Art::Owlemons { + inner: ArtStruct::from_raw(env, obj)?, + }), + "PASSAGE" => Ok(Art::Passage { + inner: ArtStruct::from_raw(env, obj)?, + }), + "POND" => Ok(Art::Pond { + inner: ArtStruct::from_raw(env, obj)?, + }), + "SUNFLOWERS" => Ok(Art::Sunflowers { + inner: ArtStruct::from_raw(env, obj)?, + }), + "TIDES" => Ok(Art::Tides { + inner: ArtStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct ArtStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Art<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Kebab { inner } => inner.0.clone(), + Self::Aztec { inner } => inner.0.clone(), + Self::Alban { inner } => inner.0.clone(), + Self::Aztec2 { inner } => inner.0.clone(), + Self::Bomb { inner } => inner.0.clone(), + Self::Plant { inner } => inner.0.clone(), + Self::Wasteland { inner } => inner.0.clone(), + Self::Pool { inner } => inner.0.clone(), + Self::Courbet { inner } => inner.0.clone(), + Self::Sea { inner } => inner.0.clone(), + Self::Sunset { inner } => inner.0.clone(), + Self::Creebet { inner } => inner.0.clone(), + Self::Wanderer { inner } => inner.0.clone(), + Self::Graham { inner } => inner.0.clone(), + Self::VariantMatch { inner } => inner.0.clone(), + Self::Bust { inner } => inner.0.clone(), + Self::Stage { inner } => inner.0.clone(), + Self::Void { inner } => inner.0.clone(), + Self::SkullAndRoses { inner } => inner.0.clone(), + Self::Wither { inner } => inner.0.clone(), + Self::Fighters { inner } => inner.0.clone(), + Self::Pointer { inner } => inner.0.clone(), + Self::Pigscene { inner } => inner.0.clone(), + Self::BurningSkull { inner } => inner.0.clone(), + Self::Skeleton { inner } => inner.0.clone(), + Self::DonkeyKong { inner } => inner.0.clone(), + Self::Earth { inner } => inner.0.clone(), + Self::Wind { inner } => inner.0.clone(), + Self::Water { inner } => inner.0.clone(), + Self::Fire { inner } => inner.0.clone(), + Self::Baroque { inner } => inner.0.clone(), + Self::Humble { inner } => inner.0.clone(), + Self::Meditative { inner } => inner.0.clone(), + Self::PrairieRide { inner } => inner.0.clone(), + Self::Unpacked { inner } => inner.0.clone(), + Self::Backyard { inner } => inner.0.clone(), + Self::Bouquet { inner } => inner.0.clone(), + Self::Cavebird { inner } => inner.0.clone(), + Self::Changing { inner } => inner.0.clone(), + Self::Cotan { inner } => inner.0.clone(), + Self::Endboss { inner } => inner.0.clone(), + Self::Fern { inner } => inner.0.clone(), + Self::Finding { inner } => inner.0.clone(), + Self::Lowmist { inner } => inner.0.clone(), + Self::Orb { inner } => inner.0.clone(), + Self::Owlemons { inner } => inner.0.clone(), + Self::Passage { inner } => inner.0.clone(), + Self::Pond { inner } => inner.0.clone(), + Self::Sunflowers { inner } => inner.0.clone(), + Self::Tides { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Kebab { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Aztec { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Alban { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Aztec2 { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Bomb { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Plant { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Wasteland { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Pool { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Courbet { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Sea { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Sunset { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Creebet { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Wanderer { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Graham { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::VariantMatch { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Bust { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Stage { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Void { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SkullAndRoses { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Wither { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Fighters { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Pointer { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Pigscene { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BurningSkull { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Skeleton { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DonkeyKong { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Earth { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Wind { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Water { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Fire { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Baroque { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Humble { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Meditative { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PrairieRide { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Unpacked { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Backyard { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Bouquet { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Cavebird { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Changing { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Cotan { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Endboss { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Fern { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Finding { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Lowmist { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Orb { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Owlemons { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Passage { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Pond { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Sunflowers { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Tides { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for Art<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Art from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Art")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Art object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "KEBAB" => Ok(Art::Kebab { + inner: ArtStruct::from_raw(env, obj)?, + }), + "AZTEC" => Ok(Art::Aztec { + inner: ArtStruct::from_raw(env, obj)?, + }), + "ALBAN" => Ok(Art::Alban { + inner: ArtStruct::from_raw(env, obj)?, + }), + "AZTEC2" => Ok(Art::Aztec2 { + inner: ArtStruct::from_raw(env, obj)?, + }), + "BOMB" => Ok(Art::Bomb { + inner: ArtStruct::from_raw(env, obj)?, + }), + "PLANT" => Ok(Art::Plant { + inner: ArtStruct::from_raw(env, obj)?, + }), + "WASTELAND" => Ok(Art::Wasteland { + inner: ArtStruct::from_raw(env, obj)?, + }), + "POOL" => Ok(Art::Pool { + inner: ArtStruct::from_raw(env, obj)?, + }), + "COURBET" => Ok(Art::Courbet { + inner: ArtStruct::from_raw(env, obj)?, + }), + "SEA" => Ok(Art::Sea { + inner: ArtStruct::from_raw(env, obj)?, + }), + "SUNSET" => Ok(Art::Sunset { + inner: ArtStruct::from_raw(env, obj)?, + }), + "CREEBET" => Ok(Art::Creebet { + inner: ArtStruct::from_raw(env, obj)?, + }), + "WANDERER" => Ok(Art::Wanderer { + inner: ArtStruct::from_raw(env, obj)?, + }), + "GRAHAM" => Ok(Art::Graham { + inner: ArtStruct::from_raw(env, obj)?, + }), + "MATCH" => Ok(Art::VariantMatch { + inner: ArtStruct::from_raw(env, obj)?, + }), + "BUST" => Ok(Art::Bust { + inner: ArtStruct::from_raw(env, obj)?, + }), + "STAGE" => Ok(Art::Stage { + inner: ArtStruct::from_raw(env, obj)?, + }), + "VOID" => Ok(Art::Void { + inner: ArtStruct::from_raw(env, obj)?, + }), + "SKULL_AND_ROSES" => Ok(Art::SkullAndRoses { + inner: ArtStruct::from_raw(env, obj)?, + }), + "WITHER" => Ok(Art::Wither { + inner: ArtStruct::from_raw(env, obj)?, + }), + "FIGHTERS" => Ok(Art::Fighters { + inner: ArtStruct::from_raw(env, obj)?, + }), + "POINTER" => Ok(Art::Pointer { + inner: ArtStruct::from_raw(env, obj)?, + }), + "PIGSCENE" => Ok(Art::Pigscene { + inner: ArtStruct::from_raw(env, obj)?, + }), + "BURNING_SKULL" => Ok(Art::BurningSkull { + inner: ArtStruct::from_raw(env, obj)?, + }), + "SKELETON" => Ok(Art::Skeleton { + inner: ArtStruct::from_raw(env, obj)?, + }), + "DONKEY_KONG" => Ok(Art::DonkeyKong { + inner: ArtStruct::from_raw(env, obj)?, + }), + "EARTH" => Ok(Art::Earth { + inner: ArtStruct::from_raw(env, obj)?, + }), + "WIND" => Ok(Art::Wind { + inner: ArtStruct::from_raw(env, obj)?, + }), + "WATER" => Ok(Art::Water { + inner: ArtStruct::from_raw(env, obj)?, + }), + "FIRE" => Ok(Art::Fire { + inner: ArtStruct::from_raw(env, obj)?, + }), + "BAROQUE" => Ok(Art::Baroque { + inner: ArtStruct::from_raw(env, obj)?, + }), + "HUMBLE" => Ok(Art::Humble { + inner: ArtStruct::from_raw(env, obj)?, + }), + "MEDITATIVE" => Ok(Art::Meditative { + inner: ArtStruct::from_raw(env, obj)?, + }), + "PRAIRIE_RIDE" => Ok(Art::PrairieRide { + inner: ArtStruct::from_raw(env, obj)?, + }), + "UNPACKED" => Ok(Art::Unpacked { + inner: ArtStruct::from_raw(env, obj)?, + }), + "BACKYARD" => Ok(Art::Backyard { + inner: ArtStruct::from_raw(env, obj)?, + }), + "BOUQUET" => Ok(Art::Bouquet { + inner: ArtStruct::from_raw(env, obj)?, + }), + "CAVEBIRD" => Ok(Art::Cavebird { + inner: ArtStruct::from_raw(env, obj)?, + }), + "CHANGING" => Ok(Art::Changing { + inner: ArtStruct::from_raw(env, obj)?, + }), + "COTAN" => Ok(Art::Cotan { + inner: ArtStruct::from_raw(env, obj)?, + }), + "ENDBOSS" => Ok(Art::Endboss { + inner: ArtStruct::from_raw(env, obj)?, + }), + "FERN" => Ok(Art::Fern { + inner: ArtStruct::from_raw(env, obj)?, + }), + "FINDING" => Ok(Art::Finding { + inner: ArtStruct::from_raw(env, obj)?, + }), + "LOWMIST" => Ok(Art::Lowmist { + inner: ArtStruct::from_raw(env, obj)?, + }), + "ORB" => Ok(Art::Orb { + inner: ArtStruct::from_raw(env, obj)?, + }), + "OWLEMONS" => Ok(Art::Owlemons { + inner: ArtStruct::from_raw(env, obj)?, + }), + "PASSAGE" => Ok(Art::Passage { + inner: ArtStruct::from_raw(env, obj)?, + }), + "POND" => Ok(Art::Pond { + inner: ArtStruct::from_raw(env, obj)?, + }), + "SUNFLOWERS" => Ok(Art::Sunflowers { + inner: ArtStruct::from_raw(env, obj)?, + }), + "TIDES" => Ok(Art::Tides { + inner: ArtStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } } - /// Gets the default spawn {@link Location} of this world - pub fn spawn_location(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSpawnLocation", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} + +impl<'mc> JNIRaw<'mc> for ArtStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Sets the spawn location of the world - pub fn set_spawn_location( - &self, - x: i32, - y: std::option::Option, - z: std::option::Option, - angle: std::option::Option, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); - args.push(val_1); - if let Some(a) = y { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - if let Some(a) = z { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for ArtStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate ArtStruct from null object.").into()); } - if let Some(a) = angle { - sig += "F"; - let val_4 = jni::objects::JValueGen::Float(a); - args.push(val_4); + let (valid, name) = env.validate_name(&obj, "org/bukkit/Art")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ArtStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - sig += ")Z"; + } +} + +impl<'mc> ArtStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Art;"); + let cls = jni.find_class("org/bukkit/Art"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::Art::from_raw(&jni, obj) + } + /// Gets the width of the painting, in blocks + pub fn block_width(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "setSpawnLocation", sig.as_str(), args); + .call_method(&self.jni_object(), "getBlockWidth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Gets the relative in-game time of this world. - /// - /// The relative time is analogous to hours * 1000 - pub fn time(&self) -> Result> { - let sig = String::from("()J"); + /// Gets the height of the painting, in blocks + pub fn block_height(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBlockHeight", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + #[deprecated] + /// Get the ID of this painting. + pub fn id(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getTime", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getId", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + Ok(res.i()?) } - /// Sets the relative in-game time on the server. - /// - /// The relative time is analogous to hours * 1000 - /// - /// Note that setting the relative time below the current relative time - /// will actually move the clock forward a day. If you require to rewind - /// time, please see {@link #setFullTime(long)} - pub fn set_time(&self, time: i64) -> Result<(), Box> { - let sig = String::from("(J)V"); - let val_1 = jni::objects::JValueGen::Long(time); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTime", + + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + #[deprecated] + /// Get a painting by its numeric ID + pub fn get_by_id( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + id: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/Art;"); + let val_1 = jni::objects::JValueGen::Int(id); + let cls = jni.find_class("org/bukkit/Art"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getById", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the full in-game time on this world - pub fn full_time(&self) -> Result> { - let sig = String::from("()J"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFullTime", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::Art::from_raw(&jni, obj)?)) } - /// Sets the in-game time on the server + /// Get a painting by its unique name /// - /// Note that this sets the full time of the world, which may cause adverse - /// effects such as breaking redstone clocks and any scheduled events - pub fn set_full_time(&self, time: i64) -> Result<(), Box> { - let sig = String::from("(J)V"); - let val_1 = jni::objects::JValueGen::Long(time); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFullTime", + /// This ignores underscores and capitalization + pub fn get_by_name( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + name: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/Art;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(name.into())?, + )); + let cls = jni.find_class("org/bukkit/Art"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getByName", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::Art::from_raw(&jni, obj)?)) } - /// Gets the full in-game time on this world since the world generation - pub fn game_time(&self) -> Result> { - let sig = String::from("()J"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getGameTime", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Returns whether the world has an ongoing storm. - pub fn has_storm(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasStorm", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} +#[repr(C)] +pub struct ServerTickManager<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ServerTickManager<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Set whether there is a storm. A duration will be set for the new - /// current conditions. - /// This will implicitly call {@link #setClearWeatherDuration(int)} with 0 - /// ticks to reset the world's clear weather. - pub fn set_storm(&self, has_storm: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(has_storm.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setStorm", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Get the remaining time in ticks of the current conditions. - pub fn weather_duration(&self) -> Result> { - let sig = String::from("()I"); +} +impl<'mc> JNIInstantiatable<'mc> for ServerTickManager<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate ServerTickManager from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/ServerTickManager")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ServerTickManager object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> ServerTickManager<'mc> { + /// Checks if the server is running normally. + /// + /// When the server is running normally it indicates that the server is not + /// currently frozen. + pub fn is_running_normally(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getWeatherDuration", + "isRunningNormally", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the remaining time in ticks of the current conditions. - pub fn set_weather_duration(&self, duration: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(duration); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setWeatherDuration", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.z()?) } - /// Returns whether there is thunder. - pub fn is_thundering(&self) -> Result> { + /// Checks if the server is currently stepping. + pub fn is_stepping(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isThundering", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isStepping", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set whether it is thundering. - /// This will implicitly call {@link #setClearWeatherDuration(int)} with 0 - /// ticks to reset the world's clear weather. - pub fn set_thundering(&self, thundering: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(thundering.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setThundering", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the thundering duration. - pub fn thunder_duration(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getThunderDuration", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the thundering duration. - pub fn set_thunder_duration(&self, duration: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(duration); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setThunderDuration", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns whether the world has clear weather. - /// This will be true such that {@link #isThundering()} and - /// {@link #hasStorm()} are both false. - pub fn is_clear_weather(&self) -> Result> { + /// Checks if the server is currently sprinting. + pub fn is_sprinting(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isClearWeather", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSprinting", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set the clear weather duration. - /// The clear weather ticks determine whether or not the world will be - /// allowed to rain or storm. If clear weather ticks are > 0, the world will - /// not naturally do either until the duration has elapsed. - /// This method is equivalent to calling {@code /weather clear} with a set - /// amount of ticks. - pub fn set_clear_weather_duration( + /// Checks if a given entity is frozen. + pub fn is_frozen( &self, - duration: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(duration); + entity: std::option::Option>>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = entity { + sig += "Lorg/bukkit/entity/Entity;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isFrozen", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the current tick rate of the server. + pub fn tick_rate(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTickRate", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the tick rate of the server. + /// + /// The normal tick rate of the server is 20. No tick rate below 1.0F or + /// above 10,000 can be applied to the server. + pub fn set_tick_rate(&self, tick: f32) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(tick); let res = self.jni_ref().call_method( &self.jni_object(), - "setClearWeatherDuration", + "setTickRate", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the clear weather duration. - pub fn clear_weather_duration(&self) -> Result> { - let sig = String::from("()I"); + /// Sets the server to a frozen state that does not tick most things. + pub fn set_frozen(&self, frozen: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(frozen.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "getClearWeatherDuration", + "setFrozen", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Creates explosion at given coordinates with given power and optionally - /// setting blocks on fire or breaking blocks. + /// Steps the game a certain amount of ticks if the server is currently + /// frozen. /// - /// Note that if a non-null {@code source} Entity is provided and {@code - /// breakBlocks} is {@code true}, the value of {@code breakBlocks} will be - /// ignored if {@link GameRule#MOB_GRIEFING} is {@code false} in the world - /// in which the explosion occurs. In other words, the mob griefing gamerule - /// will take priority over {@code breakBlocks} if explosions are not allowed. - pub fn create_explosion( - &self, - loc: impl Into>, - power: f32, - set_fire: std::option::Option, - break_blocks: std::option::Option, - source: std::option::Option>>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) - }); - args.push(val_1); - sig += "F"; - let val_2 = jni::objects::JValueGen::Float(power); - args.push(val_2); - if let Some(a) = set_fire { - sig += "Z"; - let val_3 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_3); - } - if let Some(a) = break_blocks { - sig += "Z"; - let val_4 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_4); - } - if let Some(a) = source { - sig += "Lorg/bukkit/entity/Entity;"; - let val_5 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_5); - } - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "createExplosion", sig.as_str(), args); + /// Steps occur when the server is in a frozen state which can be started by + /// either using the in game /tick freeze command or the + /// {@link #setFrozen(boolean)} method. + pub fn step_game_if_frozen(&self, ticks: i32) -> Result> { + let sig = String::from("(I)Z"); + let val_1 = jni::objects::JValueGen::Int(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "stepGameIfFrozen", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the current PVP setting for this world. - pub fn pvp(&self) -> Result> { + /// Stops the current stepping if stepping is occurring. + pub fn stop_stepping(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPVP", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "stopStepping", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the PVP setting for this world. - pub fn set_pvp(&self, pvp: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(pvp.into()); + /// Attempts to initiate a sprint, which executes all server ticks at a + /// faster rate then normal. + pub fn request_game_to_sprint(&self, ticks: i32) -> Result> { + let sig = String::from("(I)Z"); + let val_1 = jni::objects::JValueGen::Int(ticks); let res = self.jni_ref().call_method( &self.jni_object(), - "setPVP", + "requestGameToSprint", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the chunk generator for this world - pub fn generator( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/generator/ChunkGenerator;"); + /// Stops the current sprint if one is currently happening. + pub fn stop_sprinting(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getGenerator", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "stopSprinting", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::generator::ChunkGenerator::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.z()?) } - /// Gets the biome provider for this world - pub fn biome_provider( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/generator/BiomeProvider;"); + /// Gets the amount of frozen ticks left to run. + pub fn frozen_ticks_to_run(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getBiomeProvider", + "getFrozenTicksToRun", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + Ok(res.i()?) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +pub enum SoundCategory<'mc> { + Master { inner: SoundCategoryStruct<'mc> }, + Music { inner: SoundCategoryStruct<'mc> }, + Records { inner: SoundCategoryStruct<'mc> }, + Weather { inner: SoundCategoryStruct<'mc> }, + Blocks { inner: SoundCategoryStruct<'mc> }, + Hostile { inner: SoundCategoryStruct<'mc> }, + Neutral { inner: SoundCategoryStruct<'mc> }, + Players { inner: SoundCategoryStruct<'mc> }, + Ambient { inner: SoundCategoryStruct<'mc> }, + Voice { inner: SoundCategoryStruct<'mc> }, +} +impl<'mc> std::fmt::Display for SoundCategory<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + SoundCategory::Master { .. } => f.write_str("MASTER"), + SoundCategory::Music { .. } => f.write_str("MUSIC"), + SoundCategory::Records { .. } => f.write_str("RECORDS"), + SoundCategory::Weather { .. } => f.write_str("WEATHER"), + SoundCategory::Blocks { .. } => f.write_str("BLOCKS"), + SoundCategory::Hostile { .. } => f.write_str("HOSTILE"), + SoundCategory::Neutral { .. } => f.write_str("NEUTRAL"), + SoundCategory::Players { .. } => f.write_str("PLAYERS"), + SoundCategory::Ambient { .. } => f.write_str("AMBIENT"), + SoundCategory::Voice { .. } => f.write_str("VOICE"), } - Ok(Some(crate::generator::BiomeProvider::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) } - /// Saves world to disk - pub fn save(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "save", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) +} +impl<'mc> std::ops::Deref for SoundCategory<'mc> { + type Target = SoundCategoryStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + SoundCategory::Master { inner } => inner, + SoundCategory::Music { inner } => inner, + SoundCategory::Records { inner } => inner, + SoundCategory::Weather { inner } => inner, + SoundCategory::Blocks { inner } => inner, + SoundCategory::Hostile { inner } => inner, + SoundCategory::Neutral { inner } => inner, + SoundCategory::Players { inner } => inner, + SoundCategory::Ambient { inner } => inner, + SoundCategory::Voice { inner } => inner, + } } - /// Gets a list of all applied {@link BlockPopulator}s for this World - pub fn populators( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPopulators", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::generator::BlockPopulator::from_raw( - &self.jni_ref(), - obj, - )?); +} + +impl<'mc> SoundCategory<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/SoundCategory"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/SoundCategory;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "MASTER" => Ok(SoundCategory::Master { + inner: SoundCategoryStruct::from_raw(env, obj)?, + }), + "MUSIC" => Ok(SoundCategory::Music { + inner: SoundCategoryStruct::from_raw(env, obj)?, + }), + "RECORDS" => Ok(SoundCategory::Records { + inner: SoundCategoryStruct::from_raw(env, obj)?, + }), + "WEATHER" => Ok(SoundCategory::Weather { + inner: SoundCategoryStruct::from_raw(env, obj)?, + }), + "BLOCKS" => Ok(SoundCategory::Blocks { + inner: SoundCategoryStruct::from_raw(env, obj)?, + }), + "HOSTILE" => Ok(SoundCategory::Hostile { + inner: SoundCategoryStruct::from_raw(env, obj)?, + }), + "NEUTRAL" => Ok(SoundCategory::Neutral { + inner: SoundCategoryStruct::from_raw(env, obj)?, + }), + "PLAYERS" => Ok(SoundCategory::Players { + inner: SoundCategoryStruct::from_raw(env, obj)?, + }), + "AMBIENT" => Ok(SoundCategory::Ambient { + inner: SoundCategoryStruct::from_raw(env, obj)?, + }), + "VOICE" => Ok(SoundCategory::Voice { + inner: SoundCategoryStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } - Ok(new_vec) } - /// Creates a new entity at the given {@link Location} with the supplied - /// function run before the entity is added to the world. - /// - /// Note that when the function is run, the entity will not be actually in - /// the world. Any operation involving such as teleporting the entity is undefined - /// until after this function returns. - /// The passed function however is run after the potential entity's spawn - /// randomization and hence already allows access to the values of the mob, - /// whether or not those were randomized, such as attributes or the entity - /// equipment. - pub fn spawn( - &self, - location: impl Into>, - clazz: jni::objects::JClass<'mc>, - spawn_reason: std::option::Option< - impl Into>, - >, - randomize_data: std::option::Option, - function: std::option::Option< - impl Into>, - >, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Ljava/lang/Class;"; - let val_2 = jni::objects::JValueGen::Object(clazz.into()); - args.push(val_2); - if let Some(a) = spawn_reason { - sig += "Lorg/bukkit/event/entity/CreatureSpawnEvent/SpawnReason;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_3); +} + +#[repr(C)] +pub struct SoundCategoryStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for SoundCategory<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Master { inner } => inner.0.clone(), + Self::Music { inner } => inner.0.clone(), + Self::Records { inner } => inner.0.clone(), + Self::Weather { inner } => inner.0.clone(), + Self::Blocks { inner } => inner.0.clone(), + Self::Hostile { inner } => inner.0.clone(), + Self::Neutral { inner } => inner.0.clone(), + Self::Players { inner } => inner.0.clone(), + Self::Ambient { inner } => inner.0.clone(), + Self::Voice { inner } => inner.0.clone(), } - if let Some(a) = randomize_data { - sig += "Z"; - let val_4 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_4); + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Master { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Music { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Records { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Weather { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Blocks { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Hostile { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Neutral { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Players { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Ambient { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Voice { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, } - if let Some(a) = function { - sig += "Ljava/util/function/Consumer;"; - let val_5 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_5); + } +} +impl<'mc> JNIInstantiatable<'mc> for SoundCategory<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate SoundCategory from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/SoundCategory")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a SoundCategory object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "MASTER" => Ok(SoundCategory::Master { + inner: SoundCategoryStruct::from_raw(env, obj)?, + }), + "MUSIC" => Ok(SoundCategory::Music { + inner: SoundCategoryStruct::from_raw(env, obj)?, + }), + "RECORDS" => Ok(SoundCategory::Records { + inner: SoundCategoryStruct::from_raw(env, obj)?, + }), + "WEATHER" => Ok(SoundCategory::Weather { + inner: SoundCategoryStruct::from_raw(env, obj)?, + }), + "BLOCKS" => Ok(SoundCategory::Blocks { + inner: SoundCategoryStruct::from_raw(env, obj)?, + }), + "HOSTILE" => Ok(SoundCategory::Hostile { + inner: SoundCategoryStruct::from_raw(env, obj)?, + }), + "NEUTRAL" => Ok(SoundCategory::Neutral { + inner: SoundCategoryStruct::from_raw(env, obj)?, + }), + "PLAYERS" => Ok(SoundCategory::Players { + inner: SoundCategoryStruct::from_raw(env, obj)?, + }), + "AMBIENT" => Ok(SoundCategory::Ambient { + inner: SoundCategoryStruct::from_raw(env, obj)?, + }), + "VOICE" => Ok(SoundCategory::Voice { + inner: SoundCategoryStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } - sig += ")LT;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "spawn", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) } - #[deprecated] - /// Spawn a {@link FallingBlock} entity at the given {@link Location} of the specified {@link Material}. The material dictates what is falling. When the FallingBlock hits the ground, it will place that block.The Material must be a block type, check with {@link Material#isBlock() material.isBlock()}. The Material may not be air. - pub fn spawn_falling_block( - &self, - location: impl Into>, - material: impl Into>, - data: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/Material;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) - }); - args.push(val_2); - if let Some(a) = data { - sig += "B"; - let val_3 = jni::objects::JValueGen::Byte(a); - args.push(val_3); +} + +impl<'mc> JNIRaw<'mc> for SoundCategoryStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for SoundCategoryStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate SoundCategoryStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/SoundCategory")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a SoundCategoryStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - sig += ")Lorg/bukkit/entity/FallingBlock;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "spawnFallingBlock", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::entity::FallingBlock::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) } - /// Plays an effect to all players within a given radius around a location. - pub fn play_effect( - &self, - location: impl Into>, - effect: impl Into>, - data: jni::objects::JObject<'mc>, - radius: std::option::Option, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/Effect;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(effect.into().jni_object().clone()) - }); - args.push(val_2); - sig += "LT;"; - let val_3 = jni::objects::JValueGen::Object(data); - args.push(val_3); - if let Some(a) = radius { - sig += "I"; - let val_4 = jni::objects::JValueGen::Int(a); - args.push(val_4); +} + +impl<'mc> SoundCategoryStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/SoundCategory;"); + let cls = jni.find_class("org/bukkit/SoundCategory"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::SoundCategory::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +pub enum NetherWartsState<'mc> { + Seeded { inner: NetherWartsStateStruct<'mc> }, + StageOne { inner: NetherWartsStateStruct<'mc> }, + StageTwo { inner: NetherWartsStateStruct<'mc> }, + Ripe { inner: NetherWartsStateStruct<'mc> }, +} +impl<'mc> std::fmt::Display for NetherWartsState<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + NetherWartsState::Seeded { .. } => f.write_str("SEEDED"), + NetherWartsState::StageOne { .. } => f.write_str("STAGE_ONE"), + NetherWartsState::StageTwo { .. } => f.write_str("STAGE_TWO"), + NetherWartsState::Ripe { .. } => f.write_str("RIPE"), } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "playEffect", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) } - /// Get empty chunk snapshot (equivalent to all air blocks), optionally - /// including valid biome data. Used for representing an ungenerated chunk, - /// or for fetching only biome data without loading a chunk. - pub fn get_empty_chunk_snapshot( - &self, - x: i32, - z: i32, - include_biome: bool, - include_biome_temp: bool, - ) -> Result, Box> { - let sig = String::from("(IIZZ)Lorg/bukkit/ChunkSnapshot;"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(z); - let val_3 = jni::objects::JValueGen::Bool(include_biome.into()); - let val_4 = jni::objects::JValueGen::Bool(include_biome_temp.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getEmptyChunkSnapshot", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - ], +} +impl<'mc> std::ops::Deref for NetherWartsState<'mc> { + type Target = NetherWartsStateStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + NetherWartsState::Seeded { inner } => inner, + NetherWartsState::StageOne { inner } => inner, + NetherWartsState::StageTwo { inner } => inner, + NetherWartsState::Ripe { inner } => inner, + } + } +} + +impl<'mc> NetherWartsState<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/NetherWartsState"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/NetherWartsState;", + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - crate::ChunkSnapshot::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "SEEDED" => Ok(NetherWartsState::Seeded { + inner: NetherWartsStateStruct::from_raw(env, obj)?, + }), + "STAGE_ONE" => Ok(NetherWartsState::StageOne { + inner: NetherWartsStateStruct::from_raw(env, obj)?, + }), + "STAGE_TWO" => Ok(NetherWartsState::StageTwo { + inner: NetherWartsStateStruct::from_raw(env, obj)?, + }), + "RIPE" => Ok(NetherWartsState::Ripe { + inner: NetherWartsStateStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct NetherWartsStateStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for NetherWartsState<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Seeded { inner } => inner.0.clone(), + Self::StageOne { inner } => inner.0.clone(), + Self::StageTwo { inner } => inner.0.clone(), + Self::Ripe { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Seeded { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::StageOne { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::StageTwo { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Ripe { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for NetherWartsState<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate NetherWartsState from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/NetherWartsState")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a NetherWartsState object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "SEEDED" => Ok(NetherWartsState::Seeded { + inner: NetherWartsStateStruct::from_raw(env, obj)?, + }), + "STAGE_ONE" => Ok(NetherWartsState::StageOne { + inner: NetherWartsStateStruct::from_raw(env, obj)?, + }), + "STAGE_TWO" => Ok(NetherWartsState::StageTwo { + inner: NetherWartsStateStruct::from_raw(env, obj)?, + }), + "RIPE" => Ok(NetherWartsState::Ripe { + inner: NetherWartsStateStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for NetherWartsStateStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for NetherWartsStateStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate NetherWartsStateStruct from null object." + ) + .into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/NetherWartsState")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a NetherWartsStateStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } - /// Sets the spawn flags for this. - pub fn set_spawn_flags( - &self, - allow_monsters: bool, - allow_animals: bool, - ) -> Result<(), Box> { - let sig = String::from("(ZZ)V"); - let val_1 = jni::objects::JValueGen::Bool(allow_monsters.into()); - let val_2 = jni::objects::JValueGen::Bool(allow_animals.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSpawnFlags", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) +} + +impl<'mc> NetherWartsStateStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NetherWartsState;"); + let cls = jni.find_class("org/bukkit/NetherWartsState"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::NetherWartsState::from_raw(&jni, obj) } - /// Gets whether animals can spawn in this world. - pub fn allow_animals(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAllowAnimals", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Gets whether monsters can spawn in this world. - pub fn allow_monsters(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAllowMonsters", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} +#[repr(C)] +pub struct Keyed<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Keyed<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Gets the {@link Biome} at the given coordinates. - pub fn get_biome( - &self, - x: i32, - y: std::option::Option, - z: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); - args.push(val_1); - if let Some(a) = y { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Keyed<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Keyed from null object.").into()); } - if let Some(a) = z { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); + let (valid, name) = env.validate_name(&obj, "org/bukkit/Keyed")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Keyed object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - sig += ")Lorg/bukkit/block/Biome;"; + } +} + +impl<'mc> Keyed<'mc> { + /// Return the namespaced identifier for this object. + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getBiome", sig.as_str(), args); + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::Biome::from_raw(&self.jni_ref(), unsafe { + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the {@link Biome} for the given block coordinates - pub fn set_biome( - &self, - x: i32, - y: i32, - z: std::option::Option, - biome: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); - args.push(val_1); - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(y); - args.push(val_2); - if let Some(a) = z { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - if let Some(a) = biome { - sig += "Lorg/bukkit/block/Biome;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_4); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setBiome", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Gets the temperature for the given block coordinates. - /// - /// It is safe to run this method when the block does not exist, it will - /// not create the block. - /// - /// This method will return the raw temperature without adjusting for block - /// height effects. - pub fn get_temperature( - &self, - x: i32, - y: i32, - z: std::option::Option, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); - args.push(val_1); - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(y); - args.push(val_2); - if let Some(a) = z { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - sig += ")D"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTemperature", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) +} +#[repr(C)] +pub struct Utility<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Utility<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Gets the humidity for the given block coordinates. - /// - /// It is safe to run this method when the block does not exist, it will - /// not create the block. - pub fn get_humidity( - &self, - x: i32, - y: i32, - z: std::option::Option, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); - args.push(val_1); - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(y); - args.push(val_2); - if let Some(a) = z { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Utility<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Utility from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Utility")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Utility object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - sig += ")D"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHumidity", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) } - /// Gets the maximum height to which chorus fruits and nether portals can - /// bring players within this dimension. - /// This excludes portals that were already built above the limit as they - /// still connect normally. May not be greater than {@link #getMaxHeight()}. - pub fn logical_height(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getLogicalHeight", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) +} + +impl<'mc> Utility<'mc> { + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Gets if this world is natural. - /// When false, compasses spin randomly, and using a bed to set the respawn - /// point or sleep, is disabled. When true, nether portals can spawn - /// zombified piglins. - pub fn is_natural(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isNatural", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} +#[repr(C)] +pub struct Server<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Server<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Gets if beds work in this world. - /// A non-working bed will blow up when trying to sleep. {@link #isNatural()} - /// defines if a bed can be used to set spawn point. - pub fn is_bed_works(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isBedWorks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Gets if this world has skylight access. - pub fn has_sky_light(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasSkyLight", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} +impl<'mc> JNIInstantiatable<'mc> for Server<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Server from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Server")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Server object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } - /// Gets if this world has a ceiling. - pub fn has_ceiling(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "hasCeiling", sig.as_str(), vec![]); +} + +impl<'mc> Server<'mc> { + /// Gets the name of this server implementation. + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Gets if this world allow to piglins to survive without shaking and - /// transforming to zombified piglins. - pub fn is_piglin_safe(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the version string of this server implementation. + pub fn version(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isPiglinSafe", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getVersion", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Gets if this world allows players to charge and use respawn anchors. - pub fn is_respawn_anchor_works(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the Bukkit version that this server is running. + pub fn bukkit_version(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref().call_method( &self.jni_object(), - "isRespawnAnchorWorks", + "getBukkitVersion", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets if players with the bad omen effect in this world will trigger a - /// raid. - pub fn has_raids(&self) -> Result> { - let sig = String::from("()Z"); - let res = self + Ok(self .jni_ref() - .call_method(&self.jni_object(), "hasRaids", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Gets if various water/lava mechanics will be triggered in this world, eg: + /// Gets a view of all currently logged in players. This {@linkplain + /// Collections#unmodifiableCollection(Collection) view} is a reused + /// object, making some operations like {@link Collection#size()} + /// zero-allocation. /// - ///
      - ///
    • Water is evaporated
    • - ///
    • Sponges dry
    • - ///
    • Lava spreads faster and further
    • - ///
    - pub fn is_ultra_warm(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isUltraWarm", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the sea level for this world. + /// The collection is a view backed by the internal representation, such + /// that, changes to the internal state of the server will be reflected + /// immediately. However, the reuse of the returned collection (identity) + /// is not strictly guaranteed for future or all implementations. Casting + /// the collection, or relying on interface implementations (like {@link + /// Serializable} or {@link List}), is deprecated. /// - /// This is often half of {@link #getMaxHeight()} - pub fn sea_level(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSeaLevel", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - #[deprecated] - /// Gets whether the world's spawn area should be kept loaded into memory or not. - pub fn keep_spawn_in_memory(&self) -> Result> { - let sig = String::from("()Z"); + /// Iteration behavior is undefined outside of self-contained main-thread + /// uses. Normal and immediate iterator use without consequences that + /// affect the collection are fully supported. The effects following + /// (non-exhaustive) {@link Entity#teleport(Location) teleportation}, + /// {@link Player#setHealth(double) death}, and {@link Player#kickPlayer( + /// String) kicking} are undefined. Any use of this collection from + /// asynchronous threads is unsafe. + /// + /// For safe consequential iteration or mimicking the old array behavior, + /// using {@link Collection#toArray(Object[])} is recommended. For making + /// snapshots, {@link ImmutableList#copyOf(Collection)} is recommended. + pub fn online_players( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getKeepSpawnInMemory", + "getOnlinePlayers", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Sets whether the world's spawn area should be kept loaded into memory or not. - pub fn set_keep_spawn_in_memory( - &self, - keep_loaded: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(keep_loaded.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setKeepSpawnInMemory", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Player::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Gets whether or not the world will automatically save - pub fn is_auto_save(&self) -> Result> { - let sig = String::from("()Z"); + /// Get the maximum amount of players which can login to this server. + pub fn max_players(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isAutoSave", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxPlayers", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets whether or not the world will automatically save - pub fn set_auto_save(&self, value: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(value.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAutoSave", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.i()?) } - /// Sets the Difficulty of the world. - pub fn set_difficulty( - &self, - difficulty: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Difficulty;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(difficulty.into().jni_object().clone()) - }); + /// Set the maximum amount of players allowed to be logged in at once. + pub fn set_max_players(&self, max_players: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(max_players); let res = self.jni_ref().call_method( &self.jni_object(), - "setDifficulty", + "setMaxPlayers", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) - } - /// Gets the Difficulty of the world. - pub fn difficulty(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Difficulty;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDifficulty", sig.as_str(), vec![]); + } + /// Get the game port that the server runs on. + pub fn port(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPort", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Difficulty::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Returns the view distance used for this world. + /// Get the view distance from this server. pub fn view_distance(&self) -> Result> { let sig = String::from("()I"); let res = @@ -13939,7 +68567,7 @@ impl<'mc> World<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Returns the simulation distance used for this world. + /// Get the simulation distance from this server. pub fn simulation_distance(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( @@ -13951,407 +68579,372 @@ impl<'mc> World<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - #[deprecated] - /// Gets the type of this world. - pub fn world_type(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/WorldType;"); + /// Get the IP that this server is bound to, or empty string if not + /// specified. + pub fn ip(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getIp", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Get world type (level-type setting) for default world. + pub fn world_type(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() .call_method(&self.jni_object(), "getWorldType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::WorldType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Gets whether or not structures are being generated. - pub fn can_generate_structures(&self) -> Result> { + /// Get generate-structures setting. + pub fn generate_structures(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "canGenerateStructures", + "getGenerateStructures", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets whether the world is hardcore or not. - /// In a hardcore world the difficulty is locked to hard. - pub fn is_hardcore(&self) -> Result> { + /// Get max world size. + pub fn max_world_size(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxWorldSize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets whether this server allows the End or not. + pub fn allow_end(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isHardcore", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAllowEnd", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether the world is hardcore or not. - /// In a hardcore world the difficulty is locked to hard. - pub fn set_hardcore(&self, hardcore: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(hardcore.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setHardcore", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Gets the world's ticks per animal spawns valueThis value determines how many ticks there are between attempts to spawn animals.Example Usage:
    • A value of 1 will mean the server will attempt to spawn animals in this world every tick.
    • A value of 400 will mean the server will attempt to spawn animals in this world every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, animal spawning will be disabled for this world. We recommend using {@link #setSpawnFlags(boolean, boolean)} to control this instead.Minecraft default: 400. - pub fn ticks_per_animal_spawns(&self) -> Result> { - let sig = String::from("()J"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTicksPerAnimalSpawns", - sig.as_str(), - vec![], - ); + /// Gets whether this server allows the Nether or not. + pub fn allow_nether(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAllowNether", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + Ok(res.z()?) } - #[deprecated] - /// Sets the world's ticks per animal spawns valueThis value determines how many ticks there are between attempts to spawn animals.Example Usage:
    • A value of 1 will mean the server will attempt to spawn animals in this world every tick.
    • A value of 400 will mean the server will attempt to spawn animals in this world every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, animal spawning will be disabled for this world. We recommend using {@link #setSpawnFlags(boolean, boolean)} to control this instead.Minecraft default: 400. - pub fn set_ticks_per_animal_spawns( - &self, - ticks_per_animal_spawns: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks_per_animal_spawns); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTicksPerAnimalSpawns", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Gets whether the server is logging the IP addresses of players. + pub fn is_logging_ips(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isLoggingIPs", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - #[deprecated] - /// Gets the world's ticks per monster spawns valueThis value determines how many ticks there are between attempts to spawn monsters.Example Usage:
    • A value of 1 will mean the server will attempt to spawn monsters in this world every tick.
    • A value of 400 will mean the server will attempt to spawn monsters in this world every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, monsters spawning will be disabled for this world. We recommend using {@link #setSpawnFlags(boolean, boolean)} to control this instead.Minecraft default: 1. - pub fn ticks_per_monster_spawns(&self) -> Result> { - let sig = String::from("()J"); + /// Gets a list of packs to be enabled. + pub fn initial_enabled_packs(&self) -> Result, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getTicksPerMonsterSpawns", + "getInitialEnabledPacks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) - } - #[deprecated] - /// Sets the world's ticks per monster spawns valueThis value determines how many ticks there are between attempts to spawn monsters.Example Usage:
    • A value of 1 will mean the server will attempt to spawn monsters in this world on every tick.
    • A value of 400 will mean the server will attempt to spawn monsters in this world every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, monsters spawning will be disabled for this world. We recommend using {@link #setSpawnFlags(boolean, boolean)} to control this instead.Minecraft default: 1. - pub fn set_ticks_per_monster_spawns( - &self, - ticks_per_monster_spawns: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks_per_monster_spawns); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTicksPerMonsterSpawns", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); + } + Ok(new_vec) } - #[deprecated] - /// Gets the world's ticks per water mob spawns valueThis value determines how many ticks there are between attempts to spawn water mobs.Example Usage:
    • A value of 1 will mean the server will attempt to spawn water mobs in this world every tick.
    • A value of 400 will mean the server will attempt to spawn water mobs in this world every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, water mobs spawning will be disabled for this world.Minecraft default: 1. - pub fn ticks_per_water_spawns(&self) -> Result> { - let sig = String::from("()J"); + /// Gets a list of packs that will not be enabled automatically. + pub fn initial_disabled_packs(&self) -> Result, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getTicksPerWaterSpawns", + "getInitialDisabledPacks", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); + } + Ok(new_vec) } - #[deprecated] - /// Sets the world's ticks per water mob spawns valueThis value determines how many ticks there are between attempts to spawn water mobs.Example Usage:
    • A value of 1 will mean the server will attempt to spawn water mobs in this world on every tick.
    • A value of 400 will mean the server will attempt to spawn water mobs in this world every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, water mobs spawning will be disabled for this world.Minecraft default: 1. - pub fn set_ticks_per_water_spawns( + /// Get the DataPack Manager. + pub fn data_pack_manager( &self, - ticks_per_water_spawns: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks_per_water_spawns); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTicksPerWaterSpawns", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - #[deprecated] - /// Gets the default ticks per water ambient mob spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn water ambient mobs every tick.
    • A value of 400 will mean the server will attempt to spawn water ambient mobs every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, ambient mobs spawning will be disabled.Minecraft default: 1. - pub fn ticks_per_water_ambient_spawns(&self) -> Result> { - let sig = String::from("()J"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/packs/DataPackManager;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getTicksPerWaterAmbientSpawns", + "getDataPackManager", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + crate::packs::DataPackManager::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - /// Sets the world's ticks per water ambient mob spawns valueThis value determines how many ticks there are between attempts to spawn water ambient mobs.Example Usage:
    • A value of 1 will mean the server will attempt to spawn water ambient mobs in this world on every tick.
    • A value of 400 will mean the server will attempt to spawn water ambient mobs in this world every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, water ambient mobs spawning will be disabled for this world.Minecraft default: 1. - pub fn set_ticks_per_water_ambient_spawns( + /// Get the ServerTick Manager. + pub fn server_tick_manager( &self, - ticks_per_ambient_spawns: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks_per_ambient_spawns); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/ServerTickManager;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setTicksPerWaterAmbientSpawns", + "getServerTickManager", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + crate::ServerTickManager::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - /// Gets the default ticks per water underground creature spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn water underground creature every tick.
    • A value of 400 will mean the server will attempt to spawn water underground creature every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, water underground creature spawning will be disabled.Minecraft default: 1. - pub fn ticks_per_water_underground_creature_spawns( + /// Gets the resource pack configured to be sent to clients by the server. + pub fn server_resource_pack( &self, - ) -> Result> { - let sig = String::from("()J"); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/packs/ResourcePack;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getTicksPerWaterUndergroundCreatureSpawns", + "getServerResourcePack", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::packs::ResourcePack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - #[deprecated] - /// Sets the world's ticks per water underground creature spawns valueThis value determines how many ticks there are between attempts to spawn water underground creature.Example Usage:
    • A value of 1 will mean the server will attempt to spawn water underground creature in this world on every tick.
    • A value of 400 will mean the server will attempt to spawn water underground creature in this world every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, water underground creature spawning will be disabled for this world.Minecraft default: 1. - pub fn set_ticks_per_water_underground_creature_spawns( - &self, - ticks_per_water_underground_creature_spawns: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks_per_water_underground_creature_spawns); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setTicksPerWaterUndergroundCreatureSpawns", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Gets the server resource pack uri, or empty string if not specified. + pub fn resource_pack(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getResourcePack", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - #[deprecated] - /// Gets the world's ticks per ambient mob spawns valueThis value determines how many ticks there are between attempts to spawn ambient mobs.Example Usage:
    • A value of 1 will mean the server will attempt to spawn ambient mobs in this world every tick.
    • A value of 400 will mean the server will attempt to spawn ambient mobs in this world every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, ambient mobs spawning will be disabled for this world.Minecraft default: 1. - pub fn ticks_per_ambient_spawns(&self) -> Result> { - let sig = String::from("()J"); + /// Gets the SHA-1 digest of the server resource pack, or empty string if + /// not specified. + pub fn resource_pack_hash(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getTicksPerAmbientSpawns", + "getResourcePackHash", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - #[deprecated] - /// Sets the world's ticks per ambient mob spawns valueThis value determines how many ticks there are between attempts to spawn ambient mobs.Example Usage:
    • A value of 1 will mean the server will attempt to spawn ambient mobs in this world on every tick.
    • A value of 400 will mean the server will attempt to spawn ambient mobs in this world every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, ambient mobs spawning will be disabled for this world.Minecraft default: 1. - pub fn set_ticks_per_ambient_spawns( - &self, - ticks_per_ambient_spawns: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(ticks_per_ambient_spawns); + /// Gets the custom prompt message to be shown when the server resource + /// pack is required, or empty string if not specified. + pub fn resource_pack_prompt(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setTicksPerAmbientSpawns", + "getResourcePackPrompt", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Gets the world's ticks per {@link SpawnCategory} mob spawns value - /// - /// This value determines how many ticks there are between attempts to - /// spawn {@link SpawnCategory} mobs. - /// - /// Example Usage: - ///
      - ///
    • A value of 1 will mean the server will attempt to spawn {@link SpawnCategory} mobs in - /// this world every tick. - ///
    • A value of 400 will mean the server will attempt to spawn {@link SpawnCategory} mobs - /// in this world every 400th tick. - ///
    • A value below 0 will be reset back to Minecraft's default. - ///
    - /// - /// Note: - /// If set to 0, {@link SpawnCategory} mobs spawning will be disabled for this world. - /// - /// Minecraft default: 1. - pub fn get_ticks_per_spawns( - &self, - spawn_category: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/entity/SpawnCategory;)J"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(spawn_category.into().jni_object().clone()) - }); + /// Gets whether the server resource pack is enforced. + pub fn is_resource_pack_required(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getTicksPerSpawns", + "isResourcePackRequired", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + Ok(res.z()?) } - /// Sets the world's ticks per {@link SpawnCategory} mob spawns value - /// - /// This value determines how many ticks there are between attempts to - /// spawn {@link SpawnCategory} mobs. - /// - /// Example Usage: - ///
      - ///
    • A value of 1 will mean the server will attempt to spawn {@link SpawnCategory} mobs in - /// this world on every tick. - ///
    • A value of 400 will mean the server will attempt to spawn {@link SpawnCategory} mobs - /// in this world every 400th tick. - ///
    • A value below 0 will be reset back to Minecraft's default. - ///
    - /// - /// Note: - /// If set to 0, {@link SpawnCategory} mobs spawning will be disabled for this world. - /// - /// Minecraft default: 1. - pub fn set_ticks_per_spawns( - &self, - spawn_category: impl Into>, - ticks_per_category_spawn: i32, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/SpawnCategory;I)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(spawn_category.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(ticks_per_category_spawn); + /// Gets whether this server has a whitelist or not. + pub fn has_whitelist(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasWhitelist", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets if the server is whitelisted. + pub fn set_whitelist(&self, value: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(value.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setTicksPerSpawns", + "setWhitelist", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets limit for number of monsters that can spawn in a chunk in this world - pub fn monster_spawn_limit(&self) -> Result> { - let sig = String::from("()I"); + /// Gets whether the server whitelist is enforced. + /// If the whitelist is enforced, non-whitelisted players will be + /// disconnected when the server whitelist is reloaded. + pub fn is_whitelist_enforced(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getMonsterSpawnLimit", + "isWhitelistEnforced", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - #[deprecated] - /// Sets the limit for number of monsters that can spawn in a chunk in this worldNote: If set to a negative number the world will use the server-wide spawn limit instead. - pub fn set_monster_spawn_limit(&self, limit: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(limit); + /// Sets if the server whitelist is enforced. + /// If the whitelist is enforced, non-whitelisted players will be + /// disconnected when the server whitelist is reloaded. + pub fn set_whitelist_enforced(&self, value: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(value.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setMonsterSpawnLimit", + "setWhitelistEnforced", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the limit for number of animals that can spawn in a chunk in this world - pub fn animal_spawn_limit(&self) -> Result> { - let sig = String::from("()I"); + /// Gets a list of whitelisted players. + pub fn whitelisted_players( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getAnimalSpawnLimit", + "getWhitelistedPlayers", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - /// Sets the limit for number of animals that can spawn in a chunk in this worldNote: If set to a negative number the world will use the server-wide spawn limit instead. - pub fn set_animal_spawn_limit(&self, limit: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(limit); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAnimalSpawnLimit", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Reloads the whitelist from disk. + pub fn reload_whitelist(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "reloadWhitelist", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Gets the limit for number of water animals that can spawn in a chunk in this world - pub fn water_animal_spawn_limit(&self) -> Result> { - let sig = String::from("()I"); + /// Broadcast a message to all players. + /// + /// This is the same as calling {@link #broadcast(java.lang.String, + /// java.lang.String)} to {@link #BROADCAST_CHANNEL_USERS} + pub fn broadcast_message( + &self, + message: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;)I"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(message.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "getWaterAnimalSpawnLimit", + "broadcastMessage", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - #[deprecated] - /// Sets the limit for number of water animals that can spawn in a chunk in this worldNote: If set to a negative number the world will use the server-wide spawn limit instead. - pub fn set_water_animal_spawn_limit( - &self, - limit: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(limit); + /// Gets the name of the update folder. The update folder is used to safely + /// update plugins at the right moment on a plugin load. + /// + /// The update folder name is relative to the plugins folder. + pub fn update_folder(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getUpdateFolder", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gets the value of the connection throttle setting. + pub fn connection_throttle(&self) -> Result> { + let sig = String::from("()J"); let res = self.jni_ref().call_method( &self.jni_object(), - "setWaterAnimalSpawnLimit", + "getConnectionThrottle", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.j()?) } #[deprecated] - /// Gets the limit for number of water underground creature that can spawn in a chunk in this world - pub fn water_underground_creature_spawn_limit( - &self, - ) -> Result> { + /// Gets default ticks per animal spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn monsters every tick.
    • A value of 400 will mean the server will attempt to spawn monsters every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, animal spawning will be disabled. We recommend using spawn-animals to control this instead.Minecraft default: 400. + pub fn ticks_per_animal_spawns(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getWaterUndergroundCreatureSpawnLimit", + "getTicksPerAnimalSpawns", sig.as_str(), vec![], ); @@ -14359,29 +68952,25 @@ impl<'mc> World<'mc> { Ok(res.i()?) } #[deprecated] - /// Sets the limit for number of water underground creature that can spawn in a chunk in this worldNote: If set to a negative number the world will use the server-wide spawn limit instead. - pub fn set_water_underground_creature_spawn_limit( - &self, - limit: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(limit); + /// Gets the default ticks per monster spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn monsters every tick.
    • A value of 400 will mean the server will attempt to spawn monsters every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, monsters spawning will be disabled. We recommend using spawn-monsters to control this instead.Minecraft default: 1. + pub fn ticks_per_monster_spawns(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "setWaterUndergroundCreatureSpawnLimit", + "getTicksPerMonsterSpawns", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } #[deprecated] - /// Gets user-specified limit for number of water ambient mobs that can spawn in a chunk. - pub fn water_ambient_spawn_limit(&self) -> Result> { + /// Gets the default ticks per water mob spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn water mobs every tick.
    • A value of 400 will mean the server will attempt to spawn water mobs every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, water mobs spawning will be disabled.Minecraft default: 1. + pub fn ticks_per_water_spawns(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getWaterAmbientSpawnLimit", + "getTicksPerWaterSpawns", sig.as_str(), vec![], ); @@ -14389,29 +68978,27 @@ impl<'mc> World<'mc> { Ok(res.i()?) } #[deprecated] - /// Sets the limit for number of water ambient mobs that can spawn in a chunk in this worldNote: If set to a negative number the world will use the server-wide spawn limit instead. - pub fn set_water_ambient_spawn_limit( - &self, - limit: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(limit); + /// Gets the default ticks per water ambient mob spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn water ambient mobs every tick.
    • A value of 400 will mean the server will attempt to spawn water ambient mobs every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, ambient mobs spawning will be disabled.Minecraft default: 1. + pub fn ticks_per_water_ambient_spawns(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "setWaterAmbientSpawnLimit", + "getTicksPerWaterAmbientSpawns", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } #[deprecated] - /// Gets the limit for number of ambient mobs that can spawn in a chunk in this world - pub fn ambient_spawn_limit(&self) -> Result> { + /// Gets the default ticks per water underground creature spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn water underground creature every tick.
    • A value of 400 will mean the server will attempt to spawn water underground creature every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, water underground creature spawning will be disabled.Minecraft default: 1. + pub fn ticks_per_water_underground_creature_spawns( + &self, + ) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getAmbientSpawnLimit", + "getTicksPerWaterUndergroundCreatureSpawns", sig.as_str(), vec![], ); @@ -14419,22 +69006,35 @@ impl<'mc> World<'mc> { Ok(res.i()?) } #[deprecated] - /// Sets the limit for number of ambient mobs that can spawn in a chunk in this worldNote: If set to a negative number the world will use the server-wide spawn limit instead. - pub fn set_ambient_spawn_limit(&self, limit: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(limit); + /// Gets the default ticks per ambient mob spawns value.Example Usage:
    • A value of 1 will mean the server will attempt to spawn ambient mobs every tick.
    • A value of 400 will mean the server will attempt to spawn ambient mobs every 400th tick.
    • A value below 0 will be reset back to Minecraft's default.
    Note: If set to 0, ambient mobs spawning will be disabled.Minecraft default: 1. + pub fn ticks_per_ambient_spawns(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "setAmbientSpawnLimit", + "getTicksPerAmbientSpawns", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Gets the limit for number of {@link SpawnCategory} entities that can spawn in a chunk in - /// this world - pub fn get_spawn_limit( + /// Gets the default ticks per {@link SpawnCategory} spawns value. + /// + /// Example Usage: + ///
      + ///
    • A value of 1 will mean the server will attempt to spawn {@link SpawnCategory} mobs + /// every tick. + ///
    • A value of 400 will mean the server will attempt to spawn {@link SpawnCategory} mobs + /// every 400th tick. + ///
    • A value below 0 will be reset back to Minecraft's default. + ///
    + /// + /// Note: If set to 0, {@link SpawnCategory} mobs spawning will be disabled. + /// + /// Minecraft default: 1. + /// + /// Note: the {@link SpawnCategory#MISC} are not consider. + pub fn get_ticks_per_spawns( &self, spawn_category: impl Into>, ) -> Result> { @@ -14444,476 +69044,418 @@ impl<'mc> World<'mc> { }); let res = self.jni_ref().call_method( &self.jni_object(), - "getSpawnLimit", + "getTicksPerSpawns", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the limit for number of {@link SpawnCategory} entities that can spawn in a chunk in - /// this world - /// - /// Note: If set to a negative number the world will use the - /// server-wide spawn limit instead. - pub fn set_spawn_limit( - &self, - spawn_category: impl Into>, - limit: i32, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/SpawnCategory;I)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(spawn_category.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(limit); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSpawnLimit", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Play a note at the provided Location in the World. - /// - /// This will work with cake. - /// - /// This method will fail silently when called with {@link Instrument#CUSTOM_HEAD}. - pub fn play_note( - &self, - loc: impl Into>, - instrument: impl Into>, - note: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Location;Lorg/bukkit/Instrument;Lorg/bukkit/Note;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(instrument.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(note.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "playNote", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Play a Sound at the provided Location in the World. For sounds with multiple - /// variations passing the same seed will always play the same variation. - /// - /// This function will fail silently if Location or Sound are null. No sound will - /// be heard by the players if their clients do not have the respective sound for - /// the value passed. - pub fn play_sound( + /// Gets the player with the given UUID. + pub fn get_player( &self, - location: impl Into>, - sound: impl Into, - category: impl Into>, - volume: f32, - pitch: std::option::Option, - seed: std::option::Option, - ) -> Result<(), Box> { + id: impl Into>, + ) -> Result>, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; + sig += "Ljava/util/UUID;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) + jni::objects::JObject::from_raw(id.into().jni_object().clone()) }); args.push(val_1); - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(sound.into())?, - )); - args.push(val_2); - sig += "Lorg/bukkit/SoundCategory;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(category.into().jni_object().clone()) - }); - args.push(val_3); - sig += "F"; - let val_4 = jni::objects::JValueGen::Float(volume); - args.push(val_4); - if let Some(a) = pitch { - sig += "F"; - let val_5 = jni::objects::JValueGen::Float(a); - args.push(val_5); - } - if let Some(a) = seed { - sig += "J"; - let val_6 = jni::objects::JValueGen::Long(a); - args.push(val_6); - } - sig += ")V"; + sig += ")Lorg/bukkit/entity/Player;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "playSound", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get an array containing the names of all the {@link GameRule}s. - pub fn game_rules(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getGameRules", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Get the current value for a given {@link GameRule}. - pub fn get_game_rule_value( - &self, - rule: impl Into>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/GameRule;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(rule.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")LT;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getGameRuleValue", sig.as_str(), args); + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(res.l()?)) + Ok(Some(crate::entity::Player::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - #[deprecated] - /// Set the specified gamerule to specified value.The rule may attempt to validate the value passed, will return true if value was set.If rule is null, the function will return false. - pub fn set_game_rule_value( + /// Gets the player with the exact given name, case insensitive. + pub fn get_player_exact( &self, - rule: impl Into, - value: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;Ljava/lang/String;)Z"); + name: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/entity/Player;"); let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(rule.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(value.into())?, + self.jni_ref().new_string(name.into())?, )); let res = self.jni_ref().call_method( &self.jni_object(), - "setGameRuleValue", + "getPlayerExact", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Player::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Checks if string is a valid game rule - pub fn is_game_rule( + /// Attempts to match any players with the given name, and returns a list + /// of all possibly matches. + /// + /// This list is not sorted in any particular order. If an exact match is + /// found, the returned list will only contain a single result. + pub fn match_player( &self, - rule: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); + name: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;)Ljava/util/List;"); let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(rule.into())?, + self.jni_ref().new_string(name.into())?, )); let res = self.jni_ref().call_method( &self.jni_object(), - "isGameRule", + "matchPlayer", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Player::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Get the default value for a given {@link GameRule}. This value is not - /// guaranteed to match the current value. - pub fn get_game_rule_default( + /// Gets the plugin manager for interfacing with plugins. + pub fn plugin_manager( &self, - rule: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/GameRule;)LT;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(rule.into().jni_object().clone()) - }); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/plugin/PluginManager;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getGameRuleDefault", + "getPluginManager", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(res.l()?)) + crate::plugin::PluginManager::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set the given {@link GameRule}'s new value. - pub fn set_game_rule( + /// Gets the scheduler for managing scheduled events. + pub fn scheduler( &self, - rule: impl Into>, - new_value: jni::objects::JObject<'mc>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/GameRule;LT;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(rule.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(new_value); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/scheduler/BukkitScheduler;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getScheduler", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::scheduler::BukkitScheduler::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets a services manager. + pub fn services_manager( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/plugin/ServicesManager;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setGameRule", + "getServicesManager", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the world border for this world. - pub fn world_border(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/WorldBorder;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getWorldBorder", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::WorldBorder::from_raw(&self.jni_ref(), unsafe { + crate::plugin::ServicesManager::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Spawns the particle (the number of times specified by count) - /// at the target location. The position of each particle will be - /// randomized positively and negatively by the offset parameters - /// on each axis. - pub fn spawn_particle( + /// Gets a list of all worlds on this server. + pub fn worlds(&self) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorlds", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::World::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Creates or loads a world with the given name using the specified + /// options. + /// + /// If the world is already loaded, it will just return the equivalent of + /// getWorld(creator.name()). + pub fn create_world( &self, - particle: impl Into>, - x: f64, - y: f64, - z: std::option::Option, - count: std::option::Option, - offset_x: std::option::Option, - offset_y: std::option::Option, - offset_z: std::option::Option, - extra: std::option::Option, - data: std::option::Option>, - force: std::option::Option, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Particle;"; + creator: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/WorldCreator;)Lorg/bukkit/World;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(particle.into().jni_object().clone()) + jni::objects::JObject::from_raw(creator.into().jni_object().clone()) }); - args.push(val_1); - sig += "D"; - let val_2 = jni::objects::JValueGen::Double(x); - args.push(val_2); - sig += "D"; - let val_3 = jni::objects::JValueGen::Double(y); - args.push(val_3); - if let Some(a) = z { - sig += "D"; - let val_4 = jni::objects::JValueGen::Double(a); - args.push(val_4); - } - if let Some(a) = count { - sig += "I"; - let val_5 = jni::objects::JValueGen::Int(a); - args.push(val_5); - } - if let Some(a) = offset_x { - sig += "D"; - let val_6 = jni::objects::JValueGen::Double(a); - args.push(val_6); - } - if let Some(a) = offset_y { - sig += "D"; - let val_7 = jni::objects::JValueGen::Double(a); - args.push(val_7); - } - if let Some(a) = offset_z { - sig += "D"; - let val_8 = jni::objects::JValueGen::Double(a); - args.push(val_8); - } - if let Some(a) = extra { - sig += "D"; - let val_9 = jni::objects::JValueGen::Double(a); - args.push(val_9); - } - if let Some(a) = data { - sig += "LT;"; - let val_10 = jni::objects::JValueGen::Object(a); - args.push(val_10); - } - if let Some(a) = force { - sig += "Z"; - let val_11 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_11); + let res = self.jni_ref().call_method( + &self.jni_object(), + "createWorld", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "spawnParticle", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(Some(crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Find the closest nearby structure of a given {@link Structure}. Finding - /// unexplored structures can, and will, block if the world is looking in - /// chunks that gave not generated yet. This can lead to the world - /// temporarily freezing while locating an unexplored structure. - /// - /// The {@code radius} is not a rigid square radius. Each structure may alter - /// how many chunks to check for each iteration. Do not assume that only a - /// radius x radius chunk area will be checked. For example, - /// {@link Structure#MANSION} can potentially check up to 20,000 blocks away - /// (or more) regardless of the radius used. - /// - /// This will not load or generate chunks. This can also lead to - /// instances where the server can hang if you are only looking for - /// unexplored structures. This is because it will keep looking further and - /// further out in order to find the structure. - /// - /// The difference between searching for a {@link StructureType} and a - /// {@link Structure} is, that a {@link StructureType} can refer to multiple - /// {@link Structure Structures} while searching for a {@link Structure} - /// while only search for the given {@link Structure}. - pub fn locate_nearest_structure( + /// Unloads the given world. + pub fn unload_world( &self, - origin: impl Into>, - structure: impl Into>, - radius: i32, - find_unexplored: bool, - ) -> Result>, Box> { + world: impl Into>, + save: bool, + ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; + sig += "Lorg/bukkit/World;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(origin.into().jni_object().clone()) + jni::objects::JObject::from_raw(world.into().jni_object().clone()) }); args.push(val_1); - sig += "Lorg/bukkit/generator/structure/Structure;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(structure.into().jni_object().clone()) - }); - args.push(val_2); - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(radius); - args.push(val_3); sig += "Z"; - let val_4 = jni::objects::JValueGen::Bool(find_unexplored.into()); - args.push(val_4); - sig += ")Lorg/bukkit/util/StructureSearchResult;"; + let val_2 = jni::objects::JValueGen::Bool(save.into()); + args.push(val_2); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "unloadWorld", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the world from the given Unique ID. + pub fn get_world( + &self, + uid: impl Into>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/util/UUID;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(uid.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Lorg/bukkit/World;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Create a new virtual {@link WorldBorder}. + /// + /// Note that world borders created by the server will not respect any world + /// scaling effects (i.e. coordinates are not divided by 8 in the nether). + pub fn create_world_border( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/WorldBorder;"); let res = self.jni_ref().call_method( &self.jni_object(), - "locateNearestStructure", + "createWorldBorder", sig.as_str(), - args, + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::WorldBorder::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + #[deprecated] + /// Gets the map from the given item ID. + pub fn get_map( + &self, + id: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/map/MapView;"); + let val_1 = jni::objects::JValueGen::Int(id); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMap", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::util::StructureSearchResult::from_raw( + Ok(Some(crate::map::MapView::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Find the closest nearby location with a biome matching the provided - /// {@link Biome}(s). Finding biomes can, and will, block if the world is looking - /// in chunks that have not generated yet. This can lead to the world temporarily - /// freezing while locating a biome. - /// - /// Note: This will not reflect changes made to the world after - /// generation, this method only sees the biome at the time of world generation. - /// This will not load or generate chunks. + /// Create a new map with an automatically assigned ID. + pub fn create_map( + &self, + world: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/World;)Lorg/bukkit/map/MapView;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(world.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "createMap", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::map::MapView::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Create a new explorer map targeting the closest nearby structure of a + /// given {@link StructureType}. /// - /// If multiple biomes are provided {@link BiomeSearchResult#getBiome()} will - /// indicate which one was located. Higher values for {@code horizontalInterval} - /// and {@code verticalInterval} will result in faster searches, but may lead to - /// small biomes being missed. - pub fn locate_nearest_biome( + /// This method uses implementation default values for radius and + /// findUnexplored (usually 100, true). + pub fn create_explorer_map( &self, - origin: impl Into>, - radius: i32, - horizontal_interval: i32, - vertical_interval: std::option::Option, - biomes: std::option::Option>>, - ) -> Result>, Box> { + world: impl Into>, + location: impl Into>, + structure_type: impl Into>, + radius: std::option::Option, + find_unexplored: std::option::Option, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; + sig += "Lorg/bukkit/World;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(origin.into().jni_object().clone()) + jni::objects::JObject::from_raw(world.into().jni_object().clone()) }); args.push(val_1); - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(radius); + sig += "Lorg/bukkit/Location;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); args.push(val_2); - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(horizontal_interval); + sig += "Lorg/bukkit/StructureType;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(structure_type.into().jni_object().clone()) + }); args.push(val_3); - if let Some(a) = vertical_interval { + if let Some(a) = radius { sig += "I"; let val_4 = jni::objects::JValueGen::Int(a); args.push(val_4); } - if let Some(a) = biomes { - sig += "Lorg/bukkit/block/Biome;"; - let val_5 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); + if let Some(a) = find_unexplored { + sig += "Z"; + let val_5 = jni::objects::JValueGen::Bool(a.into()); args.push(val_5); } - sig += ")Lorg/bukkit/util/BiomeSearchResult;"; + sig += ")Lorg/bukkit/inventory/ItemStack;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createExplorerMap", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Reloads the server, refreshing settings and plugin information. + pub fn reload(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "reload", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Reload only the Minecraft data for the server. This includes custom + /// advancements and loot tables. + pub fn reload_data(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "reloadData", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns the primary logger associated with this server instance. + pub fn logger( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/logging/Logger;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLogger", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::logging::JavaLogger::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets a {@link PluginCommand} with the given name or alias. + pub fn get_plugin_command( + &self, + name: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/command/PluginCommand;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "locateNearestBiome", + "getPluginCommand", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::util::BiomeSearchResult::from_raw( + Ok(Some(crate::command::PluginCommand::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Finds the nearest raid close to the given location. - pub fn locate_nearest_raid( + /// Writes loaded players to disk. + pub fn save_players(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "savePlayers", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Dispatches a command on this server, and executes it if found. + pub fn dispatch_command( &self, - location: impl Into>, - radius: i32, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Location;I)Lorg/bukkit/Raid;"); + sender: impl Into>, + command_line: impl Into, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/command/CommandSender;Ljava/lang/String;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Int(radius); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(command_line.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "locateNearestRaid", + "dispatchCommand", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), @@ -14921,1914 +69463,1505 @@ impl<'mc> World<'mc> { ], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Raid::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(res.z()?) } - /// Gets all raids that are going on over this world. - pub fn raids(&self) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getRaids", sig.as_str(), vec![]); + /// Adds a recipe to the crafting manager. + pub fn add_recipe( + &self, + recipe: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/inventory/Recipe;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(recipe.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addRecipe", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get a list of all recipes for a given item. The stack size is ignored + /// in comparisons. If the durability is -1, it will match any data value. + pub fn get_recipes_for( + &self, + result: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/inventory/ItemStack;)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(result.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getRecipesFor", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::Raid::from_raw(&self.jni_ref(), obj)?); + new_vec.push(crate::inventory::Recipe::from_raw(&self.jni_ref(), obj)?); } Ok(new_vec) } - /// Get the {@link DragonBattle} associated with this world. - /// If this world's environment is not {@link Environment#THE_END}, null will - /// be returned. - /// - /// If an end world, a dragon battle instance will be returned regardless of - /// whether or not a dragon is present in the world or a fight sequence has - /// been activated. The dragon battle instance acts as a state holder. - pub fn ender_dragon_battle( + /// Get the {@link Recipe} for the given key. + pub fn get_recipe( &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/boss/DragonBattle;"); + recipe_key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/inventory/Recipe;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(recipe_key.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getEnderDragonBattle", + "getRecipe", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::boss::DragonBattle::from_raw( + Ok(Some(crate::inventory::Recipe::from_raw( &self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, )?)) } - /// Get all {@link FeatureFlag} enabled in this world. - pub fn feature_flags( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFeatureFlags", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets all generated structures of a given {@link Structure} that intersect - /// the chunk at the given coordinates. - /// - /// If no structures are present an empty collection will be returned. - pub fn get_structures( - &self, - x: i32, - z: i32, - structure: std::option::Option>>, - ) -> Result>, Box> - { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); - args.push(val_1); - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(z); - args.push(val_2); - if let Some(a) = structure { - sig += "Lorg/bukkit/generator/structure/Structure;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_3); - } - sig += ")Ljava/util/Collection;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getStructures", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::generator::structure::GeneratedStructure::from_raw( - &self.jni_ref(), - obj, - )?); - } - Ok(new_vec) - } - /// Gets the {@link BlockState} at the given coordinates. - pub fn get_block_state( - &self, - x: i32, - y: std::option::Option, - z: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); - args.push(val_1); - if let Some(a) = y { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - if let Some(a) = z { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - sig += ")Lorg/bukkit/block/BlockState;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBlockState", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the {@link BlockData} at the given coordinates. - pub fn get_block_data( - &self, - x: i32, - y: std::option::Option, - z: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); - args.push(val_1); - if let Some(a) = y { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - if let Some(a) = z { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - sig += ")Lorg/bukkit/block/data/BlockData;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBlockData", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the type of the block at the given coordinates. - pub fn get_type( - &self, - x: i32, - y: std::option::Option, - z: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); - args.push(val_1); - if let Some(a) = y { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - if let Some(a) = z { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - sig += ")Lorg/bukkit/Material;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the {@link BlockData} at the given coordinates. - pub fn set_block_data( + /// Get the {@link Recipe} for the list of ItemStacks provided. + /// The list is formatted as a crafting matrix where the index follow + /// the pattern below: + ///
    +    /// [ 0 1 2 ]
    +    /// [ 3 4 5 ]
    +    /// [ 6 7 8 ]
    +    /// 
    + /// NOTE: This method will not modify the provided ItemStack array, for that, use + /// {@link #craftItem(ItemStack[], World, Player)}. + pub fn get_crafting_recipe( &self, - x: i32, - y: i32, - z: std::option::Option, - block_data: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); - args.push(val_1); - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(y); - args.push(val_2); - if let Some(a) = z { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - if let Some(a) = block_data { - sig += "Lorg/bukkit/block/data/BlockData;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_4); + crafting_matrix: impl Into>, + world: impl Into>, + ) -> Result>, Box> { + let sig = String::from( + "(Lorg/bukkit/inventory/ItemStack;Lorg/bukkit/World;)Lorg/bukkit/inventory/Recipe;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(crafting_matrix.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(world.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCraftingRecipe", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setBlockData", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(Some(crate::inventory::Recipe::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Sets the {@link Material} at the given coordinates. - pub fn set_type( + /// Get the crafted item using the list of {@link ItemStack} provided. + /// The list is formatted as a crafting matrix where the index follow + /// the pattern below: + ///
    +    /// [ 0 1 2 ]
    +    /// [ 3 4 5 ]
    +    /// [ 6 7 8 ]
    +    /// 
    + /// The {@link World} and {@link Player} arguments are required to fulfill the Bukkit Crafting + /// events. + /// Calls {@link org.bukkit.event.inventory.PrepareItemCraftEvent} to imitate the {@link Player} + /// initiating the crafting event. + pub fn craft_item( &self, - x: i32, - y: i32, - z: std::option::Option, - material: std::option::Option>>, - ) -> Result<(), Box> { + crafting_matrix: impl Into>, + world: impl Into>, + player: std::option::Option>>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); + sig += "Lorg/bukkit/inventory/ItemStack;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(crafting_matrix.into().jni_object().clone()) + }); args.push(val_1); - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(y); + sig += "Lorg/bukkit/World;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(world.into().jni_object().clone()) + }); args.push(val_2); - if let Some(a) = z { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - if let Some(a) = material { - sig += "Lorg/bukkit/Material;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { + if let Some(a) = player { + sig += "Lorg/bukkit/entity/Player;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); - args.push(val_4); + args.push(val_3); } - sig += ")V"; + sig += ")Lorg/bukkit/inventory/ItemStack;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "setType", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "craftItem", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Creates a new entity at the given {@link Location}. - pub fn spawn_entity( + /// Get the crafted item using the list of {@link ItemStack} provided. + /// The list is formatted as a crafting matrix where the index follow + /// the pattern below: + ///
    +    /// [ 0 1 2 ]
    +    /// [ 3 4 5 ]
    +    /// [ 6 7 8 ]
    +    /// 
    + /// The {@link World} and {@link Player} arguments are required to fulfill the Bukkit Crafting + /// events. + /// Calls {@link org.bukkit.event.inventory.PrepareItemCraftEvent} to imitate the {@link Player} + /// initiating the crafting event. + pub fn craft_item_result( &self, - loc: impl Into>, - val_type: impl Into>, - randomize_data: std::option::Option, - ) -> Result, Box> { + crafting_matrix: impl Into>, + world: impl Into>, + player: std::option::Option>>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; + sig += "Lorg/bukkit/inventory/ItemStack;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + jni::objects::JObject::from_raw(crafting_matrix.into().jni_object().clone()) }); args.push(val_1); - sig += "Lorg/bukkit/entity/EntityType;"; + sig += "Lorg/bukkit/World;"; let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(world.into().jni_object().clone()) }); args.push(val_2); - if let Some(a) = randomize_data { - sig += "Z"; - let val_3 = jni::objects::JValueGen::Bool(a.into()); + if let Some(a) = player { + sig += "Lorg/bukkit/entity/Player;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); args.push(val_3); } - sig += ")Lorg/bukkit/entity/Entity;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "spawnEntity", sig.as_str(), args); + sig += ")Lorg/bukkit/inventory/ItemCraftResult;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "craftItemResult", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + crate::inventory::ItemCraftResult::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Creates an entity of a specific class at the given {@link Location} but - /// does not spawn it in the world. - /// - /// Note: The created entity keeps a reference to the world it was - /// created in, care should be taken that the entity does not outlive the - /// world instance as this will lead to memory leaks. - pub fn create_entity( + /// Get an iterator through the list of crafting recipes. + pub fn recipe_iterator( &self, - location: impl Into>, - clazz: jni::objects::JClass<'mc>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/Location;Ljava/lang/Class;)LT;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(clazz.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "createEntity", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Iterator;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "recipeIterator", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) + blackboxmc_java::util::JavaIterator::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the highest coordinate corresponding to the {@link HeightMap} at the - /// given {@link Location}. - pub fn get_highest_block_yat( + /// Clears the list of crafting recipes. + pub fn clear_recipes(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "clearRecipes", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Resets the list of crafting recipes to the default. + pub fn reset_recipes(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "resetRecipes", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Remove a recipe from the server. + /// Note that removing a recipe may cause permanent loss of data + /// associated with that recipe (eg whether it has been discovered by + /// players). + pub fn remove_recipe( &self, - location: impl Into>, - height_map: std::option::Option>>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; + key: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)Z"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) + jni::objects::JObject::from_raw(key.into().jni_object().clone()) }); - args.push(val_1); - if let Some(a) = height_map { - sig += "Lorg/bukkit/HeightMap;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")I"; let res = self.jni_ref().call_method( &self.jni_object(), - "getHighestBlockYAt", + "removeRecipe", sig.as_str(), - args, + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Spawns a previously created entity in the world. - /// - /// The provided entity must not have already been spawned in a world. - pub fn add_entity( + /// Gets a list of command aliases defined in the server properties. + pub fn command_aliases( &self, - entity: jni::objects::JObject<'mc>, - ) -> Result, Box> { - let sig = String::from("(LT;)LT;"); - let val_1 = jni::objects::JValueGen::Object(entity); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Map;"); let res = self.jni_ref().call_method( &self.jni_object(), - "addEntity", + "getCommandAliases", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) - } - /// Gets the unique name of this world - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Gets the Unique ID of this world - pub fn uid(&self) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getUID", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the {@link World.Environment} type of this world - pub fn environment(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World/Environment;"); + /// Gets the radius, in blocks, around each worlds spawn point to protect. + pub fn spawn_radius(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getEnvironment", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSpawnRadius", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::WorldEnvironment::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Gets the Seed for this world. - pub fn seed(&self) -> Result> { - let sig = String::from("()J"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSeed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + /// Sets the radius, in blocks, around each worlds spawn point to protect. + pub fn set_spawn_radius(&self, value: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(value); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSpawnRadius", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the minimum height of this world. - /// - /// If the min height is 0, there are only blocks from y=0. - pub fn min_height(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMinHeight", sig.as_str(), vec![]); + #[deprecated] + /// Gets whether the server should send a preview of the player's chat message to the client when the player types a message + pub fn should_send_chat_previews(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "shouldSendChatPreviews", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Gets the maximum height of this world. - /// - /// If the max height is 100, there are only blocks from y=0 to y=99. - pub fn max_height(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMaxHeight", sig.as_str(), vec![]); + /// Gets whether the server only allow players with Mojang-signed public key + /// to join + pub fn is_enforcing_secure_profiles(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isEnforcingSecureProfiles", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sends this recipient a Plugin Message on the specified outgoing - /// channel. - /// - /// The message may not be larger than {@link Messenger#MAX_MESSAGE_SIZE} - /// bytes, and the plugin must be registered to send messages on the - /// specified channel. - pub fn send_plugin_message( - &self, - source: impl Into>, - channel: impl Into, - message: i8, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;Ljava/lang/String;B)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(source.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(channel.into())?, - )); - let val_3 = jni::objects::JValueGen::Byte(message); + /// Gets whether this server is allowing connections transferred from other + /// servers. + pub fn is_accepting_transfers(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "sendPluginMessage", + "isAcceptingTransfers", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets a set containing all the Plugin Channels that this client is - /// listening on. - pub fn listening_plugin_channels( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); + /// Gets whether the Server hide online players in server status. + pub fn hide_online_players(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref().call_method( &self.jni_object(), - "getListeningPluginChannels", + "getHideOnlinePlayers", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets a metadata value in the implementing object's metadata store. - pub fn set_metadata( - &self, - metadata_key: impl Into, - new_metadata_value: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - if let Some(a) = new_metadata_value { - sig += "Lorg/bukkit/metadata/MetadataValue;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; + /// Gets whether the Server is in online mode or not. + pub fn online_mode(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getOnlineMode", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets whether this server allows flying or not. + pub fn allow_flight(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAllowFlight", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets whether the server is in hardcore mode or not. + pub fn is_hardcore(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isHardcore", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Shutdowns the server, stopping everything. + pub fn shutdown(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self .jni_ref() - .call_method(&self.jni_object(), "setMetadata", sig.as_str(), args); + .call_method(&self.jni_object(), "shutdown", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } - /// Returns a list of previously set metadata values from the implementing - /// object's metadata store. - pub fn get_metadata( + /// Broadcasts the specified message to every user with the given + /// permission name. + pub fn broadcast( &self, - metadata_key: impl Into, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; + message: impl Into, + permission: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;Ljava/lang/String;)I"); let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, + self.jni_ref().new_string(message.into())?, )); - args.push(val_1); - sig += ")Ljava/util/List;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getMetadata", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::metadata::MetadataValue::from_raw( - &self.jni_ref(), - obj, - )?); - } - Ok(new_vec) - } - /// Tests to see whether the implementing object contains the given - /// metadata value in its metadata store. - pub fn has_metadata( - &self, - metadata_key: impl Into, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(permission.into())?, )); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasMetadata", sig.as_str(), args); + let res = self.jni_ref().call_method( + &self.jni_object(), + "broadcast", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Removes the given metadata value from the implementing object's - /// metadata store. - pub fn remove_metadata( + /// Gets the player by the given UUID, regardless if they are offline or + /// online. + /// + /// This will return an object even if the player does not exist. To this + /// method, all players will exist. + pub fn get_offline_player( &self, - metadata_key: impl Into, - owning_plugin: impl Into>, - ) -> Result<(), Box> { + id: impl Into>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - sig += "Lorg/bukkit/plugin/Plugin;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + sig += "Ljava/util/UUID;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(id.into().jni_object().clone()) }); - args.push(val_2); - sig += ")V"; + args.push(val_1); + sig += ")Lorg/bukkit/OfflinePlayer;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "removeMetadata", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getOfflinePlayer", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::OfflinePlayer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns a custom tag container capable of storing tags on the object. - /// Note that the tags stored on this container are all stored under their - /// own custom namespace therefore modifying default tags using this - /// {@link PersistentDataHolder} is impossible. - pub fn persistent_data_container( + /// Creates a new {@link PlayerProfile}. + pub fn create_player_profile( &self, - ) -> Result, Box> { - let args = Vec::new(); + unique_id: impl Into>, + name: std::option::Option>, + ) -> Result, Box> { + let mut args = Vec::new(); let mut sig = String::from("("); - sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; + sig += "Ljava/util/UUID;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(unique_id.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = name { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_2); + } + sig += ")Lorg/bukkit/profile/PlayerProfile;"; let res = self.jni_ref().call_method( &self.jni_object(), - "getPersistentDataContainer", + "createPlayerProfile", sig.as_str(), args, ); let res = self.jni_ref().translate_error(res)?; - crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + crate::profile::PlayerProfile::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Return the namespaced identifier for this object. - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + /// Gets a set containing all current IPs that are banned. + pub fn ipbans( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getIPBans", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for World<'mc> { - fn into(self) -> crate::RegionAccessor<'mc> { - crate::RegionAccessor::from_raw(&self.jni_ref(), self.1) - .expect("Error converting World into crate::RegionAccessor") - } -} -impl<'mc> Into> for World<'mc> { - fn into(self) -> crate::generator::WorldInfo<'mc> { - crate::generator::WorldInfo::from_raw(&self.jni_ref(), self.1) - .expect("Error converting World into crate::generator::WorldInfo") - } -} -impl<'mc> Into> for World<'mc> { - fn into(self) -> crate::plugin::messaging::PluginMessageRecipient<'mc> { - crate::plugin::messaging::PluginMessageRecipient::from_raw(&self.jni_ref(), self.1) - .expect("Error converting World into crate::plugin::messaging::PluginMessageRecipient") - } -} -impl<'mc> Into> for World<'mc> { - fn into(self) -> crate::metadata::Metadatable<'mc> { - crate::metadata::Metadatable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting World into crate::metadata::Metadatable") - } -} -impl<'mc> Into> for World<'mc> { - fn into(self) -> crate::persistence::PersistentDataHolder<'mc> { - crate::persistence::PersistentDataHolder::from_raw(&self.jni_ref(), self.1) - .expect("Error converting World into crate::persistence::PersistentDataHolder") - } -} -impl<'mc> Into> for World<'mc> { - fn into(self) -> crate::Keyed<'mc> { - crate::Keyed::from_raw(&self.jni_ref(), self.1) - .expect("Error converting World into crate::Keyed") - } -} -pub enum WorldEnvironment<'mc> {} -impl<'mc> std::fmt::Display for WorldEnvironment<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> WorldEnvironment<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/World/Environment"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/World/Environment;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct WorldEnvironmentStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for WorldEnvironment<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for WorldEnvironment<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate WorldEnvironment from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/World/Environment")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a WorldEnvironment object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for WorldEnvironmentStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for WorldEnvironmentStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate WorldEnvironmentStruct from null object." - ) - .into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/World/Environment")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a WorldEnvironmentStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> WorldEnvironmentStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/World/Environment;"); - let cls = jni.find_class("org/bukkit/World/Environment"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::WorldEnvironment::from_raw(&jni, obj) + /// Bans the specified address from the server. + pub fn ban_ip( + &self, + address: jni::objects::JObject<'mc>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/net/InetAddress;"; + let val_1 = jni::objects::JValueGen::Object(address); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "banIP", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - #[deprecated] - /// Gets the dimension ID of this environment - pub fn id(&self) -> Result> { - let sig = String::from("()I"); + /// Unbans the specified address from the server. + pub fn unban_ip( + &self, + address: jni::objects::JObject<'mc>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/net/InetAddress;"; + let val_1 = jni::objects::JValueGen::Object(address); + args.push(val_1); + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + .call_method(&self.jni_object(), "unbanIP", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - #[deprecated] - /// Get an environment by ID - pub fn get_environment( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - id: i32, - ) -> Result>, Box> { - let sig = String::from("(I)Lorg/bukkit/World/Environment;"); - let val_1 = jni::objects::JValueGen::Int(id); - let cls = jni.find_class("org/bukkit/World/Environment"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getEnvironment", + /// Gets a set containing all banned players. + pub fn banned_players( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBannedPlayers", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::WorldEnvironment::from_raw(&jni, obj)?)) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct Vibration<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Vibration<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Vibration<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Vibration from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Vibration")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Vibration object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} - -impl<'mc> Vibration<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - origin: impl Into>, - destination: impl Into>, - arrival_time: i32, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/Location;Lorg/bukkit/Vibration/Destination;I)V"); + /// Gets a ban list for the supplied type. + pub fn get_ban_list( + &self, + val_type: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/BanList/Type;)LT;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(origin.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(destination.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); - let val_3 = jni::objects::JValueGen::Int(arrival_time); - let cls = jni.find_class("org/bukkit/Vibration"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBanList", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error_no_gen(res)?; - crate::Vibration::from_raw(&jni, res) - } - /// Get the origin of the vibration. - pub fn origin(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getOrigin", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.l()?) } - /// Get the vibration destination. - pub fn destination( + /// Gets a set containing all player operators. + pub fn operators( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Vibration/Destination;"); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDestination", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getOperators", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::VibrationDestination::from_raw(&self.jni_ref(), unsafe { + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the vibration arrival time in ticks. - pub fn arrival_time(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getArrivalTime", sig.as_str(), vec![]); + /// Gets the default {@link GameMode} for new players. + pub fn default_game_mode(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/GameMode;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDefaultGameMode", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct VibrationDestination<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for VibrationDestination<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for VibrationDestination<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate VibrationDestination from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Vibration/Destination")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a VibrationDestination object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> VibrationDestination<'mc> { - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct VibrationDestinationEntityDestination<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for VibrationDestinationEntityDestination<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for VibrationDestinationEntityDestination<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate VibrationDestinationEntityDestination from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/Vibration/Destination/EntityDestination")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a VibrationDestinationEntityDestination object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + crate::GameMode::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} - -impl<'mc> VibrationDestinationEntityDestination<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - entity: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); + /// Sets the default {@link GameMode} for new players. + pub fn set_default_game_mode( + &self, + mode: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/GameMode;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + jni::objects::JObject::from_raw(mode.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/Vibration/Destination/EntityDestination"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDefaultGameMode", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error_no_gen(res)?; - crate::VibrationDestinationEntityDestination::from_raw(&jni, res) + self.jni_ref().translate_error(res)?; + Ok(()) } - - pub fn entity(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/Entity;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); + /// Gets a {@link ConsoleCommandSender} that may be used as an input source + /// for this server. + pub fn console_sender( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/command/ConsoleCommandSender;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getConsoleSender", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + crate::command::ConsoleCommandSender::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for VibrationDestinationEntityDestination<'mc> { - fn into(self) -> crate::VibrationDestination<'mc> { - crate::VibrationDestination::from_raw(&self.jni_ref(), self.1).expect("Error converting VibrationDestinationEntityDestination into crate::VibrationDestination") - } -} -#[repr(C)] -pub struct VibrationDestinationBlockDestination<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for VibrationDestinationBlockDestination<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Gets every player that has ever played on this server. + pub fn offline_players(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/OfflinePlayer;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getOfflinePlayers", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::OfflinePlayer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets the {@link Messenger} responsible for this server. + pub fn messenger( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/plugin/messaging/Messenger;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMessenger", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::plugin::messaging::Messenger::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> JNIInstantiatable<'mc> for VibrationDestinationBlockDestination<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate VibrationDestinationBlockDestination from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/Vibration/Destination/BlockDestination")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a VibrationDestinationBlockDestination object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Gets the {@link HelpMap} providing help topics for this server. + pub fn help_map(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/help/HelpMap;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHelpMap", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::help::HelpMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} - -impl<'mc> VibrationDestinationBlockDestination<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - block: impl Into>, - ) -> Result, Box> { + /// Creates an empty inventory of type {@link InventoryType#CHEST} with the + /// specified size and title. + pub fn create_inventory( + &self, + owner: impl Into>, + size: i32, + title: std::option::Option>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/block/Block;"; + sig += "Lorg/bukkit/inventory/InventoryHolder;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(block.into().jni_object().clone()) + jni::objects::JObject::from_raw(owner.into().jni_object().clone()) }); args.push(val_1); - sig += ")V"; - let cls = jni.find_class("org/bukkit/Vibration/Destination/BlockDestination"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::VibrationDestinationBlockDestination::from_raw(&jni, res) - } - - pub fn location(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(size); + args.push(val_2); + if let Some(a) = title { + sig += "Ljava/lang/String;"; + let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_3); + } + sig += ")Lorg/bukkit/inventory/Inventory;"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "createInventory", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { + crate::inventory::Inventory::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn block(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); + /// Creates an empty merchant. + pub fn create_merchant( + &self, + title: impl Into, + ) -> Result, Box> { + let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/inventory/Merchant;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(title.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "createMerchant", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { + crate::inventory::Merchant::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + /// Gets the amount of consecutive neighbor updates before skipping + /// additional ones. + pub fn max_chained_neighbor_updates(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaxChainedNeighborUpdates", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} -impl<'mc> Into> for VibrationDestinationBlockDestination<'mc> { - fn into(self) -> crate::VibrationDestination<'mc> { - crate::VibrationDestination::from_raw(&self.jni_ref(), self.1).expect("Error converting VibrationDestinationBlockDestination into crate::VibrationDestination") + #[deprecated] + /// Gets user-specified limit for number of monsters that can spawn in a chunk. + pub fn monster_spawn_limit(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMonsterSpawnLimit", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} -pub enum ChatColor<'mc> { - ColorChar { inner: ChatColorStruct<'mc> }, -} -impl<'mc> std::fmt::Display for ChatColor<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - ChatColor::ColorChar { .. } => f.write_str("COLOR_CHAR"), - } + #[deprecated] + /// Gets user-specified limit for number of animals that can spawn in a chunk. + pub fn animal_spawn_limit(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAnimalSpawnLimit", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} - -impl<'mc> ChatColor<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/ChatColor"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/ChatColor;", + #[deprecated] + /// Gets user-specified limit for number of water animals that can spawn in a chunk. + pub fn water_animal_spawn_limit(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getWaterAnimalSpawnLimit", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + #[deprecated] + /// Gets user-specified limit for number of water ambient mobs that can spawn in a chunk. + pub fn water_ambient_spawn_limit(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getWaterAmbientSpawnLimit", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + #[deprecated] + /// Get user-specified limit for number of water creature underground that can spawn in a chunk. + pub fn water_underground_creature_spawn_limit( + &self, + ) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getWaterUndergroundCreatureSpawnLimit", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + #[deprecated] + /// Gets user-specified limit for number of ambient mobs that can spawn in a chunk. + pub fn ambient_spawn_limit(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAmbientSpawnLimit", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets user-specified limit for number of {@link SpawnCategory} mobs that can spawn in + /// a chunk. + /// Note: the {@link SpawnCategory#MISC} are not consider. + pub fn get_spawn_limit( + &self, + spawn_category: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/entity/SpawnCategory;)I"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(spawn_category.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSpawnLimit", + sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Checks the current thread against the expected primary thread for the + /// server. + /// + /// Note: this method should not be used to indicate the current + /// synchronized state of the runtime. A current thread matching the main + /// thread indicates that it is synchronized, but a mismatch does not + /// preclude the same assumption. + pub fn is_primary_thread(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isPrimaryThread", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the message that is displayed on the server list. + pub fn motd(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getMotd", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? .to_string_lossy() - .to_string(); - match variant_str.as_str() { - "COLOR_CHAR" => Ok(ChatColor::ColorChar { - inner: ChatColorStruct::from_raw(env, obj)?, - }), - - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + .to_string()) } -} - -#[repr(C)] -pub struct ChatColorStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for ChatColor<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self { - Self::ColorChar { inner } => inner.0.clone(), - } + /// Set the message that is displayed on the server list. + pub fn set_motd(&self, motd: impl Into) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(motd.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMotd", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self { - Self::ColorChar { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - } + /// Gets the server links which will be sent to clients + pub fn server_links(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/ServerLinks;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getServerLinks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::ServerLinks::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> JNIInstantiatable<'mc> for ChatColor<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ChatColor from null object.").into()); + /// Gets the default message that is displayed when the server is stopped. + pub fn shutdown_message(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getShutdownMessage", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/ChatColor")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ChatColor object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? .to_string_lossy() - .to_string(); - match variant_str.as_str() { - "COLOR_CHAR" => Ok(ChatColor::ColorChar { - inner: ChatColorStruct::from_raw(env, obj)?, - }), - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } + .to_string(), + )) } -} - -impl<'mc> JNIRaw<'mc> for ChatColorStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Gets the current warning state for the server. + pub fn warning_state( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Warning/WarningState;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getWarningState", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::WarningWarningState::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets the instance of the item factory (for {@link ItemMeta}). + pub fn item_factory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/inventory/ItemFactory;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemFactory", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemFactory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> JNIInstantiatable<'mc> for ChatColorStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate ChatColorStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/ChatColor")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ChatColorStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + /// Gets the instance of the entity factory (for {@link EntitySnapshot}). + pub fn entity_factory( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityFactory;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getEntityFactory", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::entity::EntityFactory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the instance of the scoreboard manager. + /// + /// This will only exist after the first world has loaded. + pub fn scoreboard_manager( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/scoreboard/ScoreboardManager;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getScoreboardManager", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some(crate::scoreboard::ScoreboardManager::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } -} - -impl<'mc> ChatColorStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/ChatColor;"); - let cls = jni.find_class("org/bukkit/ChatColor"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::ChatColor::from_raw(&jni, obj) + /// Get (or create) a new {@link Criteria} by its name. + pub fn get_scoreboard_criteria( + &self, + name: impl Into, + ) -> Result, Box> { + let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/scoreboard/Criteria;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getScoreboardCriteria", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::scoreboard::Criteria::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the char value associated with this color - pub fn char(&self) -> Result> { - let sig = String::from("()C"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getChar", sig.as_str(), vec![]); + /// Gets an instance of the server's default server-icon. + pub fn server_icon( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/util/CachedServerIcon;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getServerIcon", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.c()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::util::CachedServerIcon::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + /// Creates a cached server-icon for the specific image. + /// + /// Size and type are implementation defined. An incompatible file is + /// guaranteed to throw an implementation-defined {@link Exception}. + pub fn load_server_icon( + &self, + image: jni::objects::JObject<'mc>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/awt/image/BufferedImage;"; + let val_1 = jni::objects::JValueGen::Object(image); + args.push(val_1); + sig += ")Lorg/bukkit/util/CachedServerIcon;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "loadServerIcon", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + crate::util::CachedServerIcon::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Checks if this code is a format code as opposed to a color code. - pub fn is_format(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isFormat", sig.as_str(), vec![]); + /// Set the idle kick timeout. Any players idle for the specified amount of + /// time will be automatically kicked. + /// + /// A value of 0 will disable the idle kick timeout. + pub fn set_idle_timeout(&self, threshold: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(threshold); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setIdleTimeout", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the idle kick timeout. + pub fn idle_timeout(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getIdleTimeout", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Checks if this code is a color code as opposed to a format code. - pub fn is_color(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isColor", sig.as_str(), vec![]); + /// Create a ChunkData for use in a generator. + /// See {@link ChunkGenerator#generateChunkData(org.bukkit.World, java.util.Random, int, int, org.bukkit.generator.ChunkGenerator.BiomeGrid)} + pub fn create_chunk_data( + &self, + world: impl Into>, + ) -> Result, Box> { + let sig = + String::from("(Lorg/bukkit/World;)Lorg/bukkit/generator/ChunkGenerator/ChunkData;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(world.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "createChunkData", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::generator::ChunkGeneratorChunkData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the color represented by the specified color code - pub fn get_by_char( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - code: impl Into, - ) -> Result>, Box> { + /// Creates a boss bar instance to display to players. The progress defaults + /// to 1.0. + /// + /// This instance is added to the persistent storage of the server and will + /// be editable by commands and restored after restart. + pub fn create_boss_bar( + &self, + key: impl Into>, + title: impl Into, + color: impl Into>, + style: impl Into>, + flags: std::option::Option>>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); + sig += "Lorg/bukkit/NamespacedKey;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(key.into().jni_object().clone()) + }); + args.push(val_1); sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(code.into())?, + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(title.into())?, )); - args.push(val_1); - sig += ")Lorg/bukkit/ChatColor;"; - let cls = jni.find_class("org/bukkit/ChatColor"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getByChar", sig.as_str(), args); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + args.push(val_2); + sig += "Lorg/bukkit/boss/BarColor;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(color.into().jni_object().clone()) + }); + args.push(val_3); + sig += "Lorg/bukkit/boss/BarStyle;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(style.into().jni_object().clone()) + }); + args.push(val_4); + if let Some(a) = flags { + sig += "Lorg/bukkit/boss/BarFlag;"; + let val_5 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_5); } - let obj = res.l()?; - Ok(Some(crate::ChatColor::from_raw(&jni, obj)?)) + sig += ")Lorg/bukkit/boss/KeyedBossBar;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createBossBar", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::boss::KeyedBossBar::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Strips the given message of all color codes - pub fn strip_color( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - input: impl Into, - ) -> Result, Box> { - let sig = String::from("(Ljava/lang/String;)Ljava/lang/String;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(input.into())?, - )); - let cls = jni.find_class("org/bukkit/ChatColor"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "stripColor", + /// Gets an unmodifiable iterator through all persistent bossbars. + ///
      + ///
    • not bound to a {@link org.bukkit.entity.Boss}
    • + ///
    • + /// not created using + /// {@link #createBossBar(String, BarColor, BarStyle, BarFlag...)} + ///
    • + ///
    + /// e.g. bossbars created using the bossbar command + pub fn boss_bars( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Iterator;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBossBars", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaIterator::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the {@link KeyedBossBar} specified by this key. + ///
      + ///
    • not bound to a {@link org.bukkit.entity.Boss}
    • + ///
    • + /// not created using + /// {@link #createBossBar(String, BarColor, BarStyle, BarFlag...)} + ///
    • + ///
    + /// e.g. bossbars created using the bossbar command + pub fn get_boss_bar( + &self, + key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/boss/KeyedBossBar;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(key.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBossBar", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error(res)?; + let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some( - jni.get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(Some(crate::boss::KeyedBossBar::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Translates a string using an alternate color code character into a - /// string that uses the internal ChatColor.COLOR_CODE color code - /// character. The alternate color code character will only be replaced if - /// it is immediately followed by 0-9, A-F, a-f, K-O, k-o, R or r. - pub fn translate_alternate_color_codes( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - alt_color_char: u16, - text_to_translate: impl Into, - ) -> Result> { - let sig = String::from("(CLjava/lang/String;)Ljava/lang/String;"); - let val_1 = jni::objects::JValueGen::Char(alt_color_char); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(text_to_translate.into())?, - )); - let cls = jni.find_class("org/bukkit/ChatColor"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "translateAlternateColorCodes", + /// Removes a {@link KeyedBossBar} specified by this key. + ///
      + ///
    • not bound to a {@link org.bukkit.entity.Boss}
    • + ///
    • + /// not created using + /// {@link #createBossBar(String, BarColor, BarStyle, BarFlag...)} + ///
    • + ///
    + /// e.g. bossbars created using the bossbar command + pub fn remove_boss_bar( + &self, + key: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(key.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeBossBar", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error(res)?; - Ok(jni - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the ChatColors used at the end of the given input string. - pub fn get_last_colors( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - input: impl Into, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;)Ljava/lang/String;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(input.into())?, - )); - let cls = jni.find_class("org/bukkit/ChatColor"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getLastColors", + /// Gets an entity on the server by its UUID + pub fn get_entity( + &self, + uuid: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Ljava/util/UUID;)Lorg/bukkit/entity/Entity;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(uuid.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getEntity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error(res)?; - Ok(jni - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct Note<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Note<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Note<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Note from null object.").into()); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Note")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Note object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + Ok(Some(crate::entity::Entity::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Get the advancement specified by this key. + pub fn get_advancement( + &self, + key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/advancement/Advancement;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(key.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAdvancement", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some(crate::advancement::Advancement::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } -} - -impl<'mc> Note<'mc> { - /// Creates a new note. - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - octave: i32, - tone: std::option::Option>>, - sharped: std::option::Option, - ) -> Result, Box> { + /// Get an iterator through all advancements. Advancements cannot be removed + /// from this iterator, + pub fn advancement_iterator( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Iterator;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "advancementIterator", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaIterator::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Creates a new {@link BlockData} instance for the specified Material, with + /// all properties initialized to unspecified defaults, except for those + /// provided in data. + /// + /// If material is specified, then the data string must not also + /// contain the material. + pub fn create_block_data( + &self, + material: impl Into>, + data: std::option::Option>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(octave); + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); args.push(val_1); - if let Some(a) = tone { - sig += "Lorg/bukkit/Note/Tone;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - if let Some(a) = sharped { - sig += "Z"; - let val_3 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_3); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/Note"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::Note::from_raw(&jni, res) + if let Some(a) = data { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_2); + } + sig += ")Lorg/bukkit/block/data/BlockData;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "createBlockData", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Creates a new note for a flat tone, such as A-flat. - pub fn flat( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - octave: i32, - tone: impl Into>, - ) -> Result, Box> { - let sig = String::from("(ILorg/bukkit/Note/Tone;)Lorg/bukkit/Note;"); - let val_1 = jni::objects::JValueGen::Int(octave); + /// Gets a tag which has already been defined within the server. Plugins are + /// suggested to use the concrete tags in {@link Tag} rather than this method + /// which makes no guarantees about which tags are available, and may also be + /// less performant due to lack of caching. + /// + /// Tags will be searched for in an implementation specific manner, but a + /// path consisting of namespace/tags/registry/key is expected. + /// + /// Server implementations are allowed to handle only the registries + /// indicated in {@link Tag}. + pub fn get_tag( + &self, + registry: impl Into, + tag: impl Into>, + clazz: jni::objects::JClass<'mc>, + ) -> Result>, Box> { + let sig = String::from( + "(Ljava/lang/String;Lorg/bukkit/NamespacedKey;Ljava/lang/Class;)Lorg/bukkit/Tag;", + ); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(registry.into())?, + )); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tone.into().jni_object().clone()) + jni::objects::JObject::from_raw(tag.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/Note"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "flat", + let val_3 = jni::objects::JValueGen::Object(clazz.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTag", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), ], ); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::Note::from_raw(&jni, obj) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Tag::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Creates a new note for a sharp tone, such as A-sharp. - pub fn sharp( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - octave: i32, - tone: impl Into>, - ) -> Result, Box> { - let sig = String::from("(ILorg/bukkit/Note/Tone;)Lorg/bukkit/Note;"); - let val_1 = jni::objects::JValueGen::Int(octave); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tone.into().jni_object().clone()) + /// Gets the specified {@link LootTable}. + pub fn get_loot_table( + &self, + key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/loot/LootTable;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(key.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/Note"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "sharp", + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLootTable", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::Note::from_raw(&jni, obj) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::loot::LootTable::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Creates a new note for a natural tone, such as A-natural. - pub fn natural( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - octave: i32, - tone: impl Into>, - ) -> Result, Box> { - let sig = String::from("(ILorg/bukkit/Note/Tone;)Lorg/bukkit/Note;"); - let val_1 = jni::objects::JValueGen::Int(octave); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(tone.into().jni_object().clone()) + /// Selects entities using the given Vanilla selector. + /// + /// No guarantees are made about the selector format, other than they match + /// the Vanilla format for the active Minecraft version. + /// + /// Usually a selector will start with '@', unless selecting a Player in + /// which case it may simply be the Player's name or UUID. + /// + /// Note that in Vanilla, elevated permissions are usually required to use + /// '@' selectors, but this method should not check such permissions from the + /// sender. + pub fn select_entities( + &self, + sender: impl Into>, + selector: impl Into, + ) -> Result>, Box> { + let sig = + String::from("(Lorg/bukkit/command/CommandSender;Ljava/lang/String;)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sender.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/Note"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "natural", + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(selector.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "selectEntities", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), ], ); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::Note::from_raw(&jni, obj) - } - - pub fn sharped(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Note;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "sharped", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Note::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn flattened(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Note;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "flattened", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Note::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - #[deprecated] - /// Returns the internal id of this note. - pub fn id(&self) -> Result> { - let sig = String::from("()B"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) - } - /// Returns the octave of this note. - pub fn octave(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getOctave", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// Returns the tone of this note. - pub fn tone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Note/Tone;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTone", sig.as_str(), vec![]); + /// Gets the structure manager for loading and saving structures. + pub fn structure_manager( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/structure/StructureManager;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getStructureManager", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::NoteTone::from_raw(&self.jni_ref(), unsafe { + crate::structure::StructureManager::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns if this note is sharped. - pub fn is_sharped(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSharped", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the pitch of this note. This is the value used with - /// {@link World#playSound} or the /playsound command. - pub fn pitch(&self) -> Result> { - let sig = String::from("()F"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPitch", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - - pub fn hash_code(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - - pub fn equals( + /// Returns the registry for the given class. + /// + /// If no registry is present for the given class null will be returned. + /// + /// Depending on the implementation not every registry present in + /// {@link Registry} will be returned by this method. + pub fn get_registry( &self, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - let sig = String::from("(Ljava/lang/Object;)Z"); - let val_1 = jni::objects::JValueGen::Object(obj); + t_class: jni::objects::JClass<'mc>, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/Class;)Lorg/bukkit/Registry;"); + let val_1 = jni::objects::JValueGen::Object(t_class.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "equals", + "getRegistry", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Registry::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } + #[deprecated] - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + pub fn get_unsafe(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/UnsafeValues;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} - -impl<'mc> std::string::ToString for Note<'mc> { - fn to_string(&self) -> String { - match &self.internal_to_string() { - Ok(a) => a.clone(), - Err(err) => format!("Error calling Note.toString: {}", err), - } - } -} - -pub enum NoteTone<'mc> { - TonesCount { inner: NoteToneStruct<'mc> }, -} -impl<'mc> std::fmt::Display for NoteTone<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - NoteTone::TonesCount { .. } => f.write_str("TONES_COUNT"), - } - } -} - -impl<'mc> NoteTone<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/Note/Tone"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/Note/Tone;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - "TONES_COUNT" => Ok(NoteTone::TonesCount { - inner: NoteToneStruct::from_raw(env, obj)?, - }), - - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct NoteToneStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for NoteTone<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self { - Self::TonesCount { inner } => inner.0.clone(), - } - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self { - Self::TonesCount { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - } - } -} -impl<'mc> JNIInstantiatable<'mc> for NoteTone<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate NoteTone from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Note/Tone")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a NoteTone object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - "TONES_COUNT" => Ok(NoteTone::TonesCount { - inner: NoteToneStruct::from_raw(env, obj)?, - }), - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for NoteToneStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for NoteToneStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate NoteToneStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Note/Tone")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a NoteToneStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> NoteToneStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Note/Tone;"); - let cls = jni.find_class("org/bukkit/Note/Tone"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::NoteTone::from_raw(&jni, obj) - } - #[deprecated] - /// Returns the id of this tone. These method allows to return the sharped id of the tone. If the tone couldn't be sharped it always return the not sharped id of this tone. - pub fn get_id(&self, sharped: bool) -> Result> { - let sig = String::from("(Z)B"); - let val_1 = jni::objects::JValueGen::Bool(sharped.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getId", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) - } - /// Returns if this tone could be sharped. - pub fn is_sharpable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isSharpable", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getUnsafe", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::UnsafeValues::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - /// Returns if this tone id is the sharped id of the tone. - pub fn is_sharped(&self, id: i8) -> Result> { - let sig = String::from("(B)Z"); - let val_1 = jni::objects::JValueGen::Byte(id); + /// Sends this recipient a Plugin Message on the specified outgoing + /// channel. + /// + /// The message may not be larger than {@link Messenger#MAX_MESSAGE_SIZE} + /// bytes, and the plugin must be registered to send messages on the + /// specified channel. + pub fn send_plugin_message( + &self, + source: impl Into>, + channel: impl Into, + message: i8, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;Ljava/lang/String;B)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(source.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(channel.into())?, + )); + let val_3 = jni::objects::JValueGen::Byte(message); let res = self.jni_ref().call_method( &self.jni_object(), - "isSharped", + "sendPluginMessage", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - #[deprecated] - /// Returns the tone to id. Also returning the semitones. - pub fn get_by_id( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - id: i8, - ) -> Result>, Box> { - let sig = String::from("(B)Lorg/bukkit/Note/Tone;"); - let val_1 = jni::objects::JValueGen::Byte(id); - let cls = jni.find_class("org/bukkit/Note/Tone"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getById", + /// Gets a set containing all the Plugin Channels that this client is + /// listening on. + pub fn listening_plugin_channels( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getListeningPluginChannels", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::NoteTone::from_raw(&jni, obj)?)) + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -16836,85 +70969,19 @@ impl<'mc> NoteToneStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum Instrument<'mc> {} -impl<'mc> std::fmt::Display for Instrument<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> Instrument<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/Instrument"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/Instrument;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } +impl<'mc> Into> for Server<'mc> { + fn into(self) -> crate::plugin::messaging::PluginMessageRecipient<'mc> { + crate::plugin::messaging::PluginMessageRecipient::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Server into crate::plugin::messaging::PluginMessageRecipient") } } - #[repr(C)] -pub struct InstrumentStruct<'mc>( +pub struct UnsafeValues<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Instrument<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for Instrument<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Instrument from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Instrument")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Instrument object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for InstrumentStruct<'mc> { +impl<'mc> JNIRaw<'mc> for UnsafeValues<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -16922,20 +70989,18 @@ impl<'mc> JNIRaw<'mc> for InstrumentStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for InstrumentStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for UnsafeValues<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate InstrumentStruct from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate UnsafeValues from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Instrument")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/UnsafeValues")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a InstrumentStruct object, got {}", + "Invalid argument passed. Expected a UnsafeValues object, got {}", name ) .into()) @@ -16945,193 +71010,456 @@ impl<'mc> JNIInstantiatable<'mc> for InstrumentStruct<'mc> { } } -impl<'mc> InstrumentStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Instrument;"); - let cls = jni.find_class("org/bukkit/Instrument"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::Instrument::from_raw(&jni, obj) +impl<'mc> UnsafeValues<'mc> { + pub fn to_legacy( + &self, + material: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/Material;)Lorg/bukkit/Material;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "toLegacy", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the sound associated with this instrument. - /// - /// Will be null for {@link Instrument#CUSTOM_HEAD} - pub fn sound(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); + + pub fn from_legacy( + &self, + material: impl Into>, + data: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = data { + sig += "B"; + let val_2 = jni::objects::JValueGen::Byte(a); + args.push(val_2); + } + sig += ")Lorg/bukkit/block/data/BlockData;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getSound", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "fromLegacy", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::Sound::from_raw(&self.jni_ref(), unsafe { + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + }) } - #[deprecated] - pub fn get_type(&self) -> Result> { - let sig = String::from("()B"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + pub fn get_material( + &self, + material: impl Into, + version: i32, + ) -> Result, Box> { + let sig = String::from("(Ljava/lang/String;I)Lorg/bukkit/Material;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(material.into())?, + )); + let val_2 = jni::objects::JValueGen::Int(version); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaterial", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn data_version(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDataVersion", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + + pub fn modify_item_stack( + &self, + stack: impl Into>, + arguments: impl Into, + ) -> Result, Box> { + let sig = String::from( + "(Lorg/bukkit/inventory/ItemStack;Ljava/lang/String;)Lorg/bukkit/inventory/ItemStack;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(stack.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(arguments.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "modifyItemStack", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn check_supported( + &self, + pdf: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/plugin/PluginDescriptionFile;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(pdf.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "checkSupported", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn process_class( + &self, + pdf: impl Into>, + path: impl Into, + clazz: i8, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/plugin/PluginDescriptionFile;Ljava/lang/String;B)B"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(pdf.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(path.into())?, + )); + let val_3 = jni::objects::JValueGen::Byte(clazz); + let res = self.jni_ref().call_method( + &self.jni_object(), + "processClass", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.b()?) } + /// Load an advancement represented by the specified string into the server. + /// The advancement format is governed by Minecraft and has no specified + /// layout. + /// + /// It is currently a JSON object, as described by the Minecraft wiki. + /// + /// Loaded advancements will be stored and persisted across server restarts + /// and reloads. + /// + /// Callers should be prepared for {@link Exception} to be thrown. + pub fn load_advancement( + &self, + key: impl Into>, + advancement: impl Into, + ) -> Result, Box> { + let sig = String::from( + "(Lorg/bukkit/NamespacedKey;Ljava/lang/String;)Lorg/bukkit/advancement/Advancement;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(key.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(advancement.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "loadAdvancement", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + crate::advancement::Advancement::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Delete an advancement which was loaded and saved by + /// {@link #loadAdvancement(org.bukkit.NamespacedKey, java.lang.String)}. + /// + /// This method will only remove advancement from persistent storage. It + /// should be accompanied by a call to {@link Server#reloadData()} in order + /// to fully remove it from the running instance. + pub fn remove_advancement( + &self, + key: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(key.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeAdvancement", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } #[deprecated] - /// Get an instrument by its type ID. - pub fn get_by_type( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: i8, - ) -> Result>, Box> { - let sig = String::from("(B)Lorg/bukkit/Instrument;"); - let val_1 = jni::objects::JValueGen::Byte(val_type); - let cls = jni.find_class("org/bukkit/Instrument"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getByType", + + pub fn get_default_attribute_modifiers( + &self, + material: impl Into>, + slot: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/Material;Lorg/bukkit/inventory/EquipmentSlot;)Lcom/google/common/collect/Multimap;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(slot.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDefaultAttributeModifiers", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) + } + #[deprecated] + + pub fn get_creative_category( + &self, + material: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/Material;)Lorg/bukkit/inventory/CreativeCategory;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getCreativeCategory", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::Instrument::from_raw(&jni, obj)?)) + let res = self.jni_ref().translate_error(res)?; + crate::inventory::CreativeCategory::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } + #[deprecated] - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + pub fn get_block_translation_key( + &self, + material: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/Material;)Ljava/lang/String;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBlockTranslationKey", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } -} -pub enum SkullType<'mc> {} -impl<'mc> std::fmt::Display for SkullType<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + #[deprecated] + + pub fn get_item_translation_key( + &self, + material: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/Material;)Ljava/lang/String;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getItemTranslationKey", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } -} -impl<'mc> SkullType<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/SkullType"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/SkullType;", + pub fn get_translation_key( + &self, + attribute: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/attribute/Attribute;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attribute.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Ljava/lang/String;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTranslationKey", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + + pub fn get_feature_flag( + &self, + key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/FeatureFlag;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(key.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getFeatureFlag", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::FeatureFlag::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + #[deprecated] + /// Do not use, method will get removed, and the plugin won't run + pub fn get_internal_potion_data( + &self, + key: impl Into>, + ) -> Result, Box> { + let sig = String::from( + "(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/potion/PotionType/InternalPotionData;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(key.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getInternalPotionData", + sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + let res = self.jni_ref().translate_error(res)?; + crate::potion::PotionTypeInternalPotionData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} - -#[repr(C)] -pub struct SkullTypeStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); -impl<'mc> JNIRaw<'mc> for SkullType<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for SkullType<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate SkullType from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/SkullType")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a SkullType object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + pub fn get_damage_effect( + &self, + key: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/damage/DamageEffect;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(key.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDamageEffect", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some(crate::damage::DamageEffect::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } -} - -impl<'mc> JNIRaw<'mc> for SkullTypeStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for SkullTypeStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate SkullTypeStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/SkullType")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a SkullTypeStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Create a new {@link DamageSource.Builder}. + pub fn create_damage_source_builder( + &self, + damage_type: impl Into>, + ) -> Result, Box> { + let sig = String::from( + "(Lorg/bukkit/damage/DamageType;)Lorg/bukkit/damage/DamageSource/Builder;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(damage_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "createDamageSourceBuilder", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::damage::DamageSourceBuilder::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> SkullTypeStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/SkullType;"); - let cls = jni.find_class("org/bukkit/SkullType"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::SkullType::from_raw(&jni, obj) + pub fn get( + &self, + registry: impl Into>, + key: impl Into>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Registry;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(registry.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Lorg/bukkit/NamespacedKey;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(key.into().jni_object().clone()) + }); + args.push(val_2); + sig += ")LB;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "get", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -17139,143 +71467,52 @@ impl<'mc> SkullTypeStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum GameRule<'mc> { - AnnounceAdvancements { inner: GameRuleStruct<'mc> }, - CommandBlockOutput { inner: GameRuleStruct<'mc> }, - DisableElytraMovementCheck { inner: GameRuleStruct<'mc> }, - DoDaylightCycle { inner: GameRuleStruct<'mc> }, - DoEntityDrops { inner: GameRuleStruct<'mc> }, - DoFireTick { inner: GameRuleStruct<'mc> }, - DoLimitedCrafting { inner: GameRuleStruct<'mc> }, - DoMobLoot { inner: GameRuleStruct<'mc> }, - ProjectilesCanBreakBlocks { inner: GameRuleStruct<'mc> }, - DoMobSpawning { inner: GameRuleStruct<'mc> }, - DoTileDrops { inner: GameRuleStruct<'mc> }, - DoWeatherCycle { inner: GameRuleStruct<'mc> }, - KeepInventory { inner: GameRuleStruct<'mc> }, - LogAdminCommands { inner: GameRuleStruct<'mc> }, - MobGriefing { inner: GameRuleStruct<'mc> }, - NaturalRegeneration { inner: GameRuleStruct<'mc> }, - ReducedDebugInfo { inner: GameRuleStruct<'mc> }, - SendCommandFeedback { inner: GameRuleStruct<'mc> }, - ShowDeathMessages { inner: GameRuleStruct<'mc> }, - SpectatorsGenerateChunks { inner: GameRuleStruct<'mc> }, - DisableRaids { inner: GameRuleStruct<'mc> }, - DoInsomnia { inner: GameRuleStruct<'mc> }, - DoImmediateRespawn { inner: GameRuleStruct<'mc> }, - DrowningDamage { inner: GameRuleStruct<'mc> }, - FallDamage { inner: GameRuleStruct<'mc> }, - FireDamage { inner: GameRuleStruct<'mc> }, - FreezeDamage { inner: GameRuleStruct<'mc> }, - DoPatrolSpawning { inner: GameRuleStruct<'mc> }, - DoTraderSpawning { inner: GameRuleStruct<'mc> }, - DoWardenSpawning { inner: GameRuleStruct<'mc> }, - ForgiveDeadPlayers { inner: GameRuleStruct<'mc> }, - UniversalAnger { inner: GameRuleStruct<'mc> }, - BlockExplosionDropDecay { inner: GameRuleStruct<'mc> }, - MobExplosionDropDecay { inner: GameRuleStruct<'mc> }, - TntExplosionDropDecay { inner: GameRuleStruct<'mc> }, - WaterSourceConversion { inner: GameRuleStruct<'mc> }, - LavaSourceConversion { inner: GameRuleStruct<'mc> }, - GlobalSoundEvents { inner: GameRuleStruct<'mc> }, - DoVinesSpread { inner: GameRuleStruct<'mc> }, - EnderPearlsVanishOnDeath { inner: GameRuleStruct<'mc> }, - RandomTickSpeed { inner: GameRuleStruct<'mc> }, - SpawnRadius { inner: GameRuleStruct<'mc> }, - MaxEntityCramming { inner: GameRuleStruct<'mc> }, - MaxCommandChainLength { inner: GameRuleStruct<'mc> }, - MaxCommandForkCount { inner: GameRuleStruct<'mc> }, - CommandModificationBlockLimit { inner: GameRuleStruct<'mc> }, - PlayersSleepingPercentage { inner: GameRuleStruct<'mc> }, - SnowAccumulationHeight { inner: GameRuleStruct<'mc> }, - PlayersNetherPortalDefaultDelay { inner: GameRuleStruct<'mc> }, - PlayersNetherPortalCreativeDelay { inner: GameRuleStruct<'mc> }, - SpawnChunkRadius { inner: GameRuleStruct<'mc> }, +pub enum HeightMap<'mc> { + MotionBlocking { inner: HeightMapStruct<'mc> }, + MotionBlockingNoLeaves { inner: HeightMapStruct<'mc> }, + OceanFloor { inner: HeightMapStruct<'mc> }, + OceanFloorWg { inner: HeightMapStruct<'mc> }, + WorldSurface { inner: HeightMapStruct<'mc> }, + WorldSurfaceWg { inner: HeightMapStruct<'mc> }, } -impl<'mc> std::fmt::Display for GameRule<'mc> { +impl<'mc> std::fmt::Display for HeightMap<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - GameRule::AnnounceAdvancements { .. } => f.write_str("ANNOUNCE_ADVANCEMENTS"), - GameRule::CommandBlockOutput { .. } => f.write_str("COMMAND_BLOCK_OUTPUT"), - GameRule::DisableElytraMovementCheck { .. } => { - f.write_str("DISABLE_ELYTRA_MOVEMENT_CHECK") - } - GameRule::DoDaylightCycle { .. } => f.write_str("DO_DAYLIGHT_CYCLE"), - GameRule::DoEntityDrops { .. } => f.write_str("DO_ENTITY_DROPS"), - GameRule::DoFireTick { .. } => f.write_str("DO_FIRE_TICK"), - GameRule::DoLimitedCrafting { .. } => f.write_str("DO_LIMITED_CRAFTING"), - GameRule::DoMobLoot { .. } => f.write_str("DO_MOB_LOOT"), - GameRule::ProjectilesCanBreakBlocks { .. } => { - f.write_str("PROJECTILES_CAN_BREAK_BLOCKS") - } - GameRule::DoMobSpawning { .. } => f.write_str("DO_MOB_SPAWNING"), - GameRule::DoTileDrops { .. } => f.write_str("DO_TILE_DROPS"), - GameRule::DoWeatherCycle { .. } => f.write_str("DO_WEATHER_CYCLE"), - GameRule::KeepInventory { .. } => f.write_str("KEEP_INVENTORY"), - GameRule::LogAdminCommands { .. } => f.write_str("LOG_ADMIN_COMMANDS"), - GameRule::MobGriefing { .. } => f.write_str("MOB_GRIEFING"), - GameRule::NaturalRegeneration { .. } => f.write_str("NATURAL_REGENERATION"), - GameRule::ReducedDebugInfo { .. } => f.write_str("REDUCED_DEBUG_INFO"), - GameRule::SendCommandFeedback { .. } => f.write_str("SEND_COMMAND_FEEDBACK"), - GameRule::ShowDeathMessages { .. } => f.write_str("SHOW_DEATH_MESSAGES"), - GameRule::SpectatorsGenerateChunks { .. } => f.write_str("SPECTATORS_GENERATE_CHUNKS"), - GameRule::DisableRaids { .. } => f.write_str("DISABLE_RAIDS"), - GameRule::DoInsomnia { .. } => f.write_str("DO_INSOMNIA"), - GameRule::DoImmediateRespawn { .. } => f.write_str("DO_IMMEDIATE_RESPAWN"), - GameRule::DrowningDamage { .. } => f.write_str("DROWNING_DAMAGE"), - GameRule::FallDamage { .. } => f.write_str("FALL_DAMAGE"), - GameRule::FireDamage { .. } => f.write_str("FIRE_DAMAGE"), - GameRule::FreezeDamage { .. } => f.write_str("FREEZE_DAMAGE"), - GameRule::DoPatrolSpawning { .. } => f.write_str("DO_PATROL_SPAWNING"), - GameRule::DoTraderSpawning { .. } => f.write_str("DO_TRADER_SPAWNING"), - GameRule::DoWardenSpawning { .. } => f.write_str("DO_WARDEN_SPAWNING"), - GameRule::ForgiveDeadPlayers { .. } => f.write_str("FORGIVE_DEAD_PLAYERS"), - GameRule::UniversalAnger { .. } => f.write_str("UNIVERSAL_ANGER"), - GameRule::BlockExplosionDropDecay { .. } => f.write_str("BLOCK_EXPLOSION_DROP_DECAY"), - GameRule::MobExplosionDropDecay { .. } => f.write_str("MOB_EXPLOSION_DROP_DECAY"), - GameRule::TntExplosionDropDecay { .. } => f.write_str("TNT_EXPLOSION_DROP_DECAY"), - GameRule::WaterSourceConversion { .. } => f.write_str("WATER_SOURCE_CONVERSION"), - GameRule::LavaSourceConversion { .. } => f.write_str("LAVA_SOURCE_CONVERSION"), - GameRule::GlobalSoundEvents { .. } => f.write_str("GLOBAL_SOUND_EVENTS"), - GameRule::DoVinesSpread { .. } => f.write_str("DO_VINES_SPREAD"), - GameRule::EnderPearlsVanishOnDeath { .. } => { - f.write_str("ENDER_PEARLS_VANISH_ON_DEATH") - } - GameRule::RandomTickSpeed { .. } => f.write_str("RANDOM_TICK_SPEED"), - GameRule::SpawnRadius { .. } => f.write_str("SPAWN_RADIUS"), - GameRule::MaxEntityCramming { .. } => f.write_str("MAX_ENTITY_CRAMMING"), - GameRule::MaxCommandChainLength { .. } => f.write_str("MAX_COMMAND_CHAIN_LENGTH"), - GameRule::MaxCommandForkCount { .. } => f.write_str("MAX_COMMAND_FORK_COUNT"), - GameRule::CommandModificationBlockLimit { .. } => { - f.write_str("COMMAND_MODIFICATION_BLOCK_LIMIT") - } - GameRule::PlayersSleepingPercentage { .. } => { - f.write_str("PLAYERS_SLEEPING_PERCENTAGE") - } - GameRule::SnowAccumulationHeight { .. } => f.write_str("SNOW_ACCUMULATION_HEIGHT"), - GameRule::PlayersNetherPortalDefaultDelay { .. } => { - f.write_str("PLAYERS_NETHER_PORTAL_DEFAULT_DELAY") - } - GameRule::PlayersNetherPortalCreativeDelay { .. } => { - f.write_str("PLAYERS_NETHER_PORTAL_CREATIVE_DELAY") - } - GameRule::SpawnChunkRadius { .. } => f.write_str("SPAWN_CHUNK_RADIUS"), + HeightMap::MotionBlocking { .. } => f.write_str("MOTION_BLOCKING"), + HeightMap::MotionBlockingNoLeaves { .. } => f.write_str("MOTION_BLOCKING_NO_LEAVES"), + HeightMap::OceanFloor { .. } => f.write_str("OCEAN_FLOOR"), + HeightMap::OceanFloorWg { .. } => f.write_str("OCEAN_FLOOR_WG"), + HeightMap::WorldSurface { .. } => f.write_str("WORLD_SURFACE"), + HeightMap::WorldSurfaceWg { .. } => f.write_str("WORLD_SURFACE_WG"), + } + } +} +impl<'mc> std::ops::Deref for HeightMap<'mc> { + type Target = HeightMapStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + HeightMap::MotionBlocking { inner } => inner, + HeightMap::MotionBlockingNoLeaves { inner } => inner, + HeightMap::OceanFloor { inner } => inner, + HeightMap::OceanFloorWg { inner } => inner, + HeightMap::WorldSurface { inner } => inner, + HeightMap::WorldSurfaceWg { inner } => inner, } } } -impl<'mc> GameRule<'mc> { +impl<'mc> HeightMap<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/GameRule"); + let cls = env.find_class("org/bukkit/HeightMap"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/GameRule;", + "(Ljava/lang/String;)Lorg/bukkit/HeightMap;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -17287,401 +71524,82 @@ impl<'mc> GameRule<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { - "ANNOUNCE_ADVANCEMENTS" => Ok(GameRule::AnnounceAdvancements { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "COMMAND_BLOCK_OUTPUT" => Ok(GameRule::CommandBlockOutput { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DISABLE_ELYTRA_MOVEMENT_CHECK" => Ok(GameRule::DisableElytraMovementCheck { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_DAYLIGHT_CYCLE" => Ok(GameRule::DoDaylightCycle { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_ENTITY_DROPS" => Ok(GameRule::DoEntityDrops { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_FIRE_TICK" => Ok(GameRule::DoFireTick { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_LIMITED_CRAFTING" => Ok(GameRule::DoLimitedCrafting { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_MOB_LOOT" => Ok(GameRule::DoMobLoot { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "PROJECTILES_CAN_BREAK_BLOCKS" => Ok(GameRule::ProjectilesCanBreakBlocks { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_MOB_SPAWNING" => Ok(GameRule::DoMobSpawning { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_TILE_DROPS" => Ok(GameRule::DoTileDrops { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_WEATHER_CYCLE" => Ok(GameRule::DoWeatherCycle { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "KEEP_INVENTORY" => Ok(GameRule::KeepInventory { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "LOG_ADMIN_COMMANDS" => Ok(GameRule::LogAdminCommands { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "MOB_GRIEFING" => Ok(GameRule::MobGriefing { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "NATURAL_REGENERATION" => Ok(GameRule::NaturalRegeneration { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "REDUCED_DEBUG_INFO" => Ok(GameRule::ReducedDebugInfo { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "SEND_COMMAND_FEEDBACK" => Ok(GameRule::SendCommandFeedback { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "SHOW_DEATH_MESSAGES" => Ok(GameRule::ShowDeathMessages { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "SPECTATORS_GENERATE_CHUNKS" => Ok(GameRule::SpectatorsGenerateChunks { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DISABLE_RAIDS" => Ok(GameRule::DisableRaids { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_INSOMNIA" => Ok(GameRule::DoInsomnia { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_IMMEDIATE_RESPAWN" => Ok(GameRule::DoImmediateRespawn { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DROWNING_DAMAGE" => Ok(GameRule::DrowningDamage { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "FALL_DAMAGE" => Ok(GameRule::FallDamage { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "FIRE_DAMAGE" => Ok(GameRule::FireDamage { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "FREEZE_DAMAGE" => Ok(GameRule::FreezeDamage { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_PATROL_SPAWNING" => Ok(GameRule::DoPatrolSpawning { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_TRADER_SPAWNING" => Ok(GameRule::DoTraderSpawning { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_WARDEN_SPAWNING" => Ok(GameRule::DoWardenSpawning { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "FORGIVE_DEAD_PLAYERS" => Ok(GameRule::ForgiveDeadPlayers { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "UNIVERSAL_ANGER" => Ok(GameRule::UniversalAnger { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "BLOCK_EXPLOSION_DROP_DECAY" => Ok(GameRule::BlockExplosionDropDecay { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "MOB_EXPLOSION_DROP_DECAY" => Ok(GameRule::MobExplosionDropDecay { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "TNT_EXPLOSION_DROP_DECAY" => Ok(GameRule::TntExplosionDropDecay { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "WATER_SOURCE_CONVERSION" => Ok(GameRule::WaterSourceConversion { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "LAVA_SOURCE_CONVERSION" => Ok(GameRule::LavaSourceConversion { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "GLOBAL_SOUND_EVENTS" => Ok(GameRule::GlobalSoundEvents { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_VINES_SPREAD" => Ok(GameRule::DoVinesSpread { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "ENDER_PEARLS_VANISH_ON_DEATH" => Ok(GameRule::EnderPearlsVanishOnDeath { - inner: GameRuleStruct::from_raw(env, obj)?, + "MOTION_BLOCKING" => Ok(HeightMap::MotionBlocking { + inner: HeightMapStruct::from_raw(env, obj)?, }), - "RANDOM_TICK_SPEED" => Ok(GameRule::RandomTickSpeed { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "SPAWN_RADIUS" => Ok(GameRule::SpawnRadius { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "MAX_ENTITY_CRAMMING" => Ok(GameRule::MaxEntityCramming { - inner: GameRuleStruct::from_raw(env, obj)?, + "MOTION_BLOCKING_NO_LEAVES" => Ok(HeightMap::MotionBlockingNoLeaves { + inner: HeightMapStruct::from_raw(env, obj)?, }), - "MAX_COMMAND_CHAIN_LENGTH" => Ok(GameRule::MaxCommandChainLength { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "MAX_COMMAND_FORK_COUNT" => Ok(GameRule::MaxCommandForkCount { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "COMMAND_MODIFICATION_BLOCK_LIMIT" => Ok(GameRule::CommandModificationBlockLimit { - inner: GameRuleStruct::from_raw(env, obj)?, + "OCEAN_FLOOR" => Ok(HeightMap::OceanFloor { + inner: HeightMapStruct::from_raw(env, obj)?, }), - "PLAYERS_SLEEPING_PERCENTAGE" => Ok(GameRule::PlayersSleepingPercentage { - inner: GameRuleStruct::from_raw(env, obj)?, + "OCEAN_FLOOR_WG" => Ok(HeightMap::OceanFloorWg { + inner: HeightMapStruct::from_raw(env, obj)?, }), - "SNOW_ACCUMULATION_HEIGHT" => Ok(GameRule::SnowAccumulationHeight { - inner: GameRuleStruct::from_raw(env, obj)?, + "WORLD_SURFACE" => Ok(HeightMap::WorldSurface { + inner: HeightMapStruct::from_raw(env, obj)?, }), - "PLAYERS_NETHER_PORTAL_DEFAULT_DELAY" => { - Ok(GameRule::PlayersNetherPortalDefaultDelay { - inner: GameRuleStruct::from_raw(env, obj)?, - }) - } - "PLAYERS_NETHER_PORTAL_CREATIVE_DELAY" => { - Ok(GameRule::PlayersNetherPortalCreativeDelay { - inner: GameRuleStruct::from_raw(env, obj)?, - }) - } - "SPAWN_CHUNK_RADIUS" => Ok(GameRule::SpawnChunkRadius { - inner: GameRuleStruct::from_raw(env, obj)?, + "WORLD_SURFACE_WG" => Ok(HeightMap::WorldSurfaceWg { + inner: HeightMapStruct::from_raw(env, obj)?, }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } -} - -#[repr(C)] -pub struct GameRuleStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for GameRule<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self { - Self::AnnounceAdvancements { inner } => inner.0.clone(), - Self::CommandBlockOutput { inner } => inner.0.clone(), - Self::DisableElytraMovementCheck { inner } => inner.0.clone(), - Self::DoDaylightCycle { inner } => inner.0.clone(), - Self::DoEntityDrops { inner } => inner.0.clone(), - Self::DoFireTick { inner } => inner.0.clone(), - Self::DoLimitedCrafting { inner } => inner.0.clone(), - Self::DoMobLoot { inner } => inner.0.clone(), - Self::ProjectilesCanBreakBlocks { inner } => inner.0.clone(), - Self::DoMobSpawning { inner } => inner.0.clone(), - Self::DoTileDrops { inner } => inner.0.clone(), - Self::DoWeatherCycle { inner } => inner.0.clone(), - Self::KeepInventory { inner } => inner.0.clone(), - Self::LogAdminCommands { inner } => inner.0.clone(), - Self::MobGriefing { inner } => inner.0.clone(), - Self::NaturalRegeneration { inner } => inner.0.clone(), - Self::ReducedDebugInfo { inner } => inner.0.clone(), - Self::SendCommandFeedback { inner } => inner.0.clone(), - Self::ShowDeathMessages { inner } => inner.0.clone(), - Self::SpectatorsGenerateChunks { inner } => inner.0.clone(), - Self::DisableRaids { inner } => inner.0.clone(), - Self::DoInsomnia { inner } => inner.0.clone(), - Self::DoImmediateRespawn { inner } => inner.0.clone(), - Self::DrowningDamage { inner } => inner.0.clone(), - Self::FallDamage { inner } => inner.0.clone(), - Self::FireDamage { inner } => inner.0.clone(), - Self::FreezeDamage { inner } => inner.0.clone(), - Self::DoPatrolSpawning { inner } => inner.0.clone(), - Self::DoTraderSpawning { inner } => inner.0.clone(), - Self::DoWardenSpawning { inner } => inner.0.clone(), - Self::ForgiveDeadPlayers { inner } => inner.0.clone(), - Self::UniversalAnger { inner } => inner.0.clone(), - Self::BlockExplosionDropDecay { inner } => inner.0.clone(), - Self::MobExplosionDropDecay { inner } => inner.0.clone(), - Self::TntExplosionDropDecay { inner } => inner.0.clone(), - Self::WaterSourceConversion { inner } => inner.0.clone(), - Self::LavaSourceConversion { inner } => inner.0.clone(), - Self::GlobalSoundEvents { inner } => inner.0.clone(), - Self::DoVinesSpread { inner } => inner.0.clone(), - Self::EnderPearlsVanishOnDeath { inner } => inner.0.clone(), - Self::RandomTickSpeed { inner } => inner.0.clone(), - Self::SpawnRadius { inner } => inner.0.clone(), - Self::MaxEntityCramming { inner } => inner.0.clone(), - Self::MaxCommandChainLength { inner } => inner.0.clone(), - Self::MaxCommandForkCount { inner } => inner.0.clone(), - Self::CommandModificationBlockLimit { inner } => inner.0.clone(), - Self::PlayersSleepingPercentage { inner } => inner.0.clone(), - Self::SnowAccumulationHeight { inner } => inner.0.clone(), - Self::PlayersNetherPortalDefaultDelay { inner } => inner.0.clone(), - Self::PlayersNetherPortalCreativeDelay { inner } => inner.0.clone(), - Self::SpawnChunkRadius { inner } => inner.0.clone(), - } - } +} + +#[repr(C)] +pub struct HeightMapStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for HeightMap<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::MotionBlocking { inner } => inner.0.clone(), + Self::MotionBlockingNoLeaves { inner } => inner.0.clone(), + Self::OceanFloor { inner } => inner.0.clone(), + Self::OceanFloorWg { inner } => inner.0.clone(), + Self::WorldSurface { inner } => inner.0.clone(), + Self::WorldSurfaceWg { inner } => inner.0.clone(), + } + } fn jni_object(&self) -> jni::objects::JObject<'mc> { match self { - Self::AnnounceAdvancements { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::CommandBlockOutput { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::DisableElytraMovementCheck { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::DoDaylightCycle { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::DoEntityDrops { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::DoFireTick { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::DoLimitedCrafting { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::DoMobLoot { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::ProjectilesCanBreakBlocks { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::DoMobSpawning { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::DoTileDrops { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::DoWeatherCycle { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::KeepInventory { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::LogAdminCommands { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::MobGriefing { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::NaturalRegeneration { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::ReducedDebugInfo { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::SendCommandFeedback { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::ShowDeathMessages { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::SpectatorsGenerateChunks { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::DisableRaids { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::DoInsomnia { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::DoImmediateRespawn { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::DrowningDamage { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::FallDamage { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::FireDamage { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::FreezeDamage { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::DoPatrolSpawning { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::DoTraderSpawning { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::DoWardenSpawning { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::ForgiveDeadPlayers { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::UniversalAnger { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::BlockExplosionDropDecay { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::MobExplosionDropDecay { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::TntExplosionDropDecay { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::WaterSourceConversion { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::LavaSourceConversion { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::GlobalSoundEvents { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::DoVinesSpread { inner } => unsafe { + Self::MotionBlocking { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::EnderPearlsVanishOnDeath { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::RandomTickSpeed { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::SpawnRadius { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::MaxEntityCramming { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::MaxCommandChainLength { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::MaxCommandForkCount { inner } => unsafe { + Self::MotionBlockingNoLeaves { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::CommandModificationBlockLimit { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::PlayersSleepingPercentage { inner } => unsafe { + Self::OceanFloor { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::SnowAccumulationHeight { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::PlayersNetherPortalDefaultDelay { inner } => unsafe { + Self::OceanFloorWg { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::PlayersNetherPortalCreativeDelay { inner } => unsafe { + Self::WorldSurface { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::SpawnChunkRadius { inner } => unsafe { + Self::WorldSurfaceWg { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, } } } -impl<'mc> JNIInstantiatable<'mc> for GameRule<'mc> { +impl<'mc> JNIInstantiatable<'mc> for HeightMap<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate GameRule from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate HeightMap from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/GameRule")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/HeightMap")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a GameRule object, got {}", + "Invalid argument passed. Expected a HeightMap object, got {}", name ) .into()) @@ -17693,162 +71611,23 @@ impl<'mc> JNIInstantiatable<'mc> for GameRule<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { - "ANNOUNCE_ADVANCEMENTS" => Ok(GameRule::AnnounceAdvancements { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "COMMAND_BLOCK_OUTPUT" => Ok(GameRule::CommandBlockOutput { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DISABLE_ELYTRA_MOVEMENT_CHECK" => Ok(GameRule::DisableElytraMovementCheck { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_DAYLIGHT_CYCLE" => Ok(GameRule::DoDaylightCycle { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_ENTITY_DROPS" => Ok(GameRule::DoEntityDrops { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_FIRE_TICK" => Ok(GameRule::DoFireTick { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_LIMITED_CRAFTING" => Ok(GameRule::DoLimitedCrafting { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_MOB_LOOT" => Ok(GameRule::DoMobLoot { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "PROJECTILES_CAN_BREAK_BLOCKS" => Ok(GameRule::ProjectilesCanBreakBlocks { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_MOB_SPAWNING" => Ok(GameRule::DoMobSpawning { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_TILE_DROPS" => Ok(GameRule::DoTileDrops { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_WEATHER_CYCLE" => Ok(GameRule::DoWeatherCycle { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "KEEP_INVENTORY" => Ok(GameRule::KeepInventory { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "LOG_ADMIN_COMMANDS" => Ok(GameRule::LogAdminCommands { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "MOB_GRIEFING" => Ok(GameRule::MobGriefing { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "NATURAL_REGENERATION" => Ok(GameRule::NaturalRegeneration { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "REDUCED_DEBUG_INFO" => Ok(GameRule::ReducedDebugInfo { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "SEND_COMMAND_FEEDBACK" => Ok(GameRule::SendCommandFeedback { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "SHOW_DEATH_MESSAGES" => Ok(GameRule::ShowDeathMessages { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "SPECTATORS_GENERATE_CHUNKS" => Ok(GameRule::SpectatorsGenerateChunks { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DISABLE_RAIDS" => Ok(GameRule::DisableRaids { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_INSOMNIA" => Ok(GameRule::DoInsomnia { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_IMMEDIATE_RESPAWN" => Ok(GameRule::DoImmediateRespawn { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DROWNING_DAMAGE" => Ok(GameRule::DrowningDamage { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "FALL_DAMAGE" => Ok(GameRule::FallDamage { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "FIRE_DAMAGE" => Ok(GameRule::FireDamage { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "FREEZE_DAMAGE" => Ok(GameRule::FreezeDamage { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_PATROL_SPAWNING" => Ok(GameRule::DoPatrolSpawning { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_TRADER_SPAWNING" => Ok(GameRule::DoTraderSpawning { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_WARDEN_SPAWNING" => Ok(GameRule::DoWardenSpawning { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "FORGIVE_DEAD_PLAYERS" => Ok(GameRule::ForgiveDeadPlayers { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "UNIVERSAL_ANGER" => Ok(GameRule::UniversalAnger { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "BLOCK_EXPLOSION_DROP_DECAY" => Ok(GameRule::BlockExplosionDropDecay { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "MOB_EXPLOSION_DROP_DECAY" => Ok(GameRule::MobExplosionDropDecay { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "TNT_EXPLOSION_DROP_DECAY" => Ok(GameRule::TntExplosionDropDecay { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "WATER_SOURCE_CONVERSION" => Ok(GameRule::WaterSourceConversion { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "LAVA_SOURCE_CONVERSION" => Ok(GameRule::LavaSourceConversion { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "GLOBAL_SOUND_EVENTS" => Ok(GameRule::GlobalSoundEvents { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "DO_VINES_SPREAD" => Ok(GameRule::DoVinesSpread { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "ENDER_PEARLS_VANISH_ON_DEATH" => Ok(GameRule::EnderPearlsVanishOnDeath { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "RANDOM_TICK_SPEED" => Ok(GameRule::RandomTickSpeed { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "SPAWN_RADIUS" => Ok(GameRule::SpawnRadius { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "MAX_ENTITY_CRAMMING" => Ok(GameRule::MaxEntityCramming { - inner: GameRuleStruct::from_raw(env, obj)?, - }), - "MAX_COMMAND_CHAIN_LENGTH" => Ok(GameRule::MaxCommandChainLength { - inner: GameRuleStruct::from_raw(env, obj)?, + "MOTION_BLOCKING" => Ok(HeightMap::MotionBlocking { + inner: HeightMapStruct::from_raw(env, obj)?, }), - "MAX_COMMAND_FORK_COUNT" => Ok(GameRule::MaxCommandForkCount { - inner: GameRuleStruct::from_raw(env, obj)?, + "MOTION_BLOCKING_NO_LEAVES" => Ok(HeightMap::MotionBlockingNoLeaves { + inner: HeightMapStruct::from_raw(env, obj)?, }), - "COMMAND_MODIFICATION_BLOCK_LIMIT" => Ok(GameRule::CommandModificationBlockLimit { - inner: GameRuleStruct::from_raw(env, obj)?, + "OCEAN_FLOOR" => Ok(HeightMap::OceanFloor { + inner: HeightMapStruct::from_raw(env, obj)?, }), - "PLAYERS_SLEEPING_PERCENTAGE" => Ok(GameRule::PlayersSleepingPercentage { - inner: GameRuleStruct::from_raw(env, obj)?, + "OCEAN_FLOOR_WG" => Ok(HeightMap::OceanFloorWg { + inner: HeightMapStruct::from_raw(env, obj)?, }), - "SNOW_ACCUMULATION_HEIGHT" => Ok(GameRule::SnowAccumulationHeight { - inner: GameRuleStruct::from_raw(env, obj)?, + "WORLD_SURFACE" => Ok(HeightMap::WorldSurface { + inner: HeightMapStruct::from_raw(env, obj)?, }), - "PLAYERS_NETHER_PORTAL_DEFAULT_DELAY" => { - Ok(GameRule::PlayersNetherPortalDefaultDelay { - inner: GameRuleStruct::from_raw(env, obj)?, - }) - } - "PLAYERS_NETHER_PORTAL_CREATIVE_DELAY" => { - Ok(GameRule::PlayersNetherPortalCreativeDelay { - inner: GameRuleStruct::from_raw(env, obj)?, - }) - } - "SPAWN_CHUNK_RADIUS" => Ok(GameRule::SpawnChunkRadius { - inner: GameRuleStruct::from_raw(env, obj)?, + "WORLD_SURFACE_WG" => Ok(HeightMap::WorldSurfaceWg { + inner: HeightMapStruct::from_raw(env, obj)?, }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } @@ -17856,7 +71635,7 @@ impl<'mc> JNIInstantiatable<'mc> for GameRule<'mc> { } } -impl<'mc> JNIRaw<'mc> for GameRuleStruct<'mc> { +impl<'mc> JNIRaw<'mc> for HeightMapStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -17864,20 +71643,20 @@ impl<'mc> JNIRaw<'mc> for GameRuleStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for GameRuleStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for HeightMapStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate GameRuleStruct from null object.").into(), + eyre::eyre!("Tried to instantiate HeightMapStruct from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/GameRule")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/HeightMap")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a GameRuleStruct object, got {}", + "Invalid argument passed. Expected a HeightMapStruct object, got {}", name ) .into()) @@ -17887,58 +71666,189 @@ impl<'mc> JNIInstantiatable<'mc> for GameRuleStruct<'mc> { } } -impl<'mc> GameRuleStruct<'mc> { - /// Get the name of this GameRule. - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) +impl<'mc> HeightMapStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/HeightMap;"); + let cls = jni.find_class("org/bukkit/HeightMap"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::HeightMap::from_raw(&jni, obj) } - /// Get the type of this rule. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/Class;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(unsafe { jni::objects::JClass::from_raw(res.as_jni().l) }) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +pub enum PortalType<'mc> { + Nether { inner: PortalTypeStruct<'mc> }, + Ender { inner: PortalTypeStruct<'mc> }, + Custom { inner: PortalTypeStruct<'mc> }, +} +impl<'mc> std::fmt::Display for PortalType<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PortalType::Nether { .. } => f.write_str("NETHER"), + PortalType::Ender { .. } => f.write_str("ENDER"), + PortalType::Custom { .. } => f.write_str("CUSTOM"), + } + } +} +impl<'mc> std::ops::Deref for PortalType<'mc> { + type Target = PortalTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + PortalType::Nether { inner } => inner, + PortalType::Ender { inner } => inner, + PortalType::Custom { inner } => inner, + } } +} - pub fn equals( - &self, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - let sig = String::from("(Ljava/lang/Object;)Z"); - let val_1 = jni::objects::JValueGen::Object(obj); - let res = self.jni_ref().call_method( - &self.jni_object(), - "equals", - sig.as_str(), +impl<'mc> PortalType<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/PortalType"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/PortalType;", vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "NETHER" => Ok(PortalType::Nether { + inner: PortalTypeStruct::from_raw(env, obj)?, + }), + "ENDER" => Ok(PortalType::Ender { + inner: PortalTypeStruct::from_raw(env, obj)?, + }), + "CUSTOM" => Ok(PortalType::Custom { + inner: PortalTypeStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } +} - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) +#[repr(C)] +pub struct PortalTypeStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PortalType<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Nether { inner } => inner.0.clone(), + Self::Ender { inner } => inner.0.clone(), + Self::Custom { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Nether { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Ender { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Custom { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for PortalType<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate PortalType from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/PortalType")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PortalType object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "NETHER" => Ok(PortalType::Nether { + inner: PortalTypeStruct::from_raw(env, obj)?, + }), + "ENDER" => Ok(PortalType::Ender { + inner: PortalTypeStruct::from_raw(env, obj)?, + }), + "CUSTOM" => Ok(PortalType::Custom { + inner: PortalTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for PortalTypeStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PortalTypeStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate PortalTypeStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/PortalType")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PortalTypeStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> PortalTypeStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/PortalType;"); + let cls = jni.find_class("org/bukkit/PortalType"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::PortalType::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -17947,12 +71857,12 @@ impl<'mc> GameRuleStruct<'mc> { } } #[repr(C)] -pub struct Raid<'mc>( +pub struct BanList<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Raid<'mc> { +impl<'mc> JNIRaw<'mc> for BanList<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -17960,18 +71870,18 @@ impl<'mc> JNIRaw<'mc> for Raid<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Raid<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BanList<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Raid from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate BanList from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Raid")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/BanList")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Raid object, got {}", + "Invalid argument passed. Expected a BanList object, got {}", name ) .into()) @@ -17981,148 +71891,128 @@ impl<'mc> JNIInstantiatable<'mc> for Raid<'mc> { } } -impl<'mc> Raid<'mc> { - /// Get whether this raid started. - pub fn is_started(&self) -> Result> { - let sig = String::from("()Z"); +impl<'mc> BanList<'mc> { + /// Gets a {@link BanEntry} by target. + pub fn get_ban_entry( + &self, + target: jni::objects::JObject<'mc>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "LT;"; + let val_1 = jni::objects::JValueGen::Object(target); + args.push(val_1); + sig += ")Lorg/bukkit/BanEntry;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "isStarted", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the amount of ticks this raid has existed. - pub fn active_ticks(&self) -> Result> { - let sig = String::from("()J"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getActiveTicks", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) - } - /// Gets the Bad Omen level of this raid. - pub fn bad_omen_level(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBadOmenLevel", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the Bad Omen level. - /// - /// If the level is higher than 1, there will be an additional wave that as - /// strong as the final wave. - pub fn set_bad_omen_level( - &self, - bad_omen_level: i32, - ) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(bad_omen_level); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setBadOmenLevel", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the center location where the raid occurs. - pub fn location(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBanEntry", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::BanEntry::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) + })?)) } - /// Gets the current status of the raid. - /// - /// Do not use this method to check if the raid has been started, call - /// {@link #isStarted()} instead. - pub fn status(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Raid/RaidStatus;"); + /// Adds a ban to this list. If a previous ban exists, this will + /// update the previous entry. + pub fn add_ban( + &self, + target: jni::objects::JObject<'mc>, + reason: impl Into, + duration: jni::objects::JObject<'mc>, + source: impl Into, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "LT;"; + let val_1 = jni::objects::JValueGen::Object(target); + args.push(val_1); + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(reason.into())?, + )); + args.push(val_2); + sig += "Ljava/time/Duration;"; + let val_3 = jni::objects::JValueGen::Object(duration); + args.push(val_3); + sig += "Ljava/lang/String;"; + let val_4 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(source.into())?, + )); + args.push(val_4); + sig += ")Lorg/bukkit/BanEntry;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getStatus", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "addBan", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::RaidRaidStatus::from_raw(&self.jni_ref(), unsafe { + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::BanEntry::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the number of raider groups which have spawned. - pub fn spawned_groups(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSpawnedGroups", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the number of raider groups which would spawn. - /// - /// This also includes the group which spawns in the additional wave (if - /// present). - pub fn total_groups(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTotalGroups", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the number of waves in this raid (exclude the additional wave). - pub fn total_waves(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTotalWaves", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + })?)) } - /// Gets the sum of all raider's health. - pub fn total_health(&self) -> Result> { - let sig = String::from("()F"); + #[deprecated] + /// Gets a set containing every {@link BanEntry} in this list. + pub fn ban_entries( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getTotalHealth", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBanEntries", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get the UUID of all heroes in this raid. - pub fn heroes( + /// Gets a set containing every {@link BanEntry} in this list. + pub fn entries( &self, ) -> Result, Box> { let sig = String::from("()Ljava/util/Set;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHeroes", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEntries", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets all remaining {@link Raider} in the present wave. - pub fn raiders(&self) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRaiders", sig.as_str(), vec![]); + #[deprecated] + /// Gets if a {@link BanEntry} exists for the target, indicating an active ban status. + pub fn is_banned(&self, target: impl Into) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(target.into())?, + )); + args.push(val_1); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isBanned", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Raider::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(res.z()?) + } + #[deprecated] + /// Removes the specified target from this list, therefore indicating a "not banned" status. + pub fn pardon(&self, target: impl Into) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(target.into())?, + )); + args.push(val_1); + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "pardon", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -18130,25 +72020,43 @@ impl<'mc> Raid<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum RaidRaidStatus<'mc> {} -impl<'mc> std::fmt::Display for RaidRaidStatus<'mc> { +pub enum BanListType<'mc> { + Name { inner: BanListTypeStruct<'mc> }, + Ip { inner: BanListTypeStruct<'mc> }, + Profile { inner: BanListTypeStruct<'mc> }, +} +impl<'mc> std::fmt::Display for BanListType<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + BanListType::Name { .. } => f.write_str("NAME"), + BanListType::Ip { .. } => f.write_str("IP"), + BanListType::Profile { .. } => f.write_str("PROFILE"), + } + } +} +impl<'mc> std::ops::Deref for BanListType<'mc> { + type Target = BanListTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + BanListType::Name { inner } => inner, + BanListType::Ip { inner } => inner, + BanListType::Profile { inner } => inner, + } } } -impl<'mc> RaidRaidStatus<'mc> { +impl<'mc> BanListType<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/Raid/RaidStatus"); + let cls = env.find_class("org/bukkit/BanList/Type"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/Raid/RaidStatus;", + "(Ljava/lang/String;)Lorg/bukkit/BanList/Type;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -18160,39 +72068,55 @@ impl<'mc> RaidRaidStatus<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NAME" => Ok(BanListType::Name { + inner: BanListTypeStruct::from_raw(env, obj)?, + }), + "IP" => Ok(BanListType::Ip { + inner: BanListTypeStruct::from_raw(env, obj)?, + }), + "PROFILE" => Ok(BanListType::Profile { + inner: BanListTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct RaidRaidStatusStruct<'mc>( +pub struct BanListTypeStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for RaidRaidStatus<'mc> { +impl<'mc> JNIRaw<'mc> for BanListType<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Name { inner } => inner.0.clone(), + Self::Ip { inner } => inner.0.clone(), + Self::Profile { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Name { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Ip { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Profile { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for RaidRaidStatus<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BanListType<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate RaidRaidStatus from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate BanListType from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Raid/RaidStatus")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/BanList/Type")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a RaidRaidStatus object, got {}", + "Invalid argument passed. Expected a BanListType object, got {}", name ) .into()) @@ -18204,13 +72128,22 @@ impl<'mc> JNIInstantiatable<'mc> for RaidRaidStatus<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NAME" => Ok(BanListType::Name { + inner: BanListTypeStruct::from_raw(env, obj)?, + }), + "IP" => Ok(BanListType::Ip { + inner: BanListTypeStruct::from_raw(env, obj)?, + }), + "PROFILE" => Ok(BanListType::Profile { + inner: BanListTypeStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for RaidRaidStatusStruct<'mc> { +impl<'mc> JNIRaw<'mc> for BanListTypeStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -18218,20 +72151,20 @@ impl<'mc> JNIRaw<'mc> for RaidRaidStatusStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for RaidRaidStatusStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BanListTypeStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate RaidRaidStatusStruct from null object.").into(), + eyre::eyre!("Tried to instantiate BanListTypeStruct from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Raid/RaidStatus")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/BanList/Type")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a RaidRaidStatusStruct object, got {}", + "Invalid argument passed. Expected a BanListTypeStruct object, got {}", name ) .into()) @@ -18241,17 +72174,17 @@ impl<'mc> JNIInstantiatable<'mc> for RaidRaidStatusStruct<'mc> { } } -impl<'mc> RaidRaidStatusStruct<'mc> { +impl<'mc> BanListTypeStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Raid/RaidStatus;"); - let cls = jni.find_class("org/bukkit/Raid/RaidStatus"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/BanList/Type;"); + let cls = jni.find_class("org/bukkit/BanList/Type"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::RaidRaidStatus::from_raw(&jni, obj) + crate::BanListType::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -18259,25 +72192,58 @@ impl<'mc> RaidRaidStatusStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum Rotation<'mc> {} -impl<'mc> std::fmt::Display for Rotation<'mc> { +pub enum MusicInstrument<'mc> { + PonderGoatHorn { inner: MusicInstrumentStruct<'mc> }, + SingGoatHorn { inner: MusicInstrumentStruct<'mc> }, + SeekGoatHorn { inner: MusicInstrumentStruct<'mc> }, + FeelGoatHorn { inner: MusicInstrumentStruct<'mc> }, + AdmireGoatHorn { inner: MusicInstrumentStruct<'mc> }, + CallGoatHorn { inner: MusicInstrumentStruct<'mc> }, + YearnGoatHorn { inner: MusicInstrumentStruct<'mc> }, + DreamGoatHorn { inner: MusicInstrumentStruct<'mc> }, +} +impl<'mc> std::fmt::Display for MusicInstrument<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + MusicInstrument::PonderGoatHorn { .. } => f.write_str("PONDER_GOAT_HORN"), + MusicInstrument::SingGoatHorn { .. } => f.write_str("SING_GOAT_HORN"), + MusicInstrument::SeekGoatHorn { .. } => f.write_str("SEEK_GOAT_HORN"), + MusicInstrument::FeelGoatHorn { .. } => f.write_str("FEEL_GOAT_HORN"), + MusicInstrument::AdmireGoatHorn { .. } => f.write_str("ADMIRE_GOAT_HORN"), + MusicInstrument::CallGoatHorn { .. } => f.write_str("CALL_GOAT_HORN"), + MusicInstrument::YearnGoatHorn { .. } => f.write_str("YEARN_GOAT_HORN"), + MusicInstrument::DreamGoatHorn { .. } => f.write_str("DREAM_GOAT_HORN"), + } + } +} +impl<'mc> std::ops::Deref for MusicInstrument<'mc> { + type Target = MusicInstrumentStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + MusicInstrument::PonderGoatHorn { inner } => inner, + MusicInstrument::SingGoatHorn { inner } => inner, + MusicInstrument::SeekGoatHorn { inner } => inner, + MusicInstrument::FeelGoatHorn { inner } => inner, + MusicInstrument::AdmireGoatHorn { inner } => inner, + MusicInstrument::CallGoatHorn { inner } => inner, + MusicInstrument::YearnGoatHorn { inner } => inner, + MusicInstrument::DreamGoatHorn { inner } => inner, + } } } -impl<'mc> Rotation<'mc> { +impl<'mc> MusicInstrument<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/Rotation"); + let cls = env.find_class("org/bukkit/MusicInstrument"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/Rotation;", + "(Ljava/lang/String;)Lorg/bukkit/MusicInstrument;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -18289,37 +72255,98 @@ impl<'mc> Rotation<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "PONDER_GOAT_HORN" => Ok(MusicInstrument::PonderGoatHorn { + inner: MusicInstrumentStruct::from_raw(env, obj)?, + }), + "SING_GOAT_HORN" => Ok(MusicInstrument::SingGoatHorn { + inner: MusicInstrumentStruct::from_raw(env, obj)?, + }), + "SEEK_GOAT_HORN" => Ok(MusicInstrument::SeekGoatHorn { + inner: MusicInstrumentStruct::from_raw(env, obj)?, + }), + "FEEL_GOAT_HORN" => Ok(MusicInstrument::FeelGoatHorn { + inner: MusicInstrumentStruct::from_raw(env, obj)?, + }), + "ADMIRE_GOAT_HORN" => Ok(MusicInstrument::AdmireGoatHorn { + inner: MusicInstrumentStruct::from_raw(env, obj)?, + }), + "CALL_GOAT_HORN" => Ok(MusicInstrument::CallGoatHorn { + inner: MusicInstrumentStruct::from_raw(env, obj)?, + }), + "YEARN_GOAT_HORN" => Ok(MusicInstrument::YearnGoatHorn { + inner: MusicInstrumentStruct::from_raw(env, obj)?, + }), + "DREAM_GOAT_HORN" => Ok(MusicInstrument::DreamGoatHorn { + inner: MusicInstrumentStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct RotationStruct<'mc>( +pub struct MusicInstrumentStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Rotation<'mc> { +impl<'mc> JNIRaw<'mc> for MusicInstrument<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::PonderGoatHorn { inner } => inner.0.clone(), + Self::SingGoatHorn { inner } => inner.0.clone(), + Self::SeekGoatHorn { inner } => inner.0.clone(), + Self::FeelGoatHorn { inner } => inner.0.clone(), + Self::AdmireGoatHorn { inner } => inner.0.clone(), + Self::CallGoatHorn { inner } => inner.0.clone(), + Self::YearnGoatHorn { inner } => inner.0.clone(), + Self::DreamGoatHorn { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::PonderGoatHorn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SingGoatHorn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SeekGoatHorn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FeelGoatHorn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AdmireGoatHorn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CallGoatHorn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::YearnGoatHorn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DreamGoatHorn { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } -impl<'mc> JNIInstantiatable<'mc> for Rotation<'mc> { +impl<'mc> JNIInstantiatable<'mc> for MusicInstrument<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Rotation from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate MusicInstrument from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Rotation")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/MusicInstrument")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Rotation object, got {}", + "Invalid argument passed. Expected a MusicInstrument object, got {}", name ) .into()) @@ -18331,13 +72358,37 @@ impl<'mc> JNIInstantiatable<'mc> for Rotation<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "PONDER_GOAT_HORN" => Ok(MusicInstrument::PonderGoatHorn { + inner: MusicInstrumentStruct::from_raw(env, obj)?, + }), + "SING_GOAT_HORN" => Ok(MusicInstrument::SingGoatHorn { + inner: MusicInstrumentStruct::from_raw(env, obj)?, + }), + "SEEK_GOAT_HORN" => Ok(MusicInstrument::SeekGoatHorn { + inner: MusicInstrumentStruct::from_raw(env, obj)?, + }), + "FEEL_GOAT_HORN" => Ok(MusicInstrument::FeelGoatHorn { + inner: MusicInstrumentStruct::from_raw(env, obj)?, + }), + "ADMIRE_GOAT_HORN" => Ok(MusicInstrument::AdmireGoatHorn { + inner: MusicInstrumentStruct::from_raw(env, obj)?, + }), + "CALL_GOAT_HORN" => Ok(MusicInstrument::CallGoatHorn { + inner: MusicInstrumentStruct::from_raw(env, obj)?, + }), + "YEARN_GOAT_HORN" => Ok(MusicInstrument::YearnGoatHorn { + inner: MusicInstrumentStruct::from_raw(env, obj)?, + }), + "DREAM_GOAT_HORN" => Ok(MusicInstrument::DreamGoatHorn { + inner: MusicInstrumentStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for RotationStruct<'mc> { +impl<'mc> JNIRaw<'mc> for MusicInstrumentStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -18345,20 +72396,21 @@ impl<'mc> JNIRaw<'mc> for RotationStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for RotationStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for MusicInstrumentStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate RotationStruct from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate MusicInstrumentStruct from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Rotation")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/MusicInstrument")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a RotationStruct object, got {}", + "Invalid argument passed. Expected a MusicInstrumentStruct object, got {}", name ) .into()) @@ -18368,42 +72420,59 @@ impl<'mc> JNIInstantiatable<'mc> for RotationStruct<'mc> { } } -impl<'mc> RotationStruct<'mc> { - pub fn values( +impl<'mc> MusicInstrumentStruct<'mc> { + #[deprecated] + /// Returns a {@link MusicInstrument} by a {@link NamespacedKey}. + pub fn get_by_key( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Rotation;"); - let cls = jni.find_class("org/bukkit/Rotation"); + namespaced_key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/MusicInstrument;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(namespaced_key.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/MusicInstrument"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.call_static_method( + cls, + "getByKey", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } let obj = res.l()?; - crate::Rotation::from_raw(&jni, obj) + Ok(Some(crate::MusicInstrument::from_raw(&jni, obj)?)) } - /// Rotate clockwise by 90 degrees. - pub fn rotate_clockwise(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Rotation;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "rotateClockwise", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Rotation::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + #[deprecated] + /// Returns all known MusicInstruments. + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); + let cls = jni.find_class("org/bukkit/MusicInstrument"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&jni, res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::MusicInstrument::from_raw(&jni, obj)?); + } + Ok(new_vec) } - /// Rotate counter-clockwise by 90 degrees. - pub fn rotate_counter_clockwise( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Rotation;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "rotateCounterClockwise", - sig.as_str(), - vec![], - ); + /// Return the namespaced identifier for this object. + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Rotation::from_raw(&self.jni_ref(), unsafe { + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -18414,12 +72483,12 @@ impl<'mc> RotationStruct<'mc> { } } #[repr(C)] -pub struct UndefinedNullability<'mc>( +pub struct Chunk<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for UndefinedNullability<'mc> { +impl<'mc> JNIRaw<'mc> for Chunk<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -18427,20 +72496,18 @@ impl<'mc> JNIRaw<'mc> for UndefinedNullability<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for UndefinedNullability<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Chunk<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate UndefinedNullability from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate Chunk from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/UndefinedNullability")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/Chunk")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a UndefinedNullability object, got {}", + "Invalid argument passed. Expected a Chunk object, got {}", name ) .into()) @@ -18450,132 +72517,428 @@ impl<'mc> JNIInstantiatable<'mc> for UndefinedNullability<'mc> { } } -impl<'mc> UndefinedNullability<'mc> { - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) +impl<'mc> Chunk<'mc> { + /// Gets the X-coordinate of this chunk + pub fn x(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} -pub enum WeatherType<'mc> {} -impl<'mc> std::fmt::Display for WeatherType<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + /// Gets the Z-coordinate of this chunk + pub fn z(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } -} - -impl<'mc> WeatherType<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/WeatherType"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/WeatherType;", - vec![jni::objects::JValueGen::from(val_1)], + /// Gets the world containing this chunk + pub fn world(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets a block from this chunk + pub fn get_block( + &self, + x: i32, + y: i32, + z: i32, + ) -> Result, Box> { + let sig = String::from("(III)Lorg/bukkit/block/Block;"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(y); + let val_3 = jni::objects::JValueGen::Int(z); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBlock", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + let res = self.jni_ref().translate_error(res)?; + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} - -#[repr(C)] -pub struct WeatherTypeStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for WeatherType<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + /// Capture thread-safe read-only snapshot of chunk data + pub fn get_chunk_snapshot( + &self, + include_maxblocky: bool, + include_biome: bool, + include_biome_temp_rain: bool, + ) -> Result, Box> { + let sig = String::from("(ZZZ)Lorg/bukkit/ChunkSnapshot;"); + let val_1 = jni::objects::JValueGen::Bool(include_maxblocky.into()); + let val_2 = jni::objects::JValueGen::Bool(include_biome.into()); + let val_3 = jni::objects::JValueGen::Bool(include_biome_temp_rain.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getChunkSnapshot", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = self.jni_ref().translate_error(res)?; + crate::ChunkSnapshot::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + /// Checks if entities in this chunk are loaded. + pub fn is_entities_loaded(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isEntitiesLoaded", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for WeatherType<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate WeatherType from null object.").into()); + /// Get a list of all entities in the chunk. + /// This will force load any entities, which are not loaded. + pub fn entities(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEntities", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get a list of all tile entities in the chunk. + pub fn tile_entities( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockState;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTileEntities", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Checks if the chunk is fully generated. + pub fn is_generated(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isGenerated", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks if the chunk is loaded. + pub fn is_loaded(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isLoaded", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Loads the chunk. + pub fn load( + &self, + generate: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = generate { + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_1); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/WeatherType")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a WeatherType object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "load", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Unloads and optionally saves the Chunk + pub fn unload( + &self, + save: std::option::Option, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = save { + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_1); } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "unload", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} - -impl<'mc> JNIRaw<'mc> for WeatherTypeStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Checks if this chunk can spawn slimes without being a swamp biome. + pub fn is_slime_chunk(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isSlimeChunk", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets whether the chunk at the specified chunk coordinates is force + /// loaded. + /// + /// A force loaded chunk will not be unloaded due to lack of player activity. + pub fn is_force_loaded(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isForceLoaded", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> JNIInstantiatable<'mc> for WeatherTypeStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate WeatherTypeStruct from null object.").into(), - ); + /// Sets whether the chunk at the specified chunk coordinates is force + /// loaded. + /// + /// A force loaded chunk will not be unloaded due to lack of player activity. + pub fn set_force_loaded(&self, forced: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(forced.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setForceLoaded", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Adds a plugin ticket for this chunk, loading this chunk if it is not + /// already loaded. + /// + /// A plugin ticket will prevent a chunk from unloading until it is + /// explicitly removed. A plugin instance may only have one ticket per chunk, + /// but each chunk can have multiple plugin tickets. + /// + pub fn add_plugin_chunk_ticket( + &self, + plugin: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addPluginChunkTicket", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Removes the specified plugin's ticket for this chunk + /// + /// A plugin ticket will prevent a chunk from unloading until it is + /// explicitly removed. A plugin instance may only have one ticket per chunk, + /// but each chunk can have multiple plugin tickets. + /// + pub fn remove_plugin_chunk_ticket( + &self, + plugin: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removePluginChunkTicket", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Retrieves a collection specifying which plugins have tickets for this + /// chunk. This collection is not updated when plugin tickets are added or + /// removed to this chunk. + /// + /// A plugin ticket will prevent a chunk from unloading until it is + /// explicitly removed. A plugin instance may only have one ticket per chunk, + /// but each chunk can have multiple plugin tickets. + /// + pub fn plugin_chunk_tickets( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPluginChunkTickets", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::plugin::Plugin::from_raw(&self.jni_ref(), obj)?); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/WeatherType")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a WeatherTypeStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + Ok(new_vec) + } + /// Gets the amount of time in ticks that this chunk has been inhabited. + /// Note that the time is incremented once per tick per player within mob + /// spawning distance of this chunk. + pub fn inhabited_time(&self) -> Result> { + let sig = String::from("()J"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getInhabitedTime", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.j()?) + } + /// Sets the amount of time in ticks that this chunk has been inhabited. + pub fn set_inhabited_time(&self, ticks: i64) -> Result<(), Box> { + let sig = String::from("(J)V"); + let val_1 = jni::objects::JValueGen::Long(ticks); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setInhabitedTime", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Tests if this chunk contains the specified biome. + pub fn contains( + &self, + biome: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/block/Biome;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(biome.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "contains", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the load level of this chunk, which determines what game logic is + /// processed. + pub fn load_level(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Chunk/LoadLevel;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLoadLevel", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::ChunkLoadLevel::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets all generated structures of a given {@link Structure} that intersect + /// this chunk. + /// + /// If no structures are present an empty collection will be returned. + pub fn get_structures( + &self, + structure: impl Into>, + ) -> Result>, Box> + { + let sig = + String::from("(Lorg/bukkit/generator/structure/Structure;)Ljava/util/Collection;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(structure.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getStructures", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::generator::structure::GeneratedStructure::from_raw( + &self.jni_ref(), + obj, + )?); } + Ok(new_vec) } -} - -impl<'mc> WeatherTypeStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/WeatherType;"); - let cls = jni.find_class("org/bukkit/WeatherType"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::WeatherType::from_raw(&jni, obj) + /// Get a list of all players who are can view the chunk from their client + /// + /// This list will be empty if no players are viewing the chunk, or the chunk + /// is unloaded. + pub fn players_seeing_chunk( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPlayersSeeingChunk", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Player::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Returns a custom tag container capable of storing tags on the object. + /// Note that the tags stored on this container are all stored under their + /// own custom namespace therefore modifying default tags using this + /// {@link PersistentDataHolder} is impossible. + pub fn persistent_data_container( + &self, + ) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/persistence/PersistentDataContainer;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPersistentDataContainer", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + crate::persistence::PersistentDataContainer::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -18583,25 +72946,55 @@ impl<'mc> WeatherTypeStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum Statistic<'mc> {} -impl<'mc> std::fmt::Display for Statistic<'mc> { +impl<'mc> Into> for Chunk<'mc> { + fn into(self) -> crate::persistence::PersistentDataHolder<'mc> { + crate::persistence::PersistentDataHolder::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Chunk into crate::persistence::PersistentDataHolder") + } +} +pub enum ChunkLoadLevel<'mc> { + Inaccessible { inner: ChunkLoadLevelStruct<'mc> }, + Border { inner: ChunkLoadLevelStruct<'mc> }, + Ticking { inner: ChunkLoadLevelStruct<'mc> }, + EntityTicking { inner: ChunkLoadLevelStruct<'mc> }, + Unloaded { inner: ChunkLoadLevelStruct<'mc> }, +} +impl<'mc> std::fmt::Display for ChunkLoadLevel<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + ChunkLoadLevel::Inaccessible { .. } => f.write_str("INACCESSIBLE"), + ChunkLoadLevel::Border { .. } => f.write_str("BORDER"), + ChunkLoadLevel::Ticking { .. } => f.write_str("TICKING"), + ChunkLoadLevel::EntityTicking { .. } => f.write_str("ENTITY_TICKING"), + ChunkLoadLevel::Unloaded { .. } => f.write_str("UNLOADED"), + } + } +} +impl<'mc> std::ops::Deref for ChunkLoadLevel<'mc> { + type Target = ChunkLoadLevelStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + ChunkLoadLevel::Inaccessible { inner } => inner, + ChunkLoadLevel::Border { inner } => inner, + ChunkLoadLevel::Ticking { inner } => inner, + ChunkLoadLevel::EntityTicking { inner } => inner, + ChunkLoadLevel::Unloaded { inner } => inner, + } } } -impl<'mc> Statistic<'mc> { +impl<'mc> ChunkLoadLevel<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/Statistic"); + let cls = env.find_class("org/bukkit/Chunk/LoadLevel"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/Statistic;", + "(Ljava/lang/String;)Lorg/bukkit/Chunk/LoadLevel;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -18613,37 +73006,71 @@ impl<'mc> Statistic<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "INACCESSIBLE" => Ok(ChunkLoadLevel::Inaccessible { + inner: ChunkLoadLevelStruct::from_raw(env, obj)?, + }), + "BORDER" => Ok(ChunkLoadLevel::Border { + inner: ChunkLoadLevelStruct::from_raw(env, obj)?, + }), + "TICKING" => Ok(ChunkLoadLevel::Ticking { + inner: ChunkLoadLevelStruct::from_raw(env, obj)?, + }), + "ENTITY_TICKING" => Ok(ChunkLoadLevel::EntityTicking { + inner: ChunkLoadLevelStruct::from_raw(env, obj)?, + }), + "UNLOADED" => Ok(ChunkLoadLevel::Unloaded { + inner: ChunkLoadLevelStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct StatisticStruct<'mc>( +pub struct ChunkLoadLevelStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Statistic<'mc> { +impl<'mc> JNIRaw<'mc> for ChunkLoadLevel<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Inaccessible { inner } => inner.0.clone(), + Self::Border { inner } => inner.0.clone(), + Self::Ticking { inner } => inner.0.clone(), + Self::EntityTicking { inner } => inner.0.clone(), + Self::Unloaded { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Inaccessible { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Border { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Ticking { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::EntityTicking { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Unloaded { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for Statistic<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ChunkLoadLevel<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Statistic from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate ChunkLoadLevel from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Statistic")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/Chunk/LoadLevel")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Statistic object, got {}", + "Invalid argument passed. Expected a ChunkLoadLevel object, got {}", name ) .into()) @@ -18655,13 +73082,28 @@ impl<'mc> JNIInstantiatable<'mc> for Statistic<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "INACCESSIBLE" => Ok(ChunkLoadLevel::Inaccessible { + inner: ChunkLoadLevelStruct::from_raw(env, obj)?, + }), + "BORDER" => Ok(ChunkLoadLevel::Border { + inner: ChunkLoadLevelStruct::from_raw(env, obj)?, + }), + "TICKING" => Ok(ChunkLoadLevel::Ticking { + inner: ChunkLoadLevelStruct::from_raw(env, obj)?, + }), + "ENTITY_TICKING" => Ok(ChunkLoadLevel::EntityTicking { + inner: ChunkLoadLevelStruct::from_raw(env, obj)?, + }), + "UNLOADED" => Ok(ChunkLoadLevel::Unloaded { + inner: ChunkLoadLevelStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for StatisticStruct<'mc> { +impl<'mc> JNIRaw<'mc> for ChunkLoadLevelStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -18669,20 +73111,20 @@ impl<'mc> JNIRaw<'mc> for StatisticStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for StatisticStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ChunkLoadLevelStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate StatisticStruct from null object.").into(), + eyre::eyre!("Tried to instantiate ChunkLoadLevelStruct from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Statistic")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/Chunk/LoadLevel")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a StatisticStruct object, got {}", + "Invalid argument passed. Expected a ChunkLoadLevelStruct object, got {}", name ) .into()) @@ -18692,66 +73134,17 @@ impl<'mc> JNIInstantiatable<'mc> for StatisticStruct<'mc> { } } -impl<'mc> StatisticStruct<'mc> { +impl<'mc> ChunkLoadLevelStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Statistic;"); - let cls = jni.find_class("org/bukkit/Statistic"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Chunk/LoadLevel;"); + let cls = jni.find_class("org/bukkit/Chunk/LoadLevel"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::Statistic::from_raw(&jni, obj) - } - /// Gets the type of this statistic. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Statistic/Type;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::StatisticType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Checks if this is a substatistic. - /// - /// A substatistic exists en masse for each block, item, or entitytype, depending on - /// {@link #getType()}. - /// - /// This is a redundant method and equivalent to checking - /// getType() != Type.UNTYPED - pub fn is_substatistic(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isSubstatistic", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Checks if this is a substatistic dealing with blocks. - /// - /// This is a redundant method and equivalent to checking - /// getType() == Type.BLOCK - pub fn is_block(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isBlock", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + crate::ChunkLoadLevel::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -18759,85 +73152,13 @@ impl<'mc> StatisticStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum StatisticType<'mc> {} -impl<'mc> std::fmt::Display for StatisticType<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> StatisticType<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/Statistic/Type"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/Statistic/Type;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - #[repr(C)] -pub struct StatisticTypeStruct<'mc>( +pub struct BlockChangeDelegate<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for StatisticType<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for StatisticType<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate StatisticType from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Statistic/Type")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a StatisticType object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for StatisticTypeStruct<'mc> { +impl<'mc> JNIRaw<'mc> for BlockChangeDelegate<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -18845,20 +73166,20 @@ impl<'mc> JNIRaw<'mc> for StatisticTypeStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for StatisticTypeStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BlockChangeDelegate<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate StatisticTypeStruct from null object.").into(), + eyre::eyre!("Tried to instantiate BlockChangeDelegate from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Statistic/Type")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/BlockChangeDelegate")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a StatisticTypeStruct object, got {}", + "Invalid argument passed. Expected a BlockChangeDelegate object, got {}", name ) .into()) @@ -18868,17 +73189,89 @@ impl<'mc> JNIInstantiatable<'mc> for StatisticTypeStruct<'mc> { } } -impl<'mc> StatisticTypeStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Statistic/Type;"); - let cls = jni.find_class("org/bukkit/Statistic/Type"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::StatisticType::from_raw(&jni, obj) +impl<'mc> BlockChangeDelegate<'mc> { + /// Set a block data at the specified coordinates. + pub fn set_block_data( + &self, + x: i32, + y: i32, + z: i32, + block_data: impl Into>, + ) -> Result> { + let sig = String::from("(IIILorg/bukkit/block/data/BlockData;)Z"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(y); + let val_3 = jni::objects::JValueGen::Int(z); + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(block_data.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBlockData", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the block data at the location. + pub fn get_block_data( + &self, + x: i32, + y: i32, + z: i32, + ) -> Result, Box> { + let sig = String::from("(III)Lorg/bukkit/block/data/BlockData;"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(y); + let val_3 = jni::objects::JValueGen::Int(z); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBlockData", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = self.jni_ref().translate_error(res)?; + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the height of the world. + pub fn height(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Checks if the specified block is empty (air) or not. + pub fn is_empty(&self, x: i32, y: i32, z: i32) -> Result> { + let sig = String::from("(III)Z"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(y); + let val_3 = jni::objects::JValueGen::Int(z); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isEmpty", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -18887,12 +73280,12 @@ impl<'mc> StatisticTypeStruct<'mc> { } } #[repr(C)] -pub struct WorldBorder<'mc>( +pub struct OfflinePlayer<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for WorldBorder<'mc> { +impl<'mc> JNIRaw<'mc> for OfflinePlayer<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -18900,18 +73293,18 @@ impl<'mc> JNIRaw<'mc> for WorldBorder<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for WorldBorder<'mc> { +impl<'mc> JNIInstantiatable<'mc> for OfflinePlayer<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate WorldBorder from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate OfflinePlayer from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/WorldBorder")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/OfflinePlayer")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a WorldBorder object, got {}", + "Invalid argument passed. Expected a OfflinePlayer object, got {}", name ) .into()) @@ -18921,366 +73314,432 @@ impl<'mc> JNIInstantiatable<'mc> for WorldBorder<'mc> { } } -impl<'mc> WorldBorder<'mc> { - /// Get the {@link World} in which the border resides. - pub fn world(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/World;"); +impl<'mc> OfflinePlayer<'mc> { + /// Checks if this player is currently online + pub fn is_online(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isOnline", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the name of this player + /// + /// Names are no longer unique past a single game session. For persistent storage + /// it is recommended that you use {@link #getUniqueId()} instead. + pub fn name(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::World::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Resets the border to default values. - pub fn reset(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "reset", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Returns the UUID of this player + pub fn unique_id( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getUniqueId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the current side length of the border. - pub fn size(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); + /// Gets a copy of the player's profile. + /// + /// If the player is online, the returned profile will be complete. + /// Otherwise, only the unique id is guaranteed to be present. You can use + /// {@link PlayerProfile#update()} to complete the returned profile. + pub fn player_profile( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/profile/PlayerProfile;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPlayerProfile", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + crate::profile::PlayerProfile::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the current border center. - pub fn center(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); + /// Checks if this player has had their profile banned. + pub fn is_banned(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getCenter", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isBanned", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets the new border center. - pub fn set_center( + /// Adds this user to the {@link ProfileBanList}. If a previous ban exists, this will + /// update the entry. + pub fn ban( &self, - x: f64, - z: std::option::Option, - ) -> Result<(), Box> { + reason: impl Into, + duration: jni::objects::JObject<'mc>, + source: impl Into, + ) -> Result>, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(x); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(reason.into())?, + )); args.push(val_1); - if let Some(a) = z { - sig += "D"; - let val_2 = jni::objects::JValueGen::Double(a); - args.push(val_2); - } - sig += ")V"; + sig += "Ljava/time/Duration;"; + let val_2 = jni::objects::JValueGen::Object(duration); + args.push(val_2); + sig += "Ljava/lang/String;"; + let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(source.into())?, + )); + args.push(val_3); + sig += ")Lorg/bukkit/BanEntry;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "setCenter", sig.as_str(), args); + .call_method(&self.jni_object(), "ban", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::BanEntry::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Checks if this player is whitelisted or not + pub fn is_whitelisted(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isWhitelisted", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets if this player is whitelisted or not + pub fn set_whitelisted(&self, value: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(value.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setWhitelisted", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the current border damage buffer. - pub fn damage_buffer(&self) -> Result> { - let sig = String::from("()D"); + /// Gets a {@link Player} object that this represents, if there is one + /// + /// If the player is online, this will return that player. Otherwise, + /// it will return null. + pub fn player(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/Player;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPlayer", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::Player::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the first date and time that this player was witnessed on this + /// server. + /// + /// If the player has never played before, this will return 0. Otherwise, + /// it will be the amount of milliseconds since midnight, January 1, 1970 + /// UTC. + pub fn first_played(&self) -> Result> { + let sig = String::from("()J"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDamageBuffer", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFirstPlayed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Sets the amount of blocks a player may safely be outside the border before taking damage. - pub fn set_damage_buffer(&self, blocks: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(blocks); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setDamageBuffer", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.j()?) } - /// Gets the current border damage amount. - pub fn damage_amount(&self) -> Result> { - let sig = String::from("()D"); + /// Gets the last date and time that this player was witnessed on this + /// server. + /// + /// If the player has never played before, this will return 0. Otherwise, + /// it will be the amount of milliseconds since midnight, January 1, 1970 + /// UTC. + pub fn last_played(&self) -> Result> { + let sig = String::from("()J"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDamageAmount", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLastPlayed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Sets the amount of damage a player takes when outside the border plus the border buffer. - pub fn set_damage_amount(&self, damage: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(damage); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setDamageAmount", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.j()?) } - /// Gets the current border warning time in seconds. - pub fn warning_time(&self) -> Result> { - let sig = String::from("()I"); + /// Checks if this player has played on this server before. + pub fn has_played_before(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getWarningTime", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasPlayedBefore", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Sets the warning time that causes the screen to be tinted red when a contracting border will reach the player within the specified time. - pub fn set_warning_time(&self, seconds: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(seconds); + #[deprecated] + /// Gets the Location where the player will spawn at their bed, null if they have not slept in one or their current bed spawn is invalid. + pub fn bed_spawn_location( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); let res = self.jni_ref().call_method( &self.jni_object(), - "setWarningTime", + "getBedSpawnLocation", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Gets the current border warning distance. - pub fn warning_distance(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the Location where the player will spawn at, null if they + /// don't have a valid respawn point. + pub fn respawn_location( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getWarningDistance", + "getRespawnLocation", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Sets the warning distance that causes the screen to be tinted red when the player is within the specified number of blocks from the border. - pub fn set_warning_distance(&self, distance: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(distance); + /// Increments the given statistic for this player for the given entity. + pub fn increment_statistic( + &self, + statistic: impl Into>, + entity_type: std::option::Option>>, + amount: std::option::Option, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Statistic;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(statistic.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = entity_type { + sig += "Lorg/bukkit/entity/EntityType;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + if let Some(a) = amount { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + sig += ")V"; let res = self.jni_ref().call_method( &self.jni_object(), - "setWarningDistance", + "incrementStatistic", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Check if the specified location is inside this border. - pub fn is_inside( + /// Decrements the given statistic for this player for the given entity. + pub fn decrement_statistic( &self, - location: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/Location;)Z"); + statistic: impl Into>, + entity_type: std::option::Option>>, + amount: std::option::Option, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Statistic;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) + jni::objects::JObject::from_raw(statistic.into().jni_object().clone()) }); + args.push(val_1); + if let Some(a) = entity_type { + sig += "Lorg/bukkit/entity/EntityType;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + if let Some(a) = amount { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + sig += ")V"; let res = self.jni_ref().call_method( &self.jni_object(), - "isInside", + "decrementStatistic", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets the maximum possible size of a WorldBorder. - pub fn max_size(&self) -> Result> { - let sig = String::from("()D"); + /// Sets the given statistic for this player for the given entity. + pub fn set_statistic( + &self, + statistic: impl Into>, + entity_type: impl Into>, + new_value: std::option::Option, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Statistic;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(statistic.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Lorg/bukkit/entity/EntityType;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(entity_type.into().jni_object().clone()) + }); + args.push(val_2); + if let Some(a) = new_value { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaxSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "setStatistic", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the value of the given statistic for this player. + pub fn get_statistic( + &self, + statistic: impl Into>, + entity_type: std::option::Option>>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Statistic;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(statistic.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = entity_type { + sig += "Lorg/bukkit/entity/EntityType;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")I"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getStatistic", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.i()?) } - /// Gets the absolute value of the maximum x/z center coordinate of a - /// WorldBorder. - pub fn max_center_coordinate(&self) -> Result> { - let sig = String::from("()D"); + /// Gets the player's last death location. + pub fn last_death_location( + &self, + ) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Lorg/bukkit/Location;"; let res = self.jni_ref().call_method( &self.jni_object(), - "getMaxCenterCoordinate", + "getLastDeathLocation", sig.as_str(), - vec![], + args, ); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -pub enum EntityEffect<'mc> {} -impl<'mc> std::fmt::Display for EntityEffect<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> EntityEffect<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/EntityEffect"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/EntityEffect;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct EntityEffectStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for EntityEffect<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for EntityEffect<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate EntityEffect from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/EntityEffect")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityEffect object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } -} - -impl<'mc> JNIRaw<'mc> for EntityEffectStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for EntityEffectStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate EntityEffectStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/EntityEffect")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityEffectStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + /// Gets the player's current location. + pub fn location(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some(crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } -} - -impl<'mc> EntityEffectStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/EntityEffect;"); - let cls = jni.find_class("org/bukkit/EntityEffect"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::EntityEffect::from_raw(&jni, obj) - } - #[deprecated] - /// Gets the data value of this EntityEffect, may not be unique. - pub fn data(&self) -> Result> { - let sig = String::from("()B"); + /// Checks if this object is a server operator + pub fn is_op(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isOp", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) + Ok(res.z()?) } - /// Gets entity superclass which this affect is applicable to. - pub fn applicable(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/Class;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getApplicable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(unsafe { jni::objects::JClass::from_raw(res.as_jni().l) }) + /// Sets the operator status of this object + pub fn set_op(&self, value: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(value.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setOp", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Checks if this effect is applicable to the given entity class. - pub fn is_applicable_to( + /// Creates a Map representation of this class. + /// + /// This class must provide a method to restore this class, as defined in + /// the {@link ConfigurationSerializable} interface javadocs. + pub fn serialize( &self, - clazz: jni::objects::JClass<'mc>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/Class;"; - let val_1 = jni::objects::JValueGen::Object(clazz.into()); - args.push(val_1); - sig += ")Z"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isApplicableTo", sig.as_str(), args); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Map;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -19288,85 +73747,32 @@ impl<'mc> EntityEffectStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum WorldType<'mc> {} -impl<'mc> std::fmt::Display for WorldType<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> WorldType<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/WorldType"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/WorldType;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct WorldTypeStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for WorldType<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for WorldType<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate WorldType from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/WorldType")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a WorldType object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} +impl<'mc> Into> for OfflinePlayer<'mc> { + fn into(self) -> crate::permissions::ServerOperator<'mc> { + crate::permissions::ServerOperator::from_raw(&self.jni_ref(), self.1) + .expect("Error converting OfflinePlayer into crate::permissions::ServerOperator") + } +} +impl<'mc> Into> for OfflinePlayer<'mc> { + fn into(self) -> crate::entity::AnimalTamer<'mc> { + crate::entity::AnimalTamer::from_raw(&self.jni_ref(), self.1) + .expect("Error converting OfflinePlayer into crate::entity::AnimalTamer") + } +} +impl<'mc> Into> + for OfflinePlayer<'mc> +{ + fn into(self) -> crate::configuration::serialization::ConfigurationSerializable<'mc> { + crate::configuration::serialization::ConfigurationSerializable::from_raw(&self.jni_ref(), self.1).expect("Error converting OfflinePlayer into crate::configuration::serialization::ConfigurationSerializable") + } +} +#[repr(C)] +pub struct Vibration<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); -impl<'mc> JNIRaw<'mc> for WorldTypeStruct<'mc> { +impl<'mc> JNIRaw<'mc> for Vibration<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -19374,20 +73780,18 @@ impl<'mc> JNIRaw<'mc> for WorldTypeStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for WorldTypeStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Vibration<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate WorldTypeStruct from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate Vibration from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/WorldType")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/Vibration")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a WorldTypeStruct object, got {}", + "Invalid argument passed. Expected a Vibration object, got {}", name ) .into()) @@ -19397,54 +73801,67 @@ impl<'mc> JNIInstantiatable<'mc> for WorldTypeStruct<'mc> { } } -impl<'mc> WorldTypeStruct<'mc> { - pub fn values( +impl<'mc> Vibration<'mc> { + pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/WorldType;"); - let cls = jni.find_class("org/bukkit/WorldType"); + origin: impl Into>, + destination: impl Into>, + arrival_time: i32, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/Location;Lorg/bukkit/Vibration/Destination;I)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(origin.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(destination.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Int(arrival_time); + let cls = jni.find_class("org/bukkit/Vibration"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::WorldType::from_raw(&jni, obj) + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::Vibration::from_raw(&jni, res) } - /// Gets the name of this WorldType - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Get the origin of the vibration. + pub fn origin(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getOrigin", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets a WorldType by its name - pub fn get_by_name( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - name: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/WorldType;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(name.into())?, - )); - let cls = jni.find_class("org/bukkit/WorldType"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getByName", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::WorldType::from_raw(&jni, obj)?)) + /// Get the vibration destination. + pub fn destination( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Vibration/Destination;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDestination", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::VibrationDestination::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the vibration arrival time in ticks. + pub fn arrival_time(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getArrivalTime", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -19453,12 +73870,12 @@ impl<'mc> WorldTypeStruct<'mc> { } } #[repr(C)] -pub struct Nameable<'mc>( +pub struct VibrationDestination<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Nameable<'mc> { +impl<'mc> JNIRaw<'mc> for VibrationDestination<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -19466,18 +73883,20 @@ impl<'mc> JNIRaw<'mc> for Nameable<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Nameable<'mc> { +impl<'mc> JNIInstantiatable<'mc> for VibrationDestination<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Nameable from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate VibrationDestination from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Nameable")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/Vibration/Destination")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Nameable object, got {}", + "Invalid argument passed. Expected a VibrationDestination object, got {}", name ) .into()) @@ -19487,68 +73906,19 @@ impl<'mc> JNIInstantiatable<'mc> for Nameable<'mc> { } } -impl<'mc> Nameable<'mc> { - /// Gets the custom name on a mob or block. If there is no name this method - /// will return null. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn custom_name(&self) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/lang/String;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCustomName", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// Sets a custom name on a mob or block. This name will be used in death - /// messages and can be sent to the client as a nameplate over the mob. - /// - /// Setting the name to null or an empty string will clear it. - /// - /// This value has no effect on players, they will always use their real - /// name. - pub fn set_custom_name( - &self, - name: impl Into, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(name.into())?, - )); - args.push(val_1); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setCustomName", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) - } - +impl<'mc> VibrationDestination<'mc> { pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } #[repr(C)] -pub struct Color<'mc>( +pub struct VibrationDestinationEntityDestination<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Color<'mc> { +impl<'mc> JNIRaw<'mc> for VibrationDestinationEntityDestination<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -19556,363 +73926,151 @@ impl<'mc> JNIRaw<'mc> for Color<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Color<'mc> { +impl<'mc> JNIInstantiatable<'mc> for VibrationDestinationEntityDestination<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Color from null object.").into()); + return Err(eyre::eyre!( + "Tried to instantiate VibrationDestinationEntityDestination from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Color")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/Vibration/Destination/EntityDestination")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Color object, got {}", - name - ) - .into()) + "Invalid argument passed. Expected a VibrationDestinationEntityDestination object, got {}", + name + ) + .into()) } else { Ok(Self(env.clone(), obj)) } } } -impl<'mc> Color<'mc> { - /// Creates a new Color object from an alpha, red, green, and blue - pub fn from_argb( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - alpha: i32, - red: std::option::Option, - green: std::option::Option, - blue: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(alpha); - args.push(val_1); - if let Some(a) = red { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - if let Some(a) = green { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - if let Some(a) = blue { - sig += "I"; - let val_4 = jni::objects::JValueGen::Int(a); - args.push(val_4); - } - sig += ")Lorg/bukkit/Color;"; - let cls = jni.find_class("org/bukkit/Color"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "fromARGB", sig.as_str(), args); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::Color::from_raw(&jni, obj) - } - /// Creates a new Color object from a red, green, and blue - pub fn from_rgb( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - red: i32, - green: std::option::Option, - blue: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(red); - args.push(val_1); - if let Some(a) = green { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - if let Some(a) = blue { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - sig += ")Lorg/bukkit/Color;"; - let cls = jni.find_class("org/bukkit/Color"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "fromRGB", sig.as_str(), args); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::Color::from_raw(&jni, obj) - } - /// Creates a new Color object from a blue, green, and red - pub fn from_bgr( +impl<'mc> VibrationDestinationEntityDestination<'mc> { + pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - blue: i32, - green: std::option::Option, - red: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(blue); - args.push(val_1); - if let Some(a) = green { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - if let Some(a) = red { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - sig += ")Lorg/bukkit/Color;"; - let cls = jni.find_class("org/bukkit/Color"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "fromBGR", sig.as_str(), args); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::Color::from_raw(&jni, obj) - } - /// Gets the alpha component - pub fn alpha(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getAlpha", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Creates a new Color object with specified component - pub fn set_alpha(&self, alpha: i32) -> Result, Box> { - let sig = String::from("(I)Lorg/bukkit/Color;"); - let val_1 = jni::objects::JValueGen::Int(alpha); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setAlpha", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Color::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the red component - pub fn red(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getRed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Creates a new Color object with specified component - pub fn set_red(&self, red: i32) -> Result, Box> { - let sig = String::from("(I)Lorg/bukkit/Color;"); - let val_1 = jni::objects::JValueGen::Int(red); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setRed", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Color::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the green component - pub fn green(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getGreen", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Creates a new Color object with specified component - pub fn set_green(&self, green: i32) -> Result, Box> { - let sig = String::from("(I)Lorg/bukkit/Color;"); - let val_1 = jni::objects::JValueGen::Int(green); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setGreen", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Color::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the blue component - pub fn blue(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBlue", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Creates a new Color object with specified component - pub fn set_blue(&self, blue: i32) -> Result, Box> { - let sig = String::from("(I)Lorg/bukkit/Color;"); - let val_1 = jni::objects::JValueGen::Int(blue); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setBlue", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Color::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the color as an RGB integer. - pub fn as_rgb(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "asRGB", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the color as an ARGB integer. - pub fn as_argb(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "asARGB", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the color as an BGR integer. - pub fn as_bgr(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "asBGR", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Creates a new color with its RGB components changed as if it was dyed - /// with the colors passed in, replicating vanilla workbench dyeing - pub fn mix_dyes( - &self, - colors: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/DyeColor;)Lorg/bukkit/Color;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(colors.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "mixDyes", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Color::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Creates a new color with its RGB components changed as if it was dyed - /// with the colors passed in, replicating vanilla workbench dyeing. - /// Note that this method does not currently take into account alpha - /// components. - pub fn mix_colors( - &self, - colors: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/Color;)Lorg/bukkit/Color;"); + entity: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/entity/Entity;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(colors.into().jni_object().clone()) + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "mixColors", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Color::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn equals( - &self, - o: jni::objects::JObject<'mc>, - ) -> Result> { - let sig = String::from("(Ljava/lang/Object;)Z"); - let val_1 = jni::objects::JValueGen::Object(o); - let res = self.jni_ref().call_method( - &self.jni_object(), - "equals", + let cls = jni.find_class("org/bukkit/Vibration/Destination/EntityDestination"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn hash_code(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error_no_gen(res)?; + crate::VibrationDestinationEntityDestination::from_raw(&jni, res) } - pub fn serialize( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); + pub fn entity(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/Entity;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getEntity", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - pub fn deserialize( + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for VibrationDestinationEntityDestination<'mc> { + fn into(self) -> crate::VibrationDestination<'mc> { + crate::VibrationDestination::from_raw(&self.jni_ref(), self.1).expect("Error converting VibrationDestinationEntityDestination into crate::VibrationDestination") + } +} +#[repr(C)] +pub struct VibrationDestinationBlockDestination<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for VibrationDestinationBlockDestination<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for VibrationDestinationBlockDestination<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate VibrationDestinationBlockDestination from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/Vibration/Destination/BlockDestination")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a VibrationDestinationBlockDestination object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> VibrationDestinationBlockDestination<'mc> { + pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - map: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Ljava/util/Map;)Lorg/bukkit/Color;"); + block: impl Into>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/block/Block;"; let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(map.into().jni_object().clone()) + jni::objects::JObject::from_raw(block.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/Color"); + args.push(val_1); + sig += ")V"; + let cls = jni.find_class("org/bukkit/Vibration/Destination/BlockDestination"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "deserialize", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::Color::from_raw(&jni, obj) + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::VibrationDestinationBlockDestination::from_raw(&jni, res) } - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + pub fn location(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn block(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -19920,28 +74078,180 @@ impl<'mc> Color<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for VibrationDestinationBlockDestination<'mc> { + fn into(self) -> crate::VibrationDestination<'mc> { + crate::VibrationDestination::from_raw(&self.jni_ref(), self.1).expect("Error converting VibrationDestinationBlockDestination into crate::VibrationDestination") + } +} -impl<'mc> std::string::ToString for Color<'mc> { - fn to_string(&self) -> String { - match &self.internal_to_string() { - Ok(a) => a.clone(), - Err(err) => format!("Error calling Color.toString: {}", err), +pub enum SkullType<'mc> { + Skeleton { inner: SkullTypeStruct<'mc> }, + Wither { inner: SkullTypeStruct<'mc> }, + Zombie { inner: SkullTypeStruct<'mc> }, + Player { inner: SkullTypeStruct<'mc> }, + Creeper { inner: SkullTypeStruct<'mc> }, + Dragon { inner: SkullTypeStruct<'mc> }, + Piglin { inner: SkullTypeStruct<'mc> }, +} +impl<'mc> std::fmt::Display for SkullType<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + SkullType::Skeleton { .. } => f.write_str("SKELETON"), + SkullType::Wither { .. } => f.write_str("WITHER"), + SkullType::Zombie { .. } => f.write_str("ZOMBIE"), + SkullType::Player { .. } => f.write_str("PLAYER"), + SkullType::Creeper { .. } => f.write_str("CREEPER"), + SkullType::Dragon { .. } => f.write_str("DRAGON"), + SkullType::Piglin { .. } => f.write_str("PIGLIN"), + } + } +} +impl<'mc> std::ops::Deref for SkullType<'mc> { + type Target = SkullTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + SkullType::Skeleton { inner } => inner, + SkullType::Wither { inner } => inner, + SkullType::Zombie { inner } => inner, + SkullType::Player { inner } => inner, + SkullType::Creeper { inner } => inner, + SkullType::Dragon { inner } => inner, + SkullType::Piglin { inner } => inner, } } } -impl<'mc> Into> for Color<'mc> { - fn into(self) -> crate::configuration::serialization::ConfigurationSerializable<'mc> { - crate::configuration::serialization::ConfigurationSerializable::from_raw(&self.jni_ref(), self.1).expect("Error converting Color into crate::configuration::serialization::ConfigurationSerializable") +impl<'mc> SkullType<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/SkullType"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/SkullType;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "SKELETON" => Ok(SkullType::Skeleton { + inner: SkullTypeStruct::from_raw(env, obj)?, + }), + "WITHER" => Ok(SkullType::Wither { + inner: SkullTypeStruct::from_raw(env, obj)?, + }), + "ZOMBIE" => Ok(SkullType::Zombie { + inner: SkullTypeStruct::from_raw(env, obj)?, + }), + "PLAYER" => Ok(SkullType::Player { + inner: SkullTypeStruct::from_raw(env, obj)?, + }), + "CREEPER" => Ok(SkullType::Creeper { + inner: SkullTypeStruct::from_raw(env, obj)?, + }), + "DRAGON" => Ok(SkullType::Dragon { + inner: SkullTypeStruct::from_raw(env, obj)?, + }), + "PIGLIN" => Ok(SkullType::Piglin { + inner: SkullTypeStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } + #[repr(C)] -pub struct RegionAccessor<'mc>( +pub struct SkullTypeStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for RegionAccessor<'mc> { +impl<'mc> JNIRaw<'mc> for SkullType<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Skeleton { inner } => inner.0.clone(), + Self::Wither { inner } => inner.0.clone(), + Self::Zombie { inner } => inner.0.clone(), + Self::Player { inner } => inner.0.clone(), + Self::Creeper { inner } => inner.0.clone(), + Self::Dragon { inner } => inner.0.clone(), + Self::Piglin { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Skeleton { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Wither { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Zombie { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Player { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Creeper { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Dragon { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Piglin { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for SkullType<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate SkullType from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/SkullType")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a SkullType object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "SKELETON" => Ok(SkullType::Skeleton { + inner: SkullTypeStruct::from_raw(env, obj)?, + }), + "WITHER" => Ok(SkullType::Wither { + inner: SkullTypeStruct::from_raw(env, obj)?, + }), + "ZOMBIE" => Ok(SkullType::Zombie { + inner: SkullTypeStruct::from_raw(env, obj)?, + }), + "PLAYER" => Ok(SkullType::Player { + inner: SkullTypeStruct::from_raw(env, obj)?, + }), + "CREEPER" => Ok(SkullType::Creeper { + inner: SkullTypeStruct::from_raw(env, obj)?, + }), + "DRAGON" => Ok(SkullType::Dragon { + inner: SkullTypeStruct::from_raw(env, obj)?, + }), + "PIGLIN" => Ok(SkullType::Piglin { + inner: SkullTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for SkullTypeStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -19949,20 +74259,20 @@ impl<'mc> JNIRaw<'mc> for RegionAccessor<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for RegionAccessor<'mc> { +impl<'mc> JNIInstantiatable<'mc> for SkullTypeStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate RegionAccessor from null object.").into(), + eyre::eyre!("Tried to instantiate SkullTypeStruct from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/RegionAccessor")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/SkullType")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a RegionAccessor object, got {}", + "Invalid argument passed. Expected a SkullTypeStruct object, got {}", name ) .into()) @@ -19972,551 +74282,584 @@ impl<'mc> JNIInstantiatable<'mc> for RegionAccessor<'mc> { } } -impl<'mc> RegionAccessor<'mc> { - /// Gets the {@link Biome} at the given coordinates. - pub fn get_biome( - &self, - x: i32, - y: std::option::Option, - z: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); - args.push(val_1); - if let Some(a) = y { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - if let Some(a) = z { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - sig += ")Lorg/bukkit/block/Biome;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBiome", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::block::Biome::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +impl<'mc> SkullTypeStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/SkullType;"); + let cls = jni.find_class("org/bukkit/SkullType"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::SkullType::from_raw(&jni, obj) } - /// Sets the {@link Biome} for the given block coordinates - pub fn set_biome( - &self, - x: i32, - y: i32, - z: std::option::Option, - biome: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); - args.push(val_1); - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(y); - args.push(val_2); - if let Some(a) = z { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - if let Some(a) = biome { - sig += "Lorg/bukkit/block/Biome;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_4); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setBiome", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Gets the {@link BlockState} at the given coordinates. - pub fn get_block_state( - &self, - x: i32, - y: std::option::Option, - z: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); - args.push(val_1); - if let Some(a) = y { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - if let Some(a) = z { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - sig += ")Lorg/bukkit/block/BlockState;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBlockState", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} +#[repr(C)] +pub struct Raid<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Raid<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Gets the {@link BlockData} at the given coordinates. - pub fn get_block_data( - &self, - x: i32, - y: std::option::Option, - z: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); - args.push(val_1); - if let Some(a) = y { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - if let Some(a) = z { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - sig += ")Lorg/bukkit/block/data/BlockData;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBlockData", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Gets the type of the block at the given coordinates. - pub fn get_type( - &self, - x: i32, - y: std::option::Option, - z: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); - args.push(val_1); - if let Some(a) = y { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); +} +impl<'mc> JNIInstantiatable<'mc> for Raid<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Raid from null object.").into()); } - if let Some(a) = z { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); + let (valid, name) = env.validate_name(&obj, "org/bukkit/Raid")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Raid object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - sig += ")Lorg/bukkit/Material;"; + } +} + +impl<'mc> Raid<'mc> { + /// Get whether this raid started. + pub fn is_started(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), args); + .call_method(&self.jni_object(), "isStarted", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets the {@link BlockData} at the given coordinates. - pub fn set_block_data( - &self, - x: i32, - y: i32, - z: std::option::Option, - block_data: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); - args.push(val_1); - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(y); - args.push(val_2); - if let Some(a) = z { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - if let Some(a) = block_data { - sig += "Lorg/bukkit/block/data/BlockData;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_4); - } - sig += ")V"; + /// Gets the amount of ticks this raid has existed. + pub fn active_ticks(&self) -> Result> { + let sig = String::from("()J"); let res = self.jni_ref() - .call_method(&self.jni_object(), "setBlockData", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getActiveTicks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.j()?) } - /// Sets the {@link Material} at the given coordinates. - pub fn set_type( - &self, - x: i32, - y: i32, - z: std::option::Option, - material: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); - args.push(val_1); - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(y); - args.push(val_2); - if let Some(a) = z { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - if let Some(a) = material { - sig += "Lorg/bukkit/Material;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_4); - } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setType", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Gets the Bad Omen level of this raid. + pub fn bad_omen_level(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBadOmenLevel", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Creates a tree at the given {@link Location} - /// - /// The provided predicate gets called for every block which gets changed - /// as a result of the tree generation. When the predicate gets called no - /// modifications to the world are done yet. Which means, that calling - /// {@link #getBlockState(Location)} in the predicate will return the state - /// of the block before the generation. + /// Sets the Bad Omen level. /// - /// If the predicate returns {@code true} the block gets set in the world. - /// If it returns {@code false} the block won't get set in the world. - pub fn generate_tree( + /// If the level is higher than 1, there will be an additional wave that as + /// strong as the final wave. + pub fn set_bad_omen_level( &self, - location: impl Into>, - random: impl Into>, - val_type: impl Into>, - state_predicate: std::option::Option< - impl Into>, - >, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Ljava/util/Random;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(random.into().jni_object().clone()) - }); - args.push(val_2); - sig += "Lorg/bukkit/TreeType;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - args.push(val_3); - if let Some(a) = state_predicate { - sig += "Ljava/util/function/Predicate;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_4); - } - sig += ")Z"; + bad_omen_level: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(bad_omen_level); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBadOmenLevel", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the center location where the raid occurs. + pub fn location(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "generateTree", sig.as_str(), args); + .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Creates a new entity at the given {@link Location}. - pub fn spawn_entity( - &self, - loc: impl Into>, - val_type: impl Into>, - randomize_data: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(loc.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/entity/EntityType;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - args.push(val_2); - if let Some(a) = randomize_data { - sig += "Z"; - let val_3 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_3); - } - sig += ")Lorg/bukkit/entity/Entity;"; + /// Gets the current status of the raid. + /// + /// Do not use this method to check if the raid has been started, call + /// {@link #isStarted()} instead. + pub fn status(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Raid/RaidStatus;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "spawnEntity", sig.as_str(), args); + .call_method(&self.jni_object(), "getStatus", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + crate::RaidRaidStatus::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get a list of all entities in this RegionAccessor - pub fn entities(&self) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/List;"; + /// Gets the number of raider groups which have spawned. + pub fn spawned_groups(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSpawnedGroups", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the number of raider groups which would spawn. + /// + /// This also includes the group which spawns in the additional wave (if + /// present). + pub fn total_groups(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTotalGroups", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the number of waves in this raid (exclude the additional wave). + pub fn total_waves(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTotalWaves", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the sum of all raider's health. + pub fn total_health(&self) -> Result> { + let sig = String::from("()F"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTotalHealth", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Get the UUID of all heroes in this raid. + pub fn heroes( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getEntities", sig.as_str(), args); + .call_method(&self.jni_object(), "getHeroes", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get a list of all living entities in this RegionAccessor - pub fn living_entities( - &self, - ) -> Result>, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/List;"; + /// Gets all remaining {@link Raider} in the present wave. + pub fn raiders(&self) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLivingEntities", sig.as_str(), args); + .call_method(&self.jni_object(), "getRaiders", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::entity::LivingEntity::from_raw(&self.jni_ref(), obj)?); + new_vec.push(crate::entity::Raider::from_raw(&self.jni_ref(), obj)?); } Ok(new_vec) } - /// Get a collection of all entities in this RegionAccessor matching the given - /// class/interface - pub fn get_entities_by_class( - &self, - cls: jni::objects::JClass<'mc>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/Class;"; - let val_1 = jni::objects::JValueGen::Object(cls.into()); - args.push(val_1); - sig += ")Ljava/util/Collection;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getEntitiesByClass", - sig.as_str(), - args, - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(obj); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +pub enum RaidRaidStatus<'mc> { + Ongoing { inner: RaidRaidStatusStruct<'mc> }, + Victory { inner: RaidRaidStatusStruct<'mc> }, + Loss { inner: RaidRaidStatusStruct<'mc> }, + Stopped { inner: RaidRaidStatusStruct<'mc> }, +} +impl<'mc> std::fmt::Display for RaidRaidStatus<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + RaidRaidStatus::Ongoing { .. } => f.write_str("ONGOING"), + RaidRaidStatus::Victory { .. } => f.write_str("VICTORY"), + RaidRaidStatus::Loss { .. } => f.write_str("LOSS"), + RaidRaidStatus::Stopped { .. } => f.write_str("STOPPED"), } - Ok(new_vec) } - /// Get a collection of all entities in this RegionAccessor matching any of the - /// given classes/interfaces - pub fn get_entities_by_classes( - &self, - classes: jni::objects::JClass<'mc>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/Class;"; - let val_1 = jni::objects::JValueGen::Object(classes.into()); - args.push(val_1); - sig += ")Ljava/util/Collection;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getEntitiesByClasses", - sig.as_str(), - args, - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); +} +impl<'mc> std::ops::Deref for RaidRaidStatus<'mc> { + type Target = RaidRaidStatusStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + RaidRaidStatus::Ongoing { inner } => inner, + RaidRaidStatus::Victory { inner } => inner, + RaidRaidStatus::Loss { inner } => inner, + RaidRaidStatus::Stopped { inner } => inner, } - Ok(new_vec) } - /// Creates an entity of a specific class at the given {@link Location} but - /// does not spawn it in the world. - /// - /// Note: The created entity keeps a reference to the world it was - /// created in, care should be taken that the entity does not outlive the - /// world instance as this will lead to memory leaks. - pub fn create_entity( - &self, - location: impl Into>, - clazz: jni::objects::JClass<'mc>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/Location;Ljava/lang/Class;)LT;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(clazz.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "createEntity", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], +} + +impl<'mc> RaidRaidStatus<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/Raid/RaidStatus"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/Raid/RaidStatus;", + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "ONGOING" => Ok(RaidRaidStatus::Ongoing { + inner: RaidRaidStatusStruct::from_raw(env, obj)?, + }), + "VICTORY" => Ok(RaidRaidStatus::Victory { + inner: RaidRaidStatusStruct::from_raw(env, obj)?, + }), + "LOSS" => Ok(RaidRaidStatus::Loss { + inner: RaidRaidStatusStruct::from_raw(env, obj)?, + }), + "STOPPED" => Ok(RaidRaidStatus::Stopped { + inner: RaidRaidStatusStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } - /// Creates a new entity at the given {@link Location} with the supplied - /// function run before the entity is added to the world. - /// - /// Note that when the function is run, the entity will not be actually in - /// the world. Any operation involving such as teleporting the entity is undefined - /// until after this function returns. - /// The passed function however is run after the potential entity's spawn - /// randomization and hence already allows access to the values of the mob, - /// whether or not those were randomized, such as attributes or the entity - /// equipment. - pub fn spawn( - &self, - location: impl Into>, - clazz: jni::objects::JClass<'mc>, - randomize_data: std::option::Option, - function: std::option::Option< - impl Into>, - >, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Ljava/lang/Class;"; - let val_2 = jni::objects::JValueGen::Object(clazz.into()); - args.push(val_2); - if let Some(a) = randomize_data { - sig += "Z"; - let val_3 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_3); +} + +#[repr(C)] +pub struct RaidRaidStatusStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for RaidRaidStatus<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Ongoing { inner } => inner.0.clone(), + Self::Victory { inner } => inner.0.clone(), + Self::Loss { inner } => inner.0.clone(), + Self::Stopped { inner } => inner.0.clone(), } - if let Some(a) = function { - sig += "Ljava/util/function/Consumer;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_4); + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Ongoing { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Victory { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Loss { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Stopped { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, } - sig += ")LT;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "spawn", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) } - /// Gets the highest coordinate corresponding to the {@link HeightMap} at the - /// given {@link Location}. - pub fn get_highest_block_yat( - &self, - location: impl Into>, - height_map: std::option::Option>>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(location.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = height_map { - sig += "Lorg/bukkit/HeightMap;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); +} +impl<'mc> JNIInstantiatable<'mc> for RaidRaidStatus<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate RaidRaidStatus from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Raid/RaidStatus")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a RaidRaidStatus object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "ONGOING" => Ok(RaidRaidStatus::Ongoing { + inner: RaidRaidStatusStruct::from_raw(env, obj)?, + }), + "VICTORY" => Ok(RaidRaidStatus::Victory { + inner: RaidRaidStatusStruct::from_raw(env, obj)?, + }), + "LOSS" => Ok(RaidRaidStatus::Loss { + inner: RaidRaidStatusStruct::from_raw(env, obj)?, + }), + "STOPPED" => Ok(RaidRaidStatus::Stopped { + inner: RaidRaidStatusStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } - sig += ")I"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "getHighestBlockYAt", - sig.as_str(), - args, - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) } - /// Spawns a previously created entity in the world. - /// - /// The provided entity must not have already been spawned in a world. - pub fn add_entity( - &self, - entity: jni::objects::JObject<'mc>, - ) -> Result, Box> { - let sig = String::from("(LT;)LT;"); - let val_1 = jni::objects::JValueGen::Object(entity); - let res = self.jni_ref().call_method( - &self.jni_object(), - "addEntity", - sig.as_str(), +} + +impl<'mc> JNIRaw<'mc> for RaidRaidStatusStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for RaidRaidStatusStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate RaidRaidStatusStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Raid/RaidStatus")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a RaidRaidStatusStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> RaidRaidStatusStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Raid/RaidStatus;"); + let cls = jni.find_class("org/bukkit/Raid/RaidStatus"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::RaidRaidStatus::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +pub enum Rotation<'mc> { + None { inner: RotationStruct<'mc> }, + Clockwise45 { inner: RotationStruct<'mc> }, + Clockwise { inner: RotationStruct<'mc> }, + Clockwise135 { inner: RotationStruct<'mc> }, + Flipped { inner: RotationStruct<'mc> }, + Flipped45 { inner: RotationStruct<'mc> }, + CounterClockwise { inner: RotationStruct<'mc> }, + CounterClockwise45 { inner: RotationStruct<'mc> }, +} +impl<'mc> std::fmt::Display for Rotation<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Rotation::None { .. } => f.write_str("NONE"), + Rotation::Clockwise45 { .. } => f.write_str("CLOCKWISE_45"), + Rotation::Clockwise { .. } => f.write_str("CLOCKWISE"), + Rotation::Clockwise135 { .. } => f.write_str("CLOCKWISE_135"), + Rotation::Flipped { .. } => f.write_str("FLIPPED"), + Rotation::Flipped45 { .. } => f.write_str("FLIPPED_45"), + Rotation::CounterClockwise { .. } => f.write_str("COUNTER_CLOCKWISE"), + Rotation::CounterClockwise45 { .. } => f.write_str("COUNTER_CLOCKWISE_45"), + } + } +} +impl<'mc> std::ops::Deref for Rotation<'mc> { + type Target = RotationStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + Rotation::None { inner } => inner, + Rotation::Clockwise45 { inner } => inner, + Rotation::Clockwise { inner } => inner, + Rotation::Clockwise135 { inner } => inner, + Rotation::Flipped { inner } => inner, + Rotation::Flipped45 { inner } => inner, + Rotation::CounterClockwise { inner } => inner, + Rotation::CounterClockwise45 { inner } => inner, + } + } +} + +impl<'mc> Rotation<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/Rotation"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/Rotation;", vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) - } + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "NONE" => Ok(Rotation::None { + inner: RotationStruct::from_raw(env, obj)?, + }), + "CLOCKWISE_45" => Ok(Rotation::Clockwise45 { + inner: RotationStruct::from_raw(env, obj)?, + }), + "CLOCKWISE" => Ok(Rotation::Clockwise { + inner: RotationStruct::from_raw(env, obj)?, + }), + "CLOCKWISE_135" => Ok(Rotation::Clockwise135 { + inner: RotationStruct::from_raw(env, obj)?, + }), + "FLIPPED" => Ok(Rotation::Flipped { + inner: RotationStruct::from_raw(env, obj)?, + }), + "FLIPPED_45" => Ok(Rotation::Flipped45 { + inner: RotationStruct::from_raw(env, obj)?, + }), + "COUNTER_CLOCKWISE" => Ok(Rotation::CounterClockwise { + inner: RotationStruct::from_raw(env, obj)?, + }), + "COUNTER_CLOCKWISE_45" => Ok(Rotation::CounterClockwise45 { + inner: RotationStruct::from_raw(env, obj)?, + }), - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } + #[repr(C)] -pub struct WorldCreator<'mc>( +pub struct RotationStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for WorldCreator<'mc> { +impl<'mc> JNIRaw<'mc> for Rotation<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::None { inner } => inner.0.clone(), + Self::Clockwise45 { inner } => inner.0.clone(), + Self::Clockwise { inner } => inner.0.clone(), + Self::Clockwise135 { inner } => inner.0.clone(), + Self::Flipped { inner } => inner.0.clone(), + Self::Flipped45 { inner } => inner.0.clone(), + Self::CounterClockwise { inner } => inner.0.clone(), + Self::CounterClockwise45 { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::None { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Clockwise45 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Clockwise { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Clockwise135 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Flipped { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Flipped45 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CounterClockwise { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CounterClockwise45 { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for Rotation<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Rotation from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Rotation")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Rotation object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "NONE" => Ok(Rotation::None { + inner: RotationStruct::from_raw(env, obj)?, + }), + "CLOCKWISE_45" => Ok(Rotation::Clockwise45 { + inner: RotationStruct::from_raw(env, obj)?, + }), + "CLOCKWISE" => Ok(Rotation::Clockwise { + inner: RotationStruct::from_raw(env, obj)?, + }), + "CLOCKWISE_135" => Ok(Rotation::Clockwise135 { + inner: RotationStruct::from_raw(env, obj)?, + }), + "FLIPPED" => Ok(Rotation::Flipped { + inner: RotationStruct::from_raw(env, obj)?, + }), + "FLIPPED_45" => Ok(Rotation::Flipped45 { + inner: RotationStruct::from_raw(env, obj)?, + }), + "COUNTER_CLOCKWISE" => Ok(Rotation::CounterClockwise { + inner: RotationStruct::from_raw(env, obj)?, + }), + "COUNTER_CLOCKWISE_45" => Ok(Rotation::CounterClockwise45 { + inner: RotationStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for RotationStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -20524,18 +74867,20 @@ impl<'mc> JNIRaw<'mc> for WorldCreator<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for WorldCreator<'mc> { +impl<'mc> JNIInstantiatable<'mc> for RotationStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate WorldCreator from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate RotationStruct from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/WorldCreator")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/Rotation")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a WorldCreator object, got {}", + "Invalid argument passed. Expected a RotationStruct object, got {}", name ) .into()) @@ -20545,420 +74890,248 @@ impl<'mc> JNIInstantiatable<'mc> for WorldCreator<'mc> { } } -impl<'mc> WorldCreator<'mc> { - /// Creates an empty WorldCreationOptions for the given world name - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - name: impl Into, - ) -> Result, Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(name.into())?, - )); - let cls = jni.find_class("org/bukkit/WorldCreator"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error_no_gen(res)?; - crate::WorldCreator::from_raw(&jni, res) - } - /// Copies the options from the specified {@link WorldCreator} - pub fn copy( - &self, - creator: impl Into>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/WorldCreator;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(creator.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Lorg/bukkit/WorldCreator;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "copy", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::WorldCreator::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Creates a new {@link WorldCreator} for the given world name - pub fn name( +impl<'mc> RotationStruct<'mc> { + pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - name: std::option::Option>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = name { - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(a.into())?, - )); - args.push(val_1); - } - sig += ")Lorg/bukkit/WorldCreator;"; - let cls = jni.find_class("org/bukkit/WorldCreator"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Rotation;"); + let cls = jni.find_class("org/bukkit/Rotation"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "name", sig.as_str(), args); + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::WorldCreator::from_raw(&jni, obj) + crate::Rotation::from_raw(&jni, obj) } - /// Sets the seed that will be used to create this world - pub fn seed( - &self, - seed: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = seed { - sig += "J"; - let val_1 = jni::objects::JValueGen::Long(a); - args.push(val_1); - } - sig += ")Lorg/bukkit/WorldCreator;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "seed", sig.as_str(), args); + /// Rotate clockwise by 90 degrees. + pub fn rotate_clockwise(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Rotation;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "rotateClockwise", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::WorldCreator::from_raw(&self.jni_ref(), unsafe { + crate::Rotation::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the environment that will be used to create or load the world - pub fn environment( + /// Rotate counter-clockwise by 90 degrees. + pub fn rotate_counter_clockwise( &self, - env: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = env { - sig += "Lorg/bukkit/World/Environment;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")Lorg/bukkit/WorldCreator;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "environment", sig.as_str(), args); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Rotation;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "rotateCounterClockwise", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - crate::WorldCreator::from_raw(&self.jni_ref(), unsafe { + crate::Rotation::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the type of the world that will be created or loaded - pub fn get_type( - &self, - val_type: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = val_type { - sig += "Lorg/bukkit/WorldType;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - sig += ")Lorg/bukkit/WorldCreator;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "type", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::WorldCreator::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Sets the generator that will be used to create or load the world. - /// - /// This may be null, in which case the "natural" generator for this - /// environment will be used. - /// - /// If the generator cannot be found for the given name, the natural - /// environment generator will be used instead and a warning will be - /// printed to the specified output - pub fn generator( - &self, - generator: std::option::Option>, - output: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = generator { - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_1); +} +#[repr(C)] +pub struct UndefinedNullability<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for UndefinedNullability<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for UndefinedNullability<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate UndefinedNullability from null object.").into(), + ); } - if let Some(a) = output { - sig += "Lorg/bukkit/command/CommandSender;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); + let (valid, name) = env.validate_name(&obj, "org/bukkit/UndefinedNullability")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a UndefinedNullability object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - sig += ")Lorg/bukkit/WorldCreator;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "generator", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::WorldCreator::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) } - /// Sets the biome provider that will be used to create or load the world. - /// - /// This may be null, in which case the biome provider from the - /// {@link ChunkGenerator} will be used. If no {@link ChunkGenerator} is - /// specific the "natural" biome provider for this environment will be used. - /// - /// If the biome provider cannot be found for the given name and no - /// {@link ChunkGenerator} is specific, the natural environment biome - /// provider will be used instead and a warning will be printed to the - /// specified output - pub fn biome_provider( - &self, - biome_provider: std::option::Option>, - output: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = biome_provider { - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_1); +} + +impl<'mc> UndefinedNullability<'mc> { + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +pub enum WeatherType<'mc> { + Downfall { inner: WeatherTypeStruct<'mc> }, + Clear { inner: WeatherTypeStruct<'mc> }, +} +impl<'mc> std::fmt::Display for WeatherType<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + WeatherType::Downfall { .. } => f.write_str("DOWNFALL"), + WeatherType::Clear { .. } => f.write_str("CLEAR"), } - if let Some(a) = output { - sig += "Lorg/bukkit/command/CommandSender;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); + } +} +impl<'mc> std::ops::Deref for WeatherType<'mc> { + type Target = WeatherTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + WeatherType::Downfall { inner } => inner, + WeatherType::Clear { inner } => inner, } - sig += ")Lorg/bukkit/WorldCreator;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "biomeProvider", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::WorldCreator::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) } - /// Sets the generator settings of the world that will be created or loaded. - /// - /// Currently only {@link WorldType#FLAT} uses these settings, and expects - /// them to be in JSON format with a valid biome (1.18.2 and - /// above) defined. An example valid configuration is as follows: - /// {"layers": [{"block": "stone", "height": 1}, {"block": "grass_block", "height": 1}], "biome":"plains"} - pub fn generator_settings( - &self, - generator_settings: std::option::Option>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = generator_settings { - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_1); +} + +impl<'mc> WeatherType<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/WeatherType"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/WeatherType;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "DOWNFALL" => Ok(WeatherType::Downfall { + inner: WeatherTypeStruct::from_raw(env, obj)?, + }), + "CLEAR" => Ok(WeatherType::Clear { + inner: WeatherTypeStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } - sig += ")Lorg/bukkit/WorldCreator;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "generatorSettings", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::WorldCreator::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) } - /// Sets whether or not worlds created or loaded with this creator will - /// have structures. - pub fn generate_structures( - &self, - generate: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = generate { - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_1); +} + +#[repr(C)] +pub struct WeatherTypeStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for WeatherType<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Downfall { inner } => inner.0.clone(), + Self::Clear { inner } => inner.0.clone(), } - sig += ")Lorg/bukkit/WorldCreator;"; - let res = self.jni_ref().call_method( - &self.jni_object(), - "generateStructures", - sig.as_str(), - args, - ); - let res = self.jni_ref().translate_error(res)?; - crate::WorldCreator::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) } - /// Sets whether the world will be hardcore or not. - /// In a hardcore world the difficulty will be locked to hard. - pub fn hardcore( - &self, - hardcore: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = hardcore { - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_1); + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Downfall { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Clear { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, } - sig += ")Lorg/bukkit/WorldCreator;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hardcore", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::WorldCreator::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) } - /// Sets whether the spawn chunks will be kept loaded. - /// - /// Setting this to false will also stop the spawn chunks from being generated - /// when creating a new world. - /// - /// Has little performance benefit unless paired with a {@link ChunkGenerator} - /// that overrides {@link ChunkGenerator#getFixedSpawnLocation(World, Random)}. - pub fn keep_spawn_in_memory( - &self, - keep_spawn_in_memory: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = keep_spawn_in_memory { - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_1); +} +impl<'mc> JNIInstantiatable<'mc> for WeatherType<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate WeatherType from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/WeatherType")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a WeatherType object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "DOWNFALL" => Ok(WeatherType::Downfall { + inner: WeatherTypeStruct::from_raw(env, obj)?, + }), + "CLEAR" => Ok(WeatherType::Clear { + inner: WeatherTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } - sig += ")Lorg/bukkit/WorldCreator;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "keepSpawnInMemory", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::WorldCreator::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) } - /// Creates a world with the specified options. - /// - /// If the world already exists, it will be loaded from disk and some - /// options may be ignored. - pub fn create_world(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "createWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::World::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) +} + +impl<'mc> JNIRaw<'mc> for WeatherTypeStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Attempts to get the {@link ChunkGenerator} with the given name. - /// - /// If the generator is not found, null will be returned and a message will - /// be printed to the specified {@link CommandSender} explaining why. - /// - /// The name must be in the "plugin:id" notation, or optionally just - /// "plugin", where "plugin" is the safe-name of a plugin and "id" is an - /// optional unique identifier for the generator you wish to request from - /// the plugin. - pub fn get_generator_for_name( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - world: impl Into, - name: impl Into, - output: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;Ljava/lang/String;Lorg/bukkit/command/CommandSender;)Lorg/bukkit/generator/ChunkGenerator;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(world.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(name.into())?, - )); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(output.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/WorldCreator"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getGeneratorForName", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for WeatherTypeStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate WeatherTypeStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/WeatherType")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a WeatherTypeStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - let obj = res.l()?; - Ok(Some(crate::generator::ChunkGenerator::from_raw(&jni, obj)?)) } - /// Attempts to get the {@link BiomeProvider} with the given name. - /// - /// If the biome provider is not found, null will be returned and a message - /// will be printed to the specified {@link CommandSender} explaining why. - /// - /// The name must be in the "plugin:id" notation, or optionally just - /// "plugin", where "plugin" is the safe-name of a plugin and "id" is an - /// optional unique identifier for the biome provider you wish to request - /// from the plugin. - pub fn get_biome_provider_for_name( +} + +impl<'mc> WeatherTypeStruct<'mc> { + pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - world: impl Into, - name: impl Into, - output: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;Ljava/lang/String;Lorg/bukkit/command/CommandSender;)Lorg/bukkit/generator/BiomeProvider;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(world.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(name.into())?, - )); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(output.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/WorldCreator"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/WeatherType;"); + let cls = jni.find_class("org/bukkit/WeatherType"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getBiomeProviderForName", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } let obj = res.l()?; - Ok(Some(crate::generator::BiomeProvider::from_raw(&jni, obj)?)) + crate::WeatherType::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -20967,12 +75140,12 @@ impl<'mc> WorldCreator<'mc> { } } #[repr(C)] -pub struct ChunkSnapshot<'mc>( +pub struct WorldBorder<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ChunkSnapshot<'mc> { +impl<'mc> JNIRaw<'mc> for WorldBorder<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -20980,18 +75153,18 @@ impl<'mc> JNIRaw<'mc> for ChunkSnapshot<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ChunkSnapshot<'mc> { +impl<'mc> JNIInstantiatable<'mc> for WorldBorder<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ChunkSnapshot from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate WorldBorder from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/ChunkSnapshot")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/WorldBorder")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ChunkSnapshot object, got {}", + "Invalid argument passed. Expected a WorldBorder object, got {}", name ) .into()) @@ -21001,278 +75174,203 @@ impl<'mc> JNIInstantiatable<'mc> for ChunkSnapshot<'mc> { } } -impl<'mc> ChunkSnapshot<'mc> { - /// Gets the X-coordinate of this chunk - pub fn x(&self) -> Result> { - let sig = String::from("()I"); +impl<'mc> WorldBorder<'mc> { + /// Get the {@link World} in which the border resides. + pub fn world(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/World;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) } - /// Gets the Z-coordinate of this chunk - pub fn z(&self) -> Result> { - let sig = String::from("()I"); + /// Resets the border to default values. + pub fn reset(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + .call_method(&self.jni_object(), "reset", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Gets name of the world containing this chunk - pub fn world_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getWorldName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self + /// Gets the current side length of the border. + pub fn size(&self) -> Result> { + let sig = String::from("()D"); + let res = self .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } - /// Get block type for block at corresponding coordinate in the chunk - pub fn get_block_type( - &self, - x: i32, - y: i32, - z: i32, - ) -> Result, Box> { - let sig = String::from("(III)Lorg/bukkit/Material;"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(y); - let val_3 = jni::objects::JValueGen::Int(z); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getBlockType", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); + /// Gets the current border center. + pub fn center(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCenter", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { + crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get block data for block at corresponding coordinate in the chunk - pub fn get_block_data( + /// Sets the new border center. + pub fn set_center( &self, - x: i32, - y: i32, - z: i32, - ) -> Result, Box> { - let sig = String::from("(III)Lorg/bukkit/block/data/BlockData;"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(y); - let val_3 = jni::objects::JValueGen::Int(z); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getBlockData", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = self.jni_ref().translate_error(res)?; - crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + x: f64, + z: std::option::Option, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(x); + args.push(val_1); + if let Some(a) = z { + sig += "D"; + let val_2 = jni::objects::JValueGen::Double(a); + args.push(val_2); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setCenter", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - #[deprecated] - /// Get block data for block at corresponding coordinate in the chunk - pub fn get_data(&self, x: i32, y: i32, z: i32) -> Result> { - let sig = String::from("(III)I"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(y); - let val_3 = jni::objects::JValueGen::Int(z); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getData", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); + /// Gets the current border damage buffer. + pub fn damage_buffer(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDamageBuffer", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.d()?) } - /// Get sky light level for block at corresponding coordinate in the chunk - pub fn get_block_sky_light( - &self, - x: i32, - y: i32, - z: i32, - ) -> Result> { - let sig = String::from("(III)I"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(y); - let val_3 = jni::objects::JValueGen::Int(z); + /// Sets the amount of blocks a player may safely be outside the border before taking damage. + pub fn set_damage_buffer(&self, blocks: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(blocks); let res = self.jni_ref().call_method( &self.jni_object(), - "getBlockSkyLight", + "setDamageBuffer", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the current border damage amount. + pub fn damage_amount(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDamageAmount", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.d()?) } - /// Get light level emitted by block at corresponding coordinate in the - /// chunk - pub fn get_block_emitted_light( - &self, - x: i32, - y: i32, - z: i32, - ) -> Result> { - let sig = String::from("(III)I"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(y); - let val_3 = jni::objects::JValueGen::Int(z); + /// Sets the amount of damage a player takes when outside the border plus the border buffer. + pub fn set_damage_amount(&self, damage: f64) -> Result<(), Box> { + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(damage); let res = self.jni_ref().call_method( &self.jni_object(), - "getBlockEmittedLight", + "setDamageAmount", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![jni::objects::JValueGen::from(val_1)], ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the current border warning time in seconds. + pub fn warning_time(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getWarningTime", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Gets the highest non-air coordinate at the given coordinates - pub fn get_highest_block_yat(&self, x: i32, z: i32) -> Result> { - let sig = String::from("(II)I"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(z); + /// Sets the warning time that causes the screen to be tinted red when a contracting border will reach the player within the specified time. + pub fn set_warning_time(&self, seconds: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(seconds); let res = self.jni_ref().call_method( &self.jni_object(), - "getHighestBlockYAt", + "setWarningTime", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Get biome at given coordinates - pub fn get_biome( - &self, - x: i32, - y: i32, - z: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); - args.push(val_1); - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(y); - args.push(val_2); - if let Some(a) = z { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - sig += ")Lorg/bukkit/block/Biome;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBiome", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::block::Biome::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Get raw biome temperature at given coordinates - pub fn get_raw_biome_temperature( - &self, - x: i32, - y: i32, - z: std::option::Option, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); - args.push(val_1); - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(y); - args.push(val_2); - if let Some(a) = z { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - sig += ")D"; + /// Gets the current border warning distance. + pub fn warning_distance(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getRawBiomeTemperature", + "getWarningDistance", sig.as_str(), - args, + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.i()?) } - /// Get world full time when chunk snapshot was captured - pub fn capture_full_time(&self) -> Result> { - let sig = String::from("()J"); + /// Sets the warning distance that causes the screen to be tinted red when the player is within the specified number of blocks from the border. + pub fn set_warning_distance(&self, distance: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(distance); let res = self.jni_ref().call_method( &self.jni_object(), - "getCaptureFullTime", + "setWarningDistance", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - /// Test if section is empty - pub fn is_section_empty(&self, sy: i32) -> Result> { - let sig = String::from("(I)Z"); - let val_1 = jni::objects::JValueGen::Int(sy); + /// Check if the specified location is inside this border. + pub fn is_inside( + &self, + location: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/Location;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "isSectionEmpty", + "isInside", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Tests if this chunk contains the specified biome. - pub fn contains( - &self, - biome: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/block/Biome;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(biome.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "contains", sig.as_str(), args); + /// Gets the maximum possible size of a WorldBorder. + pub fn max_size(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMaxSize", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the absolute value of the maximum x/z center coordinate of a + /// WorldBorder. + pub fn max_center_coordinate(&self) -> Result> { + let sig = String::from("()D"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaxCenterCoordinate", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.d()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -21281,12 +75379,12 @@ impl<'mc> ChunkSnapshot<'mc> { } } #[repr(C)] -pub struct SoundGroup<'mc>( +pub struct ServerLinks<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for SoundGroup<'mc> { +impl<'mc> JNIRaw<'mc> for ServerLinks<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -21294,18 +75392,18 @@ impl<'mc> JNIRaw<'mc> for SoundGroup<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for SoundGroup<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ServerLinks<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate SoundGroup from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate ServerLinks from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/SoundGroup")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/ServerLinks")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SoundGroup object, got {}", + "Invalid argument passed. Expected a ServerLinks object, got {}", name ) .into()) @@ -21315,81 +75413,132 @@ impl<'mc> JNIInstantiatable<'mc> for SoundGroup<'mc> { } } -impl<'mc> SoundGroup<'mc> { - /// Get the volume these sounds are played at. - /// Note that this volume does not always represent the actual volume - /// received by the client. - pub fn volume(&self) -> Result> { - let sig = String::from("()F"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getVolume", sig.as_str(), vec![]); +impl<'mc> ServerLinks<'mc> { + /// Gets the link of a given type, if it exists. + pub fn get_link( + &self, + val_type: impl Into>, + ) -> Result>, Box> { + let sig = + String::from("(Lorg/bukkit/ServerLinks/Type;)Lorg/bukkit/ServerLinks/ServerLink;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getLink", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::ServerLinksServerLink::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets the pitch these sounds are played at. - /// Note that this pitch does not always represent the actual pitch received - /// by the client. - pub fn pitch(&self) -> Result> { - let sig = String::from("()F"); + /// Gets an immutable list of all links. + pub fn links( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getPitch", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Gets the corresponding breaking sound for this group. - pub fn break_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getBreakSound", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLinks", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::ServerLinksServerLink::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(new_vec) } - /// Gets the corresponding step sound for this group. - pub fn step_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getStepSound", sig.as_str(), vec![]); + /// Adds the given link, overwriting the first link of the same type if + /// already set. + pub fn set_link( + &self, + val_type: impl Into>, + url: jni::objects::JObject<'mc>, + ) -> Result, Box> { + let sig = String::from( + "(Lorg/bukkit/ServerLinks/Type;Ljava/net/URI;)Lorg/bukkit/ServerLinks/ServerLink;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(url); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLink", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { + crate::ServerLinksServerLink::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the corresponding place sound for this group. - pub fn place_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPlaceSound", sig.as_str(), vec![]); + /// Adds the given link to the list of links. + pub fn add_link( + &self, + display_name: impl Into, + url: jni::objects::JObject<'mc>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(display_name.into())?, + )); + args.push(val_1); + sig += "Ljava/net/URI;"; + let val_2 = jni::objects::JValueGen::Object(url); + args.push(val_2); + sig += ")Lorg/bukkit/ServerLinks/ServerLink;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "addLink", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { + crate::ServerLinksServerLink::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the corresponding hit sound for this group. - pub fn hit_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHitSound", sig.as_str(), vec![]); + /// Removes the given link. + pub fn remove_link( + &self, + link: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/ServerLinks/ServerLink;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(link.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeLink", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Gets the corresponding fall sound for this group. - pub fn fall_sound(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Sound;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getFallSound", sig.as_str(), vec![]); + /// Returns a copy of this link collection, unassociated from the server. + pub fn copy(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/ServerLinks;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "copy", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Sound::from_raw(&self.jni_ref(), unsafe { + crate::ServerLinks::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -21400,12 +75549,12 @@ impl<'mc> SoundGroup<'mc> { } } #[repr(C)] -pub struct Translatable<'mc>( +pub struct ServerLinksServerLink<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Translatable<'mc> { +impl<'mc> JNIRaw<'mc> for ServerLinksServerLink<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -21413,18 +75562,21 @@ impl<'mc> JNIRaw<'mc> for Translatable<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Translatable<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ServerLinksServerLink<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Translatable from null object.").into()); + return Err(eyre::eyre!( + "Tried to instantiate ServerLinksServerLink from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Translatable")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/ServerLinks/ServerLink")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Translatable object, got {}", + "Invalid argument passed. Expected a ServerLinksServerLink object, got {}", name ) .into()) @@ -21434,16 +75586,30 @@ impl<'mc> JNIInstantiatable<'mc> for Translatable<'mc> { } } -impl<'mc> Translatable<'mc> { - /// Get the translation key, suitable for use in a translation component. - pub fn translation_key(&self) -> Result> { +impl<'mc> ServerLinksServerLink<'mc> { + /// Gets the type of this link if it is a known special type. + pub fn get_type( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/ServerLinks/Type;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::ServerLinksType::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Gets the display name/text of this link. + pub fn display_name(&self) -> Result> { let sig = String::from("()Ljava/lang/String;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTranslationKey", - sig.as_str(), - vec![], - ); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDisplayName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(self .jni_ref() @@ -21451,31 +75617,79 @@ impl<'mc> Translatable<'mc> { .to_string_lossy() .to_string()) } + /// Gets the url of this link. + pub fn url(&self) -> Result, Box> { + let sig = String::from("()Ljava/net/URI;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getUrl", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) + } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum GameMode<'mc> {} -impl<'mc> std::fmt::Display for GameMode<'mc> { +pub enum ServerLinksType<'mc> { + ReportBug { inner: ServerLinksTypeStruct<'mc> }, + CommunityGuidelines { inner: ServerLinksTypeStruct<'mc> }, + Support { inner: ServerLinksTypeStruct<'mc> }, + Status { inner: ServerLinksTypeStruct<'mc> }, + Feedback { inner: ServerLinksTypeStruct<'mc> }, + Community { inner: ServerLinksTypeStruct<'mc> }, + Website { inner: ServerLinksTypeStruct<'mc> }, + Forums { inner: ServerLinksTypeStruct<'mc> }, + News { inner: ServerLinksTypeStruct<'mc> }, + Announcements { inner: ServerLinksTypeStruct<'mc> }, +} +impl<'mc> std::fmt::Display for ServerLinksType<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + ServerLinksType::ReportBug { .. } => f.write_str("REPORT_BUG"), + ServerLinksType::CommunityGuidelines { .. } => f.write_str("COMMUNITY_GUIDELINES"), + ServerLinksType::Support { .. } => f.write_str("SUPPORT"), + ServerLinksType::Status { .. } => f.write_str("STATUS"), + ServerLinksType::Feedback { .. } => f.write_str("FEEDBACK"), + ServerLinksType::Community { .. } => f.write_str("COMMUNITY"), + ServerLinksType::Website { .. } => f.write_str("WEBSITE"), + ServerLinksType::Forums { .. } => f.write_str("FORUMS"), + ServerLinksType::News { .. } => f.write_str("NEWS"), + ServerLinksType::Announcements { .. } => f.write_str("ANNOUNCEMENTS"), + } + } +} +impl<'mc> std::ops::Deref for ServerLinksType<'mc> { + type Target = ServerLinksTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + ServerLinksType::ReportBug { inner } => inner, + ServerLinksType::CommunityGuidelines { inner } => inner, + ServerLinksType::Support { inner } => inner, + ServerLinksType::Status { inner } => inner, + ServerLinksType::Feedback { inner } => inner, + ServerLinksType::Community { inner } => inner, + ServerLinksType::Website { inner } => inner, + ServerLinksType::Forums { inner } => inner, + ServerLinksType::News { inner } => inner, + ServerLinksType::Announcements { inner } => inner, + } } } -impl<'mc> GameMode<'mc> { +impl<'mc> ServerLinksType<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/GameMode"); + let cls = env.find_class("org/bukkit/ServerLinks/Type"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/GameMode;", + "(Ljava/lang/String;)Lorg/bukkit/ServerLinks/Type;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -21487,37 +75701,100 @@ impl<'mc> GameMode<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "REPORT_BUG" => Ok(ServerLinksType::ReportBug { + inner: ServerLinksTypeStruct::from_raw(env, obj)?, + }), + "COMMUNITY_GUIDELINES" => Ok(ServerLinksType::CommunityGuidelines { + inner: ServerLinksTypeStruct::from_raw(env, obj)?, + }), + "SUPPORT" => Ok(ServerLinksType::Support { + inner: ServerLinksTypeStruct::from_raw(env, obj)?, + }), + "STATUS" => Ok(ServerLinksType::Status { + inner: ServerLinksTypeStruct::from_raw(env, obj)?, + }), + "FEEDBACK" => Ok(ServerLinksType::Feedback { + inner: ServerLinksTypeStruct::from_raw(env, obj)?, + }), + "COMMUNITY" => Ok(ServerLinksType::Community { + inner: ServerLinksTypeStruct::from_raw(env, obj)?, + }), + "WEBSITE" => Ok(ServerLinksType::Website { + inner: ServerLinksTypeStruct::from_raw(env, obj)?, + }), + "FORUMS" => Ok(ServerLinksType::Forums { + inner: ServerLinksTypeStruct::from_raw(env, obj)?, + }), + "NEWS" => Ok(ServerLinksType::News { + inner: ServerLinksTypeStruct::from_raw(env, obj)?, + }), + "ANNOUNCEMENTS" => Ok(ServerLinksType::Announcements { + inner: ServerLinksTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct GameModeStruct<'mc>( +pub struct ServerLinksTypeStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for GameMode<'mc> { +impl<'mc> JNIRaw<'mc> for ServerLinksType<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::ReportBug { inner } => inner.0.clone(), + Self::CommunityGuidelines { inner } => inner.0.clone(), + Self::Support { inner } => inner.0.clone(), + Self::Status { inner } => inner.0.clone(), + Self::Feedback { inner } => inner.0.clone(), + Self::Community { inner } => inner.0.clone(), + Self::Website { inner } => inner.0.clone(), + Self::Forums { inner } => inner.0.clone(), + Self::News { inner } => inner.0.clone(), + Self::Announcements { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::ReportBug { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CommunityGuidelines { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Support { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Status { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Feedback { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Community { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Website { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Forums { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::News { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Announcements { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } -impl<'mc> JNIInstantiatable<'mc> for GameMode<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ServerLinksType<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate GameMode from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate ServerLinksType from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/GameMode")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/ServerLinks/Type")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a GameMode object, got {}", + "Invalid argument passed. Expected a ServerLinksType object, got {}", name ) .into()) @@ -21529,13 +75806,43 @@ impl<'mc> JNIInstantiatable<'mc> for GameMode<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "REPORT_BUG" => Ok(ServerLinksType::ReportBug { + inner: ServerLinksTypeStruct::from_raw(env, obj)?, + }), + "COMMUNITY_GUIDELINES" => Ok(ServerLinksType::CommunityGuidelines { + inner: ServerLinksTypeStruct::from_raw(env, obj)?, + }), + "SUPPORT" => Ok(ServerLinksType::Support { + inner: ServerLinksTypeStruct::from_raw(env, obj)?, + }), + "STATUS" => Ok(ServerLinksType::Status { + inner: ServerLinksTypeStruct::from_raw(env, obj)?, + }), + "FEEDBACK" => Ok(ServerLinksType::Feedback { + inner: ServerLinksTypeStruct::from_raw(env, obj)?, + }), + "COMMUNITY" => Ok(ServerLinksType::Community { + inner: ServerLinksTypeStruct::from_raw(env, obj)?, + }), + "WEBSITE" => Ok(ServerLinksType::Website { + inner: ServerLinksTypeStruct::from_raw(env, obj)?, + }), + "FORUMS" => Ok(ServerLinksType::Forums { + inner: ServerLinksTypeStruct::from_raw(env, obj)?, + }), + "NEWS" => Ok(ServerLinksType::News { + inner: ServerLinksTypeStruct::from_raw(env, obj)?, + }), + "ANNOUNCEMENTS" => Ok(ServerLinksType::Announcements { + inner: ServerLinksTypeStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for GameModeStruct<'mc> { +impl<'mc> JNIRaw<'mc> for ServerLinksTypeStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -21543,20 +75850,21 @@ impl<'mc> JNIRaw<'mc> for GameModeStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for GameModeStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ServerLinksTypeStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate GameModeStruct from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate ServerLinksTypeStruct from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/GameMode")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/ServerLinks/Type")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a GameModeStruct object, got {}", + "Invalid argument passed. Expected a ServerLinksTypeStruct object, got {}", name ) .into()) @@ -21566,50 +75874,70 @@ impl<'mc> JNIInstantiatable<'mc> for GameModeStruct<'mc> { } } -impl<'mc> GameModeStruct<'mc> { +impl<'mc> ServerLinksTypeStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/GameMode;"); - let cls = jni.find_class("org/bukkit/GameMode"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/ServerLinks/Type;"); + let cls = jni.find_class("org/bukkit/ServerLinks/Type"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::GameMode::from_raw(&jni, obj) + crate::ServerLinksType::from_raw(&jni, obj) } - #[deprecated] - /// Gets the mode value associated with this GameMode - pub fn value(&self) -> Result> { - let sig = String::from("()I"); + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct FeatureFlag<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for FeatureFlag<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for FeatureFlag<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate FeatureFlag from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/FeatureFlag")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a FeatureFlag object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> FeatureFlag<'mc> { + /// Return the namespaced identifier for this object. + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getValue", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - #[deprecated] - /// Gets the GameMode represented by the specified value - pub fn get_by_value( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - value: i32, - ) -> Result>, Box> { - let sig = String::from("(I)Lorg/bukkit/GameMode;"); - let val_1 = jni::objects::JValueGen::Int(value); - let cls = jni.find_class("org/bukkit/GameMode"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getByValue", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::GameMode::from_raw(&jni, obj)?)) + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -21617,85 +75945,197 @@ impl<'mc> GameModeStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum Difficulty<'mc> {} -impl<'mc> std::fmt::Display for Difficulty<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} +impl<'mc> Into> for FeatureFlag<'mc> { + fn into(self) -> crate::Keyed<'mc> { + crate::Keyed::from_raw(&self.jni_ref(), self.1) + .expect("Error converting FeatureFlag into crate::Keyed") } } +#[repr(C)] +pub struct Nameable<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); -impl<'mc> Difficulty<'mc> { - pub fn value_of( +impl<'mc> JNIRaw<'mc> for Nameable<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Nameable<'mc> { + fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/Difficulty"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/Difficulty;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Nameable from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Nameable")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Nameable object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } } } +impl<'mc> Nameable<'mc> { + /// Gets the custom name on a mob or block. If there is no name this method + /// will return null. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn custom_name(&self) -> Result, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/lang/String;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCustomName", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Sets a custom name on a mob or block. This name will be used in death + /// messages and can be sent to the client as a nameplate over the mob. + /// + /// Setting the name to null or an empty string will clear it. + /// + /// This value has no effect on players, they will always use their real + /// name. + pub fn set_custom_name( + &self, + name: impl Into, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(name.into())?, + )); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setCustomName", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} #[repr(C)] -pub struct DifficultyStruct<'mc>( +pub struct Tag<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Difficulty<'mc> { +impl<'mc> JNIRaw<'mc> for Tag<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + self.0.clone() } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Difficulty<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Tag<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Difficulty from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Tag from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Difficulty")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/Tag")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Difficulty object, got {}", + "Invalid argument passed. Expected a Tag object, got {}", name ) .into()) } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + Ok(Self(env.clone(), obj)) } } } -impl<'mc> JNIRaw<'mc> for DifficultyStruct<'mc> { +impl<'mc> Tag<'mc> { + /// Returns whether or not this tag has an entry for the specified item. + pub fn is_tagged( + &self, + item: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(LT;)Z"); + let val_1 = jni::objects::JValueGen::Object(item); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isTagged", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets an immutable set of all tagged items. + pub fn values( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getValues", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Return the namespaced identifier for this object. + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Tag<'mc> { + fn into(self) -> crate::Keyed<'mc> { + crate::Keyed::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Tag into crate::Keyed") + } +} +#[repr(C)] +pub struct RegionAccessor<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for RegionAccessor<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -21703,20 +76143,20 @@ impl<'mc> JNIRaw<'mc> for DifficultyStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for DifficultyStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for RegionAccessor<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate DifficultyStruct from null object.").into(), + eyre::eyre!("Tried to instantiate RegionAccessor from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Difficulty")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/RegionAccessor")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a DifficultyStruct object, got {}", + "Invalid argument passed. Expected a RegionAccessor object, got {}", name ) .into()) @@ -21726,50 +76166,537 @@ impl<'mc> JNIInstantiatable<'mc> for DifficultyStruct<'mc> { } } -impl<'mc> DifficultyStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Difficulty;"); - let cls = jni.find_class("org/bukkit/Difficulty"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::Difficulty::from_raw(&jni, obj) +impl<'mc> RegionAccessor<'mc> { + /// Gets the {@link Biome} at the given coordinates. + pub fn get_biome( + &self, + x: i32, + y: std::option::Option, + z: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); + args.push(val_1); + if let Some(a) = y { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + if let Some(a) = z { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + sig += ")Lorg/bukkit/block/Biome;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBiome", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::block::Biome::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - #[deprecated] - /// Gets the difficulty value associated with this Difficulty. - pub fn value(&self) -> Result> { - let sig = String::from("()I"); + /// Sets the {@link Biome} for the given block coordinates + pub fn set_biome( + &self, + x: i32, + y: i32, + z: std::option::Option, + biome: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); + args.push(val_1); + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(y); + args.push(val_2); + if let Some(a) = z { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + if let Some(a) = biome { + sig += "Lorg/bukkit/block/Biome;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_4); + } + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getValue", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "setBiome", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the {@link BlockState} at the given coordinates. + pub fn get_block_state( + &self, + x: i32, + y: std::option::Option, + z: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); + args.push(val_1); + if let Some(a) = y { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + if let Some(a) = z { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + sig += ")Lorg/bukkit/block/BlockState;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBlockState", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockState::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the {@link BlockData} at the given coordinates. + pub fn get_block_data( + &self, + x: i32, + y: std::option::Option, + z: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); + args.push(val_1); + if let Some(a) = y { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + if let Some(a) = z { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + sig += ")Lorg/bukkit/block/data/BlockData;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBlockData", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the type of the block at the given coordinates. + pub fn get_type( + &self, + x: i32, + y: std::option::Option, + z: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); + args.push(val_1); + if let Some(a) = y { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + if let Some(a) = z { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + sig += ")Lorg/bukkit/Material;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the {@link BlockData} at the given coordinates. + pub fn set_block_data( + &self, + x: i32, + y: i32, + z: std::option::Option, + block_data: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); + args.push(val_1); + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(y); + args.push(val_2); + if let Some(a) = z { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + if let Some(a) = block_data { + sig += "Lorg/bukkit/block/data/BlockData;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_4); + } + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setBlockData", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets the {@link Material} at the given coordinates. + pub fn set_type( + &self, + x: i32, + y: i32, + z: std::option::Option, + material: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); + args.push(val_1); + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(y); + args.push(val_2); + if let Some(a) = z { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + if let Some(a) = material { + sig += "Lorg/bukkit/Material;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_4); + } + sig += ")V"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setType", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Creates a tree at the given {@link Location} + /// + /// The provided predicate gets called for every block which gets changed + /// as a result of the tree generation. When the predicate gets called no + /// modifications to the world are done yet. Which means, that calling + /// {@link #getBlockState(Location)} in the predicate will return the state + /// of the block before the generation. + /// + /// If the predicate returns {@code true} the block gets set in the world. + /// If it returns {@code false} the block won't get set in the world. + pub fn generate_tree( + &self, + location: impl Into>, + random: impl Into>, + val_type: impl Into>, + state_predicate: std::option::Option< + impl Into>, + >, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Ljava/util/Random;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(random.into().jni_object().clone()) + }); + args.push(val_2); + sig += "Lorg/bukkit/TreeType;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + args.push(val_3); + if let Some(a) = state_predicate { + sig += "Ljava/util/function/Predicate;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_4); + } + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "generateTree", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Creates a new entity at the given {@link Location}. + pub fn spawn_entity( + &self, + loc: impl Into>, + val_type: impl Into>, + randomize_data: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(loc.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Lorg/bukkit/entity/EntityType;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + args.push(val_2); + if let Some(a) = randomize_data { + sig += "Z"; + let val_3 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_3); + } + sig += ")Lorg/bukkit/entity/Entity;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "spawnEntity", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::entity::Entity::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get a list of all entities in this RegionAccessor + pub fn entities(&self) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/util/List;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getEntities", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Get a list of all living entities in this RegionAccessor + pub fn living_entities( + &self, + ) -> Result>, Box> { + let args = Vec::new(); + let mut sig = String::from("("); + sig += ")Ljava/util/List;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLivingEntities", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::LivingEntity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Get a collection of all entities in this RegionAccessor matching the given + /// class/interface + pub fn get_entities_by_class( + &self, + cls: jni::objects::JClass<'mc>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(cls.into()); + args.push(val_1); + sig += ")Ljava/util/Collection;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getEntitiesByClass", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(obj); + } + Ok(new_vec) + } + /// Get a collection of all entities in this RegionAccessor matching any of the + /// given classes/interfaces + pub fn get_entities_by_classes( + &self, + classes: jni::objects::JClass<'mc>, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/Class;"; + let val_1 = jni::objects::JValueGen::Object(classes.into()); + args.push(val_1); + sig += ")Ljava/util/Collection;"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getEntitiesByClasses", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::entity::Entity::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Creates an entity of a specific class at the given {@link Location} but + /// does not spawn it in the world. + /// + /// Note: The created entity keeps a reference to the world it was + /// created in, care should be taken that the entity does not outlive the + /// world instance as this will lead to memory leaks. + pub fn create_entity( + &self, + location: impl Into>, + clazz: jni::objects::JClass<'mc>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/Location;Ljava/lang/Class;)LT;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(clazz.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "createEntity", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) + } + /// Creates a new entity at the given {@link Location} with the supplied + /// function run before the entity is added to the world. + /// + /// Note that when the function is run, the entity will not be actually in + /// the world. Any operation involving such as teleporting the entity is undefined + /// until after this function returns. + /// The passed function however is run after the potential entity's spawn + /// randomization and hence already allows access to the values of the mob, + /// whether or not those were randomized, such as attributes or the entity + /// equipment. + pub fn spawn( + &self, + location: impl Into>, + clazz: jni::objects::JClass<'mc>, + randomize_data: std::option::Option, + function: std::option::Option< + impl Into>, + >, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Ljava/lang/Class;"; + let val_2 = jni::objects::JValueGen::Object(clazz.into()); + args.push(val_2); + if let Some(a) = randomize_data { + sig += "Z"; + let val_3 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_3); + } + if let Some(a) = function { + sig += "Ljava/util/function/Consumer;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_4); + } + sig += ")LT;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "spawn", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) + } + /// Gets the highest coordinate corresponding to the {@link HeightMap} at the + /// given {@link Location}. + pub fn get_highest_block_yat( + &self, + location: impl Into>, + height_map: std::option::Option>>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(location.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = height_map { + sig += "Lorg/bukkit/HeightMap;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")I"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "getHighestBlockYAt", + sig.as_str(), + args, + ); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - #[deprecated] - /// Gets the Difficulty represented by the specified value - pub fn get_by_value( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - value: i32, - ) -> Result>, Box> { - let sig = String::from("(I)Lorg/bukkit/Difficulty;"); - let val_1 = jni::objects::JValueGen::Int(value); - let cls = jni.find_class("org/bukkit/Difficulty"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getByValue", + /// Spawns a previously created entity in the world. + /// + /// The provided entity must not have already been spawned in a world. + pub fn add_entity( + &self, + entity: jni::objects::JObject<'mc>, + ) -> Result, Box> { + let sig = String::from("(LT;)LT;"); + let val_1 = jni::objects::JValueGen::Object(entity); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addEntity", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::Difficulty::from_raw(&jni, obj)?)) + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -21778,12 +76705,12 @@ impl<'mc> DifficultyStruct<'mc> { } } #[repr(C)] -pub struct StructureType<'mc>( +pub struct ChunkSnapshot<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for StructureType<'mc> { +impl<'mc> JNIRaw<'mc> for ChunkSnapshot<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -21791,18 +76718,18 @@ impl<'mc> JNIRaw<'mc> for StructureType<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for StructureType<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ChunkSnapshot<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate StructureType from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate ChunkSnapshot from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/StructureType")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/ChunkSnapshot")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a StructureType object, got {}", + "Invalid argument passed. Expected a ChunkSnapshot object, got {}", name ) .into()) @@ -21812,71 +76739,31 @@ impl<'mc> JNIInstantiatable<'mc> for StructureType<'mc> { } } -impl<'mc> StructureType<'mc> { - /// Get the name of this structure. This is case-sensitive when used in - /// commands. - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); +impl<'mc> ChunkSnapshot<'mc> { + /// Gets the X-coordinate of this chunk + pub fn x(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Get the {@link org.bukkit.map.MapCursor.Type} that this structure can use on maps. If - /// this is null, this structure will not appear on explorer maps. - pub fn map_icon( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/map/MapCursor/Type;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMapIcon", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::map::MapCursorType::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - - pub fn equals( - &self, - other: jni::objects::JObject<'mc>, - ) -> Result> { - let sig = String::from("(Ljava/lang/Object;)Z"); - let val_1 = jni::objects::JValueGen::Object(other); - let res = self.jni_ref().call_method( - &self.jni_object(), - "equals", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - - pub fn hash_code(&self) -> Result> { + /// Gets the Z-coordinate of this chunk + pub fn z(&self) -> Result> { let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { + /// Gets name of the world containing this chunk + pub fn world_name(&self) -> Result> { let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getWorldName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(self .jni_ref() @@ -21884,712 +76771,492 @@ impl<'mc> StructureType<'mc> { .to_string_lossy() .to_string()) } - /// Get all registered {@link StructureType}s. - pub fn structure_types( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let cls = jni.find_class("org/bukkit/StructureType"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getStructureTypes", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - blackboxmc_java::util::JavaMap::from_raw(&jni, obj) - } - - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} - -impl<'mc> std::string::ToString for StructureType<'mc> { - fn to_string(&self) -> String { - match &self.internal_to_string() { - Ok(a) => a.clone(), - Err(err) => format!("Error calling StructureType.toString: {}", err), - } - } -} - -impl<'mc> Into> for StructureType<'mc> { - fn into(self) -> crate::Keyed<'mc> { - crate::Keyed::from_raw(&self.jni_ref(), self.1) - .expect("Error converting StructureType into crate::Keyed") - } -} -#[repr(C)] -pub struct Location<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Location<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Location<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Location from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Location")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Location object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Location<'mc> { - /// Constructs a new Location with the given coordinates and direction - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - world: impl Into>, - x: f64, - y: f64, - z: f64, - yaw: std::option::Option, - pitch: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/World;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); - args.push(val_1); - sig += "D"; - let val_2 = jni::objects::JValueGen::Double(x); - args.push(val_2); - sig += "D"; - let val_3 = jni::objects::JValueGen::Double(y); - args.push(val_3); - sig += "D"; - let val_4 = jni::objects::JValueGen::Double(z); - args.push(val_4); - if let Some(a) = yaw { - sig += "F"; - let val_5 = jni::objects::JValueGen::Float(a); - args.push(val_5); - } - if let Some(a) = pitch { - sig += "F"; - let val_6 = jni::objects::JValueGen::Float(a); - args.push(val_6); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/Location"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::Location::from_raw(&jni, res) - } - /// Sets the world that this location resides in - pub fn set_world( + /// Get block type for block at corresponding coordinate in the chunk + pub fn get_block_type( &self, - world: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/World;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); + x: i32, + y: i32, + z: i32, + ) -> Result, Box> { + let sig = String::from("(III)Lorg/bukkit/Material;"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(y); + let val_3 = jni::objects::JValueGen::Int(z); let res = self.jni_ref().call_method( &self.jni_object(), - "setWorld", + "getBlockType", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks if world in this location is present and loaded. - pub fn is_world_loaded(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isWorldLoaded", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the world that this location resides in - pub fn world(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::World::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Gets the chunk at the represented location - pub fn chunk(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Chunk;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getChunk", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Chunk::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the block at the represented location - pub fn block(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBlock", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { + crate::Material::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the x-coordinate of this location - pub fn set_x(&self, x: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(x); + /// Get block data for block at corresponding coordinate in the chunk + pub fn get_block_data( + &self, + x: i32, + y: i32, + z: i32, + ) -> Result, Box> { + let sig = String::from("(III)Lorg/bukkit/block/data/BlockData;"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(y); + let val_3 = jni::objects::JValueGen::Int(z); let res = self.jni_ref().call_method( &self.jni_object(), - "setX", + "getBlockData", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the x-coordinate of this location - pub fn x(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the floored value of the X component, indicating the block that - /// this location is contained with. - pub fn block_x(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBlockX", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::block::data::BlockData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Sets the y-coordinate of this location - pub fn set_y(&self, y: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(y); + #[deprecated] + /// Get block data for block at corresponding coordinate in the chunk + pub fn get_data(&self, x: i32, y: i32, z: i32) -> Result> { + let sig = String::from("(III)I"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(y); + let val_3 = jni::objects::JValueGen::Int(z); let res = self.jni_ref().call_method( &self.jni_object(), - "setY", + "getData", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the y-coordinate of this location - pub fn y(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the floored value of the Y component, indicating the block that - /// this location is contained with. - pub fn block_y(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBlockY", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the z-coordinate of this location - pub fn set_z(&self, z: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(z); + /// Get sky light level for block at corresponding coordinate in the chunk + pub fn get_block_sky_light( + &self, + x: i32, + y: i32, + z: i32, + ) -> Result> { + let sig = String::from("(III)I"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(y); + let val_3 = jni::objects::JValueGen::Int(z); let res = self.jni_ref().call_method( &self.jni_object(), - "setZ", + "getBlockSkyLight", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the z-coordinate of this location - pub fn z(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the floored value of the Z component, indicating the block that - /// this location is contained with. - pub fn block_z(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBlockZ", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.i()?) } - /// Sets the yaw of this location, measured in degrees. - ///
      - ///
    • A yaw of 0 or 360 represents the positive z direction. - ///
    • A yaw of 180 represents the negative z direction. - ///
    • A yaw of 90 represents the negative x direction. - ///
    • A yaw of 270 represents the positive x direction. - ///
    - /// Increasing yaw values are the equivalent of turning to your - /// right-facing, increasing the scale of the next respective axis, and - /// decreasing the scale of the previous axis. - pub fn set_yaw(&self, yaw: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(yaw); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setYaw", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the yaw of this location, measured in degrees. - ///
      - ///
    • A yaw of 0 or 360 represents the positive z direction. - ///
    • A yaw of 180 represents the negative z direction. - ///
    • A yaw of 90 represents the negative x direction. - ///
    • A yaw of 270 represents the positive x direction. - ///
    - /// Increasing yaw values are the equivalent of turning to your - /// right-facing, increasing the scale of the next respective axis, and - /// decreasing the scale of the previous axis. - pub fn yaw(&self) -> Result> { - let sig = String::from("()F"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getYaw", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Sets the pitch of this location, measured in degrees. - ///
      - ///
    • A pitch of 0 represents level forward facing. - ///
    • A pitch of 90 represents downward facing, or negative y - /// direction. - ///
    • A pitch of -90 represents upward facing, or positive y direction. - ///
    - /// Increasing pitch values the equivalent of looking down. - pub fn set_pitch(&self, pitch: f32) -> Result<(), Box> { - let sig = String::from("(F)V"); - let val_1 = jni::objects::JValueGen::Float(pitch); + /// Get light level emitted by block at corresponding coordinate in the + /// chunk + pub fn get_block_emitted_light( + &self, + x: i32, + y: i32, + z: i32, + ) -> Result> { + let sig = String::from("(III)I"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(y); + let val_3 = jni::objects::JValueGen::Int(z); let res = self.jni_ref().call_method( &self.jni_object(), - "setPitch", + "getBlockEmittedLight", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the pitch of this location, measured in degrees. - ///
      - ///
    • A pitch of 0 represents level forward facing. - ///
    • A pitch of 90 represents downward facing, or negative y - /// direction. - ///
    • A pitch of -90 represents upward facing, or positive y direction. - ///
    - /// Increasing pitch values the equivalent of looking down. - pub fn pitch(&self) -> Result> { - let sig = String::from("()F"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPitch", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) - } - /// Gets a unit-vector pointing in the direction that this Location is - /// facing. - pub fn direction(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Sets the {@link #getYaw() yaw} and {@link #getPitch() pitch} to point - /// in the direction of the vector. - pub fn set_direction( - &self, - vector: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)Lorg/bukkit/Location;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(vector.into().jni_object().clone()) - }); + /// Gets the highest non-air coordinate at the given coordinates + pub fn get_highest_block_yat(&self, x: i32, z: i32) -> Result> { + let sig = String::from("(II)I"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(z); let res = self.jni_ref().call_method( &self.jni_object(), - "setDirection", + "getHighestBlockYAt", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Adds the location by another. Not world-aware. - pub fn add( + /// Get biome at given coordinates + pub fn get_biome( &self, - x: f64, - y: std::option::Option, - z: std::option::Option, - ) -> Result, Box> { + x: i32, + y: i32, + z: std::option::Option, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(x); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); args.push(val_1); - if let Some(a) = y { - sig += "D"; - let val_2 = jni::objects::JValueGen::Double(a); - args.push(val_2); - } + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(y); + args.push(val_2); if let Some(a) = z { - sig += "D"; - let val_3 = jni::objects::JValueGen::Double(a); + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); args.push(val_3); } - sig += ")Lorg/bukkit/Location;"; + sig += ")Lorg/bukkit/block/Biome;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "add", sig.as_str(), args); + .call_method(&self.jni_object(), "getBiome", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { + crate::block::Biome::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Subtracts the location by another. Not world-aware and - /// orientation independent. - pub fn subtract( + /// Get raw biome temperature at given coordinates + pub fn get_raw_biome_temperature( &self, - x: f64, - y: std::option::Option, - z: std::option::Option, - ) -> Result, Box> { + x: i32, + y: i32, + z: std::option::Option, + ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(x); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); args.push(val_1); - if let Some(a) = y { - sig += "D"; - let val_2 = jni::objects::JValueGen::Double(a); - args.push(val_2); - } + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(y); + args.push(val_2); if let Some(a) = z { - sig += "D"; - let val_3 = jni::objects::JValueGen::Double(a); + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); args.push(val_3); } - sig += ")Lorg/bukkit/Location;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "subtract", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the magnitude of the location, defined as sqrt(x^2+y^2+z^2). The - /// value of this method is not cached and uses a costly square-root - /// function, so do not repeatedly call this method to get the location's - /// magnitude. NaN will be returned if the inner result of the sqrt() - /// function overflows, which will be caused if the length is too long. Not - /// world-aware and orientation independent. - pub fn length(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "length", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the magnitude of the location squared. Not world-aware and - /// orientation independent. - pub fn length_squared(&self) -> Result> { - let sig = String::from("()D"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "lengthSquared", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Get the distance between this location and another. The value of this - /// method is not cached and uses a costly square-root function, so do not - /// repeatedly call this method to get the location's magnitude. NaN will - /// be returned if the inner result of the sqrt() function overflows, which - /// will be caused if the distance is too long. - pub fn distance( - &self, - o: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/Location;)D"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(o.into().jni_object().clone()) - }); + sig += ")D"; let res = self.jni_ref().call_method( &self.jni_object(), - "distance", + "getRawBiomeTemperature", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + args, ); let res = self.jni_ref().translate_error(res)?; Ok(res.d()?) } - /// Get the squared distance between this location and another. - pub fn distance_squared( - &self, - o: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/Location;)D"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(o.into().jni_object().clone()) - }); + /// Get world full time when chunk snapshot was captured + pub fn capture_full_time(&self) -> Result> { + let sig = String::from("()J"); let res = self.jni_ref().call_method( &self.jni_object(), - "distanceSquared", + "getCaptureFullTime", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.j()?) } - /// Performs scalar multiplication, multiplying all components with a - /// scalar. Not world-aware. - pub fn multiply(&self, m: f64) -> Result, Box> { - let sig = String::from("(D)Lorg/bukkit/Location;"); - let val_1 = jni::objects::JValueGen::Double(m); + /// Test if section is empty + pub fn is_section_empty(&self, sy: i32) -> Result> { + let sig = String::from("(I)Z"); + let val_1 = jni::objects::JValueGen::Int(sy); let res = self.jni_ref().call_method( &self.jni_object(), - "multiply", + "isSectionEmpty", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Zero this location's components. Not world-aware. - pub fn zero(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); + /// Tests if this chunk contains the specified biome. + pub fn contains( + &self, + biome: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/block/Biome;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(biome.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "zero", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "contains", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - pub fn equals( - &self, + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct SoundGroup<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for SoundGroup<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for SoundGroup<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, - ) -> Result> { - let sig = String::from("(Ljava/lang/Object;)Z"); - let val_1 = jni::objects::JValueGen::Object(obj); - let res = self.jni_ref().call_method( - &self.jni_object(), - "equals", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate SoundGroup from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/SoundGroup")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a SoundGroup object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } +} - pub fn hash_code(&self) -> Result> { - let sig = String::from("()I"); +impl<'mc> SoundGroup<'mc> { + /// Get the volume these sounds are played at. + /// Note that this volume does not always represent the actual volume + /// received by the client. + pub fn volume(&self) -> Result> { + let sig = String::from("()F"); let res = self .jni_ref() - .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getVolume", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.f()?) } - - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Gets the pitch these sounds are played at. + /// Note that this pitch does not always represent the actual pitch received + /// by the client. + pub fn pitch(&self) -> Result> { + let sig = String::from("()F"); let res = self .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPitch", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.f()?) } - /// Constructs a new {@link Vector} based on this Location - pub fn to_vector(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "toVector", sig.as_str(), vec![]); + /// Gets the corresponding breaking sound for this group. + pub fn break_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getBreakSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + /// Gets the corresponding step sound for this group. + pub fn step_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getStepSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { + crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Check if each component of this Location is finite. - pub fn check_finite(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Gets the corresponding place sound for this group. + pub fn place_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "checkFinite", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) + .call_method(&self.jni_object(), "getPlaceSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Safely converts a double (location coordinate) to an int (block - /// coordinate) - pub fn loc_to_block( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - loc: f64, - ) -> Result> { - let sig = String::from("(D)I"); - let val_1 = jni::objects::JValueGen::Double(loc); - let cls = jni.find_class("org/bukkit/Location"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "locToBlock", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - Ok(res.i()?) + /// Gets the corresponding hit sound for this group. + pub fn hit_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getHitSound", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Sound::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - - pub fn serialize( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); + /// Gets the corresponding fall sound for this group. + pub fn fall_sound(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Sound;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getFallSound", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + crate::Sound::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Required method for deserialization - pub fn deserialize( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_args: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Ljava/util/Map;)Lorg/bukkit/Location;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_args.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/Location"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "deserialize", + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct Translatable<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Translatable<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Translatable<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Translatable from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/Translatable")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Translatable object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Translatable<'mc> { + /// Get the translation key, suitable for use in a translation component. + pub fn translation_key(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTranslationKey", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::Location::from_raw(&jni, obj) + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct JukeboxSong<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for JukeboxSong<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for JukeboxSong<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate JukeboxSong from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/JukeboxSong")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a JukeboxSong object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } - /// Normalizes the given yaw angle to a value between +/-180 - /// degrees. - pub fn normalize_yaw( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - yaw: f32, - ) -> Result> { - let sig = String::from("(F)F"); - let val_1 = jni::objects::JValueGen::Float(yaw); - let cls = jni.find_class("org/bukkit/Location"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "normalizeYaw", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - Ok(res.f()?) +} + +impl<'mc> JukeboxSong<'mc> { + /// Return the namespaced identifier for this object. + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Normalizes the given pitch angle to a value between +/-90 - /// degrees. - pub fn normalize_pitch( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - pitch: f32, - ) -> Result> { - let sig = String::from("(F)F"); - let val_1 = jni::objects::JValueGen::Float(pitch); - let cls = jni.find_class("org/bukkit/Location"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "normalizePitch", + /// Get the translation key, suitable for use in a translation component. + pub fn translation_key(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTranslationKey", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - let res = jni.translate_error(res)?; - Ok(res.f()?) + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -22597,42 +77264,58 @@ impl<'mc> Location<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } - -impl<'mc> std::string::ToString for Location<'mc> { - fn to_string(&self) -> String { - match &self.internal_to_string() { - Ok(a) => a.clone(), - Err(err) => format!("Error calling Location.toString: {}", err), - } +impl<'mc> Into> for JukeboxSong<'mc> { + fn into(self) -> crate::Keyed<'mc> { + crate::Keyed::from_raw(&self.jni_ref(), self.1) + .expect("Error converting JukeboxSong into crate::Keyed") } } - -impl<'mc> Into> - for Location<'mc> -{ - fn into(self) -> crate::configuration::serialization::ConfigurationSerializable<'mc> { - crate::configuration::serialization::ConfigurationSerializable::from_raw(&self.jni_ref(), self.1).expect("Error converting Location into crate::configuration::serialization::ConfigurationSerializable") +impl<'mc> Into> for JukeboxSong<'mc> { + fn into(self) -> crate::Translatable<'mc> { + crate::Translatable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting JukeboxSong into crate::Translatable") } } -pub enum Fluid<'mc> {} -impl<'mc> std::fmt::Display for Fluid<'mc> { +pub enum ExplosionResult<'mc> { + Keep { inner: ExplosionResultStruct<'mc> }, + Destroy { inner: ExplosionResultStruct<'mc> }, + DestroyWithDecay { inner: ExplosionResultStruct<'mc> }, + TriggerBlock { inner: ExplosionResultStruct<'mc> }, +} +impl<'mc> std::fmt::Display for ExplosionResult<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + ExplosionResult::Keep { .. } => f.write_str("KEEP"), + ExplosionResult::Destroy { .. } => f.write_str("DESTROY"), + ExplosionResult::DestroyWithDecay { .. } => f.write_str("DESTROY_WITH_DECAY"), + ExplosionResult::TriggerBlock { .. } => f.write_str("TRIGGER_BLOCK"), + } + } +} +impl<'mc> std::ops::Deref for ExplosionResult<'mc> { + type Target = ExplosionResultStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + ExplosionResult::Keep { inner } => inner, + ExplosionResult::Destroy { inner } => inner, + ExplosionResult::DestroyWithDecay { inner } => inner, + ExplosionResult::TriggerBlock { inner } => inner, + } } } -impl<'mc> Fluid<'mc> { +impl<'mc> ExplosionResult<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/Fluid"); + let cls = env.find_class("org/bukkit/ExplosionResult"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/Fluid;", + "(Ljava/lang/String;)Lorg/bukkit/ExplosionResult;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -22644,37 +77327,66 @@ impl<'mc> Fluid<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "KEEP" => Ok(ExplosionResult::Keep { + inner: ExplosionResultStruct::from_raw(env, obj)?, + }), + "DESTROY" => Ok(ExplosionResult::Destroy { + inner: ExplosionResultStruct::from_raw(env, obj)?, + }), + "DESTROY_WITH_DECAY" => Ok(ExplosionResult::DestroyWithDecay { + inner: ExplosionResultStruct::from_raw(env, obj)?, + }), + "TRIGGER_BLOCK" => Ok(ExplosionResult::TriggerBlock { + inner: ExplosionResultStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct FluidStruct<'mc>( +pub struct ExplosionResultStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Fluid<'mc> { +impl<'mc> JNIRaw<'mc> for ExplosionResult<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Keep { inner } => inner.0.clone(), + Self::Destroy { inner } => inner.0.clone(), + Self::DestroyWithDecay { inner } => inner.0.clone(), + Self::TriggerBlock { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Keep { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Destroy { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DestroyWithDecay { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TriggerBlock { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } -impl<'mc> JNIInstantiatable<'mc> for Fluid<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ExplosionResult<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Fluid from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate ExplosionResult from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Fluid")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/ExplosionResult")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Fluid object, got {}", + "Invalid argument passed. Expected a ExplosionResult object, got {}", name ) .into()) @@ -22686,13 +77398,25 @@ impl<'mc> JNIInstantiatable<'mc> for Fluid<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "KEEP" => Ok(ExplosionResult::Keep { + inner: ExplosionResultStruct::from_raw(env, obj)?, + }), + "DESTROY" => Ok(ExplosionResult::Destroy { + inner: ExplosionResultStruct::from_raw(env, obj)?, + }), + "DESTROY_WITH_DECAY" => Ok(ExplosionResult::DestroyWithDecay { + inner: ExplosionResultStruct::from_raw(env, obj)?, + }), + "TRIGGER_BLOCK" => Ok(ExplosionResult::TriggerBlock { + inner: ExplosionResultStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for FluidStruct<'mc> { +impl<'mc> JNIRaw<'mc> for ExplosionResultStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -22700,18 +77424,21 @@ impl<'mc> JNIRaw<'mc> for FluidStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for FluidStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ExplosionResultStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate FluidStruct from null object.").into()); + return Err(eyre::eyre!( + "Tried to instantiate ExplosionResultStruct from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/Fluid")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/ExplosionResult")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a FluidStruct object, got {}", + "Invalid argument passed. Expected a ExplosionResultStruct object, got {}", name ) .into()) @@ -22721,28 +77448,17 @@ impl<'mc> JNIInstantiatable<'mc> for FluidStruct<'mc> { } } -impl<'mc> FluidStruct<'mc> { +impl<'mc> ExplosionResultStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Fluid;"); - let cls = jni.find_class("org/bukkit/Fluid"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/ExplosionResult;"); + let cls = jni.find_class("org/bukkit/ExplosionResult"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::Fluid::from_raw(&jni, obj) - } - - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + crate::ExplosionResult::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -22750,25 +77466,46 @@ impl<'mc> FluidStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum TreeType<'mc> {} -impl<'mc> std::fmt::Display for TreeType<'mc> { +pub enum Fluid<'mc> { + Water { inner: FluidStruct<'mc> }, + FlowingWater { inner: FluidStruct<'mc> }, + Lava { inner: FluidStruct<'mc> }, + FlowingLava { inner: FluidStruct<'mc> }, +} +impl<'mc> std::fmt::Display for Fluid<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + Fluid::Water { .. } => f.write_str("WATER"), + Fluid::FlowingWater { .. } => f.write_str("FLOWING_WATER"), + Fluid::Lava { .. } => f.write_str("LAVA"), + Fluid::FlowingLava { .. } => f.write_str("FLOWING_LAVA"), + } + } +} +impl<'mc> std::ops::Deref for Fluid<'mc> { + type Target = FluidStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + Fluid::Water { inner } => inner, + Fluid::FlowingWater { inner } => inner, + Fluid::Lava { inner } => inner, + Fluid::FlowingLava { inner } => inner, + } } } -impl<'mc> TreeType<'mc> { +impl<'mc> Fluid<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/TreeType"); + let cls = env.find_class("org/bukkit/Fluid"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/TreeType;", + "(Ljava/lang/String;)Lorg/bukkit/Fluid;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -22780,37 +77517,64 @@ impl<'mc> TreeType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "WATER" => Ok(Fluid::Water { + inner: FluidStruct::from_raw(env, obj)?, + }), + "FLOWING_WATER" => Ok(Fluid::FlowingWater { + inner: FluidStruct::from_raw(env, obj)?, + }), + "LAVA" => Ok(Fluid::Lava { + inner: FluidStruct::from_raw(env, obj)?, + }), + "FLOWING_LAVA" => Ok(Fluid::FlowingLava { + inner: FluidStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct TreeTypeStruct<'mc>( +pub struct FluidStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for TreeType<'mc> { +impl<'mc> JNIRaw<'mc> for Fluid<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Water { inner } => inner.0.clone(), + Self::FlowingWater { inner } => inner.0.clone(), + Self::Lava { inner } => inner.0.clone(), + Self::FlowingLava { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Water { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::FlowingWater { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Lava { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::FlowingLava { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } -impl<'mc> JNIInstantiatable<'mc> for TreeType<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Fluid<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate TreeType from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Fluid from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/TreeType")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/Fluid")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a TreeType object, got {}", + "Invalid argument passed. Expected a Fluid object, got {}", name ) .into()) @@ -22822,13 +77586,25 @@ impl<'mc> JNIInstantiatable<'mc> for TreeType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "WATER" => Ok(Fluid::Water { + inner: FluidStruct::from_raw(env, obj)?, + }), + "FLOWING_WATER" => Ok(Fluid::FlowingWater { + inner: FluidStruct::from_raw(env, obj)?, + }), + "LAVA" => Ok(Fluid::Lava { + inner: FluidStruct::from_raw(env, obj)?, + }), + "FLOWING_LAVA" => Ok(Fluid::FlowingLava { + inner: FluidStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for TreeTypeStruct<'mc> { +impl<'mc> JNIRaw<'mc> for FluidStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -22836,20 +77612,18 @@ impl<'mc> JNIRaw<'mc> for TreeTypeStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for TreeTypeStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for FluidStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate TreeTypeStruct from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate FluidStruct from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/TreeType")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/Fluid")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a TreeTypeStruct object, got {}", + "Invalid argument passed. Expected a FluidStruct object, got {}", name ) .into()) @@ -22859,17 +77633,28 @@ impl<'mc> JNIInstantiatable<'mc> for TreeTypeStruct<'mc> { } } -impl<'mc> TreeTypeStruct<'mc> { +impl<'mc> FluidStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/TreeType;"); - let cls = jni.find_class("org/bukkit/TreeType"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Fluid;"); + let cls = jni.find_class("org/bukkit/Fluid"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::TreeType::from_raw(&jni, obj) + crate::Fluid::from_raw(&jni, obj) + } + + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -22877,25 +77662,106 @@ impl<'mc> TreeTypeStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum DyeColor<'mc> {} -impl<'mc> std::fmt::Display for DyeColor<'mc> { +pub enum TreeType<'mc> { + Tree { inner: TreeTypeStruct<'mc> }, + BigTree { inner: TreeTypeStruct<'mc> }, + Redwood { inner: TreeTypeStruct<'mc> }, + TallRedwood { inner: TreeTypeStruct<'mc> }, + Birch { inner: TreeTypeStruct<'mc> }, + Jungle { inner: TreeTypeStruct<'mc> }, + SmallJungle { inner: TreeTypeStruct<'mc> }, + CocoaTree { inner: TreeTypeStruct<'mc> }, + JungleBush { inner: TreeTypeStruct<'mc> }, + RedMushroom { inner: TreeTypeStruct<'mc> }, + BrownMushroom { inner: TreeTypeStruct<'mc> }, + Swamp { inner: TreeTypeStruct<'mc> }, + Acacia { inner: TreeTypeStruct<'mc> }, + DarkOak { inner: TreeTypeStruct<'mc> }, + MegaRedwood { inner: TreeTypeStruct<'mc> }, + MegaPine { inner: TreeTypeStruct<'mc> }, + TallBirch { inner: TreeTypeStruct<'mc> }, + ChorusPlant { inner: TreeTypeStruct<'mc> }, + CrimsonFungus { inner: TreeTypeStruct<'mc> }, + WarpedFungus { inner: TreeTypeStruct<'mc> }, + Azalea { inner: TreeTypeStruct<'mc> }, + Mangrove { inner: TreeTypeStruct<'mc> }, + TallMangrove { inner: TreeTypeStruct<'mc> }, + Cherry { inner: TreeTypeStruct<'mc> }, +} +impl<'mc> std::fmt::Display for TreeType<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + TreeType::Tree { .. } => f.write_str("TREE"), + TreeType::BigTree { .. } => f.write_str("BIG_TREE"), + TreeType::Redwood { .. } => f.write_str("REDWOOD"), + TreeType::TallRedwood { .. } => f.write_str("TALL_REDWOOD"), + TreeType::Birch { .. } => f.write_str("BIRCH"), + TreeType::Jungle { .. } => f.write_str("JUNGLE"), + TreeType::SmallJungle { .. } => f.write_str("SMALL_JUNGLE"), + TreeType::CocoaTree { .. } => f.write_str("COCOA_TREE"), + TreeType::JungleBush { .. } => f.write_str("JUNGLE_BUSH"), + TreeType::RedMushroom { .. } => f.write_str("RED_MUSHROOM"), + TreeType::BrownMushroom { .. } => f.write_str("BROWN_MUSHROOM"), + TreeType::Swamp { .. } => f.write_str("SWAMP"), + TreeType::Acacia { .. } => f.write_str("ACACIA"), + TreeType::DarkOak { .. } => f.write_str("DARK_OAK"), + TreeType::MegaRedwood { .. } => f.write_str("MEGA_REDWOOD"), + TreeType::MegaPine { .. } => f.write_str("MEGA_PINE"), + TreeType::TallBirch { .. } => f.write_str("TALL_BIRCH"), + TreeType::ChorusPlant { .. } => f.write_str("CHORUS_PLANT"), + TreeType::CrimsonFungus { .. } => f.write_str("CRIMSON_FUNGUS"), + TreeType::WarpedFungus { .. } => f.write_str("WARPED_FUNGUS"), + TreeType::Azalea { .. } => f.write_str("AZALEA"), + TreeType::Mangrove { .. } => f.write_str("MANGROVE"), + TreeType::TallMangrove { .. } => f.write_str("TALL_MANGROVE"), + TreeType::Cherry { .. } => f.write_str("CHERRY"), + } + } +} +impl<'mc> std::ops::Deref for TreeType<'mc> { + type Target = TreeTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + TreeType::Tree { inner } => inner, + TreeType::BigTree { inner } => inner, + TreeType::Redwood { inner } => inner, + TreeType::TallRedwood { inner } => inner, + TreeType::Birch { inner } => inner, + TreeType::Jungle { inner } => inner, + TreeType::SmallJungle { inner } => inner, + TreeType::CocoaTree { inner } => inner, + TreeType::JungleBush { inner } => inner, + TreeType::RedMushroom { inner } => inner, + TreeType::BrownMushroom { inner } => inner, + TreeType::Swamp { inner } => inner, + TreeType::Acacia { inner } => inner, + TreeType::DarkOak { inner } => inner, + TreeType::MegaRedwood { inner } => inner, + TreeType::MegaPine { inner } => inner, + TreeType::TallBirch { inner } => inner, + TreeType::ChorusPlant { inner } => inner, + TreeType::CrimsonFungus { inner } => inner, + TreeType::WarpedFungus { inner } => inner, + TreeType::Azalea { inner } => inner, + TreeType::Mangrove { inner } => inner, + TreeType::TallMangrove { inner } => inner, + TreeType::Cherry { inner } => inner, + } } } -impl<'mc> DyeColor<'mc> { +impl<'mc> TreeType<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/DyeColor"); + let cls = env.find_class("org/bukkit/TreeType"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/DyeColor;", + "(Ljava/lang/String;)Lorg/bukkit/TreeType;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -22907,37 +77773,184 @@ impl<'mc> DyeColor<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "TREE" => Ok(TreeType::Tree { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "BIG_TREE" => Ok(TreeType::BigTree { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "REDWOOD" => Ok(TreeType::Redwood { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "TALL_REDWOOD" => Ok(TreeType::TallRedwood { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "BIRCH" => Ok(TreeType::Birch { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "JUNGLE" => Ok(TreeType::Jungle { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "SMALL_JUNGLE" => Ok(TreeType::SmallJungle { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "COCOA_TREE" => Ok(TreeType::CocoaTree { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "JUNGLE_BUSH" => Ok(TreeType::JungleBush { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "RED_MUSHROOM" => Ok(TreeType::RedMushroom { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "BROWN_MUSHROOM" => Ok(TreeType::BrownMushroom { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "SWAMP" => Ok(TreeType::Swamp { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "ACACIA" => Ok(TreeType::Acacia { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "DARK_OAK" => Ok(TreeType::DarkOak { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "MEGA_REDWOOD" => Ok(TreeType::MegaRedwood { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "MEGA_PINE" => Ok(TreeType::MegaPine { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "TALL_BIRCH" => Ok(TreeType::TallBirch { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "CHORUS_PLANT" => Ok(TreeType::ChorusPlant { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "CRIMSON_FUNGUS" => Ok(TreeType::CrimsonFungus { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "WARPED_FUNGUS" => Ok(TreeType::WarpedFungus { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "AZALEA" => Ok(TreeType::Azalea { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "MANGROVE" => Ok(TreeType::Mangrove { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "TALL_MANGROVE" => Ok(TreeType::TallMangrove { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "CHERRY" => Ok(TreeType::Cherry { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct DyeColorStruct<'mc>( +pub struct TreeTypeStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for DyeColor<'mc> { +impl<'mc> JNIRaw<'mc> for TreeType<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Tree { inner } => inner.0.clone(), + Self::BigTree { inner } => inner.0.clone(), + Self::Redwood { inner } => inner.0.clone(), + Self::TallRedwood { inner } => inner.0.clone(), + Self::Birch { inner } => inner.0.clone(), + Self::Jungle { inner } => inner.0.clone(), + Self::SmallJungle { inner } => inner.0.clone(), + Self::CocoaTree { inner } => inner.0.clone(), + Self::JungleBush { inner } => inner.0.clone(), + Self::RedMushroom { inner } => inner.0.clone(), + Self::BrownMushroom { inner } => inner.0.clone(), + Self::Swamp { inner } => inner.0.clone(), + Self::Acacia { inner } => inner.0.clone(), + Self::DarkOak { inner } => inner.0.clone(), + Self::MegaRedwood { inner } => inner.0.clone(), + Self::MegaPine { inner } => inner.0.clone(), + Self::TallBirch { inner } => inner.0.clone(), + Self::ChorusPlant { inner } => inner.0.clone(), + Self::CrimsonFungus { inner } => inner.0.clone(), + Self::WarpedFungus { inner } => inner.0.clone(), + Self::Azalea { inner } => inner.0.clone(), + Self::Mangrove { inner } => inner.0.clone(), + Self::TallMangrove { inner } => inner.0.clone(), + Self::Cherry { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Tree { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BigTree { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Redwood { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::TallRedwood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Birch { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Jungle { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SmallJungle { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CocoaTree { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::JungleBush { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RedMushroom { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BrownMushroom { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Swamp { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Acacia { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::DarkOak { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::MegaRedwood { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MegaPine { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::TallBirch { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ChorusPlant { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CrimsonFungus { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WarpedFungus { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Azalea { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Mangrove { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::TallMangrove { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Cherry { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for DyeColor<'mc> { +impl<'mc> JNIInstantiatable<'mc> for TreeType<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate DyeColor from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate TreeType from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/DyeColor")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/TreeType")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a DyeColor object, got {}", + "Invalid argument passed. Expected a TreeType object, got {}", name ) .into()) @@ -22949,13 +77962,85 @@ impl<'mc> JNIInstantiatable<'mc> for DyeColor<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "TREE" => Ok(TreeType::Tree { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "BIG_TREE" => Ok(TreeType::BigTree { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "REDWOOD" => Ok(TreeType::Redwood { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "TALL_REDWOOD" => Ok(TreeType::TallRedwood { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "BIRCH" => Ok(TreeType::Birch { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "JUNGLE" => Ok(TreeType::Jungle { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "SMALL_JUNGLE" => Ok(TreeType::SmallJungle { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "COCOA_TREE" => Ok(TreeType::CocoaTree { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "JUNGLE_BUSH" => Ok(TreeType::JungleBush { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "RED_MUSHROOM" => Ok(TreeType::RedMushroom { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "BROWN_MUSHROOM" => Ok(TreeType::BrownMushroom { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "SWAMP" => Ok(TreeType::Swamp { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "ACACIA" => Ok(TreeType::Acacia { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "DARK_OAK" => Ok(TreeType::DarkOak { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "MEGA_REDWOOD" => Ok(TreeType::MegaRedwood { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "MEGA_PINE" => Ok(TreeType::MegaPine { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "TALL_BIRCH" => Ok(TreeType::TallBirch { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "CHORUS_PLANT" => Ok(TreeType::ChorusPlant { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "CRIMSON_FUNGUS" => Ok(TreeType::CrimsonFungus { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "WARPED_FUNGUS" => Ok(TreeType::WarpedFungus { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "AZALEA" => Ok(TreeType::Azalea { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "MANGROVE" => Ok(TreeType::Mangrove { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "TALL_MANGROVE" => Ok(TreeType::TallMangrove { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), + "CHERRY" => Ok(TreeType::Cherry { + inner: TreeTypeStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for DyeColorStruct<'mc> { +impl<'mc> JNIRaw<'mc> for TreeTypeStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -22963,20 +78048,20 @@ impl<'mc> JNIRaw<'mc> for DyeColorStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for DyeColorStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for TreeTypeStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate DyeColorStruct from null object.").into(), + eyre::eyre!("Tried to instantiate TreeTypeStruct from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/DyeColor")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/TreeType")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a DyeColorStruct object, got {}", + "Invalid argument passed. Expected a TreeTypeStruct object, got {}", name ) .into()) @@ -22986,178 +78071,17 @@ impl<'mc> JNIInstantiatable<'mc> for DyeColorStruct<'mc> { } } -impl<'mc> DyeColorStruct<'mc> { +impl<'mc> TreeTypeStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/DyeColor;"); - let cls = jni.find_class("org/bukkit/DyeColor"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/TreeType;"); + let cls = jni.find_class("org/bukkit/TreeType"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::DyeColor::from_raw(&jni, obj) - } - #[deprecated] - /// Gets the associated wool data value representing this color. - pub fn wool_data(&self) -> Result> { - let sig = String::from("()B"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getWoolData", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) - } - #[deprecated] - /// Gets the associated dye data value representing this color. - pub fn dye_data(&self) -> Result> { - let sig = String::from("()B"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDyeData", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) - } - /// Gets the color that this dye represents. - pub fn color(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Color;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Color::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the firework color that this dye represents. - pub fn firework_color(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Color;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getFireworkColor", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::Color::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - #[deprecated] - /// Gets the DyeColor with the given wool data value. - pub fn get_by_wool_data( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - data: i8, - ) -> Result>, Box> { - let sig = String::from("(B)Lorg/bukkit/DyeColor;"); - let val_1 = jni::objects::JValueGen::Byte(data); - let cls = jni.find_class("org/bukkit/DyeColor"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getByWoolData", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::DyeColor::from_raw(&jni, obj)?)) - } - #[deprecated] - /// Gets the DyeColor with the given dye data value. - pub fn get_by_dye_data( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - data: i8, - ) -> Result>, Box> { - let sig = String::from("(B)Lorg/bukkit/DyeColor;"); - let val_1 = jni::objects::JValueGen::Byte(data); - let cls = jni.find_class("org/bukkit/DyeColor"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getByDyeData", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::DyeColor::from_raw(&jni, obj)?)) - } - /// Gets the DyeColor with the given color value. - pub fn get_by_color( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - color: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Color;)Lorg/bukkit/DyeColor;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/DyeColor"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getByColor", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::DyeColor::from_raw(&jni, obj)?)) - } - /// Gets the DyeColor with the given firework color value. - pub fn get_by_firework_color( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - color: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/Color;)Lorg/bukkit/DyeColor;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/DyeColor"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getByFireworkColor", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::DyeColor::from_raw(&jni, obj)?)) - } - #[deprecated] - /// Gets the DyeColor for the given name, possibly doing legacy transformations. - pub fn legacy_value_of( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - name: impl Into, - ) -> Result, Box> { - let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/DyeColor;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(name.into())?, - )); - let cls = jni.find_class("org/bukkit/DyeColor"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "legacyValueOf", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::DyeColor::from_raw(&jni, obj) + crate::TreeType::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -23165,10 +78089,34 @@ impl<'mc> DyeColorStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum FluidCollisionMode<'mc> {} +pub enum FluidCollisionMode<'mc> { + Never { + inner: FluidCollisionModeStruct<'mc>, + }, + SourceOnly { + inner: FluidCollisionModeStruct<'mc>, + }, + Always { + inner: FluidCollisionModeStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for FluidCollisionMode<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + FluidCollisionMode::Never { .. } => f.write_str("NEVER"), + FluidCollisionMode::SourceOnly { .. } => f.write_str("SOURCE_ONLY"), + FluidCollisionMode::Always { .. } => f.write_str("ALWAYS"), + } + } +} +impl<'mc> std::ops::Deref for FluidCollisionMode<'mc> { + type Target = FluidCollisionModeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + FluidCollisionMode::Never { inner } => inner, + FluidCollisionMode::SourceOnly { inner } => inner, + FluidCollisionMode::Always { inner } => inner, + } } } @@ -23195,6 +78143,16 @@ impl<'mc> FluidCollisionMode<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NEVER" => Ok(FluidCollisionMode::Never { + inner: FluidCollisionModeStruct::from_raw(env, obj)?, + }), + "SOURCE_ONLY" => Ok(FluidCollisionMode::SourceOnly { + inner: FluidCollisionModeStruct::from_raw(env, obj)?, + }), + "ALWAYS" => Ok(FluidCollisionMode::Always { + inner: FluidCollisionModeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -23208,10 +78166,20 @@ pub struct FluidCollisionModeStruct<'mc>( impl<'mc> JNIRaw<'mc> for FluidCollisionMode<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Never { inner } => inner.0.clone(), + Self::SourceOnly { inner } => inner.0.clone(), + Self::Always { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Never { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SourceOnly { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Always { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for FluidCollisionMode<'mc> { @@ -23239,6 +78207,15 @@ impl<'mc> JNIInstantiatable<'mc> for FluidCollisionMode<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NEVER" => Ok(FluidCollisionMode::Never { + inner: FluidCollisionModeStruct::from_raw(env, obj)?, + }), + "SOURCE_ONLY" => Ok(FluidCollisionMode::SourceOnly { + inner: FluidCollisionModeStruct::from_raw(env, obj)?, + }), + "ALWAYS" => Ok(FluidCollisionMode::Always { + inner: FluidCollisionModeStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -23295,233 +78272,6 @@ impl<'mc> FluidCollisionModeStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -#[repr(C)] -pub struct NamespacedKey<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for NamespacedKey<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for NamespacedKey<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate NamespacedKey from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/NamespacedKey")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a NamespacedKey object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> NamespacedKey<'mc> { - /// Create a key in the plugin's namespace. - /// - /// Namespaces may only contain lowercase alphanumeric characters, periods, - /// underscores, and hyphens. - /// - /// Keys may only contain lowercase alphanumeric characters, periods, - /// underscores, hyphens, and forward slashes. - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - plugin: impl Into>, - key: impl Into, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/plugin/Plugin;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(key.into())?, - )); - args.push(val_2); - sig += ")V"; - let cls = jni.find_class("org/bukkit/NamespacedKey"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::NamespacedKey::from_raw(&jni, res) - } - - pub fn namespace(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getNamespace", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - - pub fn key(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - - pub fn hash_code(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - - pub fn equals( - &self, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - let sig = String::from("(Ljava/lang/Object;)Z"); - let val_1 = jni::objects::JValueGen::Object(obj); - let res = self.jni_ref().call_method( - &self.jni_object(), - "equals", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - #[deprecated] - /// Return a new random key in the {@link #BUKKIT} namespace. - pub fn random_key( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); - let cls = jni.find_class("org/bukkit/NamespacedKey"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "randomKey", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::NamespacedKey::from_raw(&jni, obj) - } - /// Get a key in the Minecraft namespace. - pub fn minecraft( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - key: impl Into, - ) -> Result, Box> { - let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/NamespacedKey;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(key.into())?, - )); - let cls = jni.find_class("org/bukkit/NamespacedKey"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "minecraft", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::NamespacedKey::from_raw(&jni, obj) - } - /// Get a NamespacedKey from the supplied string with a default namespace if - /// a namespace is not defined. This is a utility method meant to fetch a - /// NamespacedKey from user input. Please note that casing does matter and - /// any instance of uppercase characters will be considered invalid. The - /// input contract is as follows: - ///
    -    /// fromString("foo", plugin) -{@literal >} "plugin:foo"
    -    /// fromString("foo:bar", plugin) -{@literal >} "foo:bar"
    -    /// fromString(":foo", null) -{@literal >} "minecraft:foo"
    -    /// fromString("foo", null) -{@literal >} "minecraft:foo"
    -    /// fromString("Foo", plugin) -{@literal >} null
    -    /// fromString(":Foo", plugin) -{@literal >} null
    -    /// fromString("foo:bar:bazz", plugin) -{@literal >} null
    -    /// fromString("", plugin) -{@literal >} null
    -    /// 
    - pub fn from_string( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - string: impl Into, - default_namespace: std::option::Option>>, - ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(string.into())?, - )); - args.push(val_1); - if let Some(a) = default_namespace { - sig += "Lorg/bukkit/plugin/Plugin;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/NamespacedKey;"; - let cls = jni.find_class("org/bukkit/NamespacedKey"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "fromString", sig.as_str(), args); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::NamespacedKey::from_raw(&jni, obj)?)) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} - -impl<'mc> std::string::ToString for NamespacedKey<'mc> { - fn to_string(&self) -> String { - match &self.internal_to_string() { - Ok(a) => a.clone(), - Err(err) => format!("Error calling NamespacedKey.toString: {}", err), - } - } -} - pub enum GameEvent<'mc> { BlockActivate { inner: GameEventStruct<'mc> }, BlockAttach { inner: GameEventStruct<'mc> }, @@ -23692,6 +78442,93 @@ impl<'mc> std::fmt::Display for GameEvent<'mc> { } } } +impl<'mc> std::ops::Deref for GameEvent<'mc> { + type Target = GameEventStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + GameEvent::BlockActivate { inner } => inner, + GameEvent::BlockAttach { inner } => inner, + GameEvent::BlockChange { inner } => inner, + GameEvent::BlockClose { inner } => inner, + GameEvent::BlockDeactivate { inner } => inner, + GameEvent::BlockDestroy { inner } => inner, + GameEvent::BlockDetach { inner } => inner, + GameEvent::BlockOpen { inner } => inner, + GameEvent::BlockPlace { inner } => inner, + GameEvent::BlockPress { inner } => inner, + GameEvent::BlockSwitch { inner } => inner, + GameEvent::BlockUnpress { inner } => inner, + GameEvent::BlockUnswitch { inner } => inner, + GameEvent::ContainerClose { inner } => inner, + GameEvent::ContainerOpen { inner } => inner, + GameEvent::DispenseFail { inner } => inner, + GameEvent::Drink { inner } => inner, + GameEvent::DrinkingFinish { inner } => inner, + GameEvent::Eat { inner } => inner, + GameEvent::ElytraFreeFall { inner } => inner, + GameEvent::ElytraGlide { inner } => inner, + GameEvent::EntityDamage { inner } => inner, + GameEvent::EntityDamaged { inner } => inner, + GameEvent::EntityDie { inner } => inner, + GameEvent::EntityDismount { inner } => inner, + GameEvent::EntityDying { inner } => inner, + GameEvent::EntityInteract { inner } => inner, + GameEvent::EntityMount { inner } => inner, + GameEvent::EntityKilled { inner } => inner, + GameEvent::EntityPlace { inner } => inner, + GameEvent::EntityAction { inner } => inner, + GameEvent::EntityRoar { inner } => inner, + GameEvent::EntityShake { inner } => inner, + GameEvent::Equip { inner } => inner, + GameEvent::Explode { inner } => inner, + GameEvent::Flap { inner } => inner, + GameEvent::FluidPickup { inner } => inner, + GameEvent::FluidPlace { inner } => inner, + GameEvent::HitGround { inner } => inner, + GameEvent::InstrumentPlay { inner } => inner, + GameEvent::ItemInteractFinish { inner } => inner, + GameEvent::ItemInteractStart { inner } => inner, + GameEvent::JukeboxPlay { inner } => inner, + GameEvent::JukeboxStopPlay { inner } => inner, + GameEvent::LightningStrike { inner } => inner, + GameEvent::MobInteract { inner } => inner, + GameEvent::NoteBlockPlay { inner } => inner, + GameEvent::PistonContract { inner } => inner, + GameEvent::PistonExtend { inner } => inner, + GameEvent::PrimeFuse { inner } => inner, + GameEvent::ProjectileLand { inner } => inner, + GameEvent::ProjectileShoot { inner } => inner, + GameEvent::RavagerRoar { inner } => inner, + GameEvent::RingBell { inner } => inner, + GameEvent::SculkSensorTendrilsClicking { inner } => inner, + GameEvent::Shear { inner } => inner, + GameEvent::Shriek { inner } => inner, + GameEvent::ShulkerClose { inner } => inner, + GameEvent::ShulkerOpen { inner } => inner, + GameEvent::Splash { inner } => inner, + GameEvent::Step { inner } => inner, + GameEvent::Swim { inner } => inner, + GameEvent::Teleport { inner } => inner, + GameEvent::Unequip { inner } => inner, + GameEvent::WolfShaking { inner } => inner, + GameEvent::Resonate1 { inner } => inner, + GameEvent::Resonate2 { inner } => inner, + GameEvent::Resonate3 { inner } => inner, + GameEvent::Resonate4 { inner } => inner, + GameEvent::Resonate5 { inner } => inner, + GameEvent::Resonate6 { inner } => inner, + GameEvent::Resonate7 { inner } => inner, + GameEvent::Resonate8 { inner } => inner, + GameEvent::Resonate9 { inner } => inner, + GameEvent::Resonate10 { inner } => inner, + GameEvent::Resonate11 { inner } => inner, + GameEvent::Resonate12 { inner } => inner, + GameEvent::Resonate13 { inner } => inner, + GameEvent::Resonate14 { inner } => inner, + GameEvent::Resonate15 { inner } => inner, + } + } +} impl<'mc> GameEvent<'mc> { pub fn value_of( @@ -24853,10 +79690,28 @@ impl<'mc> BanEntry<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum Axis<'mc> {} +pub enum Axis<'mc> { + X { inner: AxisStruct<'mc> }, + Y { inner: AxisStruct<'mc> }, + Z { inner: AxisStruct<'mc> }, +} impl<'mc> std::fmt::Display for Axis<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + Axis::X { .. } => f.write_str("X"), + Axis::Y { .. } => f.write_str("Y"), + Axis::Z { .. } => f.write_str("Z"), + } + } +} +impl<'mc> std::ops::Deref for Axis<'mc> { + type Target = AxisStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + Axis::X { inner } => inner, + Axis::Y { inner } => inner, + Axis::Z { inner } => inner, + } } } @@ -24883,6 +79738,16 @@ impl<'mc> Axis<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "X" => Ok(Axis::X { + inner: AxisStruct::from_raw(env, obj)?, + }), + "Y" => Ok(Axis::Y { + inner: AxisStruct::from_raw(env, obj)?, + }), + "Z" => Ok(Axis::Z { + inner: AxisStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -24896,10 +79761,18 @@ pub struct AxisStruct<'mc>( impl<'mc> JNIRaw<'mc> for Axis<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::X { inner } => inner.0.clone(), + Self::Y { inner } => inner.0.clone(), + Self::Z { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::X { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Y { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Z { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for Axis<'mc> { @@ -24925,6 +79798,15 @@ impl<'mc> JNIInstantiatable<'mc> for Axis<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "X" => Ok(Axis::X { + inner: AxisStruct::from_raw(env, obj)?, + }), + "Y" => Ok(Axis::Y { + inner: AxisStruct::from_raw(env, obj)?, + }), + "Z" => Ok(Axis::Z { + inner: AxisStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -25006,5 +79888,6 @@ pub mod profile; pub mod projectiles; pub mod scheduler; pub mod scoreboard; +pub mod spawner; pub mod structure; pub mod util; diff --git a/blackboxmc-rs-bukkit/src/loot/mod.rs b/blackboxmc-rs-bukkit/src/loot/mod.rs index 652f4b9..a430f26 100644 --- a/blackboxmc-rs-bukkit/src/loot/mod.rs +++ b/blackboxmc-rs-bukkit/src/loot/mod.rs @@ -2,10 +2,625 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; -pub enum LootTables<'mc> {} +pub enum LootTables<'mc> { + Empty { inner: LootTablesStruct<'mc> }, + AbandonedMineshaft { inner: LootTablesStruct<'mc> }, + BuriedTreasure { inner: LootTablesStruct<'mc> }, + DesertPyramid { inner: LootTablesStruct<'mc> }, + EndCityTreasure { inner: LootTablesStruct<'mc> }, + IglooChest { inner: LootTablesStruct<'mc> }, + JungleTemple { inner: LootTablesStruct<'mc> }, + JungleTempleDispenser { inner: LootTablesStruct<'mc> }, + NetherBridge { inner: LootTablesStruct<'mc> }, + PillagerOutpost { inner: LootTablesStruct<'mc> }, + BastionTreasure { inner: LootTablesStruct<'mc> }, + BastionOther { inner: LootTablesStruct<'mc> }, + BastionBridge { inner: LootTablesStruct<'mc> }, + BastionHoglinStable { inner: LootTablesStruct<'mc> }, + AncientCity { inner: LootTablesStruct<'mc> }, + AncientCityIceBox { inner: LootTablesStruct<'mc> }, + RuinedPortal { inner: LootTablesStruct<'mc> }, + TrialChambersReward { inner: LootTablesStruct<'mc> }, + TrialChambersRewardCommon { inner: LootTablesStruct<'mc> }, + TrialChambersRewardRare { inner: LootTablesStruct<'mc> }, + TrialChambersRewardUnique { inner: LootTablesStruct<'mc> }, + TrialChambersRewardOminous { inner: LootTablesStruct<'mc> }, + TrialChambersRewardOminousCommon { inner: LootTablesStruct<'mc> }, + TrialChambersRewardOminousRare { inner: LootTablesStruct<'mc> }, + TrialChambersRewardOminousUnique { inner: LootTablesStruct<'mc> }, + TrialChambersSupply { inner: LootTablesStruct<'mc> }, + TrialChambersCorridor { inner: LootTablesStruct<'mc> }, + TrialChambersIntersection { inner: LootTablesStruct<'mc> }, + TrialChambersIntersectionBarrel { inner: LootTablesStruct<'mc> }, + TrialChambersEntrance { inner: LootTablesStruct<'mc> }, + TrialChambersCorridorDispenser { inner: LootTablesStruct<'mc> }, + TrialChambersChamberDispenser { inner: LootTablesStruct<'mc> }, + TrialChambersWaterDispenser { inner: LootTablesStruct<'mc> }, + TrialChambersCorridorPot { inner: LootTablesStruct<'mc> }, + EquipmentTrialChamber { inner: LootTablesStruct<'mc> }, + EquipmentTrialChamberRanged { inner: LootTablesStruct<'mc> }, + EquipmentTrialChamberMelee { inner: LootTablesStruct<'mc> }, + ShipwreckMap { inner: LootTablesStruct<'mc> }, + ShipwreckSupply { inner: LootTablesStruct<'mc> }, + ShipwreckTreasure { inner: LootTablesStruct<'mc> }, + SimpleDungeon { inner: LootTablesStruct<'mc> }, + SpawnBonusChest { inner: LootTablesStruct<'mc> }, + StrongholdCorridor { inner: LootTablesStruct<'mc> }, + StrongholdCrossing { inner: LootTablesStruct<'mc> }, + StrongholdLibrary { inner: LootTablesStruct<'mc> }, + UnderwaterRuinBig { inner: LootTablesStruct<'mc> }, + UnderwaterRuinSmall { inner: LootTablesStruct<'mc> }, + VillageArmorer { inner: LootTablesStruct<'mc> }, + VillageButcher { inner: LootTablesStruct<'mc> }, + VillageCartographer { inner: LootTablesStruct<'mc> }, + VillageDesertHouse { inner: LootTablesStruct<'mc> }, + VillageFisher { inner: LootTablesStruct<'mc> }, + VillageFletcher { inner: LootTablesStruct<'mc> }, + VillageMason { inner: LootTablesStruct<'mc> }, + VillagePlainsHouse { inner: LootTablesStruct<'mc> }, + VillageSavannaHouse { inner: LootTablesStruct<'mc> }, + VillageShepherd { inner: LootTablesStruct<'mc> }, + VillageSnowyHouse { inner: LootTablesStruct<'mc> }, + VillageTaigaHouse { inner: LootTablesStruct<'mc> }, + VillageTannery { inner: LootTablesStruct<'mc> }, + VillageTemple { inner: LootTablesStruct<'mc> }, + VillageToolsmith { inner: LootTablesStruct<'mc> }, + VillageWeaponsmith { inner: LootTablesStruct<'mc> }, + WoodlandMansion { inner: LootTablesStruct<'mc> }, + ArmorStand { inner: LootTablesStruct<'mc> }, + Axolotl { inner: LootTablesStruct<'mc> }, + Bat { inner: LootTablesStruct<'mc> }, + Bee { inner: LootTablesStruct<'mc> }, + Blaze { inner: LootTablesStruct<'mc> }, + Cat { inner: LootTablesStruct<'mc> }, + CaveSpider { inner: LootTablesStruct<'mc> }, + Chicken { inner: LootTablesStruct<'mc> }, + Cod { inner: LootTablesStruct<'mc> }, + Cow { inner: LootTablesStruct<'mc> }, + Creeper { inner: LootTablesStruct<'mc> }, + Dolphin { inner: LootTablesStruct<'mc> }, + Donkey { inner: LootTablesStruct<'mc> }, + Drowned { inner: LootTablesStruct<'mc> }, + ElderGuardian { inner: LootTablesStruct<'mc> }, + EnderDragon { inner: LootTablesStruct<'mc> }, + Enderman { inner: LootTablesStruct<'mc> }, + Endermite { inner: LootTablesStruct<'mc> }, + Evoker { inner: LootTablesStruct<'mc> }, + Fox { inner: LootTablesStruct<'mc> }, + Ghast { inner: LootTablesStruct<'mc> }, + Giant { inner: LootTablesStruct<'mc> }, + GlowSquid { inner: LootTablesStruct<'mc> }, + Goat { inner: LootTablesStruct<'mc> }, + Guardian { inner: LootTablesStruct<'mc> }, + Hoglin { inner: LootTablesStruct<'mc> }, + Horse { inner: LootTablesStruct<'mc> }, + Husk { inner: LootTablesStruct<'mc> }, + Illusioner { inner: LootTablesStruct<'mc> }, + IronGolem { inner: LootTablesStruct<'mc> }, + Llama { inner: LootTablesStruct<'mc> }, + MagmaCube { inner: LootTablesStruct<'mc> }, + Mooshroom { inner: LootTablesStruct<'mc> }, + Mule { inner: LootTablesStruct<'mc> }, + Ocelot { inner: LootTablesStruct<'mc> }, + Panda { inner: LootTablesStruct<'mc> }, + Parrot { inner: LootTablesStruct<'mc> }, + Phantom { inner: LootTablesStruct<'mc> }, + Pig { inner: LootTablesStruct<'mc> }, + Piglin { inner: LootTablesStruct<'mc> }, + PiglinBrute { inner: LootTablesStruct<'mc> }, + Pillager { inner: LootTablesStruct<'mc> }, + Player { inner: LootTablesStruct<'mc> }, + PolarBear { inner: LootTablesStruct<'mc> }, + Pufferfish { inner: LootTablesStruct<'mc> }, + Rabbit { inner: LootTablesStruct<'mc> }, + Ravager { inner: LootTablesStruct<'mc> }, + Salmon { inner: LootTablesStruct<'mc> }, + Shulker { inner: LootTablesStruct<'mc> }, + Silverfish { inner: LootTablesStruct<'mc> }, + Skeleton { inner: LootTablesStruct<'mc> }, + SkeletonHorse { inner: LootTablesStruct<'mc> }, + Slime { inner: LootTablesStruct<'mc> }, + SnowGolem { inner: LootTablesStruct<'mc> }, + Spider { inner: LootTablesStruct<'mc> }, + Squid { inner: LootTablesStruct<'mc> }, + Stray { inner: LootTablesStruct<'mc> }, + Strider { inner: LootTablesStruct<'mc> }, + TraderLlama { inner: LootTablesStruct<'mc> }, + TropicalFish { inner: LootTablesStruct<'mc> }, + Turtle { inner: LootTablesStruct<'mc> }, + Vex { inner: LootTablesStruct<'mc> }, + Villager { inner: LootTablesStruct<'mc> }, + Vindicator { inner: LootTablesStruct<'mc> }, + WanderingTrader { inner: LootTablesStruct<'mc> }, + Witch { inner: LootTablesStruct<'mc> }, + Wither { inner: LootTablesStruct<'mc> }, + WitherSkeleton { inner: LootTablesStruct<'mc> }, + Wolf { inner: LootTablesStruct<'mc> }, + Zoglin { inner: LootTablesStruct<'mc> }, + Zombie { inner: LootTablesStruct<'mc> }, + ZombieHorse { inner: LootTablesStruct<'mc> }, + ZombieVillager { inner: LootTablesStruct<'mc> }, + ZombifiedPiglin { inner: LootTablesStruct<'mc> }, + ArmorerGift { inner: LootTablesStruct<'mc> }, + ButcherGift { inner: LootTablesStruct<'mc> }, + CartographerGift { inner: LootTablesStruct<'mc> }, + CatMorningGift { inner: LootTablesStruct<'mc> }, + ClericGift { inner: LootTablesStruct<'mc> }, + FarmerGift { inner: LootTablesStruct<'mc> }, + FishermanGift { inner: LootTablesStruct<'mc> }, + Fishing { inner: LootTablesStruct<'mc> }, + FishingFish { inner: LootTablesStruct<'mc> }, + FishingJunk { inner: LootTablesStruct<'mc> }, + FishingTreasure { inner: LootTablesStruct<'mc> }, + FletcherGift { inner: LootTablesStruct<'mc> }, + LeatherworkerGift { inner: LootTablesStruct<'mc> }, + LibrarianGift { inner: LootTablesStruct<'mc> }, + MasonGift { inner: LootTablesStruct<'mc> }, + ShepherdGift { inner: LootTablesStruct<'mc> }, + ToolsmithGift { inner: LootTablesStruct<'mc> }, + WeaponsmithGift { inner: LootTablesStruct<'mc> }, + SnifferDigging { inner: LootTablesStruct<'mc> }, + PandaSneeze { inner: LootTablesStruct<'mc> }, + PiglinBartering { inner: LootTablesStruct<'mc> }, + TrialChamberKey { inner: LootTablesStruct<'mc> }, + TrialChamberConsumables { inner: LootTablesStruct<'mc> }, + OminousTrialChamberKey { inner: LootTablesStruct<'mc> }, + OminousTrialChamberConsumables { inner: LootTablesStruct<'mc> }, + TrialChamberItemsToDropWhenOminous { inner: LootTablesStruct<'mc> }, + ShearingBogged { inner: LootTablesStruct<'mc> }, + DesertWellArchaeology { inner: LootTablesStruct<'mc> }, + DesertPyramidArchaeology { inner: LootTablesStruct<'mc> }, + TrailRuinsArchaeologyCommon { inner: LootTablesStruct<'mc> }, + TrailRuinsArchaeologyRare { inner: LootTablesStruct<'mc> }, + OceanRuinWarmArchaeology { inner: LootTablesStruct<'mc> }, + OceanRuinColdArchaeology { inner: LootTablesStruct<'mc> }, + Sheep { inner: LootTablesStruct<'mc> }, + SheepBlack { inner: LootTablesStruct<'mc> }, + SheepBlue { inner: LootTablesStruct<'mc> }, + SheepBrown { inner: LootTablesStruct<'mc> }, + SheepCyan { inner: LootTablesStruct<'mc> }, + SheepGray { inner: LootTablesStruct<'mc> }, + SheepGreen { inner: LootTablesStruct<'mc> }, + SheepLightBlue { inner: LootTablesStruct<'mc> }, + SheepLightGray { inner: LootTablesStruct<'mc> }, + SheepLime { inner: LootTablesStruct<'mc> }, + SheepMagenta { inner: LootTablesStruct<'mc> }, + SheepOrange { inner: LootTablesStruct<'mc> }, + SheepPink { inner: LootTablesStruct<'mc> }, + SheepPurple { inner: LootTablesStruct<'mc> }, + SheepRed { inner: LootTablesStruct<'mc> }, + SheepWhite { inner: LootTablesStruct<'mc> }, + SheepYellow { inner: LootTablesStruct<'mc> }, +} impl<'mc> std::fmt::Display for LootTables<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + LootTables::Empty { .. } => f.write_str("EMPTY"), + LootTables::AbandonedMineshaft { .. } => f.write_str("ABANDONED_MINESHAFT"), + LootTables::BuriedTreasure { .. } => f.write_str("BURIED_TREASURE"), + LootTables::DesertPyramid { .. } => f.write_str("DESERT_PYRAMID"), + LootTables::EndCityTreasure { .. } => f.write_str("END_CITY_TREASURE"), + LootTables::IglooChest { .. } => f.write_str("IGLOO_CHEST"), + LootTables::JungleTemple { .. } => f.write_str("JUNGLE_TEMPLE"), + LootTables::JungleTempleDispenser { .. } => f.write_str("JUNGLE_TEMPLE_DISPENSER"), + LootTables::NetherBridge { .. } => f.write_str("NETHER_BRIDGE"), + LootTables::PillagerOutpost { .. } => f.write_str("PILLAGER_OUTPOST"), + LootTables::BastionTreasure { .. } => f.write_str("BASTION_TREASURE"), + LootTables::BastionOther { .. } => f.write_str("BASTION_OTHER"), + LootTables::BastionBridge { .. } => f.write_str("BASTION_BRIDGE"), + LootTables::BastionHoglinStable { .. } => f.write_str("BASTION_HOGLIN_STABLE"), + LootTables::AncientCity { .. } => f.write_str("ANCIENT_CITY"), + LootTables::AncientCityIceBox { .. } => f.write_str("ANCIENT_CITY_ICE_BOX"), + LootTables::RuinedPortal { .. } => f.write_str("RUINED_PORTAL"), + LootTables::TrialChambersReward { .. } => f.write_str("TRIAL_CHAMBERS_REWARD"), + LootTables::TrialChambersRewardCommon { .. } => { + f.write_str("TRIAL_CHAMBERS_REWARD_COMMON") + } + LootTables::TrialChambersRewardRare { .. } => f.write_str("TRIAL_CHAMBERS_REWARD_RARE"), + LootTables::TrialChambersRewardUnique { .. } => { + f.write_str("TRIAL_CHAMBERS_REWARD_UNIQUE") + } + LootTables::TrialChambersRewardOminous { .. } => { + f.write_str("TRIAL_CHAMBERS_REWARD_OMINOUS") + } + LootTables::TrialChambersRewardOminousCommon { .. } => { + f.write_str("TRIAL_CHAMBERS_REWARD_OMINOUS_COMMON") + } + LootTables::TrialChambersRewardOminousRare { .. } => { + f.write_str("TRIAL_CHAMBERS_REWARD_OMINOUS_RARE") + } + LootTables::TrialChambersRewardOminousUnique { .. } => { + f.write_str("TRIAL_CHAMBERS_REWARD_OMINOUS_UNIQUE") + } + LootTables::TrialChambersSupply { .. } => f.write_str("TRIAL_CHAMBERS_SUPPLY"), + LootTables::TrialChambersCorridor { .. } => f.write_str("TRIAL_CHAMBERS_CORRIDOR"), + LootTables::TrialChambersIntersection { .. } => { + f.write_str("TRIAL_CHAMBERS_INTERSECTION") + } + LootTables::TrialChambersIntersectionBarrel { .. } => { + f.write_str("TRIAL_CHAMBERS_INTERSECTION_BARREL") + } + LootTables::TrialChambersEntrance { .. } => f.write_str("TRIAL_CHAMBERS_ENTRANCE"), + LootTables::TrialChambersCorridorDispenser { .. } => { + f.write_str("TRIAL_CHAMBERS_CORRIDOR_DISPENSER") + } + LootTables::TrialChambersChamberDispenser { .. } => { + f.write_str("TRIAL_CHAMBERS_CHAMBER_DISPENSER") + } + LootTables::TrialChambersWaterDispenser { .. } => { + f.write_str("TRIAL_CHAMBERS_WATER_DISPENSER") + } + LootTables::TrialChambersCorridorPot { .. } => { + f.write_str("TRIAL_CHAMBERS_CORRIDOR_POT") + } + LootTables::EquipmentTrialChamber { .. } => f.write_str("EQUIPMENT_TRIAL_CHAMBER"), + LootTables::EquipmentTrialChamberRanged { .. } => { + f.write_str("EQUIPMENT_TRIAL_CHAMBER_RANGED") + } + LootTables::EquipmentTrialChamberMelee { .. } => { + f.write_str("EQUIPMENT_TRIAL_CHAMBER_MELEE") + } + LootTables::ShipwreckMap { .. } => f.write_str("SHIPWRECK_MAP"), + LootTables::ShipwreckSupply { .. } => f.write_str("SHIPWRECK_SUPPLY"), + LootTables::ShipwreckTreasure { .. } => f.write_str("SHIPWRECK_TREASURE"), + LootTables::SimpleDungeon { .. } => f.write_str("SIMPLE_DUNGEON"), + LootTables::SpawnBonusChest { .. } => f.write_str("SPAWN_BONUS_CHEST"), + LootTables::StrongholdCorridor { .. } => f.write_str("STRONGHOLD_CORRIDOR"), + LootTables::StrongholdCrossing { .. } => f.write_str("STRONGHOLD_CROSSING"), + LootTables::StrongholdLibrary { .. } => f.write_str("STRONGHOLD_LIBRARY"), + LootTables::UnderwaterRuinBig { .. } => f.write_str("UNDERWATER_RUIN_BIG"), + LootTables::UnderwaterRuinSmall { .. } => f.write_str("UNDERWATER_RUIN_SMALL"), + LootTables::VillageArmorer { .. } => f.write_str("VILLAGE_ARMORER"), + LootTables::VillageButcher { .. } => f.write_str("VILLAGE_BUTCHER"), + LootTables::VillageCartographer { .. } => f.write_str("VILLAGE_CARTOGRAPHER"), + LootTables::VillageDesertHouse { .. } => f.write_str("VILLAGE_DESERT_HOUSE"), + LootTables::VillageFisher { .. } => f.write_str("VILLAGE_FISHER"), + LootTables::VillageFletcher { .. } => f.write_str("VILLAGE_FLETCHER"), + LootTables::VillageMason { .. } => f.write_str("VILLAGE_MASON"), + LootTables::VillagePlainsHouse { .. } => f.write_str("VILLAGE_PLAINS_HOUSE"), + LootTables::VillageSavannaHouse { .. } => f.write_str("VILLAGE_SAVANNA_HOUSE"), + LootTables::VillageShepherd { .. } => f.write_str("VILLAGE_SHEPHERD"), + LootTables::VillageSnowyHouse { .. } => f.write_str("VILLAGE_SNOWY_HOUSE"), + LootTables::VillageTaigaHouse { .. } => f.write_str("VILLAGE_TAIGA_HOUSE"), + LootTables::VillageTannery { .. } => f.write_str("VILLAGE_TANNERY"), + LootTables::VillageTemple { .. } => f.write_str("VILLAGE_TEMPLE"), + LootTables::VillageToolsmith { .. } => f.write_str("VILLAGE_TOOLSMITH"), + LootTables::VillageWeaponsmith { .. } => f.write_str("VILLAGE_WEAPONSMITH"), + LootTables::WoodlandMansion { .. } => f.write_str("WOODLAND_MANSION"), + LootTables::ArmorStand { .. } => f.write_str("ARMOR_STAND"), + LootTables::Axolotl { .. } => f.write_str("AXOLOTL"), + LootTables::Bat { .. } => f.write_str("BAT"), + LootTables::Bee { .. } => f.write_str("BEE"), + LootTables::Blaze { .. } => f.write_str("BLAZE"), + LootTables::Cat { .. } => f.write_str("CAT"), + LootTables::CaveSpider { .. } => f.write_str("CAVE_SPIDER"), + LootTables::Chicken { .. } => f.write_str("CHICKEN"), + LootTables::Cod { .. } => f.write_str("COD"), + LootTables::Cow { .. } => f.write_str("COW"), + LootTables::Creeper { .. } => f.write_str("CREEPER"), + LootTables::Dolphin { .. } => f.write_str("DOLPHIN"), + LootTables::Donkey { .. } => f.write_str("DONKEY"), + LootTables::Drowned { .. } => f.write_str("DROWNED"), + LootTables::ElderGuardian { .. } => f.write_str("ELDER_GUARDIAN"), + LootTables::EnderDragon { .. } => f.write_str("ENDER_DRAGON"), + LootTables::Enderman { .. } => f.write_str("ENDERMAN"), + LootTables::Endermite { .. } => f.write_str("ENDERMITE"), + LootTables::Evoker { .. } => f.write_str("EVOKER"), + LootTables::Fox { .. } => f.write_str("FOX"), + LootTables::Ghast { .. } => f.write_str("GHAST"), + LootTables::Giant { .. } => f.write_str("GIANT"), + LootTables::GlowSquid { .. } => f.write_str("GLOW_SQUID"), + LootTables::Goat { .. } => f.write_str("GOAT"), + LootTables::Guardian { .. } => f.write_str("GUARDIAN"), + LootTables::Hoglin { .. } => f.write_str("HOGLIN"), + LootTables::Horse { .. } => f.write_str("HORSE"), + LootTables::Husk { .. } => f.write_str("HUSK"), + LootTables::Illusioner { .. } => f.write_str("ILLUSIONER"), + LootTables::IronGolem { .. } => f.write_str("IRON_GOLEM"), + LootTables::Llama { .. } => f.write_str("LLAMA"), + LootTables::MagmaCube { .. } => f.write_str("MAGMA_CUBE"), + LootTables::Mooshroom { .. } => f.write_str("MOOSHROOM"), + LootTables::Mule { .. } => f.write_str("MULE"), + LootTables::Ocelot { .. } => f.write_str("OCELOT"), + LootTables::Panda { .. } => f.write_str("PANDA"), + LootTables::Parrot { .. } => f.write_str("PARROT"), + LootTables::Phantom { .. } => f.write_str("PHANTOM"), + LootTables::Pig { .. } => f.write_str("PIG"), + LootTables::Piglin { .. } => f.write_str("PIGLIN"), + LootTables::PiglinBrute { .. } => f.write_str("PIGLIN_BRUTE"), + LootTables::Pillager { .. } => f.write_str("PILLAGER"), + LootTables::Player { .. } => f.write_str("PLAYER"), + LootTables::PolarBear { .. } => f.write_str("POLAR_BEAR"), + LootTables::Pufferfish { .. } => f.write_str("PUFFERFISH"), + LootTables::Rabbit { .. } => f.write_str("RABBIT"), + LootTables::Ravager { .. } => f.write_str("RAVAGER"), + LootTables::Salmon { .. } => f.write_str("SALMON"), + LootTables::Shulker { .. } => f.write_str("SHULKER"), + LootTables::Silverfish { .. } => f.write_str("SILVERFISH"), + LootTables::Skeleton { .. } => f.write_str("SKELETON"), + LootTables::SkeletonHorse { .. } => f.write_str("SKELETON_HORSE"), + LootTables::Slime { .. } => f.write_str("SLIME"), + LootTables::SnowGolem { .. } => f.write_str("SNOW_GOLEM"), + LootTables::Spider { .. } => f.write_str("SPIDER"), + LootTables::Squid { .. } => f.write_str("SQUID"), + LootTables::Stray { .. } => f.write_str("STRAY"), + LootTables::Strider { .. } => f.write_str("STRIDER"), + LootTables::TraderLlama { .. } => f.write_str("TRADER_LLAMA"), + LootTables::TropicalFish { .. } => f.write_str("TROPICAL_FISH"), + LootTables::Turtle { .. } => f.write_str("TURTLE"), + LootTables::Vex { .. } => f.write_str("VEX"), + LootTables::Villager { .. } => f.write_str("VILLAGER"), + LootTables::Vindicator { .. } => f.write_str("VINDICATOR"), + LootTables::WanderingTrader { .. } => f.write_str("WANDERING_TRADER"), + LootTables::Witch { .. } => f.write_str("WITCH"), + LootTables::Wither { .. } => f.write_str("WITHER"), + LootTables::WitherSkeleton { .. } => f.write_str("WITHER_SKELETON"), + LootTables::Wolf { .. } => f.write_str("WOLF"), + LootTables::Zoglin { .. } => f.write_str("ZOGLIN"), + LootTables::Zombie { .. } => f.write_str("ZOMBIE"), + LootTables::ZombieHorse { .. } => f.write_str("ZOMBIE_HORSE"), + LootTables::ZombieVillager { .. } => f.write_str("ZOMBIE_VILLAGER"), + LootTables::ZombifiedPiglin { .. } => f.write_str("ZOMBIFIED_PIGLIN"), + LootTables::ArmorerGift { .. } => f.write_str("ARMORER_GIFT"), + LootTables::ButcherGift { .. } => f.write_str("BUTCHER_GIFT"), + LootTables::CartographerGift { .. } => f.write_str("CARTOGRAPHER_GIFT"), + LootTables::CatMorningGift { .. } => f.write_str("CAT_MORNING_GIFT"), + LootTables::ClericGift { .. } => f.write_str("CLERIC_GIFT"), + LootTables::FarmerGift { .. } => f.write_str("FARMER_GIFT"), + LootTables::FishermanGift { .. } => f.write_str("FISHERMAN_GIFT"), + LootTables::Fishing { .. } => f.write_str("FISHING"), + LootTables::FishingFish { .. } => f.write_str("FISHING_FISH"), + LootTables::FishingJunk { .. } => f.write_str("FISHING_JUNK"), + LootTables::FishingTreasure { .. } => f.write_str("FISHING_TREASURE"), + LootTables::FletcherGift { .. } => f.write_str("FLETCHER_GIFT"), + LootTables::LeatherworkerGift { .. } => f.write_str("LEATHERWORKER_GIFT"), + LootTables::LibrarianGift { .. } => f.write_str("LIBRARIAN_GIFT"), + LootTables::MasonGift { .. } => f.write_str("MASON_GIFT"), + LootTables::ShepherdGift { .. } => f.write_str("SHEPHERD_GIFT"), + LootTables::ToolsmithGift { .. } => f.write_str("TOOLSMITH_GIFT"), + LootTables::WeaponsmithGift { .. } => f.write_str("WEAPONSMITH_GIFT"), + LootTables::SnifferDigging { .. } => f.write_str("SNIFFER_DIGGING"), + LootTables::PandaSneeze { .. } => f.write_str("PANDA_SNEEZE"), + LootTables::PiglinBartering { .. } => f.write_str("PIGLIN_BARTERING"), + LootTables::TrialChamberKey { .. } => f.write_str("TRIAL_CHAMBER_KEY"), + LootTables::TrialChamberConsumables { .. } => f.write_str("TRIAL_CHAMBER_CONSUMABLES"), + LootTables::OminousTrialChamberKey { .. } => f.write_str("OMINOUS_TRIAL_CHAMBER_KEY"), + LootTables::OminousTrialChamberConsumables { .. } => { + f.write_str("OMINOUS_TRIAL_CHAMBER_CONSUMABLES") + } + LootTables::TrialChamberItemsToDropWhenOminous { .. } => { + f.write_str("TRIAL_CHAMBER_ITEMS_TO_DROP_WHEN_OMINOUS") + } + LootTables::ShearingBogged { .. } => f.write_str("SHEARING_BOGGED"), + LootTables::DesertWellArchaeology { .. } => f.write_str("DESERT_WELL_ARCHAEOLOGY"), + LootTables::DesertPyramidArchaeology { .. } => { + f.write_str("DESERT_PYRAMID_ARCHAEOLOGY") + } + LootTables::TrailRuinsArchaeologyCommon { .. } => { + f.write_str("TRAIL_RUINS_ARCHAEOLOGY_COMMON") + } + LootTables::TrailRuinsArchaeologyRare { .. } => { + f.write_str("TRAIL_RUINS_ARCHAEOLOGY_RARE") + } + LootTables::OceanRuinWarmArchaeology { .. } => { + f.write_str("OCEAN_RUIN_WARM_ARCHAEOLOGY") + } + LootTables::OceanRuinColdArchaeology { .. } => { + f.write_str("OCEAN_RUIN_COLD_ARCHAEOLOGY") + } + LootTables::Sheep { .. } => f.write_str("SHEEP"), + LootTables::SheepBlack { .. } => f.write_str("SHEEP_BLACK"), + LootTables::SheepBlue { .. } => f.write_str("SHEEP_BLUE"), + LootTables::SheepBrown { .. } => f.write_str("SHEEP_BROWN"), + LootTables::SheepCyan { .. } => f.write_str("SHEEP_CYAN"), + LootTables::SheepGray { .. } => f.write_str("SHEEP_GRAY"), + LootTables::SheepGreen { .. } => f.write_str("SHEEP_GREEN"), + LootTables::SheepLightBlue { .. } => f.write_str("SHEEP_LIGHT_BLUE"), + LootTables::SheepLightGray { .. } => f.write_str("SHEEP_LIGHT_GRAY"), + LootTables::SheepLime { .. } => f.write_str("SHEEP_LIME"), + LootTables::SheepMagenta { .. } => f.write_str("SHEEP_MAGENTA"), + LootTables::SheepOrange { .. } => f.write_str("SHEEP_ORANGE"), + LootTables::SheepPink { .. } => f.write_str("SHEEP_PINK"), + LootTables::SheepPurple { .. } => f.write_str("SHEEP_PURPLE"), + LootTables::SheepRed { .. } => f.write_str("SHEEP_RED"), + LootTables::SheepWhite { .. } => f.write_str("SHEEP_WHITE"), + LootTables::SheepYellow { .. } => f.write_str("SHEEP_YELLOW"), + } + } +} +impl<'mc> std::ops::Deref for LootTables<'mc> { + type Target = LootTablesStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + LootTables::Empty { inner } => inner, + LootTables::AbandonedMineshaft { inner } => inner, + LootTables::BuriedTreasure { inner } => inner, + LootTables::DesertPyramid { inner } => inner, + LootTables::EndCityTreasure { inner } => inner, + LootTables::IglooChest { inner } => inner, + LootTables::JungleTemple { inner } => inner, + LootTables::JungleTempleDispenser { inner } => inner, + LootTables::NetherBridge { inner } => inner, + LootTables::PillagerOutpost { inner } => inner, + LootTables::BastionTreasure { inner } => inner, + LootTables::BastionOther { inner } => inner, + LootTables::BastionBridge { inner } => inner, + LootTables::BastionHoglinStable { inner } => inner, + LootTables::AncientCity { inner } => inner, + LootTables::AncientCityIceBox { inner } => inner, + LootTables::RuinedPortal { inner } => inner, + LootTables::TrialChambersReward { inner } => inner, + LootTables::TrialChambersRewardCommon { inner } => inner, + LootTables::TrialChambersRewardRare { inner } => inner, + LootTables::TrialChambersRewardUnique { inner } => inner, + LootTables::TrialChambersRewardOminous { inner } => inner, + LootTables::TrialChambersRewardOminousCommon { inner } => inner, + LootTables::TrialChambersRewardOminousRare { inner } => inner, + LootTables::TrialChambersRewardOminousUnique { inner } => inner, + LootTables::TrialChambersSupply { inner } => inner, + LootTables::TrialChambersCorridor { inner } => inner, + LootTables::TrialChambersIntersection { inner } => inner, + LootTables::TrialChambersIntersectionBarrel { inner } => inner, + LootTables::TrialChambersEntrance { inner } => inner, + LootTables::TrialChambersCorridorDispenser { inner } => inner, + LootTables::TrialChambersChamberDispenser { inner } => inner, + LootTables::TrialChambersWaterDispenser { inner } => inner, + LootTables::TrialChambersCorridorPot { inner } => inner, + LootTables::EquipmentTrialChamber { inner } => inner, + LootTables::EquipmentTrialChamberRanged { inner } => inner, + LootTables::EquipmentTrialChamberMelee { inner } => inner, + LootTables::ShipwreckMap { inner } => inner, + LootTables::ShipwreckSupply { inner } => inner, + LootTables::ShipwreckTreasure { inner } => inner, + LootTables::SimpleDungeon { inner } => inner, + LootTables::SpawnBonusChest { inner } => inner, + LootTables::StrongholdCorridor { inner } => inner, + LootTables::StrongholdCrossing { inner } => inner, + LootTables::StrongholdLibrary { inner } => inner, + LootTables::UnderwaterRuinBig { inner } => inner, + LootTables::UnderwaterRuinSmall { inner } => inner, + LootTables::VillageArmorer { inner } => inner, + LootTables::VillageButcher { inner } => inner, + LootTables::VillageCartographer { inner } => inner, + LootTables::VillageDesertHouse { inner } => inner, + LootTables::VillageFisher { inner } => inner, + LootTables::VillageFletcher { inner } => inner, + LootTables::VillageMason { inner } => inner, + LootTables::VillagePlainsHouse { inner } => inner, + LootTables::VillageSavannaHouse { inner } => inner, + LootTables::VillageShepherd { inner } => inner, + LootTables::VillageSnowyHouse { inner } => inner, + LootTables::VillageTaigaHouse { inner } => inner, + LootTables::VillageTannery { inner } => inner, + LootTables::VillageTemple { inner } => inner, + LootTables::VillageToolsmith { inner } => inner, + LootTables::VillageWeaponsmith { inner } => inner, + LootTables::WoodlandMansion { inner } => inner, + LootTables::ArmorStand { inner } => inner, + LootTables::Axolotl { inner } => inner, + LootTables::Bat { inner } => inner, + LootTables::Bee { inner } => inner, + LootTables::Blaze { inner } => inner, + LootTables::Cat { inner } => inner, + LootTables::CaveSpider { inner } => inner, + LootTables::Chicken { inner } => inner, + LootTables::Cod { inner } => inner, + LootTables::Cow { inner } => inner, + LootTables::Creeper { inner } => inner, + LootTables::Dolphin { inner } => inner, + LootTables::Donkey { inner } => inner, + LootTables::Drowned { inner } => inner, + LootTables::ElderGuardian { inner } => inner, + LootTables::EnderDragon { inner } => inner, + LootTables::Enderman { inner } => inner, + LootTables::Endermite { inner } => inner, + LootTables::Evoker { inner } => inner, + LootTables::Fox { inner } => inner, + LootTables::Ghast { inner } => inner, + LootTables::Giant { inner } => inner, + LootTables::GlowSquid { inner } => inner, + LootTables::Goat { inner } => inner, + LootTables::Guardian { inner } => inner, + LootTables::Hoglin { inner } => inner, + LootTables::Horse { inner } => inner, + LootTables::Husk { inner } => inner, + LootTables::Illusioner { inner } => inner, + LootTables::IronGolem { inner } => inner, + LootTables::Llama { inner } => inner, + LootTables::MagmaCube { inner } => inner, + LootTables::Mooshroom { inner } => inner, + LootTables::Mule { inner } => inner, + LootTables::Ocelot { inner } => inner, + LootTables::Panda { inner } => inner, + LootTables::Parrot { inner } => inner, + LootTables::Phantom { inner } => inner, + LootTables::Pig { inner } => inner, + LootTables::Piglin { inner } => inner, + LootTables::PiglinBrute { inner } => inner, + LootTables::Pillager { inner } => inner, + LootTables::Player { inner } => inner, + LootTables::PolarBear { inner } => inner, + LootTables::Pufferfish { inner } => inner, + LootTables::Rabbit { inner } => inner, + LootTables::Ravager { inner } => inner, + LootTables::Salmon { inner } => inner, + LootTables::Shulker { inner } => inner, + LootTables::Silverfish { inner } => inner, + LootTables::Skeleton { inner } => inner, + LootTables::SkeletonHorse { inner } => inner, + LootTables::Slime { inner } => inner, + LootTables::SnowGolem { inner } => inner, + LootTables::Spider { inner } => inner, + LootTables::Squid { inner } => inner, + LootTables::Stray { inner } => inner, + LootTables::Strider { inner } => inner, + LootTables::TraderLlama { inner } => inner, + LootTables::TropicalFish { inner } => inner, + LootTables::Turtle { inner } => inner, + LootTables::Vex { inner } => inner, + LootTables::Villager { inner } => inner, + LootTables::Vindicator { inner } => inner, + LootTables::WanderingTrader { inner } => inner, + LootTables::Witch { inner } => inner, + LootTables::Wither { inner } => inner, + LootTables::WitherSkeleton { inner } => inner, + LootTables::Wolf { inner } => inner, + LootTables::Zoglin { inner } => inner, + LootTables::Zombie { inner } => inner, + LootTables::ZombieHorse { inner } => inner, + LootTables::ZombieVillager { inner } => inner, + LootTables::ZombifiedPiglin { inner } => inner, + LootTables::ArmorerGift { inner } => inner, + LootTables::ButcherGift { inner } => inner, + LootTables::CartographerGift { inner } => inner, + LootTables::CatMorningGift { inner } => inner, + LootTables::ClericGift { inner } => inner, + LootTables::FarmerGift { inner } => inner, + LootTables::FishermanGift { inner } => inner, + LootTables::Fishing { inner } => inner, + LootTables::FishingFish { inner } => inner, + LootTables::FishingJunk { inner } => inner, + LootTables::FishingTreasure { inner } => inner, + LootTables::FletcherGift { inner } => inner, + LootTables::LeatherworkerGift { inner } => inner, + LootTables::LibrarianGift { inner } => inner, + LootTables::MasonGift { inner } => inner, + LootTables::ShepherdGift { inner } => inner, + LootTables::ToolsmithGift { inner } => inner, + LootTables::WeaponsmithGift { inner } => inner, + LootTables::SnifferDigging { inner } => inner, + LootTables::PandaSneeze { inner } => inner, + LootTables::PiglinBartering { inner } => inner, + LootTables::TrialChamberKey { inner } => inner, + LootTables::TrialChamberConsumables { inner } => inner, + LootTables::OminousTrialChamberKey { inner } => inner, + LootTables::OminousTrialChamberConsumables { inner } => inner, + LootTables::TrialChamberItemsToDropWhenOminous { inner } => inner, + LootTables::ShearingBogged { inner } => inner, + LootTables::DesertWellArchaeology { inner } => inner, + LootTables::DesertPyramidArchaeology { inner } => inner, + LootTables::TrailRuinsArchaeologyCommon { inner } => inner, + LootTables::TrailRuinsArchaeologyRare { inner } => inner, + LootTables::OceanRuinWarmArchaeology { inner } => inner, + LootTables::OceanRuinColdArchaeology { inner } => inner, + LootTables::Sheep { inner } => inner, + LootTables::SheepBlack { inner } => inner, + LootTables::SheepBlue { inner } => inner, + LootTables::SheepBrown { inner } => inner, + LootTables::SheepCyan { inner } => inner, + LootTables::SheepGray { inner } => inner, + LootTables::SheepGreen { inner } => inner, + LootTables::SheepLightBlue { inner } => inner, + LootTables::SheepLightGray { inner } => inner, + LootTables::SheepLime { inner } => inner, + LootTables::SheepMagenta { inner } => inner, + LootTables::SheepOrange { inner } => inner, + LootTables::SheepPink { inner } => inner, + LootTables::SheepPurple { inner } => inner, + LootTables::SheepRed { inner } => inner, + LootTables::SheepWhite { inner } => inner, + LootTables::SheepYellow { inner } => inner, + } } } @@ -32,6 +647,581 @@ impl<'mc> LootTables<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "EMPTY" => Ok(LootTables::Empty { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ABANDONED_MINESHAFT" => Ok(LootTables::AbandonedMineshaft { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "BURIED_TREASURE" => Ok(LootTables::BuriedTreasure { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "DESERT_PYRAMID" => Ok(LootTables::DesertPyramid { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "END_CITY_TREASURE" => Ok(LootTables::EndCityTreasure { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "IGLOO_CHEST" => Ok(LootTables::IglooChest { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "JUNGLE_TEMPLE" => Ok(LootTables::JungleTemple { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "JUNGLE_TEMPLE_DISPENSER" => Ok(LootTables::JungleTempleDispenser { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "NETHER_BRIDGE" => Ok(LootTables::NetherBridge { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "PILLAGER_OUTPOST" => Ok(LootTables::PillagerOutpost { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "BASTION_TREASURE" => Ok(LootTables::BastionTreasure { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "BASTION_OTHER" => Ok(LootTables::BastionOther { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "BASTION_BRIDGE" => Ok(LootTables::BastionBridge { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "BASTION_HOGLIN_STABLE" => Ok(LootTables::BastionHoglinStable { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ANCIENT_CITY" => Ok(LootTables::AncientCity { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ANCIENT_CITY_ICE_BOX" => Ok(LootTables::AncientCityIceBox { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "RUINED_PORTAL" => Ok(LootTables::RuinedPortal { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBERS_REWARD" => Ok(LootTables::TrialChambersReward { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBERS_REWARD_COMMON" => Ok(LootTables::TrialChambersRewardCommon { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBERS_REWARD_RARE" => Ok(LootTables::TrialChambersRewardRare { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBERS_REWARD_UNIQUE" => Ok(LootTables::TrialChambersRewardUnique { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBERS_REWARD_OMINOUS" => Ok(LootTables::TrialChambersRewardOminous { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBERS_REWARD_OMINOUS_COMMON" => { + Ok(LootTables::TrialChambersRewardOminousCommon { + inner: LootTablesStruct::from_raw(env, obj)?, + }) + } + "TRIAL_CHAMBERS_REWARD_OMINOUS_RARE" => { + Ok(LootTables::TrialChambersRewardOminousRare { + inner: LootTablesStruct::from_raw(env, obj)?, + }) + } + "TRIAL_CHAMBERS_REWARD_OMINOUS_UNIQUE" => { + Ok(LootTables::TrialChambersRewardOminousUnique { + inner: LootTablesStruct::from_raw(env, obj)?, + }) + } + "TRIAL_CHAMBERS_SUPPLY" => Ok(LootTables::TrialChambersSupply { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBERS_CORRIDOR" => Ok(LootTables::TrialChambersCorridor { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBERS_INTERSECTION" => Ok(LootTables::TrialChambersIntersection { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBERS_INTERSECTION_BARREL" => { + Ok(LootTables::TrialChambersIntersectionBarrel { + inner: LootTablesStruct::from_raw(env, obj)?, + }) + } + "TRIAL_CHAMBERS_ENTRANCE" => Ok(LootTables::TrialChambersEntrance { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBERS_CORRIDOR_DISPENSER" => Ok(LootTables::TrialChambersCorridorDispenser { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBERS_CHAMBER_DISPENSER" => Ok(LootTables::TrialChambersChamberDispenser { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBERS_WATER_DISPENSER" => Ok(LootTables::TrialChambersWaterDispenser { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBERS_CORRIDOR_POT" => Ok(LootTables::TrialChambersCorridorPot { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "EQUIPMENT_TRIAL_CHAMBER" => Ok(LootTables::EquipmentTrialChamber { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "EQUIPMENT_TRIAL_CHAMBER_RANGED" => Ok(LootTables::EquipmentTrialChamberRanged { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "EQUIPMENT_TRIAL_CHAMBER_MELEE" => Ok(LootTables::EquipmentTrialChamberMelee { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHIPWRECK_MAP" => Ok(LootTables::ShipwreckMap { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHIPWRECK_SUPPLY" => Ok(LootTables::ShipwreckSupply { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHIPWRECK_TREASURE" => Ok(LootTables::ShipwreckTreasure { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SIMPLE_DUNGEON" => Ok(LootTables::SimpleDungeon { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SPAWN_BONUS_CHEST" => Ok(LootTables::SpawnBonusChest { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "STRONGHOLD_CORRIDOR" => Ok(LootTables::StrongholdCorridor { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "STRONGHOLD_CROSSING" => Ok(LootTables::StrongholdCrossing { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "STRONGHOLD_LIBRARY" => Ok(LootTables::StrongholdLibrary { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "UNDERWATER_RUIN_BIG" => Ok(LootTables::UnderwaterRuinBig { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "UNDERWATER_RUIN_SMALL" => Ok(LootTables::UnderwaterRuinSmall { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_ARMORER" => Ok(LootTables::VillageArmorer { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_BUTCHER" => Ok(LootTables::VillageButcher { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_CARTOGRAPHER" => Ok(LootTables::VillageCartographer { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_DESERT_HOUSE" => Ok(LootTables::VillageDesertHouse { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_FISHER" => Ok(LootTables::VillageFisher { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_FLETCHER" => Ok(LootTables::VillageFletcher { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_MASON" => Ok(LootTables::VillageMason { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_PLAINS_HOUSE" => Ok(LootTables::VillagePlainsHouse { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_SAVANNA_HOUSE" => Ok(LootTables::VillageSavannaHouse { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_SHEPHERD" => Ok(LootTables::VillageShepherd { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_SNOWY_HOUSE" => Ok(LootTables::VillageSnowyHouse { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_TAIGA_HOUSE" => Ok(LootTables::VillageTaigaHouse { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_TANNERY" => Ok(LootTables::VillageTannery { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_TEMPLE" => Ok(LootTables::VillageTemple { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_TOOLSMITH" => Ok(LootTables::VillageToolsmith { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_WEAPONSMITH" => Ok(LootTables::VillageWeaponsmith { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "WOODLAND_MANSION" => Ok(LootTables::WoodlandMansion { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ARMOR_STAND" => Ok(LootTables::ArmorStand { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "AXOLOTL" => Ok(LootTables::Axolotl { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "BAT" => Ok(LootTables::Bat { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "BEE" => Ok(LootTables::Bee { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "BLAZE" => Ok(LootTables::Blaze { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "CAT" => Ok(LootTables::Cat { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "CAVE_SPIDER" => Ok(LootTables::CaveSpider { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "CHICKEN" => Ok(LootTables::Chicken { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "COD" => Ok(LootTables::Cod { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "COW" => Ok(LootTables::Cow { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "CREEPER" => Ok(LootTables::Creeper { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "DOLPHIN" => Ok(LootTables::Dolphin { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "DONKEY" => Ok(LootTables::Donkey { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "DROWNED" => Ok(LootTables::Drowned { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ELDER_GUARDIAN" => Ok(LootTables::ElderGuardian { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ENDER_DRAGON" => Ok(LootTables::EnderDragon { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ENDERMAN" => Ok(LootTables::Enderman { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ENDERMITE" => Ok(LootTables::Endermite { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "EVOKER" => Ok(LootTables::Evoker { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "FOX" => Ok(LootTables::Fox { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "GHAST" => Ok(LootTables::Ghast { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "GIANT" => Ok(LootTables::Giant { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "GLOW_SQUID" => Ok(LootTables::GlowSquid { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "GOAT" => Ok(LootTables::Goat { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "GUARDIAN" => Ok(LootTables::Guardian { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "HOGLIN" => Ok(LootTables::Hoglin { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "HORSE" => Ok(LootTables::Horse { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "HUSK" => Ok(LootTables::Husk { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ILLUSIONER" => Ok(LootTables::Illusioner { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "IRON_GOLEM" => Ok(LootTables::IronGolem { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "LLAMA" => Ok(LootTables::Llama { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "MAGMA_CUBE" => Ok(LootTables::MagmaCube { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "MOOSHROOM" => Ok(LootTables::Mooshroom { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "MULE" => Ok(LootTables::Mule { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "OCELOT" => Ok(LootTables::Ocelot { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "PANDA" => Ok(LootTables::Panda { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "PARROT" => Ok(LootTables::Parrot { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "PHANTOM" => Ok(LootTables::Phantom { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "PIG" => Ok(LootTables::Pig { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "PIGLIN" => Ok(LootTables::Piglin { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "PIGLIN_BRUTE" => Ok(LootTables::PiglinBrute { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "PILLAGER" => Ok(LootTables::Pillager { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "PLAYER" => Ok(LootTables::Player { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "POLAR_BEAR" => Ok(LootTables::PolarBear { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "PUFFERFISH" => Ok(LootTables::Pufferfish { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "RABBIT" => Ok(LootTables::Rabbit { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "RAVAGER" => Ok(LootTables::Ravager { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SALMON" => Ok(LootTables::Salmon { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHULKER" => Ok(LootTables::Shulker { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SILVERFISH" => Ok(LootTables::Silverfish { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SKELETON" => Ok(LootTables::Skeleton { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SKELETON_HORSE" => Ok(LootTables::SkeletonHorse { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SLIME" => Ok(LootTables::Slime { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SNOW_GOLEM" => Ok(LootTables::SnowGolem { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SPIDER" => Ok(LootTables::Spider { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SQUID" => Ok(LootTables::Squid { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "STRAY" => Ok(LootTables::Stray { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "STRIDER" => Ok(LootTables::Strider { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRADER_LLAMA" => Ok(LootTables::TraderLlama { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TROPICAL_FISH" => Ok(LootTables::TropicalFish { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TURTLE" => Ok(LootTables::Turtle { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VEX" => Ok(LootTables::Vex { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGER" => Ok(LootTables::Villager { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VINDICATOR" => Ok(LootTables::Vindicator { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "WANDERING_TRADER" => Ok(LootTables::WanderingTrader { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "WITCH" => Ok(LootTables::Witch { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "WITHER" => Ok(LootTables::Wither { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "WITHER_SKELETON" => Ok(LootTables::WitherSkeleton { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "WOLF" => Ok(LootTables::Wolf { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ZOGLIN" => Ok(LootTables::Zoglin { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ZOMBIE" => Ok(LootTables::Zombie { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ZOMBIE_HORSE" => Ok(LootTables::ZombieHorse { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ZOMBIE_VILLAGER" => Ok(LootTables::ZombieVillager { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ZOMBIFIED_PIGLIN" => Ok(LootTables::ZombifiedPiglin { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ARMORER_GIFT" => Ok(LootTables::ArmorerGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "BUTCHER_GIFT" => Ok(LootTables::ButcherGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "CARTOGRAPHER_GIFT" => Ok(LootTables::CartographerGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "CAT_MORNING_GIFT" => Ok(LootTables::CatMorningGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "CLERIC_GIFT" => Ok(LootTables::ClericGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "FARMER_GIFT" => Ok(LootTables::FarmerGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "FISHERMAN_GIFT" => Ok(LootTables::FishermanGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "FISHING" => Ok(LootTables::Fishing { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "FISHING_FISH" => Ok(LootTables::FishingFish { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "FISHING_JUNK" => Ok(LootTables::FishingJunk { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "FISHING_TREASURE" => Ok(LootTables::FishingTreasure { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "FLETCHER_GIFT" => Ok(LootTables::FletcherGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "LEATHERWORKER_GIFT" => Ok(LootTables::LeatherworkerGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "LIBRARIAN_GIFT" => Ok(LootTables::LibrarianGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "MASON_GIFT" => Ok(LootTables::MasonGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEPHERD_GIFT" => Ok(LootTables::ShepherdGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TOOLSMITH_GIFT" => Ok(LootTables::ToolsmithGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "WEAPONSMITH_GIFT" => Ok(LootTables::WeaponsmithGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SNIFFER_DIGGING" => Ok(LootTables::SnifferDigging { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "PANDA_SNEEZE" => Ok(LootTables::PandaSneeze { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "PIGLIN_BARTERING" => Ok(LootTables::PiglinBartering { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBER_KEY" => Ok(LootTables::TrialChamberKey { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBER_CONSUMABLES" => Ok(LootTables::TrialChamberConsumables { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "OMINOUS_TRIAL_CHAMBER_KEY" => Ok(LootTables::OminousTrialChamberKey { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "OMINOUS_TRIAL_CHAMBER_CONSUMABLES" => Ok(LootTables::OminousTrialChamberConsumables { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBER_ITEMS_TO_DROP_WHEN_OMINOUS" => { + Ok(LootTables::TrialChamberItemsToDropWhenOminous { + inner: LootTablesStruct::from_raw(env, obj)?, + }) + } + "SHEARING_BOGGED" => Ok(LootTables::ShearingBogged { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "DESERT_WELL_ARCHAEOLOGY" => Ok(LootTables::DesertWellArchaeology { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "DESERT_PYRAMID_ARCHAEOLOGY" => Ok(LootTables::DesertPyramidArchaeology { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRAIL_RUINS_ARCHAEOLOGY_COMMON" => Ok(LootTables::TrailRuinsArchaeologyCommon { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRAIL_RUINS_ARCHAEOLOGY_RARE" => Ok(LootTables::TrailRuinsArchaeologyRare { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "OCEAN_RUIN_WARM_ARCHAEOLOGY" => Ok(LootTables::OceanRuinWarmArchaeology { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "OCEAN_RUIN_COLD_ARCHAEOLOGY" => Ok(LootTables::OceanRuinColdArchaeology { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP" => Ok(LootTables::Sheep { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_BLACK" => Ok(LootTables::SheepBlack { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_BLUE" => Ok(LootTables::SheepBlue { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_BROWN" => Ok(LootTables::SheepBrown { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_CYAN" => Ok(LootTables::SheepCyan { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_GRAY" => Ok(LootTables::SheepGray { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_GREEN" => Ok(LootTables::SheepGreen { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_LIGHT_BLUE" => Ok(LootTables::SheepLightBlue { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_LIGHT_GRAY" => Ok(LootTables::SheepLightGray { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_LIME" => Ok(LootTables::SheepLime { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_MAGENTA" => Ok(LootTables::SheepMagenta { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_ORANGE" => Ok(LootTables::SheepOrange { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_PINK" => Ok(LootTables::SheepPink { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_PURPLE" => Ok(LootTables::SheepPurple { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_RED" => Ok(LootTables::SheepRed { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_WHITE" => Ok(LootTables::SheepWhite { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_YELLOW" => Ok(LootTables::SheepYellow { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -45,10 +1235,656 @@ pub struct LootTablesStruct<'mc>( impl<'mc> JNIRaw<'mc> for LootTables<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Empty { inner } => inner.0.clone(), + Self::AbandonedMineshaft { inner } => inner.0.clone(), + Self::BuriedTreasure { inner } => inner.0.clone(), + Self::DesertPyramid { inner } => inner.0.clone(), + Self::EndCityTreasure { inner } => inner.0.clone(), + Self::IglooChest { inner } => inner.0.clone(), + Self::JungleTemple { inner } => inner.0.clone(), + Self::JungleTempleDispenser { inner } => inner.0.clone(), + Self::NetherBridge { inner } => inner.0.clone(), + Self::PillagerOutpost { inner } => inner.0.clone(), + Self::BastionTreasure { inner } => inner.0.clone(), + Self::BastionOther { inner } => inner.0.clone(), + Self::BastionBridge { inner } => inner.0.clone(), + Self::BastionHoglinStable { inner } => inner.0.clone(), + Self::AncientCity { inner } => inner.0.clone(), + Self::AncientCityIceBox { inner } => inner.0.clone(), + Self::RuinedPortal { inner } => inner.0.clone(), + Self::TrialChambersReward { inner } => inner.0.clone(), + Self::TrialChambersRewardCommon { inner } => inner.0.clone(), + Self::TrialChambersRewardRare { inner } => inner.0.clone(), + Self::TrialChambersRewardUnique { inner } => inner.0.clone(), + Self::TrialChambersRewardOminous { inner } => inner.0.clone(), + Self::TrialChambersRewardOminousCommon { inner } => inner.0.clone(), + Self::TrialChambersRewardOminousRare { inner } => inner.0.clone(), + Self::TrialChambersRewardOminousUnique { inner } => inner.0.clone(), + Self::TrialChambersSupply { inner } => inner.0.clone(), + Self::TrialChambersCorridor { inner } => inner.0.clone(), + Self::TrialChambersIntersection { inner } => inner.0.clone(), + Self::TrialChambersIntersectionBarrel { inner } => inner.0.clone(), + Self::TrialChambersEntrance { inner } => inner.0.clone(), + Self::TrialChambersCorridorDispenser { inner } => inner.0.clone(), + Self::TrialChambersChamberDispenser { inner } => inner.0.clone(), + Self::TrialChambersWaterDispenser { inner } => inner.0.clone(), + Self::TrialChambersCorridorPot { inner } => inner.0.clone(), + Self::EquipmentTrialChamber { inner } => inner.0.clone(), + Self::EquipmentTrialChamberRanged { inner } => inner.0.clone(), + Self::EquipmentTrialChamberMelee { inner } => inner.0.clone(), + Self::ShipwreckMap { inner } => inner.0.clone(), + Self::ShipwreckSupply { inner } => inner.0.clone(), + Self::ShipwreckTreasure { inner } => inner.0.clone(), + Self::SimpleDungeon { inner } => inner.0.clone(), + Self::SpawnBonusChest { inner } => inner.0.clone(), + Self::StrongholdCorridor { inner } => inner.0.clone(), + Self::StrongholdCrossing { inner } => inner.0.clone(), + Self::StrongholdLibrary { inner } => inner.0.clone(), + Self::UnderwaterRuinBig { inner } => inner.0.clone(), + Self::UnderwaterRuinSmall { inner } => inner.0.clone(), + Self::VillageArmorer { inner } => inner.0.clone(), + Self::VillageButcher { inner } => inner.0.clone(), + Self::VillageCartographer { inner } => inner.0.clone(), + Self::VillageDesertHouse { inner } => inner.0.clone(), + Self::VillageFisher { inner } => inner.0.clone(), + Self::VillageFletcher { inner } => inner.0.clone(), + Self::VillageMason { inner } => inner.0.clone(), + Self::VillagePlainsHouse { inner } => inner.0.clone(), + Self::VillageSavannaHouse { inner } => inner.0.clone(), + Self::VillageShepherd { inner } => inner.0.clone(), + Self::VillageSnowyHouse { inner } => inner.0.clone(), + Self::VillageTaigaHouse { inner } => inner.0.clone(), + Self::VillageTannery { inner } => inner.0.clone(), + Self::VillageTemple { inner } => inner.0.clone(), + Self::VillageToolsmith { inner } => inner.0.clone(), + Self::VillageWeaponsmith { inner } => inner.0.clone(), + Self::WoodlandMansion { inner } => inner.0.clone(), + Self::ArmorStand { inner } => inner.0.clone(), + Self::Axolotl { inner } => inner.0.clone(), + Self::Bat { inner } => inner.0.clone(), + Self::Bee { inner } => inner.0.clone(), + Self::Blaze { inner } => inner.0.clone(), + Self::Cat { inner } => inner.0.clone(), + Self::CaveSpider { inner } => inner.0.clone(), + Self::Chicken { inner } => inner.0.clone(), + Self::Cod { inner } => inner.0.clone(), + Self::Cow { inner } => inner.0.clone(), + Self::Creeper { inner } => inner.0.clone(), + Self::Dolphin { inner } => inner.0.clone(), + Self::Donkey { inner } => inner.0.clone(), + Self::Drowned { inner } => inner.0.clone(), + Self::ElderGuardian { inner } => inner.0.clone(), + Self::EnderDragon { inner } => inner.0.clone(), + Self::Enderman { inner } => inner.0.clone(), + Self::Endermite { inner } => inner.0.clone(), + Self::Evoker { inner } => inner.0.clone(), + Self::Fox { inner } => inner.0.clone(), + Self::Ghast { inner } => inner.0.clone(), + Self::Giant { inner } => inner.0.clone(), + Self::GlowSquid { inner } => inner.0.clone(), + Self::Goat { inner } => inner.0.clone(), + Self::Guardian { inner } => inner.0.clone(), + Self::Hoglin { inner } => inner.0.clone(), + Self::Horse { inner } => inner.0.clone(), + Self::Husk { inner } => inner.0.clone(), + Self::Illusioner { inner } => inner.0.clone(), + Self::IronGolem { inner } => inner.0.clone(), + Self::Llama { inner } => inner.0.clone(), + Self::MagmaCube { inner } => inner.0.clone(), + Self::Mooshroom { inner } => inner.0.clone(), + Self::Mule { inner } => inner.0.clone(), + Self::Ocelot { inner } => inner.0.clone(), + Self::Panda { inner } => inner.0.clone(), + Self::Parrot { inner } => inner.0.clone(), + Self::Phantom { inner } => inner.0.clone(), + Self::Pig { inner } => inner.0.clone(), + Self::Piglin { inner } => inner.0.clone(), + Self::PiglinBrute { inner } => inner.0.clone(), + Self::Pillager { inner } => inner.0.clone(), + Self::Player { inner } => inner.0.clone(), + Self::PolarBear { inner } => inner.0.clone(), + Self::Pufferfish { inner } => inner.0.clone(), + Self::Rabbit { inner } => inner.0.clone(), + Self::Ravager { inner } => inner.0.clone(), + Self::Salmon { inner } => inner.0.clone(), + Self::Shulker { inner } => inner.0.clone(), + Self::Silverfish { inner } => inner.0.clone(), + Self::Skeleton { inner } => inner.0.clone(), + Self::SkeletonHorse { inner } => inner.0.clone(), + Self::Slime { inner } => inner.0.clone(), + Self::SnowGolem { inner } => inner.0.clone(), + Self::Spider { inner } => inner.0.clone(), + Self::Squid { inner } => inner.0.clone(), + Self::Stray { inner } => inner.0.clone(), + Self::Strider { inner } => inner.0.clone(), + Self::TraderLlama { inner } => inner.0.clone(), + Self::TropicalFish { inner } => inner.0.clone(), + Self::Turtle { inner } => inner.0.clone(), + Self::Vex { inner } => inner.0.clone(), + Self::Villager { inner } => inner.0.clone(), + Self::Vindicator { inner } => inner.0.clone(), + Self::WanderingTrader { inner } => inner.0.clone(), + Self::Witch { inner } => inner.0.clone(), + Self::Wither { inner } => inner.0.clone(), + Self::WitherSkeleton { inner } => inner.0.clone(), + Self::Wolf { inner } => inner.0.clone(), + Self::Zoglin { inner } => inner.0.clone(), + Self::Zombie { inner } => inner.0.clone(), + Self::ZombieHorse { inner } => inner.0.clone(), + Self::ZombieVillager { inner } => inner.0.clone(), + Self::ZombifiedPiglin { inner } => inner.0.clone(), + Self::ArmorerGift { inner } => inner.0.clone(), + Self::ButcherGift { inner } => inner.0.clone(), + Self::CartographerGift { inner } => inner.0.clone(), + Self::CatMorningGift { inner } => inner.0.clone(), + Self::ClericGift { inner } => inner.0.clone(), + Self::FarmerGift { inner } => inner.0.clone(), + Self::FishermanGift { inner } => inner.0.clone(), + Self::Fishing { inner } => inner.0.clone(), + Self::FishingFish { inner } => inner.0.clone(), + Self::FishingJunk { inner } => inner.0.clone(), + Self::FishingTreasure { inner } => inner.0.clone(), + Self::FletcherGift { inner } => inner.0.clone(), + Self::LeatherworkerGift { inner } => inner.0.clone(), + Self::LibrarianGift { inner } => inner.0.clone(), + Self::MasonGift { inner } => inner.0.clone(), + Self::ShepherdGift { inner } => inner.0.clone(), + Self::ToolsmithGift { inner } => inner.0.clone(), + Self::WeaponsmithGift { inner } => inner.0.clone(), + Self::SnifferDigging { inner } => inner.0.clone(), + Self::PandaSneeze { inner } => inner.0.clone(), + Self::PiglinBartering { inner } => inner.0.clone(), + Self::TrialChamberKey { inner } => inner.0.clone(), + Self::TrialChamberConsumables { inner } => inner.0.clone(), + Self::OminousTrialChamberKey { inner } => inner.0.clone(), + Self::OminousTrialChamberConsumables { inner } => inner.0.clone(), + Self::TrialChamberItemsToDropWhenOminous { inner } => inner.0.clone(), + Self::ShearingBogged { inner } => inner.0.clone(), + Self::DesertWellArchaeology { inner } => inner.0.clone(), + Self::DesertPyramidArchaeology { inner } => inner.0.clone(), + Self::TrailRuinsArchaeologyCommon { inner } => inner.0.clone(), + Self::TrailRuinsArchaeologyRare { inner } => inner.0.clone(), + Self::OceanRuinWarmArchaeology { inner } => inner.0.clone(), + Self::OceanRuinColdArchaeology { inner } => inner.0.clone(), + Self::Sheep { inner } => inner.0.clone(), + Self::SheepBlack { inner } => inner.0.clone(), + Self::SheepBlue { inner } => inner.0.clone(), + Self::SheepBrown { inner } => inner.0.clone(), + Self::SheepCyan { inner } => inner.0.clone(), + Self::SheepGray { inner } => inner.0.clone(), + Self::SheepGreen { inner } => inner.0.clone(), + Self::SheepLightBlue { inner } => inner.0.clone(), + Self::SheepLightGray { inner } => inner.0.clone(), + Self::SheepLime { inner } => inner.0.clone(), + Self::SheepMagenta { inner } => inner.0.clone(), + Self::SheepOrange { inner } => inner.0.clone(), + Self::SheepPink { inner } => inner.0.clone(), + Self::SheepPurple { inner } => inner.0.clone(), + Self::SheepRed { inner } => inner.0.clone(), + Self::SheepWhite { inner } => inner.0.clone(), + Self::SheepYellow { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Empty { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::AbandonedMineshaft { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BuriedTreasure { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DesertPyramid { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EndCityTreasure { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IglooChest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::JungleTemple { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::JungleTempleDispenser { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NetherBridge { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PillagerOutpost { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BastionTreasure { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BastionOther { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BastionBridge { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BastionHoglinStable { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AncientCity { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AncientCityIceBox { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RuinedPortal { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrialChambersReward { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrialChambersRewardCommon { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrialChambersRewardRare { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrialChambersRewardUnique { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrialChambersRewardOminous { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrialChambersRewardOminousCommon { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrialChambersRewardOminousRare { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrialChambersRewardOminousUnique { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrialChambersSupply { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrialChambersCorridor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrialChambersIntersection { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrialChambersIntersectionBarrel { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrialChambersEntrance { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrialChambersCorridorDispenser { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrialChambersChamberDispenser { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrialChambersWaterDispenser { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrialChambersCorridorPot { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EquipmentTrialChamber { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EquipmentTrialChamberRanged { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EquipmentTrialChamberMelee { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ShipwreckMap { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ShipwreckSupply { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ShipwreckTreasure { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SimpleDungeon { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SpawnBonusChest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrongholdCorridor { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrongholdCrossing { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrongholdLibrary { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::UnderwaterRuinBig { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::UnderwaterRuinSmall { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VillageArmorer { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VillageButcher { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VillageCartographer { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VillageDesertHouse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VillageFisher { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VillageFletcher { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VillageMason { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VillagePlainsHouse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VillageSavannaHouse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VillageShepherd { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VillageSnowyHouse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VillageTaigaHouse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VillageTannery { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VillageTemple { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VillageToolsmith { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VillageWeaponsmith { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WoodlandMansion { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ArmorStand { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Axolotl { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Bat { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Bee { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Blaze { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Cat { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CaveSpider { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Chicken { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Cod { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Cow { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Creeper { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Dolphin { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Donkey { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Drowned { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ElderGuardian { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::EnderDragon { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Enderman { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Endermite { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Evoker { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Fox { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Ghast { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Giant { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::GlowSquid { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Goat { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Guardian { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Hoglin { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Horse { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Husk { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Illusioner { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::IronGolem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Llama { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::MagmaCube { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Mooshroom { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Mule { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Ocelot { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Panda { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Parrot { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Phantom { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Pig { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Piglin { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PiglinBrute { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Pillager { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Player { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::PolarBear { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Pufferfish { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Rabbit { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Ravager { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Salmon { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Shulker { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Silverfish { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Skeleton { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SkeletonHorse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Slime { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SnowGolem { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Spider { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Squid { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Stray { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Strider { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::TraderLlama { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TropicalFish { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Turtle { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Vex { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Villager { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Vindicator { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WanderingTrader { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Witch { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Wither { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::WitherSkeleton { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Wolf { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Zoglin { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Zombie { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ZombieHorse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ZombieVillager { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ZombifiedPiglin { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ArmorerGift { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ButcherGift { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CartographerGift { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CatMorningGift { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ClericGift { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FarmerGift { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FishermanGift { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Fishing { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::FishingFish { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FishingJunk { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FishingTreasure { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FletcherGift { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LeatherworkerGift { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LibrarianGift { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::MasonGift { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ShepherdGift { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ToolsmithGift { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WeaponsmithGift { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SnifferDigging { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PandaSneeze { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PiglinBartering { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrialChamberKey { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrialChamberConsumables { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OminousTrialChamberKey { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OminousTrialChamberConsumables { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrialChamberItemsToDropWhenOminous { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ShearingBogged { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DesertWellArchaeology { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DesertPyramidArchaeology { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrailRuinsArchaeologyCommon { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::TrailRuinsArchaeologyRare { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OceanRuinWarmArchaeology { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::OceanRuinColdArchaeology { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Sheep { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SheepBlack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SheepBlue { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SheepBrown { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SheepCyan { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SheepGray { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SheepGreen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SheepLightBlue { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SheepLightGray { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SheepLime { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SheepMagenta { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SheepOrange { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SheepPink { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SheepPurple { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SheepRed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SheepWhite { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SheepYellow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } impl<'mc> JNIInstantiatable<'mc> for LootTables<'mc> { @@ -74,6 +1910,586 @@ impl<'mc> JNIInstantiatable<'mc> for LootTables<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "EMPTY" => Ok(LootTables::Empty { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ABANDONED_MINESHAFT" => Ok(LootTables::AbandonedMineshaft { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "BURIED_TREASURE" => Ok(LootTables::BuriedTreasure { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "DESERT_PYRAMID" => Ok(LootTables::DesertPyramid { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "END_CITY_TREASURE" => Ok(LootTables::EndCityTreasure { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "IGLOO_CHEST" => Ok(LootTables::IglooChest { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "JUNGLE_TEMPLE" => Ok(LootTables::JungleTemple { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "JUNGLE_TEMPLE_DISPENSER" => Ok(LootTables::JungleTempleDispenser { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "NETHER_BRIDGE" => Ok(LootTables::NetherBridge { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "PILLAGER_OUTPOST" => Ok(LootTables::PillagerOutpost { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "BASTION_TREASURE" => Ok(LootTables::BastionTreasure { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "BASTION_OTHER" => Ok(LootTables::BastionOther { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "BASTION_BRIDGE" => Ok(LootTables::BastionBridge { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "BASTION_HOGLIN_STABLE" => Ok(LootTables::BastionHoglinStable { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ANCIENT_CITY" => Ok(LootTables::AncientCity { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ANCIENT_CITY_ICE_BOX" => Ok(LootTables::AncientCityIceBox { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "RUINED_PORTAL" => Ok(LootTables::RuinedPortal { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBERS_REWARD" => Ok(LootTables::TrialChambersReward { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBERS_REWARD_COMMON" => Ok(LootTables::TrialChambersRewardCommon { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBERS_REWARD_RARE" => Ok(LootTables::TrialChambersRewardRare { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBERS_REWARD_UNIQUE" => Ok(LootTables::TrialChambersRewardUnique { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBERS_REWARD_OMINOUS" => Ok(LootTables::TrialChambersRewardOminous { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBERS_REWARD_OMINOUS_COMMON" => { + Ok(LootTables::TrialChambersRewardOminousCommon { + inner: LootTablesStruct::from_raw(env, obj)?, + }) + } + "TRIAL_CHAMBERS_REWARD_OMINOUS_RARE" => { + Ok(LootTables::TrialChambersRewardOminousRare { + inner: LootTablesStruct::from_raw(env, obj)?, + }) + } + "TRIAL_CHAMBERS_REWARD_OMINOUS_UNIQUE" => { + Ok(LootTables::TrialChambersRewardOminousUnique { + inner: LootTablesStruct::from_raw(env, obj)?, + }) + } + "TRIAL_CHAMBERS_SUPPLY" => Ok(LootTables::TrialChambersSupply { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBERS_CORRIDOR" => Ok(LootTables::TrialChambersCorridor { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBERS_INTERSECTION" => Ok(LootTables::TrialChambersIntersection { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBERS_INTERSECTION_BARREL" => { + Ok(LootTables::TrialChambersIntersectionBarrel { + inner: LootTablesStruct::from_raw(env, obj)?, + }) + } + "TRIAL_CHAMBERS_ENTRANCE" => Ok(LootTables::TrialChambersEntrance { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBERS_CORRIDOR_DISPENSER" => { + Ok(LootTables::TrialChambersCorridorDispenser { + inner: LootTablesStruct::from_raw(env, obj)?, + }) + } + "TRIAL_CHAMBERS_CHAMBER_DISPENSER" => { + Ok(LootTables::TrialChambersChamberDispenser { + inner: LootTablesStruct::from_raw(env, obj)?, + }) + } + "TRIAL_CHAMBERS_WATER_DISPENSER" => Ok(LootTables::TrialChambersWaterDispenser { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBERS_CORRIDOR_POT" => Ok(LootTables::TrialChambersCorridorPot { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "EQUIPMENT_TRIAL_CHAMBER" => Ok(LootTables::EquipmentTrialChamber { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "EQUIPMENT_TRIAL_CHAMBER_RANGED" => Ok(LootTables::EquipmentTrialChamberRanged { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "EQUIPMENT_TRIAL_CHAMBER_MELEE" => Ok(LootTables::EquipmentTrialChamberMelee { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHIPWRECK_MAP" => Ok(LootTables::ShipwreckMap { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHIPWRECK_SUPPLY" => Ok(LootTables::ShipwreckSupply { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHIPWRECK_TREASURE" => Ok(LootTables::ShipwreckTreasure { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SIMPLE_DUNGEON" => Ok(LootTables::SimpleDungeon { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SPAWN_BONUS_CHEST" => Ok(LootTables::SpawnBonusChest { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "STRONGHOLD_CORRIDOR" => Ok(LootTables::StrongholdCorridor { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "STRONGHOLD_CROSSING" => Ok(LootTables::StrongholdCrossing { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "STRONGHOLD_LIBRARY" => Ok(LootTables::StrongholdLibrary { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "UNDERWATER_RUIN_BIG" => Ok(LootTables::UnderwaterRuinBig { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "UNDERWATER_RUIN_SMALL" => Ok(LootTables::UnderwaterRuinSmall { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_ARMORER" => Ok(LootTables::VillageArmorer { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_BUTCHER" => Ok(LootTables::VillageButcher { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_CARTOGRAPHER" => Ok(LootTables::VillageCartographer { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_DESERT_HOUSE" => Ok(LootTables::VillageDesertHouse { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_FISHER" => Ok(LootTables::VillageFisher { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_FLETCHER" => Ok(LootTables::VillageFletcher { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_MASON" => Ok(LootTables::VillageMason { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_PLAINS_HOUSE" => Ok(LootTables::VillagePlainsHouse { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_SAVANNA_HOUSE" => Ok(LootTables::VillageSavannaHouse { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_SHEPHERD" => Ok(LootTables::VillageShepherd { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_SNOWY_HOUSE" => Ok(LootTables::VillageSnowyHouse { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_TAIGA_HOUSE" => Ok(LootTables::VillageTaigaHouse { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_TANNERY" => Ok(LootTables::VillageTannery { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_TEMPLE" => Ok(LootTables::VillageTemple { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_TOOLSMITH" => Ok(LootTables::VillageToolsmith { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGE_WEAPONSMITH" => Ok(LootTables::VillageWeaponsmith { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "WOODLAND_MANSION" => Ok(LootTables::WoodlandMansion { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ARMOR_STAND" => Ok(LootTables::ArmorStand { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "AXOLOTL" => Ok(LootTables::Axolotl { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "BAT" => Ok(LootTables::Bat { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "BEE" => Ok(LootTables::Bee { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "BLAZE" => Ok(LootTables::Blaze { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "CAT" => Ok(LootTables::Cat { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "CAVE_SPIDER" => Ok(LootTables::CaveSpider { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "CHICKEN" => Ok(LootTables::Chicken { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "COD" => Ok(LootTables::Cod { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "COW" => Ok(LootTables::Cow { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "CREEPER" => Ok(LootTables::Creeper { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "DOLPHIN" => Ok(LootTables::Dolphin { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "DONKEY" => Ok(LootTables::Donkey { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "DROWNED" => Ok(LootTables::Drowned { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ELDER_GUARDIAN" => Ok(LootTables::ElderGuardian { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ENDER_DRAGON" => Ok(LootTables::EnderDragon { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ENDERMAN" => Ok(LootTables::Enderman { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ENDERMITE" => Ok(LootTables::Endermite { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "EVOKER" => Ok(LootTables::Evoker { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "FOX" => Ok(LootTables::Fox { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "GHAST" => Ok(LootTables::Ghast { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "GIANT" => Ok(LootTables::Giant { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "GLOW_SQUID" => Ok(LootTables::GlowSquid { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "GOAT" => Ok(LootTables::Goat { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "GUARDIAN" => Ok(LootTables::Guardian { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "HOGLIN" => Ok(LootTables::Hoglin { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "HORSE" => Ok(LootTables::Horse { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "HUSK" => Ok(LootTables::Husk { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ILLUSIONER" => Ok(LootTables::Illusioner { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "IRON_GOLEM" => Ok(LootTables::IronGolem { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "LLAMA" => Ok(LootTables::Llama { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "MAGMA_CUBE" => Ok(LootTables::MagmaCube { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "MOOSHROOM" => Ok(LootTables::Mooshroom { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "MULE" => Ok(LootTables::Mule { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "OCELOT" => Ok(LootTables::Ocelot { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "PANDA" => Ok(LootTables::Panda { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "PARROT" => Ok(LootTables::Parrot { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "PHANTOM" => Ok(LootTables::Phantom { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "PIG" => Ok(LootTables::Pig { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "PIGLIN" => Ok(LootTables::Piglin { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "PIGLIN_BRUTE" => Ok(LootTables::PiglinBrute { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "PILLAGER" => Ok(LootTables::Pillager { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "PLAYER" => Ok(LootTables::Player { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "POLAR_BEAR" => Ok(LootTables::PolarBear { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "PUFFERFISH" => Ok(LootTables::Pufferfish { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "RABBIT" => Ok(LootTables::Rabbit { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "RAVAGER" => Ok(LootTables::Ravager { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SALMON" => Ok(LootTables::Salmon { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHULKER" => Ok(LootTables::Shulker { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SILVERFISH" => Ok(LootTables::Silverfish { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SKELETON" => Ok(LootTables::Skeleton { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SKELETON_HORSE" => Ok(LootTables::SkeletonHorse { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SLIME" => Ok(LootTables::Slime { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SNOW_GOLEM" => Ok(LootTables::SnowGolem { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SPIDER" => Ok(LootTables::Spider { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SQUID" => Ok(LootTables::Squid { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "STRAY" => Ok(LootTables::Stray { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "STRIDER" => Ok(LootTables::Strider { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRADER_LLAMA" => Ok(LootTables::TraderLlama { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TROPICAL_FISH" => Ok(LootTables::TropicalFish { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TURTLE" => Ok(LootTables::Turtle { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VEX" => Ok(LootTables::Vex { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VILLAGER" => Ok(LootTables::Villager { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "VINDICATOR" => Ok(LootTables::Vindicator { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "WANDERING_TRADER" => Ok(LootTables::WanderingTrader { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "WITCH" => Ok(LootTables::Witch { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "WITHER" => Ok(LootTables::Wither { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "WITHER_SKELETON" => Ok(LootTables::WitherSkeleton { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "WOLF" => Ok(LootTables::Wolf { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ZOGLIN" => Ok(LootTables::Zoglin { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ZOMBIE" => Ok(LootTables::Zombie { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ZOMBIE_HORSE" => Ok(LootTables::ZombieHorse { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ZOMBIE_VILLAGER" => Ok(LootTables::ZombieVillager { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ZOMBIFIED_PIGLIN" => Ok(LootTables::ZombifiedPiglin { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "ARMORER_GIFT" => Ok(LootTables::ArmorerGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "BUTCHER_GIFT" => Ok(LootTables::ButcherGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "CARTOGRAPHER_GIFT" => Ok(LootTables::CartographerGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "CAT_MORNING_GIFT" => Ok(LootTables::CatMorningGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "CLERIC_GIFT" => Ok(LootTables::ClericGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "FARMER_GIFT" => Ok(LootTables::FarmerGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "FISHERMAN_GIFT" => Ok(LootTables::FishermanGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "FISHING" => Ok(LootTables::Fishing { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "FISHING_FISH" => Ok(LootTables::FishingFish { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "FISHING_JUNK" => Ok(LootTables::FishingJunk { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "FISHING_TREASURE" => Ok(LootTables::FishingTreasure { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "FLETCHER_GIFT" => Ok(LootTables::FletcherGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "LEATHERWORKER_GIFT" => Ok(LootTables::LeatherworkerGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "LIBRARIAN_GIFT" => Ok(LootTables::LibrarianGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "MASON_GIFT" => Ok(LootTables::MasonGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEPHERD_GIFT" => Ok(LootTables::ShepherdGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TOOLSMITH_GIFT" => Ok(LootTables::ToolsmithGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "WEAPONSMITH_GIFT" => Ok(LootTables::WeaponsmithGift { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SNIFFER_DIGGING" => Ok(LootTables::SnifferDigging { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "PANDA_SNEEZE" => Ok(LootTables::PandaSneeze { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "PIGLIN_BARTERING" => Ok(LootTables::PiglinBartering { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBER_KEY" => Ok(LootTables::TrialChamberKey { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRIAL_CHAMBER_CONSUMABLES" => Ok(LootTables::TrialChamberConsumables { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "OMINOUS_TRIAL_CHAMBER_KEY" => Ok(LootTables::OminousTrialChamberKey { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "OMINOUS_TRIAL_CHAMBER_CONSUMABLES" => { + Ok(LootTables::OminousTrialChamberConsumables { + inner: LootTablesStruct::from_raw(env, obj)?, + }) + } + "TRIAL_CHAMBER_ITEMS_TO_DROP_WHEN_OMINOUS" => { + Ok(LootTables::TrialChamberItemsToDropWhenOminous { + inner: LootTablesStruct::from_raw(env, obj)?, + }) + } + "SHEARING_BOGGED" => Ok(LootTables::ShearingBogged { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "DESERT_WELL_ARCHAEOLOGY" => Ok(LootTables::DesertWellArchaeology { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "DESERT_PYRAMID_ARCHAEOLOGY" => Ok(LootTables::DesertPyramidArchaeology { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRAIL_RUINS_ARCHAEOLOGY_COMMON" => Ok(LootTables::TrailRuinsArchaeologyCommon { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "TRAIL_RUINS_ARCHAEOLOGY_RARE" => Ok(LootTables::TrailRuinsArchaeologyRare { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "OCEAN_RUIN_WARM_ARCHAEOLOGY" => Ok(LootTables::OceanRuinWarmArchaeology { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "OCEAN_RUIN_COLD_ARCHAEOLOGY" => Ok(LootTables::OceanRuinColdArchaeology { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP" => Ok(LootTables::Sheep { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_BLACK" => Ok(LootTables::SheepBlack { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_BLUE" => Ok(LootTables::SheepBlue { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_BROWN" => Ok(LootTables::SheepBrown { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_CYAN" => Ok(LootTables::SheepCyan { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_GRAY" => Ok(LootTables::SheepGray { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_GREEN" => Ok(LootTables::SheepGreen { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_LIGHT_BLUE" => Ok(LootTables::SheepLightBlue { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_LIGHT_GRAY" => Ok(LootTables::SheepLightGray { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_LIME" => Ok(LootTables::SheepLime { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_MAGENTA" => Ok(LootTables::SheepMagenta { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_ORANGE" => Ok(LootTables::SheepOrange { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_PINK" => Ok(LootTables::SheepPink { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_PURPLE" => Ok(LootTables::SheepPurple { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_RED" => Ok(LootTables::SheepRed { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_WHITE" => Ok(LootTables::SheepWhite { + inner: LootTablesStruct::from_raw(env, obj)?, + }), + "SHEEP_YELLOW" => Ok(LootTables::SheepYellow { + inner: LootTablesStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -153,6 +2569,237 @@ impl<'mc> LootTablesStruct<'mc> { } } #[repr(C)] +pub struct LootTable<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for LootTable<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for LootTable<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate LootTable from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/loot/LootTable")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a LootTable object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> LootTable<'mc> { + /// Returns a mutable list of loot generated by this LootTable. + pub fn populate_loot( + &self, + random: impl Into>, + context: impl Into>, + ) -> Result>, Box> { + let sig = + String::from("(Ljava/util/Random;Lorg/bukkit/loot/LootContext;)Ljava/util/Collection;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(random.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(context.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "populateLoot", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::inventory::ItemStack::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Attempt to fill an inventory with this LootTable's loot. + pub fn fill_inventory( + &self, + inventory: impl Into>, + random: impl Into>, + context: impl Into>, + ) -> Result<(), Box> { + let sig = String::from( + "(Lorg/bukkit/inventory/Inventory;Ljava/util/Random;Lorg/bukkit/loot/LootContext;)V", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(inventory.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(random.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(context.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "fillInventory", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Return the namespaced identifier for this object. + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for LootTable<'mc> { + fn into(self) -> crate::Keyed<'mc> { + crate::Keyed::from_raw(&self.jni_ref(), self.1) + .expect("Error converting LootTable into crate::Keyed") + } +} +#[repr(C)] +pub struct Lootable<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Lootable<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Lootable<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Lootable from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/loot/Lootable")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Lootable object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Lootable<'mc> { + /// Set the loot table for a container or entity. + /// + /// To remove a loot table use null. Do not use {@link LootTables#EMPTY} to + /// clear a LootTable. + pub fn set_loot_table( + &self, + table: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/loot/LootTable;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(table.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLootTable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the Loot Table attached to this block or entity. + /// + /// If an block/entity does not have a loot table, this will return null, NOT + /// an empty loot table. + pub fn loot_table( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/loot/LootTable;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLootTable", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::loot::LootTable::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Set the seed used when this Loot Table generates loot. + pub fn set_seed(&self, seed: i64) -> Result<(), Box> { + let sig = String::from("(J)V"); + let val_1 = jni::objects::JValueGen::Long(seed); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSeed", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the Loot Table's seed. + /// + /// The seed is used when generating loot. + pub fn seed(&self) -> Result> { + let sig = String::from("()J"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSeed", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.j()?) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] pub struct LootContext<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, @@ -210,12 +2857,8 @@ impl<'mc> LootContext<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.f()?) } - /// Represents the - /// {@link org.bukkit.enchantments.Enchantment#LOOTING} the - /// {@link #getKiller()} entity has on their equipped item. - /// This value is only set via - /// {@link LootContext.Builder#lootingModifier(int)}. If not set, the - /// {@link #getKiller()} entity's looting level will be used instead. + #[deprecated] + /// Represents the {@link org.bukkit.enchantments.Enchantment#LOOTING} the {@link #getKiller()} entity has on their equipped item. This value is only set via {@link LootContext.Builder#lootingModifier(int)}. If not set, the {@link #getKiller()} entity's looting level will be used instead. pub fn looting_modifier(&self) -> Result> { let sig = String::from("()I"); let res = self.jni_ref().call_method( @@ -344,10 +2987,8 @@ impl<'mc> LootContextBuilder<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Set the {@link org.bukkit.enchantments.Enchantment#LOOTING} - /// level equivalent to use when generating loot. Values less than or - /// equal to 0 will force the {@link LootTable} to only return a single - /// {@link org.bukkit.inventory.ItemStack} per pool. + #[deprecated] + /// Set the {@link org.bukkit.enchantments.Enchantment#LOOTING} level equivalent to use when generating loot. Values less than or equal to 0 will force the {@link LootTable} to only return a single {@link org.bukkit.inventory.ItemStack} per pool. pub fn looting_modifier( &self, modifier: i32, @@ -426,234 +3067,3 @@ impl<'mc> LootContextBuilder<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -#[repr(C)] -pub struct LootTable<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for LootTable<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for LootTable<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate LootTable from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/loot/LootTable")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a LootTable object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> LootTable<'mc> { - /// Returns a mutable list of loot generated by this LootTable. - pub fn populate_loot( - &self, - random: impl Into>, - context: impl Into>, - ) -> Result>, Box> { - let sig = - String::from("(Ljava/util/Random;Lorg/bukkit/loot/LootContext;)Ljava/util/Collection;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(random.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(context.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "populateLoot", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::inventory::ItemStack::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Attempt to fill an inventory with this LootTable's loot. - pub fn fill_inventory( - &self, - inventory: impl Into>, - random: impl Into>, - context: impl Into>, - ) -> Result<(), Box> { - let sig = String::from( - "(Lorg/bukkit/inventory/Inventory;Ljava/util/Random;Lorg/bukkit/loot/LootContext;)V", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(inventory.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(random.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(context.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "fillInventory", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Return the namespaced identifier for this object. - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for LootTable<'mc> { - fn into(self) -> crate::Keyed<'mc> { - crate::Keyed::from_raw(&self.jni_ref(), self.1) - .expect("Error converting LootTable into crate::Keyed") - } -} -#[repr(C)] -pub struct Lootable<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Lootable<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Lootable<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Lootable from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/loot/Lootable")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Lootable object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Lootable<'mc> { - /// Set the loot table for a container or entity. - /// - /// To remove a loot table use null. Do not use {@link LootTables#EMPTY} to - /// clear a LootTable. - pub fn set_loot_table( - &self, - table: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/loot/LootTable;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(table.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setLootTable", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the Loot Table attached to this block or entity. - /// - /// If an block/entity does not have a loot table, this will return null, NOT - /// an empty loot table. - pub fn loot_table( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/loot/LootTable;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLootTable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::loot::LootTable::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - /// Set the seed used when this Loot Table generates loot. - pub fn set_seed(&self, seed: i64) -> Result<(), Box> { - let sig = String::from("(J)V"); - let val_1 = jni::objects::JValueGen::Long(seed); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSeed", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the Loot Table's seed. - /// - /// The seed is used when generating loot. - pub fn seed(&self) -> Result> { - let sig = String::from("()J"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSeed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} diff --git a/blackboxmc-rs-bukkit/src/map/mod.rs b/blackboxmc-rs-bukkit/src/map/mod.rs index f7b522d..9419d12 100644 --- a/blackboxmc-rs-bukkit/src/map/mod.rs +++ b/blackboxmc-rs-bukkit/src/map/mod.rs @@ -3,12 +3,12 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] -pub struct MapCursor<'mc>( +pub struct MinecraftFont<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for MapCursor<'mc> { +impl<'mc> JNIRaw<'mc> for MinecraftFont<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -16,18 +16,18 @@ impl<'mc> JNIRaw<'mc> for MapCursor<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for MapCursor<'mc> { +impl<'mc> JNIInstantiatable<'mc> for MinecraftFont<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate MapCursor from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate MinecraftFont from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/map/MapCursor")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/map/MinecraftFont")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a MapCursor object, got {}", + "Invalid argument passed. Expected a MinecraftFont object, got {}", name ) .into()) @@ -37,220 +37,374 @@ impl<'mc> JNIInstantiatable<'mc> for MapCursor<'mc> { } } -impl<'mc> MapCursor<'mc> { - /// Initialize the map cursor. +impl<'mc> MinecraftFont<'mc> { + /// Initialize a new MinecraftFont. pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - x: i8, - y: i8, - direction: i8, - val_type: impl Into>, - visible: bool, - caption: std::option::Option>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "B"; - let val_1 = jni::objects::JValueGen::Byte(x); - args.push(val_1); - sig += "B"; - let val_2 = jni::objects::JValueGen::Byte(y); - args.push(val_2); - sig += "B"; - let val_3 = jni::objects::JValueGen::Byte(direction); - args.push(val_3); - sig += "Lorg/bukkit/map/MapCursor/Type;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - args.push(val_4); - sig += "Z"; - let val_5 = jni::objects::JValueGen::Bool(visible.into()); - args.push(val_5); - if let Some(a) = caption { - sig += "Ljava/lang/String;"; - let val_6 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(a.into())?, - )); - args.push(val_6); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/map/MapCursor"); + ) -> Result, Box> { + let sig = String::from("()V"); + let cls = jni.find_class("org/bukkit/map/MinecraftFont"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.new_object(cls, sig.as_str(), vec![]); let res = jni.translate_error_no_gen(res)?; - crate::map::MapCursor::from_raw(&jni, res) + crate::map::MinecraftFont::from_raw(&jni, res) } - /// Get the X position of this cursor. - pub fn x(&self) -> Result> { - let sig = String::from("()B"); + // SUPER CLASS: org.bukkit.map.MapFont ( []) + /// Set the sprite for a given character. + pub fn set_char( + &self, + ch: u16, + sprite: impl Into>, + ) -> Result<(), Box> { + let temp_clone = crate::map::MapFont::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::map::MapFont = temp_clone.into(); + real.set_char(ch, sprite) + } + /// Get the sprite for a given character. + pub fn get_char( + &self, + ch: u16, + ) -> Result>, Box> { + let temp_clone = crate::map::MapFont::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::map::MapFont = temp_clone.into(); + real.get_char(ch) + } + /// Get the width of the given text as it would be rendered using this + /// font. + pub fn get_width(&self, text: impl Into) -> Result> { + let temp_clone = crate::map::MapFont::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::map::MapFont = temp_clone.into(); + real.get_width(text) + } + /// Get the height of this font. + pub fn height(&self) -> Result> { + let temp_clone = crate::map::MapFont::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::map::MapFont = temp_clone.into(); + real.height() + } + /// Check whether the given text is valid. + pub fn is_valid(&self, text: impl Into) -> Result> { + let temp_clone = crate::map::MapFont::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::map::MapFont = temp_clone.into(); + real.is_valid(text) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for MinecraftFont<'mc> { + fn into(self) -> crate::map::MapFont<'mc> { + crate::map::MapFont::from_raw(&self.jni_ref(), self.1) + .expect("Error converting MinecraftFont into crate::map::MapFont") + } +} +#[repr(C)] +pub struct MapView<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for MapView<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for MapView<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate MapView from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/map/MapView")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a MapView object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> MapView<'mc> { + /// Get the ID of this map item for use with {@link MapMeta}. + pub fn id(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getId", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) + Ok(res.i()?) } - /// Get the Y position of this cursor. - pub fn y(&self) -> Result> { - let sig = String::from("()B"); + /// Check whether this map is virtual. A map is virtual if its lowermost + /// MapRenderer is plugin-provided. + pub fn is_virtual(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) - } - /// Get the direction of this cursor. - pub fn direction(&self) -> Result> { - let sig = String::from("()B"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isVirtual", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) + Ok(res.z()?) } - /// Get the type of this cursor. - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/map/MapCursor/Type;"); + /// Get the scale of this map. + pub fn scale(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/map/MapView/Scale;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getScale", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::map::MapCursorType::from_raw(&self.jni_ref(), unsafe { + crate::map::MapViewScale::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - #[deprecated] - /// Get the type of this cursor. - pub fn raw_type(&self) -> Result> { - let sig = String::from("()B"); + /// Set the scale of this map. + pub fn set_scale( + &self, + scale: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/map/MapView/Scale;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(scale.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setScale", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the center X position of this map. + pub fn center_x(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getRawType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getCenterX", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) + Ok(res.i()?) } - /// Get the visibility status of this cursor. - pub fn is_visible(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isVisible", sig.as_str(), vec![]); + /// Get the center Z position of this map. + pub fn center_z(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCenterZ", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Set the X position of this cursor. - pub fn set_x(&self, x: i8) -> Result<(), Box> { - let sig = String::from("(B)V"); - let val_1 = jni::objects::JValueGen::Byte(x); + /// Set the center X position of this map. + pub fn set_center_x(&self, x: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(x); let res = self.jni_ref().call_method( &self.jni_object(), - "setX", + "setCenterX", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Set the Y position of this cursor. - pub fn set_y(&self, y: i8) -> Result<(), Box> { - let sig = String::from("(B)V"); - let val_1 = jni::objects::JValueGen::Byte(y); + /// Set the center Z position of this map. + pub fn set_center_z(&self, z: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(z); let res = self.jni_ref().call_method( &self.jni_object(), - "setY", + "setCenterZ", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Set the direction of this cursor. - pub fn set_direction(&self, direction: i8) -> Result<(), Box> { - let sig = String::from("(B)V"); - let val_1 = jni::objects::JValueGen::Byte(direction); + /// Get the world that this map is associated with. Primarily used by the + /// internal renderer, but may be used by external renderers. May return + /// null if the world the map is associated with is not loaded. + pub fn world(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/World;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::World::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Set the world that this map is associated with. The world is used by + /// the internal renderer, and may also be used by external renderers. + pub fn set_world( + &self, + world: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/World;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(world.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setDirection", + "setWorld", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Set the type of this cursor. - pub fn set_type( + /// Get a list of MapRenderers currently in effect. + pub fn renderers( &self, - val_type: impl Into>, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRenderers", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::map::MapRenderer::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Add a renderer to this map. + pub fn add_renderer( + &self, + renderer: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/map/MapCursor/Type;)V"); + let sig = String::from("(Lorg/bukkit/map/MapRenderer;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(renderer.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setType", + "addRenderer", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - /// Set the type of this cursor. - pub fn set_raw_type(&self, val_type: i8) -> Result<(), Box> { - let sig = String::from("(B)V"); - let val_1 = jni::objects::JValueGen::Byte(val_type); + /// Remove a renderer from this map. + pub fn remove_renderer( + &self, + renderer: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/map/MapRenderer;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(renderer.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setRawType", + "removeRenderer", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Set the visibility status of this cursor. - pub fn set_visible(&self, visible: bool) -> Result<(), Box> { + /// Gets whether a position cursor should be shown when the map is near its + /// center. + pub fn is_tracking_position(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isTrackingPosition", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets whether a position cursor should be shown when the map is near its + /// center. + pub fn set_tracking_position( + &self, + tracking_position: bool, + ) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(visible.into()); + let val_1 = jni::objects::JValueGen::Bool(tracking_position.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setVisible", + "setTrackingPosition", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the caption on this cursor. - pub fn caption(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCaption", sig.as_str(), vec![]); + /// Whether the map will show a smaller position cursor (true), or no + /// position cursor (false) when cursor is outside of map's range. + pub fn is_unlimited_tracking(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isUnlimitedTracking", + sig.as_str(), + vec![], + ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(res.z()?) } - /// Sets the caption on this cursor. - pub fn set_caption( + /// Whether the map will show a smaller position cursor (true), or no + /// position cursor (false) when cursor is outside of map's range. + pub fn set_unlimited_tracking( &self, - caption: impl Into, + unlimited: bool, ) -> Result<(), Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(caption.into())?, - )); + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(unlimited.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setCaption", + "setUnlimitedTracking", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets whether the map is locked or not. + /// A locked map may not be explored further. + pub fn is_locked(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isLocked", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets whether the map is locked or not. + /// A locked map may not be explored further. + pub fn set_locked(&self, locked: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(locked.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setLocked", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -263,25 +417,49 @@ impl<'mc> MapCursor<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum MapCursorType<'mc> {} -impl<'mc> std::fmt::Display for MapCursorType<'mc> { +pub enum MapViewScale<'mc> { + Closest { inner: MapViewScaleStruct<'mc> }, + Close { inner: MapViewScaleStruct<'mc> }, + Normal { inner: MapViewScaleStruct<'mc> }, + Far { inner: MapViewScaleStruct<'mc> }, + Farthest { inner: MapViewScaleStruct<'mc> }, +} +impl<'mc> std::fmt::Display for MapViewScale<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + MapViewScale::Closest { .. } => f.write_str("CLOSEST"), + MapViewScale::Close { .. } => f.write_str("CLOSE"), + MapViewScale::Normal { .. } => f.write_str("NORMAL"), + MapViewScale::Far { .. } => f.write_str("FAR"), + MapViewScale::Farthest { .. } => f.write_str("FARTHEST"), + } + } +} +impl<'mc> std::ops::Deref for MapViewScale<'mc> { + type Target = MapViewScaleStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + MapViewScale::Closest { inner } => inner, + MapViewScale::Close { inner } => inner, + MapViewScale::Normal { inner } => inner, + MapViewScale::Far { inner } => inner, + MapViewScale::Farthest { inner } => inner, + } } } -impl<'mc> MapCursorType<'mc> { +impl<'mc> MapViewScale<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/map/MapCursor/Type"); + let cls = env.find_class("org/bukkit/map/MapView/Scale"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/map/MapCursor/Type;", + "(Ljava/lang/String;)Lorg/bukkit/map/MapView/Scale;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -293,37 +471,65 @@ impl<'mc> MapCursorType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "CLOSEST" => Ok(MapViewScale::Closest { + inner: MapViewScaleStruct::from_raw(env, obj)?, + }), + "CLOSE" => Ok(MapViewScale::Close { + inner: MapViewScaleStruct::from_raw(env, obj)?, + }), + "NORMAL" => Ok(MapViewScale::Normal { + inner: MapViewScaleStruct::from_raw(env, obj)?, + }), + "FAR" => Ok(MapViewScale::Far { + inner: MapViewScaleStruct::from_raw(env, obj)?, + }), + "FARTHEST" => Ok(MapViewScale::Farthest { + inner: MapViewScaleStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } #[repr(C)] -pub struct MapCursorTypeStruct<'mc>( +pub struct MapViewScaleStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for MapCursorType<'mc> { +impl<'mc> JNIRaw<'mc> for MapViewScale<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Closest { inner } => inner.0.clone(), + Self::Close { inner } => inner.0.clone(), + Self::Normal { inner } => inner.0.clone(), + Self::Far { inner } => inner.0.clone(), + Self::Farthest { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Closest { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Close { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Normal { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Far { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Farthest { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for MapCursorType<'mc> { +impl<'mc> JNIInstantiatable<'mc> for MapViewScale<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate MapCursorType from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate MapViewScale from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/map/MapCursor/Type")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/map/MapView/Scale")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a MapCursorType object, got {}", + "Invalid argument passed. Expected a MapViewScale object, got {}", name ) .into()) @@ -335,13 +541,28 @@ impl<'mc> JNIInstantiatable<'mc> for MapCursorType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "CLOSEST" => Ok(MapViewScale::Closest { + inner: MapViewScaleStruct::from_raw(env, obj)?, + }), + "CLOSE" => Ok(MapViewScale::Close { + inner: MapViewScaleStruct::from_raw(env, obj)?, + }), + "NORMAL" => Ok(MapViewScale::Normal { + inner: MapViewScaleStruct::from_raw(env, obj)?, + }), + "FAR" => Ok(MapViewScale::Far { + inner: MapViewScaleStruct::from_raw(env, obj)?, + }), + "FARTHEST" => Ok(MapViewScale::Farthest { + inner: MapViewScaleStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } } } -impl<'mc> JNIRaw<'mc> for MapCursorTypeStruct<'mc> { +impl<'mc> JNIRaw<'mc> for MapViewScaleStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -349,20 +570,20 @@ impl<'mc> JNIRaw<'mc> for MapCursorTypeStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for MapCursorTypeStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for MapViewScaleStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate MapCursorTypeStruct from null object.").into(), + eyre::eyre!("Tried to instantiate MapViewScaleStruct from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/map/MapCursor/Type")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/map/MapView/Scale")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a MapCursorTypeStruct object, got {}", + "Invalid argument passed. Expected a MapViewScaleStruct object, got {}", name ) .into()) @@ -372,31 +593,20 @@ impl<'mc> JNIInstantiatable<'mc> for MapCursorTypeStruct<'mc> { } } -impl<'mc> MapCursorTypeStruct<'mc> { +impl<'mc> MapViewScaleStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/map/MapCursor/Type;"); - let cls = jni.find_class("org/bukkit/map/MapCursor/Type"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/map/MapView/Scale;"); + let cls = jni.find_class("org/bukkit/map/MapView/Scale"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::map::MapCursorType::from_raw(&jni, obj) - } - - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + crate::map::MapViewScale::from_raw(&jni, obj) } #[deprecated] - /// Gets the internal value of the cursor. + /// Get the raw value of this scale level. pub fn value(&self) -> Result> { let sig = String::from("()B"); let res = self @@ -405,29 +615,6 @@ impl<'mc> MapCursorTypeStruct<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.b()?) } - #[deprecated] - /// Get a cursor by its internal value. - pub fn by_value( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - value: i8, - ) -> Result>, Box> { - let sig = String::from("(B)Lorg/bukkit/map/MapCursor/Type;"); - let val_1 = jni::objects::JValueGen::Byte(value); - let cls = jni.find_class("org/bukkit/map/MapCursor/Type"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "byValue", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::map::MapCursorType::from_raw(&jni, obj)?)) - } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; @@ -660,12 +847,12 @@ impl<'mc> MapPaletteMapColorCache<'mc> { } } #[repr(C)] -pub struct MinecraftFont<'mc>( +pub struct MapFont<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for MinecraftFont<'mc> { +impl<'mc> JNIRaw<'mc> for MapFont<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -673,18 +860,18 @@ impl<'mc> JNIRaw<'mc> for MinecraftFont<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for MinecraftFont<'mc> { +impl<'mc> JNIInstantiatable<'mc> for MapFont<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate MinecraftFont from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate MapFont from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/map/MinecraftFont")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/map/MapFont")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a MinecraftFont object, got {}", + "Invalid argument passed. Expected a MapFont object, got {}", name ) .into()) @@ -694,66 +881,101 @@ impl<'mc> JNIInstantiatable<'mc> for MinecraftFont<'mc> { } } -impl<'mc> MinecraftFont<'mc> { - /// Initialize a new MinecraftFont. +impl<'mc> MapFont<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { + ) -> Result, Box> { let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/map/MinecraftFont"); + let cls = jni.find_class("org/bukkit/map/MapFont"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), vec![]); let res = jni.translate_error_no_gen(res)?; - crate::map::MinecraftFont::from_raw(&jni, res) + crate::map::MapFont::from_raw(&jni, res) } - // SUPER CLASS: org.bukkit.map.MapFont ( []) /// Set the sprite for a given character. pub fn set_char( &self, ch: u16, sprite: impl Into>, ) -> Result<(), Box> { - let temp_clone = crate::map::MapFont::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::map::MapFont = temp_clone.into(); - real.set_char(ch, sprite) + let sig = String::from("(CLorg/bukkit/map/MapFont/CharacterSprite;)V"); + let val_1 = jni::objects::JValueGen::Char(ch); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sprite.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setChar", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } /// Get the sprite for a given character. pub fn get_char( &self, ch: u16, ) -> Result>, Box> { - let temp_clone = crate::map::MapFont::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::map::MapFont = temp_clone.into(); - real.get_char(ch) + let sig = String::from("(C)Lorg/bukkit/map/MapFont/CharacterSprite;"); + let val_1 = jni::objects::JValueGen::Char(ch); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getChar", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::map::MapFontCharacterSprite::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } /// Get the width of the given text as it would be rendered using this /// font. pub fn get_width(&self, text: impl Into) -> Result> { - let temp_clone = crate::map::MapFont::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::map::MapFont = temp_clone.into(); - real.get_width(text) + let sig = String::from("(Ljava/lang/String;)I"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(text.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getWidth", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } /// Get the height of this font. pub fn height(&self) -> Result> { - let temp_clone = crate::map::MapFont::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::map::MapFont = temp_clone.into(); - real.height() + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } /// Check whether the given text is valid. pub fn is_valid(&self, text: impl Into) -> Result> { - let temp_clone = crate::map::MapFont::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::map::MapFont = temp_clone.into(); - real.is_valid(text) + let sig = String::from("(Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(text.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isValid", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -761,19 +983,13 @@ impl<'mc> MinecraftFont<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for MinecraftFont<'mc> { - fn into(self) -> crate::map::MapFont<'mc> { - crate::map::MapFont::from_raw(&self.jni_ref(), self.1) - .expect("Error converting MinecraftFont into crate::map::MapFont") - } -} #[repr(C)] -pub struct MapCursorCollection<'mc>( +pub struct MapFontCharacterSprite<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for MapCursorCollection<'mc> { +impl<'mc> JNIRaw<'mc> for MapFontCharacterSprite<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -781,20 +997,21 @@ impl<'mc> JNIRaw<'mc> for MapCursorCollection<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for MapCursorCollection<'mc> { +impl<'mc> JNIInstantiatable<'mc> for MapFontCharacterSprite<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate MapCursorCollection from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate MapFontCharacterSprite from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/map/MapCursorCollection")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/map/MapFont/CharacterSprite")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a MapCursorCollection object, got {}", + "Invalid argument passed. Expected a MapFontCharacterSprite object, got {}", name ) .into()) @@ -804,127 +1021,79 @@ impl<'mc> JNIInstantiatable<'mc> for MapCursorCollection<'mc> { } } -impl<'mc> MapCursorCollection<'mc> { +impl<'mc> MapFontCharacterSprite<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/map/MapCursorCollection"); + width: i32, + height: i32, + data: bool, + ) -> Result, Box> { + let sig = String::from("(IIZ)V"); + let val_1 = jni::objects::JValueGen::Int(width); + let val_2 = jni::objects::JValueGen::Int(height); + let val_3 = jni::objects::JValueGen::Bool(data.into()); + let cls = jni.find_class("org/bukkit/map/MapFont/CharacterSprite"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), vec![]); - let res = jni.translate_error_no_gen(res)?; - crate::map::MapCursorCollection::from_raw(&jni, res) - } - /// Get the amount of cursors in this collection. - pub fn size(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "size", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Get a cursor from this collection. - pub fn get_cursor( - &self, - index: i32, - ) -> Result, Box> { - let sig = String::from("(I)Lorg/bukkit/map/MapCursor;"); - let val_1 = jni::objects::JValueGen::Int(index); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCursor", + let res = jni.new_object( + cls, sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); - let res = self.jni_ref().translate_error(res)?; - crate::map::MapCursor::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let res = jni.translate_error_no_gen(res)?; + crate::map::MapFontCharacterSprite::from_raw(&jni, res) } - /// Remove a cursor from the collection. - pub fn remove_cursor( - &self, - cursor: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/map/MapCursor;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(cursor.into().jni_object().clone()) - }); + /// Get the value of a pixel of the character. + pub fn get(&self, row: i32, col: i32) -> Result> { + let sig = String::from("(II)Z"); + let val_1 = jni::objects::JValueGen::Int(row); + let val_2 = jni::objects::JValueGen::Int(col); let res = self.jni_ref().call_method( &self.jni_object(), - "removeCursor", + "get", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - #[deprecated] - /// Add a cursor to the collection. - pub fn add_cursor( - &self, - x: i32, - y: std::option::Option, - direction: std::option::Option, - val_type: std::option::Option, - visible: std::option::Option, - caption: std::option::Option>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(x); - args.push(val_1); - if let Some(a) = y { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); - args.push(val_2); - } - if let Some(a) = direction { - sig += "B"; - let val_3 = jni::objects::JValueGen::Byte(a); - args.push(val_3); - } - if let Some(a) = val_type { - sig += "B"; - let val_4 = jni::objects::JValueGen::Byte(a); - args.push(val_4); - } - if let Some(a) = visible { - sig += "Z"; - let val_5 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_5); - } - if let Some(a) = caption { - sig += "Ljava/lang/String;"; - let val_6 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, - )); - args.push(val_6); - } - sig += ")Lorg/bukkit/map/MapCursor;"; + /// Get the width of the character sprite. + pub fn width(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "addCursor", sig.as_str(), args); + .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::map::MapCursor::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + Ok(res.i()?) + } + /// Get the height of the character sprite. + pub fn height(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } } #[repr(C)] -pub struct MapRenderer<'mc>( +pub struct MapCursor<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for MapRenderer<'mc> { +impl<'mc> JNIRaw<'mc> for MapCursor<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -932,18 +1101,18 @@ impl<'mc> JNIRaw<'mc> for MapRenderer<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for MapRenderer<'mc> { +impl<'mc> JNIInstantiatable<'mc> for MapCursor<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate MapRenderer from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate MapCursor from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/map/MapRenderer")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/map/MapCursor")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a MapRenderer object, got {}", + "Invalid argument passed. Expected a MapCursor object, got {}", name ) .into()) @@ -953,58 +1122,220 @@ impl<'mc> JNIInstantiatable<'mc> for MapRenderer<'mc> { } } -impl<'mc> MapRenderer<'mc> { - pub fn from_extendable( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - plugin: &'mc crate::plugin::Plugin, - address: i32, - lib_name: String, - name: String, - ) -> Result> { - let obj = unsafe { plugin.new_extendable(address, "MapRenderer", name, lib_name) }?; - Self::from_raw(env, obj) - } - /// Initialize the map renderer base with the given contextual status. +impl<'mc> MapCursor<'mc> { + /// Initialize the map cursor. pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - contextual: std::option::Option, - ) -> Result, Box> { + x: i8, + y: i8, + direction: i8, + val_type: impl Into>, + visible: bool, + caption: std::option::Option>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = contextual { - sig += "Z"; - let val_1 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_1); + sig += "B"; + let val_1 = jni::objects::JValueGen::Byte(x); + args.push(val_1); + sig += "B"; + let val_2 = jni::objects::JValueGen::Byte(y); + args.push(val_2); + sig += "B"; + let val_3 = jni::objects::JValueGen::Byte(direction); + args.push(val_3); + sig += "Lorg/bukkit/map/MapCursor/Type;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + args.push(val_4); + sig += "Z"; + let val_5 = jni::objects::JValueGen::Bool(visible.into()); + args.push(val_5); + if let Some(a) = caption { + sig += "Ljava/lang/String;"; + let val_6 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(a.into())?, + )); + args.push(val_6); } sig += ")V"; - let cls = jni.find_class("org/bukkit/map/MapRenderer"); + let cls = jni.find_class("org/bukkit/map/MapCursor"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::map::MapRenderer::from_raw(&jni, res) + crate::map::MapCursor::from_raw(&jni, res) } - /// Get whether the renderer is contextual, i.e. has different canvases for - /// different players. - pub fn is_contextual(&self) -> Result> { - let sig = String::from("()Z"); + /// Get the X position of this cursor. + pub fn x(&self) -> Result> { + let sig = String::from("()B"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.b()?) + } + /// Get the Y position of this cursor. + pub fn y(&self) -> Result> { + let sig = String::from("()B"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.b()?) + } + /// Get the direction of this cursor. + pub fn direction(&self) -> Result> { + let sig = String::from("()B"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isContextual", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.b()?) + } + /// Get the type of this cursor. + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/map/MapCursor/Type;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::map::MapCursorType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + #[deprecated] + /// Get the type of this cursor. + pub fn raw_type(&self) -> Result> { + let sig = String::from("()B"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRawType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.b()?) + } + /// Get the visibility status of this cursor. + pub fn is_visible(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isVisible", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Initialize this MapRenderer for the given map. - pub fn initialize( + /// Set the X position of this cursor. + pub fn set_x(&self, x: i8) -> Result<(), Box> { + let sig = String::from("(B)V"); + let val_1 = jni::objects::JValueGen::Byte(x); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setX", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Set the Y position of this cursor. + pub fn set_y(&self, y: i8) -> Result<(), Box> { + let sig = String::from("(B)V"); + let val_1 = jni::objects::JValueGen::Byte(y); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setY", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Set the direction of this cursor. + pub fn set_direction(&self, direction: i8) -> Result<(), Box> { + let sig = String::from("(B)V"); + let val_1 = jni::objects::JValueGen::Byte(direction); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDirection", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Set the type of this cursor. + pub fn set_type( &self, - map: impl Into>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/map/MapView;)V"); + let sig = String::from("(Lorg/bukkit/map/MapCursor/Type;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(map.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "initialize", + "setType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] + /// Set the type of this cursor. + pub fn set_raw_type(&self, val_type: i8) -> Result<(), Box> { + let sig = String::from("(B)V"); + let val_1 = jni::objects::JValueGen::Byte(val_type); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRawType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Set the visibility status of this cursor. + pub fn set_visible(&self, visible: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(visible.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setVisible", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the caption on this cursor. + pub fn caption(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCaption", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Sets the caption on this cursor. + pub fn set_caption( + &self, + caption: impl Into, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(caption.into())?, + )); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setCaption", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -1018,12 +1349,12 @@ impl<'mc> MapRenderer<'mc> { } } #[repr(C)] -pub struct MapCanvas<'mc>( +pub struct MapCursorType<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for MapCanvas<'mc> { +impl<'mc> JNIRaw<'mc> for MapCursorType<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1031,18 +1362,18 @@ impl<'mc> JNIRaw<'mc> for MapCanvas<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for MapCanvas<'mc> { +impl<'mc> JNIInstantiatable<'mc> for MapCursorType<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate MapCanvas from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate MapCursorType from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/map/MapCanvas")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/map/MapCursor/Type")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a MapCanvas object, got {}", + "Invalid argument passed. Expected a MapCursorType object, got {}", name ) .into()) @@ -1052,254 +1383,104 @@ impl<'mc> JNIInstantiatable<'mc> for MapCanvas<'mc> { } } -impl<'mc> MapCanvas<'mc> { - /// Get the map this canvas is attached to. - pub fn map_view(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/map/MapView;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMapView", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::map::MapView::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the cursor collection associated with this canvas. - pub fn cursors( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/map/MapCursorCollection;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCursors", sig.as_str(), vec![]); +impl<'mc> MapCursorType<'mc> { + #[deprecated] + /// Gets the internal value of the cursor. + pub fn value(&self) -> Result> { + let sig = String::from("()B"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getValue", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::map::MapCursorCollection::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.b()?) } - /// Set the cursor collection associated with this canvas. This does not - /// usually need to be called since a MapCursorCollection is already - /// provided. - pub fn set_cursors( - &self, - cursors: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/map/MapCursorCollection;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(cursors.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCursors", + #[deprecated] + /// Get a cursor by its internal value. + pub fn by_value( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + value: i8, + ) -> Result>, Box> { + let sig = String::from("(B)Lorg/bukkit/map/MapCursor/Type;"); + let val_1 = jni::objects::JValueGen::Byte(value); + let cls = jni.find_class("org/bukkit/map/MapCursor/Type"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "byValue", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get a pixel from the canvas. - /// If no color is set at the given position for this canvas, then null is - /// returned and the color returned by {@link #getBasePixelColor(int, int)} - /// is shown on the map. - pub fn get_pixel_color( - &self, - x: i32, - y: i32, - ) -> Result, Box> { - let sig = String::from("(II)Ljava/awt/Color;"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(y); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPixelColor", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; + let res = jni.translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - let r = self.jni_ref().call_method( - unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }, - "getRed", - "(V)I", - vec![], - ); - let r = self.jni_ref().translate_error(r)?.i()? as u8; - let g = self.jni_ref().call_method( - unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }, - "getGreen", - "(V)I", - vec![], - ); - let g = self.jni_ref().translate_error(g)?.i()? as u8; - let b = self.jni_ref().call_method( - unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }, - "getBlue", - "(V)I", - vec![], - ); - let b = self.jni_ref().translate_error(b)?.i()? as u8; - Ok(Some((r, g, b))) + let obj = res.l()?; + Ok(Some(crate::map::MapCursorType::from_raw(&jni, obj)?)) } - /// Get a pixel from the layers below this canvas. - pub fn get_base_pixel_color( + #[deprecated] + + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/map/MapCursor/Type;"); + let cls = jni.find_class("org/bukkit/map/MapCursor/Type"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::map::MapCursorType::from_raw(&jni, obj) + } + #[deprecated] + + pub fn compare_to( &self, - x: i32, - y: i32, - ) -> Result<(u8, u8, u8), Box> { - let sig = String::from("(II)Ljava/awt/Color;"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(y); + other: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(LT;)I"); + let val_1 = jni::objects::JValueGen::Object(other); let res = self.jni_ref().call_method( &self.jni_object(), - "getBasePixelColor", + "compareTo", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - let r = self.jni_ref().call_method( - unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }, - "getRed", - "(V)I", - vec![], - ); - let r = self.jni_ref().translate_error(r)?.i()? as u8; - let g = self.jni_ref().call_method( - unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }, - "getGreen", - "(V)I", - vec![], - ); - let g = self.jni_ref().translate_error(g)?.i()? as u8; - let b = self.jni_ref().call_method( - unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }, - "getBlue", - "(V)I", - vec![], - ); - let b = self.jni_ref().translate_error(b)?.i()? as u8; - Ok((r, g, b)) + Ok(res.i()?) } #[deprecated] - /// Draw a pixel to the canvas. - pub fn set_pixel(&self, x: i32, y: i32, color: i8) -> Result<(), Box> { - let sig = String::from("(IIB)V"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(y); - let val_3 = jni::objects::JValueGen::Byte(color); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPixel", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "name", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } #[deprecated] - /// Get a pixel from the canvas. - pub fn get_pixel(&self, x: i32, y: i32) -> Result> { - let sig = String::from("(II)B"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(y); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPixel", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + + pub fn ordinal(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "ordinal", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) + Ok(res.i()?) } - #[deprecated] - /// Get a pixel from the layers below this canvas. - pub fn get_base_pixel(&self, x: i32, y: i32) -> Result> { - let sig = String::from("(II)B"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(y); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getBasePixel", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + /// Return the namespaced identifier for this object. + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) - } - /// Draw an image to the map. The image will be clipped if necessary. - pub fn draw_image( - &self, - x: i32, - y: i32, - image: jni::objects::JObject<'mc>, - ) -> Result<(), Box> { - let sig = String::from("(IILjava/awt/Image;)V"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(y); - let val_3 = jni::objects::JValueGen::Object(image); - let res = self.jni_ref().call_method( - &self.jni_object(), - "drawImage", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Render text to the map using fancy formatting. Newline (\n) characters - /// will move down one line and return to the original column, and the text - /// color can be changed using sequences such as "§12;", replacing 12 with - /// the palette index of the color (see {@link MapPalette}). - pub fn draw_text( - &self, - x: i32, - y: i32, - font: impl Into>, - text: impl Into, - ) -> Result<(), Box> { - let sig = String::from("(IILorg/bukkit/map/MapFont;Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Int(x); - let val_2 = jni::objects::JValueGen::Int(y); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(font.into().jni_object().clone()) - }); - let val_4 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(text.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "drawText", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1307,13 +1488,25 @@ impl<'mc> MapCanvas<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for MapCursorType<'mc> { + fn into(self) -> crate::util::OldEnum<'mc> { + crate::util::OldEnum::from_raw(&self.jni_ref(), self.1) + .expect("Error converting MapCursorType into crate::util::OldEnum") + } +} +impl<'mc> Into> for MapCursorType<'mc> { + fn into(self) -> crate::Keyed<'mc> { + crate::Keyed::from_raw(&self.jni_ref(), self.1) + .expect("Error converting MapCursorType into crate::Keyed") + } +} #[repr(C)] -pub struct MapFont<'mc>( +pub struct MapCursorCollection<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for MapFont<'mc> { +impl<'mc> JNIRaw<'mc> for MapCursorCollection<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1321,18 +1514,20 @@ impl<'mc> JNIRaw<'mc> for MapFont<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for MapFont<'mc> { +impl<'mc> JNIInstantiatable<'mc> for MapCursorCollection<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate MapFont from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate MapCursorCollection from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/map/MapFont")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/map/MapCursorCollection")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a MapFont object, got {}", + "Invalid argument passed. Expected a MapCursorCollection object, got {}", name ) .into()) @@ -1342,101 +1537,113 @@ impl<'mc> JNIInstantiatable<'mc> for MapFont<'mc> { } } -impl<'mc> MapFont<'mc> { +impl<'mc> MapCursorCollection<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { + ) -> Result, Box> { let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/map/MapFont"); + let cls = jni.find_class("org/bukkit/map/MapCursorCollection"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), vec![]); let res = jni.translate_error_no_gen(res)?; - crate::map::MapFont::from_raw(&jni, res) + crate::map::MapCursorCollection::from_raw(&jni, res) } - /// Set the sprite for a given character. - pub fn set_char( - &self, - ch: u16, - sprite: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(CLorg/bukkit/map/MapFont/CharacterSprite;)V"); - let val_1 = jni::objects::JValueGen::Char(ch); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sprite.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setChar", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + /// Get the amount of cursors in this collection. + pub fn size(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "size", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Get the sprite for a given character. - pub fn get_char( + /// Get a cursor from this collection. + pub fn get_cursor( &self, - ch: u16, - ) -> Result>, Box> { - let sig = String::from("(C)Lorg/bukkit/map/MapFont/CharacterSprite;"); - let val_1 = jni::objects::JValueGen::Char(ch); + index: i32, + ) -> Result, Box> { + let sig = String::from("(I)Lorg/bukkit/map/MapCursor;"); + let val_1 = jni::objects::JValueGen::Int(index); let res = self.jni_ref().call_method( &self.jni_object(), - "getChar", + "getCursor", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::map::MapFontCharacterSprite::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + crate::map::MapCursor::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get the width of the given text as it would be rendered using this - /// font. - pub fn get_width(&self, text: impl Into) -> Result> { - let sig = String::from("(Ljava/lang/String;)I"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(text.into())?, - )); + /// Remove a cursor from the collection. + pub fn remove_cursor( + &self, + cursor: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/map/MapCursor;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(cursor.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "getWidth", + "removeCursor", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.z()?) } - /// Get the height of this font. - pub fn height(&self) -> Result> { - let sig = String::from("()I"); + #[deprecated] + /// Add a cursor to the collection. + pub fn add_cursor( + &self, + x: i32, + y: std::option::Option, + direction: std::option::Option, + val_type: std::option::Option, + visible: std::option::Option, + caption: std::option::Option>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(x); + args.push(val_1); + if let Some(a) = y { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + if let Some(a) = direction { + sig += "B"; + let val_3 = jni::objects::JValueGen::Byte(a); + args.push(val_3); + } + if let Some(a) = val_type { + sig += "B"; + let val_4 = jni::objects::JValueGen::Byte(a); + args.push(val_4); + } + if let Some(a) = visible { + sig += "Z"; + let val_5 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_5); + } + if let Some(a) = caption { + sig += "Ljava/lang/String;"; + let val_6 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_6); + } + sig += ")Lorg/bukkit/map/MapCursor;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Check whether the given text is valid. - pub fn is_valid(&self, text: impl Into) -> Result> { - let sig = String::from("(Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(text.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isValid", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "addCursor", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::map::MapCursor::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1445,12 +1652,12 @@ impl<'mc> MapFont<'mc> { } } #[repr(C)] -pub struct MapFontCharacterSprite<'mc>( +pub struct MapRenderer<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for MapFontCharacterSprite<'mc> { +impl<'mc> JNIRaw<'mc> for MapRenderer<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1458,21 +1665,18 @@ impl<'mc> JNIRaw<'mc> for MapFontCharacterSprite<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for MapFontCharacterSprite<'mc> { +impl<'mc> JNIInstantiatable<'mc> for MapRenderer<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate MapFontCharacterSprite from null object." - ) - .into()); + return Err(eyre::eyre!("Tried to instantiate MapRenderer from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/map/MapFont/CharacterSprite")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/map/MapRenderer")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a MapFontCharacterSprite object, got {}", + "Invalid argument passed. Expected a MapRenderer object, got {}", name ) .into()) @@ -1482,65 +1686,63 @@ impl<'mc> JNIInstantiatable<'mc> for MapFontCharacterSprite<'mc> { } } -impl<'mc> MapFontCharacterSprite<'mc> { +impl<'mc> MapRenderer<'mc> { + pub fn from_extendable( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + plugin: &'mc crate::plugin::Plugin, + address: i32, + lib_name: String, + name: String, + ) -> Result> { + let obj = unsafe { plugin.new_extendable(address, "MapRenderer", name, lib_name) }?; + Self::from_raw(env, obj) + } + /// Initialize the map renderer base with the given contextual status. pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - width: i32, - height: i32, - data: bool, - ) -> Result, Box> { - let sig = String::from("(IIZ)V"); - let val_1 = jni::objects::JValueGen::Int(width); - let val_2 = jni::objects::JValueGen::Int(height); - let val_3 = jni::objects::JValueGen::Bool(data.into()); - let cls = jni.find_class("org/bukkit/map/MapFont/CharacterSprite"); + contextual: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = contextual { + sig += "Z"; + let val_1 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_1); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/map/MapRenderer"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); + let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::map::MapFontCharacterSprite::from_raw(&jni, res) + crate::map::MapRenderer::from_raw(&jni, res) } - /// Get the value of a pixel of the character. - pub fn get(&self, row: i32, col: i32) -> Result> { - let sig = String::from("(II)Z"); - let val_1 = jni::objects::JValueGen::Int(row); - let val_2 = jni::objects::JValueGen::Int(col); + /// Get whether the renderer is contextual, i.e. has different canvases for + /// different players. + pub fn is_contextual(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isContextual", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Initialize this MapRenderer for the given map. + pub fn initialize( + &self, + map: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/map/MapView;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(map.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "get", + "initialize", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the width of the character sprite. - pub fn width(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWidth", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Get the height of the character sprite. - pub fn height(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1549,12 +1751,12 @@ impl<'mc> MapFontCharacterSprite<'mc> { } } #[repr(C)] -pub struct MapView<'mc>( +pub struct MapCanvas<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for MapView<'mc> { +impl<'mc> JNIRaw<'mc> for MapCanvas<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1562,18 +1764,18 @@ impl<'mc> JNIRaw<'mc> for MapView<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for MapView<'mc> { +impl<'mc> JNIInstantiatable<'mc> for MapCanvas<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate MapView from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate MapCanvas from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/map/MapView")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/map/MapCanvas")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a MapView object, got {}", + "Invalid argument passed. Expected a MapCanvas object, got {}", name ) .into()) @@ -1583,268 +1785,251 @@ impl<'mc> JNIInstantiatable<'mc> for MapView<'mc> { } } -impl<'mc> MapView<'mc> { - /// Get the ID of this map item for use with {@link MapMeta}. - pub fn id(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Check whether this map is virtual. A map is virtual if its lowermost - /// MapRenderer is plugin-provided. - pub fn is_virtual(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isVirtual", sig.as_str(), vec![]); +impl<'mc> MapCanvas<'mc> { + /// Get the map this canvas is attached to. + pub fn map_view(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/map/MapView;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMapView", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::map::MapView::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Get the scale of this map. - pub fn scale(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/map/MapView/Scale;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getScale", sig.as_str(), vec![]); + /// Get the cursor collection associated with this canvas. + pub fn cursors( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/map/MapCursorCollection;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCursors", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::map::MapViewScale::from_raw(&self.jni_ref(), unsafe { + crate::map::MapCursorCollection::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Set the scale of this map. - pub fn set_scale( + /// Set the cursor collection associated with this canvas. This does not + /// usually need to be called since a MapCursorCollection is already + /// provided. + pub fn set_cursors( &self, - scale: impl Into>, + cursors: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/map/MapView/Scale;)V"); + let sig = String::from("(Lorg/bukkit/map/MapCursorCollection;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(scale.into().jni_object().clone()) + jni::objects::JObject::from_raw(cursors.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setScale", + "setCursors", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Get the center X position of this map. - pub fn center_x(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCenterX", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Get the center Z position of this map. - pub fn center_z(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCenterZ", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Set the center X position of this map. - pub fn set_center_x(&self, x: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); + /// Get a pixel from the canvas. + /// If no color is set at the given position for this canvas, then null is + /// returned and the color returned by {@link #getBasePixelColor(int, int)} + /// is shown on the map. + pub fn get_pixel_color( + &self, + x: i32, + y: i32, + ) -> Result, Box> { + let sig = String::from("(II)Ljava/awt/Color;"); let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(y); let res = self.jni_ref().call_method( &self.jni_object(), - "setCenterX", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Set the center Z position of this map. - pub fn set_center_z(&self, z: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(z); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setCenterZ", + "getPixelColor", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the world that this map is associated with. Primarily used by the - /// internal renderer, but may be used by external renderers. May return - /// null if the world the map is associated with is not loaded. - pub fn world(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/World;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWorld", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(crate::World::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) + let r = self.jni_ref().call_method( + unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }, + "getRed", + "(V)I", + vec![], + ); + let r = self.jni_ref().translate_error(r)?.i()? as u8; + let g = self.jni_ref().call_method( + unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }, + "getGreen", + "(V)I", + vec![], + ); + let g = self.jni_ref().translate_error(g)?.i()? as u8; + let b = self.jni_ref().call_method( + unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }, + "getBlue", + "(V)I", + vec![], + ); + let b = self.jni_ref().translate_error(b)?.i()? as u8; + Ok(Some((r, g, b))) } - /// Set the world that this map is associated with. The world is used by - /// the internal renderer, and may also be used by external renderers. - pub fn set_world( + /// Get a pixel from the layers below this canvas. + pub fn get_base_pixel_color( &self, - world: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/World;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); + x: i32, + y: i32, + ) -> Result<(u8, u8, u8), Box> { + let sig = String::from("(II)Ljava/awt/Color;"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(y); let res = self.jni_ref().call_method( &self.jni_object(), - "setWorld", + "getBasePixelColor", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get a list of MapRenderers currently in effect. - pub fn renderers( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getRenderers", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::map::MapRenderer::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + let r = self.jni_ref().call_method( + unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }, + "getRed", + "(V)I", + vec![], + ); + let r = self.jni_ref().translate_error(r)?.i()? as u8; + let g = self.jni_ref().call_method( + unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }, + "getGreen", + "(V)I", + vec![], + ); + let g = self.jni_ref().translate_error(g)?.i()? as u8; + let b = self.jni_ref().call_method( + unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }, + "getBlue", + "(V)I", + vec![], + ); + let b = self.jni_ref().translate_error(b)?.i()? as u8; + Ok((r, g, b)) } - /// Add a renderer to this map. - pub fn add_renderer( - &self, - renderer: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/map/MapRenderer;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(renderer.into().jni_object().clone()) - }); + #[deprecated] + /// Draw a pixel to the canvas. + pub fn set_pixel(&self, x: i32, y: i32, color: i8) -> Result<(), Box> { + let sig = String::from("(IIB)V"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(y); + let val_3 = jni::objects::JValueGen::Byte(color); let res = self.jni_ref().call_method( &self.jni_object(), - "addRenderer", + "setPixel", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Remove a renderer from this map. - pub fn remove_renderer( - &self, - renderer: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/map/MapRenderer;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(renderer.into().jni_object().clone()) - }); + #[deprecated] + /// Get a pixel from the canvas. + pub fn get_pixel(&self, x: i32, y: i32) -> Result> { + let sig = String::from("(II)B"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(y); let res = self.jni_ref().call_method( &self.jni_object(), - "removeRenderer", + "getPixel", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.b()?) } - /// Gets whether a position cursor should be shown when the map is near its - /// center. - pub fn is_tracking_position(&self) -> Result> { - let sig = String::from("()Z"); + #[deprecated] + /// Get a pixel from the layers below this canvas. + pub fn get_base_pixel(&self, x: i32, y: i32) -> Result> { + let sig = String::from("(II)B"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(y); let res = self.jni_ref().call_method( &self.jni_object(), - "isTrackingPosition", + "getBasePixel", sig.as_str(), - vec![], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.b()?) } - /// Sets whether a position cursor should be shown when the map is near its - /// center. - pub fn set_tracking_position( + /// Draw an image to the map. The image will be clipped if necessary. + pub fn draw_image( &self, - tracking_position: bool, + x: i32, + y: i32, + image: jni::objects::JObject<'mc>, ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(tracking_position.into()); + let sig = String::from("(IILjava/awt/Image;)V"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(y); + let val_3 = jni::objects::JValueGen::Object(image); let res = self.jni_ref().call_method( &self.jni_object(), - "setTrackingPosition", + "drawImage", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Whether the map will show a smaller position cursor (true), or no - /// position cursor (false) when cursor is outside of map's range. - pub fn is_unlimited_tracking(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isUnlimitedTracking", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Whether the map will show a smaller position cursor (true), or no - /// position cursor (false) when cursor is outside of map's range. - pub fn set_unlimited_tracking( + /// Render text to the map using fancy formatting. Newline (\n) characters + /// will move down one line and return to the original column, and the text + /// color can be changed using sequences such as "§12;", replacing 12 with + /// the palette index of the color (see {@link MapPalette}). + pub fn draw_text( &self, - unlimited: bool, + x: i32, + y: i32, + font: impl Into>, + text: impl Into, ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(unlimited.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setUnlimitedTracking", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets whether the map is locked or not. - /// A locked map may not be explored further. - pub fn is_locked(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isLocked", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets whether the map is locked or not. - /// A locked map may not be explored further. - pub fn set_locked(&self, locked: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(locked.into()); + let sig = String::from("(IILorg/bukkit/map/MapFont;Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Int(x); + let val_2 = jni::objects::JValueGen::Int(y); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(font.into().jni_object().clone()) + }); + let val_4 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(text.into())?, + )); let res = self.jni_ref().call_method( &self.jni_object(), - "setLocked", + "drawText", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + ], ); self.jni_ref().translate_error(res)?; Ok(()) @@ -1855,140 +2040,3 @@ impl<'mc> MapView<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum MapViewScale<'mc> {} -impl<'mc> std::fmt::Display for MapViewScale<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> MapViewScale<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/map/MapView/Scale"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/map/MapView/Scale;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct MapViewScaleStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for MapViewScale<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for MapViewScale<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate MapViewScale from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/map/MapView/Scale")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a MapViewScale object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for MapViewScaleStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for MapViewScaleStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate MapViewScaleStruct from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/map/MapView/Scale")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a MapViewScaleStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> MapViewScaleStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/map/MapView/Scale;"); - let cls = jni.find_class("org/bukkit/map/MapView/Scale"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::map::MapViewScale::from_raw(&jni, obj) - } - #[deprecated] - /// Get the raw value of this scale level. - pub fn value(&self) -> Result> { - let sig = String::from("()B"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getValue", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} diff --git a/blackboxmc-rs-bukkit/src/material/mod.rs b/blackboxmc-rs-bukkit/src/material/mod.rs index 29f87a4..2063781 100644 --- a/blackboxmc-rs-bukkit/src/material/mod.rs +++ b/blackboxmc-rs-bukkit/src/material/mod.rs @@ -3,12 +3,12 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] -pub struct Button<'mc>( +pub struct WoodenStep<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Button<'mc> { +impl<'mc> JNIRaw<'mc> for WoodenStep<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -16,18 +16,18 @@ impl<'mc> JNIRaw<'mc> for Button<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Button<'mc> { +impl<'mc> JNIInstantiatable<'mc> for WoodenStep<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Button from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate WoodenStep from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Button")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/WoodenStep")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Button object, got {}", + "Invalid argument passed. Expected a WoodenStep object, got {}", name ) .into()) @@ -37,14 +37,14 @@ impl<'mc> JNIInstantiatable<'mc> for Button<'mc> { } } -impl<'mc> Button<'mc> { +impl<'mc> WoodenStep<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); if let Some(a) = val_type { @@ -60,66 +60,45 @@ impl<'mc> Button<'mc> { args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Button"); + let cls = jni.find_class("org/bukkit/material/WoodenStep"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Button::from_raw(&jni, res) + crate::material::WoodenStep::from_raw(&jni, res) } - /// Gets the current state of this Material, indicating if it's powered or - /// unpowered - pub fn is_powered(&self) -> Result> { + /// Test if step is inverted + pub fn is_inverted(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInverted", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the current state of this button - pub fn set_powered(&self, bool: bool) -> Result<(), Box> { + /// Set step inverted state + pub fn set_inverted(&self, inv: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(bool.into()); + let val_1 = jni::objects::JValueGen::Bool(inv.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setPowered", + "setInverted", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the face that this block is attached on - pub fn attached_face( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAttachedFace", sig.as_str(), vec![]); + + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/WoodenStep;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + crate::material::WoodenStep::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the direction this button is pointing toward - pub fn set_facing_direction( - &self, - face: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFacingDirection", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } #[doc(hidden)] pub fn internal_to_string(&self) -> Result> { @@ -134,26 +113,35 @@ impl<'mc> Button<'mc> { .to_string_lossy() .to_string()) } - - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Button;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + // SUPER CLASS: org.bukkit.material.Wood ( ['isInverted', 'setInverted', 'clone', 'toString']) + /// Gets the current species of this wood block + pub fn species(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/TreeSpecies;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSpecies", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Button::from_raw(&self.jni_ref(), unsafe { + crate::TreeSpecies::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.SimpleAttachableMaterialData ( ['isPowered', 'setPowered', 'getAttachedFace', 'setFacingDirection', 'toString', 'clone']) - - pub fn facing(&self) -> Result, Box> { - let temp_clone = - crate::material::SimpleAttachableMaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::SimpleAttachableMaterialData = temp_clone.into(); - real.facing() + /// Sets the species of this wood block + pub fn set_species( + &self, + species: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/TreeSpecies;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(species.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSpecies", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -162,34 +150,28 @@ impl<'mc> Button<'mc> { } } -impl<'mc> std::string::ToString for Button<'mc> { +impl<'mc> std::string::ToString for WoodenStep<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling Button.toString: {}", err), + Err(err) => format!("Error calling WoodenStep.toString: {}", err), } } } -impl<'mc> Into> for Button<'mc> { - fn into(self) -> crate::material::Redstone<'mc> { - crate::material::Redstone::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Button into crate::material::Redstone") - } -} -impl<'mc> Into> for Button<'mc> { - fn into(self) -> crate::material::SimpleAttachableMaterialData<'mc> { - crate::material::SimpleAttachableMaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Button into crate::material::SimpleAttachableMaterialData") +impl<'mc> Into> for WoodenStep<'mc> { + fn into(self) -> crate::material::Wood<'mc> { + crate::material::Wood::from_raw(&self.jni_ref(), self.1) + .expect("Error converting WoodenStep into crate::material::Wood") } } #[repr(C)] -pub struct Ladder<'mc>( +pub struct Wood<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Ladder<'mc> { +impl<'mc> JNIRaw<'mc> for Wood<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -197,18 +179,18 @@ impl<'mc> JNIRaw<'mc> for Ladder<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Ladder<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Wood<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Ladder from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Wood from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Ladder")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Wood")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Ladder object, got {}", + "Invalid argument passed. Expected a Wood object, got {}", name ) .into()) @@ -218,14 +200,14 @@ impl<'mc> JNIInstantiatable<'mc> for Ladder<'mc> { } } -impl<'mc> Ladder<'mc> { +impl<'mc> Wood<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); if let Some(a) = val_type { @@ -241,37 +223,35 @@ impl<'mc> Ladder<'mc> { args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Ladder"); + let cls = jni.find_class("org/bukkit/material/Wood"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Ladder::from_raw(&jni, res) + crate::material::Wood::from_raw(&jni, res) } - /// Gets the face that this block is attached on - pub fn attached_face( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + /// Gets the current species of this wood block + pub fn species(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/TreeSpecies;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAttachedFace", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSpecies", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + crate::TreeSpecies::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the direction this ladder is facing - pub fn set_facing_direction( + /// Sets the species of this wood block + pub fn set_species( &self, - face: impl Into>, + species: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + let sig = String::from("(Lorg/bukkit/TreeSpecies;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) + jni::objects::JObject::from_raw(species.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setFacingDirection", + "setSpecies", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -279,55 +259,114 @@ impl<'mc> Ladder<'mc> { Ok(()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Ladder;"); + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Wood;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Ladder::from_raw(&self.jni_ref(), unsafe { + crate::material::Wood::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.SimpleAttachableMaterialData ( ['getAttachedFace', 'setFacingDirection', 'clone']) - - pub fn facing(&self) -> Result, Box> { - let temp_clone = - crate::material::SimpleAttachableMaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::SimpleAttachableMaterialData = temp_clone.into(); - real.facing() + // SUPER CLASS: org.bukkit.material.MaterialData ( ['getSpecies', 'setSpecies', 'toString', 'clone']) + /// Gets the raw data in this material + pub fn data(&self) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.data() } - - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let temp_clone = - crate::material::SimpleAttachableMaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::SimpleAttachableMaterialData = temp_clone.into(); - real.internal_to_string() + /// Sets the raw data of this material + pub fn set_data(&self, data: i8) -> Result<(), Box> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.set_data(data) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + /// Gets the Material that this MaterialData represents + pub fn item_type(&self) -> Result, Box> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.item_type() } -} -impl<'mc> Into> for Ladder<'mc> { - fn into(self) -> crate::material::SimpleAttachableMaterialData<'mc> { - crate::material::SimpleAttachableMaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Ladder into crate::material::SimpleAttachableMaterialData") + /// Creates a new ItemStack based on this MaterialData + pub fn to_item_stack( + &self, + amount: std::option::Option, + ) -> Result, Box> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.to_item_stack(amount) } -} + + pub fn hash_code(&self) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.hash_code() + } + + pub fn equals( + &self, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.equals(obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} + +impl<'mc> std::string::ToString for Wood<'mc> { + fn to_string(&self) -> String { + match &self.internal_to_string() { + Ok(a) => a.clone(), + Err(err) => format!("Error calling Wood.toString: {}", err), + } + } +} + +impl<'mc> Into> for Wood<'mc> { + fn into(self) -> crate::material::MaterialData<'mc> { + crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Wood into crate::material::MaterialData") + } +} #[repr(C)] -pub struct PoweredRail<'mc>( +pub struct Vine<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PoweredRail<'mc> { +impl<'mc> JNIRaw<'mc> for Vine<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -335,18 +374,18 @@ impl<'mc> JNIRaw<'mc> for PoweredRail<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PoweredRail<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Vine<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate PoweredRail from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Vine from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/PoweredRail")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Vine")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PoweredRail object, got {}", + "Invalid argument passed. Expected a Vine object, got {}", name ) .into()) @@ -356,14 +395,14 @@ impl<'mc> JNIInstantiatable<'mc> for PoweredRail<'mc> { } } -impl<'mc> PoweredRail<'mc> { +impl<'mc> Vine<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); if let Some(a) = val_type { @@ -379,28 +418,62 @@ impl<'mc> PoweredRail<'mc> { args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/PoweredRail"); + let cls = jni.find_class("org/bukkit/material/Vine"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::PoweredRail::from_raw(&jni, res) + crate::material::Vine::from_raw(&jni, res) } - - pub fn is_powered(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); + /// Check if the vine is attached to the specified face of an adjacent + /// block. You can check two faces at once by passing e.g. {@link + /// BlockFace#NORTH_EAST}. + pub fn is_on_face( + &self, + face: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isOnFace", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set whether this PoweredRail should be powered or not. - pub fn set_powered(&self, is_powered: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(is_powered.into()); + /// Attach the vine to the specified face of an adjacent block. + pub fn put_on_face( + &self, + face: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setPowered", + "putOnFace", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Detach the vine from the specified face of an adjacent block. + pub fn remove_from_face( + &self, + face: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeFromFace", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -408,36 +481,84 @@ impl<'mc> PoweredRail<'mc> { Ok(()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/PoweredRail;"); + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Vine;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::PoweredRail::from_raw(&self.jni_ref(), unsafe { + crate::material::Vine::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.ExtendedRails ( ['isPowered', 'setPowered', 'clone']) + // SUPER CLASS: org.bukkit.material.MaterialData ( ['isOnFace', 'putOnFace', 'removeFromFace', 'toString', 'clone']) + /// Gets the raw data in this material + pub fn data(&self) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.data() + } + /// Sets the raw data of this material + pub fn set_data(&self, data: i8) -> Result<(), Box> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.set_data(data) + } + /// Gets the Material that this MaterialData represents + pub fn item_type(&self) -> Result, Box> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.item_type() + } + /// Creates a new ItemStack based on this MaterialData + pub fn to_item_stack( + &self, + amount: std::option::Option, + ) -> Result, Box> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.to_item_stack(amount) + } - pub fn is_curve(&self) -> Result> { - let temp_clone = crate::material::ExtendedRails::from_raw(&self.0, unsafe { + pub fn hash_code(&self) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::material::ExtendedRails = temp_clone.into(); - real.is_curve() + let real: crate::material::MaterialData = temp_clone.into(); + real.hash_code() } - pub fn set_direction( + pub fn equals( &self, - face: impl Into>, - is_on_slope: bool, - ) -> Result<(), Box> { - let temp_clone = crate::material::ExtendedRails::from_raw(&self.0, unsafe { + obj: jni::objects::JObject<'mc>, + ) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::material::ExtendedRails = temp_clone.into(); - real.set_direction(face, is_on_slope) + let real: crate::material::MaterialData = temp_clone.into(); + real.equals(obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -445,16 +566,20 @@ impl<'mc> PoweredRail<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PoweredRail<'mc> { - fn into(self) -> crate::material::Redstone<'mc> { - crate::material::Redstone::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PoweredRail into crate::material::Redstone") + +impl<'mc> std::string::ToString for Vine<'mc> { + fn to_string(&self) -> String { + match &self.internal_to_string() { + Ok(a) => a.clone(), + Err(err) => format!("Error calling Vine.toString: {}", err), + } } } -impl<'mc> Into> for PoweredRail<'mc> { - fn into(self) -> crate::material::ExtendedRails<'mc> { - crate::material::ExtendedRails::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PoweredRail into crate::material::ExtendedRails") + +impl<'mc> Into> for Vine<'mc> { + fn into(self) -> crate::material::MaterialData<'mc> { + crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Vine into crate::material::MaterialData") } } #[repr(C)] @@ -670,12 +795,12 @@ impl<'mc> Into> for TripwireH } } #[repr(C)] -pub struct FlowerPot<'mc>( +pub struct Tripwire<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for FlowerPot<'mc> { +impl<'mc> JNIRaw<'mc> for Tripwire<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -683,18 +808,18 @@ impl<'mc> JNIRaw<'mc> for FlowerPot<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for FlowerPot<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Tripwire<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate FlowerPot from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Tripwire from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/FlowerPot")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Tripwire")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a FlowerPot object, got {}", + "Invalid argument passed. Expected a Tripwire object, got {}", name ) .into()) @@ -704,14 +829,14 @@ impl<'mc> JNIInstantiatable<'mc> for FlowerPot<'mc> { } } -impl<'mc> FlowerPot<'mc> { +impl<'mc> Tripwire<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); if let Some(a) = val_type { @@ -727,37 +852,53 @@ impl<'mc> FlowerPot<'mc> { args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/FlowerPot"); + let cls = jni.find_class("org/bukkit/material/Tripwire"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::FlowerPot::from_raw(&jni, res) + crate::material::Tripwire::from_raw(&jni, res) } - /// Get the material in the flower pot - pub fn contents( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/MaterialData;"); + /// Test if tripwire is currently activated + pub fn is_activated(&self) -> Result> { + let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getContents", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isActivated", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Set the contents of the flower pot - pub fn set_contents( - &self, - material_data: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/material/MaterialData;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material_data.into().jni_object().clone()) - }); + /// Set tripwire activated state + pub fn set_activated(&self, act: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(act.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setContents", + "setActivated", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Test if object triggering this tripwire directly + pub fn is_object_triggering(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isObjectTriggering", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set object triggering state for this tripwire + pub fn set_object_triggering(&self, trig: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(trig.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setObjectTriggering", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -765,6 +906,17 @@ impl<'mc> FlowerPot<'mc> { Ok(()) } + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Tripwire;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::material::Tripwire::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + #[doc(hidden)] pub fn internal_to_string(&self) -> Result> { let sig = String::from("()Ljava/lang/String;"); @@ -778,18 +930,7 @@ impl<'mc> FlowerPot<'mc> { .to_string_lossy() .to_string()) } - - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/FlowerPot;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::material::FlowerPot::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['getContents', 'setContents', 'toString', 'clone']) + // SUPER CLASS: org.bukkit.material.MaterialData ( ['isActivated', 'setActivated', 'isObjectTriggering', 'setObjectTriggering', 'clone', 'toString']) /// Gets the raw data in this material pub fn data(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { @@ -851,19 +992,19 @@ impl<'mc> FlowerPot<'mc> { } } -impl<'mc> std::string::ToString for FlowerPot<'mc> { +impl<'mc> std::string::ToString for Tripwire<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling FlowerPot.toString: {}", err), + Err(err) => format!("Error calling Tripwire.toString: {}", err), } } } -impl<'mc> Into> for FlowerPot<'mc> { +impl<'mc> Into> for Tripwire<'mc> { fn into(self) -> crate::material::MaterialData<'mc> { crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting FlowerPot into crate::material::MaterialData") + .expect("Error converting Tripwire into crate::material::MaterialData") } } #[repr(C)] @@ -1069,12 +1210,12 @@ impl<'mc> Into> for TrapDoor< } } #[repr(C)] -pub struct SpawnEgg<'mc>( +pub struct TexturedMaterial<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for SpawnEgg<'mc> { +impl<'mc> JNIRaw<'mc> for TexturedMaterial<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1082,18 +1223,20 @@ impl<'mc> JNIRaw<'mc> for SpawnEgg<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for SpawnEgg<'mc> { +impl<'mc> JNIInstantiatable<'mc> for TexturedMaterial<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate SpawnEgg from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate TexturedMaterial from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/SpawnEgg")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/TexturedMaterial")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SpawnEgg object, got {}", + "Invalid argument passed. Expected a TexturedMaterial object, got {}", name ) .into()) @@ -1103,62 +1246,56 @@ impl<'mc> JNIInstantiatable<'mc> for SpawnEgg<'mc> { } } -impl<'mc> SpawnEgg<'mc> { +impl<'mc> TexturedMaterial<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: std::option::Option>>, + val_type: impl Into>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = val_type { - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + args.push(val_1); if let Some(a) = data { sig += "B"; let val_2 = jni::objects::JValueGen::Byte(a); args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/SpawnEgg"); + let cls = jni.find_class("org/bukkit/material/TexturedMaterial"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::SpawnEgg::from_raw(&jni, res) + crate::material::TexturedMaterial::from_raw(&jni, res) } - #[deprecated] - /// Get the type of entity this egg will spawn. - pub fn spawned_type( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + /// Gets the current Material this block is made of + pub fn material(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getSpawnedType", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaterial", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { + crate::Material::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - #[deprecated] - /// Set the type of entity this egg will spawn. - pub fn set_spawned_type( + /// Sets the material this block is made of + pub fn set_material( &self, - val_type: impl Into>, + material: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/entity/EntityType;)V"); + let sig = String::from("(Lorg/bukkit/Material;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(material.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setSpawnedType", + "setMaterial", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -1180,17 +1317,19 @@ impl<'mc> SpawnEgg<'mc> { .to_string()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/SpawnEgg;"); + pub fn clone( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/TexturedMaterial;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::SpawnEgg::from_raw(&self.jni_ref(), unsafe { + crate::material::TexturedMaterial::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['getSpawnedType', 'setSpawnedType', 'toString', 'clone']) + // SUPER CLASS: org.bukkit.material.MaterialData ( ['getMaterial', 'setMaterial', 'toString', 'clone']) /// Gets the raw data in this material pub fn data(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { @@ -1252,28 +1391,28 @@ impl<'mc> SpawnEgg<'mc> { } } -impl<'mc> std::string::ToString for SpawnEgg<'mc> { +impl<'mc> std::string::ToString for TexturedMaterial<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling SpawnEgg.toString: {}", err), + Err(err) => format!("Error calling TexturedMaterial.toString: {}", err), } } } -impl<'mc> Into> for SpawnEgg<'mc> { +impl<'mc> Into> for TexturedMaterial<'mc> { fn into(self) -> crate::material::MaterialData<'mc> { crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SpawnEgg into crate::material::MaterialData") + .expect("Error converting TexturedMaterial into crate::material::MaterialData") } } #[repr(C)] -pub struct Gate<'mc>( +pub struct Step<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Gate<'mc> { +impl<'mc> JNIRaw<'mc> for Step<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1281,18 +1420,18 @@ impl<'mc> JNIRaw<'mc> for Gate<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Gate<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Step<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Gate from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Step from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Gate")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Step")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Gate object, got {}", + "Invalid argument passed. Expected a Step object, got {}", name ) .into()) @@ -1302,14 +1441,14 @@ impl<'mc> JNIInstantiatable<'mc> for Gate<'mc> { } } -impl<'mc> Gate<'mc> { +impl<'mc> Step<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); if let Some(a) = val_type { @@ -1325,57 +1464,44 @@ impl<'mc> Gate<'mc> { args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Gate"); + let cls = jni.find_class("org/bukkit/material/Step"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Gate::from_raw(&jni, res) - } - - pub fn set_facing_direction( - &self, - face: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFacingDirection", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::material::Step::from_raw(&jni, res) } - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + pub fn textures(&self) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTextures", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::Material::from_raw(&self.0, obj)?); + } + Ok(new_vec) } - - pub fn is_open(&self) -> Result> { + /// Test if step is inverted + pub fn is_inverted(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isOpen", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInverted", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - - pub fn set_open(&self, is_open: bool) -> Result<(), Box> { + /// Set step inverted state + pub fn set_inverted(&self, inv: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(is_open.into()); + let val_1 = jni::objects::JValueGen::Bool(inv.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setOpen", + "setInverted", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -1383,6 +1509,17 @@ impl<'mc> Gate<'mc> { Ok(()) } + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Step;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::material::Step::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + #[doc(hidden)] pub fn internal_to_string(&self) -> Result> { let sig = String::from("()Ljava/lang/String;"); @@ -1396,71 +1533,25 @@ impl<'mc> Gate<'mc> { .to_string_lossy() .to_string()) } - - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Gate;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::material::Gate::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['setFacingDirection', 'getFacing', 'isOpen', 'setOpen', 'toString', 'clone']) - /// Gets the raw data in this material - pub fn data(&self) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + // SUPER CLASS: org.bukkit.material.TexturedMaterial ( ['getTextures', 'isInverted', 'setInverted', 'clone', 'toString']) + /// Gets the current Material this block is made of + pub fn material(&self) -> Result, Box> { + let temp_clone = crate::material::TexturedMaterial::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.data() + let real: crate::material::TexturedMaterial = temp_clone.into(); + real.material() } - /// Sets the raw data of this material - pub fn set_data(&self, data: i8) -> Result<(), Box> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.set_data(data) - } - /// Gets the Material that this MaterialData represents - pub fn item_type(&self) -> Result, Box> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.item_type() - } - /// Creates a new ItemStack based on this MaterialData - pub fn to_item_stack( - &self, - amount: std::option::Option, - ) -> Result, Box> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.to_item_stack(amount) - } - - pub fn hash_code(&self) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.hash_code() - } - - pub fn equals( + /// Sets the material this block is made of + pub fn set_material( &self, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + material: impl Into>, + ) -> Result<(), Box> { + let temp_clone = crate::material::TexturedMaterial::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.equals(obj) + let real: crate::material::TexturedMaterial = temp_clone.into(); + real.set_material(material) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1469,40 +1560,28 @@ impl<'mc> Gate<'mc> { } } -impl<'mc> std::string::ToString for Gate<'mc> { +impl<'mc> std::string::ToString for Step<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling Gate.toString: {}", err), + Err(err) => format!("Error calling Step.toString: {}", err), } } } -impl<'mc> Into> for Gate<'mc> { - fn into(self) -> crate::material::Directional<'mc> { - crate::material::Directional::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Gate into crate::material::Directional") - } -} -impl<'mc> Into> for Gate<'mc> { - fn into(self) -> crate::material::Openable<'mc> { - crate::material::Openable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Gate into crate::material::Openable") - } -} -impl<'mc> Into> for Gate<'mc> { - fn into(self) -> crate::material::MaterialData<'mc> { - crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Gate into crate::material::MaterialData") +impl<'mc> Into> for Step<'mc> { + fn into(self) -> crate::material::TexturedMaterial<'mc> { + crate::material::TexturedMaterial::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Step into crate::material::TexturedMaterial") } } #[repr(C)] -pub struct PistonExtensionMaterial<'mc>( +pub struct Stairs<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PistonExtensionMaterial<'mc> { +impl<'mc> JNIRaw<'mc> for Stairs<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1510,22 +1589,18 @@ impl<'mc> JNIRaw<'mc> for PistonExtensionMaterial<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PistonExtensionMaterial<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Stairs<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PistonExtensionMaterial from null object." - ) - .into()); + return Err(eyre::eyre!("Tried to instantiate Stairs from null object.").into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/material/PistonExtensionMaterial")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Stairs")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PistonExtensionMaterial object, got {}", + "Invalid argument passed. Expected a Stairs object, got {}", name ) .into()) @@ -1535,14 +1610,14 @@ impl<'mc> JNIInstantiatable<'mc> for PistonExtensionMaterial<'mc> { } } -impl<'mc> PistonExtensionMaterial<'mc> { +impl<'mc> Stairs<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_type: impl Into>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "Lorg/bukkit/Material;"; @@ -1556,13 +1631,45 @@ impl<'mc> PistonExtensionMaterial<'mc> { args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/PistonExtensionMaterial"); + let cls = jni.find_class("org/bukkit/material/Stairs"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::PistonExtensionMaterial::from_raw(&jni, res) + crate::material::Stairs::from_raw(&jni, res) + } + + pub fn ascending_direction( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAscendingDirection", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } + pub fn descending_direction( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDescendingDirection", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Set the direction the stair part of the block is facing pub fn set_facing_direction( &self, face: impl Into>, @@ -1591,22 +1698,22 @@ impl<'mc> PistonExtensionMaterial<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Checks if this piston extension is sticky, and returns true if so - pub fn is_sticky(&self) -> Result> { + /// Test if step is inverted + pub fn is_inverted(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isSticky", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isInverted", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets whether or not this extension is sticky - pub fn set_sticky(&self, sticky: bool) -> Result<(), Box> { + /// Set step inverted state + pub fn set_inverted(&self, inv: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(sticky.into()); + let val_1 = jni::objects::JValueGen::Bool(inv.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setSticky", + "setInverted", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -1614,32 +1721,31 @@ impl<'mc> PistonExtensionMaterial<'mc> { Ok(()) } - pub fn attached_face( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAttachedFace", sig.as_str(), vec![]); + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - pub fn clone( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/PistonExtensionMaterial;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Stairs;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::PistonExtensionMaterial::from_raw(&self.jni_ref(), unsafe { + crate::material::Stairs::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['setFacingDirection', 'getFacing', 'isSticky', 'setSticky', 'getAttachedFace', 'clone']) + // SUPER CLASS: org.bukkit.material.MaterialData ( ['getAscendingDirection', 'getDescendingDirection', 'setFacingDirection', 'getFacing', 'isInverted', 'setInverted', 'toString', 'clone']) /// Gets the raw data in this material pub fn data(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { @@ -1676,15 +1782,6 @@ impl<'mc> PistonExtensionMaterial<'mc> { real.to_item_stack(amount) } - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.internal_to_string() - } - pub fn hash_code(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) @@ -1709,25 +1806,35 @@ impl<'mc> PistonExtensionMaterial<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PistonExtensionMaterial<'mc> { - fn into(self) -> crate::material::Attachable<'mc> { - crate::material::Attachable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PistonExtensionMaterial into crate::material::Attachable") + +impl<'mc> std::string::ToString for Stairs<'mc> { + fn to_string(&self) -> String { + match &self.internal_to_string() { + Ok(a) => a.clone(), + Err(err) => format!("Error calling Stairs.toString: {}", err), + } } } -impl<'mc> Into> for PistonExtensionMaterial<'mc> { + +impl<'mc> Into> for Stairs<'mc> { + fn into(self) -> crate::material::Directional<'mc> { + crate::material::Directional::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Stairs into crate::material::Directional") + } +} +impl<'mc> Into> for Stairs<'mc> { fn into(self) -> crate::material::MaterialData<'mc> { crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PistonExtensionMaterial into crate::material::MaterialData") + .expect("Error converting Stairs into crate::material::MaterialData") } } #[repr(C)] -pub struct MonsterEggs<'mc>( +pub struct SmoothBrick<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for MonsterEggs<'mc> { +impl<'mc> JNIRaw<'mc> for SmoothBrick<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1735,18 +1842,18 @@ impl<'mc> JNIRaw<'mc> for MonsterEggs<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for MonsterEggs<'mc> { +impl<'mc> JNIInstantiatable<'mc> for SmoothBrick<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate MonsterEggs from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate SmoothBrick from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/MonsterEggs")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/SmoothBrick")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a MonsterEggs object, got {}", + "Invalid argument passed. Expected a SmoothBrick object, got {}", name ) .into()) @@ -1756,14 +1863,14 @@ impl<'mc> JNIInstantiatable<'mc> for MonsterEggs<'mc> { } } -impl<'mc> MonsterEggs<'mc> { +impl<'mc> SmoothBrick<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); if let Some(a) = val_type { @@ -1779,11 +1886,11 @@ impl<'mc> MonsterEggs<'mc> { args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/MonsterEggs"); + let cls = jni.find_class("org/bukkit/material/SmoothBrick"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::MonsterEggs::from_raw(&jni, res) + crate::material::SmoothBrick::from_raw(&jni, res) } pub fn textures(&self) -> Result>, Box> { @@ -1802,13 +1909,13 @@ impl<'mc> MonsterEggs<'mc> { Ok(new_vec) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/MonsterEggs;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/SmoothBrick;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::MonsterEggs::from_raw(&self.jni_ref(), unsafe { + crate::material::SmoothBrick::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -1847,19 +1954,19 @@ impl<'mc> MonsterEggs<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for MonsterEggs<'mc> { +impl<'mc> Into> for SmoothBrick<'mc> { fn into(self) -> crate::material::TexturedMaterial<'mc> { crate::material::TexturedMaterial::from_raw(&self.jni_ref(), self.1) - .expect("Error converting MonsterEggs into crate::material::TexturedMaterial") + .expect("Error converting SmoothBrick into crate::material::TexturedMaterial") } } #[repr(C)] -pub struct Cauldron<'mc>( +pub struct Sign<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Cauldron<'mc> { +impl<'mc> JNIRaw<'mc> for Sign<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1867,18 +1974,18 @@ impl<'mc> JNIRaw<'mc> for Cauldron<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Cauldron<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Sign<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Cauldron from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Sign from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Cauldron")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Sign")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Cauldron object, got {}", + "Invalid argument passed. Expected a Sign object, got {}", name ) .into()) @@ -1888,14 +1995,14 @@ impl<'mc> JNIInstantiatable<'mc> for Cauldron<'mc> { } } -impl<'mc> Cauldron<'mc> { +impl<'mc> Sign<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); if let Some(a) = val_type { @@ -1911,29 +2018,62 @@ impl<'mc> Cauldron<'mc> { args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Cauldron"); + let cls = jni.find_class("org/bukkit/material/Sign"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Cauldron::from_raw(&jni, res) + crate::material::Sign::from_raw(&jni, res) } - /// Check if the cauldron is full. - pub fn is_full(&self) -> Result> { + /// Check if this sign is attached to a wall + pub fn is_wall_sign(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isFull", sig.as_str(), vec![]); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isWallSign", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Check if the cauldron is empty. - pub fn is_empty(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the face that this block is attached on + pub fn attached_face( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAttachedFace", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the direction that this sign is currently facing + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn set_facing_direction( + &self, + face: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFacingDirection", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } #[doc(hidden)] @@ -1950,17 +2090,17 @@ impl<'mc> Cauldron<'mc> { .to_string()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Cauldron;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Sign;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Cauldron::from_raw(&self.jni_ref(), unsafe { + crate::material::Sign::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['isFull', 'isEmpty', 'toString', 'clone']) + // SUPER CLASS: org.bukkit.material.MaterialData ( ['isWallSign', 'getAttachedFace', 'getFacing', 'setFacingDirection', 'toString', 'clone']) /// Gets the raw data in this material pub fn data(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { @@ -2022,28 +2162,34 @@ impl<'mc> Cauldron<'mc> { } } -impl<'mc> std::string::ToString for Cauldron<'mc> { +impl<'mc> std::string::ToString for Sign<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling Cauldron.toString: {}", err), + Err(err) => format!("Error calling Sign.toString: {}", err), } } } -impl<'mc> Into> for Cauldron<'mc> { +impl<'mc> Into> for Sign<'mc> { + fn into(self) -> crate::material::Attachable<'mc> { + crate::material::Attachable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Sign into crate::material::Attachable") + } +} +impl<'mc> Into> for Sign<'mc> { fn into(self) -> crate::material::MaterialData<'mc> { crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Cauldron into crate::material::MaterialData") + .expect("Error converting Sign into crate::material::MaterialData") } } #[repr(C)] -pub struct Sign<'mc>( +pub struct Mushroom<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Sign<'mc> { +impl<'mc> JNIRaw<'mc> for Mushroom<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2051,18 +2197,18 @@ impl<'mc> JNIRaw<'mc> for Sign<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Sign<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Mushroom<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Sign from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Mushroom from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Sign")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Mushroom")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Sign object, got {}", + "Invalid argument passed. Expected a Mushroom object, got {}", name ) .into()) @@ -2072,87 +2218,139 @@ impl<'mc> JNIInstantiatable<'mc> for Sign<'mc> { } } -impl<'mc> Sign<'mc> { +impl<'mc> Mushroom<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: std::option::Option>>, + shroom: impl Into>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = val_type { - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(shroom.into().jni_object().clone()) + }); + args.push(val_1); if let Some(a) = data { sig += "B"; let val_2 = jni::objects::JValueGen::Byte(a); args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Sign"); + let cls = jni.find_class("org/bukkit/material/Mushroom"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Sign::from_raw(&jni, res) + crate::material::Mushroom::from_raw(&jni, res) } - /// Check if this sign is attached to a wall - pub fn is_wall_sign(&self) -> Result> { + + pub fn is_stem(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isWallSign", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isStem", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Gets the face that this block is attached on - pub fn attached_face( + #[deprecated] + /// Sets this to be a mushroom stem. + pub fn set_stem(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setStem", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the mushroom texture of this block. + pub fn block_texture( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/types/MushroomBlockTexture;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAttachedFace", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBlockTexture", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + crate::material::types::MushroomBlockTexture::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the direction that this sign is currently facing - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + /// Sets the mushroom texture of this block. + pub fn set_block_texture( + &self, + texture: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/material/types/MushroomBlockTexture;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(texture.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBlockTexture", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks whether a face of the block is painted with cap texture. + pub fn is_face_painted( + &self, + face: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isFacePainted", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - - pub fn set_facing_direction( + #[deprecated] + /// Set a face of the block to be painted or not. Note that due to the nature of how the data is stored, setting a face painted or not is not guaranteed to leave the other faces unchanged. + pub fn set_face_painted( &self, face: impl Into>, + painted: bool, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + let sig = String::from("(Lorg/bukkit/block/BlockFace;Z)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(face.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Bool(painted.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setFacingDirection", + "setFacePainted", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } + pub fn painted_faces( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPaintedFaces", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + #[doc(hidden)] pub fn internal_to_string(&self) -> Result> { let sig = String::from("()Ljava/lang/String;"); @@ -2167,17 +2365,17 @@ impl<'mc> Sign<'mc> { .to_string()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Sign;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Mushroom;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Sign::from_raw(&self.jni_ref(), unsafe { + crate::material::Mushroom::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['isWallSign', 'getAttachedFace', 'getFacing', 'setFacingDirection', 'toString', 'clone']) + // SUPER CLASS: org.bukkit.material.MaterialData ( ['isStem', 'setStem', 'getBlockTexture', 'setBlockTexture', 'isFacePainted', 'setFacePainted', 'getPaintedFaces', 'toString', 'clone']) /// Gets the raw data in this material pub fn data(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { @@ -2239,34 +2437,28 @@ impl<'mc> Sign<'mc> { } } -impl<'mc> std::string::ToString for Sign<'mc> { +impl<'mc> std::string::ToString for Mushroom<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling Sign.toString: {}", err), + Err(err) => format!("Error calling Mushroom.toString: {}", err), } } } -impl<'mc> Into> for Sign<'mc> { - fn into(self) -> crate::material::Attachable<'mc> { - crate::material::Attachable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Sign into crate::material::Attachable") - } -} -impl<'mc> Into> for Sign<'mc> { +impl<'mc> Into> for Mushroom<'mc> { fn into(self) -> crate::material::MaterialData<'mc> { crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Sign into crate::material::MaterialData") + .expect("Error converting Mushroom into crate::material::MaterialData") } } #[repr(C)] -pub struct Step<'mc>( +pub struct MonsterEggs<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Step<'mc> { +impl<'mc> JNIRaw<'mc> for MonsterEggs<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2274,18 +2466,18 @@ impl<'mc> JNIRaw<'mc> for Step<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Step<'mc> { +impl<'mc> JNIInstantiatable<'mc> for MonsterEggs<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Step from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate MonsterEggs from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Step")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/MonsterEggs")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Step object, got {}", + "Invalid argument passed. Expected a MonsterEggs object, got {}", name ) .into()) @@ -2295,14 +2487,14 @@ impl<'mc> JNIInstantiatable<'mc> for Step<'mc> { } } -impl<'mc> Step<'mc> { +impl<'mc> MonsterEggs<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); if let Some(a) = val_type { @@ -2318,11 +2510,11 @@ impl<'mc> Step<'mc> { args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Step"); + let cls = jni.find_class("org/bukkit/material/MonsterEggs"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Step::from_raw(&jni, res) + crate::material::MonsterEggs::from_raw(&jni, res) } pub fn textures(&self) -> Result>, Box> { @@ -2340,54 +2532,18 @@ impl<'mc> Step<'mc> { } Ok(new_vec) } - /// Test if step is inverted - pub fn is_inverted(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInverted", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Set step inverted state - pub fn set_inverted(&self, inv: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(inv.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setInverted", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Step;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/MonsterEggs;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Step::from_raw(&self.jni_ref(), unsafe { + crate::material::MonsterEggs::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - // SUPER CLASS: org.bukkit.material.TexturedMaterial ( ['getTextures', 'isInverted', 'setInverted', 'clone', 'toString']) + // SUPER CLASS: org.bukkit.material.TexturedMaterial ( ['getTextures', 'clone']) /// Gets the current Material this block is made of pub fn material(&self) -> Result, Box> { let temp_clone = crate::material::TexturedMaterial::from_raw(&self.0, unsafe { @@ -2408,34 +2564,33 @@ impl<'mc> Step<'mc> { real.set_material(material) } + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let temp_clone = crate::material::TexturedMaterial::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::TexturedMaterial = temp_clone.into(); + real.internal_to_string() + } + pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } - -impl<'mc> std::string::ToString for Step<'mc> { - fn to_string(&self) -> String { - match &self.internal_to_string() { - Ok(a) => a.clone(), - Err(err) => format!("Error calling Step.toString: {}", err), - } - } -} - -impl<'mc> Into> for Step<'mc> { +impl<'mc> Into> for MonsterEggs<'mc> { fn into(self) -> crate::material::TexturedMaterial<'mc> { crate::material::TexturedMaterial::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Step into crate::material::TexturedMaterial") + .expect("Error converting MonsterEggs into crate::material::TexturedMaterial") } } #[repr(C)] -pub struct RedstoneTorch<'mc>( +pub struct MaterialData<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for RedstoneTorch<'mc> { +impl<'mc> JNIRaw<'mc> for MaterialData<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2443,18 +2598,18 @@ impl<'mc> JNIRaw<'mc> for RedstoneTorch<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for RedstoneTorch<'mc> { +impl<'mc> JNIInstantiatable<'mc> for MaterialData<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate RedstoneTorch from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate MaterialData from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/RedstoneTorch")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/MaterialData")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a RedstoneTorch object, got {}", + "Invalid argument passed. Expected a MaterialData object, got {}", name ) .into()) @@ -2464,44 +2619,88 @@ impl<'mc> JNIInstantiatable<'mc> for RedstoneTorch<'mc> { } } -impl<'mc> RedstoneTorch<'mc> { +impl<'mc> MaterialData<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: std::option::Option>>, + val_type: impl Into>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = val_type { - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + args.push(val_1); if let Some(a) = data { sig += "B"; let val_2 = jni::objects::JValueGen::Byte(a); args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/RedstoneTorch"); + let cls = jni.find_class("org/bukkit/material/MaterialData"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::RedstoneTorch::from_raw(&jni, res) + crate::material::MaterialData::from_raw(&jni, res) } - /// Gets the current state of this Material, indicating if it's powered or - /// unpowered - pub fn is_powered(&self) -> Result> { - let sig = String::from("()Z"); + #[deprecated] + /// Gets the raw data in this material + pub fn data(&self) -> Result> { + let sig = String::from("()B"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.b()?) + } + #[deprecated] + /// Sets the raw data of this material + pub fn set_data(&self, data: i8) -> Result<(), Box> { + let sig = String::from("(B)V"); + let val_1 = jni::objects::JValueGen::Byte(data); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setData", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the Material that this MaterialData represents + pub fn item_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Material;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getItemType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Material::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Creates a new ItemStack based on this MaterialData + pub fn to_item_stack( + &self, + amount: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = amount { + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(a); + args.push(val_1); + } + sig += ")Lorg/bukkit/inventory/ItemStack;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "toItemStack", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } #[doc(hidden)] @@ -2518,37 +2717,40 @@ impl<'mc> RedstoneTorch<'mc> { .to_string()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/RedstoneTorch;"); + pub fn hash_code(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::RedstoneTorch::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - // SUPER CLASS: org.bukkit.material.Torch ( ['isPowered', 'toString', 'clone']) - /// Gets the face that this block is attached on - pub fn attached_face( + + pub fn equals( &self, - ) -> Result, Box> { - let temp_clone = crate::material::Torch::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::Torch = temp_clone.into(); - real.attached_face() + obj: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(Ljava/lang/Object;)Z"); + let val_1 = jni::objects::JValueGen::Object(obj); + let res = self.jni_ref().call_method( + &self.jni_object(), + "equals", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - pub fn set_facing_direction( - &self, - face: impl Into>, - ) -> Result<(), Box> { - let temp_clone = crate::material::Torch::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::Torch = temp_clone.into(); - real.set_facing_direction(face) + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/MaterialData;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -2557,34 +2759,22 @@ impl<'mc> RedstoneTorch<'mc> { } } -impl<'mc> std::string::ToString for RedstoneTorch<'mc> { +impl<'mc> std::string::ToString for MaterialData<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling RedstoneTorch.toString: {}", err), + Err(err) => format!("Error calling MaterialData.toString: {}", err), } } } -impl<'mc> Into> for RedstoneTorch<'mc> { - fn into(self) -> crate::material::Redstone<'mc> { - crate::material::Redstone::from_raw(&self.jni_ref(), self.1) - .expect("Error converting RedstoneTorch into crate::material::Redstone") - } -} -impl<'mc> Into> for RedstoneTorch<'mc> { - fn into(self) -> crate::material::Torch<'mc> { - crate::material::Torch::from_raw(&self.jni_ref(), self.1) - .expect("Error converting RedstoneTorch into crate::material::Torch") - } -} #[repr(C)] -pub struct PistonBaseMaterial<'mc>( +pub struct Lever<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PistonBaseMaterial<'mc> { +impl<'mc> JNIRaw<'mc> for Lever<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2592,20 +2782,18 @@ impl<'mc> JNIRaw<'mc> for PistonBaseMaterial<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PistonBaseMaterial<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Lever<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate PistonBaseMaterial from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate Lever from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/PistonBaseMaterial")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Lever")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PistonBaseMaterial object, got {}", + "Invalid argument passed. Expected a Lever object, got {}", name ) .into()) @@ -2615,32 +2803,215 @@ impl<'mc> JNIInstantiatable<'mc> for PistonBaseMaterial<'mc> { } } -impl<'mc> PistonBaseMaterial<'mc> { +impl<'mc> Lever<'mc> { #[deprecated] - /// Constructs a PistonBaseMaterial. + pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: impl Into>, + val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = data { + if let Some(a) = val_type { + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + if let Some(a) = data { sig += "B"; let val_2 = jni::objects::JValueGen::Byte(a); args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/PistonBaseMaterial"); + let cls = jni.find_class("org/bukkit/material/Lever"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::PistonBaseMaterial::from_raw(&jni, res) + crate::material::Lever::from_raw(&jni, res) + } + /// Gets the current state of this Material, indicating if it's powered or + /// unpowered + pub fn is_powered(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set this lever to be powered or not. + pub fn set_powered(&self, is_powered: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(is_powered.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPowered", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the face that this block is attached on + pub fn attached_face( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAttachedFace", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the direction this lever is pointing in + pub fn set_facing_direction( + &self, + face: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFacingDirection", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Lever;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::material::Lever::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + // SUPER CLASS: org.bukkit.material.SimpleAttachableMaterialData ( ['isPowered', 'setPowered', 'getAttachedFace', 'setFacingDirection', 'toString', 'clone']) + + pub fn facing(&self) -> Result, Box> { + let temp_clone = + crate::material::SimpleAttachableMaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::SimpleAttachableMaterialData = temp_clone.into(); + real.facing() + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} + +impl<'mc> std::string::ToString for Lever<'mc> { + fn to_string(&self) -> String { + match &self.internal_to_string() { + Ok(a) => a.clone(), + Err(err) => format!("Error calling Lever.toString: {}", err), + } + } +} + +impl<'mc> Into> for Lever<'mc> { + fn into(self) -> crate::material::Redstone<'mc> { + crate::material::Redstone::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Lever into crate::material::Redstone") + } +} +impl<'mc> Into> for Lever<'mc> { + fn into(self) -> crate::material::SimpleAttachableMaterialData<'mc> { + crate::material::SimpleAttachableMaterialData::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Lever into crate::material::SimpleAttachableMaterialData") + } +} +#[repr(C)] +pub struct Gate<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Gate<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Gate<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Gate from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Gate")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Gate object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Gate<'mc> { + #[deprecated] + + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + val_type: std::option::Option>>, + data: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = val_type { + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + if let Some(a) = data { + sig += "B"; + let val_2 = jni::objects::JValueGen::Byte(a); + args.push(val_2); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/material/Gate"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::material::Gate::from_raw(&jni, res) } pub fn set_facing_direction( @@ -2672,50 +3043,53 @@ impl<'mc> PistonBaseMaterial<'mc> { }) } - pub fn is_powered(&self) -> Result> { + pub fn is_open(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isOpen", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the current state of this piston - pub fn set_powered(&self, powered: bool) -> Result<(), Box> { + + pub fn set_open(&self, is_open: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(powered.into()); + let val_1 = jni::objects::JValueGen::Bool(is_open.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setPowered", + "setOpen", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks if this piston base is sticky, and returns true if so - pub fn is_sticky(&self) -> Result> { - let sig = String::from("()Z"); + + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isSticky", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - pub fn clone( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/PistonBaseMaterial;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Gate;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::PistonBaseMaterial::from_raw(&self.jni_ref(), unsafe { + crate::material::Gate::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['setFacingDirection', 'getFacing', 'isPowered', 'setPowered', 'isSticky', 'clone']) + // SUPER CLASS: org.bukkit.material.MaterialData ( ['setFacingDirection', 'getFacing', 'isOpen', 'setOpen', 'toString', 'clone']) /// Gets the raw data in this material pub fn data(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { @@ -2752,15 +3126,6 @@ impl<'mc> PistonBaseMaterial<'mc> { real.to_item_stack(amount) } - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.internal_to_string() - } - pub fn hash_code(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) @@ -2785,31 +3150,41 @@ impl<'mc> PistonBaseMaterial<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PistonBaseMaterial<'mc> { + +impl<'mc> std::string::ToString for Gate<'mc> { + fn to_string(&self) -> String { + match &self.internal_to_string() { + Ok(a) => a.clone(), + Err(err) => format!("Error calling Gate.toString: {}", err), + } + } +} + +impl<'mc> Into> for Gate<'mc> { fn into(self) -> crate::material::Directional<'mc> { crate::material::Directional::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PistonBaseMaterial into crate::material::Directional") + .expect("Error converting Gate into crate::material::Directional") } } -impl<'mc> Into> for PistonBaseMaterial<'mc> { - fn into(self) -> crate::material::Redstone<'mc> { - crate::material::Redstone::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PistonBaseMaterial into crate::material::Redstone") +impl<'mc> Into> for Gate<'mc> { + fn into(self) -> crate::material::Openable<'mc> { + crate::material::Openable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Gate into crate::material::Openable") } } -impl<'mc> Into> for PistonBaseMaterial<'mc> { +impl<'mc> Into> for Gate<'mc> { fn into(self) -> crate::material::MaterialData<'mc> { crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PistonBaseMaterial into crate::material::MaterialData") + .expect("Error converting Gate into crate::material::MaterialData") } } #[repr(C)] -pub struct SimpleAttachableMaterialData<'mc>( +pub struct FlowerPot<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for SimpleAttachableMaterialData<'mc> { +impl<'mc> JNIRaw<'mc> for FlowerPot<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2817,22 +3192,18 @@ impl<'mc> JNIRaw<'mc> for SimpleAttachableMaterialData<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for SimpleAttachableMaterialData<'mc> { +impl<'mc> JNIInstantiatable<'mc> for FlowerPot<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate SimpleAttachableMaterialData from null object." - ) - .into()); + return Err(eyre::eyre!("Tried to instantiate FlowerPot from null object.").into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/material/SimpleAttachableMaterialData")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/FlowerPot")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SimpleAttachableMaterialData object, got {}", + "Invalid argument passed. Expected a FlowerPot object, got {}", name ) .into()) @@ -2842,45 +3213,66 @@ impl<'mc> JNIInstantiatable<'mc> for SimpleAttachableMaterialData<'mc> { } } -impl<'mc> SimpleAttachableMaterialData<'mc> { +impl<'mc> FlowerPot<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: impl Into>, + val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> - { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - args.push(val_1); + if let Some(a) = val_type { + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } if let Some(a) = data { sig += "B"; let val_2 = jni::objects::JValueGen::Byte(a); args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/SimpleAttachableMaterialData"); + let cls = jni.find_class("org/bukkit/material/FlowerPot"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::SimpleAttachableMaterialData::from_raw(&jni, res) + crate::material::FlowerPot::from_raw(&jni, res) } - - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + /// Get the material in the flower pot + pub fn contents( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/MaterialData;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getContents", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } + /// Set the contents of the flower pot + pub fn set_contents( + &self, + material_data: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/material/MaterialData;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(material_data.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setContents", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } #[doc(hidden)] pub fn internal_to_string(&self) -> Result> { @@ -2896,33 +3288,17 @@ impl<'mc> SimpleAttachableMaterialData<'mc> { .to_string()) } - pub fn clone( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/material/SimpleAttachableMaterialData;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/FlowerPot;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::SimpleAttachableMaterialData::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the face that this block is attached on - pub fn attached_face( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAttachedFace", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + crate::material::FlowerPot::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['getFacing', 'toString', 'clone', 'getAttachedFace']) + // SUPER CLASS: org.bukkit.material.MaterialData ( ['getContents', 'setContents', 'toString', 'clone']) /// Gets the raw data in this material pub fn data(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { @@ -2984,91 +3360,28 @@ impl<'mc> SimpleAttachableMaterialData<'mc> { } } -impl<'mc> std::string::ToString for SimpleAttachableMaterialData<'mc> { +impl<'mc> std::string::ToString for FlowerPot<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!( - "Error calling SimpleAttachableMaterialData.toString: {}", - err - ), + Err(err) => format!("Error calling FlowerPot.toString: {}", err), } } } -impl<'mc> Into> for SimpleAttachableMaterialData<'mc> { - fn into(self) -> crate::material::Attachable<'mc> { - crate::material::Attachable::from_raw(&self.jni_ref(), self.1).expect( - "Error converting SimpleAttachableMaterialData into crate::material::Attachable", - ) - } -} -impl<'mc> Into> for SimpleAttachableMaterialData<'mc> { +impl<'mc> Into> for FlowerPot<'mc> { fn into(self) -> crate::material::MaterialData<'mc> { - crate::material::MaterialData::from_raw(&self.jni_ref(), self.1).expect( - "Error converting SimpleAttachableMaterialData into crate::material::MaterialData", - ) - } -} -#[repr(C)] -pub struct PressureSensor<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PressureSensor<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PressureSensor<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate PressureSensor from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/PressureSensor")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PressureSensor object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> PressureSensor<'mc> { - pub fn is_pressed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isPressed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) + .expect("Error converting FlowerPot into crate::material::MaterialData") } } #[repr(C)] -pub struct Stairs<'mc>( +pub struct ExtendedRails<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Stairs<'mc> { +impl<'mc> JNIRaw<'mc> for ExtendedRails<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3076,18 +3389,18 @@ impl<'mc> JNIRaw<'mc> for Stairs<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Stairs<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ExtendedRails<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Stairs from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate ExtendedRails from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Stairs")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/ExtendedRails")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Stairs object, got {}", + "Invalid argument passed. Expected a ExtendedRails object, got {}", name ) .into()) @@ -3097,14 +3410,14 @@ impl<'mc> JNIInstantiatable<'mc> for Stairs<'mc> { } } -impl<'mc> Stairs<'mc> { +impl<'mc> ExtendedRails<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_type: impl Into>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "Lorg/bukkit/Material;"; @@ -3118,174 +3431,80 @@ impl<'mc> Stairs<'mc> { args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Stairs"); + let cls = jni.find_class("org/bukkit/material/ExtendedRails"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Stairs::from_raw(&jni, res) + crate::material::ExtendedRails::from_raw(&jni, res) } - pub fn ascending_direction( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getAscendingDirection", - sig.as_str(), - vec![], - ); + pub fn is_curve(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isCurve", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - pub fn descending_direction( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getDescendingDirection", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Set the direction the stair part of the block is facing - pub fn set_facing_direction( + pub fn set_direction( &self, face: impl Into>, + is_on_slope: bool, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + let sig = String::from("(Lorg/bukkit/block/BlockFace;Z)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(face.into().jni_object().clone()) }); + let val_2 = jni::objects::JValueGen::Bool(is_on_slope.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setFacingDirection", + "setDirection", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); self.jni_ref().translate_error(res)?; Ok(()) } - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/ExtendedRails;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + crate::material::ExtendedRails::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Test if step is inverted - pub fn is_inverted(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isInverted", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Set step inverted state - pub fn set_inverted(&self, inv: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(inv.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setInverted", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } + // SUPER CLASS: org.bukkit.material.Rails ( ['isCurve', 'setDirection', 'clone']) - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Stairs;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::material::Stairs::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['getAscendingDirection', 'getDescendingDirection', 'setFacingDirection', 'getFacing', 'isInverted', 'setInverted', 'toString', 'clone']) - /// Gets the raw data in this material - pub fn data(&self) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.data() - } - /// Sets the raw data of this material - pub fn set_data(&self, data: i8) -> Result<(), Box> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.set_data(data) - } - /// Gets the Material that this MaterialData represents - pub fn item_type(&self) -> Result, Box> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.item_type() - } - /// Creates a new ItemStack based on this MaterialData - pub fn to_item_stack( - &self, - amount: std::option::Option, - ) -> Result, Box> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + pub fn is_on_slope(&self) -> Result> { + let temp_clone = crate::material::Rails::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.to_item_stack(amount) + let real: crate::material::Rails = temp_clone.into(); + real.is_on_slope() } - pub fn hash_code(&self) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + pub fn direction(&self) -> Result, Box> { + let temp_clone = crate::material::Rails::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.hash_code() + let real: crate::material::Rails = temp_clone.into(); + real.direction() } - pub fn equals( - &self, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let temp_clone = crate::material::Rails::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.equals(obj) + let real: crate::material::Rails = temp_clone.into(); + real.internal_to_string() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -3293,35 +3512,19 @@ impl<'mc> Stairs<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } - -impl<'mc> std::string::ToString for Stairs<'mc> { - fn to_string(&self) -> String { - match &self.internal_to_string() { - Ok(a) => a.clone(), - Err(err) => format!("Error calling Stairs.toString: {}", err), - } - } -} - -impl<'mc> Into> for Stairs<'mc> { - fn into(self) -> crate::material::Directional<'mc> { - crate::material::Directional::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Stairs into crate::material::Directional") - } -} -impl<'mc> Into> for Stairs<'mc> { - fn into(self) -> crate::material::MaterialData<'mc> { - crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Stairs into crate::material::MaterialData") +impl<'mc> Into> for ExtendedRails<'mc> { + fn into(self) -> crate::material::Rails<'mc> { + crate::material::Rails::from_raw(&self.jni_ref(), self.1) + .expect("Error converting ExtendedRails into crate::material::Rails") } } #[repr(C)] -pub struct Crops<'mc>( +pub struct Diode<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Crops<'mc> { +impl<'mc> JNIRaw<'mc> for Diode<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3329,18 +3532,18 @@ impl<'mc> JNIRaw<'mc> for Crops<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Crops<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Diode<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Crops from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Diode from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Crops")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Diode")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Crops object, got {}", + "Invalid argument passed. Expected a Diode object, got {}", name ) .into()) @@ -3350,72 +3553,92 @@ impl<'mc> JNIInstantiatable<'mc> for Crops<'mc> { } } -impl<'mc> Crops<'mc> { - #[deprecated] - +impl<'mc> Diode<'mc> { + /// Constructs a diode switched on or off, with the specified delay and + /// facing the specified direction. pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: std::option::Option>>, - data: std::option::Option, - ) -> Result, Box> { + facing_direction: std::option::Option>>, + delay: std::option::Option, + state: std::option::Option, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = val_type { - sig += "Lorg/bukkit/Material;"; + if let Some(a) = facing_direction { + sig += "Lorg/bukkit/block/BlockFace;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); args.push(val_1); } - if let Some(a) = data { - sig += "B"; - let val_2 = jni::objects::JValueGen::Byte(a); + if let Some(a) = delay { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); args.push(val_2); } + if let Some(a) = state { + sig += "Z"; + let val_3 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_3); + } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Crops"); + let cls = jni.find_class("org/bukkit/material/Diode"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Crops::from_raw(&jni, res) + crate::material::Diode::from_raw(&jni, res) } - /// Gets the current growth state of this crop - /// For crops with only four growth states such as beetroot, only the values SEEDED, SMALL, TALL and RIPE will be - /// returned. - pub fn state(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/CropState;"); + /// Sets the delay of the repeater. + pub fn set_delay(&self, delay: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(delay); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDelay", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the delay of the repeater in ticks. + pub fn delay(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getState", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDelay", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::CropState::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Sets the growth state of this crop - /// For crops with only four growth states such as beetroot, the 8 CropStates are mapped into four states: - /// SEEDED, SMALL, TALL and RIPE - /// GERMINATED will change to SEEDED - /// VERY_SMALL will change to SMALL - /// MEDIUM will change to TALL - /// VERY_TALL will change to RIPE - pub fn set_state( + /// Sets the direction this diode is facing. + pub fn set_facing_direction( &self, - state: impl Into>, + face: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/CropState;)V"); + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(state.into().jni_object().clone()) + jni::objects::JObject::from_raw(face.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setState", + "setFacingDirection", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } + /// Gets the direction this diode is facing + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } #[doc(hidden)] pub fn internal_to_string(&self) -> Result> { @@ -3431,17 +3654,26 @@ impl<'mc> Crops<'mc> { .to_string()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Crops;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Diode;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Crops::from_raw(&self.jni_ref(), unsafe { + crate::material::Diode::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['getState', 'setState', 'toString', 'clone']) + /// Checks if the diode is powered. + pub fn is_powered(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + // SUPER CLASS: org.bukkit.material.MaterialData ( ['setDelay', 'getDelay', 'setFacingDirection', 'getFacing', 'toString', 'clone', 'isPowered']) /// Gets the raw data in this material pub fn data(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { @@ -3503,28 +3735,40 @@ impl<'mc> Crops<'mc> { } } -impl<'mc> std::string::ToString for Crops<'mc> { +impl<'mc> std::string::ToString for Diode<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling Crops.toString: {}", err), + Err(err) => format!("Error calling Diode.toString: {}", err), } } } -impl<'mc> Into> for Crops<'mc> { - fn into(self) -> crate::material::MaterialData<'mc> { - crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Crops into crate::material::MaterialData") +impl<'mc> Into> for Diode<'mc> { + fn into(self) -> crate::material::Directional<'mc> { + crate::material::Directional::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Diode into crate::material::Directional") + } +} +impl<'mc> Into> for Diode<'mc> { + fn into(self) -> crate::material::Redstone<'mc> { + crate::material::Redstone::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Diode into crate::material::Redstone") + } +} +impl<'mc> Into> for Diode<'mc> { + fn into(self) -> crate::material::MaterialData<'mc> { + crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Diode into crate::material::MaterialData") } } #[repr(C)] -pub struct Door<'mc>( +pub struct Cake<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Door<'mc> { +impl<'mc> JNIRaw<'mc> for Cake<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3532,18 +3776,18 @@ impl<'mc> JNIRaw<'mc> for Door<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Door<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Cake<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Door from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Cake from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Door")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Cake")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Door object, got {}", + "Invalid argument passed. Expected a Cake object, got {}", name ) .into()) @@ -3553,120 +3797,82 @@ impl<'mc> JNIInstantiatable<'mc> for Door<'mc> { } } -impl<'mc> Door<'mc> { - /// Constructs the bottom half of a wooden door of the given species, facing the specified direction and set to open - /// or closed +impl<'mc> Cake<'mc> { + #[deprecated] + pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - species: std::option::Option>>, - face: std::option::Option>>, - is_open: std::option::Option, - ) -> Result, Box> { + val_type: std::option::Option>>, + data: std::option::Option, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = species { - sig += "Lorg/bukkit/TreeSpecies;"; + if let Some(a) = val_type { + sig += "Lorg/bukkit/Material;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); args.push(val_1); } - if let Some(a) = face { - sig += "Lorg/bukkit/block/BlockFace;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); + if let Some(a) = data { + sig += "B"; + let val_2 = jni::objects::JValueGen::Byte(a); args.push(val_2); } - if let Some(a) = is_open { - sig += "Z"; - let val_3 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_3); - } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Door"); + let cls = jni.find_class("org/bukkit/material/Cake"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Door::from_raw(&jni, res) + crate::material::Cake::from_raw(&jni, res) } - /// Returns the item type of a wooden door for the given tree species. - pub fn get_wood_door_of_species( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - species: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/TreeSpecies;)Lorg/bukkit/Material;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(species.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/material/Door"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getWoodDoorOfSpecies", + /// Gets the number of slices eaten from this cake + pub fn slices_eaten(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSlicesEaten", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the number of slices remaining on this cake + pub fn slices_remaining(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSlicesRemaining", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::Material::from_raw(&jni, obj) - } - /// Result is undefined if isTopHalf() is true. - pub fn is_open(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isOpen", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Set whether the door is open. Undefined if isTopHalf() is true. - pub fn set_open(&self, is_open: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(is_open.into()); + /// Sets the number of slices eaten from this cake + pub fn set_slices_eaten(&self, n: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(n); let res = self.jni_ref().call_method( &self.jni_object(), - "setOpen", + "setSlicesEaten", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn is_top_half(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isTopHalf", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Configure this part of the door to be either the top or the bottom half - pub fn set_top_half(&self, is_top_half: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(is_top_half.into()); + /// Sets the number of slices remaining on this cake + pub fn set_slices_remaining(&self, n: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(n); let res = self.jni_ref().call_method( &self.jni_object(), - "setTopHalf", + "setSlicesRemaining", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - #[deprecated] - - pub fn hinge_corner(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getHingeCorner", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } #[doc(hidden)] pub fn internal_to_string(&self) -> Result> { @@ -3681,73 +3887,18 @@ impl<'mc> Door<'mc> { .to_string_lossy() .to_string()) } - /// Set the direction that this door should is facing. - /// Undefined if isTopHalf() is true. - pub fn set_facing_direction( - &self, - face: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFacingDirection", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the direction that this door is facing. - /// Undefined if isTopHalf() is true. - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns the side of the door the hinge is on. - /// Undefined if isTopHalf() is false. - pub fn hinge(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHinge", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Set whether the hinge is on the left or right side. Left is false, right is true. - /// Undefined if isTopHalf() is false. - pub fn set_hinge(&self, is_hinge_right: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(is_hinge_right.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setHinge", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Door;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Cake;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Door::from_raw(&self.jni_ref(), unsafe { + crate::material::Cake::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['getWoodDoorOfSpecies', 'isOpen', 'setOpen', 'isTopHalf', 'setTopHalf', 'getHingeCorner', 'toString', 'setFacingDirection', 'getFacing', 'getHinge', 'setHinge', 'clone']) + // SUPER CLASS: org.bukkit.material.MaterialData ( ['getSlicesEaten', 'getSlicesRemaining', 'setSlicesEaten', 'setSlicesRemaining', 'toString', 'clone']) /// Gets the raw data in this material pub fn data(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { @@ -3809,40 +3960,28 @@ impl<'mc> Door<'mc> { } } -impl<'mc> std::string::ToString for Door<'mc> { +impl<'mc> std::string::ToString for Cake<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling Door.toString: {}", err), + Err(err) => format!("Error calling Cake.toString: {}", err), } } } -impl<'mc> Into> for Door<'mc> { - fn into(self) -> crate::material::Directional<'mc> { - crate::material::Directional::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Door into crate::material::Directional") - } -} -impl<'mc> Into> for Door<'mc> { - fn into(self) -> crate::material::Openable<'mc> { - crate::material::Openable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Door into crate::material::Openable") - } -} -impl<'mc> Into> for Door<'mc> { +impl<'mc> Into> for Cake<'mc> { fn into(self) -> crate::material::MaterialData<'mc> { crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Door into crate::material::MaterialData") + .expect("Error converting Cake into crate::material::MaterialData") } } #[repr(C)] -pub struct Mushroom<'mc>( +pub struct Bed<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Mushroom<'mc> { +impl<'mc> JNIRaw<'mc> for Bed<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3850,18 +3989,18 @@ impl<'mc> JNIRaw<'mc> for Mushroom<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Mushroom<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Bed<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Mushroom from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Bed from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Mushroom")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Bed")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Mushroom object, got {}", + "Invalid argument passed. Expected a Bed object, got {}", name ) .into()) @@ -3871,135 +4010,84 @@ impl<'mc> JNIInstantiatable<'mc> for Mushroom<'mc> { } } -impl<'mc> Mushroom<'mc> { +impl<'mc> Bed<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - shroom: impl Into>, + val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(shroom.into().jni_object().clone()) - }); - args.push(val_1); + if let Some(a) = val_type { + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } if let Some(a) = data { sig += "B"; let val_2 = jni::objects::JValueGen::Byte(a); args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Mushroom"); + let cls = jni.find_class("org/bukkit/material/Bed"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Mushroom::from_raw(&jni, res) + crate::material::Bed::from_raw(&jni, res) } - - pub fn is_stem(&self) -> Result> { + /// Determine if this block represents the head of the bed + pub fn is_head_of_bed(&self) -> Result> { let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isStem", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Sets this to be a mushroom stem. - pub fn set_stem(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setStem", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the mushroom texture of this block. - pub fn block_texture( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/types/MushroomBlockTexture;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getBlockTexture", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isHeadOfBed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::types::MushroomBlockTexture::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets the mushroom texture of this block. - pub fn set_block_texture( - &self, - texture: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/material/types/MushroomBlockTexture;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(texture.into().jni_object().clone()) - }); + /// Configure this to be either the head or the foot of the bed + pub fn set_head_of_bed(&self, is_head_of_bed: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(is_head_of_bed.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setBlockTexture", + "setHeadOfBed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Checks whether a face of the block is painted with cap texture. - pub fn is_face_painted( - &self, - face: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isFacePainted", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - #[deprecated] - /// Set a face of the block to be painted or not. Note that due to the nature of how the data is stored, setting a face painted or not is not guaranteed to leave the other faces unchanged. - pub fn set_face_painted( + /// Set which direction the head of the bed is facing. Note that this will + /// only affect one of the two blocks the bed is made of. + pub fn set_facing_direction( &self, face: impl Into>, - painted: bool, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;Z)V"); + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(face.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Bool(painted.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setFacePainted", + "setFacingDirection", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn painted_faces( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPaintedFaces", sig.as_str(), vec![]); + /// Get the direction that this bed's head is facing toward + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -4018,17 +4106,17 @@ impl<'mc> Mushroom<'mc> { .to_string()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Mushroom;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Bed;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Mushroom::from_raw(&self.jni_ref(), unsafe { + crate::material::Bed::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['isStem', 'setStem', 'getBlockTexture', 'setBlockTexture', 'isFacePainted', 'setFacePainted', 'getPaintedFaces', 'toString', 'clone']) + // SUPER CLASS: org.bukkit.material.MaterialData ( ['isHeadOfBed', 'setHeadOfBed', 'setFacingDirection', 'getFacing', 'toString', 'clone']) /// Gets the raw data in this material pub fn data(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { @@ -4090,28 +4178,34 @@ impl<'mc> Mushroom<'mc> { } } -impl<'mc> std::string::ToString for Mushroom<'mc> { +impl<'mc> std::string::ToString for Bed<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling Mushroom.toString: {}", err), + Err(err) => format!("Error calling Bed.toString: {}", err), } } } -impl<'mc> Into> for Mushroom<'mc> { +impl<'mc> Into> for Bed<'mc> { + fn into(self) -> crate::material::Directional<'mc> { + crate::material::Directional::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Bed into crate::material::Directional") + } +} +impl<'mc> Into> for Bed<'mc> { fn into(self) -> crate::material::MaterialData<'mc> { crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Mushroom into crate::material::MaterialData") + .expect("Error converting Bed into crate::material::MaterialData") } } #[repr(C)] -pub struct FurnaceAndDispenser<'mc>( +pub struct Banner<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for FurnaceAndDispenser<'mc> { +impl<'mc> JNIRaw<'mc> for Banner<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -4119,20 +4213,18 @@ impl<'mc> JNIRaw<'mc> for FurnaceAndDispenser<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for FurnaceAndDispenser<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Banner<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate FurnaceAndDispenser from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate Banner from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/FurnaceAndDispenser")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Banner")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a FurnaceAndDispenser object, got {}", + "Invalid argument passed. Expected a Banner object, got {}", name ) .into()) @@ -4142,95 +4234,201 @@ impl<'mc> JNIInstantiatable<'mc> for FurnaceAndDispenser<'mc> { } } -impl<'mc> FurnaceAndDispenser<'mc> { +impl<'mc> Banner<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: impl Into>, + val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - args.push(val_1); + if let Some(a) = val_type { + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } if let Some(a) = data { sig += "B"; let val_2 = jni::objects::JValueGen::Byte(a); args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/FurnaceAndDispenser"); + let cls = jni.find_class("org/bukkit/material/Banner"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::FurnaceAndDispenser::from_raw(&jni, res) + crate::material::Banner::from_raw(&jni, res) } - pub fn clone( + pub fn is_wall_banner(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isWallBanner", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn attached_face( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/FurnaceAndDispenser;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAttachedFace", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::FurnaceAndDispenser::from_raw(&self.jni_ref(), unsafe { + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.DirectionalContainer ( ['clone']) pub fn set_facing_direction( &self, face: impl Into>, ) -> Result<(), Box> { - let temp_clone = crate::material::DirectionalContainer::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::DirectionalContainer = temp_clone.into(); - real.set_facing_direction(face) - } - - pub fn facing(&self) -> Result, Box> { - let temp_clone = crate::material::DirectionalContainer::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::DirectionalContainer = temp_clone.into(); - real.facing() + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFacingDirection", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } #[doc(hidden)] pub fn internal_to_string(&self) -> Result> { - let temp_clone = crate::material::DirectionalContainer::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::DirectionalContainer = temp_clone.into(); - real.internal_to_string() + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Banner;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::material::Banner::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> Into> for FurnaceAndDispenser<'mc> { - fn into(self) -> crate::material::DirectionalContainer<'mc> { - crate::material::DirectionalContainer::from_raw(&self.jni_ref(), self.1).expect( - "Error converting FurnaceAndDispenser into crate::material::DirectionalContainer", - ) + // SUPER CLASS: org.bukkit.material.MaterialData ( ['isWallBanner', 'getAttachedFace', 'getFacing', 'setFacingDirection', 'toString', 'clone']) + /// Gets the raw data in this material + pub fn data(&self) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.data() } -} + /// Sets the raw data of this material + pub fn set_data(&self, data: i8) -> Result<(), Box> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.set_data(data) + } + /// Gets the Material that this MaterialData represents + pub fn item_type(&self) -> Result, Box> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.item_type() + } + /// Creates a new ItemStack based on this MaterialData + pub fn to_item_stack( + &self, + amount: std::option::Option, + ) -> Result, Box> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.to_item_stack(amount) + } + + pub fn hash_code(&self) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.hash_code() + } + + pub fn equals( + &self, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.equals(obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} + +impl<'mc> std::string::ToString for Banner<'mc> { + fn to_string(&self) -> String { + match &self.internal_to_string() { + Ok(a) => a.clone(), + Err(err) => format!("Error calling Banner.toString: {}", err), + } + } +} + +impl<'mc> Into> for Banner<'mc> { + fn into(self) -> crate::material::Attachable<'mc> { + crate::material::Attachable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Banner into crate::material::Attachable") + } +} +impl<'mc> Into> for Banner<'mc> { + fn into(self) -> crate::material::MaterialData<'mc> { + crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Banner into crate::material::MaterialData") + } +} #[repr(C)] -pub struct LongGrass<'mc>( +pub struct Button<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for LongGrass<'mc> { +impl<'mc> JNIRaw<'mc> for Button<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -4238,18 +4436,18 @@ impl<'mc> JNIRaw<'mc> for LongGrass<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for LongGrass<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Button<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate LongGrass from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Button from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/LongGrass")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Button")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a LongGrass object, got {}", + "Invalid argument passed. Expected a Button object, got {}", name ) .into()) @@ -4259,14 +4457,14 @@ impl<'mc> JNIInstantiatable<'mc> for LongGrass<'mc> { } } -impl<'mc> LongGrass<'mc> { +impl<'mc> Button<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); if let Some(a) = val_type { @@ -4282,35 +4480,60 @@ impl<'mc> LongGrass<'mc> { args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/LongGrass"); + let cls = jni.find_class("org/bukkit/material/Button"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::LongGrass::from_raw(&jni, res) + crate::material::Button::from_raw(&jni, res) } - /// Gets the current species of this grass - pub fn species(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/GrassSpecies;"); + /// Gets the current state of this Material, indicating if it's powered or + /// unpowered + pub fn is_powered(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the current state of this button + pub fn set_powered(&self, bool: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(bool.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPowered", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the face that this block is attached on + pub fn attached_face( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getSpecies", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAttachedFace", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::GrassSpecies::from_raw(&self.jni_ref(), unsafe { + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the species of this grass - pub fn set_species( + /// Sets the direction this button is pointing toward + pub fn set_facing_direction( &self, - species: impl Into>, + face: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/GrassSpecies;)V"); + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(species.into().jni_object().clone()) + jni::objects::JObject::from_raw(face.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setSpecies", + "setFacingDirection", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -4332,70 +4555,25 @@ impl<'mc> LongGrass<'mc> { .to_string()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/LongGrass;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Button;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::LongGrass::from_raw(&self.jni_ref(), unsafe { + crate::material::Button::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['getSpecies', 'setSpecies', 'toString', 'clone']) - /// Gets the raw data in this material - pub fn data(&self) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.data() - } - /// Sets the raw data of this material - pub fn set_data(&self, data: i8) -> Result<(), Box> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.set_data(data) - } - /// Gets the Material that this MaterialData represents - pub fn item_type(&self) -> Result, Box> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.item_type() - } - /// Creates a new ItemStack based on this MaterialData - pub fn to_item_stack( - &self, - amount: std::option::Option, - ) -> Result, Box> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.to_item_stack(amount) - } - - pub fn hash_code(&self) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.hash_code() - } + // SUPER CLASS: org.bukkit.material.SimpleAttachableMaterialData ( ['isPowered', 'setPowered', 'getAttachedFace', 'setFacingDirection', 'toString', 'clone']) - pub fn equals( - &self, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.equals(obj) + pub fn facing(&self) -> Result, Box> { + let temp_clone = + crate::material::SimpleAttachableMaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::SimpleAttachableMaterialData = temp_clone.into(); + real.facing() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -4404,28 +4582,34 @@ impl<'mc> LongGrass<'mc> { } } -impl<'mc> std::string::ToString for LongGrass<'mc> { +impl<'mc> std::string::ToString for Button<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling LongGrass.toString: {}", err), + Err(err) => format!("Error calling Button.toString: {}", err), } } } -impl<'mc> Into> for LongGrass<'mc> { - fn into(self) -> crate::material::MaterialData<'mc> { - crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting LongGrass into crate::material::MaterialData") +impl<'mc> Into> for Button<'mc> { + fn into(self) -> crate::material::Redstone<'mc> { + crate::material::Redstone::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Button into crate::material::Redstone") + } +} +impl<'mc> Into> for Button<'mc> { + fn into(self) -> crate::material::SimpleAttachableMaterialData<'mc> { + crate::material::SimpleAttachableMaterialData::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Button into crate::material::SimpleAttachableMaterialData") } } #[repr(C)] -pub struct Tripwire<'mc>( +pub struct Ladder<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Tripwire<'mc> { +impl<'mc> JNIRaw<'mc> for Ladder<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -4433,18 +4617,18 @@ impl<'mc> JNIRaw<'mc> for Tripwire<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Tripwire<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Ladder<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Tripwire from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Ladder from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Tripwire")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Ladder")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Tripwire object, got {}", + "Invalid argument passed. Expected a Ladder object, got {}", name ) .into()) @@ -4454,14 +4638,14 @@ impl<'mc> JNIInstantiatable<'mc> for Tripwire<'mc> { } } -impl<'mc> Tripwire<'mc> { +impl<'mc> Ladder<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); if let Some(a) = val_type { @@ -4477,53 +4661,37 @@ impl<'mc> Tripwire<'mc> { args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Tripwire"); + let cls = jni.find_class("org/bukkit/material/Ladder"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Tripwire::from_raw(&jni, res) + crate::material::Ladder::from_raw(&jni, res) } - /// Test if tripwire is currently activated - pub fn is_activated(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the face that this block is attached on + pub fn attached_face( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isActivated", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAttachedFace", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Set tripwire activated state - pub fn set_activated(&self, act: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(act.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setActivated", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Test if object triggering this tripwire directly - pub fn is_object_triggering(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isObjectTriggering", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set object triggering state for this tripwire - pub fn set_object_triggering(&self, trig: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(trig.into()); + /// Sets the direction this ladder is facing + pub fn set_facing_direction( + &self, + face: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setObjectTriggering", + "setFacingDirection", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -4531,84 +4699,35 @@ impl<'mc> Tripwire<'mc> { Ok(()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Tripwire;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Ladder;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Tripwire::from_raw(&self.jni_ref(), unsafe { + crate::material::Ladder::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } + // SUPER CLASS: org.bukkit.material.SimpleAttachableMaterialData ( ['getAttachedFace', 'setFacingDirection', 'clone']) - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['isActivated', 'setActivated', 'isObjectTriggering', 'setObjectTriggering', 'clone', 'toString']) - /// Gets the raw data in this material - pub fn data(&self) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.data() - } - /// Sets the raw data of this material - pub fn set_data(&self, data: i8) -> Result<(), Box> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.set_data(data) - } - /// Gets the Material that this MaterialData represents - pub fn item_type(&self) -> Result, Box> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.item_type() - } - /// Creates a new ItemStack based on this MaterialData - pub fn to_item_stack( - &self, - amount: std::option::Option, - ) -> Result, Box> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.to_item_stack(amount) - } - - pub fn hash_code(&self) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.hash_code() + pub fn facing(&self) -> Result, Box> { + let temp_clone = + crate::material::SimpleAttachableMaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::SimpleAttachableMaterialData = temp_clone.into(); + real.facing() } - pub fn equals( - &self, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.equals(obj) + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let temp_clone = + crate::material::SimpleAttachableMaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::SimpleAttachableMaterialData = temp_clone.into(); + real.internal_to_string() } pub fn instance_of(&self, other: impl Into) -> Result { @@ -4616,29 +4735,19 @@ impl<'mc> Tripwire<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } - -impl<'mc> std::string::ToString for Tripwire<'mc> { - fn to_string(&self) -> String { - match &self.internal_to_string() { - Ok(a) => a.clone(), - Err(err) => format!("Error calling Tripwire.toString: {}", err), - } - } -} - -impl<'mc> Into> for Tripwire<'mc> { - fn into(self) -> crate::material::MaterialData<'mc> { - crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Tripwire into crate::material::MaterialData") +impl<'mc> Into> for Ladder<'mc> { + fn into(self) -> crate::material::SimpleAttachableMaterialData<'mc> { + crate::material::SimpleAttachableMaterialData::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Ladder into crate::material::SimpleAttachableMaterialData") } } #[repr(C)] -pub struct SmoothBrick<'mc>( +pub struct PoweredRail<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for SmoothBrick<'mc> { +impl<'mc> JNIRaw<'mc> for PoweredRail<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -4646,18 +4755,18 @@ impl<'mc> JNIRaw<'mc> for SmoothBrick<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for SmoothBrick<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PoweredRail<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate SmoothBrick from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate PoweredRail from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/SmoothBrick")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/PoweredRail")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a SmoothBrick object, got {}", + "Invalid argument passed. Expected a PoweredRail object, got {}", name ) .into()) @@ -4667,14 +4776,14 @@ impl<'mc> JNIInstantiatable<'mc> for SmoothBrick<'mc> { } } -impl<'mc> SmoothBrick<'mc> { +impl<'mc> PoweredRail<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); if let Some(a) = val_type { @@ -4690,67 +4799,65 @@ impl<'mc> SmoothBrick<'mc> { args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/SmoothBrick"); + let cls = jni.find_class("org/bukkit/material/PoweredRail"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::SmoothBrick::from_raw(&jni, res) + crate::material::PoweredRail::from_raw(&jni, res) } - pub fn textures(&self) -> Result>, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTextures", sig.as_str(), vec![]); + pub fn is_powered(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::Material::from_raw(&self.0, obj)?); - } - Ok(new_vec) + Ok(res.z()?) + } + /// Set whether this PoweredRail should be powered or not. + pub fn set_powered(&self, is_powered: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(is_powered.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPowered", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/SmoothBrick;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/PoweredRail;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::SmoothBrick::from_raw(&self.jni_ref(), unsafe { + crate::material::PoweredRail::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.TexturedMaterial ( ['getTextures', 'clone']) - /// Gets the current Material this block is made of - pub fn material(&self) -> Result, Box> { - let temp_clone = crate::material::TexturedMaterial::from_raw(&self.0, unsafe { + // SUPER CLASS: org.bukkit.material.ExtendedRails ( ['isPowered', 'setPowered', 'clone']) + + pub fn is_curve(&self) -> Result> { + let temp_clone = crate::material::ExtendedRails::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::material::TexturedMaterial = temp_clone.into(); - real.material() + let real: crate::material::ExtendedRails = temp_clone.into(); + real.is_curve() } - /// Sets the material this block is made of - pub fn set_material( + + pub fn set_direction( &self, - material: impl Into>, + face: impl Into>, + is_on_slope: bool, ) -> Result<(), Box> { - let temp_clone = crate::material::TexturedMaterial::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::TexturedMaterial = temp_clone.into(); - real.set_material(material) - } - - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let temp_clone = crate::material::TexturedMaterial::from_raw(&self.0, unsafe { + let temp_clone = crate::material::ExtendedRails::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::material::TexturedMaterial = temp_clone.into(); - real.internal_to_string() + let real: crate::material::ExtendedRails = temp_clone.into(); + real.set_direction(face, is_on_slope) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -4758,19 +4865,25 @@ impl<'mc> SmoothBrick<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for SmoothBrick<'mc> { - fn into(self) -> crate::material::TexturedMaterial<'mc> { - crate::material::TexturedMaterial::from_raw(&self.jni_ref(), self.1) - .expect("Error converting SmoothBrick into crate::material::TexturedMaterial") +impl<'mc> Into> for PoweredRail<'mc> { + fn into(self) -> crate::material::Redstone<'mc> { + crate::material::Redstone::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PoweredRail into crate::material::Redstone") + } +} +impl<'mc> Into> for PoweredRail<'mc> { + fn into(self) -> crate::material::ExtendedRails<'mc> { + crate::material::ExtendedRails::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PoweredRail into crate::material::ExtendedRails") } } #[repr(C)] -pub struct TexturedMaterial<'mc>( +pub struct SpawnEgg<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for TexturedMaterial<'mc> { +impl<'mc> JNIRaw<'mc> for SpawnEgg<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -4778,20 +4891,18 @@ impl<'mc> JNIRaw<'mc> for TexturedMaterial<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for TexturedMaterial<'mc> { +impl<'mc> JNIInstantiatable<'mc> for SpawnEgg<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate TexturedMaterial from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate SpawnEgg from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/TexturedMaterial")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/SpawnEgg")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a TexturedMaterial object, got {}", + "Invalid argument passed. Expected a SpawnEgg object, got {}", name ) .into()) @@ -4801,56 +4912,62 @@ impl<'mc> JNIInstantiatable<'mc> for TexturedMaterial<'mc> { } } -impl<'mc> TexturedMaterial<'mc> { +impl<'mc> SpawnEgg<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: impl Into>, + val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - args.push(val_1); + if let Some(a) = val_type { + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } if let Some(a) = data { sig += "B"; let val_2 = jni::objects::JValueGen::Byte(a); args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/TexturedMaterial"); + let cls = jni.find_class("org/bukkit/material/SpawnEgg"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::TexturedMaterial::from_raw(&jni, res) + crate::material::SpawnEgg::from_raw(&jni, res) } - /// Gets the current Material this block is made of - pub fn material(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); + #[deprecated] + /// Get the type of entity this egg will spawn. + pub fn spawned_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getMaterial", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSpawnedType", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { + crate::entity::EntityType::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the material this block is made of - pub fn set_material( + #[deprecated] + /// Set the type of entity this egg will spawn. + pub fn set_spawned_type( &self, - material: impl Into>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/Material;)V"); + let sig = String::from("(Lorg/bukkit/entity/EntityType;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(material.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setMaterial", + "setSpawnedType", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -4872,19 +4989,17 @@ impl<'mc> TexturedMaterial<'mc> { .to_string()) } - pub fn clone( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/TexturedMaterial;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/SpawnEgg;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::TexturedMaterial::from_raw(&self.jni_ref(), unsafe { + crate::material::SpawnEgg::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['getMaterial', 'setMaterial', 'toString', 'clone']) + // SUPER CLASS: org.bukkit.material.MaterialData ( ['getSpawnedType', 'setSpawnedType', 'toString', 'clone']) /// Gets the raw data in this material pub fn data(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { @@ -4946,28 +5061,28 @@ impl<'mc> TexturedMaterial<'mc> { } } -impl<'mc> std::string::ToString for TexturedMaterial<'mc> { +impl<'mc> std::string::ToString for SpawnEgg<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling TexturedMaterial.toString: {}", err), + Err(err) => format!("Error calling SpawnEgg.toString: {}", err), } } } -impl<'mc> Into> for TexturedMaterial<'mc> { +impl<'mc> Into> for SpawnEgg<'mc> { fn into(self) -> crate::material::MaterialData<'mc> { crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting TexturedMaterial into crate::material::MaterialData") + .expect("Error converting SpawnEgg into crate::material::MaterialData") } } #[repr(C)] -pub struct Furnace<'mc>( +pub struct PistonExtensionMaterial<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Furnace<'mc> { +impl<'mc> JNIRaw<'mc> for PistonExtensionMaterial<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -4975,18 +5090,22 @@ impl<'mc> JNIRaw<'mc> for Furnace<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Furnace<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PistonExtensionMaterial<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Furnace from null object.").into()); + return Err(eyre::eyre!( + "Tried to instantiate PistonExtensionMaterial from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Furnace")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/material/PistonExtensionMaterial")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Furnace object, got {}", + "Invalid argument passed. Expected a PistonExtensionMaterial object, got {}", name ) .into()) @@ -4996,140 +5115,78 @@ impl<'mc> JNIInstantiatable<'mc> for Furnace<'mc> { } } -impl<'mc> Furnace<'mc> { +impl<'mc> PistonExtensionMaterial<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: std::option::Option>>, + val_type: impl Into>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = val_type { - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + args.push(val_1); if let Some(a) = data { sig += "B"; let val_2 = jni::objects::JValueGen::Byte(a); args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Furnace"); + let cls = jni.find_class("org/bukkit/material/PistonExtensionMaterial"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Furnace::from_raw(&jni, res) + crate::material::PistonExtensionMaterial::from_raw(&jni, res) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Furnace;"); + pub fn set_facing_direction( + &self, + face: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFacingDirection", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Furnace::from_raw(&self.jni_ref(), unsafe { + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.FurnaceAndDispenser ( ['clone']) - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Furnace<'mc> { - fn into(self) -> crate::material::FurnaceAndDispenser<'mc> { - crate::material::FurnaceAndDispenser::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Furnace into crate::material::FurnaceAndDispenser") - } -} -#[repr(C)] -pub struct Command<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Command<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Command<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Command from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Command")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Command object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Command<'mc> { - #[deprecated] - - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: std::option::Option>>, - data: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = val_type { - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - if let Some(a) = data { - sig += "B"; - let val_2 = jni::objects::JValueGen::Byte(a); - args.push(val_2); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Command"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::material::Command::from_raw(&jni, res) - } - /// Gets the current state of this Material, indicating if it's powered or - /// unpowered - pub fn is_powered(&self) -> Result> { + /// Checks if this piston extension is sticky, and returns true if so + pub fn is_sticky(&self) -> Result> { let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isSticky", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the current state of this Material - pub fn set_powered(&self, bool: bool) -> Result<(), Box> { + /// Sets whether or not this extension is sticky + pub fn set_sticky(&self, sticky: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(bool.into()); + let val_1 = jni::objects::JValueGen::Bool(sticky.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setPowered", + "setSticky", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -5137,31 +5194,32 @@ impl<'mc> Command<'mc> { Ok(()) } - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + pub fn attached_face( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAttachedFace", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Command;"); + pub fn clone( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/PistonExtensionMaterial;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Command::from_raw(&self.jni_ref(), unsafe { + crate::material::PistonExtensionMaterial::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['isPowered', 'setPowered', 'toString', 'clone']) + // SUPER CLASS: org.bukkit.material.MaterialData ( ['setFacingDirection', 'getFacing', 'isSticky', 'setSticky', 'getAttachedFace', 'clone']) /// Gets the raw data in this material pub fn data(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { @@ -5198,6 +5256,15 @@ impl<'mc> Command<'mc> { real.to_item_stack(amount) } + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.internal_to_string() + } + pub fn hash_code(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) @@ -5222,35 +5289,25 @@ impl<'mc> Command<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } - -impl<'mc> std::string::ToString for Command<'mc> { - fn to_string(&self) -> String { - match &self.internal_to_string() { - Ok(a) => a.clone(), - Err(err) => format!("Error calling Command.toString: {}", err), - } - } -} - -impl<'mc> Into> for Command<'mc> { - fn into(self) -> crate::material::Redstone<'mc> { - crate::material::Redstone::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Command into crate::material::Redstone") +impl<'mc> Into> for PistonExtensionMaterial<'mc> { + fn into(self) -> crate::material::Attachable<'mc> { + crate::material::Attachable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PistonExtensionMaterial into crate::material::Attachable") } } -impl<'mc> Into> for Command<'mc> { +impl<'mc> Into> for PistonExtensionMaterial<'mc> { fn into(self) -> crate::material::MaterialData<'mc> { crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Command into crate::material::MaterialData") + .expect("Error converting PistonExtensionMaterial into crate::material::MaterialData") } } #[repr(C)] -pub struct Diode<'mc>( +pub struct Cauldron<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Diode<'mc> { +impl<'mc> JNIRaw<'mc> for Cauldron<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -5258,18 +5315,18 @@ impl<'mc> JNIRaw<'mc> for Diode<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Diode<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Cauldron<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Diode from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Cauldron from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Diode")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Cauldron")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Diode object, got {}", + "Invalid argument passed. Expected a Cauldron object, got {}", name ) .into()) @@ -5279,91 +5336,52 @@ impl<'mc> JNIInstantiatable<'mc> for Diode<'mc> { } } -impl<'mc> Diode<'mc> { - /// Constructs a diode switched on or off, with the specified delay and - /// facing the specified direction. +impl<'mc> Cauldron<'mc> { + #[deprecated] + pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - facing_direction: std::option::Option>>, - delay: std::option::Option, - state: std::option::Option, - ) -> Result, Box> { + val_type: std::option::Option>>, + data: std::option::Option, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = facing_direction { - sig += "Lorg/bukkit/block/BlockFace;"; + if let Some(a) = val_type { + sig += "Lorg/bukkit/Material;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); args.push(val_1); } - if let Some(a) = delay { - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(a); + if let Some(a) = data { + sig += "B"; + let val_2 = jni::objects::JValueGen::Byte(a); args.push(val_2); } - if let Some(a) = state { - sig += "Z"; - let val_3 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_3); - } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Diode"); + let cls = jni.find_class("org/bukkit/material/Cauldron"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Diode::from_raw(&jni, res) - } - /// Sets the delay of the repeater. - pub fn set_delay(&self, delay: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(delay); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setDelay", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::material::Cauldron::from_raw(&jni, res) } - /// Gets the delay of the repeater in ticks. - pub fn delay(&self) -> Result> { - let sig = String::from("()I"); + /// Check if the cauldron is full. + pub fn is_full(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getDelay", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isFull", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Sets the direction this diode is facing. - pub fn set_facing_direction( - &self, - face: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFacingDirection", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.z()?) } - /// Gets the direction this diode is facing - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + /// Check if the cauldron is empty. + pub fn is_empty(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isEmpty", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } #[doc(hidden)] @@ -5380,26 +5398,17 @@ impl<'mc> Diode<'mc> { .to_string()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Diode;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Cauldron;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Diode::from_raw(&self.jni_ref(), unsafe { + crate::material::Cauldron::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Checks if the diode is powered. - pub fn is_powered(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['setDelay', 'getDelay', 'setFacingDirection', 'getFacing', 'toString', 'clone', 'isPowered']) + // SUPER CLASS: org.bukkit.material.MaterialData ( ['isFull', 'isEmpty', 'toString', 'clone']) /// Gets the raw data in this material pub fn data(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { @@ -5461,40 +5470,28 @@ impl<'mc> Diode<'mc> { } } -impl<'mc> std::string::ToString for Diode<'mc> { +impl<'mc> std::string::ToString for Cauldron<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling Diode.toString: {}", err), + Err(err) => format!("Error calling Cauldron.toString: {}", err), } } } -impl<'mc> Into> for Diode<'mc> { - fn into(self) -> crate::material::Directional<'mc> { - crate::material::Directional::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Diode into crate::material::Directional") - } -} -impl<'mc> Into> for Diode<'mc> { - fn into(self) -> crate::material::Redstone<'mc> { - crate::material::Redstone::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Diode into crate::material::Redstone") - } -} -impl<'mc> Into> for Diode<'mc> { +impl<'mc> Into> for Cauldron<'mc> { fn into(self) -> crate::material::MaterialData<'mc> { crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Diode into crate::material::MaterialData") + .expect("Error converting Cauldron into crate::material::MaterialData") } } #[repr(C)] -pub struct Comparator<'mc>( +pub struct RedstoneTorch<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Comparator<'mc> { +impl<'mc> JNIRaw<'mc> for RedstoneTorch<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -5502,18 +5499,18 @@ impl<'mc> JNIRaw<'mc> for Comparator<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Comparator<'mc> { +impl<'mc> JNIInstantiatable<'mc> for RedstoneTorch<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Comparator from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate RedstoneTorch from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Comparator")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/RedstoneTorch")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Comparator object, got {}", + "Invalid argument passed. Expected a RedstoneTorch object, got {}", name ) .into()) @@ -5523,97 +5520,45 @@ impl<'mc> JNIInstantiatable<'mc> for Comparator<'mc> { } } -impl<'mc> Comparator<'mc> { - /// Constructs a comparator switched on or off, with the specified mode and facing the specified direction. +impl<'mc> RedstoneTorch<'mc> { + #[deprecated] + pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - facing_direction: std::option::Option>>, - is_subtraction: std::option::Option, - state: std::option::Option, - ) -> Result, Box> { + val_type: std::option::Option>>, + data: std::option::Option, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = facing_direction { - sig += "Lorg/bukkit/block/BlockFace;"; + if let Some(a) = val_type { + sig += "Lorg/bukkit/Material;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); args.push(val_1); } - if let Some(a) = is_subtraction { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); + if let Some(a) = data { + sig += "B"; + let val_2 = jni::objects::JValueGen::Byte(a); args.push(val_2); } - if let Some(a) = state { - sig += "Z"; - let val_3 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_3); - } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Comparator"); + let cls = jni.find_class("org/bukkit/material/RedstoneTorch"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Comparator::from_raw(&jni, res) - } - /// Sets whether the comparator is in subtraction mode. - pub fn set_subtraction_mode( - &self, - is_subtraction: bool, - ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(is_subtraction.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSubtractionMode", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::material::RedstoneTorch::from_raw(&jni, res) } - /// Checks whether the comparator is in subtraction mode - pub fn is_subtraction_mode(&self) -> Result> { + /// Gets the current state of this Material, indicating if it's powered or + /// unpowered + pub fn is_powered(&self) -> Result> { let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isSubtractionMode", - sig.as_str(), - vec![], - ); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Sets the direction this comparator is facing - pub fn set_facing_direction( - &self, - face: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFacingDirection", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the direction this comparator is facing - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } #[doc(hidden)] pub fn internal_to_string(&self) -> Result> { @@ -5629,88 +5574,37 @@ impl<'mc> Comparator<'mc> { .to_string()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Comparator;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/RedstoneTorch;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Comparator::from_raw(&self.jni_ref(), unsafe { + crate::material::RedstoneTorch::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Checks if the comparator is powered - pub fn is_powered(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Checks if the comparator is being powered - pub fn is_being_powered(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isBeingPowered", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['setSubtractionMode', 'isSubtractionMode', 'setFacingDirection', 'getFacing', 'toString', 'clone', 'isPowered', 'isBeingPowered']) - /// Gets the raw data in this material - pub fn data(&self) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.data() - } - /// Sets the raw data of this material - pub fn set_data(&self, data: i8) -> Result<(), Box> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.set_data(data) - } - /// Gets the Material that this MaterialData represents - pub fn item_type(&self) -> Result, Box> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.item_type() - } - /// Creates a new ItemStack based on this MaterialData - pub fn to_item_stack( + // SUPER CLASS: org.bukkit.material.Torch ( ['isPowered', 'toString', 'clone']) + /// Gets the face that this block is attached on + pub fn attached_face( &self, - amount: std::option::Option, - ) -> Result, Box> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.to_item_stack(amount) - } - - pub fn hash_code(&self) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + ) -> Result, Box> { + let temp_clone = crate::material::Torch::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.hash_code() + let real: crate::material::Torch = temp_clone.into(); + real.attached_face() } - pub fn equals( + pub fn set_facing_direction( &self, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + face: impl Into>, + ) -> Result<(), Box> { + let temp_clone = crate::material::Torch::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.equals(obj) + let real: crate::material::Torch = temp_clone.into(); + real.set_facing_direction(face) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -5719,40 +5613,34 @@ impl<'mc> Comparator<'mc> { } } -impl<'mc> std::string::ToString for Comparator<'mc> { +impl<'mc> std::string::ToString for RedstoneTorch<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling Comparator.toString: {}", err), + Err(err) => format!("Error calling RedstoneTorch.toString: {}", err), } } } -impl<'mc> Into> for Comparator<'mc> { - fn into(self) -> crate::material::Directional<'mc> { - crate::material::Directional::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Comparator into crate::material::Directional") - } -} -impl<'mc> Into> for Comparator<'mc> { +impl<'mc> Into> for RedstoneTorch<'mc> { fn into(self) -> crate::material::Redstone<'mc> { crate::material::Redstone::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Comparator into crate::material::Redstone") + .expect("Error converting RedstoneTorch into crate::material::Redstone") } } -impl<'mc> Into> for Comparator<'mc> { - fn into(self) -> crate::material::MaterialData<'mc> { - crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Comparator into crate::material::MaterialData") +impl<'mc> Into> for RedstoneTorch<'mc> { + fn into(self) -> crate::material::Torch<'mc> { + crate::material::Torch::from_raw(&self.jni_ref(), self.1) + .expect("Error converting RedstoneTorch into crate::material::Torch") } } #[repr(C)] -pub struct NetherWarts<'mc>( +pub struct PistonBaseMaterial<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for NetherWarts<'mc> { +impl<'mc> JNIRaw<'mc> for PistonBaseMaterial<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -5760,18 +5648,20 @@ impl<'mc> JNIRaw<'mc> for NetherWarts<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for NetherWarts<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PistonBaseMaterial<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate NetherWarts from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate PistonBaseMaterial from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/NetherWarts")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/PistonBaseMaterial")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a NetherWarts object, got {}", + "Invalid argument passed. Expected a PistonBaseMaterial object, got {}", name ) .into()) @@ -5781,58 +5671,45 @@ impl<'mc> JNIInstantiatable<'mc> for NetherWarts<'mc> { } } -impl<'mc> NetherWarts<'mc> { +impl<'mc> PistonBaseMaterial<'mc> { #[deprecated] - + /// Constructs a PistonBaseMaterial. pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: std::option::Option>>, + val_type: impl Into>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = val_type { - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + args.push(val_1); if let Some(a) = data { sig += "B"; let val_2 = jni::objects::JValueGen::Byte(a); args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/NetherWarts"); + let cls = jni.find_class("org/bukkit/material/PistonBaseMaterial"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::NetherWarts::from_raw(&jni, res) - } - /// Gets the current growth state of this nether wart - pub fn state(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NetherWartsState;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getState", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::NetherWartsState::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + crate::material::PistonBaseMaterial::from_raw(&jni, res) } - /// Sets the growth state of this nether wart - pub fn set_state( + + pub fn set_facing_direction( &self, - state: impl Into>, + face: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/NetherWartsState;)V"); + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(state.into().jni_object().clone()) + jni::objects::JObject::from_raw(face.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setState", + "setFacingDirection", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -5840,31 +5717,61 @@ impl<'mc> NetherWarts<'mc> { Ok(()) } - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn is_powered(&self) -> Result> { + let sig = String::from("()Z"); + let res = self .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the current state of this piston + pub fn set_powered(&self, powered: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(powered.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPowered", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks if this piston base is sticky, and returns true if so + pub fn is_sticky(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isSticky", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/NetherWarts;"); + pub fn clone( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/PistonBaseMaterial;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::NetherWarts::from_raw(&self.jni_ref(), unsafe { + crate::material::PistonBaseMaterial::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['getState', 'setState', 'toString', 'clone']) + // SUPER CLASS: org.bukkit.material.MaterialData ( ['setFacingDirection', 'getFacing', 'isPowered', 'setPowered', 'isSticky', 'clone']) /// Gets the raw data in this material pub fn data(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { @@ -5901,6 +5808,15 @@ impl<'mc> NetherWarts<'mc> { real.to_item_stack(amount) } + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.internal_to_string() + } + pub fn hash_code(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) @@ -5925,29 +5841,31 @@ impl<'mc> NetherWarts<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } - -impl<'mc> std::string::ToString for NetherWarts<'mc> { - fn to_string(&self) -> String { - match &self.internal_to_string() { - Ok(a) => a.clone(), - Err(err) => format!("Error calling NetherWarts.toString: {}", err), - } +impl<'mc> Into> for PistonBaseMaterial<'mc> { + fn into(self) -> crate::material::Directional<'mc> { + crate::material::Directional::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PistonBaseMaterial into crate::material::Directional") } } - -impl<'mc> Into> for NetherWarts<'mc> { +impl<'mc> Into> for PistonBaseMaterial<'mc> { + fn into(self) -> crate::material::Redstone<'mc> { + crate::material::Redstone::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PistonBaseMaterial into crate::material::Redstone") + } +} +impl<'mc> Into> for PistonBaseMaterial<'mc> { fn into(self) -> crate::material::MaterialData<'mc> { crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting NetherWarts into crate::material::MaterialData") + .expect("Error converting PistonBaseMaterial into crate::material::MaterialData") } } #[repr(C)] -pub struct Bed<'mc>( +pub struct SimpleAttachableMaterialData<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Bed<'mc> { +impl<'mc> JNIRaw<'mc> for SimpleAttachableMaterialData<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -5955,18 +5873,22 @@ impl<'mc> JNIRaw<'mc> for Bed<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Bed<'mc> { +impl<'mc> JNIInstantiatable<'mc> for SimpleAttachableMaterialData<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Bed from null object.").into()); + return Err(eyre::eyre!( + "Tried to instantiate SimpleAttachableMaterialData from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Bed")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/material/SimpleAttachableMaterialData")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Bed object, got {}", + "Invalid argument passed. Expected a SimpleAttachableMaterialData object, got {}", name ) .into()) @@ -5976,77 +5898,35 @@ impl<'mc> JNIInstantiatable<'mc> for Bed<'mc> { } } -impl<'mc> Bed<'mc> { +impl<'mc> SimpleAttachableMaterialData<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: std::option::Option>>, + val_type: impl Into>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> + { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = val_type { - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + args.push(val_1); if let Some(a) = data { sig += "B"; let val_2 = jni::objects::JValueGen::Byte(a); args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Bed"); + let cls = jni.find_class("org/bukkit/material/SimpleAttachableMaterialData"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Bed::from_raw(&jni, res) - } - /// Determine if this block represents the head of the bed - pub fn is_head_of_bed(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isHeadOfBed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Configure this to be either the head or the foot of the bed - pub fn set_head_of_bed(&self, is_head_of_bed: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(is_head_of_bed.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setHeadOfBed", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Set which direction the head of the bed is facing. Note that this will - /// only affect one of the two blocks the bed is made of. - pub fn set_facing_direction( - &self, - face: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFacingDirection", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + crate::material::SimpleAttachableMaterialData::from_raw(&jni, res) } - /// Get the direction that this bed's head is facing toward + pub fn facing(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self @@ -6072,17 +5952,33 @@ impl<'mc> Bed<'mc> { .to_string()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Bed;"); + pub fn clone( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/material/SimpleAttachableMaterialData;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Bed::from_raw(&self.jni_ref(), unsafe { + crate::material::SimpleAttachableMaterialData::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['isHeadOfBed', 'setHeadOfBed', 'setFacingDirection', 'getFacing', 'toString', 'clone']) + /// Gets the face that this block is attached on + pub fn attached_face( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAttachedFace", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + // SUPER CLASS: org.bukkit.material.MaterialData ( ['getFacing', 'toString', 'clone', 'getAttachedFace']) /// Gets the raw data in this material pub fn data(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { @@ -6144,34 +6040,39 @@ impl<'mc> Bed<'mc> { } } -impl<'mc> std::string::ToString for Bed<'mc> { +impl<'mc> std::string::ToString for SimpleAttachableMaterialData<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling Bed.toString: {}", err), + Err(err) => format!( + "Error calling SimpleAttachableMaterialData.toString: {}", + err + ), } } } -impl<'mc> Into> for Bed<'mc> { - fn into(self) -> crate::material::Directional<'mc> { - crate::material::Directional::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Bed into crate::material::Directional") +impl<'mc> Into> for SimpleAttachableMaterialData<'mc> { + fn into(self) -> crate::material::Attachable<'mc> { + crate::material::Attachable::from_raw(&self.jni_ref(), self.1).expect( + "Error converting SimpleAttachableMaterialData into crate::material::Attachable", + ) } } -impl<'mc> Into> for Bed<'mc> { +impl<'mc> Into> for SimpleAttachableMaterialData<'mc> { fn into(self) -> crate::material::MaterialData<'mc> { - crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Bed into crate::material::MaterialData") + crate::material::MaterialData::from_raw(&self.jni_ref(), self.1).expect( + "Error converting SimpleAttachableMaterialData into crate::material::MaterialData", + ) } } #[repr(C)] -pub struct Chest<'mc>( +pub struct PressureSensor<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Chest<'mc> { +impl<'mc> JNIRaw<'mc> for PressureSensor<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6179,18 +6080,20 @@ impl<'mc> JNIRaw<'mc> for Chest<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Chest<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PressureSensor<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Chest from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate PressureSensor from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Chest")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/PressureSensor")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Chest object, got {}", + "Invalid argument passed. Expected a PressureSensor object, got {}", name ) .into()) @@ -6200,74 +6103,14 @@ impl<'mc> JNIInstantiatable<'mc> for Chest<'mc> { } } -impl<'mc> Chest<'mc> { - #[deprecated] - - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: std::option::Option>>, - data: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = val_type { - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - if let Some(a) = data { - sig += "B"; - let val_2 = jni::objects::JValueGen::Byte(a); - args.push(val_2); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Chest"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::material::Chest::from_raw(&jni, res) - } - - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Chest;"); +impl<'mc> PressureSensor<'mc> { + pub fn is_pressed(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isPressed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Chest::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - // SUPER CLASS: org.bukkit.material.DirectionalContainer ( ['clone']) - - pub fn set_facing_direction( - &self, - face: impl Into>, - ) -> Result<(), Box> { - let temp_clone = crate::material::DirectionalContainer::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::DirectionalContainer = temp_clone.into(); - real.set_facing_direction(face) - } - - pub fn facing(&self) -> Result, Box> { - let temp_clone = crate::material::DirectionalContainer::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::DirectionalContainer = temp_clone.into(); - real.facing() - } - - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let temp_clone = crate::material::DirectionalContainer::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::DirectionalContainer = temp_clone.into(); - real.internal_to_string() + Ok(res.z()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -6275,19 +6118,13 @@ impl<'mc> Chest<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Chest<'mc> { - fn into(self) -> crate::material::DirectionalContainer<'mc> { - crate::material::DirectionalContainer::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Chest into crate::material::DirectionalContainer") - } -} #[repr(C)] -pub struct Wood<'mc>( +pub struct Crops<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Wood<'mc> { +impl<'mc> JNIRaw<'mc> for Crops<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6295,18 +6132,18 @@ impl<'mc> JNIRaw<'mc> for Wood<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Wood<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Crops<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Wood from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Crops from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Wood")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Crops")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Wood object, got {}", + "Invalid argument passed. Expected a Crops object, got {}", name ) .into()) @@ -6316,14 +6153,14 @@ impl<'mc> JNIInstantiatable<'mc> for Wood<'mc> { } } -impl<'mc> Wood<'mc> { +impl<'mc> Crops<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); if let Some(a) = val_type { @@ -6339,35 +6176,43 @@ impl<'mc> Wood<'mc> { args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Wood"); + let cls = jni.find_class("org/bukkit/material/Crops"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Wood::from_raw(&jni, res) + crate::material::Crops::from_raw(&jni, res) } - /// Gets the current species of this wood block - pub fn species(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/TreeSpecies;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSpecies", sig.as_str(), vec![]); + /// Gets the current growth state of this crop + /// For crops with only four growth states such as beetroot, only the values SEEDED, SMALL, TALL and RIPE will be + /// returned. + pub fn state(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/CropState;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getState", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::TreeSpecies::from_raw(&self.jni_ref(), unsafe { + crate::CropState::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the species of this wood block - pub fn set_species( + /// Sets the growth state of this crop + /// For crops with only four growth states such as beetroot, the 8 CropStates are mapped into four states: + /// SEEDED, SMALL, TALL and RIPE + /// GERMINATED will change to SEEDED + /// VERY_SMALL will change to SMALL + /// MEDIUM will change to TALL + /// VERY_TALL will change to RIPE + pub fn set_state( &self, - species: impl Into>, + state: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/TreeSpecies;)V"); + let sig = String::from("(Lorg/bukkit/CropState;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(species.into().jni_object().clone()) + jni::objects::JObject::from_raw(state.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setSpecies", + "setState", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -6389,17 +6234,17 @@ impl<'mc> Wood<'mc> { .to_string()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Wood;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Crops;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Wood::from_raw(&self.jni_ref(), unsafe { + crate::material::Crops::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['getSpecies', 'setSpecies', 'toString', 'clone']) + // SUPER CLASS: org.bukkit.material.MaterialData ( ['getState', 'setState', 'toString', 'clone']) /// Gets the raw data in this material pub fn data(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { @@ -6461,28 +6306,28 @@ impl<'mc> Wood<'mc> { } } -impl<'mc> std::string::ToString for Wood<'mc> { +impl<'mc> std::string::ToString for Crops<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling Wood.toString: {}", err), + Err(err) => format!("Error calling Crops.toString: {}", err), } } } -impl<'mc> Into> for Wood<'mc> { +impl<'mc> Into> for Crops<'mc> { fn into(self) -> crate::material::MaterialData<'mc> { crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Wood into crate::material::MaterialData") + .expect("Error converting Crops into crate::material::MaterialData") } } #[repr(C)] -pub struct Openable<'mc>( +pub struct Door<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Openable<'mc> { +impl<'mc> JNIRaw<'mc> for Door<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6490,18 +6335,18 @@ impl<'mc> JNIRaw<'mc> for Openable<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Openable<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Door<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Openable from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Door from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Openable")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Door")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Openable object, got {}", + "Invalid argument passed. Expected a Door object, got {}", name ) .into()) @@ -6511,8 +6356,65 @@ impl<'mc> JNIInstantiatable<'mc> for Openable<'mc> { } } -impl<'mc> Openable<'mc> { - /// Check to see if the door is open. +impl<'mc> Door<'mc> { + /// Constructs the bottom half of a wooden door of the given species, facing the specified direction and set to open + /// or closed + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + species: std::option::Option>>, + face: std::option::Option>>, + is_open: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = species { + sig += "Lorg/bukkit/TreeSpecies;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + if let Some(a) = face { + sig += "Lorg/bukkit/block/BlockFace;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + if let Some(a) = is_open { + sig += "Z"; + let val_3 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_3); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/material/Door"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::material::Door::from_raw(&jni, res) + } + /// Returns the item type of a wooden door for the given tree species. + pub fn get_wood_door_of_species( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + species: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/TreeSpecies;)Lorg/bukkit/Material;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(species.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/material/Door"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getWoodDoorOfSpecies", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::Material::from_raw(&jni, obj) + } + /// Result is undefined if isTopHalf() is true. pub fn is_open(&self) -> Result> { let sig = String::from("()Z"); let res = self @@ -6521,7 +6423,7 @@ impl<'mc> Openable<'mc> { let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Configure this door to be either open or closed; + /// Set whether the door is open. Undefined if isTopHalf() is true. pub fn set_open(&self, is_open: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); let val_1 = jni::objects::JValueGen::Bool(is_open.into()); @@ -6535,109 +6437,55 @@ impl<'mc> Openable<'mc> { Ok(()) } - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct Banner<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Banner<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Banner<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Banner from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Banner")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Banner object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Banner<'mc> { - #[deprecated] - - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: std::option::Option>>, - data: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = val_type { - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - if let Some(a) = data { - sig += "B"; - let val_2 = jni::objects::JValueGen::Byte(a); - args.push(val_2); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Banner"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::material::Banner::from_raw(&jni, res) - } - - pub fn is_wall_banner(&self) -> Result> { + pub fn is_top_half(&self) -> Result> { let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isWallBanner", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isTopHalf", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } + /// Configure this part of the door to be either the top or the bottom half + pub fn set_top_half(&self, is_top_half: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(is_top_half.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setTopHalf", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + #[deprecated] - pub fn attached_face( - &self, - ) -> Result, Box> { + pub fn hinge_corner(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAttachedFace", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getHingeCorner", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - + /// Set the direction that this door should is facing. + /// Undefined if isTopHalf() is true. pub fn set_facing_direction( &self, face: impl Into>, @@ -6655,32 +6503,54 @@ impl<'mc> Banner<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Get the direction that this door is facing. + /// Undefined if isTopHalf() is true. + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Returns the side of the door the hinge is on. + /// Undefined if isTopHalf() is false. + pub fn hinge(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHinge", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set whether the hinge is on the left or right side. Left is false, right is true. + /// Undefined if isTopHalf() is false. + pub fn set_hinge(&self, is_hinge_right: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(is_hinge_right.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setHinge", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Banner;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Door;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Banner::from_raw(&self.jni_ref(), unsafe { + crate::material::Door::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['isWallBanner', 'getAttachedFace', 'getFacing', 'setFacingDirection', 'toString', 'clone']) + // SUPER CLASS: org.bukkit.material.MaterialData ( ['getWoodDoorOfSpecies', 'isOpen', 'setOpen', 'isTopHalf', 'setTopHalf', 'getHingeCorner', 'toString', 'setFacingDirection', 'getFacing', 'getHinge', 'setHinge', 'clone']) /// Gets the raw data in this material pub fn data(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { @@ -6742,34 +6612,40 @@ impl<'mc> Banner<'mc> { } } -impl<'mc> std::string::ToString for Banner<'mc> { +impl<'mc> std::string::ToString for Door<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling Banner.toString: {}", err), + Err(err) => format!("Error calling Door.toString: {}", err), } } } -impl<'mc> Into> for Banner<'mc> { - fn into(self) -> crate::material::Attachable<'mc> { - crate::material::Attachable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Banner into crate::material::Attachable") +impl<'mc> Into> for Door<'mc> { + fn into(self) -> crate::material::Directional<'mc> { + crate::material::Directional::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Door into crate::material::Directional") } } -impl<'mc> Into> for Banner<'mc> { +impl<'mc> Into> for Door<'mc> { + fn into(self) -> crate::material::Openable<'mc> { + crate::material::Openable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Door into crate::material::Openable") + } +} +impl<'mc> Into> for Door<'mc> { fn into(self) -> crate::material::MaterialData<'mc> { crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Banner into crate::material::MaterialData") + .expect("Error converting Door into crate::material::MaterialData") } } #[repr(C)] -pub struct Sandstone<'mc>( +pub struct FurnaceAndDispenser<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Sandstone<'mc> { +impl<'mc> JNIRaw<'mc> for FurnaceAndDispenser<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6777,18 +6653,20 @@ impl<'mc> JNIRaw<'mc> for Sandstone<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Sandstone<'mc> { +impl<'mc> JNIInstantiatable<'mc> for FurnaceAndDispenser<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Sandstone from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate FurnaceAndDispenser from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Sandstone")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/FurnaceAndDispenser")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Sandstone object, got {}", + "Invalid argument passed. Expected a FurnaceAndDispenser object, got {}", name ) .into()) @@ -6798,14 +6676,131 @@ impl<'mc> JNIInstantiatable<'mc> for Sandstone<'mc> { } } -impl<'mc> Sandstone<'mc> { +impl<'mc> FurnaceAndDispenser<'mc> { + #[deprecated] + + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + val_type: impl Into>, + data: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = data { + sig += "B"; + let val_2 = jni::objects::JValueGen::Byte(a); + args.push(val_2); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/material/FurnaceAndDispenser"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::material::FurnaceAndDispenser::from_raw(&jni, res) + } + + pub fn clone( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/FurnaceAndDispenser;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::material::FurnaceAndDispenser::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + // SUPER CLASS: org.bukkit.material.DirectionalContainer ( ['clone']) + + pub fn set_facing_direction( + &self, + face: impl Into>, + ) -> Result<(), Box> { + let temp_clone = crate::material::DirectionalContainer::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::DirectionalContainer = temp_clone.into(); + real.set_facing_direction(face) + } + + pub fn facing(&self) -> Result, Box> { + let temp_clone = crate::material::DirectionalContainer::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::DirectionalContainer = temp_clone.into(); + real.facing() + } + + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let temp_clone = crate::material::DirectionalContainer::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::DirectionalContainer = temp_clone.into(); + real.internal_to_string() + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for FurnaceAndDispenser<'mc> { + fn into(self) -> crate::material::DirectionalContainer<'mc> { + crate::material::DirectionalContainer::from_raw(&self.jni_ref(), self.1).expect( + "Error converting FurnaceAndDispenser into crate::material::DirectionalContainer", + ) + } +} +#[repr(C)] +pub struct LongGrass<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for LongGrass<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for LongGrass<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate LongGrass from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/LongGrass")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a LongGrass object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> LongGrass<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); if let Some(a) = val_type { @@ -6821,35 +6816,35 @@ impl<'mc> Sandstone<'mc> { args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Sandstone"); + let cls = jni.find_class("org/bukkit/material/LongGrass"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Sandstone::from_raw(&jni, res) + crate::material::LongGrass::from_raw(&jni, res) } - /// Gets the current type of this sandstone - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/SandstoneType;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + /// Gets the current species of this grass + pub fn species(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/GrassSpecies;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSpecies", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::SandstoneType::from_raw(&self.jni_ref(), unsafe { + crate::GrassSpecies::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the type of this sandstone - pub fn set_type( + /// Sets the species of this grass + pub fn set_species( &self, - val_type: impl Into>, + species: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/SandstoneType;)V"); + let sig = String::from("(Lorg/bukkit/GrassSpecies;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + jni::objects::JObject::from_raw(species.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setType", + "setSpecies", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -6871,17 +6866,17 @@ impl<'mc> Sandstone<'mc> { .to_string()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Sandstone;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/LongGrass;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Sandstone::from_raw(&self.jni_ref(), unsafe { + crate::material::LongGrass::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['getType', 'setType', 'toString', 'clone']) + // SUPER CLASS: org.bukkit.material.MaterialData ( ['getSpecies', 'setSpecies', 'toString', 'clone']) /// Gets the raw data in this material pub fn data(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { @@ -6943,28 +6938,28 @@ impl<'mc> Sandstone<'mc> { } } -impl<'mc> std::string::ToString for Sandstone<'mc> { +impl<'mc> std::string::ToString for LongGrass<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling Sandstone.toString: {}", err), + Err(err) => format!("Error calling LongGrass.toString: {}", err), } } } -impl<'mc> Into> for Sandstone<'mc> { +impl<'mc> Into> for LongGrass<'mc> { fn into(self) -> crate::material::MaterialData<'mc> { crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Sandstone into crate::material::MaterialData") + .expect("Error converting LongGrass into crate::material::MaterialData") } } #[repr(C)] -pub struct CocoaPlant<'mc>( +pub struct Furnace<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for CocoaPlant<'mc> { +impl<'mc> JNIRaw<'mc> for Furnace<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -6972,18 +6967,18 @@ impl<'mc> JNIRaw<'mc> for CocoaPlant<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for CocoaPlant<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Furnace<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate CocoaPlant from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Furnace from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/CocoaPlant")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Furnace")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a CocoaPlant object, got {}", + "Invalid argument passed. Expected a Furnace object, got {}", name ) .into()) @@ -6993,91 +6988,140 @@ impl<'mc> JNIInstantiatable<'mc> for CocoaPlant<'mc> { } } -impl<'mc> CocoaPlant<'mc> { +impl<'mc> Furnace<'mc> { + #[deprecated] + pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - sz: std::option::Option>>, - dir: std::option::Option>>, - ) -> Result, Box> { + val_type: std::option::Option>>, + data: std::option::Option, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = sz { - sig += "Lorg/bukkit/material/CocoaPlant/CocoaPlantSize;"; + if let Some(a) = val_type { + sig += "Lorg/bukkit/Material;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); args.push(val_1); } - if let Some(a) = dir { - sig += "Lorg/bukkit/block/BlockFace;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); + if let Some(a) = data { + sig += "B"; + let val_2 = jni::objects::JValueGen::Byte(a); args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/CocoaPlant"); + let cls = jni.find_class("org/bukkit/material/Furnace"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::CocoaPlant::from_raw(&jni, res) + crate::material::Furnace::from_raw(&jni, res) } - /// Get size of plant - pub fn size( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/CocoaPlant/CocoaPlantSize;"); + + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Furnace;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::CocoaPlantCocoaPlantSize::from_raw(&self.jni_ref(), unsafe { + crate::material::Furnace::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Set size of plant - pub fn set_size( - &self, - sz: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/material/CocoaPlant/CocoaPlantSize;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sz.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSize", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + // SUPER CLASS: org.bukkit.material.FurnaceAndDispenser ( ['clone']) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Furnace<'mc> { + fn into(self) -> crate::material::FurnaceAndDispenser<'mc> { + crate::material::FurnaceAndDispenser::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Furnace into crate::material::FurnaceAndDispenser") } +} +#[repr(C)] +pub struct Command<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); - pub fn attached_face( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAttachedFace", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +impl<'mc> JNIRaw<'mc> for Command<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Command<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Command from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Command")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Command object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } +} - pub fn set_facing_direction( - &self, - face: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); +impl<'mc> Command<'mc> { + #[deprecated] + + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + val_type: std::option::Option>>, + data: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = val_type { + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + if let Some(a) = data { + sig += "B"; + let val_2 = jni::objects::JValueGen::Byte(a); + args.push(val_2); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/material/Command"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::material::Command::from_raw(&jni, res) + } + /// Gets the current state of this Material, indicating if it's powered or + /// unpowered + pub fn is_powered(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the current state of this Material + pub fn set_powered(&self, bool: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(bool.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setFacingDirection", + "setPowered", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -7085,28 +7129,6 @@ impl<'mc> CocoaPlant<'mc> { Ok(()) } - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/CocoaPlant;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::material::CocoaPlant::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - #[doc(hidden)] pub fn internal_to_string(&self) -> Result> { let sig = String::from("()Ljava/lang/String;"); @@ -7120,7 +7142,18 @@ impl<'mc> CocoaPlant<'mc> { .to_string_lossy() .to_string()) } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['getSize', 'setSize', 'getAttachedFace', 'setFacingDirection', 'getFacing', 'clone', 'toString']) + + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Command;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::material::Command::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + // SUPER CLASS: org.bukkit.material.MaterialData ( ['isPowered', 'setPowered', 'toString', 'clone']) /// Gets the raw data in this material pub fn data(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { @@ -7182,192 +7215,53 @@ impl<'mc> CocoaPlant<'mc> { } } -impl<'mc> std::string::ToString for CocoaPlant<'mc> { +impl<'mc> std::string::ToString for Command<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling CocoaPlant.toString: {}", err), + Err(err) => format!("Error calling Command.toString: {}", err), } } } -impl<'mc> Into> for CocoaPlant<'mc> { - fn into(self) -> crate::material::Directional<'mc> { - crate::material::Directional::from_raw(&self.jni_ref(), self.1) - .expect("Error converting CocoaPlant into crate::material::Directional") - } -} -impl<'mc> Into> for CocoaPlant<'mc> { - fn into(self) -> crate::material::Attachable<'mc> { - crate::material::Attachable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting CocoaPlant into crate::material::Attachable") +impl<'mc> Into> for Command<'mc> { + fn into(self) -> crate::material::Redstone<'mc> { + crate::material::Redstone::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Command into crate::material::Redstone") } } -impl<'mc> Into> for CocoaPlant<'mc> { +impl<'mc> Into> for Command<'mc> { fn into(self) -> crate::material::MaterialData<'mc> { crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting CocoaPlant into crate::material::MaterialData") - } -} -pub enum CocoaPlantCocoaPlantSize<'mc> {} -impl<'mc> std::fmt::Display for CocoaPlantCocoaPlantSize<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> CocoaPlantCocoaPlantSize<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/material/CocoaPlant/CocoaPlantSize"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/material/CocoaPlant/CocoaPlantSize;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + .expect("Error converting Command into crate::material::MaterialData") } } - #[repr(C)] -pub struct CocoaPlantCocoaPlantSizeStruct<'mc>( +pub struct Comparator<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for CocoaPlantCocoaPlantSize<'mc> { +impl<'mc> JNIRaw<'mc> for Comparator<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + self.0.clone() } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for CocoaPlantCocoaPlantSize<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Comparator<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate CocoaPlantCocoaPlantSize from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/material/CocoaPlant/CocoaPlantSize")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a CocoaPlantCocoaPlantSize object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for CocoaPlantCocoaPlantSizeStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for CocoaPlantCocoaPlantSizeStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate CocoaPlantCocoaPlantSizeStruct from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/material/CocoaPlant/CocoaPlantSize")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a CocoaPlantCocoaPlantSizeStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> CocoaPlantCocoaPlantSizeStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/CocoaPlant/CocoaPlantSize;"); - let cls = jni.find_class("org/bukkit/material/CocoaPlant/CocoaPlantSize"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::material::CocoaPlantCocoaPlantSize::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct Skull<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Skull<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Skull<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Skull from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Comparator from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Skull")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Comparator")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Skull object, got {}", + "Invalid argument passed. Expected a Comparator object, got {}", name ) .into()) @@ -7377,36 +7271,69 @@ impl<'mc> JNIInstantiatable<'mc> for Skull<'mc> { } } -impl<'mc> Skull<'mc> { - #[deprecated] - +impl<'mc> Comparator<'mc> { + /// Constructs a comparator switched on or off, with the specified mode and facing the specified direction. pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: std::option::Option>>, - data: std::option::Option, - ) -> Result, Box> { + facing_direction: std::option::Option>>, + is_subtraction: std::option::Option, + state: std::option::Option, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = val_type { - sig += "Lorg/bukkit/Material;"; + if let Some(a) = facing_direction { + sig += "Lorg/bukkit/block/BlockFace;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); args.push(val_1); } - if let Some(a) = data { - sig += "B"; - let val_2 = jni::objects::JValueGen::Byte(a); + if let Some(a) = is_subtraction { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); args.push(val_2); } + if let Some(a) = state { + sig += "Z"; + let val_3 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_3); + } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Skull"); + let cls = jni.find_class("org/bukkit/material/Comparator"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Skull::from_raw(&jni, res) + crate::material::Comparator::from_raw(&jni, res) } - + /// Sets whether the comparator is in subtraction mode. + pub fn set_subtraction_mode( + &self, + is_subtraction: bool, + ) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(is_subtraction.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSubtractionMode", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Checks whether the comparator is in subtraction mode + pub fn is_subtraction_mode(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isSubtractionMode", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the direction this comparator is facing pub fn set_facing_direction( &self, face: impl Into>, @@ -7424,7 +7351,7 @@ impl<'mc> Skull<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - + /// Gets the direction this comparator is facing pub fn facing(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self @@ -7450,17 +7377,35 @@ impl<'mc> Skull<'mc> { .to_string()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Skull;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Comparator;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Skull::from_raw(&self.jni_ref(), unsafe { + crate::material::Comparator::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['setFacingDirection', 'getFacing', 'toString', 'clone']) + /// Checks if the comparator is powered + pub fn is_powered(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks if the comparator is being powered + pub fn is_being_powered(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isBeingPowered", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + // SUPER CLASS: org.bukkit.material.MaterialData ( ['setSubtractionMode', 'isSubtractionMode', 'setFacingDirection', 'getFacing', 'toString', 'clone', 'isPowered', 'isBeingPowered']) /// Gets the raw data in this material pub fn data(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { @@ -7522,34 +7467,40 @@ impl<'mc> Skull<'mc> { } } -impl<'mc> std::string::ToString for Skull<'mc> { +impl<'mc> std::string::ToString for Comparator<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling Skull.toString: {}", err), + Err(err) => format!("Error calling Comparator.toString: {}", err), } } } -impl<'mc> Into> for Skull<'mc> { +impl<'mc> Into> for Comparator<'mc> { fn into(self) -> crate::material::Directional<'mc> { crate::material::Directional::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Skull into crate::material::Directional") + .expect("Error converting Comparator into crate::material::Directional") } } -impl<'mc> Into> for Skull<'mc> { +impl<'mc> Into> for Comparator<'mc> { + fn into(self) -> crate::material::Redstone<'mc> { + crate::material::Redstone::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Comparator into crate::material::Redstone") + } +} +impl<'mc> Into> for Comparator<'mc> { fn into(self) -> crate::material::MaterialData<'mc> { crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Skull into crate::material::MaterialData") + .expect("Error converting Comparator into crate::material::MaterialData") } } #[repr(C)] -pub struct Sapling<'mc>( +pub struct NetherWarts<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Sapling<'mc> { +impl<'mc> JNIRaw<'mc> for NetherWarts<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -7557,18 +7508,18 @@ impl<'mc> JNIRaw<'mc> for Sapling<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Sapling<'mc> { +impl<'mc> JNIInstantiatable<'mc> for NetherWarts<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Sapling from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate NetherWarts from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Sapling")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/NetherWarts")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Sapling object, got {}", + "Invalid argument passed. Expected a NetherWarts object, got {}", name ) .into()) @@ -7578,57 +7529,58 @@ impl<'mc> JNIInstantiatable<'mc> for Sapling<'mc> { } } -impl<'mc> Sapling<'mc> { - /// Constructs a sapling of the given tree species and if is it instant - /// growable +impl<'mc> NetherWarts<'mc> { + #[deprecated] + pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - species: std::option::Option>>, - is_instant_growable: std::option::Option, - ) -> Result, Box> { + val_type: std::option::Option>>, + data: std::option::Option, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = species { - sig += "Lorg/bukkit/TreeSpecies;"; + if let Some(a) = val_type { + sig += "Lorg/bukkit/Material;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); args.push(val_1); } - if let Some(a) = is_instant_growable { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); + if let Some(a) = data { + sig += "B"; + let val_2 = jni::objects::JValueGen::Byte(a); args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Sapling"); + let cls = jni.find_class("org/bukkit/material/NetherWarts"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Sapling::from_raw(&jni, res) + crate::material::NetherWarts::from_raw(&jni, res) } - /// Checks if the Sapling would grow when next ticked with bonemeal - pub fn is_instant_growable(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isInstantGrowable", - sig.as_str(), - vec![], - ); + /// Gets the current growth state of this nether wart + pub fn state(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NetherWartsState;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getState", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::NetherWartsState::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Set whether this sapling will grow when next ticked with bonemeal - pub fn set_is_instant_growable( + /// Sets the growth state of this nether wart + pub fn set_state( &self, - is_instant_growable: bool, + state: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(is_instant_growable.into()); + let sig = String::from("(Lorg/bukkit/NetherWartsState;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(state.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setIsInstantGrowable", + "setState", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -7650,45 +7602,70 @@ impl<'mc> Sapling<'mc> { .to_string()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Sapling;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/NetherWarts;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Sapling::from_raw(&self.jni_ref(), unsafe { + crate::material::NetherWarts::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.Wood ( ['isInstantGrowable', 'setIsInstantGrowable', 'toString', 'clone']) - /// Gets the current species of this wood block - pub fn species(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/TreeSpecies;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSpecies", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::TreeSpecies::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + // SUPER CLASS: org.bukkit.material.MaterialData ( ['getState', 'setState', 'toString', 'clone']) + /// Gets the raw data in this material + pub fn data(&self) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.data() } - /// Sets the species of this wood block - pub fn set_species( + /// Sets the raw data of this material + pub fn set_data(&self, data: i8) -> Result<(), Box> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.set_data(data) + } + /// Gets the Material that this MaterialData represents + pub fn item_type(&self) -> Result, Box> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.item_type() + } + /// Creates a new ItemStack based on this MaterialData + pub fn to_item_stack( &self, - species: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/TreeSpecies;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(species.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSpecies", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + amount: std::option::Option, + ) -> Result, Box> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.to_item_stack(amount) + } + + pub fn hash_code(&self) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.hash_code() + } + + pub fn equals( + &self, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.equals(obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -7697,28 +7674,28 @@ impl<'mc> Sapling<'mc> { } } -impl<'mc> std::string::ToString for Sapling<'mc> { +impl<'mc> std::string::ToString for NetherWarts<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling Sapling.toString: {}", err), + Err(err) => format!("Error calling NetherWarts.toString: {}", err), } } } -impl<'mc> Into> for Sapling<'mc> { - fn into(self) -> crate::material::Wood<'mc> { - crate::material::Wood::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Sapling into crate::material::Wood") +impl<'mc> Into> for NetherWarts<'mc> { + fn into(self) -> crate::material::MaterialData<'mc> { + crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) + .expect("Error converting NetherWarts into crate::material::MaterialData") } } #[repr(C)] -pub struct Lever<'mc>( +pub struct Chest<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Lever<'mc> { +impl<'mc> JNIRaw<'mc> for Chest<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -7726,18 +7703,18 @@ impl<'mc> JNIRaw<'mc> for Lever<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Lever<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Chest<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Lever from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Chest from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Lever")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Chest")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Lever object, got {}", + "Invalid argument passed. Expected a Chest object, got {}", name ) .into()) @@ -7747,14 +7724,14 @@ impl<'mc> JNIInstantiatable<'mc> for Lever<'mc> { } } -impl<'mc> Lever<'mc> { +impl<'mc> Chest<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); if let Some(a) = val_type { @@ -7770,136 +7747,135 @@ impl<'mc> Lever<'mc> { args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Lever"); + let cls = jni.find_class("org/bukkit/material/Chest"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Lever::from_raw(&jni, res) + crate::material::Chest::from_raw(&jni, res) } - /// Gets the current state of this Material, indicating if it's powered or - /// unpowered - pub fn is_powered(&self) -> Result> { - let sig = String::from("()Z"); + + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Chest;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Set this lever to be powered or not. - pub fn set_powered(&self, is_powered: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(is_powered.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPowered", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the face that this block is attached on - pub fn attached_face( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAttachedFace", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + crate::material::Chest::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the direction this lever is pointing in + // SUPER CLASS: org.bukkit.material.DirectionalContainer ( ['clone']) + pub fn set_facing_direction( &self, face: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFacingDirection", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Lever;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::material::Lever::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let temp_clone = crate::material::DirectionalContainer::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::DirectionalContainer = temp_clone.into(); + real.set_facing_direction(face) } - // SUPER CLASS: org.bukkit.material.SimpleAttachableMaterialData ( ['isPowered', 'setPowered', 'getAttachedFace', 'setFacingDirection', 'toString', 'clone']) pub fn facing(&self) -> Result, Box> { - let temp_clone = - crate::material::SimpleAttachableMaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::SimpleAttachableMaterialData = temp_clone.into(); + let temp_clone = crate::material::DirectionalContainer::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::DirectionalContainer = temp_clone.into(); real.facing() } + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let temp_clone = crate::material::DirectionalContainer::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::DirectionalContainer = temp_clone.into(); + real.internal_to_string() + } + pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } - -impl<'mc> std::string::ToString for Lever<'mc> { - fn to_string(&self) -> String { - match &self.internal_to_string() { - Ok(a) => a.clone(), - Err(err) => format!("Error calling Lever.toString: {}", err), - } +impl<'mc> Into> for Chest<'mc> { + fn into(self) -> crate::material::DirectionalContainer<'mc> { + crate::material::DirectionalContainer::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Chest into crate::material::DirectionalContainer") } } - -impl<'mc> Into> for Lever<'mc> { - fn into(self) -> crate::material::Redstone<'mc> { - crate::material::Redstone::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Lever into crate::material::Redstone") +#[repr(C)] +pub struct Openable<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Openable<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> Into> for Lever<'mc> { - fn into(self) -> crate::material::SimpleAttachableMaterialData<'mc> { - crate::material::SimpleAttachableMaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Lever into crate::material::SimpleAttachableMaterialData") +impl<'mc> JNIInstantiatable<'mc> for Openable<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Openable from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Openable")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Openable object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Openable<'mc> { + /// Check to see if the door is open. + pub fn is_open(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isOpen", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Configure this door to be either open or closed; + pub fn set_open(&self, is_open: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(is_open.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setOpen", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } } #[repr(C)] -pub struct Dispenser<'mc>( +pub struct Sandstone<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Dispenser<'mc> { +impl<'mc> JNIRaw<'mc> for Sandstone<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -7907,18 +7883,18 @@ impl<'mc> JNIRaw<'mc> for Dispenser<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Dispenser<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Sandstone<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Dispenser from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Sandstone from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Dispenser")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Sandstone")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Dispenser object, got {}", + "Invalid argument passed. Expected a Sandstone object, got {}", name ) .into()) @@ -7928,14 +7904,14 @@ impl<'mc> JNIInstantiatable<'mc> for Dispenser<'mc> { } } -impl<'mc> Dispenser<'mc> { +impl<'mc> Sandstone<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); if let Some(a) = val_type { @@ -7951,24 +7927,35 @@ impl<'mc> Dispenser<'mc> { args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Dispenser"); + let cls = jni.find_class("org/bukkit/material/Sandstone"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Dispenser::from_raw(&jni, res) + crate::material::Sandstone::from_raw(&jni, res) } - - pub fn set_facing_direction( + /// Gets the current type of this sandstone + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/SandstoneType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::SandstoneType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the type of this sandstone + pub fn set_type( &self, - face: impl Into>, + val_type: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + let sig = String::from("(Lorg/bukkit/SandstoneType;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "setFacingDirection", + "setType", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -7976,47 +7963,114 @@ impl<'mc> Dispenser<'mc> { Ok(()) } - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Dispenser;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Sandstone;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Dispenser::from_raw(&self.jni_ref(), unsafe { + crate::material::Sandstone::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.FurnaceAndDispenser ( ['setFacingDirection', 'getFacing', 'clone']) + // SUPER CLASS: org.bukkit.material.MaterialData ( ['getType', 'setType', 'toString', 'clone']) + /// Gets the raw data in this material + pub fn data(&self) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.data() + } + /// Sets the raw data of this material + pub fn set_data(&self, data: i8) -> Result<(), Box> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.set_data(data) + } + /// Gets the Material that this MaterialData represents + pub fn item_type(&self) -> Result, Box> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.item_type() + } + /// Creates a new ItemStack based on this MaterialData + pub fn to_item_stack( + &self, + amount: std::option::Option, + ) -> Result, Box> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.to_item_stack(amount) + } + + pub fn hash_code(&self) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.hash_code() + } + + pub fn equals( + &self, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.equals(obj) + } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Dispenser<'mc> { - fn into(self) -> crate::material::FurnaceAndDispenser<'mc> { - crate::material::FurnaceAndDispenser::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Dispenser into crate::material::FurnaceAndDispenser") + +impl<'mc> std::string::ToString for Sandstone<'mc> { + fn to_string(&self) -> String { + match &self.internal_to_string() { + Ok(a) => a.clone(), + Err(err) => format!("Error calling Sandstone.toString: {}", err), + } + } +} + +impl<'mc> Into> for Sandstone<'mc> { + fn into(self) -> crate::material::MaterialData<'mc> { + crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Sandstone into crate::material::MaterialData") } } #[repr(C)] -pub struct Redstone<'mc>( +pub struct CocoaPlant<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Redstone<'mc> { +impl<'mc> JNIRaw<'mc> for CocoaPlant<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -8024,18 +8078,18 @@ impl<'mc> JNIRaw<'mc> for Redstone<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Redstone<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CocoaPlant<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Redstone from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate CocoaPlant from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Redstone")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/CocoaPlant")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Redstone object, got {}", + "Invalid argument passed. Expected a CocoaPlant object, got {}", name ) .into()) @@ -8045,60 +8099,67 @@ impl<'mc> JNIInstantiatable<'mc> for Redstone<'mc> { } } -impl<'mc> Redstone<'mc> { - /// Gets the current state of this Material, indicating if it's powered or - /// unpowered - pub fn is_powered(&self) -> Result> { - let sig = String::from("()Z"); +impl<'mc> CocoaPlant<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + sz: std::option::Option>>, + dir: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = sz { + sig += "Lorg/bukkit/material/CocoaPlant/CocoaPlantSize;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + if let Some(a) = dir { + sig += "Lorg/bukkit/block/BlockFace;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/material/CocoaPlant"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::material::CocoaPlant::from_raw(&jni, res) + } + /// Get size of plant + pub fn size( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/CocoaPlant/CocoaPlantSize;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getSize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct Attachable<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Attachable<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + crate::material::CocoaPlantCocoaPlantSize::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> JNIInstantiatable<'mc> for Attachable<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Attachable from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Attachable")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Attachable object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Set size of plant + pub fn set_size( + &self, + sz: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/material/CocoaPlant/CocoaPlantSize;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(sz.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSize", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -impl<'mc> Attachable<'mc> { - /// Gets the face that this block is attached on pub fn attached_face( &self, ) -> Result, Box> { @@ -8111,7 +8172,7 @@ impl<'mc> Attachable<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Sets the direction that this block is facing in + pub fn set_facing_direction( &self, face: impl Into>, @@ -8129,7 +8190,7 @@ impl<'mc> Attachable<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the direction this block is facing + pub fn facing(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self @@ -8141,104 +8202,253 @@ impl<'mc> Attachable<'mc> { }) } + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/CocoaPlant;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::material::CocoaPlant::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + // SUPER CLASS: org.bukkit.material.MaterialData ( ['getSize', 'setSize', 'getAttachedFace', 'setFacingDirection', 'getFacing', 'clone', 'toString']) + /// Gets the raw data in this material + pub fn data(&self) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.data() + } + /// Sets the raw data of this material + pub fn set_data(&self, data: i8) -> Result<(), Box> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.set_data(data) + } + /// Gets the Material that this MaterialData represents + pub fn item_type(&self) -> Result, Box> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.item_type() + } + /// Creates a new ItemStack based on this MaterialData + pub fn to_item_stack( + &self, + amount: std::option::Option, + ) -> Result, Box> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.to_item_stack(amount) + } + + pub fn hash_code(&self) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.hash_code() + } + + pub fn equals( + &self, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.equals(obj) + } + pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Attachable<'mc> { + +impl<'mc> std::string::ToString for CocoaPlant<'mc> { + fn to_string(&self) -> String { + match &self.internal_to_string() { + Ok(a) => a.clone(), + Err(err) => format!("Error calling CocoaPlant.toString: {}", err), + } + } +} + +impl<'mc> Into> for CocoaPlant<'mc> { fn into(self) -> crate::material::Directional<'mc> { crate::material::Directional::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Attachable into crate::material::Directional") + .expect("Error converting CocoaPlant into crate::material::Directional") + } +} +impl<'mc> Into> for CocoaPlant<'mc> { + fn into(self) -> crate::material::Attachable<'mc> { + crate::material::Attachable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting CocoaPlant into crate::material::Attachable") + } +} +impl<'mc> Into> for CocoaPlant<'mc> { + fn into(self) -> crate::material::MaterialData<'mc> { + crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) + .expect("Error converting CocoaPlant into crate::material::MaterialData") + } +} +pub enum CocoaPlantCocoaPlantSize<'mc> { + Small { + inner: CocoaPlantCocoaPlantSizeStruct<'mc>, + }, + Medium { + inner: CocoaPlantCocoaPlantSizeStruct<'mc>, + }, + Large { + inner: CocoaPlantCocoaPlantSizeStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for CocoaPlantCocoaPlantSize<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + CocoaPlantCocoaPlantSize::Small { .. } => f.write_str("SMALL"), + CocoaPlantCocoaPlantSize::Medium { .. } => f.write_str("MEDIUM"), + CocoaPlantCocoaPlantSize::Large { .. } => f.write_str("LARGE"), + } + } +} +impl<'mc> std::ops::Deref for CocoaPlantCocoaPlantSize<'mc> { + type Target = CocoaPlantCocoaPlantSizeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + CocoaPlantCocoaPlantSize::Small { inner } => inner, + CocoaPlantCocoaPlantSize::Medium { inner } => inner, + CocoaPlantCocoaPlantSize::Large { inner } => inner, + } + } +} + +impl<'mc> CocoaPlantCocoaPlantSize<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/material/CocoaPlant/CocoaPlantSize"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/material/CocoaPlant/CocoaPlantSize;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "SMALL" => Ok(CocoaPlantCocoaPlantSize::Small { + inner: CocoaPlantCocoaPlantSizeStruct::from_raw(env, obj)?, + }), + "MEDIUM" => Ok(CocoaPlantCocoaPlantSize::Medium { + inner: CocoaPlantCocoaPlantSizeStruct::from_raw(env, obj)?, + }), + "LARGE" => Ok(CocoaPlantCocoaPlantSize::Large { + inner: CocoaPlantCocoaPlantSizeStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } + #[repr(C)] -pub struct Colorable<'mc>( +pub struct CocoaPlantCocoaPlantSizeStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Colorable<'mc> { +impl<'mc> JNIRaw<'mc> for CocoaPlantCocoaPlantSize<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + match self { + Self::Small { inner } => inner.0.clone(), + Self::Medium { inner } => inner.0.clone(), + Self::Large { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + match self { + Self::Small { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Medium { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Large { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } -impl<'mc> JNIInstantiatable<'mc> for Colorable<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CocoaPlantCocoaPlantSize<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Colorable from null object.").into()); + return Err(eyre::eyre!( + "Tried to instantiate CocoaPlantCocoaPlantSize from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Colorable")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/material/CocoaPlant/CocoaPlantSize")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Colorable object, got {}", + "Invalid argument passed. Expected a CocoaPlantCocoaPlantSize object, got {}", name ) .into()) } else { - Ok(Self(env.clone(), obj)) + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "SMALL" => Ok(CocoaPlantCocoaPlantSize::Small { + inner: CocoaPlantCocoaPlantSizeStruct::from_raw(env, obj)?, + }), + "MEDIUM" => Ok(CocoaPlantCocoaPlantSize::Medium { + inner: CocoaPlantCocoaPlantSizeStruct::from_raw(env, obj)?, + }), + "LARGE" => Ok(CocoaPlantCocoaPlantSize::Large { + inner: CocoaPlantCocoaPlantSizeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } } -impl<'mc> Colorable<'mc> { - /// Gets the color of this object. - /// - /// This may be null to represent the default color of an object, if the - /// object has a special default color (e.g Shulkers). - pub fn color(&self) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/DyeColor;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::DyeColor::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?)) - } - /// Sets the color of this object to the specified DyeColor. - /// - /// This may be null to represent the default color of an object, if the - /// object has a special default color (e.g Shulkers). - pub fn set_color( - &self, - color: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/DyeColor;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setColor", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct Leaves<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Leaves<'mc> { +impl<'mc> JNIRaw<'mc> for CocoaPlantCocoaPlantSizeStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -8246,204 +8456,22 @@ impl<'mc> JNIRaw<'mc> for Leaves<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Leaves<'mc> { +impl<'mc> JNIInstantiatable<'mc> for CocoaPlantCocoaPlantSizeStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Leaves from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Leaves")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Leaves object, got {}", - name + return Err(eyre::eyre!( + "Tried to instantiate CocoaPlantCocoaPlantSizeStruct from null object." ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Leaves<'mc> { - /// Constructs a leaf block of the given tree species and flag for whether - /// this leaf block will disappear when too far from a log. - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - species: std::option::Option>>, - is_decayable: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = species { - sig += "Lorg/bukkit/TreeSpecies;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - if let Some(a) = is_decayable { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Leaves"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::material::Leaves::from_raw(&jni, res) - } - /// Checks if this leaf block is in the process of decaying - pub fn is_decaying(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isDecaying", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Set whether this leaf block is in the process of decaying - pub fn set_decaying(&self, is_decaying: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(is_decaying.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setDecaying", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks if this leaf block is permanent or can decay when too far from a - /// log - pub fn is_decayable(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isDecayable", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Set whether this leaf block will disappear when too far from a log - pub fn set_decayable(&self, is_decayable: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(is_decayable.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setDecayable", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Leaves;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::material::Leaves::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - // SUPER CLASS: org.bukkit.material.Wood ( ['isDecaying', 'setDecaying', 'isDecayable', 'setDecayable', 'toString', 'clone']) - /// Gets the current species of this wood block - pub fn species(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/TreeSpecies;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSpecies", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::TreeSpecies::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the species of this wood block - pub fn set_species( - &self, - species: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/TreeSpecies;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(species.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSpecies", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} - -impl<'mc> std::string::ToString for Leaves<'mc> { - fn to_string(&self) -> String { - match &self.internal_to_string() { - Ok(a) => a.clone(), - Err(err) => format!("Error calling Leaves.toString: {}", err), - } - } -} - -impl<'mc> Into> for Leaves<'mc> { - fn into(self) -> crate::material::Wood<'mc> { - crate::material::Wood::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Leaves into crate::material::Wood") - } -} -#[repr(C)] -pub struct DetectorRail<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for DetectorRail<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for DetectorRail<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate DetectorRail from null object.").into()); + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/DetectorRail")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/material/CocoaPlant/CocoaPlantSize")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a DetectorRail object, got {}", + "Invalid argument passed. Expected a CocoaPlantCocoaPlantSizeStruct object, got {}", name ) .into()) @@ -8453,88 +8481,17 @@ impl<'mc> JNIInstantiatable<'mc> for DetectorRail<'mc> { } } -impl<'mc> DetectorRail<'mc> { - #[deprecated] - - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: std::option::Option>>, - data: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = val_type { - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - if let Some(a) = data { - sig += "B"; - let val_2 = jni::objects::JValueGen::Byte(a); - args.push(val_2); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/material/DetectorRail"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::material::DetectorRail::from_raw(&jni, res) - } - - pub fn is_pressed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isPressed", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn set_pressed(&self, is_pressed: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(is_pressed.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setPressed", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/DetectorRail;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::material::DetectorRail::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - // SUPER CLASS: org.bukkit.material.ExtendedRails ( ['isPressed', 'setPressed', 'clone']) - - pub fn is_curve(&self) -> Result> { - let temp_clone = crate::material::ExtendedRails::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::ExtendedRails = temp_clone.into(); - real.is_curve() - } - - pub fn set_direction( - &self, - face: impl Into>, - is_on_slope: bool, - ) -> Result<(), Box> { - let temp_clone = crate::material::ExtendedRails::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::ExtendedRails = temp_clone.into(); - real.set_direction(face, is_on_slope) +impl<'mc> CocoaPlantCocoaPlantSizeStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/CocoaPlant/CocoaPlantSize;"); + let cls = jni.find_class("org/bukkit/material/CocoaPlant/CocoaPlantSize"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::material::CocoaPlantCocoaPlantSize::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -8542,25 +8499,13 @@ impl<'mc> DetectorRail<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for DetectorRail<'mc> { - fn into(self) -> crate::material::PressureSensor<'mc> { - crate::material::PressureSensor::from_raw(&self.jni_ref(), self.1) - .expect("Error converting DetectorRail into crate::material::PressureSensor") - } -} -impl<'mc> Into> for DetectorRail<'mc> { - fn into(self) -> crate::material::ExtendedRails<'mc> { - crate::material::ExtendedRails::from_raw(&self.jni_ref(), self.1) - .expect("Error converting DetectorRail into crate::material::ExtendedRails") - } -} #[repr(C)] -pub struct Rails<'mc>( +pub struct Skull<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Rails<'mc> { +impl<'mc> JNIRaw<'mc> for Skull<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -8568,18 +8513,18 @@ impl<'mc> JNIRaw<'mc> for Rails<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Rails<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Skull<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Rails from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Skull from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Rails")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Skull")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Rails object, got {}", + "Invalid argument passed. Expected a Skull object, got {}", name ) .into()) @@ -8589,14 +8534,14 @@ impl<'mc> JNIInstantiatable<'mc> for Rails<'mc> { } } -impl<'mc> Rails<'mc> { +impl<'mc> Skull<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); if let Some(a) = val_type { @@ -8612,36 +8557,36 @@ impl<'mc> Rails<'mc> { args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Rails"); + let cls = jni.find_class("org/bukkit/material/Skull"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Rails::from_raw(&jni, res) + crate::material::Skull::from_raw(&jni, res) } - pub fn is_on_slope(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isOnSlope", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + pub fn set_facing_direction( + &self, + face: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFacingDirection", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - pub fn is_curve(&self) -> Result> { - let sig = String::from("()Z"); + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isCurve", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn direction(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) @@ -8661,45 +8606,18 @@ impl<'mc> Rails<'mc> { .to_string_lossy() .to_string()) } - /// Set the direction of these tracks - /// - /// Note that tracks are bidirectional and that the direction returned is - /// the ascending direction if the track is set on a slope. If it is set as - /// a curve, the corner of the track should be supplied. - pub fn set_direction( - &self, - face: impl Into>, - is_on_slope: bool, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;Z)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Bool(is_on_slope.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setDirection", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Rails;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Skull;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Rails::from_raw(&self.jni_ref(), unsafe { + crate::material::Skull::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['isOnSlope', 'isCurve', 'getDirection', 'toString', 'setDirection', 'clone']) + // SUPER CLASS: org.bukkit.material.MaterialData ( ['setFacingDirection', 'getFacing', 'toString', 'clone']) /// Gets the raw data in this material pub fn data(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { @@ -8744,15 +8662,190 @@ impl<'mc> Rails<'mc> { real.hash_code() } - pub fn equals( + pub fn equals( + &self, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.equals(obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} + +impl<'mc> std::string::ToString for Skull<'mc> { + fn to_string(&self) -> String { + match &self.internal_to_string() { + Ok(a) => a.clone(), + Err(err) => format!("Error calling Skull.toString: {}", err), + } + } +} + +impl<'mc> Into> for Skull<'mc> { + fn into(self) -> crate::material::Directional<'mc> { + crate::material::Directional::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Skull into crate::material::Directional") + } +} +impl<'mc> Into> for Skull<'mc> { + fn into(self) -> crate::material::MaterialData<'mc> { + crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Skull into crate::material::MaterialData") + } +} +#[repr(C)] +pub struct Sapling<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Sapling<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Sapling<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Sapling from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Sapling")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Sapling object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Sapling<'mc> { + /// Constructs a sapling of the given tree species and if is it instant + /// growable + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + species: std::option::Option>>, + is_instant_growable: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = species { + sig += "Lorg/bukkit/TreeSpecies;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + if let Some(a) = is_instant_growable { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/material/Sapling"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::material::Sapling::from_raw(&jni, res) + } + /// Checks if the Sapling would grow when next ticked with bonemeal + pub fn is_instant_growable(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isInstantGrowable", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Set whether this sapling will grow when next ticked with bonemeal + pub fn set_is_instant_growable( + &self, + is_instant_growable: bool, + ) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(is_instant_growable.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setIsInstantGrowable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Sapling;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::material::Sapling::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + // SUPER CLASS: org.bukkit.material.Wood ( ['isInstantGrowable', 'setIsInstantGrowable', 'toString', 'clone']) + /// Gets the current species of this wood block + pub fn species(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/TreeSpecies;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSpecies", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::TreeSpecies::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the species of this wood block + pub fn set_species( &self, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.equals(obj) + species: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/TreeSpecies;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(species.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSpecies", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -8761,28 +8854,28 @@ impl<'mc> Rails<'mc> { } } -impl<'mc> std::string::ToString for Rails<'mc> { +impl<'mc> std::string::ToString for Sapling<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling Rails.toString: {}", err), + Err(err) => format!("Error calling Sapling.toString: {}", err), } } } -impl<'mc> Into> for Rails<'mc> { - fn into(self) -> crate::material::MaterialData<'mc> { - crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Rails into crate::material::MaterialData") +impl<'mc> Into> for Sapling<'mc> { + fn into(self) -> crate::material::Wood<'mc> { + crate::material::Wood::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Sapling into crate::material::Wood") } } #[repr(C)] -pub struct Cake<'mc>( +pub struct Dispenser<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Cake<'mc> { +impl<'mc> JNIRaw<'mc> for Dispenser<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -8790,18 +8883,18 @@ impl<'mc> JNIRaw<'mc> for Cake<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Cake<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Dispenser<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Cake from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Dispenser from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Cake")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Dispenser")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Cake object, got {}", + "Invalid argument passed. Expected a Dispenser object, got {}", name ) .into()) @@ -8811,14 +8904,14 @@ impl<'mc> JNIInstantiatable<'mc> for Cake<'mc> { } } -impl<'mc> Cake<'mc> { +impl<'mc> Dispenser<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); if let Some(a) = val_type { @@ -8834,138 +8927,280 @@ impl<'mc> Cake<'mc> { args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Cake"); + let cls = jni.find_class("org/bukkit/material/Dispenser"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Cake::from_raw(&jni, res) - } - /// Gets the number of slices eaten from this cake - pub fn slices_eaten(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSlicesEaten", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the number of slices remaining on this cake - pub fn slices_remaining(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getSlicesRemaining", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::material::Dispenser::from_raw(&jni, res) } - /// Sets the number of slices eaten from this cake - pub fn set_slices_eaten(&self, n: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(n); + + pub fn set_facing_direction( + &self, + face: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setSlicesEaten", + "setFacingDirection", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Sets the number of slices remaining on this cake - pub fn set_slices_remaining(&self, n: i32) -> Result<(), Box> { - let sig = String::from("(I)V"); - let val_1 = jni::objects::JValueGen::Int(n); + + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Dispenser;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::material::Dispenser::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + // SUPER CLASS: org.bukkit.material.FurnaceAndDispenser ( ['setFacingDirection', 'getFacing', 'clone']) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Dispenser<'mc> { + fn into(self) -> crate::material::FurnaceAndDispenser<'mc> { + crate::material::FurnaceAndDispenser::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Dispenser into crate::material::FurnaceAndDispenser") + } +} +#[repr(C)] +pub struct Redstone<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Redstone<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Redstone<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Redstone from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Redstone")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Redstone object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Redstone<'mc> { + /// Gets the current state of this Material, indicating if it's powered or + /// unpowered + pub fn is_powered(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct Attachable<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Attachable<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Attachable<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Attachable from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Attachable")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Attachable object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Attachable<'mc> { + /// Gets the face that this block is attached on + pub fn attached_face( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAttachedFace", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the direction that this block is facing in + pub fn set_facing_direction( + &self, + face: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setSlicesRemaining", + "setFacingDirection", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Cake;"); + /// Gets the direction this block is facing + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Cake::from_raw(&self.jni_ref(), unsafe { + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['getSlicesEaten', 'getSlicesRemaining', 'setSlicesEaten', 'setSlicesRemaining', 'toString', 'clone']) - /// Gets the raw data in this material - pub fn data(&self) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.data() + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Sets the raw data of this material - pub fn set_data(&self, data: i8) -> Result<(), Box> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.set_data(data) +} +impl<'mc> Into> for Attachable<'mc> { + fn into(self) -> crate::material::Directional<'mc> { + crate::material::Directional::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Attachable into crate::material::Directional") } - /// Gets the Material that this MaterialData represents - pub fn item_type(&self) -> Result, Box> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.item_type() +} +#[repr(C)] +pub struct Colorable<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Colorable<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Creates a new ItemStack based on this MaterialData - pub fn to_item_stack( - &self, - amount: std::option::Option, - ) -> Result, Box> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.to_item_stack(amount) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - - pub fn hash_code(&self) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.hash_code() +} +impl<'mc> JNIInstantiatable<'mc> for Colorable<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Colorable from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Colorable")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Colorable object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } +} - pub fn equals( +impl<'mc> Colorable<'mc> { + /// Gets the color of this object. + /// + /// This may be null to represent the default color of an object, if the + /// object has a special default color (e.g Shulkers). + pub fn color(&self) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/DyeColor;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::DyeColor::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?)) + } + /// Sets the color of this object to the specified DyeColor. + /// + /// This may be null to represent the default color of an object, if the + /// object has a special default color (e.g Shulkers). + pub fn set_color( &self, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.equals(obj) + color: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/DyeColor;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(color.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setColor", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -8973,29 +9208,13 @@ impl<'mc> Cake<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } - -impl<'mc> std::string::ToString for Cake<'mc> { - fn to_string(&self) -> String { - match &self.internal_to_string() { - Ok(a) => a.clone(), - Err(err) => format!("Error calling Cake.toString: {}", err), - } - } -} - -impl<'mc> Into> for Cake<'mc> { - fn into(self) -> crate::material::MaterialData<'mc> { - crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Cake into crate::material::MaterialData") - } -} #[repr(C)] -pub struct WoodenStep<'mc>( +pub struct Leaves<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for WoodenStep<'mc> { +impl<'mc> JNIRaw<'mc> for Leaves<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -9003,18 +9222,18 @@ impl<'mc> JNIRaw<'mc> for WoodenStep<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for WoodenStep<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Leaves<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate WoodenStep from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Leaves from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/WoodenStep")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Leaves")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a WoodenStep object, got {}", + "Invalid argument passed. Expected a Leaves object, got {}", name ) .into()) @@ -9024,67 +9243,79 @@ impl<'mc> JNIInstantiatable<'mc> for WoodenStep<'mc> { } } -impl<'mc> WoodenStep<'mc> { - #[deprecated] - +impl<'mc> Leaves<'mc> { + /// Constructs a leaf block of the given tree species and flag for whether + /// this leaf block will disappear when too far from a log. pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: std::option::Option>>, - data: std::option::Option, - ) -> Result, Box> { + species: std::option::Option>>, + is_decayable: std::option::Option, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = val_type { - sig += "Lorg/bukkit/Material;"; + if let Some(a) = species { + sig += "Lorg/bukkit/TreeSpecies;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); args.push(val_1); } - if let Some(a) = data { - sig += "B"; - let val_2 = jni::objects::JValueGen::Byte(a); + if let Some(a) = is_decayable { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/WoodenStep"); + let cls = jni.find_class("org/bukkit/material/Leaves"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::WoodenStep::from_raw(&jni, res) + crate::material::Leaves::from_raw(&jni, res) } - /// Test if step is inverted - pub fn is_inverted(&self) -> Result> { + /// Checks if this leaf block is in the process of decaying + pub fn is_decaying(&self) -> Result> { let sig = String::from("()Z"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isInverted", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isDecaying", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Set step inverted state - pub fn set_inverted(&self, inv: bool) -> Result<(), Box> { + /// Set whether this leaf block is in the process of decaying + pub fn set_decaying(&self, is_decaying: bool) -> Result<(), Box> { let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(inv.into()); + let val_1 = jni::objects::JValueGen::Bool(is_decaying.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setInverted", + "setDecaying", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/WoodenStep;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + /// Checks if this leaf block is permanent or can decay when too far from a + /// log + pub fn is_decayable(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isDecayable", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::WoodenStep::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) + } + /// Set whether this leaf block will disappear when too far from a log + pub fn set_decayable(&self, is_decayable: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(is_decayable.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDecayable", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } #[doc(hidden)] @@ -9100,7 +9331,18 @@ impl<'mc> WoodenStep<'mc> { .to_string_lossy() .to_string()) } - // SUPER CLASS: org.bukkit.material.Wood ( ['isInverted', 'setInverted', 'clone', 'toString']) + + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Leaves;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::material::Leaves::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + // SUPER CLASS: org.bukkit.material.Wood ( ['isDecaying', 'setDecaying', 'isDecayable', 'setDecayable', 'toString', 'clone']) /// Gets the current species of this wood block pub fn species(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/TreeSpecies;"); @@ -9137,28 +9379,28 @@ impl<'mc> WoodenStep<'mc> { } } -impl<'mc> std::string::ToString for WoodenStep<'mc> { +impl<'mc> std::string::ToString for Leaves<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling WoodenStep.toString: {}", err), + Err(err) => format!("Error calling Leaves.toString: {}", err), } } } -impl<'mc> Into> for WoodenStep<'mc> { +impl<'mc> Into> for Leaves<'mc> { fn into(self) -> crate::material::Wood<'mc> { crate::material::Wood::from_raw(&self.jni_ref(), self.1) - .expect("Error converting WoodenStep into crate::material::Wood") + .expect("Error converting Leaves into crate::material::Wood") } } #[repr(C)] -pub struct EnderChest<'mc>( +pub struct DetectorRail<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EnderChest<'mc> { +impl<'mc> JNIRaw<'mc> for DetectorRail<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -9166,18 +9408,18 @@ impl<'mc> JNIRaw<'mc> for EnderChest<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EnderChest<'mc> { +impl<'mc> JNIInstantiatable<'mc> for DetectorRail<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate EnderChest from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate DetectorRail from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/EnderChest")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/DetectorRail")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EnderChest object, got {}", + "Invalid argument passed. Expected a DetectorRail object, got {}", name ) .into()) @@ -9187,14 +9429,14 @@ impl<'mc> JNIInstantiatable<'mc> for EnderChest<'mc> { } } -impl<'mc> EnderChest<'mc> { +impl<'mc> DetectorRail<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); if let Some(a) = val_type { @@ -9210,153 +9452,28 @@ impl<'mc> EnderChest<'mc> { args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/EnderChest"); + let cls = jni.find_class("org/bukkit/material/DetectorRail"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::EnderChest::from_raw(&jni, res) + crate::material::DetectorRail::from_raw(&jni, res) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/EnderChest;"); + pub fn is_pressed(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isPressed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::EnderChest::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - // SUPER CLASS: org.bukkit.material.DirectionalContainer ( ['clone']) - - pub fn set_facing_direction( - &self, - face: impl Into>, - ) -> Result<(), Box> { - let temp_clone = crate::material::DirectionalContainer::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::DirectionalContainer = temp_clone.into(); - real.set_facing_direction(face) - } - - pub fn facing(&self) -> Result, Box> { - let temp_clone = crate::material::DirectionalContainer::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::DirectionalContainer = temp_clone.into(); - real.facing() - } - - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let temp_clone = crate::material::DirectionalContainer::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::DirectionalContainer = temp_clone.into(); - real.internal_to_string() - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for EnderChest<'mc> { - fn into(self) -> crate::material::DirectionalContainer<'mc> { - crate::material::DirectionalContainer::from_raw(&self.jni_ref(), self.1) - .expect("Error converting EnderChest into crate::material::DirectionalContainer") - } -} -#[repr(C)] -pub struct Tree<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Tree<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Tree<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Tree from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Tree")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Tree object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + Ok(res.z()?) } -} -impl<'mc> Tree<'mc> { - /// Constructs a tree block of the given tree species, and facing the given - /// direction. - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - species: std::option::Option>>, - dir: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = species { - sig += "Lorg/bukkit/TreeSpecies;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - if let Some(a) = dir { - sig += "Lorg/bukkit/block/BlockFace;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Tree"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::material::Tree::from_raw(&jni, res) - } - /// Get direction of the log - pub fn direction(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Set direction of the log - pub fn set_direction( - &self, - dir: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(dir.into().jni_object().clone()) - }); + pub fn set_pressed(&self, is_pressed: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(is_pressed.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setDirection", + "setPressed", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); @@ -9364,59 +9481,36 @@ impl<'mc> Tree<'mc> { Ok(()) } - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Tree;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/DetectorRail;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Tree::from_raw(&self.jni_ref(), unsafe { + crate::material::DetectorRail::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.Wood ( ['getDirection', 'setDirection', 'toString', 'clone']) - /// Gets the current species of this wood block - pub fn species(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/TreeSpecies;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getSpecies", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::TreeSpecies::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + // SUPER CLASS: org.bukkit.material.ExtendedRails ( ['isPressed', 'setPressed', 'clone']) + + pub fn is_curve(&self) -> Result> { + let temp_clone = crate::material::ExtendedRails::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::ExtendedRails = temp_clone.into(); + real.is_curve() } - /// Sets the species of this wood block - pub fn set_species( + + pub fn set_direction( &self, - species: impl Into>, + face: impl Into>, + is_on_slope: bool, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/TreeSpecies;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(species.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setSpecies", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + let temp_clone = crate::material::ExtendedRails::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::ExtendedRails = temp_clone.into(); + real.set_direction(face, is_on_slope) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -9424,29 +9518,25 @@ impl<'mc> Tree<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } - -impl<'mc> std::string::ToString for Tree<'mc> { - fn to_string(&self) -> String { - match &self.internal_to_string() { - Ok(a) => a.clone(), - Err(err) => format!("Error calling Tree.toString: {}", err), - } +impl<'mc> Into> for DetectorRail<'mc> { + fn into(self) -> crate::material::PressureSensor<'mc> { + crate::material::PressureSensor::from_raw(&self.jni_ref(), self.1) + .expect("Error converting DetectorRail into crate::material::PressureSensor") } } - -impl<'mc> Into> for Tree<'mc> { - fn into(self) -> crate::material::Wood<'mc> { - crate::material::Wood::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Tree into crate::material::Wood") +impl<'mc> Into> for DetectorRail<'mc> { + fn into(self) -> crate::material::ExtendedRails<'mc> { + crate::material::ExtendedRails::from_raw(&self.jni_ref(), self.1) + .expect("Error converting DetectorRail into crate::material::ExtendedRails") } } #[repr(C)] -pub struct MaterialData<'mc>( +pub struct Rails<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for MaterialData<'mc> { +impl<'mc> JNIRaw<'mc> for Rails<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -9454,18 +9544,18 @@ impl<'mc> JNIRaw<'mc> for MaterialData<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for MaterialData<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Rails<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate MaterialData from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Rails from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/MaterialData")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Rails")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a MaterialData object, got {}", + "Invalid argument passed. Expected a Rails object, got {}", name ) .into()) @@ -9475,86 +9565,61 @@ impl<'mc> JNIInstantiatable<'mc> for MaterialData<'mc> { } } -impl<'mc> MaterialData<'mc> { +impl<'mc> Rails<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: impl Into>, + val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - args.push(val_1); + if let Some(a) = val_type { + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } if let Some(a) = data { sig += "B"; let val_2 = jni::objects::JValueGen::Byte(a); args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/MaterialData"); + let cls = jni.find_class("org/bukkit/material/Rails"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::MaterialData::from_raw(&jni, res) + crate::material::Rails::from_raw(&jni, res) } - #[deprecated] - /// Gets the raw data in this material - pub fn data(&self) -> Result> { - let sig = String::from("()B"); + + pub fn is_on_slope(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getData", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isOnSlope", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) + Ok(res.z()?) } - #[deprecated] - /// Sets the raw data of this material - pub fn set_data(&self, data: i8) -> Result<(), Box> { - let sig = String::from("(B)V"); - let val_1 = jni::objects::JValueGen::Byte(data); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setData", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + + pub fn is_curve(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isCurve", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the Material that this MaterialData represents - pub fn item_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Material;"); + + pub fn direction(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getItemType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Material::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Creates a new ItemStack based on this MaterialData - pub fn to_item_stack( - &self, - amount: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = amount { - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(a); - args.push(val_1); - } - sig += ")Lorg/bukkit/inventory/ItemStack;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "toItemStack", sig.as_str(), args); + .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::inventory::ItemStack::from_raw(&self.jni_ref(), unsafe { + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -9572,122 +9637,98 @@ impl<'mc> MaterialData<'mc> { .to_string_lossy() .to_string()) } - - pub fn hash_code(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - - pub fn equals( + /// Set the direction of these tracks + /// + /// Note that tracks are bidirectional and that the direction returned is + /// the ascending direction if the track is set on a slope. If it is set as + /// a curve, the corner of the track should be supplied. + pub fn set_direction( &self, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - let sig = String::from("(Ljava/lang/Object;)Z"); - let val_1 = jni::objects::JValueGen::Object(obj); + face: impl Into>, + is_on_slope: bool, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;Z)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Bool(is_on_slope.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "equals", + "setDirection", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/MaterialData;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Rails;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::MaterialData::from_raw(&self.jni_ref(), unsafe { + crate::material::Rails::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} - -impl<'mc> std::string::ToString for MaterialData<'mc> { - fn to_string(&self) -> String { - match &self.internal_to_string() { - Ok(a) => a.clone(), - Err(err) => format!("Error calling MaterialData.toString: {}", err), - } + // SUPER CLASS: org.bukkit.material.MaterialData ( ['isOnSlope', 'isCurve', 'getDirection', 'toString', 'setDirection', 'clone']) + /// Gets the raw data in this material + pub fn data(&self) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.data() } -} - -#[repr(C)] -pub struct Directional<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Directional<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Sets the raw data of this material + pub fn set_data(&self, data: i8) -> Result<(), Box> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.set_data(data) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets the Material that this MaterialData represents + pub fn item_type(&self) -> Result, Box> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.item_type() } -} -impl<'mc> JNIInstantiatable<'mc> for Directional<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Directional from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Directional")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Directional object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Creates a new ItemStack based on this MaterialData + pub fn to_item_stack( + &self, + amount: std::option::Option, + ) -> Result, Box> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.to_item_stack(amount) } -} -impl<'mc> Directional<'mc> { - /// Sets the direction that this block is facing in - pub fn set_facing_direction( - &self, - face: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFacingDirection", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + pub fn hash_code(&self) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.hash_code() } - /// Gets the direction this block is facing - pub fn facing(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + + pub fn equals( + &self, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.equals(obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -9695,13 +9736,29 @@ impl<'mc> Directional<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } + +impl<'mc> std::string::ToString for Rails<'mc> { + fn to_string(&self) -> String { + match &self.internal_to_string() { + Ok(a) => a.clone(), + Err(err) => format!("Error calling Rails.toString: {}", err), + } + } +} + +impl<'mc> Into> for Rails<'mc> { + fn into(self) -> crate::material::MaterialData<'mc> { + crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Rails into crate::material::MaterialData") + } +} #[repr(C)] -pub struct Torch<'mc>( +pub struct EnderChest<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Torch<'mc> { +impl<'mc> JNIRaw<'mc> for EnderChest<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -9709,18 +9766,18 @@ impl<'mc> JNIRaw<'mc> for Torch<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Torch<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EnderChest<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Torch from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate EnderChest from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Torch")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/EnderChest")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Torch object, got {}", + "Invalid argument passed. Expected a EnderChest object, got {}", name ) .into()) @@ -9730,14 +9787,14 @@ impl<'mc> JNIInstantiatable<'mc> for Torch<'mc> { } } -impl<'mc> Torch<'mc> { +impl<'mc> EnderChest<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); if let Some(a) = val_type { @@ -9753,72 +9810,50 @@ impl<'mc> Torch<'mc> { args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Torch"); + let cls = jni.find_class("org/bukkit/material/EnderChest"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Torch::from_raw(&jni, res) + crate::material::EnderChest::from_raw(&jni, res) } - /// Gets the face that this block is attached on - pub fn attached_face( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/BlockFace;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAttachedFace", sig.as_str(), vec![]); + + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/EnderChest;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + crate::material::EnderChest::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } + // SUPER CLASS: org.bukkit.material.DirectionalContainer ( ['clone']) pub fn set_facing_direction( &self, face: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setFacingDirection", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Torch;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::material::Torch::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let temp_clone = crate::material::DirectionalContainer::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::DirectionalContainer = temp_clone.into(); + real.set_facing_direction(face) } - // SUPER CLASS: org.bukkit.material.SimpleAttachableMaterialData ( ['getAttachedFace', 'setFacingDirection', 'clone']) pub fn facing(&self) -> Result, Box> { - let temp_clone = - crate::material::SimpleAttachableMaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::SimpleAttachableMaterialData = temp_clone.into(); + let temp_clone = crate::material::DirectionalContainer::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::DirectionalContainer = temp_clone.into(); real.facing() } #[doc(hidden)] pub fn internal_to_string(&self) -> Result> { - let temp_clone = - crate::material::SimpleAttachableMaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::SimpleAttachableMaterialData = temp_clone.into(); + let temp_clone = crate::material::DirectionalContainer::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::DirectionalContainer = temp_clone.into(); real.internal_to_string() } @@ -9827,19 +9862,19 @@ impl<'mc> Torch<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Torch<'mc> { - fn into(self) -> crate::material::SimpleAttachableMaterialData<'mc> { - crate::material::SimpleAttachableMaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Torch into crate::material::SimpleAttachableMaterialData") +impl<'mc> Into> for EnderChest<'mc> { + fn into(self) -> crate::material::DirectionalContainer<'mc> { + crate::material::DirectionalContainer::from_raw(&self.jni_ref(), self.1) + .expect("Error converting EnderChest into crate::material::DirectionalContainer") } } #[repr(C)] -pub struct PressurePlate<'mc>( +pub struct Tree<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PressurePlate<'mc> { +impl<'mc> JNIRaw<'mc> for Tree<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -9847,18 +9882,18 @@ impl<'mc> JNIRaw<'mc> for PressurePlate<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PressurePlate<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Tree<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate PressurePlate from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Tree from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/PressurePlate")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Tree")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PressurePlate object, got {}", + "Invalid argument passed. Expected a Tree object, got {}", name ) .into()) @@ -9868,43 +9903,65 @@ impl<'mc> JNIInstantiatable<'mc> for PressurePlate<'mc> { } } -impl<'mc> PressurePlate<'mc> { - #[deprecated] - +impl<'mc> Tree<'mc> { + /// Constructs a tree block of the given tree species, and facing the given + /// direction. pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: std::option::Option>>, - data: std::option::Option, - ) -> Result, Box> { + species: std::option::Option>>, + dir: std::option::Option>>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = val_type { - sig += "Lorg/bukkit/Material;"; + if let Some(a) = species { + sig += "Lorg/bukkit/TreeSpecies;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); args.push(val_1); } - if let Some(a) = data { - sig += "B"; - let val_2 = jni::objects::JValueGen::Byte(a); + if let Some(a) = dir { + sig += "Lorg/bukkit/block/BlockFace;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/PressurePlate"); + let cls = jni.find_class("org/bukkit/material/Tree"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::PressurePlate::from_raw(&jni, res) + crate::material::Tree::from_raw(&jni, res) } - - pub fn is_pressed(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isPressed", sig.as_str(), vec![]); + /// Get direction of the log + pub fn direction(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDirection", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Set direction of the log + pub fn set_direction( + &self, + dir: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(dir.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDirection", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } #[doc(hidden)] @@ -9921,70 +9978,45 @@ impl<'mc> PressurePlate<'mc> { .to_string()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/PressurePlate;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Tree;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::material::PressurePlate::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['isPressed', 'toString', 'clone']) - /// Gets the raw data in this material - pub fn data(&self) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.data() - } - /// Sets the raw data of this material - pub fn set_data(&self, data: i8) -> Result<(), Box> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.set_data(data) - } - /// Gets the Material that this MaterialData represents - pub fn item_type(&self) -> Result, Box> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.item_type() - } - /// Creates a new ItemStack based on this MaterialData - pub fn to_item_stack( - &self, - amount: std::option::Option, - ) -> Result, Box> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.to_item_stack(amount) - } - - pub fn hash_code(&self) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.hash_code() + let res = self.jni_ref().translate_error(res)?; + crate::material::Tree::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - - pub fn equals( + // SUPER CLASS: org.bukkit.material.Wood ( ['getDirection', 'setDirection', 'toString', 'clone']) + /// Gets the current species of this wood block + pub fn species(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/TreeSpecies;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSpecies", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::TreeSpecies::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets the species of this wood block + pub fn set_species( &self, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.equals(obj) + species: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/TreeSpecies;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(species.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSpecies", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -9993,34 +10025,28 @@ impl<'mc> PressurePlate<'mc> { } } -impl<'mc> std::string::ToString for PressurePlate<'mc> { +impl<'mc> std::string::ToString for Tree<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling PressurePlate.toString: {}", err), + Err(err) => format!("Error calling Tree.toString: {}", err), } } } -impl<'mc> Into> for PressurePlate<'mc> { - fn into(self) -> crate::material::PressureSensor<'mc> { - crate::material::PressureSensor::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PressurePlate into crate::material::PressureSensor") - } -} -impl<'mc> Into> for PressurePlate<'mc> { - fn into(self) -> crate::material::MaterialData<'mc> { - crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PressurePlate into crate::material::MaterialData") +impl<'mc> Into> for Tree<'mc> { + fn into(self) -> crate::material::Wood<'mc> { + crate::material::Wood::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Tree into crate::material::Wood") } } #[repr(C)] -pub struct Hopper<'mc>( +pub struct Directional<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Hopper<'mc> { +impl<'mc> JNIRaw<'mc> for Directional<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -10028,18 +10054,18 @@ impl<'mc> JNIRaw<'mc> for Hopper<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Hopper<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Directional<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Hopper from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Directional from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Hopper")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Directional")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Hopper object, got {}", + "Invalid argument passed. Expected a Directional object, got {}", name ) .into()) @@ -10049,58 +10075,8 @@ impl<'mc> JNIInstantiatable<'mc> for Hopper<'mc> { } } -impl<'mc> Hopper<'mc> { - /// Constructs a hopper facing the specified direction and either active or - /// not. - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - facing_direction: std::option::Option>>, - is_active: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = facing_direction { - sig += "Lorg/bukkit/block/BlockFace;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_1); - } - if let Some(a) = is_active { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Hopper"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::material::Hopper::from_raw(&jni, res) - } - /// Sets whether the hopper is active or not. - pub fn set_active(&self, is_active: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(is_active.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setActive", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Checks whether the hopper is active or not. - pub fn is_active(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isActive", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets the direction this hopper is facing +impl<'mc> Directional<'mc> { + /// Sets the direction that this block is facing in pub fn set_facing_direction( &self, face: impl Into>, @@ -10118,7 +10094,7 @@ impl<'mc> Hopper<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the direction this hopper is facing + /// Gets the direction this block is facing pub fn facing(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/block/BlockFace;"); let res = self @@ -10130,135 +10106,156 @@ impl<'mc> Hopper<'mc> { }) } - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } +} +#[repr(C)] +pub struct Torch<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Hopper;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::material::Hopper::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Checks if the hopper is powered. - pub fn is_powered(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['setActive', 'isActive', 'setFacingDirection', 'getFacing', 'toString', 'clone', 'isPowered']) - /// Gets the raw data in this material - pub fn data(&self) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.data() - } - /// Sets the raw data of this material - pub fn set_data(&self, data: i8) -> Result<(), Box> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.set_data(data) +impl<'mc> JNIRaw<'mc> for Torch<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Gets the Material that this MaterialData represents - pub fn item_type(&self) -> Result, Box> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.item_type() + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Creates a new ItemStack based on this MaterialData - pub fn to_item_stack( - &self, - amount: std::option::Option, - ) -> Result, Box> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.to_item_stack(amount) +} +impl<'mc> JNIInstantiatable<'mc> for Torch<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Torch from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Torch")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Torch object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } +} - pub fn hash_code(&self) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.hash_code() +impl<'mc> Torch<'mc> { + #[deprecated] + + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + val_type: std::option::Option>>, + data: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = val_type { + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } + if let Some(a) = data { + sig += "B"; + let val_2 = jni::objects::JValueGen::Byte(a); + args.push(val_2); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/material/Torch"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::material::Torch::from_raw(&jni, res) + } + /// Gets the face that this block is attached on + pub fn attached_face( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAttachedFace", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - pub fn equals( + pub fn set_facing_direction( &self, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::material::MaterialData = temp_clone.into(); - real.equals(obj) + face: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(face.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setFacingDirection", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Torch;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::material::Torch::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} + // SUPER CLASS: org.bukkit.material.SimpleAttachableMaterialData ( ['getAttachedFace', 'setFacingDirection', 'clone']) -impl<'mc> std::string::ToString for Hopper<'mc> { - fn to_string(&self) -> String { - match &self.internal_to_string() { - Ok(a) => a.clone(), - Err(err) => format!("Error calling Hopper.toString: {}", err), - } + pub fn facing(&self) -> Result, Box> { + let temp_clone = + crate::material::SimpleAttachableMaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::SimpleAttachableMaterialData = temp_clone.into(); + real.facing() } -} -impl<'mc> Into> for Hopper<'mc> { - fn into(self) -> crate::material::Directional<'mc> { - crate::material::Directional::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Hopper into crate::material::Directional") + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let temp_clone = + crate::material::SimpleAttachableMaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::SimpleAttachableMaterialData = temp_clone.into(); + real.internal_to_string() } -} -impl<'mc> Into> for Hopper<'mc> { - fn into(self) -> crate::material::Redstone<'mc> { - crate::material::Redstone::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Hopper into crate::material::Redstone") + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Hopper<'mc> { - fn into(self) -> crate::material::MaterialData<'mc> { - crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Hopper into crate::material::MaterialData") +impl<'mc> Into> for Torch<'mc> { + fn into(self) -> crate::material::SimpleAttachableMaterialData<'mc> { + crate::material::SimpleAttachableMaterialData::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Torch into crate::material::SimpleAttachableMaterialData") } } #[repr(C)] -pub struct Wool<'mc>( +pub struct PressurePlate<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Wool<'mc> { +impl<'mc> JNIRaw<'mc> for PressurePlate<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -10266,18 +10263,18 @@ impl<'mc> JNIRaw<'mc> for Wool<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Wool<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PressurePlate<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Wool from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate PressurePlate from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Wool")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/PressurePlate")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Wool object, got {}", + "Invalid argument passed. Expected a PressurePlate object, got {}", name ) .into()) @@ -10287,14 +10284,14 @@ impl<'mc> JNIInstantiatable<'mc> for Wool<'mc> { } } -impl<'mc> Wool<'mc> { +impl<'mc> PressurePlate<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); if let Some(a) = val_type { @@ -10310,40 +10307,20 @@ impl<'mc> Wool<'mc> { args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Wool"); + let cls = jni.find_class("org/bukkit/material/PressurePlate"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Wool::from_raw(&jni, res) + crate::material::PressurePlate::from_raw(&jni, res) } - /// Gets the current color of this dye - pub fn color(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/DyeColor;"); + + pub fn is_pressed(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isPressed", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::DyeColor::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Sets the color of this dye - pub fn set_color( - &self, - color: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/DyeColor;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(color.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setColor", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + Ok(res.z()?) } #[doc(hidden)] @@ -10360,17 +10337,17 @@ impl<'mc> Wool<'mc> { .to_string()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Wool;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/PressurePlate;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Wool::from_raw(&self.jni_ref(), unsafe { + crate::material::PressurePlate::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['getColor', 'setColor', 'toString', 'clone']) + // SUPER CLASS: org.bukkit.material.MaterialData ( ['isPressed', 'toString', 'clone']) /// Gets the raw data in this material pub fn data(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { @@ -10432,34 +10409,34 @@ impl<'mc> Wool<'mc> { } } -impl<'mc> std::string::ToString for Wool<'mc> { +impl<'mc> std::string::ToString for PressurePlate<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling Wool.toString: {}", err), + Err(err) => format!("Error calling PressurePlate.toString: {}", err), } } } -impl<'mc> Into> for Wool<'mc> { - fn into(self) -> crate::material::Colorable<'mc> { - crate::material::Colorable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Wool into crate::material::Colorable") +impl<'mc> Into> for PressurePlate<'mc> { + fn into(self) -> crate::material::PressureSensor<'mc> { + crate::material::PressureSensor::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PressurePlate into crate::material::PressureSensor") } } -impl<'mc> Into> for Wool<'mc> { +impl<'mc> Into> for PressurePlate<'mc> { fn into(self) -> crate::material::MaterialData<'mc> { crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Wool into crate::material::MaterialData") + .expect("Error converting PressurePlate into crate::material::MaterialData") } } #[repr(C)] -pub struct Vine<'mc>( +pub struct Hopper<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Vine<'mc> { +impl<'mc> JNIRaw<'mc> for Hopper<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -10467,18 +10444,18 @@ impl<'mc> JNIRaw<'mc> for Vine<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Vine<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Hopper<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Vine from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Hopper from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Vine")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Hopper")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Vine object, got {}", + "Invalid argument passed. Expected a Hopper object, got {}", name ) .into()) @@ -10488,75 +10465,59 @@ impl<'mc> JNIInstantiatable<'mc> for Vine<'mc> { } } -impl<'mc> Vine<'mc> { - #[deprecated] - +impl<'mc> Hopper<'mc> { + /// Constructs a hopper facing the specified direction and either active or + /// not. pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: std::option::Option>>, - data: std::option::Option, - ) -> Result, Box> { + facing_direction: std::option::Option>>, + is_active: std::option::Option, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = val_type { - sig += "Lorg/bukkit/Material;"; + if let Some(a) = facing_direction { + sig += "Lorg/bukkit/block/BlockFace;"; let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(a.into().jni_object().clone()) }); args.push(val_1); } - if let Some(a) = data { - sig += "B"; - let val_2 = jni::objects::JValueGen::Byte(a); + if let Some(a) = is_active { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Vine"); + let cls = jni.find_class("org/bukkit/material/Hopper"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Vine::from_raw(&jni, res) - } - /// Check if the vine is attached to the specified face of an adjacent - /// block. You can check two faces at once by passing e.g. {@link - /// BlockFace#NORTH_EAST}. - pub fn is_on_face( - &self, - face: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isOnFace", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::material::Hopper::from_raw(&jni, res) } - /// Attach the vine to the specified face of an adjacent block. - pub fn put_on_face( - &self, - face: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) - }); + /// Sets whether the hopper is active or not. + pub fn set_active(&self, is_active: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(is_active.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "putOnFace", + "setActive", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Detach the vine from the specified face of an adjacent block. - pub fn remove_from_face( + /// Checks whether the hopper is active or not. + pub fn is_active(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isActive", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Sets the direction this hopper is facing + pub fn set_facing_direction( &self, face: impl Into>, ) -> Result<(), Box> { @@ -10566,13 +10527,24 @@ impl<'mc> Vine<'mc> { }); let res = self.jni_ref().call_method( &self.jni_object(), - "removeFromFace", + "setFacingDirection", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } + /// Gets the direction this hopper is facing + pub fn facing(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/BlockFace;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getFacing", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::BlockFace::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } #[doc(hidden)] pub fn internal_to_string(&self) -> Result> { @@ -10588,17 +10560,26 @@ impl<'mc> Vine<'mc> { .to_string()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Vine;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Hopper;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Vine::from_raw(&self.jni_ref(), unsafe { + crate::material::Hopper::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.MaterialData ( ['isOnFace', 'putOnFace', 'removeFromFace', 'toString', 'clone']) + /// Checks if the hopper is powered. + pub fn is_powered(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isPowered", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + // SUPER CLASS: org.bukkit.material.MaterialData ( ['setActive', 'isActive', 'setFacingDirection', 'getFacing', 'toString', 'clone', 'isPowered']) /// Gets the raw data in this material pub fn data(&self) -> Result> { let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { @@ -10660,28 +10641,40 @@ impl<'mc> Vine<'mc> { } } -impl<'mc> std::string::ToString for Vine<'mc> { +impl<'mc> std::string::ToString for Hopper<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling Vine.toString: {}", err), + Err(err) => format!("Error calling Hopper.toString: {}", err), } } } -impl<'mc> Into> for Vine<'mc> { +impl<'mc> Into> for Hopper<'mc> { + fn into(self) -> crate::material::Directional<'mc> { + crate::material::Directional::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Hopper into crate::material::Directional") + } +} +impl<'mc> Into> for Hopper<'mc> { + fn into(self) -> crate::material::Redstone<'mc> { + crate::material::Redstone::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Hopper into crate::material::Redstone") + } +} +impl<'mc> Into> for Hopper<'mc> { fn into(self) -> crate::material::MaterialData<'mc> { crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Vine into crate::material::MaterialData") + .expect("Error converting Hopper into crate::material::MaterialData") } } #[repr(C)] -pub struct Dye<'mc>( +pub struct Wool<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Dye<'mc> { +impl<'mc> JNIRaw<'mc> for Wool<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -10689,18 +10682,18 @@ impl<'mc> JNIRaw<'mc> for Dye<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Dye<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Wool<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Dye from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Wool from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Dye")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Wool")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Dye object, got {}", + "Invalid argument passed. Expected a Wool object, got {}", name ) .into()) @@ -10710,14 +10703,14 @@ impl<'mc> JNIInstantiatable<'mc> for Dye<'mc> { } } -impl<'mc> Dye<'mc> { +impl<'mc> Wool<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); if let Some(a) = val_type { @@ -10733,11 +10726,11 @@ impl<'mc> Dye<'mc> { args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/Dye"); + let cls = jni.find_class("org/bukkit/material/Wool"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::Dye::from_raw(&jni, res) + crate::material::Wool::from_raw(&jni, res) } /// Gets the current color of this dye pub fn color(&self) -> Result, Box> { @@ -10783,13 +10776,13 @@ impl<'mc> Dye<'mc> { .to_string()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/Dye;"); + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Wool;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::Dye::from_raw(&self.jni_ref(), unsafe { + crate::material::Wool::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } @@ -10855,34 +10848,34 @@ impl<'mc> Dye<'mc> { } } -impl<'mc> std::string::ToString for Dye<'mc> { +impl<'mc> std::string::ToString for Wool<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling Dye.toString: {}", err), + Err(err) => format!("Error calling Wool.toString: {}", err), } } } -impl<'mc> Into> for Dye<'mc> { +impl<'mc> Into> for Wool<'mc> { fn into(self) -> crate::material::Colorable<'mc> { crate::material::Colorable::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Dye into crate::material::Colorable") + .expect("Error converting Wool into crate::material::Colorable") } } -impl<'mc> Into> for Dye<'mc> { +impl<'mc> Into> for Wool<'mc> { fn into(self) -> crate::material::MaterialData<'mc> { crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Dye into crate::material::MaterialData") + .expect("Error converting Wool into crate::material::MaterialData") } } #[repr(C)] -pub struct ExtendedRails<'mc>( +pub struct Dye<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ExtendedRails<'mc> { +impl<'mc> JNIRaw<'mc> for Dye<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -10890,18 +10883,18 @@ impl<'mc> JNIRaw<'mc> for ExtendedRails<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ExtendedRails<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Dye<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ExtendedRails from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Dye from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/material/ExtendedRails")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/material/Dye")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ExtendedRails object, got {}", + "Invalid argument passed. Expected a Dye object, got {}", name ) .into()) @@ -10911,101 +10904,143 @@ impl<'mc> JNIInstantiatable<'mc> for ExtendedRails<'mc> { } } -impl<'mc> ExtendedRails<'mc> { +impl<'mc> Dye<'mc> { #[deprecated] pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: impl Into>, + val_type: std::option::Option>>, data: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/Material;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - args.push(val_1); + if let Some(a) = val_type { + sig += "Lorg/bukkit/Material;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_1); + } if let Some(a) = data { sig += "B"; let val_2 = jni::objects::JValueGen::Byte(a); args.push(val_2); } sig += ")V"; - let cls = jni.find_class("org/bukkit/material/ExtendedRails"); + let cls = jni.find_class("org/bukkit/material/Dye"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::material::ExtendedRails::from_raw(&jni, res) + crate::material::Dye::from_raw(&jni, res) } - - pub fn is_curve(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the current color of this dye + pub fn color(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/DyeColor;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isCurve", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getColor", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::DyeColor::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - - pub fn set_direction( + /// Sets the color of this dye + pub fn set_color( &self, - face: impl Into>, - is_on_slope: bool, + color: impl Into>, ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/block/BlockFace;Z)V"); + let sig = String::from("(Lorg/bukkit/DyeColor;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(face.into().jni_object().clone()) + jni::objects::JObject::from_raw(color.into().jni_object().clone()) }); - let val_2 = jni::objects::JValueGen::Bool(is_on_slope.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setDirection", + "setColor", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/material/ExtendedRails;"); + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/material/Dye;"); let res = self .jni_ref() .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::material::ExtendedRails::from_raw(&self.jni_ref(), unsafe { + crate::material::Dye::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - // SUPER CLASS: org.bukkit.material.Rails ( ['isCurve', 'setDirection', 'clone']) - - pub fn is_on_slope(&self) -> Result> { - let temp_clone = crate::material::Rails::from_raw(&self.0, unsafe { + // SUPER CLASS: org.bukkit.material.MaterialData ( ['getColor', 'setColor', 'toString', 'clone']) + /// Gets the raw data in this material + pub fn data(&self) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::material::Rails = temp_clone.into(); - real.is_on_slope() + let real: crate::material::MaterialData = temp_clone.into(); + real.data() + } + /// Sets the raw data of this material + pub fn set_data(&self, data: i8) -> Result<(), Box> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.set_data(data) + } + /// Gets the Material that this MaterialData represents + pub fn item_type(&self) -> Result, Box> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.item_type() + } + /// Creates a new ItemStack based on this MaterialData + pub fn to_item_stack( + &self, + amount: std::option::Option, + ) -> Result, Box> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::material::MaterialData = temp_clone.into(); + real.to_item_stack(amount) } - pub fn direction(&self) -> Result, Box> { - let temp_clone = crate::material::Rails::from_raw(&self.0, unsafe { + pub fn hash_code(&self) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::material::Rails = temp_clone.into(); - real.direction() + let real: crate::material::MaterialData = temp_clone.into(); + real.hash_code() } - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let temp_clone = crate::material::Rails::from_raw(&self.0, unsafe { + pub fn equals( + &self, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + let temp_clone = crate::material::MaterialData::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; - let real: crate::material::Rails = temp_clone.into(); - real.internal_to_string() + let real: crate::material::MaterialData = temp_clone.into(); + real.equals(obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -11013,10 +11048,26 @@ impl<'mc> ExtendedRails<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for ExtendedRails<'mc> { - fn into(self) -> crate::material::Rails<'mc> { - crate::material::Rails::from_raw(&self.jni_ref(), self.1) - .expect("Error converting ExtendedRails into crate::material::Rails") + +impl<'mc> std::string::ToString for Dye<'mc> { + fn to_string(&self) -> String { + match &self.internal_to_string() { + Ok(a) => a.clone(), + Err(err) => format!("Error calling Dye.toString: {}", err), + } + } +} + +impl<'mc> Into> for Dye<'mc> { + fn into(self) -> crate::material::Colorable<'mc> { + crate::material::Colorable::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Dye into crate::material::Colorable") + } +} +impl<'mc> Into> for Dye<'mc> { + fn into(self) -> crate::material::MaterialData<'mc> { + crate::material::MaterialData::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Dye into crate::material::MaterialData") } } #[repr(C)] diff --git a/blackboxmc-rs-bukkit/src/material/types/mod.rs b/blackboxmc-rs-bukkit/src/material/types/mod.rs index 1294f35..d598fa0 100644 --- a/blackboxmc-rs-bukkit/src/material/types/mod.rs +++ b/blackboxmc-rs-bukkit/src/material/types/mod.rs @@ -2,10 +2,84 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; -pub enum MushroomBlockTexture<'mc> {} +pub enum MushroomBlockTexture<'mc> { + AllPores { + inner: MushroomBlockTextureStruct<'mc>, + }, + CapNorthWest { + inner: MushroomBlockTextureStruct<'mc>, + }, + CapNorth { + inner: MushroomBlockTextureStruct<'mc>, + }, + CapNorthEast { + inner: MushroomBlockTextureStruct<'mc>, + }, + CapWest { + inner: MushroomBlockTextureStruct<'mc>, + }, + CapTop { + inner: MushroomBlockTextureStruct<'mc>, + }, + CapEast { + inner: MushroomBlockTextureStruct<'mc>, + }, + CapSouthWest { + inner: MushroomBlockTextureStruct<'mc>, + }, + CapSouth { + inner: MushroomBlockTextureStruct<'mc>, + }, + CapSouthEast { + inner: MushroomBlockTextureStruct<'mc>, + }, + StemSides { + inner: MushroomBlockTextureStruct<'mc>, + }, + AllCap { + inner: MushroomBlockTextureStruct<'mc>, + }, + AllStem { + inner: MushroomBlockTextureStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for MushroomBlockTexture<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + MushroomBlockTexture::AllPores { .. } => f.write_str("ALL_PORES"), + MushroomBlockTexture::CapNorthWest { .. } => f.write_str("CAP_NORTH_WEST"), + MushroomBlockTexture::CapNorth { .. } => f.write_str("CAP_NORTH"), + MushroomBlockTexture::CapNorthEast { .. } => f.write_str("CAP_NORTH_EAST"), + MushroomBlockTexture::CapWest { .. } => f.write_str("CAP_WEST"), + MushroomBlockTexture::CapTop { .. } => f.write_str("CAP_TOP"), + MushroomBlockTexture::CapEast { .. } => f.write_str("CAP_EAST"), + MushroomBlockTexture::CapSouthWest { .. } => f.write_str("CAP_SOUTH_WEST"), + MushroomBlockTexture::CapSouth { .. } => f.write_str("CAP_SOUTH"), + MushroomBlockTexture::CapSouthEast { .. } => f.write_str("CAP_SOUTH_EAST"), + MushroomBlockTexture::StemSides { .. } => f.write_str("STEM_SIDES"), + MushroomBlockTexture::AllCap { .. } => f.write_str("ALL_CAP"), + MushroomBlockTexture::AllStem { .. } => f.write_str("ALL_STEM"), + } + } +} +impl<'mc> std::ops::Deref for MushroomBlockTexture<'mc> { + type Target = MushroomBlockTextureStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + MushroomBlockTexture::AllPores { inner } => inner, + MushroomBlockTexture::CapNorthWest { inner } => inner, + MushroomBlockTexture::CapNorth { inner } => inner, + MushroomBlockTexture::CapNorthEast { inner } => inner, + MushroomBlockTexture::CapWest { inner } => inner, + MushroomBlockTexture::CapTop { inner } => inner, + MushroomBlockTexture::CapEast { inner } => inner, + MushroomBlockTexture::CapSouthWest { inner } => inner, + MushroomBlockTexture::CapSouth { inner } => inner, + MushroomBlockTexture::CapSouthEast { inner } => inner, + MushroomBlockTexture::StemSides { inner } => inner, + MushroomBlockTexture::AllCap { inner } => inner, + MushroomBlockTexture::AllStem { inner } => inner, + } } } @@ -32,6 +106,46 @@ impl<'mc> MushroomBlockTexture<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "ALL_PORES" => Ok(MushroomBlockTexture::AllPores { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + "CAP_NORTH_WEST" => Ok(MushroomBlockTexture::CapNorthWest { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + "CAP_NORTH" => Ok(MushroomBlockTexture::CapNorth { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + "CAP_NORTH_EAST" => Ok(MushroomBlockTexture::CapNorthEast { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + "CAP_WEST" => Ok(MushroomBlockTexture::CapWest { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + "CAP_TOP" => Ok(MushroomBlockTexture::CapTop { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + "CAP_EAST" => Ok(MushroomBlockTexture::CapEast { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + "CAP_SOUTH_WEST" => Ok(MushroomBlockTexture::CapSouthWest { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + "CAP_SOUTH" => Ok(MushroomBlockTexture::CapSouth { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + "CAP_SOUTH_EAST" => Ok(MushroomBlockTexture::CapSouthEast { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + "STEM_SIDES" => Ok(MushroomBlockTexture::StemSides { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + "ALL_CAP" => Ok(MushroomBlockTexture::AllCap { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + "ALL_STEM" => Ok(MushroomBlockTexture::AllStem { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -45,10 +159,48 @@ pub struct MushroomBlockTextureStruct<'mc>( impl<'mc> JNIRaw<'mc> for MushroomBlockTexture<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::AllPores { inner } => inner.0.clone(), + Self::CapNorthWest { inner } => inner.0.clone(), + Self::CapNorth { inner } => inner.0.clone(), + Self::CapNorthEast { inner } => inner.0.clone(), + Self::CapWest { inner } => inner.0.clone(), + Self::CapTop { inner } => inner.0.clone(), + Self::CapEast { inner } => inner.0.clone(), + Self::CapSouthWest { inner } => inner.0.clone(), + Self::CapSouth { inner } => inner.0.clone(), + Self::CapSouthEast { inner } => inner.0.clone(), + Self::StemSides { inner } => inner.0.clone(), + Self::AllCap { inner } => inner.0.clone(), + Self::AllStem { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::AllPores { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CapNorthWest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CapNorth { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CapNorthEast { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CapWest { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CapTop { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CapEast { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CapSouthWest { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CapSouth { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::CapSouthEast { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StemSides { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::AllCap { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::AllStem { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for MushroomBlockTexture<'mc> { @@ -77,6 +229,45 @@ impl<'mc> JNIInstantiatable<'mc> for MushroomBlockTexture<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "ALL_PORES" => Ok(MushroomBlockTexture::AllPores { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + "CAP_NORTH_WEST" => Ok(MushroomBlockTexture::CapNorthWest { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + "CAP_NORTH" => Ok(MushroomBlockTexture::CapNorth { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + "CAP_NORTH_EAST" => Ok(MushroomBlockTexture::CapNorthEast { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + "CAP_WEST" => Ok(MushroomBlockTexture::CapWest { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + "CAP_TOP" => Ok(MushroomBlockTexture::CapTop { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + "CAP_EAST" => Ok(MushroomBlockTexture::CapEast { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + "CAP_SOUTH_WEST" => Ok(MushroomBlockTexture::CapSouthWest { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + "CAP_SOUTH" => Ok(MushroomBlockTexture::CapSouth { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + "CAP_SOUTH_EAST" => Ok(MushroomBlockTexture::CapSouthEast { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + "STEM_SIDES" => Ok(MushroomBlockTexture::StemSides { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + "ALL_CAP" => Ok(MushroomBlockTexture::AllCap { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), + "ALL_STEM" => Ok(MushroomBlockTexture::AllStem { + inner: MushroomBlockTextureStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } diff --git a/blackboxmc-rs-bukkit/src/metadata/mod.rs b/blackboxmc-rs-bukkit/src/metadata/mod.rs index b7e6f1a..1122c99 100644 --- a/blackboxmc-rs-bukkit/src/metadata/mod.rs +++ b/blackboxmc-rs-bukkit/src/metadata/mod.rs @@ -3,12 +3,12 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] -pub struct MetadataStore<'mc>( +pub struct MetadataValueAdapter<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for MetadataStore<'mc> { +impl<'mc> JNIRaw<'mc> for MetadataValueAdapter<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -16,18 +16,20 @@ impl<'mc> JNIRaw<'mc> for MetadataStore<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for MetadataStore<'mc> { +impl<'mc> JNIInstantiatable<'mc> for MetadataValueAdapter<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate MetadataStore from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate MetadataValueAdapter from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/metadata/MetadataStore")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/metadata/MetadataValueAdapter")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a MetadataStore object, got {}", + "Invalid argument passed. Expected a MetadataValueAdapter object, got {}", name ) .into()) @@ -37,137 +39,118 @@ impl<'mc> JNIInstantiatable<'mc> for MetadataStore<'mc> { } } -impl<'mc> MetadataStore<'mc> { - /// Adds a metadata value to an object. - pub fn set_metadata( - &self, - subject: jni::objects::JObject<'mc>, - metadata_key: impl Into, - new_metadata_value: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(LT;Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); - let val_1 = jni::objects::JValueGen::Object(subject); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setMetadata", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Returns all metadata values attached to an object. If multiple plugins - /// have attached metadata, each will value will be included. - pub fn get_metadata( +impl<'mc> MetadataValueAdapter<'mc> { + pub fn owning_plugin( &self, - subject: jni::objects::JObject<'mc>, - metadata_key: impl Into, - ) -> Result>, Box> { - let sig = String::from("(LT;Ljava/lang/String;)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(subject); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMetadata", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/plugin/Plugin;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getOwningPlugin", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::metadata::MetadataValue::from_raw( - &self.jni_ref(), - obj, - )?); + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } - Ok(new_vec) + Ok(Some(crate::plugin::Plugin::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Tests to see if a metadata attribute has been set on an object. - pub fn has_metadata( - &self, - subject: jni::objects::JObject<'mc>, - metadata_key: impl Into, - ) -> Result> { - let sig = String::from("(LT;Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(subject); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "hasMetadata", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + + pub fn as_int(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "asInt", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + + pub fn as_float(&self) -> Result> { + let sig = String::from("()F"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "asFloat", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + + pub fn as_double(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "asDouble", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + + pub fn as_long(&self) -> Result> { + let sig = String::from("()J"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "asLong", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.j()?) + } + + pub fn as_short(&self) -> Result> { + let sig = String::from("()S"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "asShort", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.s()?) + } + + pub fn as_byte(&self) -> Result> { + let sig = String::from("()B"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "asByte", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.b()?) + } + + pub fn as_boolean(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "asBoolean", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes a metadata item owned by a plugin from a subject. - pub fn remove_metadata( - &self, - subject: jni::objects::JObject<'mc>, - metadata_key: impl Into, - owning_plugin: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(LT;Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); - let val_1 = jni::objects::JValueGen::Object(subject); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removeMetadata", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + + pub fn as_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "asString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Invalidates all metadata in the metadata store that originates from the - /// given plugin. Doing this will force each invalidated metadata item to - /// be recalculated the next time it is accessed. - pub fn invalidate_all( - &self, - owning_plugin: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "invalidateAll", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + /// Fetches the value of this metadata item. + pub fn value(&self) -> Result>, Box> { + let sig = String::from("()Ljava/lang/Object;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "value", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) + } + /// Invalidates this metadata item, forcing it to recompute when next + /// accessed. + pub fn invalidate(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "invalidate", sig.as_str(), vec![]); self.jni_ref().translate_error(res)?; Ok(()) } @@ -177,6 +160,12 @@ impl<'mc> MetadataStore<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for MetadataValueAdapter<'mc> { + fn into(self) -> crate::metadata::MetadataValue<'mc> { + crate::metadata::MetadataValue::from_raw(&self.jni_ref(), self.1) + .expect("Error converting MetadataValueAdapter into crate::metadata::MetadataValue") + } +} #[repr(C)] pub struct MetadataStoreBase<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, @@ -374,12 +363,12 @@ impl<'mc> MetadataStoreBase<'mc> { } } #[repr(C)] -pub struct FixedMetadataValue<'mc>( +pub struct LazyMetadataValue<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for FixedMetadataValue<'mc> { +impl<'mc> JNIRaw<'mc> for LazyMetadataValue<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -387,20 +376,20 @@ impl<'mc> JNIRaw<'mc> for FixedMetadataValue<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for FixedMetadataValue<'mc> { +impl<'mc> JNIInstantiatable<'mc> for LazyMetadataValue<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate FixedMetadataValue from null object.").into(), + eyre::eyre!("Tried to instantiate LazyMetadataValue from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/metadata/FixedMetadataValue")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/metadata/LazyMetadataValue")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a FixedMetadataValue object, got {}", + "Invalid argument passed. Expected a LazyMetadataValue object, got {}", name ) .into()) @@ -410,30 +399,17 @@ impl<'mc> JNIInstantiatable<'mc> for FixedMetadataValue<'mc> { } } -impl<'mc> FixedMetadataValue<'mc> { - /// Initializes a FixedMetadataValue with an Object - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - owning_plugin: impl Into>, - value: jni::objects::JObject<'mc>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;Ljava/lang/Object;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(value); - let cls = jni.find_class("org/bukkit/metadata/FixedMetadataValue"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = jni.translate_error_no_gen(res)?; - crate::metadata::FixedMetadataValue::from_raw(&jni, res) +impl<'mc> LazyMetadataValue<'mc> { + pub fn value(&self) -> Result>, Box> { + let sig = String::from("()Ljava/lang/Object;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "value", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) } pub fn invalidate(&self) -> Result<(), Box> { @@ -444,111 +420,373 @@ impl<'mc> FixedMetadataValue<'mc> { self.jni_ref().translate_error(res)?; Ok(()) } + // SUPER CLASS: org.bukkit.metadata.MetadataValueAdapter ( ['value', 'invalidate']) - pub fn value(&self) -> Result>, Box> { - let sig = String::from("()Ljava/lang/Object;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "value", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(res.l()?)) + pub fn owning_plugin( + &self, + ) -> Result>, Box> { + let temp_clone = crate::metadata::MetadataValueAdapter::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::metadata::MetadataValueAdapter = temp_clone.into(); + real.owning_plugin() + } + + pub fn as_int(&self) -> Result> { + let temp_clone = crate::metadata::MetadataValueAdapter::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::metadata::MetadataValueAdapter = temp_clone.into(); + real.as_int() + } + + pub fn as_float(&self) -> Result> { + let temp_clone = crate::metadata::MetadataValueAdapter::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::metadata::MetadataValueAdapter = temp_clone.into(); + real.as_float() + } + + pub fn as_double(&self) -> Result> { + let temp_clone = crate::metadata::MetadataValueAdapter::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::metadata::MetadataValueAdapter = temp_clone.into(); + real.as_double() + } + + pub fn as_long(&self) -> Result> { + let temp_clone = crate::metadata::MetadataValueAdapter::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::metadata::MetadataValueAdapter = temp_clone.into(); + real.as_long() + } + + pub fn as_short(&self) -> Result> { + let temp_clone = crate::metadata::MetadataValueAdapter::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::metadata::MetadataValueAdapter = temp_clone.into(); + real.as_short() + } + + pub fn as_byte(&self) -> Result> { + let temp_clone = crate::metadata::MetadataValueAdapter::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::metadata::MetadataValueAdapter = temp_clone.into(); + real.as_byte() + } + + pub fn as_boolean(&self) -> Result> { + let temp_clone = crate::metadata::MetadataValueAdapter::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::metadata::MetadataValueAdapter = temp_clone.into(); + real.as_boolean() + } + + pub fn as_string(&self) -> Result> { + let temp_clone = crate::metadata::MetadataValueAdapter::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::metadata::MetadataValueAdapter = temp_clone.into(); + real.as_string() } - // SUPER CLASS: org.bukkit.metadata.LazyMetadataValue ( ['invalidate', 'value']) pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for FixedMetadataValue<'mc> { - fn into(self) -> crate::metadata::LazyMetadataValue<'mc> { - crate::metadata::LazyMetadataValue::from_raw(&self.jni_ref(), self.1) - .expect("Error converting FixedMetadataValue into crate::metadata::LazyMetadataValue") +impl<'mc> Into> for LazyMetadataValue<'mc> { + fn into(self) -> crate::metadata::MetadataValueAdapter<'mc> { + crate::metadata::MetadataValueAdapter::from_raw(&self.jni_ref(), self.1) + .expect("Error converting LazyMetadataValue into crate::metadata::MetadataValueAdapter") + } +} +pub enum LazyMetadataValueCacheStrategy<'mc> { + CacheAfterFirstEval { + inner: LazyMetadataValueCacheStrategyStruct<'mc>, + }, + NeverCache { + inner: LazyMetadataValueCacheStrategyStruct<'mc>, + }, + CacheEternally { + inner: LazyMetadataValueCacheStrategyStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for LazyMetadataValueCacheStrategy<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + LazyMetadataValueCacheStrategy::CacheAfterFirstEval { .. } => { + f.write_str("CACHE_AFTER_FIRST_EVAL") + } + LazyMetadataValueCacheStrategy::NeverCache { .. } => f.write_str("NEVER_CACHE"), + LazyMetadataValueCacheStrategy::CacheEternally { .. } => f.write_str("CACHE_ETERNALLY"), + } + } +} +impl<'mc> std::ops::Deref for LazyMetadataValueCacheStrategy<'mc> { + type Target = LazyMetadataValueCacheStrategyStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + LazyMetadataValueCacheStrategy::CacheAfterFirstEval { inner } => inner, + LazyMetadataValueCacheStrategy::NeverCache { inner } => inner, + LazyMetadataValueCacheStrategy::CacheEternally { inner } => inner, + } + } +} + +impl<'mc> LazyMetadataValueCacheStrategy<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/metadata/LazyMetadataValue/CacheStrategy"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/metadata/LazyMetadataValue/CacheStrategy;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "CACHE_AFTER_FIRST_EVAL" => Ok(LazyMetadataValueCacheStrategy::CacheAfterFirstEval { + inner: LazyMetadataValueCacheStrategyStruct::from_raw(env, obj)?, + }), + "NEVER_CACHE" => Ok(LazyMetadataValueCacheStrategy::NeverCache { + inner: LazyMetadataValueCacheStrategyStruct::from_raw(env, obj)?, + }), + "CACHE_ETERNALLY" => Ok(LazyMetadataValueCacheStrategy::CacheEternally { + inner: LazyMetadataValueCacheStrategyStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } + #[repr(C)] -pub struct Metadatable<'mc>( +pub struct LazyMetadataValueCacheStrategyStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Metadatable<'mc> { +impl<'mc> JNIRaw<'mc> for LazyMetadataValueCacheStrategy<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + match self { + Self::CacheAfterFirstEval { inner } => inner.0.clone(), + Self::NeverCache { inner } => inner.0.clone(), + Self::CacheEternally { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + match self { + Self::CacheAfterFirstEval { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NeverCache { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CacheEternally { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } -impl<'mc> JNIInstantiatable<'mc> for Metadatable<'mc> { +impl<'mc> JNIInstantiatable<'mc> for LazyMetadataValueCacheStrategy<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Metadatable from null object.").into()); + return Err(eyre::eyre!( + "Tried to instantiate LazyMetadataValueCacheStrategy from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/metadata/Metadatable")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/metadata/LazyMetadataValue/CacheStrategy")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Metadatable object, got {}", + "Invalid argument passed. Expected a LazyMetadataValueCacheStrategy object, got {}", name ) .into()) } else { - Ok(Self(env.clone(), obj)) + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "CACHE_AFTER_FIRST_EVAL" => { + Ok(LazyMetadataValueCacheStrategy::CacheAfterFirstEval { + inner: LazyMetadataValueCacheStrategyStruct::from_raw(env, obj)?, + }) + } + "NEVER_CACHE" => Ok(LazyMetadataValueCacheStrategy::NeverCache { + inner: LazyMetadataValueCacheStrategyStruct::from_raw(env, obj)?, + }), + "CACHE_ETERNALLY" => Ok(LazyMetadataValueCacheStrategy::CacheEternally { + inner: LazyMetadataValueCacheStrategyStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } } } } -impl<'mc> Metadatable<'mc> { - /// Sets a metadata value in the implementing object's metadata store. - pub fn set_metadata( - &self, - metadata_key: impl Into, - new_metadata_value: std::option::Option>>, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(metadata_key.into())?, - )); - args.push(val_1); - if let Some(a) = new_metadata_value { - sig += "Lorg/bukkit/metadata/MetadataValue;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); +impl<'mc> JNIRaw<'mc> for LazyMetadataValueCacheStrategyStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for LazyMetadataValueCacheStrategyStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate LazyMetadataValueCacheStrategyStruct from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/metadata/LazyMetadataValue/CacheStrategy")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a LazyMetadataValueCacheStrategyStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - sig += ")V"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setMetadata", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) } - /// Returns a list of previously set metadata values from the implementing - /// object's metadata store. +} + +impl<'mc> LazyMetadataValueCacheStrategyStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/metadata/LazyMetadataValue/CacheStrategy;"); + let cls = jni.find_class("org/bukkit/metadata/LazyMetadataValue/CacheStrategy"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::metadata::LazyMetadataValueCacheStrategy::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct MetadataStore<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for MetadataStore<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for MetadataStore<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate MetadataStore from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/metadata/MetadataStore")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a MetadataStore object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> MetadataStore<'mc> { + /// Adds a metadata value to an object. + pub fn set_metadata( + &self, + subject: jni::objects::JObject<'mc>, + metadata_key: impl Into, + new_metadata_value: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(LT;Ljava/lang/String;Lorg/bukkit/metadata/MetadataValue;)V"); + let val_1 = jni::objects::JValueGen::Object(subject); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(new_metadata_value.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMetadata", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Returns all metadata values attached to an object. If multiple plugins + /// have attached metadata, each will value will be included. pub fn get_metadata( &self, + subject: jni::objects::JObject<'mc>, metadata_key: impl Into, ) -> Result>, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + let sig = String::from("(LT;Ljava/lang/String;)Ljava/util/List;"); + let val_1 = jni::objects::JValueGen::Object(subject); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( self.jni_ref().new_string(metadata_key.into())?, )); - args.push(val_1); - sig += ")Ljava/util/List;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getMetadata", sig.as_str(), args); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMetadata", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; @@ -562,49 +800,74 @@ impl<'mc> Metadatable<'mc> { } Ok(new_vec) } - /// Tests to see whether the implementing object contains the given - /// metadata value in its metadata store. + /// Tests to see if a metadata attribute has been set on an object. pub fn has_metadata( &self, + subject: jni::objects::JObject<'mc>, metadata_key: impl Into, ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + let sig = String::from("(LT;Ljava/lang/String;)Z"); + let val_1 = jni::objects::JValueGen::Object(subject); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( self.jni_ref().new_string(metadata_key.into())?, )); - args.push(val_1); - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hasMetadata", sig.as_str(), args); + let res = self.jni_ref().call_method( + &self.jni_object(), + "hasMetadata", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - /// Removes the given metadata value from the implementing object's - /// metadata store. + /// Removes a metadata item owned by a plugin from a subject. pub fn remove_metadata( &self, + subject: jni::objects::JObject<'mc>, metadata_key: impl Into, owning_plugin: impl Into>, ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + let sig = String::from("(LT;Ljava/lang/String;Lorg/bukkit/plugin/Plugin;)V"); + let val_1 = jni::objects::JValueGen::Object(subject); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( self.jni_ref().new_string(metadata_key.into())?, )); - args.push(val_1); - sig += "Lorg/bukkit/plugin/Plugin;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { + let val_3 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) }); - args.push(val_2); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "removeMetadata", sig.as_str(), args); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeMetadata", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Invalidates all metadata in the metadata store that originates from the + /// given plugin. Doing this will force each invalidated metadata item to + /// be recalculated the next time it is accessed. + pub fn invalidate_all( + &self, + owning_plugin: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "invalidateAll", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } @@ -615,12 +878,12 @@ impl<'mc> Metadatable<'mc> { } } #[repr(C)] -pub struct MetadataValueAdapter<'mc>( +pub struct FixedMetadataValue<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for MetadataValueAdapter<'mc> { +impl<'mc> JNIRaw<'mc> for FixedMetadataValue<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -628,20 +891,20 @@ impl<'mc> JNIRaw<'mc> for MetadataValueAdapter<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for MetadataValueAdapter<'mc> { +impl<'mc> JNIInstantiatable<'mc> for FixedMetadataValue<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate MetadataValueAdapter from null object.").into(), + eyre::eyre!("Tried to instantiate FixedMetadataValue from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/metadata/MetadataValueAdapter")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/metadata/FixedMetadataValue")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a MetadataValueAdapter object, got {}", + "Invalid argument passed. Expected a FixedMetadataValue object, got {}", name ) .into()) @@ -651,118 +914,201 @@ impl<'mc> JNIInstantiatable<'mc> for MetadataValueAdapter<'mc> { } } -impl<'mc> MetadataValueAdapter<'mc> { - pub fn owning_plugin( - &self, - ) -> Result>, Box> { - let sig = String::from("()Lorg/bukkit/plugin/Plugin;"); +impl<'mc> FixedMetadataValue<'mc> { + /// Initializes a FixedMetadataValue with an Object + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + owning_plugin: impl Into>, + value: jni::objects::JObject<'mc>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;Ljava/lang/Object;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(value); + let cls = jni.find_class("org/bukkit/metadata/FixedMetadataValue"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::metadata::FixedMetadataValue::from_raw(&jni, res) + } + + pub fn invalidate(&self) -> Result<(), Box> { + let sig = String::from("()V"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getOwningPlugin", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::plugin::Plugin::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + .call_method(&self.jni_object(), "invalidate", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } - pub fn as_int(&self) -> Result> { - let sig = String::from("()I"); + pub fn value(&self) -> Result>, Box> { + let sig = String::from("()Ljava/lang/Object;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "asInt", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "value", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(res.l()?)) } + // SUPER CLASS: org.bukkit.metadata.LazyMetadataValue ( ['invalidate', 'value']) - pub fn as_float(&self) -> Result> { - let sig = String::from("()F"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "asFloat", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - - pub fn as_double(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "asDouble", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) +} +impl<'mc> Into> for FixedMetadataValue<'mc> { + fn into(self) -> crate::metadata::LazyMetadataValue<'mc> { + crate::metadata::LazyMetadataValue::from_raw(&self.jni_ref(), self.1) + .expect("Error converting FixedMetadataValue into crate::metadata::LazyMetadataValue") } +} +#[repr(C)] +pub struct Metadatable<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); - pub fn as_long(&self) -> Result> { - let sig = String::from("()J"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "asLong", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) +impl<'mc> JNIRaw<'mc> for Metadatable<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - - pub fn as_short(&self) -> Result> { - let sig = String::from("()S"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "asShort", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.s()?) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - - pub fn as_byte(&self) -> Result> { - let sig = String::from("()B"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "asByte", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.b()?) +} +impl<'mc> JNIInstantiatable<'mc> for Metadatable<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Metadatable from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/metadata/Metadatable")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Metadatable object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } +} - pub fn as_boolean(&self) -> Result> { - let sig = String::from("()Z"); +impl<'mc> Metadatable<'mc> { + /// Sets a metadata value in the implementing object's metadata store. + pub fn set_metadata( + &self, + metadata_key: impl Into, + new_metadata_value: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + if let Some(a) = new_metadata_value { + sig += "Lorg/bukkit/metadata/MetadataValue;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")V"; let res = self .jni_ref() - .call_method(&self.jni_object(), "asBoolean", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + .call_method(&self.jni_object(), "setMetadata", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - - pub fn as_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Returns a list of previously set metadata values from the implementing + /// object's metadata store. + pub fn get_metadata( + &self, + metadata_key: impl Into, + ) -> Result>, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += ")Ljava/util/List;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "asString", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMetadata", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::metadata::MetadataValue::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(new_vec) } - /// Fetches the value of this metadata item. - pub fn value(&self) -> Result>, Box> { - let sig = String::from("()Ljava/lang/Object;"); + /// Tests to see whether the implementing object contains the given + /// metadata value in its metadata store. + pub fn has_metadata( + &self, + metadata_key: impl Into, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "value", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hasMetadata", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(res.l()?)) + Ok(res.z()?) } - /// Invalidates this metadata item, forcing it to recompute when next - /// accessed. - pub fn invalidate(&self) -> Result<(), Box> { - let sig = String::from("()V"); + /// Removes the given metadata value from the implementing object's + /// metadata store. + pub fn remove_metadata( + &self, + metadata_key: impl Into, + owning_plugin: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(metadata_key.into())?, + )); + args.push(val_1); + sig += "Lorg/bukkit/plugin/Plugin;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(owning_plugin.into().jni_object().clone()) + }); + args.push(val_2); + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "invalidate", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "removeMetadata", sig.as_str(), args); self.jni_ref().translate_error(res)?; Ok(()) } @@ -772,12 +1118,6 @@ impl<'mc> MetadataValueAdapter<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for MetadataValueAdapter<'mc> { - fn into(self) -> crate::metadata::MetadataValue<'mc> { - crate::metadata::MetadataValue::from_raw(&self.jni_ref(), self.1) - .expect("Error converting MetadataValueAdapter into crate::metadata::MetadataValue") - } -} #[repr(C)] pub struct MetadataConversionException<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, @@ -991,285 +1331,6 @@ impl<'mc> MetadataValue<'mc> { } } #[repr(C)] -pub struct LazyMetadataValue<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for LazyMetadataValue<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for LazyMetadataValue<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate LazyMetadataValue from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/metadata/LazyMetadataValue")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a LazyMetadataValue object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> LazyMetadataValue<'mc> { - pub fn value(&self) -> Result>, Box> { - let sig = String::from("()Ljava/lang/Object;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "value", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(res.l()?)) - } - - pub fn invalidate(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "invalidate", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - // SUPER CLASS: org.bukkit.metadata.MetadataValueAdapter ( ['value', 'invalidate']) - - pub fn owning_plugin( - &self, - ) -> Result>, Box> { - let temp_clone = crate::metadata::MetadataValueAdapter::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::metadata::MetadataValueAdapter = temp_clone.into(); - real.owning_plugin() - } - - pub fn as_int(&self) -> Result> { - let temp_clone = crate::metadata::MetadataValueAdapter::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::metadata::MetadataValueAdapter = temp_clone.into(); - real.as_int() - } - - pub fn as_float(&self) -> Result> { - let temp_clone = crate::metadata::MetadataValueAdapter::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::metadata::MetadataValueAdapter = temp_clone.into(); - real.as_float() - } - - pub fn as_double(&self) -> Result> { - let temp_clone = crate::metadata::MetadataValueAdapter::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::metadata::MetadataValueAdapter = temp_clone.into(); - real.as_double() - } - - pub fn as_long(&self) -> Result> { - let temp_clone = crate::metadata::MetadataValueAdapter::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::metadata::MetadataValueAdapter = temp_clone.into(); - real.as_long() - } - - pub fn as_short(&self) -> Result> { - let temp_clone = crate::metadata::MetadataValueAdapter::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::metadata::MetadataValueAdapter = temp_clone.into(); - real.as_short() - } - - pub fn as_byte(&self) -> Result> { - let temp_clone = crate::metadata::MetadataValueAdapter::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::metadata::MetadataValueAdapter = temp_clone.into(); - real.as_byte() - } - - pub fn as_boolean(&self) -> Result> { - let temp_clone = crate::metadata::MetadataValueAdapter::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::metadata::MetadataValueAdapter = temp_clone.into(); - real.as_boolean() - } - - pub fn as_string(&self) -> Result> { - let temp_clone = crate::metadata::MetadataValueAdapter::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::metadata::MetadataValueAdapter = temp_clone.into(); - real.as_string() - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for LazyMetadataValue<'mc> { - fn into(self) -> crate::metadata::MetadataValueAdapter<'mc> { - crate::metadata::MetadataValueAdapter::from_raw(&self.jni_ref(), self.1) - .expect("Error converting LazyMetadataValue into crate::metadata::MetadataValueAdapter") - } -} -pub enum LazyMetadataValueCacheStrategy<'mc> {} -impl<'mc> std::fmt::Display for LazyMetadataValueCacheStrategy<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> LazyMetadataValueCacheStrategy<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/metadata/LazyMetadataValue/CacheStrategy"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/metadata/LazyMetadataValue/CacheStrategy;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - -#[repr(C)] -pub struct LazyMetadataValueCacheStrategyStruct<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for LazyMetadataValueCacheStrategy<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} - } -} -impl<'mc> JNIInstantiatable<'mc> for LazyMetadataValueCacheStrategy<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate LazyMetadataValueCacheStrategy from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/metadata/LazyMetadataValue/CacheStrategy")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a LazyMetadataValueCacheStrategy object, got {}", - name - ) - .into()) - } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } - } -} - -impl<'mc> JNIRaw<'mc> for LazyMetadataValueCacheStrategyStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for LazyMetadataValueCacheStrategyStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate LazyMetadataValueCacheStrategyStruct from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/metadata/LazyMetadataValue/CacheStrategy")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a LazyMetadataValueCacheStrategyStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> LazyMetadataValueCacheStrategyStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/metadata/LazyMetadataValue/CacheStrategy;"); - let cls = jni.find_class("org/bukkit/metadata/LazyMetadataValue/CacheStrategy"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::metadata::LazyMetadataValueCacheStrategy::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] pub struct MetadataEvaluationException<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, diff --git a/blackboxmc-rs-bukkit/src/packs/mod.rs b/blackboxmc-rs-bukkit/src/packs/mod.rs index af61a8e..54e37d9 100644 --- a/blackboxmc-rs-bukkit/src/packs/mod.rs +++ b/blackboxmc-rs-bukkit/src/packs/mod.rs @@ -3,12 +3,12 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] -pub struct DataPackManager<'mc>( +pub struct DataPack<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for DataPackManager<'mc> { +impl<'mc> JNIRaw<'mc> for DataPack<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -16,20 +16,18 @@ impl<'mc> JNIRaw<'mc> for DataPackManager<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for DataPackManager<'mc> { +impl<'mc> JNIInstantiatable<'mc> for DataPack<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate DataPackManager from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate DataPack from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/packs/DataPackManager")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/packs/DataPack")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a DataPackManager object, got {}", + "Invalid argument passed. Expected a DataPack object, got {}", name ) .into()) @@ -39,126 +37,151 @@ impl<'mc> JNIInstantiatable<'mc> for DataPackManager<'mc> { } } -impl<'mc> DataPackManager<'mc> { - /// Return all the available {@link DataPack}s on the server. - pub fn data_packs( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); +impl<'mc> DataPack<'mc> { + /// Gets the title of the data pack. + pub fn title(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTitle", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gets the description of the data pack. + pub fn description(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDataPacks", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getDescription", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::packs::DataPack::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Gets a {@link DataPack} by its key. - pub fn get_data_pack( - &self, - data_pack_key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/packs/DataPack;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(data_pack_key.into().jni_object().clone()) - }); + /// Gets the pack format. + /// + /// Pack formats are non-standard and unrelated to the version of Minecraft. For + /// a list of known pack versions, see the + /// Minecraft Wiki. + pub fn pack_format(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPackFormat", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Gets the minimum supported pack format. If the data pack does not specify a + /// minimum supported format, {@link #getPackFormat()} is returned. + /// + /// Pack formats are non-standard and unrelated to the version of Minecraft. For + /// a list of known pack versions, see the + /// Minecraft Wiki. + pub fn min_supported_pack_format(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getDataPack", + "getMinSupportedPackFormat", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::packs::DataPack::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) + Ok(res.i()?) } - /// Return all the enabled {@link DataPack} in the World. - pub fn get_enabled_data_packs( - &self, - world: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/World;)Ljava/util/Collection;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); + /// Gets the maximum supported pack format. If the data pack does not specify a + /// maximum supported format, {@link #getPackFormat()} is returned. + /// + /// Pack formats are non-standard and unrelated to the version of Minecraft. For + /// a list of known pack versions, see the + /// Minecraft Wiki. + pub fn max_supported_pack_format(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref().call_method( &self.jni_object(), - "getEnabledDataPacks", + "getMaxSupportedPackFormat", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::packs::DataPack::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + Ok(res.i()?) } - /// Return all the disabled {@link DataPack} in the World. - pub fn get_disabled_data_packs( + /// Gets if the data pack is enabled on the server. + pub fn is_enabled(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isEnabled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets if the data pack is required on the server. + pub fn is_required(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isRequired", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Gets the compatibility of this data pack with the server. + pub fn compatibility( &self, - world: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/World;)Ljava/util/Collection;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/packs/DataPack/Compatibility;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getDisabledDataPacks", + "getCompatibility", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::packs::DataPack::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) + crate::packs::DataPackCompatibility::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets if the EntityType is enabled for use by the Features in World. - pub fn is_enabled_by_feature( + /// Gets a set of features requested by this data pack. + pub fn requested_features( &self, - entity_type: impl Into>, - world: impl Into>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/entity/EntityType;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity_type.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Lorg/bukkit/World;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); - args.push(val_2); - sig += ")Z"; + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); let res = self.jni_ref().call_method( &self.jni_object(), - "isEnabledByFeature", + "getRequestedFeatures", sig.as_str(), - args, + vec![], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the source of this data pack. + pub fn source(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/packs/DataPack/Source;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getSource", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::packs::DataPackSource::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Return the namespaced identifier for this object. + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -166,312 +189,40 @@ impl<'mc> DataPackManager<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -#[repr(C)] -pub struct ResourcePack<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for ResourcePack<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() +impl<'mc> Into> for DataPack<'mc> { + fn into(self) -> crate::Keyed<'mc> { + crate::Keyed::from_raw(&self.jni_ref(), self.1) + .expect("Error converting DataPack into crate::Keyed") } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } +} +pub enum DataPackCompatibility<'mc> { + New { + inner: DataPackCompatibilityStruct<'mc>, + }, + Old { + inner: DataPackCompatibilityStruct<'mc>, + }, + Compatible { + inner: DataPackCompatibilityStruct<'mc>, + }, +} +impl<'mc> std::fmt::Display for DataPackCompatibility<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + DataPackCompatibility::New { .. } => f.write_str("NEW"), + DataPackCompatibility::Old { .. } => f.write_str("OLD"), + DataPackCompatibility::Compatible { .. } => f.write_str("COMPATIBLE"), + } } } -impl<'mc> JNIInstantiatable<'mc> for ResourcePack<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ResourcePack from null object.").into()); +impl<'mc> std::ops::Deref for DataPackCompatibility<'mc> { + type Target = DataPackCompatibilityStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + DataPackCompatibility::New { inner } => inner, + DataPackCompatibility::Old { inner } => inner, + DataPackCompatibility::Compatible { inner } => inner, } - let (valid, name) = env.validate_name(&obj, "org/bukkit/packs/ResourcePack")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ResourcePack object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> ResourcePack<'mc> { - /// Gets the id of the resource pack. - pub fn id(&self) -> Result, Box> { - let sig = String::from("()Ljava/util/UUID;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the url of the resource pack. - pub fn url(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getUrl", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Gets the hash of the resource pack. - pub fn hash(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getHash", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// Gets the prompt to show of the resource pack. - pub fn prompt(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPrompt", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) - } - /// Gets if the resource pack is required by the server. - pub fn is_required(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isRequired", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct DataPack<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for DataPack<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for DataPack<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate DataPack from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/packs/DataPack")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a DataPack object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> DataPack<'mc> { - /// Gets the title of the data pack. - pub fn title(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTitle", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Gets the description of the data pack. - pub fn description(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getDescription", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Gets the pack format. - /// - /// Pack formats are non-standard and unrelated to the version of Minecraft. For - /// a list of known pack versions, see the - /// Minecraft Wiki. - pub fn pack_format(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPackFormat", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the minimum supported pack format. If the data pack does not specify a - /// minimum supported format, {@link #getPackFormat()} is returned. - /// - /// Pack formats are non-standard and unrelated to the version of Minecraft. For - /// a list of known pack versions, see the - /// Minecraft Wiki. - pub fn min_supported_pack_format(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMinSupportedPackFormat", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets the maximum supported pack format. If the data pack does not specify a - /// maximum supported format, {@link #getPackFormat()} is returned. - /// - /// Pack formats are non-standard and unrelated to the version of Minecraft. For - /// a list of known pack versions, see the - /// Minecraft Wiki. - pub fn max_supported_pack_format(&self) -> Result> { - let sig = String::from("()I"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMaxSupportedPackFormat", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Gets if the data pack is enabled on the server. - pub fn is_enabled(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isEnabled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets if the data pack is required on the server. - pub fn is_required(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isRequired", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Gets the compatibility of this data pack with the server. - pub fn compatibility( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/packs/DataPack/Compatibility;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCompatibility", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::packs::DataPackCompatibility::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets a set of features requested by this data pack. - pub fn requested_features( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getRequestedFeatures", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the source of this data pack. - pub fn source(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/packs/DataPack/Source;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getSource", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::packs::DataPackSource::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Return the namespaced identifier for this object. - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for DataPack<'mc> { - fn into(self) -> crate::Keyed<'mc> { - crate::Keyed::from_raw(&self.jni_ref(), self.1) - .expect("Error converting DataPack into crate::Keyed") - } -} -pub enum DataPackCompatibility<'mc> {} -impl<'mc> std::fmt::Display for DataPackCompatibility<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} } } @@ -498,6 +249,16 @@ impl<'mc> DataPackCompatibility<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NEW" => Ok(DataPackCompatibility::New { + inner: DataPackCompatibilityStruct::from_raw(env, obj)?, + }), + "OLD" => Ok(DataPackCompatibility::Old { + inner: DataPackCompatibilityStruct::from_raw(env, obj)?, + }), + "COMPATIBLE" => Ok(DataPackCompatibility::Compatible { + inner: DataPackCompatibilityStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -511,10 +272,20 @@ pub struct DataPackCompatibilityStruct<'mc>( impl<'mc> JNIRaw<'mc> for DataPackCompatibility<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::New { inner } => inner.0.clone(), + Self::Old { inner } => inner.0.clone(), + Self::Compatible { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::New { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Old { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Compatible { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } impl<'mc> JNIInstantiatable<'mc> for DataPackCompatibility<'mc> { @@ -543,6 +314,15 @@ impl<'mc> JNIInstantiatable<'mc> for DataPackCompatibility<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NEW" => Ok(DataPackCompatibility::New { + inner: DataPackCompatibilityStruct::from_raw(env, obj)?, + }), + "OLD" => Ok(DataPackCompatibility::Old { + inner: DataPackCompatibilityStruct::from_raw(env, obj)?, + }), + "COMPATIBLE" => Ok(DataPackCompatibility::Compatible { + inner: DataPackCompatibilityStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -599,10 +379,34 @@ impl<'mc> DataPackCompatibilityStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum DataPackSource<'mc> {} +pub enum DataPackSource<'mc> { + Default { inner: DataPackSourceStruct<'mc> }, + BuiltIn { inner: DataPackSourceStruct<'mc> }, + Feature { inner: DataPackSourceStruct<'mc> }, + World { inner: DataPackSourceStruct<'mc> }, + Server { inner: DataPackSourceStruct<'mc> }, +} impl<'mc> std::fmt::Display for DataPackSource<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + DataPackSource::Default { .. } => f.write_str("DEFAULT"), + DataPackSource::BuiltIn { .. } => f.write_str("BUILT_IN"), + DataPackSource::Feature { .. } => f.write_str("FEATURE"), + DataPackSource::World { .. } => f.write_str("WORLD"), + DataPackSource::Server { .. } => f.write_str("SERVER"), + } + } +} +impl<'mc> std::ops::Deref for DataPackSource<'mc> { + type Target = DataPackSourceStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + DataPackSource::Default { inner } => inner, + DataPackSource::BuiltIn { inner } => inner, + DataPackSource::Feature { inner } => inner, + DataPackSource::World { inner } => inner, + DataPackSource::Server { inner } => inner, + } } } @@ -629,57 +433,319 @@ impl<'mc> DataPackSource<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "DEFAULT" => Ok(DataPackSource::Default { + inner: DataPackSourceStruct::from_raw(env, obj)?, + }), + "BUILT_IN" => Ok(DataPackSource::BuiltIn { + inner: DataPackSourceStruct::from_raw(env, obj)?, + }), + "FEATURE" => Ok(DataPackSource::Feature { + inner: DataPackSourceStruct::from_raw(env, obj)?, + }), + "WORLD" => Ok(DataPackSource::World { + inner: DataPackSourceStruct::from_raw(env, obj)?, + }), + "SERVER" => Ok(DataPackSource::Server { + inner: DataPackSourceStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } -} +} + +#[repr(C)] +pub struct DataPackSourceStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for DataPackSource<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Default { inner } => inner.0.clone(), + Self::BuiltIn { inner } => inner.0.clone(), + Self::Feature { inner } => inner.0.clone(), + Self::World { inner } => inner.0.clone(), + Self::Server { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Default { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::BuiltIn { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Feature { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::World { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Server { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for DataPackSource<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate DataPackSource from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/packs/DataPack/Source")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a DataPackSource object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "DEFAULT" => Ok(DataPackSource::Default { + inner: DataPackSourceStruct::from_raw(env, obj)?, + }), + "BUILT_IN" => Ok(DataPackSource::BuiltIn { + inner: DataPackSourceStruct::from_raw(env, obj)?, + }), + "FEATURE" => Ok(DataPackSource::Feature { + inner: DataPackSourceStruct::from_raw(env, obj)?, + }), + "WORLD" => Ok(DataPackSource::World { + inner: DataPackSourceStruct::from_raw(env, obj)?, + }), + "SERVER" => Ok(DataPackSource::Server { + inner: DataPackSourceStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for DataPackSourceStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for DataPackSourceStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate DataPackSourceStruct from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/packs/DataPack/Source")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a DataPackSourceStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> DataPackSourceStruct<'mc> { + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/packs/DataPack/Source;"); + let cls = jni.find_class("org/bukkit/packs/DataPack/Source"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::packs::DataPackSource::from_raw(&jni, obj) + } + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} #[repr(C)] -pub struct DataPackSourceStruct<'mc>( +pub struct DataPackManager<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for DataPackSource<'mc> { +impl<'mc> JNIRaw<'mc> for DataPackManager<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + self.0.clone() } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for DataPackSource<'mc> { +impl<'mc> JNIInstantiatable<'mc> for DataPackManager<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate DataPackSource from null object.").into(), + eyre::eyre!("Tried to instantiate DataPackManager from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/packs/DataPack/Source")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/packs/DataPackManager")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a DataPackSource object, got {}", + "Invalid argument passed. Expected a DataPackManager object, got {}", name ) .into()) } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + Ok(Self(env.clone(), obj)) } } } -impl<'mc> JNIRaw<'mc> for DataPackSourceStruct<'mc> { +impl<'mc> DataPackManager<'mc> { + /// Return all the available {@link DataPack}s on the server. + pub fn data_packs( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDataPacks", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::packs::DataPack::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Gets a {@link DataPack} by its key. + pub fn get_data_pack( + &self, + data_pack_key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/packs/DataPack;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(data_pack_key.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDataPack", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::packs::DataPack::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Return all the enabled {@link DataPack} in the World. + pub fn get_enabled_data_packs( + &self, + world: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/World;)Ljava/util/Collection;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(world.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getEnabledDataPacks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::packs::DataPack::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Return all the disabled {@link DataPack} in the World. + pub fn get_disabled_data_packs( + &self, + world: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/World;)Ljava/util/Collection;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(world.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDisabledDataPacks", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::packs::DataPack::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) + } + /// Gets if the EntityType is enabled for use by the Features in World. + pub fn is_enabled_by_feature( + &self, + entity_type: impl Into>, + world: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/EntityType;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(entity_type.into().jni_object().clone()) + }); + args.push(val_1); + sig += "Lorg/bukkit/World;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(world.into().jni_object().clone()) + }); + args.push(val_2); + sig += ")Z"; + let res = self.jni_ref().call_method( + &self.jni_object(), + "isEnabledByFeature", + sig.as_str(), + args, + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct ResourcePack<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ResourcePack<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -687,20 +753,18 @@ impl<'mc> JNIRaw<'mc> for DataPackSourceStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for DataPackSourceStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ResourcePack<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate DataPackSourceStruct from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate ResourcePack from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/packs/DataPack/Source")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/packs/ResourcePack")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a DataPackSourceStruct object, got {}", + "Invalid argument passed. Expected a ResourcePack object, got {}", name ) .into()) @@ -710,17 +774,73 @@ impl<'mc> JNIInstantiatable<'mc> for DataPackSourceStruct<'mc> { } } -impl<'mc> DataPackSourceStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/packs/DataPack/Source;"); - let cls = jni.find_class("org/bukkit/packs/DataPack/Source"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::packs::DataPackSource::from_raw(&jni, obj) +impl<'mc> ResourcePack<'mc> { + /// Gets the id of the resource pack. + pub fn id(&self) -> Result, Box> { + let sig = String::from("()Ljava/util/UUID;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaUUID::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the url of the resource pack. + pub fn url(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getUrl", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gets the hash of the resource pack. + pub fn hash(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHash", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Gets the prompt to show of the resource pack. + pub fn prompt(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPrompt", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + /// Gets if the resource pack is required by the server. + pub fn is_required(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isRequired", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } pub fn instance_of(&self, other: impl Into) -> Result { diff --git a/blackboxmc-rs-bukkit/src/permissions/mod.rs b/blackboxmc-rs-bukkit/src/permissions/mod.rs index a2830b9..261dafa 100644 --- a/blackboxmc-rs-bukkit/src/permissions/mod.rs +++ b/blackboxmc-rs-bukkit/src/permissions/mod.rs @@ -2,10 +2,31 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; -pub enum PermissionDefault<'mc> {} +pub enum PermissionDefault<'mc> { + VariantTrue { inner: PermissionDefaultStruct<'mc> }, + VariantFalse { inner: PermissionDefaultStruct<'mc> }, + Op { inner: PermissionDefaultStruct<'mc> }, + NotOp { inner: PermissionDefaultStruct<'mc> }, +} impl<'mc> std::fmt::Display for PermissionDefault<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + PermissionDefault::VariantTrue { .. } => f.write_str("TRUE"), + PermissionDefault::VariantFalse { .. } => f.write_str("FALSE"), + PermissionDefault::Op { .. } => f.write_str("OP"), + PermissionDefault::NotOp { .. } => f.write_str("NOT_OP"), + } + } +} +impl<'mc> std::ops::Deref for PermissionDefault<'mc> { + type Target = PermissionDefaultStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + PermissionDefault::VariantTrue { inner } => inner, + PermissionDefault::VariantFalse { inner } => inner, + PermissionDefault::Op { inner } => inner, + PermissionDefault::NotOp { inner } => inner, + } } } @@ -32,6 +53,19 @@ impl<'mc> PermissionDefault<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "TRUE" => Ok(PermissionDefault::VariantTrue { + inner: PermissionDefaultStruct::from_raw(env, obj)?, + }), + "FALSE" => Ok(PermissionDefault::VariantFalse { + inner: PermissionDefaultStruct::from_raw(env, obj)?, + }), + "OP" => Ok(PermissionDefault::Op { + inner: PermissionDefaultStruct::from_raw(env, obj)?, + }), + "NOT_OP" => Ok(PermissionDefault::NotOp { + inner: PermissionDefaultStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -45,10 +79,24 @@ pub struct PermissionDefaultStruct<'mc>( impl<'mc> JNIRaw<'mc> for PermissionDefault<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::VariantTrue { inner } => inner.0.clone(), + Self::VariantFalse { inner } => inner.0.clone(), + Self::Op { inner } => inner.0.clone(), + Self::NotOp { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::VariantTrue { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::VariantFalse { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Op { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::NotOp { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for PermissionDefault<'mc> { @@ -76,6 +124,18 @@ impl<'mc> JNIInstantiatable<'mc> for PermissionDefault<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "TRUE" => Ok(PermissionDefault::VariantTrue { + inner: PermissionDefaultStruct::from_raw(env, obj)?, + }), + "FALSE" => Ok(PermissionDefault::VariantFalse { + inner: PermissionDefaultStruct::from_raw(env, obj)?, + }), + "OP" => Ok(PermissionDefault::Op { + inner: PermissionDefaultStruct::from_raw(env, obj)?, + }), + "NOT_OP" => Ok(PermissionDefault::NotOp { + inner: PermissionDefaultStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -321,12 +381,12 @@ impl<'mc> PermissionAttachmentInfo<'mc> { } } #[repr(C)] -pub struct PermissibleBase<'mc>( +pub struct PermissionAttachment<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PermissibleBase<'mc> { +impl<'mc> JNIRaw<'mc> for PermissionAttachment<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -334,20 +394,21 @@ impl<'mc> JNIRaw<'mc> for PermissibleBase<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PermissibleBase<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PermissionAttachment<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate PermissibleBase from null object.").into(), + eyre::eyre!("Tried to instantiate PermissionAttachment from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/permissions/PermissibleBase")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/permissions/PermissionAttachment")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PermissibleBase object, got {}", + "Invalid argument passed. Expected a PermissionAttachment object, got {}", name ) .into()) @@ -357,52 +418,123 @@ impl<'mc> JNIInstantiatable<'mc> for PermissibleBase<'mc> { } } -impl<'mc> PermissibleBase<'mc> { +impl<'mc> PermissionAttachment<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - opable: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/permissions/ServerOperator;)V"); + plugin: impl Into>, + permissible: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;Lorg/bukkit/permissions/Permissible;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(opable.into().jni_object().clone()) + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/permissions/PermissibleBase"); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(permissible.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/permissions/PermissionAttachment"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); let res = jni.translate_error_no_gen(res)?; - crate::permissions::PermissibleBase::from_raw(&jni, res) + crate::permissions::PermissionAttachment::from_raw(&jni, res) } - - pub fn is_op(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the plugin responsible for this attachment + pub fn plugin(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/plugin/Plugin;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "isOp", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPlugin", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::plugin::Plugin::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - - pub fn set_op(&self, value: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(value.into()); + /// Sets an object to be called for when this attachment is removed from a + /// {@link Permissible}. May be null. + pub fn set_removal_callback( + &self, + ex: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/permissions/PermissionRemovedExecutor;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(ex.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setOp", + "setRemovalCallback", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn is_permission_set( + /// Gets the class that was previously set to be called when this + /// attachment was removed from a {@link Permissible}. May be null. + pub fn removal_callback( + &self, + ) -> Result< + Option>, + Box, + > { + let sig = String::from("()Lorg/bukkit/permissions/PermissionRemovedExecutor;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getRemovalCallback", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + crate::permissions::PermissionRemovedExecutor::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + })?, + )) + } + /// Gets the Permissible that this is attached to + pub fn permissible( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/permissions/Permissible;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPermissible", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::permissions::Permissible::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets a copy of all set permissions and values contained within this + /// attachment. + /// + /// This map may be modified but will not affect the attachment, as it is a + /// copy. + pub fn permissions( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Map;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPermissions", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Sets a permission to the given value + pub fn set_permission( &self, perm: impl Into>, - ) -> Result> { + value: bool, + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "Lorg/bukkit/permissions/Permission;"; @@ -410,18 +542,24 @@ impl<'mc> PermissibleBase<'mc> { jni::objects::JObject::from_raw(perm.into().jni_object().clone()) }); args.push(val_1); - sig += ")Z"; + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(value.into()); + args.push(val_2); + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "isPermissionSet", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + .call_method(&self.jni_object(), "setPermission", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) } - - pub fn has_permission( + /// Removes the specified permission from this attachment. + /// + /// If the permission does not exist in this attachment, nothing will + /// happen. + pub fn unset_permission( &self, perm: impl Into>, - ) -> Result> { + ) -> Result<(), Box> { let mut args = Vec::new(); let mut sig = String::from("("); sig += "Lorg/bukkit/permissions/Permission;"; @@ -429,329 +567,97 @@ impl<'mc> PermissibleBase<'mc> { jni::objects::JObject::from_raw(perm.into().jni_object().clone()) }); args.push(val_1); - sig += ")Z"; + sig += ")V"; let res = self.jni_ref() - .call_method(&self.jni_object(), "hasPermission", sig.as_str(), args); + .call_method(&self.jni_object(), "unsetPermission", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Removes this attachment from its registered {@link Permissible} + pub fn remove(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } - pub fn add_attachment( - &self, - plugin: impl Into>, - name: std::option::Option>, - value: std::option::Option, - ticks: std::option::Option, - ) -> Result>, Box> - { + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct Permission<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Permission<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Permission<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Permission from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/permissions/Permission")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Permission object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Permission<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + name: impl Into, + description: std::option::Option>, + default_value: std::option::Option>>, + children: std::option::Option>>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/plugin/Plugin;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(name.into())?, + )); args.push(val_1); - if let Some(a) = name { + if let Some(a) = description { sig += "Ljava/lang/String;"; let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(a.into())?, + jni.new_string(a.into())?, )); args.push(val_2); } - if let Some(a) = value { - sig += "Z"; - let val_3 = jni::objects::JValueGen::Bool(a.into()); + if let Some(a) = default_value { + sig += "Lorg/bukkit/permissions/PermissionDefault;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); args.push(val_3); } - if let Some(a) = ticks { - sig += "I"; - let val_4 = jni::objects::JValueGen::Int(a); - args.push(val_4); - } - sig += ")Lorg/bukkit/permissions/PermissionAttachment;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "addAttachment", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::permissions::PermissionAttachment::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - - pub fn remove_attachment( - &self, - attachment: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/permissions/PermissionAttachment;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attachment.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "removeAttachment", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn recalculate_permissions(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "recalculatePermissions", - sig.as_str(), - vec![], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn clear_permissions(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "clearPermissions", - sig.as_str(), - vec![], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn effective_permissions( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getEffectivePermissions", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for PermissibleBase<'mc> { - fn into(self) -> crate::permissions::Permissible<'mc> { - crate::permissions::Permissible::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PermissibleBase into crate::permissions::Permissible") - } -} -#[repr(C)] -pub struct ServerOperator<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for ServerOperator<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for ServerOperator<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate ServerOperator from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/permissions/ServerOperator")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a ServerOperator object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> ServerOperator<'mc> { - /// Checks if this object is a server operator - pub fn is_op(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isOp", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Sets the operator status of this object - pub fn set_op(&self, value: bool) -> Result<(), Box> { - let sig = String::from("(Z)V"); - let val_1 = jni::objects::JValueGen::Bool(value.into()); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setOp", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct PermissionRemovedExecutor<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PermissionRemovedExecutor<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PermissionRemovedExecutor<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PermissionRemovedExecutor from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/permissions/PermissionRemovedExecutor")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PermissionRemovedExecutor object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> PermissionRemovedExecutor<'mc> { - /// Called when a {@link PermissionAttachment} is removed from a {@link - /// Permissible} - pub fn attachment_removed( - &self, - attachment: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/permissions/PermissionAttachment;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(attachment.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "attachmentRemoved", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct Permission<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Permission<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Permission<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Permission from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/permissions/Permission")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Permission object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Permission<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - name: impl Into, - description: std::option::Option>, - default_value: std::option::Option>>, - children: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(name.into())?, - )); - args.push(val_1); - if let Some(a) = description { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(a.into())?, - )); - args.push(val_2); - } - if let Some(a) = default_value { - sig += "Lorg/bukkit/permissions/PermissionDefault;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_3); - } - if let Some(a) = children { - sig += "Ljava/util/Map;"; - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); + if let Some(a) = children { + sig += "Ljava/util/Map;"; + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); args.push(val_4); } sig += ")V"; @@ -1032,12 +938,244 @@ impl<'mc> Permission<'mc> { } } #[repr(C)] -pub struct PermissionAttachment<'mc>( +pub struct PermissibleBase<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PermissibleBase<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PermissibleBase<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate PermissibleBase from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/permissions/PermissibleBase")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PermissibleBase object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> PermissibleBase<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + opable: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/permissions/ServerOperator;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(opable.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/permissions/PermissibleBase"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error_no_gen(res)?; + crate::permissions::PermissibleBase::from_raw(&jni, res) + } + + pub fn is_op(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isOp", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn set_op(&self, value: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(value.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setOp", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn is_permission_set( + &self, + perm: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/permissions/Permission;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(perm.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isPermissionSet", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn has_permission( + &self, + perm: impl Into>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/permissions/Permission;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(perm.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")Z"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasPermission", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn add_attachment( + &self, + plugin: impl Into>, + name: std::option::Option>, + value: std::option::Option, + ticks: std::option::Option, + ) -> Result>, Box> + { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/plugin/Plugin;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = name { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(a.into())?, + )); + args.push(val_2); + } + if let Some(a) = value { + sig += "Z"; + let val_3 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_3); + } + if let Some(a) = ticks { + sig += "I"; + let val_4 = jni::objects::JValueGen::Int(a); + args.push(val_4); + } + sig += ")Lorg/bukkit/permissions/PermissionAttachment;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "addAttachment", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::permissions::PermissionAttachment::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + + pub fn remove_attachment( + &self, + attachment: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/permissions/PermissionAttachment;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(attachment.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removeAttachment", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn recalculate_permissions(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "recalculatePermissions", + sig.as_str(), + vec![], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn clear_permissions(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "clearPermissions", + sig.as_str(), + vec![], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn effective_permissions( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getEffectivePermissions", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for PermissibleBase<'mc> { + fn into(self) -> crate::permissions::Permissible<'mc> { + crate::permissions::Permissible::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PermissibleBase into crate::permissions::Permissible") + } +} +#[repr(C)] +pub struct ServerOperator<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PermissionAttachment<'mc> { +impl<'mc> JNIRaw<'mc> for ServerOperator<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1045,21 +1183,20 @@ impl<'mc> JNIRaw<'mc> for PermissionAttachment<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PermissionAttachment<'mc> { +impl<'mc> JNIInstantiatable<'mc> for ServerOperator<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate PermissionAttachment from null object.").into(), + eyre::eyre!("Tried to instantiate ServerOperator from null object.").into(), ); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/permissions/PermissionAttachment")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/permissions/ServerOperator")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PermissionAttachment object, got {}", + "Invalid argument passed. Expected a ServerOperator object, got {}", name ) .into()) @@ -1069,171 +1206,94 @@ impl<'mc> JNIInstantiatable<'mc> for PermissionAttachment<'mc> { } } -impl<'mc> PermissionAttachment<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - plugin: impl Into>, - permissible: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;Lorg/bukkit/permissions/Permissible;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(permissible.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/permissions/PermissionAttachment"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = jni.translate_error_no_gen(res)?; - crate::permissions::PermissionAttachment::from_raw(&jni, res) - } - /// Gets the plugin responsible for this attachment - pub fn plugin(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/plugin/Plugin;"); +impl<'mc> ServerOperator<'mc> { + /// Checks if this object is a server operator + pub fn is_op(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getPlugin", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isOp", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::plugin::Plugin::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.z()?) } - /// Sets an object to be called for when this attachment is removed from a - /// {@link Permissible}. May be null. - pub fn set_removal_callback( - &self, - ex: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/permissions/PermissionRemovedExecutor;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(ex.into().jni_object().clone()) - }); + /// Sets the operator status of this object + pub fn set_op(&self, value: bool) -> Result<(), Box> { + let sig = String::from("(Z)V"); + let val_1 = jni::objects::JValueGen::Bool(value.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "setRemovalCallback", + "setOp", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Gets the class that was previously set to be called when this - /// attachment was removed from a {@link Permissible}. May be null. - pub fn removal_callback( - &self, - ) -> Result< - Option>, - Box, - > { - let sig = String::from("()Lorg/bukkit/permissions/PermissionRemovedExecutor;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getRemovalCallback", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - crate::permissions::PermissionRemovedExecutor::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - })?, - )) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Gets the Permissible that this is attached to - pub fn permissible( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/permissions/Permissible;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPermissible", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::permissions::Permissible::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} +#[repr(C)] +pub struct PermissionRemovedExecutor<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PermissionRemovedExecutor<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Gets a copy of all set permissions and values contained within this - /// attachment. - /// - /// This map may be modified but will not affect the attachment, as it is a - /// copy. - pub fn permissions( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPermissions", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Sets a permission to the given value - pub fn set_permission( - &self, - perm: impl Into>, - value: bool, - ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/permissions/Permission;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(perm.into().jni_object().clone()) - }); - args.push(val_1); - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(value.into()); - args.push(val_2); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "setPermission", sig.as_str(), args); - self.jni_ref().translate_error(res)?; - Ok(()) +} +impl<'mc> JNIInstantiatable<'mc> for PermissionRemovedExecutor<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate PermissionRemovedExecutor from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/permissions/PermissionRemovedExecutor")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PermissionRemovedExecutor object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } - /// Removes the specified permission from this attachment. - /// - /// If the permission does not exist in this attachment, nothing will - /// happen. - pub fn unset_permission( +} + +impl<'mc> PermissionRemovedExecutor<'mc> { + /// Called when a {@link PermissionAttachment} is removed from a {@link + /// Permissible} + pub fn attachment_removed( &self, - perm: impl Into>, + attachment: impl Into>, ) -> Result<(), Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/permissions/Permission;"; + let sig = String::from("(Lorg/bukkit/permissions/PermissionAttachment;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(perm.into().jni_object().clone()) + jni::objects::JObject::from_raw(attachment.into().jni_object().clone()) }); - args.push(val_1); - sig += ")V"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "unsetPermission", sig.as_str(), args); + let res = self.jni_ref().call_method( + &self.jni_object(), + "attachmentRemoved", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - /// Removes this attachment from its registered {@link Permissible} - pub fn remove(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; diff --git a/blackboxmc-rs-bukkit/src/plugin/java/mod.rs b/blackboxmc-rs-bukkit/src/plugin/java/mod.rs index a07bd26..885770d 100644 --- a/blackboxmc-rs-bukkit/src/plugin/java/mod.rs +++ b/blackboxmc-rs-bukkit/src/plugin/java/mod.rs @@ -3,6 +3,128 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] +pub struct JavaPluginLoader<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for JavaPluginLoader<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for JavaPluginLoader<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate JavaPluginLoader from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/plugin/java/JavaPluginLoader")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a JavaPluginLoader object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> JavaPluginLoader<'mc> { + #[deprecated] + /// This class was not meant to be constructed explicitly + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + instance: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/Server;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(instance.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/plugin/java/PluginLoader"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error_no_gen(res)?; + crate::plugin::java::JavaPluginLoader::from_raw(&jni, res) + } + + pub fn plugin_file_filters( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/regex/Pattern;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPluginFileFilters", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::regex::JavaPattern::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn enable_plugin( + &self, + plugin: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "enablePlugin", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn disable_plugin( + &self, + plugin: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "disablePlugin", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for JavaPluginLoader<'mc> { + fn into(self) -> crate::plugin::PluginLoader<'mc> { + crate::plugin::PluginLoader::from_raw(&self.jni_ref(), self.1) + .expect("Error converting JavaPluginLoader into crate::plugin::PluginLoader") + } +} +#[repr(C)] pub struct JavaPlugin<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, @@ -509,125 +631,3 @@ impl<'mc> Into> for JavaPlugin<'mc> { .expect("Error converting JavaPlugin into crate::plugin::PluginBase") } } -#[repr(C)] -pub struct JavaPluginLoader<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for JavaPluginLoader<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for JavaPluginLoader<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate JavaPluginLoader from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/plugin/java/JavaPluginLoader")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a JavaPluginLoader object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> JavaPluginLoader<'mc> { - #[deprecated] - /// This class was not meant to be constructed explicitly - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - instance: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/Server;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(instance.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/plugin/java/PluginLoader"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error_no_gen(res)?; - crate::plugin::java::JavaPluginLoader::from_raw(&jni, res) - } - - pub fn plugin_file_filters( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/regex/Pattern;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPluginFileFilters", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::regex::JavaPattern::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn enable_plugin( - &self, - plugin: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "enablePlugin", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn disable_plugin( - &self, - plugin: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "disablePlugin", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for JavaPluginLoader<'mc> { - fn into(self) -> crate::plugin::PluginLoader<'mc> { - crate::plugin::PluginLoader::from_raw(&self.jni_ref(), self.1) - .expect("Error converting JavaPluginLoader into crate::plugin::PluginLoader") - } -} diff --git a/blackboxmc-rs-bukkit/src/plugin/messaging/mod.rs b/blackboxmc-rs-bukkit/src/plugin/messaging/mod.rs index 5fdcbbc..07b5fd9 100644 --- a/blackboxmc-rs-bukkit/src/plugin/messaging/mod.rs +++ b/blackboxmc-rs-bukkit/src/plugin/messaging/mod.rs @@ -3,102 +3,6 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] -pub struct PluginMessageRecipient<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PluginMessageRecipient<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PluginMessageRecipient<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PluginMessageRecipient from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/plugin/messaging/PluginMessageRecipient")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PluginMessageRecipient object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> PluginMessageRecipient<'mc> { - /// Sends this recipient a Plugin Message on the specified outgoing - /// channel. - /// - /// The message may not be larger than {@link Messenger#MAX_MESSAGE_SIZE} - /// bytes, and the plugin must be registered to send messages on the - /// specified channel. - pub fn send_plugin_message( - &self, - source: impl Into>, - channel: impl Into, - message: i8, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;Ljava/lang/String;B)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(source.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(channel.into())?, - )); - let val_3 = jni::objects::JValueGen::Byte(message); - let res = self.jni_ref().call_method( - &self.jni_object(), - "sendPluginMessage", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets a set containing all the Plugin Channels that this client is - /// listening on. - pub fn listening_plugin_channels( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getListeningPluginChannels", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] pub struct StandardMessenger<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, @@ -559,6 +463,260 @@ impl<'mc> Into> for StandardMessenger<' } } #[repr(C)] +pub struct PluginMessageListenerRegistration<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PluginMessageListenerRegistration<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PluginMessageListenerRegistration<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate PluginMessageListenerRegistration from null object." + ) + .into()); + } + let (valid, name) = env.validate_name( + &obj, + "org/bukkit/plugin/messaging/PluginMessageListenerRegistration", + )?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PluginMessageListenerRegistration object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> PluginMessageListenerRegistration<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + messenger: impl Into>, + plugin: impl Into>, + channel: impl Into, + listener: impl Into>, + ) -> Result< + crate::plugin::messaging::PluginMessageListenerRegistration<'mc>, + Box, + > { + let sig = String::from("(Lorg/bukkit/plugin/messaging/Messenger;Lorg/bukkit/plugin/Plugin;Ljava/lang/String;Lorg/bukkit/plugin/messaging/PluginMessageListener;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(messenger.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(channel.into())?, + )); + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(listener.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/plugin/messaging/PluginMessageListenerRegistration"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::plugin::messaging::PluginMessageListenerRegistration::from_raw(&jni, res) + } + /// Gets the plugin channel that this registration is about. + pub fn channel(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getChannel", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gets the registered listener described by this registration. + pub fn listener( + &self, + ) -> Result, Box> + { + let sig = String::from("()Lorg/bukkit/plugin/messaging/PluginMessageListener;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getListener", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::plugin::messaging::PluginMessageListener::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the plugin that this registration is for. + pub fn plugin(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/plugin/Plugin;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPlugin", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::plugin::Plugin::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Checks if this registration is still valid. + pub fn is_valid(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn equals( + &self, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(Ljava/lang/Object;)Z"); + let val_1 = jni::objects::JValueGen::Object(obj); + let res = self.jni_ref().call_method( + &self.jni_object(), + "equals", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn hash_code(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct PluginMessageRecipient<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PluginMessageRecipient<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PluginMessageRecipient<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate PluginMessageRecipient from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/plugin/messaging/PluginMessageRecipient")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PluginMessageRecipient object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> PluginMessageRecipient<'mc> { + /// Sends this recipient a Plugin Message on the specified outgoing + /// channel. + /// + /// The message may not be larger than {@link Messenger#MAX_MESSAGE_SIZE} + /// bytes, and the plugin must be registered to send messages on the + /// specified channel. + pub fn send_plugin_message( + &self, + source: impl Into>, + channel: impl Into, + message: i8, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;Ljava/lang/String;B)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(source.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + self.jni_ref().new_string(channel.into())?, + )); + let val_3 = jni::objects::JValueGen::Byte(message); + let res = self.jni_ref().call_method( + &self.jni_object(), + "sendPluginMessage", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets a set containing all the Plugin Channels that this client is + /// listening on. + pub fn listening_plugin_channels( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getListeningPluginChannels", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] pub struct PluginMessageListener<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, @@ -1148,168 +1306,29 @@ impl<'mc> ChannelNameTooLongException<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -#[repr(C)] -pub struct PluginMessageListenerRegistration<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PluginMessageListenerRegistration<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } +pub enum PluginChannelDirection<'mc> { + Incoming { + inner: PluginChannelDirectionStruct<'mc>, + }, + Outgoing { + inner: PluginChannelDirectionStruct<'mc>, + }, } -impl<'mc> JNIInstantiatable<'mc> for PluginMessageListenerRegistration<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PluginMessageListenerRegistration from null object." - ) - .into()); - } - let (valid, name) = env.validate_name( - &obj, - "org/bukkit/plugin/messaging/PluginMessageListenerRegistration", - )?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PluginMessageListenerRegistration object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) +impl<'mc> std::fmt::Display for PluginChannelDirection<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PluginChannelDirection::Incoming { .. } => f.write_str("INCOMING"), + PluginChannelDirection::Outgoing { .. } => f.write_str("OUTGOING"), } } } - -impl<'mc> PluginMessageListenerRegistration<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - messenger: impl Into>, - plugin: impl Into>, - channel: impl Into, - listener: impl Into>, - ) -> Result< - crate::plugin::messaging::PluginMessageListenerRegistration<'mc>, - Box, - > { - let sig = String::from("(Lorg/bukkit/plugin/messaging/Messenger;Lorg/bukkit/plugin/Plugin;Ljava/lang/String;Lorg/bukkit/plugin/messaging/PluginMessageListener;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(messenger.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(channel.into())?, - )); - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(listener.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/plugin/messaging/PluginMessageListenerRegistration"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - ], - ); - let res = jni.translate_error_no_gen(res)?; - crate::plugin::messaging::PluginMessageListenerRegistration::from_raw(&jni, res) - } - /// Gets the plugin channel that this registration is about. - pub fn channel(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getChannel", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Gets the registered listener described by this registration. - pub fn listener( - &self, - ) -> Result, Box> - { - let sig = String::from("()Lorg/bukkit/plugin/messaging/PluginMessageListener;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getListener", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::plugin::messaging::PluginMessageListener::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the plugin that this registration is for. - pub fn plugin(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/plugin/Plugin;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPlugin", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::plugin::Plugin::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Checks if this registration is still valid. - pub fn is_valid(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isValid", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn equals( - &self, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - let sig = String::from("(Ljava/lang/Object;)Z"); - let val_1 = jni::objects::JValueGen::Object(obj); - let res = self.jni_ref().call_method( - &self.jni_object(), - "equals", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn hash_code(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -pub enum PluginChannelDirection<'mc> {} -impl<'mc> std::fmt::Display for PluginChannelDirection<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} +impl<'mc> std::ops::Deref for PluginChannelDirection<'mc> { + type Target = PluginChannelDirectionStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + PluginChannelDirection::Incoming { inner } => inner, + PluginChannelDirection::Outgoing { inner } => inner, + } } } @@ -1336,6 +1355,13 @@ impl<'mc> PluginChannelDirection<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "INCOMING" => Ok(PluginChannelDirection::Incoming { + inner: PluginChannelDirectionStruct::from_raw(env, obj)?, + }), + "OUTGOING" => Ok(PluginChannelDirection::Outgoing { + inner: PluginChannelDirectionStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -1349,10 +1375,16 @@ pub struct PluginChannelDirectionStruct<'mc>( impl<'mc> JNIRaw<'mc> for PluginChannelDirection<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Incoming { inner } => inner.0.clone(), + Self::Outgoing { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Incoming { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Outgoing { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for PluginChannelDirection<'mc> { @@ -1382,6 +1414,12 @@ impl<'mc> JNIInstantiatable<'mc> for PluginChannelDirection<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "INCOMING" => Ok(PluginChannelDirection::Incoming { + inner: PluginChannelDirectionStruct::from_raw(env, obj)?, + }), + "OUTGOING" => Ok(PluginChannelDirection::Outgoing { + inner: PluginChannelDirectionStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } diff --git a/blackboxmc-rs-bukkit/src/plugin/mod.rs b/blackboxmc-rs-bukkit/src/plugin/mod.rs index d7bdd0b..b3d272c 100644 --- a/blackboxmc-rs-bukkit/src/plugin/mod.rs +++ b/blackboxmc-rs-bukkit/src/plugin/mod.rs @@ -3,12 +3,12 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] -pub struct EventExecutor<'mc>( +pub struct TimedRegisteredListener<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EventExecutor<'mc> { +impl<'mc> JNIRaw<'mc> for TimedRegisteredListener<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -16,18 +16,21 @@ impl<'mc> JNIRaw<'mc> for EventExecutor<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EventExecutor<'mc> { +impl<'mc> JNIInstantiatable<'mc> for TimedRegisteredListener<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate EventExecutor from null object.").into()); + return Err(eyre::eyre!( + "Tried to instantiate TimedRegisteredListener from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/plugin/EventExecutor")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/plugin/TimedRegisteredListener")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EventExecutor object, got {}", + "Invalid argument passed. Expected a TimedRegisteredListener object, got {}", name ) .into()) @@ -37,89 +40,175 @@ impl<'mc> JNIInstantiatable<'mc> for EventExecutor<'mc> { } } -impl<'mc> EventExecutor<'mc> { - pub fn execute( - &self, - listener: impl Into>, - event: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/Listener;Lorg/bukkit/event/Event;)V"); +impl<'mc> TimedRegisteredListener<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + plugin_listener: impl Into>, + event_executor: impl Into>, + event_priority: impl Into>, + registered_plugin: impl Into>, + listen_cancelled: bool, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/event/Listener;Lorg/bukkit/plugin/EventExecutor;Lorg/bukkit/event/EventPriority;Lorg/bukkit/plugin/Plugin;Z)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(listener.into().jni_object().clone()) + jni::objects::JObject::from_raw(plugin_listener.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(event.into().jni_object().clone()) + jni::objects::JObject::from_raw(event_executor.into().jni_object().clone()) }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "execute", + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(event_priority.into().jni_object().clone()) + }); + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(registered_plugin.into().jni_object().clone()) + }); + let val_5 = jni::objects::JValueGen::Bool(listen_cancelled.into()); + let cls = jni.find_class("org/bukkit/plugin/TimedRegisteredListener"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + jni::objects::JValueGen::from(val_5), ], ); + let res = jni.translate_error_no_gen(res)?; + crate::plugin::TimedRegisteredListener::from_raw(&jni, res) + } + + pub fn call_event( + &self, + event: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/event/Event;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(event.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "callEvent", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); self.jni_ref().translate_error(res)?; Ok(()) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) + /// Resets the call count and total time for this listener + pub fn reset(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "reset", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) } -} -#[repr(C)] -pub struct InvalidDescriptionException<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for InvalidDescriptionException<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Gets the total times this listener has been called + pub fn count(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCount", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets the total time calls to this listener have taken + pub fn total_time(&self) -> Result> { + let sig = String::from("()J"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTotalTime", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.j()?) } -} -impl<'mc> JNIInstantiatable<'mc> for InvalidDescriptionException<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate InvalidDescriptionException from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/plugin/InvalidDescriptionException")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a InvalidDescriptionException object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + /// Gets the class of the events this listener handled. If it handled + /// multiple classes of event, the closest shared superclass will be + /// returned, such that for any event this listener has handled, + /// this.getEventClass().isAssignableFrom(event.getClass()) + /// and no class this.getEventClass().isAssignableFrom(clazz) + /// {@literal && this.getEventClass() != clazz &&} + /// event.getClass().isAssignableFrom(clazz) for all handled events. + pub fn event_class( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/lang/Class;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getEventClass", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); } + Ok(Some(unsafe { + jni::objects::JClass::from_raw(res.as_jni().l) + })) + } + /// Gets whether this listener has handled multiple events, such that for + /// some two events, eventA.getClass() != eventB.getClass(). + pub fn has_multiple(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "hasMultiple", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + // SUPER CLASS: org.bukkit.plugin.RegisteredListener ( ['callEvent', 'reset', 'getCount', 'getTotalTime', 'getEventClass', 'hasMultiple']) + /// Gets the listener for this registration + pub fn listener(&self) -> Result, Box> { + let temp_clone = crate::plugin::RegisteredListener::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::plugin::RegisteredListener = temp_clone.into(); + real.listener() + } + /// Gets the plugin for this registration + pub fn plugin(&self) -> Result, Box> { + let temp_clone = crate::plugin::RegisteredListener::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::plugin::RegisteredListener = temp_clone.into(); + real.plugin() + } + /// Gets the priority for this registration + pub fn priority(&self) -> Result, Box> { + let temp_clone = crate::plugin::RegisteredListener::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::plugin::RegisteredListener = temp_clone.into(); + real.priority() + } + /// Whether this listener accepts cancelled events + pub fn is_ignoring_cancelled(&self) -> Result> { + let temp_clone = crate::plugin::RegisteredListener::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::plugin::RegisteredListener = temp_clone.into(); + real.is_ignoring_cancelled() } -} -impl<'mc> InvalidDescriptionException<'mc> { pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for TimedRegisteredListener<'mc> { + fn into(self) -> crate::plugin::RegisteredListener<'mc> { + crate::plugin::RegisteredListener::from_raw(&self.jni_ref(), self.1).expect( + "Error converting TimedRegisteredListener into crate::plugin::RegisteredListener", + ) + } +} #[repr(C)] -pub struct PluginDescriptionFile<'mc>( +pub struct RegisteredServiceProvider<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PluginDescriptionFile<'mc> { +impl<'mc> JNIRaw<'mc> for RegisteredServiceProvider<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -127,21 +216,22 @@ impl<'mc> JNIRaw<'mc> for PluginDescriptionFile<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PluginDescriptionFile<'mc> { +impl<'mc> JNIInstantiatable<'mc> for RegisteredServiceProvider<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate PluginDescriptionFile from null object." + "Tried to instantiate RegisteredServiceProvider from null object." ) .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/plugin/PluginDescriptionFile")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/plugin/RegisteredServiceProvider")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PluginDescriptionFile object, got {}", + "Invalid argument passed. Expected a RegisteredServiceProvider object, got {}", name ) .into()) @@ -151,440 +241,385 @@ impl<'mc> JNIInstantiatable<'mc> for PluginDescriptionFile<'mc> { } } -impl<'mc> PluginDescriptionFile<'mc> { - /// Creates a new PluginDescriptionFile with the given detailed +impl<'mc> RegisteredServiceProvider<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - plugin_name: impl Into, - plugin_version: std::option::Option>, - main_class: std::option::Option>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(plugin_name.into())?, - )); - args.push(val_1); - if let Some(a) = plugin_version { - sig += "Ljava/lang/String;"; - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(a.into())?, - )); - args.push(val_2); - } - if let Some(a) = main_class { - sig += "Ljava/lang/String;"; - let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(a.into())?, - )); - args.push(val_3); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/plugin/PluginDescriptionFile"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::plugin::PluginDescriptionFile::from_raw(&jni, res) - } - /// Gives the name of the plugin. This name is a unique identifier for - /// plugins. - ///
      - ///
    • Must consist of all alphanumeric characters, underscores, hyphon, - /// and period (a-z,A-Z,0-9, _.-). Any other character will cause the - /// plugin.yml to fail loading. - ///
    • Used to determine the name of the plugin's data folder. Data - /// folders are placed in the ./plugins/ directory by default, but this - /// behavior should not be relied on. {@link Plugin#getDataFolder()} - /// should be used to reference the data folder. - ///
    • It is good practice to name your jar the same as this, for example - /// 'MyPlugin.jar'. - ///
    • Case sensitive. - ///
    • The is the token referenced in {@link #getDepend()}, {@link - /// #getSoftDepend()}, and {@link #getLoadBefore()}. - ///
    • Using spaces in the plugin's name is deprecated. - ///
    - /// - /// In the plugin.yml, this entry is named name. - /// - /// Example:
    name: MyPlugin
    - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Gives the list of other plugin APIs which this plugin provides. - /// These are usable for other plugins to depend on. - ///
      - ///
    • Must consist of all alphanumeric characters, underscores, hyphon, - /// and period (a-z,A-Z,0-9, _.-). Any other character will cause the - /// plugin.yml to fail loading. - ///
    • A different plugin providing the same one or using it as their name - /// will not result in the plugin to fail loading. - ///
    • Case sensitive. - ///
    • An entry of this list can be referenced in {@link #getDepend()}, - /// {@link #getSoftDepend()}, and {@link #getLoadBefore()}. - ///
    • provides must be in YAML list - /// format. - ///
    - /// - /// In the plugin.yml, this entry is named provides. - /// - /// Example: - ///
    provides:
    -    /// - OtherPluginName
    -    /// - OldPluginName
    - pub fn provides(&self) -> Result, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getProvides", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), - ); - } - Ok(new_vec) + service: jni::objects::JClass<'mc>, + provider: jni::objects::JObject<'mc>, + priority: impl Into>, + plugin: impl Into>, + ) -> Result, Box> { + let sig = String::from( + "(Ljava/lang/Class;LT;Lorg/bukkit/plugin/ServicePriority;Lorg/bukkit/plugin/Plugin;)V", + ); + let val_1 = jni::objects::JValueGen::Object(service.into()); + let val_2 = jni::objects::JValueGen::Object(provider); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(priority.into().jni_object().clone()) + }); + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/plugin/RegisteredServiceProvider"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::plugin::RegisteredServiceProvider::from_raw(&jni, res) } - /// Gives the version of the plugin. - ///
      - ///
    • Version is an arbitrary string, however the most common format is - /// MajorRelease.MinorRelease.Build (eg: 1.4.1). - ///
    • Typically you will increment this every time you release a new - /// feature or bug fix. - ///
    • Displayed when a user types /version PluginName - ///
    - /// - /// In the plugin.yml, this entry is named version. - /// - /// Example:
    version: 1.4.1
    - pub fn version(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + + pub fn service(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/Class;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getVersion", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getService", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(unsafe { jni::objects::JClass::from_raw(res.as_jni().l) }) } - /// Gives the fully qualified name of the main class for a plugin. The - /// format should follow the {@link ClassLoader#loadClass(String)} syntax - /// to successfully be resolved at runtime. For most plugins, this is the - /// class that extends {@link JavaPlugin}. - ///
      - ///
    • This must contain the full namespace including the class file - /// itself. - ///
    • If your namespace is org.bukkit.plugin, and your class - /// file is called MyPlugin then this must be - /// org.bukkit.plugin.MyPlugin - ///
    • No plugin can use org.bukkit. as a base package for - /// any class, including the main class. - ///
    - /// - /// In the plugin.yml, this entry is named main. - /// - /// Example: - ///
    main: org.bukkit.plugin.MyPlugin
    - pub fn main(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + + pub fn plugin(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/plugin/Plugin;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getMain", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPlugin", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + crate::plugin::Plugin::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gives a human-friendly description of the functionality the plugin - /// provides. - ///
      - ///
    • The description can have multiple lines. - ///
    • Displayed when a user types /version PluginName - ///
    - /// - /// In the plugin.yml, this entry is named description. - /// - /// Example: - ///
    description: This plugin is so 31337. You can set yourself on fire.
    - pub fn description(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); + + pub fn provider(&self) -> Result, Box> { + let sig = String::from("()LT;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getDescription", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getProvider", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(res.l()?) } - /// Gives the phase of server startup that the plugin should be loaded. - ///
      - ///
    • Possible values are in {@link PluginLoadOrder}. - ///
    • Defaults to {@link PluginLoadOrder#POSTWORLD}. - ///
    • Certain caveats apply to each phase. - ///
    • When different, {@link #getDepend()}, {@link #getSoftDepend()}, and - /// {@link #getLoadBefore()} become relative in order loaded per-phase. - /// If a plugin loads at STARTUP, but a dependency loads - /// at POSTWORLD, the dependency will not be loaded before - /// the plugin is loaded. - ///
    - /// - /// In the plugin.yml, this entry is named load. - /// - /// Example:
    load: STARTUP
    - pub fn load(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/plugin/PluginLoadOrder;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getLoad", sig.as_str(), vec![]); + + pub fn priority( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/plugin/ServicePriority;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPriority", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::plugin::PluginLoadOrder::from_raw(&self.jni_ref(), unsafe { + crate::plugin::ServicePriority::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gives the list of authors for the plugin. - ///
      - ///
    • Gives credit to the developer. - ///
    • Used in some server error messages to provide helpful feedback on - /// who to contact when an error occurs. - ///
    • A SpigotMC forum handle or email address is recommended. - ///
    • Is displayed when a user types /version PluginName - ///
    • authors must be in YAML list - /// format. - ///
    - /// - /// In the plugin.yml, this has two entries, author and - /// authors. - /// - /// Single author example: - ///
    author: CaptainInflamo
    - /// Multiple author example: - ///
    authors: [Cogito, verrier, EvilSeph]
    - /// When both are specified, author will be the first entry in the list, so - /// this example: - ///
    author: Grum
    -    /// authors:
    -    /// - feildmaster
    -    /// - amaranth
    - /// Is equivilant to this example: - ///
    authors: [Grum, feildmaster, aramanth]
    - pub fn authors(&self) -> Result, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAuthors", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), - ); - } - Ok(new_vec) - } - /// Gives the list of contributors for the plugin. - ///
      - ///
    • Gives credit to those that have contributed to the plugin, though - /// not enough so to warrant authorship. - ///
    • Unlike {@link #getAuthors()}, contributors will not be mentioned in - /// server error messages as a means of contact. - ///
    • A SpigotMC forum handle or email address is recommended. - ///
    • Is displayed when a user types /version PluginName - ///
    • contributors must be in YAML list - /// format. - ///
    - /// - /// Example: - ///
    authors: [Choco, md_5]
    - pub fn contributors(&self) -> Result, Box> { - let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getContributors", sig.as_str(), vec![]); + + pub fn compare_to( + &self, + other: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/plugin/RegisteredServiceProvider;)I"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(other.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "compareTo", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), + Ok(res.i()?) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct RegisteredListener<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for RegisteredListener<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for RegisteredListener<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate RegisteredListener from null object.").into(), ); } - Ok(new_vec) + let (valid, name) = env.validate_name(&obj, "org/bukkit/plugin/RegisteredListener")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a RegisteredListener object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } - /// Gives the plugin's or plugin's author's website. - ///
      - ///
    • A link to the Curse page that includes documentation and downloads - /// is highly recommended. - ///
    • Displayed when a user types /version PluginName - ///
    - /// - /// In the plugin.yml, this entry is named website. - /// - /// Example: - ///
    website: http://www.curse.com/server-mods/minecraft/myplugin
    - pub fn website(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); +} + +impl<'mc> RegisteredListener<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + listener: impl Into>, + executor: impl Into>, + priority: impl Into>, + plugin: impl Into>, + ignore_cancelled: bool, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/event/Listener;Lorg/bukkit/plugin/EventExecutor;Lorg/bukkit/event/EventPriority;Lorg/bukkit/plugin/Plugin;Z)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(listener.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(executor.into().jni_object().clone()) + }); + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(priority.into().jni_object().clone()) + }); + let val_4 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); + let val_5 = jni::objects::JValueGen::Bool(ignore_cancelled.into()); + let cls = jni.find_class("org/bukkit/plugin/RegisteredListener"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + jni::objects::JValueGen::from(val_5), + ], + ); + let res = jni.translate_error_no_gen(res)?; + crate::plugin::RegisteredListener::from_raw(&jni, res) + } + /// Gets the listener for this registration + pub fn listener(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/Listener;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getWebsite", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getListener", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + crate::event::Listener::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gives a list of other plugins that the plugin requires. - ///
      - ///
    • Use the value in the {@link #getName()} of the target plugin to - /// specify the dependency. - ///
    • If any plugin listed here is not found, your plugin will fail to - /// load at startup. - ///
    • If multiple plugins list each other in depend, - /// creating a network with no individual plugin does not list another - /// plugin in the network, - /// all plugins in that network will fail. - ///
    • depend must be in YAML list - /// format. - ///
    - /// - /// In the plugin.yml, this entry is named depend. - /// - /// Example: - ///
    depend:
    -    /// - OnePlugin
    -    /// - AnotherPlugin
    - pub fn depend(&self) -> Result, Box> { - let sig = String::from("()Ljava/util/List;"); + /// Gets the plugin for this registration + pub fn plugin(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/plugin/Plugin;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getDepend", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPlugin", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), - ); - } - Ok(new_vec) + crate::plugin::Plugin::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gives a list of other plugins that the plugin requires for full - /// functionality. The {@link PluginManager} will make best effort to treat - /// all entries here as if they were a {@link #getDepend() dependency}, but - /// will never fail because of one of these entries. - ///
      - ///
    • Use the value in the {@link #getName()} of the target plugin to - /// specify the dependency. - ///
    • When an unresolvable plugin is listed, it will be ignored and does - /// not affect load order. - ///
    • When a circular dependency occurs (a network of plugins depending - /// or soft-dependending each other), it will arbitrarily choose a - /// plugin that can be resolved when ignoring soft-dependencies. - ///
    • softdepend must be in YAML list - /// format. - ///
    - /// - /// In the plugin.yml, this entry is named softdepend. - /// - /// Example: - ///
    softdepend: [OnePlugin, AnotherPlugin]
    - pub fn soft_depend(&self) -> Result, Box> { - let sig = String::from("()Ljava/util/List;"); + /// Gets the priority for this registration + pub fn priority(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/event/EventPriority;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getSoftDepend", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getPriority", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), - ); - } - Ok(new_vec) + crate::event::EventPriority::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the list of plugins that should consider this plugin a - /// soft-dependency. + /// Calls the event executor + pub fn call_event( + &self, + event: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/event/Event;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(event.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "callEvent", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Whether this listener accepts cancelled events + pub fn is_ignoring_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isIgnoringCancelled", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct PluginDescriptionFile<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PluginDescriptionFile<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PluginDescriptionFile<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate PluginDescriptionFile from null object." + ) + .into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/plugin/PluginDescriptionFile")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PluginDescriptionFile object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> PluginDescriptionFile<'mc> { + /// Creates a new PluginDescriptionFile with the given detailed + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + plugin_name: impl Into, + plugin_version: std::option::Option>, + main_class: std::option::Option>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(plugin_name.into())?, + )); + args.push(val_1); + if let Some(a) = plugin_version { + sig += "Ljava/lang/String;"; + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(a.into())?, + )); + args.push(val_2); + } + if let Some(a) = main_class { + sig += "Ljava/lang/String;"; + let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(a.into())?, + )); + args.push(val_3); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/plugin/PluginDescriptionFile"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::plugin::PluginDescriptionFile::from_raw(&jni, res) + } + /// Gives the name of the plugin. This name is a unique identifier for + /// plugins. /// + /// + /// In the plugin.yml, this entry is named name. + /// + /// Example:
    name: MyPlugin
    + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gives the list of other plugin APIs which this plugin provides. + /// These are usable for other plugins to depend on. + ///
    /// - /// In the plugin.yml, this entry is named loadbefore. + /// In the plugin.yml, this entry is named provides. /// /// Example: - ///
    loadbefore:
    -    /// - OnePlugin
    -    /// - AnotherPlugin
    - pub fn load_before(&self) -> Result, Box> { + ///
    provides:
    +    /// - OtherPluginName
    +    /// - OldPluginName
    + pub fn provides(&self) -> Result, Box> { let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getLoadBefore", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getProvides", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; @@ -600,22 +635,76 @@ impl<'mc> PluginDescriptionFile<'mc> { } Ok(new_vec) } - /// Gives the token to prefix plugin-specific logging messages with. + /// Gives the version of the plugin. ///
      - ///
    • This includes all messages using {@link Plugin#getLogger()}. - ///
    • If not specified, the server uses the plugin's {@link #getName() - /// name}. - ///
    • This should clearly indicate what plugin is being logged. + ///
    • Version is an arbitrary string, however the most common format is + /// MajorRelease.MinorRelease.Build (eg: 1.4.1). + ///
    • Typically you will increment this every time you release a new + /// feature or bug fix. + ///
    • Displayed when a user types /version PluginName ///
    /// - /// In the plugin.yml, this entry is named prefix. + /// In the plugin.yml, this entry is named version. /// - /// Example:
    prefix: ex-why-zee
    - pub fn prefix(&self) -> Result, Box> { + /// Example:
    version: 1.4.1
    + pub fn version(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getVersion", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gives the fully qualified name of the main class for a plugin. The + /// format should follow the {@link ClassLoader#loadClass(String)} syntax + /// to successfully be resolved at runtime. For most plugins, this is the + /// class that extends {@link JavaPlugin}. + ///
      + ///
    • This must contain the full namespace including the class file + /// itself. + ///
    • If your namespace is org.bukkit.plugin, and your class + /// file is called MyPlugin then this must be + /// org.bukkit.plugin.MyPlugin + ///
    • No plugin can use org.bukkit. as a base package for + /// any class, including the main class. + ///
    + /// + /// In the plugin.yml, this entry is named main. + /// + /// Example: + ///
    main: org.bukkit.plugin.MyPlugin
    + pub fn main(&self) -> Result> { let sig = String::from("()Ljava/lang/String;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getPrefix", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMain", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gives a human-friendly description of the functionality the plugin + /// provides. + ///
      + ///
    • The description can have multiple lines. + ///
    • Displayed when a user types /version PluginName + ///
    + /// + /// In the plugin.yml, this entry is named description. + /// + /// Example: + ///
    description: This plugin is so 31337. You can set yourself on fire.
    + pub fn description(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getDescription", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); @@ -627,348 +716,129 @@ impl<'mc> PluginDescriptionFile<'mc> { .to_string(), )) } - /// Gives the map of command-name to command-properties. Each entry in this - /// map corresponds to a single command and the respective values are the - /// properties of the command. Each property, with the exception of - /// aliases, can be defined at runtime using methods in {@link - /// PluginCommand} and are defined here only as a convenience. - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - ///
    The command section's description
    NodeMethodTypeDescriptionExample
    description{@link PluginCommand#setDescription(String)}StringA user-friendly description for a command. It is useful for - /// documentation purposes as well as in-game help.
    description: Set yourself on fire
    aliases{@link PluginCommand#setAliases(List)}String or List of - /// stringsAlternative command names, with special usefulness for commands - /// that are already registered. Aliases are not effective when - /// defined at runtime, so the plugin description file is the - /// only way to have them properly defined. + /// Gives the phase of server startup that the plugin should be loaded. + ///
      + ///
    • Possible values are in {@link PluginLoadOrder}. + ///
    • Defaults to {@link PluginLoadOrder#POSTWORLD}. + ///
    • Certain caveats apply to each phase. + ///
    • When different, {@link #getDepend()}, {@link #getSoftDepend()}, and + /// {@link #getLoadBefore()} become relative in order loaded per-phase. + /// If a plugin loads at STARTUP, but a dependency loads + /// at POSTWORLD, the dependency will not be loaded before + /// the plugin is loaded. + ///
    /// - /// Note: Command aliases may not have a colon in them.
    Single alias format: - ///
    aliases: combust_me
    or - /// multiple alias format: - ///
    aliases: [combust_me, combustMe]
    permission{@link PluginCommand#setPermission(String)}StringThe name of the {@link Permission} required to use the command. - /// A user without the permission will receive the specified - /// message (see {@linkplain - /// PluginCommand#setPermissionMessage(String) below}), or a - /// standard one if no specific message is defined. Without the - /// permission node, no {@link - /// PluginCommand#setExecutor(CommandExecutor) CommandExecutor} or - /// {@link PluginCommand#setTabCompleter(TabCompleter)} will be called.
    permission: inferno.flagrate
    permission-message{@link PluginCommand#setPermissionMessage(String)}String
      - ///
    • Displayed to a player that attempts to use a command, but - /// does not have the required permission. See {@link - /// PluginCommand#getPermission() above}. - ///
    • <permission> is a macro that is replaced with the - /// permission node required to use the command. - ///
    • Using empty quotes is a valid way to indicate nothing - /// should be displayed to a player. - ///
    permission-message: You do not have /<permission>
    usage{@link PluginCommand#setUsage(String)}StringThis message is displayed to a player when the {@link - /// PluginCommand#setExecutor(CommandExecutor)} {@linkplain - /// CommandExecutor#onCommand(CommandSender, Command, String, String[]) returns false}. - /// <command> is a macro that is replaced the command issued.
    usage: Syntax error! Perhaps you meant /<command> PlayerName?
    - /// It is worth noting that to use a colon in a yaml, like - /// `usage: Usage: /god [player]', you need to - /// surround - /// the message with double-quote: - ///
    usage: "Usage: /god [player]"
    - /// The commands are structured as a hiearchy of nested mappings. - /// The primary (top-level, no intendentation) node is - /// `commands', while each individual command name is - /// indented, indicating it maps to some value (in our case, the - /// properties of the table above). + /// In the plugin.yml, this entry is named load. /// - /// Here is an example bringing together the piecemeal examples above, as - /// well as few more definitions:
    -    /// commands:
    -    /// flagrate:
    -    /// description: Set yourself on fire.
    -    /// aliases: [combust_me, combustMe]
    -    /// permission: inferno.flagrate
    -    /// permission-message: You do not have /<permission>
    -    /// usage: Syntax error! Perhaps you meant /<command> PlayerName?
    -    /// burningdeaths:
    -    /// description: List how many times you have died by fire.
    -    /// aliases:
    -    /// - burning_deaths
    -    /// - burningDeaths
    -    /// permission: inferno.burningdeaths
    -    /// usage: |
    -    /// /<command> [player]
    -    /// Example: /<command> - see how many times you have burned to death
    -    /// Example: /<command> CaptainIce - see how many times CaptainIce has burned to death
    -    /// # The next command has no description, aliases, etc. defined, but is still valid
    -    /// # Having an empty declaration is useful for defining the description, permission, and messages from a configuration dynamically
    -    /// apocalypse:
    -    /// 
    - /// Note: Command names may not have a colon in their name. - pub fn commands( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Map;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCommands", sig.as_str(), vec![]); + /// Example:
    load: STARTUP
    + pub fn load(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/plugin/PluginLoadOrder;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLoad", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + crate::plugin::PluginLoadOrder::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gives the list of permissions the plugin will register at runtime, - /// immediately proceding enabling. The format for defining permissions is - /// a map from permission name to properties. To represent a map without - /// any specific property, empty curly-braces ( - /// {} ) may be used (as a null value is not - /// accepted, unlike the {@link #getCommands() commands} above). - /// - /// A list of optional properties for permissions: - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - ///
    The permission section's description
    NodeDescriptionExample
    descriptionPlaintext (user-friendly) description of what the permission - /// is for.
    description: Allows you to set yourself on fire
    defaultThe default state for the permission, as defined by {@link - /// Permission#getDefault()}. If not defined, it will be set to - /// the value of {@link PluginDescriptionFile#getPermissionDefault()}. - /// - /// For reference:
      - ///
    • true - Represents a positive assignment to - /// {@link Permissible permissibles}. - ///
    • false - Represents no assignment to {@link - /// Permissible permissibles}. - ///
    • op - Represents a positive assignment to - /// {@link Permissible#isOp() operator permissibles}. - ///
    • notop - Represents a positive assignment to - /// {@link Permissible#isOp() non-operator permissibiles}. - ///
    default: true
    childrenAllows other permissions to be set as a {@linkplain - /// Permission#getChildren() relation} to the parent permission. - /// When a parent permissions is assigned, child permissions are - /// respectively assigned as well. + /// Gives the list of authors for the plugin. ///
      - ///
    • When a parent permission is assigned negatively, child - /// permissions are assigned based on an inversion of their - /// association. - ///
    • When a parent permission is assigned positively, child - /// permissions are assigned based on their association. + ///
    • Gives credit to the developer. + ///
    • Used in some server error messages to provide helpful feedback on + /// who to contact when an error occurs. + ///
    • A SpigotMC forum handle or email address is recommended. + ///
    • Is displayed when a user types /version PluginName + ///
    • authors must be in YAML list + /// format. ///
    /// - /// Child permissions may be defined in a number of ways:
      - ///
    • Children may be defined as a list of - /// names. Using a list will treat all children associated - /// positively to their parent. - ///
    • Children may be defined as a map. Each permission name maps - /// to either a boolean (representing the association), or a - /// nested permission definition (just as another permission). - /// Using a nested definition treats the child as a positive - /// association. - ///
    • A nested permission definition must be a map of these same - /// properties. To define a valid nested permission without - /// defining any specific property, empty curly-braces ( - /// {} ) must be used. - ///
    • A nested permission may carry it's own nested permissions - /// as children, as they may also have nested permissions, and - /// so forth. There is no direct limit to how deep the - /// permission tree is defined. - ///
    As a list: - ///
    children: [inferno.flagrate, inferno.burningdeaths]
    - /// Or as a mapping: - ///
    children:
    -    /// inferno.flagrate: true
    -    /// inferno.burningdeaths: true
    - /// An additional example showing basic nested values can be seen - /// here. - ///
    - /// The permissions are structured as a hiearchy of nested mappings. - /// The primary (top-level, no intendentation) node is - /// `permissions', while each individual permission name is - /// indented, indicating it maps to some value (in our case, the - /// properties of the table above). + /// In the plugin.yml, this has two entries, author and + /// authors. /// - /// Here is an example using some of the properties:
    -    /// permissions:
    -    /// inferno.*:
    -    /// description: Gives access to all Inferno commands
    -    /// children:
    -    /// inferno.flagrate: true
    -    /// inferno.burningdeaths: true
    -    /// inferno.flagate:
    -    /// description: Allows you to ignite yourself
    -    /// default: true
    -    /// inferno.burningdeaths:
    -    /// description: Allows you to see how many times you have burned to death
    -    /// default: true
    -    /// 
    - /// Another example, with nested definitions, can be found here. - pub fn permissions( - &self, - ) -> Result>, Box> { + /// Single author example: + ///
    author: CaptainInflamo
    + /// Multiple author example: + ///
    authors: [Cogito, verrier, EvilSeph]
    + /// When both are specified, author will be the first entry in the list, so + /// this example: + ///
    author: Grum
    +    /// authors:
    +    /// - feildmaster
    +    /// - amaranth
    + /// Is equivilant to this example: + ///
    authors: [Grum, feildmaster, aramanth]
    + pub fn authors(&self) -> Result, Box> { let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getPermissions", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAuthors", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; - new_vec.push(crate::permissions::Permission::from_raw(&self.0, obj)?); - } - Ok(new_vec) - } - /// Gives the default {@link Permission#getDefault() default} state of - /// {@link #getPermissions() permissions} registered for the plugin. - ///
      - ///
    • If not specified, it will be {@link PermissionDefault#OP}. - ///
    • It is matched using {@link PermissionDefault#getByName(String)} - ///
    • It only affects permissions that do not define the - /// default node. - ///
    • It may be any value in {@link PermissionDefault}. - ///
    - /// - /// In the plugin.yml, this entry is named default-permission. - /// - /// Example:
    default-permission: NOT_OP
    - pub fn permission_default( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/permissions/PermissionDefault;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getPermissionDefault", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::permissions::PermissionDefault::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + new_vec.push( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); + } + Ok(new_vec) } - /// Gives a set of every {@link PluginAwareness} for a plugin. An awareness - /// dictates something that a plugin developer acknowledges when the plugin - /// is compiled. Some implementions may define extra awarenesses that are - /// not included in the API. Any unrecognized - /// awareness (one unsupported or in a future version) will cause a dummy - /// object to be created instead of failing. + /// Gives the list of contributors for the plugin. /// /// - /// In the plugin.yml, this entry is named awareness. - /// - /// Example:
    awareness:
    -    /// - !@UTF8
    - /// - /// Note: Although unknown versions of some future awareness are - /// gracefully substituted, previous versions of Bukkit (ones prior to the - /// first implementation of awareness) will fail to load a plugin that - /// defines any awareness. - pub fn awareness( - &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/Set;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getAwareness", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Returns the name of a plugin, including the version. This method is - /// provided for convenience; it uses the {@link #getName()} and {@link - /// #getVersion()} entries. - pub fn full_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Example: + ///
    authors: [Choco, md_5]
    + pub fn contributors(&self) -> Result, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getFullName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getContributors", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); + } + Ok(new_vec) } - /// Gives the API version which this plugin is designed to support. No - /// specific format is guaranteed. + /// Gives the plugin's or plugin's author's website. ///
      - ///
    • Refer to release notes for supported API versions. + ///
    • A link to the Curse page that includes documentation and downloads + /// is highly recommended. + ///
    • Displayed when a user types /version PluginName ///
    /// - /// In the plugin.yml, this entry is named api-version. + /// In the plugin.yml, this entry is named website. /// - /// Example:
    api-version: 1.13
    - pub fn apiversion(&self) -> Result, Box> { + /// Example: + ///
    website: http://www.curse.com/server-mods/minecraft/myplugin
    + pub fn website(&self) -> Result, Box> { let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getAPIVersion", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getWebsite", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); @@ -980,18 +850,33 @@ impl<'mc> PluginDescriptionFile<'mc> { .to_string(), )) } - /// Gets the libraries this plugin requires. This is a preview feature. + /// Gives a list of other plugins that the plugin requires. ///
      - ///
    • Libraries must be GAV specifiers and are loaded from Maven Central. + ///
    • Use the value in the {@link #getName()} of the target plugin to + /// specify the dependency. + ///
    • If any plugin listed here is not found, your plugin will fail to + /// load at startup. + ///
    • If multiple plugins list each other in depend, + /// creating a network with no individual plugin does not list another + /// plugin in the network, + /// all plugins in that network will fail. + ///
    • depend must be in YAML list + /// format. ///
    /// - /// Example:
    libraries:
    -    /// - com.squareup.okhttp3:okhttp:4.9.0
    - pub fn libraries(&self) -> Result, Box> { + /// In the plugin.yml, this entry is named depend. + /// + /// Example: + ///
    depend:
    +    /// - OnePlugin
    +    /// - AnotherPlugin
    + pub fn depend(&self) -> Result, Box> { let sig = String::from("()Ljava/util/List;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLibraries", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getDepend", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; let mut new_vec = Vec::new(); let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; @@ -1007,516 +892,527 @@ impl<'mc> PluginDescriptionFile<'mc> { } Ok(new_vec) } - #[deprecated] - - pub fn class_loader_of(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/String;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getClassLoaderOf", - sig.as_str(), - vec![], - ); + /// Gives a list of other plugins that the plugin requires for full + /// functionality. The {@link PluginManager} will make best effort to treat + /// all entries here as if they were a {@link #getDepend() dependency}, but + /// will never fail because of one of these entries. + ///
      + ///
    • Use the value in the {@link #getName()} of the target plugin to + /// specify the dependency. + ///
    • When an unresolvable plugin is listed, it will be ignored and does + /// not affect load order. + ///
    • When a circular dependency occurs (a network of plugins depending + /// or soft-dependending each other), it will arbitrarily choose a + /// plugin that can be resolved when ignoring soft-dependencies. + ///
    • softdepend must be in YAML list + /// format. + ///
    + /// + /// In the plugin.yml, this entry is named softdepend. + /// + /// Example: + ///
    softdepend: [OnePlugin, AnotherPlugin]
    + pub fn soft_depend(&self) -> Result, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSoftDepend", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); } - Ok(Some( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string(), - )) + Ok(new_vec) } - - pub fn raw_name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + /// Gets the list of plugins that should consider this plugin a + /// soft-dependency. + ///
      + ///
    • Use the value in the {@link #getName()} of the target plugin to + /// specify the dependency. + ///
    • The plugin should load before any other plugins listed here. + ///
    • Specifying another plugin here is strictly equivalent to having the + /// specified plugin's {@link #getSoftDepend()} include {@link + /// #getName() this plugin}. + ///
    • loadbefore must be in YAML list + /// format. + ///
    + /// + /// In the plugin.yml, this entry is named loadbefore. + /// + /// Example: + ///
    loadbefore:
    +    /// - OnePlugin
    +    /// - AnotherPlugin
    + pub fn load_before(&self) -> Result, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getRawName", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLoadBefore", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct UnknownDependencyException<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for UnknownDependencyException<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for UnknownDependencyException<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate UnknownDependencyException from null object." - ) - .into()); - } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/plugin/UnknownDependencyException")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a UnknownDependencyException object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); } + Ok(new_vec) } -} - -impl<'mc> UnknownDependencyException<'mc> { - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct PluginLoader<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PluginLoader<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Gives the token to prefix plugin-specific logging messages with. + ///
      + ///
    • This includes all messages using {@link Plugin#getLogger()}. + ///
    • If not specified, the server uses the plugin's {@link #getName() + /// name}. + ///
    • This should clearly indicate what plugin is being logged. + ///
    + /// + /// In the plugin.yml, this entry is named prefix. + /// + /// Example:
    prefix: ex-why-zee
    + pub fn prefix(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getPrefix", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gives the map of command-name to command-properties. Each entry in this + /// map corresponds to a single command and the respective values are the + /// properties of the command. Each property, with the exception of + /// aliases, can be defined at runtime using methods in {@link + /// PluginCommand} and are defined here only as a convenience. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///
    The command section's description
    NodeMethodTypeDescriptionExample
    description{@link PluginCommand#setDescription(String)}StringA user-friendly description for a command. It is useful for + /// documentation purposes as well as in-game help.
    description: Set yourself on fire
    aliases{@link PluginCommand#setAliases(List)}String or List of + /// stringsAlternative command names, with special usefulness for commands + /// that are already registered. Aliases are not effective when + /// defined at runtime, so the plugin description file is the + /// only way to have them properly defined. + /// + /// Note: Command aliases may not have a colon in them.Single alias format: + ///
    aliases: combust_me
    or + /// multiple alias format: + ///
    aliases: [combust_me, combustMe]
    permission{@link PluginCommand#setPermission(String)}StringThe name of the {@link Permission} required to use the command. + /// A user without the permission will receive the specified + /// message (see {@linkplain + /// PluginCommand#setPermissionMessage(String) below}), or a + /// standard one if no specific message is defined. Without the + /// permission node, no {@link + /// PluginCommand#setExecutor(CommandExecutor) CommandExecutor} or + /// {@link PluginCommand#setTabCompleter(TabCompleter)} will be called.
    permission: inferno.flagrate
    permission-message{@link PluginCommand#setPermissionMessage(String)}String
      + ///
    • Displayed to a player that attempts to use a command, but + /// does not have the required permission. See {@link + /// PluginCommand#getPermission() above}. + ///
    • <permission> is a macro that is replaced with the + /// permission node required to use the command. + ///
    • Using empty quotes is a valid way to indicate nothing + /// should be displayed to a player. + ///
    permission-message: You do not have /<permission>
    usage{@link PluginCommand#setUsage(String)}StringThis message is displayed to a player when the {@link + /// PluginCommand#setExecutor(CommandExecutor)} {@linkplain + /// CommandExecutor#onCommand(CommandSender, Command, String, String[]) returns false}. + /// <command> is a macro that is replaced the command issued.
    usage: Syntax error! Perhaps you meant /<command> PlayerName?
    + /// It is worth noting that to use a colon in a yaml, like + /// `usage: Usage: /god [player]', you need to + /// surround + /// the message with double-quote: + ///
    usage: "Usage: /god [player]"
    + /// The commands are structured as a hiearchy of nested mappings. + /// The primary (top-level, no intendentation) node is + /// `commands', while each individual command name is + /// indented, indicating it maps to some value (in our case, the + /// properties of the table above). + /// + /// Here is an example bringing together the piecemeal examples above, as + /// well as few more definitions:
    +    /// commands:
    +    /// flagrate:
    +    /// description: Set yourself on fire.
    +    /// aliases: [combust_me, combustMe]
    +    /// permission: inferno.flagrate
    +    /// permission-message: You do not have /<permission>
    +    /// usage: Syntax error! Perhaps you meant /<command> PlayerName?
    +    /// burningdeaths:
    +    /// description: List how many times you have died by fire.
    +    /// aliases:
    +    /// - burning_deaths
    +    /// - burningDeaths
    +    /// permission: inferno.burningdeaths
    +    /// usage: |
    +    /// /<command> [player]
    +    /// Example: /<command> - see how many times you have burned to death
    +    /// Example: /<command> CaptainIce - see how many times CaptainIce has burned to death
    +    /// # The next command has no description, aliases, etc. defined, but is still valid
    +    /// # Having an empty declaration is useful for defining the description, permission, and messages from a configuration dynamically
    +    /// apocalypse:
    +    /// 
    + /// Note: Command names may not have a colon in their name. + pub fn commands( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Map;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCommands", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> JNIInstantiatable<'mc> for PluginLoader<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate PluginLoader from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/plugin/PluginLoader")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PluginLoader object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + /// Gives the list of permissions the plugin will register at runtime, + /// immediately proceding enabling. The format for defining permissions is + /// a map from permission name to properties. To represent a map without + /// any specific property, empty curly-braces ( + /// {} ) may be used (as a null value is not + /// accepted, unlike the {@link #getCommands() commands} above). + /// + /// A list of optional properties for permissions: + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///
    The permission section's description
    NodeDescriptionExample
    descriptionPlaintext (user-friendly) description of what the permission + /// is for.
    description: Allows you to set yourself on fire
    defaultThe default state for the permission, as defined by {@link + /// Permission#getDefault()}. If not defined, it will be set to + /// the value of {@link PluginDescriptionFile#getPermissionDefault()}. + /// + /// For reference:
      + ///
    • true - Represents a positive assignment to + /// {@link Permissible permissibles}. + ///
    • false - Represents no assignment to {@link + /// Permissible permissibles}. + ///
    • op - Represents a positive assignment to + /// {@link Permissible#isOp() operator permissibles}. + ///
    • notop - Represents a positive assignment to + /// {@link Permissible#isOp() non-operator permissibiles}. + ///
    default: true
    childrenAllows other permissions to be set as a {@linkplain + /// Permission#getChildren() relation} to the parent permission. + /// When a parent permissions is assigned, child permissions are + /// respectively assigned as well. + ///
      + ///
    • When a parent permission is assigned negatively, child + /// permissions are assigned based on an inversion of their + /// association. + ///
    • When a parent permission is assigned positively, child + /// permissions are assigned based on their association. + ///
    + /// + /// Child permissions may be defined in a number of ways:
      + ///
    • Children may be defined as a list of + /// names. Using a list will treat all children associated + /// positively to their parent. + ///
    • Children may be defined as a map. Each permission name maps + /// to either a boolean (representing the association), or a + /// nested permission definition (just as another permission). + /// Using a nested definition treats the child as a positive + /// association. + ///
    • A nested permission definition must be a map of these same + /// properties. To define a valid nested permission without + /// defining any specific property, empty curly-braces ( + /// {} ) must be used. + ///
    • A nested permission may carry it's own nested permissions + /// as children, as they may also have nested permissions, and + /// so forth. There is no direct limit to how deep the + /// permission tree is defined. + ///
    As a list: + ///
    children: [inferno.flagrate, inferno.burningdeaths]
    + /// Or as a mapping: + ///
    children:
    +    /// inferno.flagrate: true
    +    /// inferno.burningdeaths: true
    + /// An additional example showing basic nested values can be seen + /// here. + ///
    + /// The permissions are structured as a hiearchy of nested mappings. + /// The primary (top-level, no intendentation) node is + /// `permissions', while each individual permission name is + /// indented, indicating it maps to some value (in our case, the + /// properties of the table above). + /// + /// Here is an example using some of the properties:
    +    /// permissions:
    +    /// inferno.*:
    +    /// description: Gives access to all Inferno commands
    +    /// children:
    +    /// inferno.flagrate: true
    +    /// inferno.burningdeaths: true
    +    /// inferno.flagate:
    +    /// description: Allows you to ignite yourself
    +    /// default: true
    +    /// inferno.burningdeaths:
    +    /// description: Allows you to see how many times you have burned to death
    +    /// default: true
    +    /// 
    + /// Another example, with nested definitions, can be found here. + pub fn permissions( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPermissions", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::permissions::Permission::from_raw(&self.0, obj)?); } + Ok(new_vec) } -} - -impl<'mc> PluginLoader<'mc> { - pub fn from_extendable( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - plugin: &'mc crate::plugin::Plugin, - address: i32, - lib_name: String, - name: String, - ) -> Result> { - let obj = unsafe { plugin.new_extendable(address, "PluginLoader", name, lib_name) }?; - Self::from_raw(env, obj) - } - /// Returns a list of all filename filters expected by this PluginLoader - pub fn plugin_file_filters( + /// Gives the default {@link Permission#getDefault() default} state of + /// {@link #getPermissions() permissions} registered for the plugin. + ///
      + ///
    • If not specified, it will be {@link PermissionDefault#OP}. + ///
    • It is matched using {@link PermissionDefault#getByName(String)} + ///
    • It only affects permissions that do not define the + /// default node. + ///
    • It may be any value in {@link PermissionDefault}. + ///
    + /// + /// In the plugin.yml, this entry is named default-permission. + /// + /// Example:
    default-permission: NOT_OP
    + pub fn permission_default( &self, - ) -> Result, Box> { - let sig = String::from("()Ljava/util/regex/Pattern;"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/permissions/PermissionDefault;"); let res = self.jni_ref().call_method( &self.jni_object(), - "getPluginFileFilters", + "getPermissionDefault", sig.as_str(), vec![], ); let res = self.jni_ref().translate_error(res)?; - blackboxmc_java::util::regex::JavaPattern::from_raw(&self.jni_ref(), unsafe { + crate::permissions::PermissionDefault::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Enables the specified plugin + /// Gives a set of every {@link PluginAwareness} for a plugin. An awareness + /// dictates something that a plugin developer acknowledges when the plugin + /// is compiled. Some implementions may define extra awarenesses that are + /// not included in the API. Any unrecognized + /// awareness (one unsupported or in a future version) will cause a dummy + /// object to be created instead of failing. + ///
      + ///
    • Currently only supports the enumerated values in {@link + /// PluginAwareness.Flags}. + ///
    • Each awareness starts the identifier with bang-at + /// (!@). + ///
    • Unrecognized (future / unimplemented) entries are quietly replaced + /// by a generic object that implements PluginAwareness. + ///
    • A type of awareness must be defined by the runtime and acknowledged + /// by the API, effectively discluding any derived type from any + /// plugin's classpath. + ///
    • awareness must be in YAML list + /// format. + ///
    /// - /// Attempting to enable a plugin that is already enabled will have no - /// effect - pub fn enable_plugin( - &self, - plugin: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "enablePlugin", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Disables the specified plugin + /// In the plugin.yml, this entry is named awareness. /// - /// Attempting to disable a plugin that is not enabled will have no effect - pub fn disable_plugin( - &self, - plugin: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "disablePlugin", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct TimedRegisteredListener<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for TimedRegisteredListener<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for TimedRegisteredListener<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate TimedRegisteredListener from null object." - ) - .into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/plugin/TimedRegisteredListener")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a TimedRegisteredListener object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> TimedRegisteredListener<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - plugin_listener: impl Into>, - event_executor: impl Into>, - event_priority: impl Into>, - registered_plugin: impl Into>, - listen_cancelled: bool, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/event/Listener;Lorg/bukkit/plugin/EventExecutor;Lorg/bukkit/event/EventPriority;Lorg/bukkit/plugin/Plugin;Z)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin_listener.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(event_executor.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(event_priority.into().jni_object().clone()) - }); - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(registered_plugin.into().jni_object().clone()) - }); - let val_5 = jni::objects::JValueGen::Bool(listen_cancelled.into()); - let cls = jni.find_class("org/bukkit/plugin/TimedRegisteredListener"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - jni::objects::JValueGen::from(val_5), - ], - ); - let res = jni.translate_error_no_gen(res)?; - crate::plugin::TimedRegisteredListener::from_raw(&jni, res) - } - - pub fn call_event( + /// Example:
    awareness:
    +    /// - !@UTF8
    + /// + /// Note: Although unknown versions of some future awareness are + /// gracefully substituted, previous versions of Bukkit (ones prior to the + /// first implementation of awareness) will fail to load a plugin that + /// defines any awareness. + pub fn awareness( &self, - event: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/Event;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(event.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "callEvent", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Resets the call count and total time for this listener - pub fn reset(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "reset", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Gets the total times this listener has been called - pub fn count(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getCount", sig.as_str(), vec![]); + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Set;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getAwareness", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + blackboxmc_java::util::JavaSet::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the total time calls to this listener have taken - pub fn total_time(&self) -> Result> { - let sig = String::from("()J"); + /// Returns the name of a plugin, including the version. This method is + /// provided for convenience; it uses the {@link #getName()} and {@link + /// #getVersion()} entries. + pub fn full_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getTotalTime", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getFullName", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.j()?) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Gets the class of the events this listener handled. If it handled - /// multiple classes of event, the closest shared superclass will be - /// returned, such that for any event this listener has handled, - /// this.getEventClass().isAssignableFrom(event.getClass()) - /// and no class this.getEventClass().isAssignableFrom(clazz) - /// {@literal && this.getEventClass() != clazz &&} - /// event.getClass().isAssignableFrom(clazz) for all handled events. - pub fn event_class( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/lang/Class;"); + /// Gives the API version which this plugin is designed to support. No + /// specific format is guaranteed. + ///
      + ///
    • Refer to release notes for supported API versions. + ///
    + /// + /// In the plugin.yml, this entry is named api-version. + /// + /// Example:
    api-version: 1.13
    + pub fn apiversion(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "getEventClass", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getAPIVersion", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { return Ok(None); } - Ok(Some(unsafe { - jni::objects::JClass::from_raw(res.as_jni().l) - })) + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) } - /// Gets whether this listener has handled multiple events, such that for - /// some two events, eventA.getClass() != eventB.getClass(). - pub fn has_multiple(&self) -> Result> { - let sig = String::from("()Z"); + /// Gets the libraries this plugin requires. This is a preview feature. + ///
      + ///
    • Libraries must be GAV specifiers and are loaded from Maven Central. + ///
    + /// + /// Example:
    libraries:
    +    /// - com.squareup.okhttp3:okhttp:4.9.0
    + pub fn libraries(&self) -> Result, Box> { + let sig = String::from("()Ljava/util/List;"); let res = self.jni_ref() - .call_method(&self.jni_object(), "hasMultiple", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getLibraries", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - // SUPER CLASS: org.bukkit.plugin.RegisteredListener ( ['callEvent', 'reset', 'getCount', 'getTotalTime', 'getEventClass', 'hasMultiple']) - /// Gets the listener for this registration - pub fn listener(&self) -> Result, Box> { - let temp_clone = crate::plugin::RegisteredListener::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::plugin::RegisteredListener = temp_clone.into(); - real.listener() - } - /// Gets the plugin for this registration - pub fn plugin(&self) -> Result, Box> { - let temp_clone = crate::plugin::RegisteredListener::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::plugin::RegisteredListener = temp_clone.into(); - real.plugin() - } - /// Gets the priority for this registration - pub fn priority(&self) -> Result, Box> { - let temp_clone = crate::plugin::RegisteredListener::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::plugin::RegisteredListener = temp_clone.into(); - real.priority() - } - /// Whether this listener accepts cancelled events - pub fn is_ignoring_cancelled(&self) -> Result> { - let temp_clone = crate::plugin::RegisteredListener::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::plugin::RegisteredListener = temp_clone.into(); - real.is_ignoring_cancelled() - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for TimedRegisteredListener<'mc> { - fn into(self) -> crate::plugin::RegisteredListener<'mc> { - crate::plugin::RegisteredListener::from_raw(&self.jni_ref(), self.1).expect( - "Error converting TimedRegisteredListener into crate::plugin::RegisteredListener", - ) - } -} -#[repr(C)] -pub struct InvalidPluginException<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for InvalidPluginException<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for InvalidPluginException<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate InvalidPluginException from null object." - ) - .into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/plugin/InvalidPluginException")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a InvalidPluginException object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> InvalidPluginException<'mc> { - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct PluginLogger<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PluginLogger<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PluginLogger<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate PluginLogger from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/plugin/PluginLogger")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PluginLogger object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> PluginLogger<'mc> { - /// Creates a new PluginLogger that extracts the name from a plugin. - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - context: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(context.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/plugin/PluginLogger"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error_no_gen(res)?; - crate::plugin::PluginLogger::from_raw(&jni, res) + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? + .to_string_lossy() + .to_string(), + ); + } + Ok(new_vec) } + #[deprecated] - pub fn log( - &self, - log_record: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Ljava/util/logging/LogRecord;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(log_record.into().jni_object().clone()) - }); + pub fn class_loader_of(&self) -> Result, Box> { + let sig = String::from("()Ljava/lang/String;"); let res = self.jni_ref().call_method( &self.jni_object(), - "log", + "getClassLoaderOf", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![], ); - self.jni_ref().translate_error(res)?; - Ok(()) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some( + self.jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string(), + )) + } + + pub fn raw_name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getRawName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1524,19 +1420,13 @@ impl<'mc> PluginLogger<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PluginLogger<'mc> { - fn into(self) -> blackboxmc_java::util::logging::JavaLogger<'mc> { - blackboxmc_java::util::logging::JavaLogger::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PluginLogger into blackboxmc_java::util::logging::JavaLogger") - } -} #[repr(C)] -pub struct Plugin<'mc>( +pub struct PluginBase<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Plugin<'mc> { +impl<'mc> JNIRaw<'mc> for PluginBase<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1544,18 +1434,18 @@ impl<'mc> JNIRaw<'mc> for Plugin<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Plugin<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PluginBase<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Plugin from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate PluginBase from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/plugin/Plugin")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/plugin/PluginBase")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Plugin object, got {}", + "Invalid argument passed. Expected a PluginBase object, got {}", name ) .into()) @@ -1565,46 +1455,7 @@ impl<'mc> JNIInstantiatable<'mc> for Plugin<'mc> { } } -impl<'mc> Plugin<'mc> { - /// Return one of the extendable classes that BlackBox supports, based on the value given. - /// - /// ## Safety - /// - It returns a Java Object that you must then cast into the proper object via JNI. You are responsible for the checks yourself. - /// - This function is specific to the BlackboxPlugin class supplied within the plugin, and will error out if you pass a regular JavaPlugin. - pub unsafe fn new_extendable( - &self, - address: i32, - class_name: impl Into - + std::convert::AsRef - + std::convert::AsRef - + std::convert::AsRef, - name: impl Into + std::convert::AsRef + std::convert::AsRef, - lib_name: impl Into + std::convert::AsRef + std::convert::AsRef, - ) -> Result> { - let obj = self.jni_ref().call_method( - &self.1, - "newExtendable", - "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)Ljava/lang/Object;", - vec![ - jni::objects::JValueGen::Int(address), - jni::objects::JValueGen::from(jni::objects::JObject::from( - self.jni_ref().new_string(class_name).unwrap(), - )), - jni::objects::JValueGen::from(jni::objects::JObject::from( - self.jni_ref().new_string(name).unwrap(), - )), - jni::objects::JValueGen::from(jni::objects::JObject::from( - self.jni_ref().new_string(lib_name).unwrap(), - )), - #[cfg(target_arch = "wasm32")] - jni::objects::JValueGen::Bool(true.into()), - #[cfg(not(target_arch = "wasm32"))] - jni::objects::JValueGen::Bool(false.into()), - ], - ); - let obj = self.jni_ref().translate_error(obj)?; - Ok(jni::objects::JObject::from_raw(*obj.l()?)) - } +impl<'mc> PluginBase<'mc> { pub fn from_extendable( env: &blackboxmc_general::SharedJNIEnv<'mc>, plugin: &'mc crate::plugin::Plugin, @@ -1612,9 +1463,58 @@ impl<'mc> Plugin<'mc> { lib_name: String, name: String, ) -> Result> { - let obj = unsafe { plugin.new_extendable(address, "Plugin", name, lib_name) }?; + let obj = unsafe { plugin.new_extendable(address, "PluginBase", name, lib_name) }?; Self::from_raw(env, obj) } + + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()V"); + let cls = jni.find_class("org/bukkit/plugin/PluginBase"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), vec![]); + let res = jni.translate_error_no_gen(res)?; + crate::plugin::PluginBase::from_raw(&jni, res) + } + + pub fn hash_code(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + + pub fn equals( + &self, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(Ljava/lang/Object;)Z"); + let val_1 = jni::objects::JValueGen::Object(obj); + let res = self.jni_ref().call_method( + &self.jni_object(), + "equals", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } /// Returns the plugin.yaml file containing the details for this plugin pub fn description( &self, @@ -1875,109 +1775,77 @@ impl<'mc> Plugin<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns the name of the plugin. - /// - /// This should return the bare name of the plugin and should be used for - /// comparison. - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Requests a list of possible completions for a command argument. - pub fn on_tab_complete( - &self, - sender: impl Into>, - command: impl Into>, - label: impl Into, - val_args: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/command/CommandSender;Lorg/bukkit/command/Command;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(command.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(label.into())?, - )); - let val_4 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(val_args.into())?, - )); - let res = self.jni_ref().call_method( - &self.jni_object(), - "onTabComplete", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - ], - ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); +} +impl<'mc> Into> for PluginBase<'mc> { + fn into(self) -> crate::plugin::Plugin<'mc> { + crate::plugin::Plugin::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PluginBase into crate::plugin::Plugin") + } +} +#[repr(C)] +pub struct EventExecutor<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for EventExecutor<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for EventExecutor<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate EventExecutor from null object.").into()); } - let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; - let iter = list.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push( - self.jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(*obj) })? - .to_string_lossy() - .to_string(), - ); + let (valid, name) = env.validate_name(&obj, "org/bukkit/plugin/EventExecutor")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EventExecutor object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } - Ok(Some(new_vec)) } - /// Executes the given command, returning its success. - /// - /// If false is returned, then the "usage" plugin.yml entry for this command - /// (if defined) will be sent to the player. - pub fn on_command( +} + +impl<'mc> EventExecutor<'mc> { + pub fn execute( &self, - sender: impl Into>, - command: impl Into>, - label: impl Into, - val_args: impl Into, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/command/CommandSender;Lorg/bukkit/command/Command;Ljava/lang/String;Ljava/lang/String;)Z"); + listener: impl Into>, + event: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/event/Listener;Lorg/bukkit/event/Event;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(sender.into().jni_object().clone()) + jni::objects::JObject::from_raw(listener.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(command.into().jni_object().clone()) + jni::objects::JObject::from_raw(event.into().jni_object().clone()) }); - let val_3 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(label.into())?, - )); - let val_4 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - self.jni_ref().new_string(val_args.into())?, - )); let res = self.jni_ref().call_method( &self.jni_object(), - "onCommand", + "execute", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), ], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1985,19 +1853,58 @@ impl<'mc> Plugin<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for Plugin<'mc> { - fn into(self) -> crate::command::TabExecutor<'mc> { - crate::command::TabExecutor::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Plugin into crate::command::TabExecutor") +#[repr(C)] +pub struct InvalidDescriptionException<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for InvalidDescriptionException<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for InvalidDescriptionException<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate InvalidDescriptionException from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/plugin/InvalidDescriptionException")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a InvalidDescriptionException object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> InvalidDescriptionException<'mc> { + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } } #[repr(C)] -pub struct AuthorNagException<'mc>( +pub struct UnknownDependencyException<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for AuthorNagException<'mc> { +impl<'mc> JNIRaw<'mc> for UnknownDependencyException<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2005,20 +1912,22 @@ impl<'mc> JNIRaw<'mc> for AuthorNagException<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for AuthorNagException<'mc> { +impl<'mc> JNIInstantiatable<'mc> for UnknownDependencyException<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate AuthorNagException from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate UnknownDependencyException from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/plugin/AuthorNagException")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/plugin/UnknownDependencyException")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a AuthorNagException object, got {}", + "Invalid argument passed. Expected a UnknownDependencyException object, got {}", name ) .into()) @@ -2028,52 +1937,172 @@ impl<'mc> JNIInstantiatable<'mc> for AuthorNagException<'mc> { } } -impl<'mc> AuthorNagException<'mc> { - /// Constructs a new AuthorNagException based on the given Exception - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - message: impl Into, - ) -> Result, Box> { - let sig = String::from("(Ljava/lang/String;)V"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(message.into())?, - )); - let cls = jni.find_class("org/bukkit/plugin/AuthorNagException"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, +impl<'mc> UnknownDependencyException<'mc> { + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct PluginLoader<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PluginLoader<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PluginLoader<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate PluginLoader from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/plugin/PluginLoader")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PluginLoader object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> PluginLoader<'mc> { + pub fn from_extendable( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + plugin: &'mc crate::plugin::Plugin, + address: i32, + lib_name: String, + name: String, + ) -> Result> { + let obj = unsafe { plugin.new_extendable(address, "PluginLoader", name, lib_name) }?; + Self::from_raw(env, obj) + } + /// Returns a list of all filename filters expected by this PluginLoader + pub fn plugin_file_filters( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/regex/Pattern;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPluginFileFilters", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::regex::JavaPattern::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Enables the specified plugin + /// + /// Attempting to enable a plugin that is already enabled will have no + /// effect + pub fn enable_plugin( + &self, + plugin: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "enablePlugin", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error_no_gen(res)?; - crate::plugin::AuthorNagException::from_raw(&jni, res) + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Disables the specified plugin + /// + /// Attempting to disable a plugin that is not enabled will have no effect + pub fn disable_plugin( + &self, + plugin: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "disablePlugin", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } - pub fn message(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getMessage", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct InvalidPluginException<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for InvalidPluginException<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for InvalidPluginException<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate InvalidPluginException from null object." + ) + .into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/plugin/InvalidPluginException")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a InvalidPluginException object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } +} +impl<'mc> InvalidPluginException<'mc> { pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } #[repr(C)] -pub struct RegisteredServiceProvider<'mc>( +pub struct PluginLogger<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for RegisteredServiceProvider<'mc> { +impl<'mc> JNIRaw<'mc> for PluginLogger<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2081,22 +2110,18 @@ impl<'mc> JNIRaw<'mc> for RegisteredServiceProvider<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for RegisteredServiceProvider<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PluginLogger<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate RegisteredServiceProvider from null object." - ) - .into()); + return Err(eyre::eyre!("Tried to instantiate PluginLogger from null object.").into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/plugin/RegisteredServiceProvider")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/plugin/PluginLogger")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a RegisteredServiceProvider object, got {}", + "Invalid argument passed. Expected a PluginLogger object, got {}", name ) .into()) @@ -2106,99 +2131,43 @@ impl<'mc> JNIInstantiatable<'mc> for RegisteredServiceProvider<'mc> { } } -impl<'mc> RegisteredServiceProvider<'mc> { +impl<'mc> PluginLogger<'mc> { + /// Creates a new PluginLogger that extracts the name from a plugin. pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - service: jni::objects::JClass<'mc>, - provider: jni::objects::JObject<'mc>, - priority: impl Into>, - plugin: impl Into>, - ) -> Result, Box> { - let sig = String::from( - "(Ljava/lang/Class;LT;Lorg/bukkit/plugin/ServicePriority;Lorg/bukkit/plugin/Plugin;)V", - ); - let val_1 = jni::objects::JValueGen::Object(service.into()); - let val_2 = jni::objects::JValueGen::Object(provider); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(priority.into().jni_object().clone()) - }); - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + context: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(context.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/plugin/RegisteredServiceProvider"); + let cls = jni.find_class("org/bukkit/plugin/PluginLogger"); let cls = jni.translate_error_with_class(cls)?; let res = jni.new_object( cls, sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = jni.translate_error_no_gen(res)?; - crate::plugin::RegisteredServiceProvider::from_raw(&jni, res) - } - - pub fn service(&self) -> Result, Box> { - let sig = String::from("()Ljava/lang/Class;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getService", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(unsafe { jni::objects::JClass::from_raw(res.as_jni().l) }) - } - - pub fn plugin(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/plugin/Plugin;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPlugin", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::plugin::Plugin::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - - pub fn provider(&self) -> Result, Box> { - let sig = String::from("()LT;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getProvider", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) - } - - pub fn priority( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/plugin/ServicePriority;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPriority", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::plugin::ServicePriority::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + crate::plugin::PluginLogger::from_raw(&jni, res) } - pub fn compare_to( + pub fn log( &self, - other: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/plugin/RegisteredServiceProvider;)I"); + log_record: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/logging/LogRecord;)V"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) + jni::objects::JObject::from_raw(log_record.into().jni_object().clone()) }); let res = self.jni_ref().call_method( &self.jni_object(), - "compareTo", + "log", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -2206,13 +2175,19 @@ impl<'mc> RegisteredServiceProvider<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for PluginLogger<'mc> { + fn into(self) -> blackboxmc_java::util::logging::JavaLogger<'mc> { + blackboxmc_java::util::logging::JavaLogger::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PluginLogger into blackboxmc_java::util::logging::JavaLogger") + } +} #[repr(C)] -pub struct PluginBase<'mc>( +pub struct Plugin<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PluginBase<'mc> { +impl<'mc> JNIRaw<'mc> for Plugin<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -2220,18 +2195,18 @@ impl<'mc> JNIRaw<'mc> for PluginBase<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PluginBase<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Plugin<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate PluginBase from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate Plugin from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/plugin/PluginBase")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/plugin/Plugin")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PluginBase object, got {}", + "Invalid argument passed. Expected a Plugin object, got {}", name ) .into()) @@ -2241,7 +2216,46 @@ impl<'mc> JNIInstantiatable<'mc> for PluginBase<'mc> { } } -impl<'mc> PluginBase<'mc> { +impl<'mc> Plugin<'mc> { + /// Return one of the extendable classes that BlackBox supports, based on the value given. + /// + /// ## Safety + /// - It returns a Java Object that you must then cast into the proper object via JNI. You are responsible for the checks yourself. + /// - This function is specific to the BlackboxPlugin class supplied within the plugin, and will error out if you pass a regular JavaPlugin. + pub unsafe fn new_extendable( + &self, + address: i32, + class_name: impl Into + + std::convert::AsRef + + std::convert::AsRef + + std::convert::AsRef, + name: impl Into + std::convert::AsRef + std::convert::AsRef, + lib_name: impl Into + std::convert::AsRef + std::convert::AsRef, + ) -> Result> { + let obj = self.jni_ref().call_method( + &self.1, + "newExtendable", + "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)Ljava/lang/Object;", + vec![ + jni::objects::JValueGen::Int(address), + jni::objects::JValueGen::from(jni::objects::JObject::from( + self.jni_ref().new_string(class_name).unwrap(), + )), + jni::objects::JValueGen::from(jni::objects::JObject::from( + self.jni_ref().new_string(name).unwrap(), + )), + jni::objects::JValueGen::from(jni::objects::JObject::from( + self.jni_ref().new_string(lib_name).unwrap(), + )), + #[cfg(target_arch = "wasm32")] + jni::objects::JValueGen::Bool(true.into()), + #[cfg(not(target_arch = "wasm32"))] + jni::objects::JValueGen::Bool(false.into()), + ], + ); + let obj = self.jni_ref().translate_error(obj)?; + Ok(jni::objects::JObject::from_raw(*obj.l()?)) + } pub fn from_extendable( env: &blackboxmc_general::SharedJNIEnv<'mc>, plugin: &'mc crate::plugin::Plugin, @@ -2249,58 +2263,9 @@ impl<'mc> PluginBase<'mc> { lib_name: String, name: String, ) -> Result> { - let obj = unsafe { plugin.new_extendable(address, "PluginBase", name, lib_name) }?; + let obj = unsafe { plugin.new_extendable(address, "Plugin", name, lib_name) }?; Self::from_raw(env, obj) } - - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/plugin/PluginBase"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), vec![]); - let res = jni.translate_error_no_gen(res)?; - crate::plugin::PluginBase::from_raw(&jni, res) - } - - pub fn hash_code(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - - pub fn equals( - &self, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - let sig = String::from("(Ljava/lang/Object;)Z"); - let val_1 = jni::objects::JValueGen::Object(obj); - let res = self.jni_ref().call_method( - &self.jni_object(), - "equals", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } /// Returns the plugin.yaml file containing the details for this plugin pub fn description( &self, @@ -2561,6 +2526,22 @@ impl<'mc> PluginBase<'mc> { jni::objects::JObject::from_raw(res.l()?.clone()) }) } + /// Returns the name of the plugin. + /// + /// This should return the bare name of the plugin and should be used for + /// comparison. + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } /// Requests a list of possible completions for a command argument. pub fn on_tab_complete( &self, @@ -2598,7 +2579,7 @@ impl<'mc> PluginBase<'mc> { return Ok(None); } let mut new_vec = Vec::new(); - let list = blackboxmc_java::util::JavaList::from_raw(&self.0, res.l()?)?; + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; let iter = list.iterator()?; while iter.has_next()? { let obj = iter.next()?; @@ -2655,16 +2636,116 @@ impl<'mc> PluginBase<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PluginBase<'mc> { - fn into(self) -> crate::plugin::Plugin<'mc> { - crate::plugin::Plugin::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PluginBase into crate::plugin::Plugin") +impl<'mc> Into> for Plugin<'mc> { + fn into(self) -> crate::command::TabExecutor<'mc> { + crate::command::TabExecutor::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Plugin into crate::command::TabExecutor") + } +} +#[repr(C)] +pub struct AuthorNagException<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for AuthorNagException<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for AuthorNagException<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate AuthorNagException from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/plugin/AuthorNagException")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a AuthorNagException object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> AuthorNagException<'mc> { + /// Constructs a new AuthorNagException based on the given Exception + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + message: impl Into, + ) -> Result, Box> { + let sig = String::from("(Ljava/lang/String;)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(message.into())?, + )); + let cls = jni.find_class("org/bukkit/plugin/AuthorNagException"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error_no_gen(res)?; + crate::plugin::AuthorNagException::from_raw(&jni, res) + } + + pub fn message(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getMessage", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum ServicePriority<'mc> {} +pub enum ServicePriority<'mc> { + Lowest { inner: ServicePriorityStruct<'mc> }, + Low { inner: ServicePriorityStruct<'mc> }, + Normal { inner: ServicePriorityStruct<'mc> }, + High { inner: ServicePriorityStruct<'mc> }, + Highest { inner: ServicePriorityStruct<'mc> }, +} impl<'mc> std::fmt::Display for ServicePriority<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + ServicePriority::Lowest { .. } => f.write_str("Lowest"), + ServicePriority::Low { .. } => f.write_str("Low"), + ServicePriority::Normal { .. } => f.write_str("Normal"), + ServicePriority::High { .. } => f.write_str("High"), + ServicePriority::Highest { .. } => f.write_str("Highest"), + } + } +} +impl<'mc> std::ops::Deref for ServicePriority<'mc> { + type Target = ServicePriorityStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + ServicePriority::Lowest { inner } => inner, + ServicePriority::Low { inner } => inner, + ServicePriority::Normal { inner } => inner, + ServicePriority::High { inner } => inner, + ServicePriority::Highest { inner } => inner, + } } } @@ -2691,6 +2772,22 @@ impl<'mc> ServicePriority<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "Lowest" => Ok(ServicePriority::Lowest { + inner: ServicePriorityStruct::from_raw(env, obj)?, + }), + "Low" => Ok(ServicePriority::Low { + inner: ServicePriorityStruct::from_raw(env, obj)?, + }), + "Normal" => Ok(ServicePriority::Normal { + inner: ServicePriorityStruct::from_raw(env, obj)?, + }), + "High" => Ok(ServicePriority::High { + inner: ServicePriorityStruct::from_raw(env, obj)?, + }), + "Highest" => Ok(ServicePriority::Highest { + inner: ServicePriorityStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -2704,10 +2801,22 @@ pub struct ServicePriorityStruct<'mc>( impl<'mc> JNIRaw<'mc> for ServicePriority<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Lowest { inner } => inner.0.clone(), + Self::Low { inner } => inner.0.clone(), + Self::Normal { inner } => inner.0.clone(), + Self::High { inner } => inner.0.clone(), + Self::Highest { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Lowest { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Low { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Normal { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::High { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Highest { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for ServicePriority<'mc> { @@ -2735,6 +2844,21 @@ impl<'mc> JNIInstantiatable<'mc> for ServicePriority<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "Lowest" => Ok(ServicePriority::Lowest { + inner: ServicePriorityStruct::from_raw(env, obj)?, + }), + "Low" => Ok(ServicePriority::Low { + inner: ServicePriorityStruct::from_raw(env, obj)?, + }), + "Normal" => Ok(ServicePriority::Normal { + inner: ServicePriorityStruct::from_raw(env, obj)?, + }), + "High" => Ok(ServicePriority::High { + inner: ServicePriorityStruct::from_raw(env, obj)?, + }), + "Highest" => Ok(ServicePriority::Highest { + inner: ServicePriorityStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -2834,10 +2958,24 @@ impl<'mc> PluginAwareness<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum PluginAwarenessFlags<'mc> {} +pub enum PluginAwarenessFlags<'mc> { + Utf8 { + inner: PluginAwarenessFlagsStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for PluginAwarenessFlags<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + PluginAwarenessFlags::Utf8 { .. } => f.write_str("UTF8"), + } + } +} +impl<'mc> std::ops::Deref for PluginAwarenessFlags<'mc> { + type Target = PluginAwarenessFlagsStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + PluginAwarenessFlags::Utf8 { inner } => inner, + } } } @@ -2864,6 +3002,10 @@ impl<'mc> PluginAwarenessFlags<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "UTF8" => Ok(PluginAwarenessFlags::Utf8 { + inner: PluginAwarenessFlagsStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -2877,10 +3019,14 @@ pub struct PluginAwarenessFlagsStruct<'mc>( impl<'mc> JNIRaw<'mc> for PluginAwarenessFlags<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Utf8 { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Utf8 { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for PluginAwarenessFlags<'mc> { @@ -2908,6 +3054,9 @@ impl<'mc> JNIInstantiatable<'mc> for PluginAwarenessFlags<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "UTF8" => Ok(PluginAwarenessFlags::Utf8 { + inner: PluginAwarenessFlagsStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -3803,155 +3952,25 @@ impl<'mc> IllegalPluginAccessException<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -#[repr(C)] -pub struct RegisteredListener<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for RegisteredListener<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } +pub enum PluginLoadOrder<'mc> { + Startup { inner: PluginLoadOrderStruct<'mc> }, + Postworld { inner: PluginLoadOrderStruct<'mc> }, } -impl<'mc> JNIInstantiatable<'mc> for RegisteredListener<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate RegisteredListener from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/plugin/RegisteredListener")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a RegisteredListener object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) +impl<'mc> std::fmt::Display for PluginLoadOrder<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PluginLoadOrder::Startup { .. } => f.write_str("STARTUP"), + PluginLoadOrder::Postworld { .. } => f.write_str("POSTWORLD"), } } } - -impl<'mc> RegisteredListener<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - listener: impl Into>, - executor: impl Into>, - priority: impl Into>, - plugin: impl Into>, - ignore_cancelled: bool, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/event/Listener;Lorg/bukkit/plugin/EventExecutor;Lorg/bukkit/event/EventPriority;Lorg/bukkit/plugin/Plugin;Z)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(listener.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(executor.into().jni_object().clone()) - }); - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(priority.into().jni_object().clone()) - }); - let val_4 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let val_5 = jni::objects::JValueGen::Bool(ignore_cancelled.into()); - let cls = jni.find_class("org/bukkit/plugin/RegisteredListener"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - jni::objects::JValueGen::from(val_5), - ], - ); - let res = jni.translate_error_no_gen(res)?; - crate::plugin::RegisteredListener::from_raw(&jni, res) - } - /// Gets the listener for this registration - pub fn listener(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/Listener;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getListener", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::Listener::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the plugin for this registration - pub fn plugin(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/plugin/Plugin;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getPlugin", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::plugin::Plugin::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the priority for this registration - pub fn priority(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/event/EventPriority;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPriority", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::event::EventPriority::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Calls the event executor - pub fn call_event( - &self, - event: impl Into>, - ) -> Result<(), Box> { - let sig = String::from("(Lorg/bukkit/event/Event;)V"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(event.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "callEvent", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Whether this listener accepts cancelled events - pub fn is_ignoring_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isIgnoringCancelled", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -pub enum PluginLoadOrder<'mc> {} -impl<'mc> std::fmt::Display for PluginLoadOrder<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} +impl<'mc> std::ops::Deref for PluginLoadOrder<'mc> { + type Target = PluginLoadOrderStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + PluginLoadOrder::Startup { inner } => inner, + PluginLoadOrder::Postworld { inner } => inner, + } } } @@ -3978,6 +3997,13 @@ impl<'mc> PluginLoadOrder<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "STARTUP" => Ok(PluginLoadOrder::Startup { + inner: PluginLoadOrderStruct::from_raw(env, obj)?, + }), + "POSTWORLD" => Ok(PluginLoadOrder::Postworld { + inner: PluginLoadOrderStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -3991,10 +4017,18 @@ pub struct PluginLoadOrderStruct<'mc>( impl<'mc> JNIRaw<'mc> for PluginLoadOrder<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Startup { inner } => inner.0.clone(), + Self::Postworld { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Startup { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Postworld { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } impl<'mc> JNIInstantiatable<'mc> for PluginLoadOrder<'mc> { @@ -4022,6 +4056,12 @@ impl<'mc> JNIInstantiatable<'mc> for PluginLoadOrder<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "STARTUP" => Ok(PluginLoadOrder::Startup { + inner: PluginLoadOrderStruct::from_raw(env, obj)?, + }), + "POSTWORLD" => Ok(PluginLoadOrder::Postworld { + inner: PluginLoadOrderStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } diff --git a/blackboxmc-rs-bukkit/src/potion/mod.rs b/blackboxmc-rs-bukkit/src/potion/mod.rs index 26090e6..9742526 100644 --- a/blackboxmc-rs-bukkit/src/potion/mod.rs +++ b/blackboxmc-rs-bukkit/src/potion/mod.rs @@ -2,10 +2,157 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; -pub enum PotionType<'mc> {} +pub enum PotionType<'mc> { + Water { inner: PotionTypeStruct<'mc> }, + Mundane { inner: PotionTypeStruct<'mc> }, + Thick { inner: PotionTypeStruct<'mc> }, + Awkward { inner: PotionTypeStruct<'mc> }, + NightVision { inner: PotionTypeStruct<'mc> }, + LongNightVision { inner: PotionTypeStruct<'mc> }, + Invisibility { inner: PotionTypeStruct<'mc> }, + LongInvisibility { inner: PotionTypeStruct<'mc> }, + Leaping { inner: PotionTypeStruct<'mc> }, + LongLeaping { inner: PotionTypeStruct<'mc> }, + StrongLeaping { inner: PotionTypeStruct<'mc> }, + FireResistance { inner: PotionTypeStruct<'mc> }, + LongFireResistance { inner: PotionTypeStruct<'mc> }, + Swiftness { inner: PotionTypeStruct<'mc> }, + LongSwiftness { inner: PotionTypeStruct<'mc> }, + StrongSwiftness { inner: PotionTypeStruct<'mc> }, + Slowness { inner: PotionTypeStruct<'mc> }, + LongSlowness { inner: PotionTypeStruct<'mc> }, + StrongSlowness { inner: PotionTypeStruct<'mc> }, + WaterBreathing { inner: PotionTypeStruct<'mc> }, + LongWaterBreathing { inner: PotionTypeStruct<'mc> }, + Healing { inner: PotionTypeStruct<'mc> }, + StrongHealing { inner: PotionTypeStruct<'mc> }, + Harming { inner: PotionTypeStruct<'mc> }, + StrongHarming { inner: PotionTypeStruct<'mc> }, + Poison { inner: PotionTypeStruct<'mc> }, + LongPoison { inner: PotionTypeStruct<'mc> }, + StrongPoison { inner: PotionTypeStruct<'mc> }, + Regeneration { inner: PotionTypeStruct<'mc> }, + LongRegeneration { inner: PotionTypeStruct<'mc> }, + StrongRegeneration { inner: PotionTypeStruct<'mc> }, + Strength { inner: PotionTypeStruct<'mc> }, + LongStrength { inner: PotionTypeStruct<'mc> }, + StrongStrength { inner: PotionTypeStruct<'mc> }, + Weakness { inner: PotionTypeStruct<'mc> }, + LongWeakness { inner: PotionTypeStruct<'mc> }, + Luck { inner: PotionTypeStruct<'mc> }, + TurtleMaster { inner: PotionTypeStruct<'mc> }, + LongTurtleMaster { inner: PotionTypeStruct<'mc> }, + StrongTurtleMaster { inner: PotionTypeStruct<'mc> }, + SlowFalling { inner: PotionTypeStruct<'mc> }, + LongSlowFalling { inner: PotionTypeStruct<'mc> }, + WindCharged { inner: PotionTypeStruct<'mc> }, + Weaving { inner: PotionTypeStruct<'mc> }, + Oozing { inner: PotionTypeStruct<'mc> }, + Infested { inner: PotionTypeStruct<'mc> }, +} impl<'mc> std::fmt::Display for PotionType<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + PotionType::Water { .. } => f.write_str("WATER"), + PotionType::Mundane { .. } => f.write_str("MUNDANE"), + PotionType::Thick { .. } => f.write_str("THICK"), + PotionType::Awkward { .. } => f.write_str("AWKWARD"), + PotionType::NightVision { .. } => f.write_str("NIGHT_VISION"), + PotionType::LongNightVision { .. } => f.write_str("LONG_NIGHT_VISION"), + PotionType::Invisibility { .. } => f.write_str("INVISIBILITY"), + PotionType::LongInvisibility { .. } => f.write_str("LONG_INVISIBILITY"), + PotionType::Leaping { .. } => f.write_str("LEAPING"), + PotionType::LongLeaping { .. } => f.write_str("LONG_LEAPING"), + PotionType::StrongLeaping { .. } => f.write_str("STRONG_LEAPING"), + PotionType::FireResistance { .. } => f.write_str("FIRE_RESISTANCE"), + PotionType::LongFireResistance { .. } => f.write_str("LONG_FIRE_RESISTANCE"), + PotionType::Swiftness { .. } => f.write_str("SWIFTNESS"), + PotionType::LongSwiftness { .. } => f.write_str("LONG_SWIFTNESS"), + PotionType::StrongSwiftness { .. } => f.write_str("STRONG_SWIFTNESS"), + PotionType::Slowness { .. } => f.write_str("SLOWNESS"), + PotionType::LongSlowness { .. } => f.write_str("LONG_SLOWNESS"), + PotionType::StrongSlowness { .. } => f.write_str("STRONG_SLOWNESS"), + PotionType::WaterBreathing { .. } => f.write_str("WATER_BREATHING"), + PotionType::LongWaterBreathing { .. } => f.write_str("LONG_WATER_BREATHING"), + PotionType::Healing { .. } => f.write_str("HEALING"), + PotionType::StrongHealing { .. } => f.write_str("STRONG_HEALING"), + PotionType::Harming { .. } => f.write_str("HARMING"), + PotionType::StrongHarming { .. } => f.write_str("STRONG_HARMING"), + PotionType::Poison { .. } => f.write_str("POISON"), + PotionType::LongPoison { .. } => f.write_str("LONG_POISON"), + PotionType::StrongPoison { .. } => f.write_str("STRONG_POISON"), + PotionType::Regeneration { .. } => f.write_str("REGENERATION"), + PotionType::LongRegeneration { .. } => f.write_str("LONG_REGENERATION"), + PotionType::StrongRegeneration { .. } => f.write_str("STRONG_REGENERATION"), + PotionType::Strength { .. } => f.write_str("STRENGTH"), + PotionType::LongStrength { .. } => f.write_str("LONG_STRENGTH"), + PotionType::StrongStrength { .. } => f.write_str("STRONG_STRENGTH"), + PotionType::Weakness { .. } => f.write_str("WEAKNESS"), + PotionType::LongWeakness { .. } => f.write_str("LONG_WEAKNESS"), + PotionType::Luck { .. } => f.write_str("LUCK"), + PotionType::TurtleMaster { .. } => f.write_str("TURTLE_MASTER"), + PotionType::LongTurtleMaster { .. } => f.write_str("LONG_TURTLE_MASTER"), + PotionType::StrongTurtleMaster { .. } => f.write_str("STRONG_TURTLE_MASTER"), + PotionType::SlowFalling { .. } => f.write_str("SLOW_FALLING"), + PotionType::LongSlowFalling { .. } => f.write_str("LONG_SLOW_FALLING"), + PotionType::WindCharged { .. } => f.write_str("WIND_CHARGED"), + PotionType::Weaving { .. } => f.write_str("WEAVING"), + PotionType::Oozing { .. } => f.write_str("OOZING"), + PotionType::Infested { .. } => f.write_str("INFESTED"), + } + } +} +impl<'mc> std::ops::Deref for PotionType<'mc> { + type Target = PotionTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + PotionType::Water { inner } => inner, + PotionType::Mundane { inner } => inner, + PotionType::Thick { inner } => inner, + PotionType::Awkward { inner } => inner, + PotionType::NightVision { inner } => inner, + PotionType::LongNightVision { inner } => inner, + PotionType::Invisibility { inner } => inner, + PotionType::LongInvisibility { inner } => inner, + PotionType::Leaping { inner } => inner, + PotionType::LongLeaping { inner } => inner, + PotionType::StrongLeaping { inner } => inner, + PotionType::FireResistance { inner } => inner, + PotionType::LongFireResistance { inner } => inner, + PotionType::Swiftness { inner } => inner, + PotionType::LongSwiftness { inner } => inner, + PotionType::StrongSwiftness { inner } => inner, + PotionType::Slowness { inner } => inner, + PotionType::LongSlowness { inner } => inner, + PotionType::StrongSlowness { inner } => inner, + PotionType::WaterBreathing { inner } => inner, + PotionType::LongWaterBreathing { inner } => inner, + PotionType::Healing { inner } => inner, + PotionType::StrongHealing { inner } => inner, + PotionType::Harming { inner } => inner, + PotionType::StrongHarming { inner } => inner, + PotionType::Poison { inner } => inner, + PotionType::LongPoison { inner } => inner, + PotionType::StrongPoison { inner } => inner, + PotionType::Regeneration { inner } => inner, + PotionType::LongRegeneration { inner } => inner, + PotionType::StrongRegeneration { inner } => inner, + PotionType::Strength { inner } => inner, + PotionType::LongStrength { inner } => inner, + PotionType::StrongStrength { inner } => inner, + PotionType::Weakness { inner } => inner, + PotionType::LongWeakness { inner } => inner, + PotionType::Luck { inner } => inner, + PotionType::TurtleMaster { inner } => inner, + PotionType::LongTurtleMaster { inner } => inner, + PotionType::StrongTurtleMaster { inner } => inner, + PotionType::SlowFalling { inner } => inner, + PotionType::LongSlowFalling { inner } => inner, + PotionType::WindCharged { inner } => inner, + PotionType::Weaving { inner } => inner, + PotionType::Oozing { inner } => inner, + PotionType::Infested { inner } => inner, + } } } @@ -32,6 +179,145 @@ impl<'mc> PotionType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "WATER" => Ok(PotionType::Water { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "MUNDANE" => Ok(PotionType::Mundane { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "THICK" => Ok(PotionType::Thick { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "AWKWARD" => Ok(PotionType::Awkward { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "NIGHT_VISION" => Ok(PotionType::NightVision { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_NIGHT_VISION" => Ok(PotionType::LongNightVision { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "INVISIBILITY" => Ok(PotionType::Invisibility { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_INVISIBILITY" => Ok(PotionType::LongInvisibility { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LEAPING" => Ok(PotionType::Leaping { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_LEAPING" => Ok(PotionType::LongLeaping { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "STRONG_LEAPING" => Ok(PotionType::StrongLeaping { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "FIRE_RESISTANCE" => Ok(PotionType::FireResistance { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_FIRE_RESISTANCE" => Ok(PotionType::LongFireResistance { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "SWIFTNESS" => Ok(PotionType::Swiftness { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_SWIFTNESS" => Ok(PotionType::LongSwiftness { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "STRONG_SWIFTNESS" => Ok(PotionType::StrongSwiftness { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "SLOWNESS" => Ok(PotionType::Slowness { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_SLOWNESS" => Ok(PotionType::LongSlowness { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "STRONG_SLOWNESS" => Ok(PotionType::StrongSlowness { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "WATER_BREATHING" => Ok(PotionType::WaterBreathing { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_WATER_BREATHING" => Ok(PotionType::LongWaterBreathing { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "HEALING" => Ok(PotionType::Healing { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "STRONG_HEALING" => Ok(PotionType::StrongHealing { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "HARMING" => Ok(PotionType::Harming { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "STRONG_HARMING" => Ok(PotionType::StrongHarming { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "POISON" => Ok(PotionType::Poison { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_POISON" => Ok(PotionType::LongPoison { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "STRONG_POISON" => Ok(PotionType::StrongPoison { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "REGENERATION" => Ok(PotionType::Regeneration { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_REGENERATION" => Ok(PotionType::LongRegeneration { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "STRONG_REGENERATION" => Ok(PotionType::StrongRegeneration { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "STRENGTH" => Ok(PotionType::Strength { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_STRENGTH" => Ok(PotionType::LongStrength { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "STRONG_STRENGTH" => Ok(PotionType::StrongStrength { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "WEAKNESS" => Ok(PotionType::Weakness { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_WEAKNESS" => Ok(PotionType::LongWeakness { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LUCK" => Ok(PotionType::Luck { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "TURTLE_MASTER" => Ok(PotionType::TurtleMaster { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_TURTLE_MASTER" => Ok(PotionType::LongTurtleMaster { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "STRONG_TURTLE_MASTER" => Ok(PotionType::StrongTurtleMaster { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "SLOW_FALLING" => Ok(PotionType::SlowFalling { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_SLOW_FALLING" => Ok(PotionType::LongSlowFalling { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "WIND_CHARGED" => Ok(PotionType::WindCharged { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "WEAVING" => Ok(PotionType::Weaving { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "OOZING" => Ok(PotionType::Oozing { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "INFESTED" => Ok(PotionType::Infested { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -45,10 +331,166 @@ pub struct PotionTypeStruct<'mc>( impl<'mc> JNIRaw<'mc> for PotionType<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Water { inner } => inner.0.clone(), + Self::Mundane { inner } => inner.0.clone(), + Self::Thick { inner } => inner.0.clone(), + Self::Awkward { inner } => inner.0.clone(), + Self::NightVision { inner } => inner.0.clone(), + Self::LongNightVision { inner } => inner.0.clone(), + Self::Invisibility { inner } => inner.0.clone(), + Self::LongInvisibility { inner } => inner.0.clone(), + Self::Leaping { inner } => inner.0.clone(), + Self::LongLeaping { inner } => inner.0.clone(), + Self::StrongLeaping { inner } => inner.0.clone(), + Self::FireResistance { inner } => inner.0.clone(), + Self::LongFireResistance { inner } => inner.0.clone(), + Self::Swiftness { inner } => inner.0.clone(), + Self::LongSwiftness { inner } => inner.0.clone(), + Self::StrongSwiftness { inner } => inner.0.clone(), + Self::Slowness { inner } => inner.0.clone(), + Self::LongSlowness { inner } => inner.0.clone(), + Self::StrongSlowness { inner } => inner.0.clone(), + Self::WaterBreathing { inner } => inner.0.clone(), + Self::LongWaterBreathing { inner } => inner.0.clone(), + Self::Healing { inner } => inner.0.clone(), + Self::StrongHealing { inner } => inner.0.clone(), + Self::Harming { inner } => inner.0.clone(), + Self::StrongHarming { inner } => inner.0.clone(), + Self::Poison { inner } => inner.0.clone(), + Self::LongPoison { inner } => inner.0.clone(), + Self::StrongPoison { inner } => inner.0.clone(), + Self::Regeneration { inner } => inner.0.clone(), + Self::LongRegeneration { inner } => inner.0.clone(), + Self::StrongRegeneration { inner } => inner.0.clone(), + Self::Strength { inner } => inner.0.clone(), + Self::LongStrength { inner } => inner.0.clone(), + Self::StrongStrength { inner } => inner.0.clone(), + Self::Weakness { inner } => inner.0.clone(), + Self::LongWeakness { inner } => inner.0.clone(), + Self::Luck { inner } => inner.0.clone(), + Self::TurtleMaster { inner } => inner.0.clone(), + Self::LongTurtleMaster { inner } => inner.0.clone(), + Self::StrongTurtleMaster { inner } => inner.0.clone(), + Self::SlowFalling { inner } => inner.0.clone(), + Self::LongSlowFalling { inner } => inner.0.clone(), + Self::WindCharged { inner } => inner.0.clone(), + Self::Weaving { inner } => inner.0.clone(), + Self::Oozing { inner } => inner.0.clone(), + Self::Infested { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Water { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Mundane { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Thick { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Awkward { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::NightVision { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LongNightVision { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Invisibility { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LongInvisibility { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Leaping { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::LongLeaping { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrongLeaping { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FireResistance { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LongFireResistance { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Swiftness { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LongSwiftness { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrongSwiftness { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Slowness { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::LongSlowness { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrongSlowness { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaterBreathing { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LongWaterBreathing { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Healing { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::StrongHealing { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Harming { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::StrongHarming { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Poison { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::LongPoison { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrongPoison { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Regeneration { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LongRegeneration { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrongRegeneration { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Strength { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::LongStrength { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrongStrength { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Weakness { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::LongWeakness { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Luck { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::TurtleMaster { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LongTurtleMaster { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::StrongTurtleMaster { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SlowFalling { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::LongSlowFalling { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WindCharged { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Weaving { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Oozing { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Infested { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for PotionType<'mc> { @@ -74,6 +516,144 @@ impl<'mc> JNIInstantiatable<'mc> for PotionType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "WATER" => Ok(PotionType::Water { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "MUNDANE" => Ok(PotionType::Mundane { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "THICK" => Ok(PotionType::Thick { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "AWKWARD" => Ok(PotionType::Awkward { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "NIGHT_VISION" => Ok(PotionType::NightVision { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_NIGHT_VISION" => Ok(PotionType::LongNightVision { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "INVISIBILITY" => Ok(PotionType::Invisibility { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_INVISIBILITY" => Ok(PotionType::LongInvisibility { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LEAPING" => Ok(PotionType::Leaping { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_LEAPING" => Ok(PotionType::LongLeaping { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "STRONG_LEAPING" => Ok(PotionType::StrongLeaping { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "FIRE_RESISTANCE" => Ok(PotionType::FireResistance { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_FIRE_RESISTANCE" => Ok(PotionType::LongFireResistance { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "SWIFTNESS" => Ok(PotionType::Swiftness { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_SWIFTNESS" => Ok(PotionType::LongSwiftness { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "STRONG_SWIFTNESS" => Ok(PotionType::StrongSwiftness { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "SLOWNESS" => Ok(PotionType::Slowness { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_SLOWNESS" => Ok(PotionType::LongSlowness { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "STRONG_SLOWNESS" => Ok(PotionType::StrongSlowness { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "WATER_BREATHING" => Ok(PotionType::WaterBreathing { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_WATER_BREATHING" => Ok(PotionType::LongWaterBreathing { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "HEALING" => Ok(PotionType::Healing { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "STRONG_HEALING" => Ok(PotionType::StrongHealing { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "HARMING" => Ok(PotionType::Harming { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "STRONG_HARMING" => Ok(PotionType::StrongHarming { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "POISON" => Ok(PotionType::Poison { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_POISON" => Ok(PotionType::LongPoison { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "STRONG_POISON" => Ok(PotionType::StrongPoison { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "REGENERATION" => Ok(PotionType::Regeneration { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_REGENERATION" => Ok(PotionType::LongRegeneration { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "STRONG_REGENERATION" => Ok(PotionType::StrongRegeneration { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "STRENGTH" => Ok(PotionType::Strength { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_STRENGTH" => Ok(PotionType::LongStrength { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "STRONG_STRENGTH" => Ok(PotionType::StrongStrength { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "WEAKNESS" => Ok(PotionType::Weakness { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_WEAKNESS" => Ok(PotionType::LongWeakness { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LUCK" => Ok(PotionType::Luck { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "TURTLE_MASTER" => Ok(PotionType::TurtleMaster { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_TURTLE_MASTER" => Ok(PotionType::LongTurtleMaster { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "STRONG_TURTLE_MASTER" => Ok(PotionType::StrongTurtleMaster { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "SLOW_FALLING" => Ok(PotionType::SlowFalling { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "LONG_SLOW_FALLING" => Ok(PotionType::LongSlowFalling { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "WIND_CHARGED" => Ok(PotionType::WindCharged { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "WEAVING" => Ok(PotionType::Weaving { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "OOZING" => Ok(PotionType::Oozing { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), + "INFESTED" => Ok(PotionType::Infested { + inner: PotionTypeStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -360,27 +940,742 @@ impl<'mc> PotionTypeInternalPotionData<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -#[repr(C)] -pub struct PotionEffect<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PotionEffect<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } +pub enum PotionEffectType<'mc> { + Speed { inner: PotionEffectTypeStruct<'mc> }, + Slowness { inner: PotionEffectTypeStruct<'mc> }, + Haste { inner: PotionEffectTypeStruct<'mc> }, + MiningFatigue { inner: PotionEffectTypeStruct<'mc> }, + Strength { inner: PotionEffectTypeStruct<'mc> }, + InstantHealth { inner: PotionEffectTypeStruct<'mc> }, + InstantDamage { inner: PotionEffectTypeStruct<'mc> }, + JumpBoost { inner: PotionEffectTypeStruct<'mc> }, + Nausea { inner: PotionEffectTypeStruct<'mc> }, + Regeneration { inner: PotionEffectTypeStruct<'mc> }, + Resistance { inner: PotionEffectTypeStruct<'mc> }, + FireResistance { inner: PotionEffectTypeStruct<'mc> }, + WaterBreathing { inner: PotionEffectTypeStruct<'mc> }, + Invisibility { inner: PotionEffectTypeStruct<'mc> }, + Blindness { inner: PotionEffectTypeStruct<'mc> }, + NightVision { inner: PotionEffectTypeStruct<'mc> }, + Hunger { inner: PotionEffectTypeStruct<'mc> }, + Weakness { inner: PotionEffectTypeStruct<'mc> }, + Poison { inner: PotionEffectTypeStruct<'mc> }, + Wither { inner: PotionEffectTypeStruct<'mc> }, + HealthBoost { inner: PotionEffectTypeStruct<'mc> }, + Absorption { inner: PotionEffectTypeStruct<'mc> }, + Saturation { inner: PotionEffectTypeStruct<'mc> }, + Glowing { inner: PotionEffectTypeStruct<'mc> }, + Levitation { inner: PotionEffectTypeStruct<'mc> }, + Luck { inner: PotionEffectTypeStruct<'mc> }, + Unluck { inner: PotionEffectTypeStruct<'mc> }, + SlowFalling { inner: PotionEffectTypeStruct<'mc> }, + ConduitPower { inner: PotionEffectTypeStruct<'mc> }, + DolphinsGrace { inner: PotionEffectTypeStruct<'mc> }, + BadOmen { inner: PotionEffectTypeStruct<'mc> }, + HeroOfTheVillage { inner: PotionEffectTypeStruct<'mc> }, + Darkness { inner: PotionEffectTypeStruct<'mc> }, + TrialOmen { inner: PotionEffectTypeStruct<'mc> }, + RaidOmen { inner: PotionEffectTypeStruct<'mc> }, + WindCharged { inner: PotionEffectTypeStruct<'mc> }, + Weaving { inner: PotionEffectTypeStruct<'mc> }, + Oozing { inner: PotionEffectTypeStruct<'mc> }, + Infested { inner: PotionEffectTypeStruct<'mc> }, } -impl<'mc> JNIInstantiatable<'mc> for PotionEffect<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate PotionEffect from null object.").into()); +impl<'mc> std::fmt::Display for PotionEffectType<'mc> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PotionEffectType::Speed { .. } => f.write_str("SPEED"), + PotionEffectType::Slowness { .. } => f.write_str("SLOWNESS"), + PotionEffectType::Haste { .. } => f.write_str("HASTE"), + PotionEffectType::MiningFatigue { .. } => f.write_str("MINING_FATIGUE"), + PotionEffectType::Strength { .. } => f.write_str("STRENGTH"), + PotionEffectType::InstantHealth { .. } => f.write_str("INSTANT_HEALTH"), + PotionEffectType::InstantDamage { .. } => f.write_str("INSTANT_DAMAGE"), + PotionEffectType::JumpBoost { .. } => f.write_str("JUMP_BOOST"), + PotionEffectType::Nausea { .. } => f.write_str("NAUSEA"), + PotionEffectType::Regeneration { .. } => f.write_str("REGENERATION"), + PotionEffectType::Resistance { .. } => f.write_str("RESISTANCE"), + PotionEffectType::FireResistance { .. } => f.write_str("FIRE_RESISTANCE"), + PotionEffectType::WaterBreathing { .. } => f.write_str("WATER_BREATHING"), + PotionEffectType::Invisibility { .. } => f.write_str("INVISIBILITY"), + PotionEffectType::Blindness { .. } => f.write_str("BLINDNESS"), + PotionEffectType::NightVision { .. } => f.write_str("NIGHT_VISION"), + PotionEffectType::Hunger { .. } => f.write_str("HUNGER"), + PotionEffectType::Weakness { .. } => f.write_str("WEAKNESS"), + PotionEffectType::Poison { .. } => f.write_str("POISON"), + PotionEffectType::Wither { .. } => f.write_str("WITHER"), + PotionEffectType::HealthBoost { .. } => f.write_str("HEALTH_BOOST"), + PotionEffectType::Absorption { .. } => f.write_str("ABSORPTION"), + PotionEffectType::Saturation { .. } => f.write_str("SATURATION"), + PotionEffectType::Glowing { .. } => f.write_str("GLOWING"), + PotionEffectType::Levitation { .. } => f.write_str("LEVITATION"), + PotionEffectType::Luck { .. } => f.write_str("LUCK"), + PotionEffectType::Unluck { .. } => f.write_str("UNLUCK"), + PotionEffectType::SlowFalling { .. } => f.write_str("SLOW_FALLING"), + PotionEffectType::ConduitPower { .. } => f.write_str("CONDUIT_POWER"), + PotionEffectType::DolphinsGrace { .. } => f.write_str("DOLPHINS_GRACE"), + PotionEffectType::BadOmen { .. } => f.write_str("BAD_OMEN"), + PotionEffectType::HeroOfTheVillage { .. } => f.write_str("HERO_OF_THE_VILLAGE"), + PotionEffectType::Darkness { .. } => f.write_str("DARKNESS"), + PotionEffectType::TrialOmen { .. } => f.write_str("TRIAL_OMEN"), + PotionEffectType::RaidOmen { .. } => f.write_str("RAID_OMEN"), + PotionEffectType::WindCharged { .. } => f.write_str("WIND_CHARGED"), + PotionEffectType::Weaving { .. } => f.write_str("WEAVING"), + PotionEffectType::Oozing { .. } => f.write_str("OOZING"), + PotionEffectType::Infested { .. } => f.write_str("INFESTED"), + } + } +} +impl<'mc> std::ops::Deref for PotionEffectType<'mc> { + type Target = PotionEffectTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + PotionEffectType::Speed { inner } => inner, + PotionEffectType::Slowness { inner } => inner, + PotionEffectType::Haste { inner } => inner, + PotionEffectType::MiningFatigue { inner } => inner, + PotionEffectType::Strength { inner } => inner, + PotionEffectType::InstantHealth { inner } => inner, + PotionEffectType::InstantDamage { inner } => inner, + PotionEffectType::JumpBoost { inner } => inner, + PotionEffectType::Nausea { inner } => inner, + PotionEffectType::Regeneration { inner } => inner, + PotionEffectType::Resistance { inner } => inner, + PotionEffectType::FireResistance { inner } => inner, + PotionEffectType::WaterBreathing { inner } => inner, + PotionEffectType::Invisibility { inner } => inner, + PotionEffectType::Blindness { inner } => inner, + PotionEffectType::NightVision { inner } => inner, + PotionEffectType::Hunger { inner } => inner, + PotionEffectType::Weakness { inner } => inner, + PotionEffectType::Poison { inner } => inner, + PotionEffectType::Wither { inner } => inner, + PotionEffectType::HealthBoost { inner } => inner, + PotionEffectType::Absorption { inner } => inner, + PotionEffectType::Saturation { inner } => inner, + PotionEffectType::Glowing { inner } => inner, + PotionEffectType::Levitation { inner } => inner, + PotionEffectType::Luck { inner } => inner, + PotionEffectType::Unluck { inner } => inner, + PotionEffectType::SlowFalling { inner } => inner, + PotionEffectType::ConduitPower { inner } => inner, + PotionEffectType::DolphinsGrace { inner } => inner, + PotionEffectType::BadOmen { inner } => inner, + PotionEffectType::HeroOfTheVillage { inner } => inner, + PotionEffectType::Darkness { inner } => inner, + PotionEffectType::TrialOmen { inner } => inner, + PotionEffectType::RaidOmen { inner } => inner, + PotionEffectType::WindCharged { inner } => inner, + PotionEffectType::Weaving { inner } => inner, + PotionEffectType::Oozing { inner } => inner, + PotionEffectType::Infested { inner } => inner, + } + } +} + +impl<'mc> PotionEffectType<'mc> { + pub fn value_of( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + arg0: impl Into, + ) -> Result, Box> { + let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); + let cls = env.find_class("org/bukkit/potion/PotionEffectType"); + let cls = env.translate_error_with_class(cls)?; + let res = env.call_static_method( + cls, + "valueOf", + "(Ljava/lang/String;)Lorg/bukkit/potion/PotionEffectType;", + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = env.translate_error(res)?; + let obj = res.l()?; + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "SPEED" => Ok(PotionEffectType::Speed { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "SLOWNESS" => Ok(PotionEffectType::Slowness { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "HASTE" => Ok(PotionEffectType::Haste { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "MINING_FATIGUE" => Ok(PotionEffectType::MiningFatigue { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "STRENGTH" => Ok(PotionEffectType::Strength { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "INSTANT_HEALTH" => Ok(PotionEffectType::InstantHealth { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "INSTANT_DAMAGE" => Ok(PotionEffectType::InstantDamage { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "JUMP_BOOST" => Ok(PotionEffectType::JumpBoost { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "NAUSEA" => Ok(PotionEffectType::Nausea { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "REGENERATION" => Ok(PotionEffectType::Regeneration { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "RESISTANCE" => Ok(PotionEffectType::Resistance { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "FIRE_RESISTANCE" => Ok(PotionEffectType::FireResistance { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "WATER_BREATHING" => Ok(PotionEffectType::WaterBreathing { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "INVISIBILITY" => Ok(PotionEffectType::Invisibility { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "BLINDNESS" => Ok(PotionEffectType::Blindness { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "NIGHT_VISION" => Ok(PotionEffectType::NightVision { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "HUNGER" => Ok(PotionEffectType::Hunger { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "WEAKNESS" => Ok(PotionEffectType::Weakness { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "POISON" => Ok(PotionEffectType::Poison { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "WITHER" => Ok(PotionEffectType::Wither { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "HEALTH_BOOST" => Ok(PotionEffectType::HealthBoost { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "ABSORPTION" => Ok(PotionEffectType::Absorption { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "SATURATION" => Ok(PotionEffectType::Saturation { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "GLOWING" => Ok(PotionEffectType::Glowing { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "LEVITATION" => Ok(PotionEffectType::Levitation { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "LUCK" => Ok(PotionEffectType::Luck { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "UNLUCK" => Ok(PotionEffectType::Unluck { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "SLOW_FALLING" => Ok(PotionEffectType::SlowFalling { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "CONDUIT_POWER" => Ok(PotionEffectType::ConduitPower { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "DOLPHINS_GRACE" => Ok(PotionEffectType::DolphinsGrace { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "BAD_OMEN" => Ok(PotionEffectType::BadOmen { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "HERO_OF_THE_VILLAGE" => Ok(PotionEffectType::HeroOfTheVillage { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "DARKNESS" => Ok(PotionEffectType::Darkness { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "TRIAL_OMEN" => Ok(PotionEffectType::TrialOmen { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "RAID_OMEN" => Ok(PotionEffectType::RaidOmen { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "WIND_CHARGED" => Ok(PotionEffectType::WindCharged { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "WEAVING" => Ok(PotionEffectType::Weaving { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "OOZING" => Ok(PotionEffectType::Oozing { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "INFESTED" => Ok(PotionEffectType::Infested { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } +} + +#[repr(C)] +pub struct PotionEffectTypeStruct<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PotionEffectType<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + match self { + Self::Speed { inner } => inner.0.clone(), + Self::Slowness { inner } => inner.0.clone(), + Self::Haste { inner } => inner.0.clone(), + Self::MiningFatigue { inner } => inner.0.clone(), + Self::Strength { inner } => inner.0.clone(), + Self::InstantHealth { inner } => inner.0.clone(), + Self::InstantDamage { inner } => inner.0.clone(), + Self::JumpBoost { inner } => inner.0.clone(), + Self::Nausea { inner } => inner.0.clone(), + Self::Regeneration { inner } => inner.0.clone(), + Self::Resistance { inner } => inner.0.clone(), + Self::FireResistance { inner } => inner.0.clone(), + Self::WaterBreathing { inner } => inner.0.clone(), + Self::Invisibility { inner } => inner.0.clone(), + Self::Blindness { inner } => inner.0.clone(), + Self::NightVision { inner } => inner.0.clone(), + Self::Hunger { inner } => inner.0.clone(), + Self::Weakness { inner } => inner.0.clone(), + Self::Poison { inner } => inner.0.clone(), + Self::Wither { inner } => inner.0.clone(), + Self::HealthBoost { inner } => inner.0.clone(), + Self::Absorption { inner } => inner.0.clone(), + Self::Saturation { inner } => inner.0.clone(), + Self::Glowing { inner } => inner.0.clone(), + Self::Levitation { inner } => inner.0.clone(), + Self::Luck { inner } => inner.0.clone(), + Self::Unluck { inner } => inner.0.clone(), + Self::SlowFalling { inner } => inner.0.clone(), + Self::ConduitPower { inner } => inner.0.clone(), + Self::DolphinsGrace { inner } => inner.0.clone(), + Self::BadOmen { inner } => inner.0.clone(), + Self::HeroOfTheVillage { inner } => inner.0.clone(), + Self::Darkness { inner } => inner.0.clone(), + Self::TrialOmen { inner } => inner.0.clone(), + Self::RaidOmen { inner } => inner.0.clone(), + Self::WindCharged { inner } => inner.0.clone(), + Self::Weaving { inner } => inner.0.clone(), + Self::Oozing { inner } => inner.0.clone(), + Self::Infested { inner } => inner.0.clone(), + } + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + match self { + Self::Speed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Slowness { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Haste { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::MiningFatigue { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Strength { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::InstantHealth { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::InstantDamage { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::JumpBoost { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Nausea { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Regeneration { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Resistance { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::FireResistance { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::WaterBreathing { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Invisibility { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Blindness { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::NightVision { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Hunger { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Weakness { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Poison { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Wither { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::HealthBoost { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Absorption { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Saturation { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Glowing { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Levitation { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Luck { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Unluck { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SlowFalling { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ConduitPower { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DolphinsGrace { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::BadOmen { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::HeroOfTheVillage { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Darkness { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::TrialOmen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::RaidOmen { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::WindCharged { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Weaving { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Oozing { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Infested { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } + } +} +impl<'mc> JNIInstantiatable<'mc> for PotionEffectType<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate PotionEffectType from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/potion/PotionEffectType")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PotionEffectType object, got {}", + name + ) + .into()) + } else { + let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); + let variant = env.translate_error(variant)?; + let variant_str = env + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "SPEED" => Ok(PotionEffectType::Speed { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "SLOWNESS" => Ok(PotionEffectType::Slowness { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "HASTE" => Ok(PotionEffectType::Haste { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "MINING_FATIGUE" => Ok(PotionEffectType::MiningFatigue { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "STRENGTH" => Ok(PotionEffectType::Strength { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "INSTANT_HEALTH" => Ok(PotionEffectType::InstantHealth { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "INSTANT_DAMAGE" => Ok(PotionEffectType::InstantDamage { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "JUMP_BOOST" => Ok(PotionEffectType::JumpBoost { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "NAUSEA" => Ok(PotionEffectType::Nausea { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "REGENERATION" => Ok(PotionEffectType::Regeneration { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "RESISTANCE" => Ok(PotionEffectType::Resistance { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "FIRE_RESISTANCE" => Ok(PotionEffectType::FireResistance { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "WATER_BREATHING" => Ok(PotionEffectType::WaterBreathing { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "INVISIBILITY" => Ok(PotionEffectType::Invisibility { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "BLINDNESS" => Ok(PotionEffectType::Blindness { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "NIGHT_VISION" => Ok(PotionEffectType::NightVision { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "HUNGER" => Ok(PotionEffectType::Hunger { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "WEAKNESS" => Ok(PotionEffectType::Weakness { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "POISON" => Ok(PotionEffectType::Poison { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "WITHER" => Ok(PotionEffectType::Wither { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "HEALTH_BOOST" => Ok(PotionEffectType::HealthBoost { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "ABSORPTION" => Ok(PotionEffectType::Absorption { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "SATURATION" => Ok(PotionEffectType::Saturation { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "GLOWING" => Ok(PotionEffectType::Glowing { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "LEVITATION" => Ok(PotionEffectType::Levitation { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "LUCK" => Ok(PotionEffectType::Luck { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "UNLUCK" => Ok(PotionEffectType::Unluck { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "SLOW_FALLING" => Ok(PotionEffectType::SlowFalling { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "CONDUIT_POWER" => Ok(PotionEffectType::ConduitPower { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "DOLPHINS_GRACE" => Ok(PotionEffectType::DolphinsGrace { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "BAD_OMEN" => Ok(PotionEffectType::BadOmen { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "HERO_OF_THE_VILLAGE" => Ok(PotionEffectType::HeroOfTheVillage { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "DARKNESS" => Ok(PotionEffectType::Darkness { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "TRIAL_OMEN" => Ok(PotionEffectType::TrialOmen { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "RAID_OMEN" => Ok(PotionEffectType::RaidOmen { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "WIND_CHARGED" => Ok(PotionEffectType::WindCharged { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "WEAVING" => Ok(PotionEffectType::Weaving { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "OOZING" => Ok(PotionEffectType::Oozing { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + "INFESTED" => Ok(PotionEffectType::Infested { + inner: PotionEffectTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), + } + } + } +} + +impl<'mc> JNIRaw<'mc> for PotionEffectTypeStruct<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PotionEffectTypeStruct<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate PotionEffectTypeStruct from null object." + ) + .into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/potion/PotionEffectType")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a PotionEffectTypeStruct object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> PotionEffectTypeStruct<'mc> { + #[deprecated] + /// Gets the PotionEffectType at the specified key + pub fn get_by_key( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + key: impl Into>, + ) -> Result>, Box> { + let sig = String::from("(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/potion/PotionEffectType;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(key.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/potion/PotionEffectType"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getByKey", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::potion::PotionEffectType::from_raw(&jni, obj)?)) + } + #[deprecated] + /// Gets the effect type specified by the unique id. + pub fn get_by_id( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + id: i32, + ) -> Result>, Box> { + let sig = String::from("(I)Lorg/bukkit/potion/PotionEffectType;"); + let val_1 = jni::objects::JValueGen::Int(id); + let cls = jni.find_class("org/bukkit/potion/PotionEffectType"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getById", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::potion::PotionEffectType::from_raw(&jni, obj)?)) + } + #[deprecated] + /// Gets the effect type specified by the given name. + pub fn get_by_name( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + name: impl Into, + ) -> Result>, Box> { + let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/potion/PotionEffectType;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(name.into())?, + )); + let cls = jni.find_class("org/bukkit/potion/PotionEffectType"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getByName", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + let obj = res.l()?; + Ok(Some(crate::potion::PotionEffectType::from_raw(&jni, obj)?)) + } + #[deprecated] + + pub fn values( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/potion/PotionEffectType;"); + let cls = jni.find_class("org/bukkit/potion/PotionEffectType"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::potion::PotionEffectType::from_raw(&jni, obj) + } + /// Return the namespaced identifier for this object. + pub fn key(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/NamespacedKey;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get the translation key, suitable for use in a translation component. + pub fn translation_key(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getTranslationKey", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct PotionEffect<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for PotionEffect<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for PotionEffect<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate PotionEffect from null object.").into()); } let (valid, name) = env.validate_name(&obj, "org/bukkit/potion/PotionEffect")?; if !valid { @@ -649,132 +1944,130 @@ impl<'mc> Into {} -impl<'mc> std::fmt::Display for PotionEffectTypeCategory<'mc> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} - } -} - -impl<'mc> PotionEffectTypeCategory<'mc> { - pub fn value_of( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - arg0: impl Into, - ) -> Result, Box> { - let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/potion/PotionEffectTypeCategory"); - let cls = env.translate_error_with_class(cls)?; - let res = env.call_static_method( - cls, - "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/potion/PotionEffectTypeCategory;", - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = env.translate_error(res)?; - let obj = res.l()?; - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } - } -} - #[repr(C)] -pub struct PotionEffectTypeCategoryStruct<'mc>( +pub struct PotionData<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PotionEffectTypeCategory<'mc> { +impl<'mc> JNIRaw<'mc> for PotionData<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + self.0.clone() } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PotionEffectTypeCategory<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PotionData<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PotionEffectTypeCategory from null object." - ) - .into()); + return Err(eyre::eyre!("Tried to instantiate PotionData from null object.").into()); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/potion/PotionEffectTypeCategory")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/potion/PotionData")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PotionEffectTypeCategory object, got {}", + "Invalid argument passed. Expected a PotionData object, got {}", name ) .into()) } else { - let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); - let variant = env.translate_error(variant)?; - let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), - } + Ok(Self(env.clone(), obj)) } } } -impl<'mc> JNIRaw<'mc> for PotionEffectTypeCategoryStruct<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PotionEffectTypeCategoryStruct<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PotionEffectTypeCategoryStruct from null object." - ) - .into()); +impl<'mc> PotionData<'mc> { + /// Instantiates a final PotionData object to contain information about a + /// Potion + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + val_type: impl Into>, + extended: std::option::Option, + upgraded: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/potion/PotionType;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = extended { + sig += "Z"; + let val_2 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_2); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/potion/PotionEffectTypeCategory")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PotionEffectTypeCategoryStruct object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) + if let Some(a) = upgraded { + sig += "Z"; + let val_3 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_3); } + sig += ")V"; + let cls = jni.find_class("org/bukkit/potion/PotionData"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::potion::PotionData::from_raw(&jni, res) + } + /// Gets the type of the potion, Type matches up with each kind of craftable + /// potion + pub fn get_type(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/potion/PotionType;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::potion::PotionType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Checks if the potion is in an upgraded state. This refers to whether or + /// not the potion is Tier 2, such as Potion of Fire Resistance II. + pub fn is_upgraded(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isUpgraded", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Checks if the potion is in an extended state. This refers to the extended + /// duration potions + pub fn is_extended(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isExtended", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } -} -impl<'mc> PotionEffectTypeCategoryStruct<'mc> { - pub fn values( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/potion/PotionEffectTypeCategory;"); - let cls = jni.find_class("org/bukkit/potion/PotionEffectTypeCategory"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::potion::PotionEffectTypeCategory::from_raw(&jni, obj) + pub fn hash_code(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + + pub fn equals( + &self, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(Ljava/lang/Object;)Z"); + let val_1 = jni::objects::JValueGen::Object(obj); + let res = self.jni_ref().call_method( + &self.jni_object(), + "equals", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -782,105 +2075,49 @@ impl<'mc> PotionEffectTypeCategoryStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum PotionEffectType<'mc> { - Speed { inner: PotionEffectTypeStruct<'mc> }, - Slowness { inner: PotionEffectTypeStruct<'mc> }, - Haste { inner: PotionEffectTypeStruct<'mc> }, - MiningFatigue { inner: PotionEffectTypeStruct<'mc> }, - Strength { inner: PotionEffectTypeStruct<'mc> }, - InstantHealth { inner: PotionEffectTypeStruct<'mc> }, - InstantDamage { inner: PotionEffectTypeStruct<'mc> }, - JumpBoost { inner: PotionEffectTypeStruct<'mc> }, - Nausea { inner: PotionEffectTypeStruct<'mc> }, - Regeneration { inner: PotionEffectTypeStruct<'mc> }, - Resistance { inner: PotionEffectTypeStruct<'mc> }, - FireResistance { inner: PotionEffectTypeStruct<'mc> }, - WaterBreathing { inner: PotionEffectTypeStruct<'mc> }, - Invisibility { inner: PotionEffectTypeStruct<'mc> }, - Blindness { inner: PotionEffectTypeStruct<'mc> }, - NightVision { inner: PotionEffectTypeStruct<'mc> }, - Hunger { inner: PotionEffectTypeStruct<'mc> }, - Weakness { inner: PotionEffectTypeStruct<'mc> }, - Poison { inner: PotionEffectTypeStruct<'mc> }, - Wither { inner: PotionEffectTypeStruct<'mc> }, - HealthBoost { inner: PotionEffectTypeStruct<'mc> }, - Absorption { inner: PotionEffectTypeStruct<'mc> }, - Saturation { inner: PotionEffectTypeStruct<'mc> }, - Glowing { inner: PotionEffectTypeStruct<'mc> }, - Levitation { inner: PotionEffectTypeStruct<'mc> }, - Luck { inner: PotionEffectTypeStruct<'mc> }, - Unluck { inner: PotionEffectTypeStruct<'mc> }, - SlowFalling { inner: PotionEffectTypeStruct<'mc> }, - ConduitPower { inner: PotionEffectTypeStruct<'mc> }, - DolphinsGrace { inner: PotionEffectTypeStruct<'mc> }, - BadOmen { inner: PotionEffectTypeStruct<'mc> }, - HeroOfTheVillage { inner: PotionEffectTypeStruct<'mc> }, - Darkness { inner: PotionEffectTypeStruct<'mc> }, - TrialOmen { inner: PotionEffectTypeStruct<'mc> }, - RaidOmen { inner: PotionEffectTypeStruct<'mc> }, - WindCharged { inner: PotionEffectTypeStruct<'mc> }, - Weaving { inner: PotionEffectTypeStruct<'mc> }, - Oozing { inner: PotionEffectTypeStruct<'mc> }, - Infested { inner: PotionEffectTypeStruct<'mc> }, +pub enum PotionEffectTypeCategory<'mc> { + Beneficial { + inner: PotionEffectTypeCategoryStruct<'mc>, + }, + Harmful { + inner: PotionEffectTypeCategoryStruct<'mc>, + }, + Neutral { + inner: PotionEffectTypeCategoryStruct<'mc>, + }, } -impl<'mc> std::fmt::Display for PotionEffectType<'mc> { +impl<'mc> std::fmt::Display for PotionEffectTypeCategory<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - PotionEffectType::Speed { .. } => f.write_str("SPEED"), - PotionEffectType::Slowness { .. } => f.write_str("SLOWNESS"), - PotionEffectType::Haste { .. } => f.write_str("HASTE"), - PotionEffectType::MiningFatigue { .. } => f.write_str("MINING_FATIGUE"), - PotionEffectType::Strength { .. } => f.write_str("STRENGTH"), - PotionEffectType::InstantHealth { .. } => f.write_str("INSTANT_HEALTH"), - PotionEffectType::InstantDamage { .. } => f.write_str("INSTANT_DAMAGE"), - PotionEffectType::JumpBoost { .. } => f.write_str("JUMP_BOOST"), - PotionEffectType::Nausea { .. } => f.write_str("NAUSEA"), - PotionEffectType::Regeneration { .. } => f.write_str("REGENERATION"), - PotionEffectType::Resistance { .. } => f.write_str("RESISTANCE"), - PotionEffectType::FireResistance { .. } => f.write_str("FIRE_RESISTANCE"), - PotionEffectType::WaterBreathing { .. } => f.write_str("WATER_BREATHING"), - PotionEffectType::Invisibility { .. } => f.write_str("INVISIBILITY"), - PotionEffectType::Blindness { .. } => f.write_str("BLINDNESS"), - PotionEffectType::NightVision { .. } => f.write_str("NIGHT_VISION"), - PotionEffectType::Hunger { .. } => f.write_str("HUNGER"), - PotionEffectType::Weakness { .. } => f.write_str("WEAKNESS"), - PotionEffectType::Poison { .. } => f.write_str("POISON"), - PotionEffectType::Wither { .. } => f.write_str("WITHER"), - PotionEffectType::HealthBoost { .. } => f.write_str("HEALTH_BOOST"), - PotionEffectType::Absorption { .. } => f.write_str("ABSORPTION"), - PotionEffectType::Saturation { .. } => f.write_str("SATURATION"), - PotionEffectType::Glowing { .. } => f.write_str("GLOWING"), - PotionEffectType::Levitation { .. } => f.write_str("LEVITATION"), - PotionEffectType::Luck { .. } => f.write_str("LUCK"), - PotionEffectType::Unluck { .. } => f.write_str("UNLUCK"), - PotionEffectType::SlowFalling { .. } => f.write_str("SLOW_FALLING"), - PotionEffectType::ConduitPower { .. } => f.write_str("CONDUIT_POWER"), - PotionEffectType::DolphinsGrace { .. } => f.write_str("DOLPHINS_GRACE"), - PotionEffectType::BadOmen { .. } => f.write_str("BAD_OMEN"), - PotionEffectType::HeroOfTheVillage { .. } => f.write_str("HERO_OF_THE_VILLAGE"), - PotionEffectType::Darkness { .. } => f.write_str("DARKNESS"), - PotionEffectType::TrialOmen { .. } => f.write_str("TRIAL_OMEN"), - PotionEffectType::RaidOmen { .. } => f.write_str("RAID_OMEN"), - PotionEffectType::WindCharged { .. } => f.write_str("WIND_CHARGED"), - PotionEffectType::Weaving { .. } => f.write_str("WEAVING"), - PotionEffectType::Oozing { .. } => f.write_str("OOZING"), - PotionEffectType::Infested { .. } => f.write_str("INFESTED"), + PotionEffectTypeCategory::Beneficial { .. } => f.write_str("BENEFICIAL"), + PotionEffectTypeCategory::Harmful { .. } => f.write_str("HARMFUL"), + PotionEffectTypeCategory::Neutral { .. } => f.write_str("NEUTRAL"), + } + } +} +impl<'mc> std::ops::Deref for PotionEffectTypeCategory<'mc> { + type Target = PotionEffectTypeCategoryStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + PotionEffectTypeCategory::Beneficial { inner } => inner, + PotionEffectTypeCategory::Harmful { inner } => inner, + PotionEffectTypeCategory::Neutral { inner } => inner, } } } -impl<'mc> PotionEffectType<'mc> { +impl<'mc> PotionEffectTypeCategory<'mc> { pub fn value_of( env: &blackboxmc_general::SharedJNIEnv<'mc>, arg0: impl Into, - ) -> Result, Box> { + ) -> Result, Box> { let val_1 = jni::objects::JObject::from(env.new_string(arg0.into())?); - let cls = env.find_class("org/bukkit/potion/PotionEffectType"); + let cls = env.find_class("org/bukkit/potion/PotionEffectTypeCategory"); let cls = env.translate_error_with_class(cls)?; let res = env.call_static_method( cls, "valueOf", - "(Ljava/lang/String;)Lorg/bukkit/potion/PotionEffectType;", + "(Ljava/lang/String;)Lorg/bukkit/potion/PotionEffectTypeCategory;", vec![jni::objects::JValueGen::from(val_1)], ); let res = env.translate_error(res)?; @@ -888,126 +2125,18 @@ impl<'mc> PotionEffectType<'mc> { let variant = env.call_method(&obj, "toString", "()Ljava/lang/String;", vec![]); let variant = env.translate_error(variant)?; let variant_str = env - .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? - .to_string_lossy() - .to_string(); - match variant_str.as_str() { - "SPEED" => Ok(PotionEffectType::Speed { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "SLOWNESS" => Ok(PotionEffectType::Slowness { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "HASTE" => Ok(PotionEffectType::Haste { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "MINING_FATIGUE" => Ok(PotionEffectType::MiningFatigue { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "STRENGTH" => Ok(PotionEffectType::Strength { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "INSTANT_HEALTH" => Ok(PotionEffectType::InstantHealth { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "INSTANT_DAMAGE" => Ok(PotionEffectType::InstantDamage { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "JUMP_BOOST" => Ok(PotionEffectType::JumpBoost { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "NAUSEA" => Ok(PotionEffectType::Nausea { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "REGENERATION" => Ok(PotionEffectType::Regeneration { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "RESISTANCE" => Ok(PotionEffectType::Resistance { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "FIRE_RESISTANCE" => Ok(PotionEffectType::FireResistance { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "WATER_BREATHING" => Ok(PotionEffectType::WaterBreathing { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "INVISIBILITY" => Ok(PotionEffectType::Invisibility { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "BLINDNESS" => Ok(PotionEffectType::Blindness { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "NIGHT_VISION" => Ok(PotionEffectType::NightVision { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "HUNGER" => Ok(PotionEffectType::Hunger { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "WEAKNESS" => Ok(PotionEffectType::Weakness { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "POISON" => Ok(PotionEffectType::Poison { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "WITHER" => Ok(PotionEffectType::Wither { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "HEALTH_BOOST" => Ok(PotionEffectType::HealthBoost { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "ABSORPTION" => Ok(PotionEffectType::Absorption { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "SATURATION" => Ok(PotionEffectType::Saturation { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "GLOWING" => Ok(PotionEffectType::Glowing { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "LEVITATION" => Ok(PotionEffectType::Levitation { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "LUCK" => Ok(PotionEffectType::Luck { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "UNLUCK" => Ok(PotionEffectType::Unluck { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "SLOW_FALLING" => Ok(PotionEffectType::SlowFalling { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "CONDUIT_POWER" => Ok(PotionEffectType::ConduitPower { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "DOLPHINS_GRACE" => Ok(PotionEffectType::DolphinsGrace { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "BAD_OMEN" => Ok(PotionEffectType::BadOmen { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "HERO_OF_THE_VILLAGE" => Ok(PotionEffectType::HeroOfTheVillage { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "DARKNESS" => Ok(PotionEffectType::Darkness { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "TRIAL_OMEN" => Ok(PotionEffectType::TrialOmen { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "RAID_OMEN" => Ok(PotionEffectType::RaidOmen { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "WIND_CHARGED" => Ok(PotionEffectType::WindCharged { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "WEAVING" => Ok(PotionEffectType::Weaving { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, + .get_string(unsafe { &jni::objects::JString::from_raw(variant.as_jni().l) })? + .to_string_lossy() + .to_string(); + match variant_str.as_str() { + "BENEFICIAL" => Ok(PotionEffectTypeCategory::Beneficial { + inner: PotionEffectTypeCategoryStruct::from_raw(env, obj)?, }), - "OOZING" => Ok(PotionEffectType::Oozing { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, + "HARMFUL" => Ok(PotionEffectTypeCategory::Harmful { + inner: PotionEffectTypeCategoryStruct::from_raw(env, obj)?, }), - "INFESTED" => Ok(PotionEffectType::Infested { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, + "NEUTRAL" => Ok(PotionEffectTypeCategory::Neutral { + inner: PotionEffectTypeCategoryStruct::from_raw(env, obj)?, }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), @@ -1016,155 +2145,45 @@ impl<'mc> PotionEffectType<'mc> { } #[repr(C)] -pub struct PotionEffectTypeStruct<'mc>( +pub struct PotionEffectTypeCategoryStruct<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PotionEffectType<'mc> { +impl<'mc> JNIRaw<'mc> for PotionEffectTypeCategory<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { match self { - Self::Speed { inner } => inner.0.clone(), - Self::Slowness { inner } => inner.0.clone(), - Self::Haste { inner } => inner.0.clone(), - Self::MiningFatigue { inner } => inner.0.clone(), - Self::Strength { inner } => inner.0.clone(), - Self::InstantHealth { inner } => inner.0.clone(), - Self::InstantDamage { inner } => inner.0.clone(), - Self::JumpBoost { inner } => inner.0.clone(), - Self::Nausea { inner } => inner.0.clone(), - Self::Regeneration { inner } => inner.0.clone(), - Self::Resistance { inner } => inner.0.clone(), - Self::FireResistance { inner } => inner.0.clone(), - Self::WaterBreathing { inner } => inner.0.clone(), - Self::Invisibility { inner } => inner.0.clone(), - Self::Blindness { inner } => inner.0.clone(), - Self::NightVision { inner } => inner.0.clone(), - Self::Hunger { inner } => inner.0.clone(), - Self::Weakness { inner } => inner.0.clone(), - Self::Poison { inner } => inner.0.clone(), - Self::Wither { inner } => inner.0.clone(), - Self::HealthBoost { inner } => inner.0.clone(), - Self::Absorption { inner } => inner.0.clone(), - Self::Saturation { inner } => inner.0.clone(), - Self::Glowing { inner } => inner.0.clone(), - Self::Levitation { inner } => inner.0.clone(), - Self::Luck { inner } => inner.0.clone(), - Self::Unluck { inner } => inner.0.clone(), - Self::SlowFalling { inner } => inner.0.clone(), - Self::ConduitPower { inner } => inner.0.clone(), - Self::DolphinsGrace { inner } => inner.0.clone(), - Self::BadOmen { inner } => inner.0.clone(), - Self::HeroOfTheVillage { inner } => inner.0.clone(), - Self::Darkness { inner } => inner.0.clone(), - Self::TrialOmen { inner } => inner.0.clone(), - Self::RaidOmen { inner } => inner.0.clone(), - Self::WindCharged { inner } => inner.0.clone(), - Self::Weaving { inner } => inner.0.clone(), - Self::Oozing { inner } => inner.0.clone(), - Self::Infested { inner } => inner.0.clone(), + Self::Beneficial { inner } => inner.0.clone(), + Self::Harmful { inner } => inner.0.clone(), + Self::Neutral { inner } => inner.0.clone(), } } fn jni_object(&self) -> jni::objects::JObject<'mc> { match self { - Self::Speed { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::Slowness { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::Haste { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::MiningFatigue { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::Strength { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::InstantHealth { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::InstantDamage { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::JumpBoost { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::Nausea { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::Regeneration { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::Resistance { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::FireResistance { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::WaterBreathing { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::Invisibility { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::Blindness { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::NightVision { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::Hunger { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::Weakness { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::Poison { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::Wither { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::HealthBoost { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::Absorption { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::Saturation { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::Glowing { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::Levitation { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::Luck { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::Unluck { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::SlowFalling { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::ConduitPower { inner } => unsafe { + Self::Beneficial { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::DolphinsGrace { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::BadOmen { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::HeroOfTheVillage { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::Darkness { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::TrialOmen { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::RaidOmen { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::WindCharged { inner } => unsafe { - jni::objects::JObject::from_raw(inner.1.clone()) - }, - Self::Weaving { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::Oozing { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, - Self::Infested { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Harmful { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Neutral { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, } } } -impl<'mc> JNIInstantiatable<'mc> for PotionEffectType<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PotionEffectTypeCategory<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate PotionEffectType from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate PotionEffectTypeCategory from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/potion/PotionEffectType")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/potion/PotionEffectTypeCategory")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PotionEffectType object, got {}", + "Invalid argument passed. Expected a PotionEffectTypeCategory object, got {}", name ) .into()) @@ -1176,122 +2195,14 @@ impl<'mc> JNIInstantiatable<'mc> for PotionEffectType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { - "SPEED" => Ok(PotionEffectType::Speed { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "SLOWNESS" => Ok(PotionEffectType::Slowness { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "HASTE" => Ok(PotionEffectType::Haste { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "MINING_FATIGUE" => Ok(PotionEffectType::MiningFatigue { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "STRENGTH" => Ok(PotionEffectType::Strength { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "INSTANT_HEALTH" => Ok(PotionEffectType::InstantHealth { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "INSTANT_DAMAGE" => Ok(PotionEffectType::InstantDamage { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "JUMP_BOOST" => Ok(PotionEffectType::JumpBoost { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "NAUSEA" => Ok(PotionEffectType::Nausea { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "REGENERATION" => Ok(PotionEffectType::Regeneration { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "RESISTANCE" => Ok(PotionEffectType::Resistance { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "FIRE_RESISTANCE" => Ok(PotionEffectType::FireResistance { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "WATER_BREATHING" => Ok(PotionEffectType::WaterBreathing { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "INVISIBILITY" => Ok(PotionEffectType::Invisibility { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "BLINDNESS" => Ok(PotionEffectType::Blindness { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "NIGHT_VISION" => Ok(PotionEffectType::NightVision { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "HUNGER" => Ok(PotionEffectType::Hunger { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "WEAKNESS" => Ok(PotionEffectType::Weakness { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "POISON" => Ok(PotionEffectType::Poison { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "WITHER" => Ok(PotionEffectType::Wither { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "HEALTH_BOOST" => Ok(PotionEffectType::HealthBoost { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "ABSORPTION" => Ok(PotionEffectType::Absorption { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "SATURATION" => Ok(PotionEffectType::Saturation { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "GLOWING" => Ok(PotionEffectType::Glowing { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "LEVITATION" => Ok(PotionEffectType::Levitation { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "LUCK" => Ok(PotionEffectType::Luck { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "UNLUCK" => Ok(PotionEffectType::Unluck { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, + "BENEFICIAL" => Ok(PotionEffectTypeCategory::Beneficial { + inner: PotionEffectTypeCategoryStruct::from_raw(env, obj)?, }), - "SLOW_FALLING" => Ok(PotionEffectType::SlowFalling { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "CONDUIT_POWER" => Ok(PotionEffectType::ConduitPower { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "DOLPHINS_GRACE" => Ok(PotionEffectType::DolphinsGrace { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "BAD_OMEN" => Ok(PotionEffectType::BadOmen { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "HERO_OF_THE_VILLAGE" => Ok(PotionEffectType::HeroOfTheVillage { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "DARKNESS" => Ok(PotionEffectType::Darkness { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "TRIAL_OMEN" => Ok(PotionEffectType::TrialOmen { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "RAID_OMEN" => Ok(PotionEffectType::RaidOmen { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "WIND_CHARGED" => Ok(PotionEffectType::WindCharged { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "WEAVING" => Ok(PotionEffectType::Weaving { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, - }), - "OOZING" => Ok(PotionEffectType::Oozing { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, + "HARMFUL" => Ok(PotionEffectTypeCategory::Harmful { + inner: PotionEffectTypeCategoryStruct::from_raw(env, obj)?, }), - "INFESTED" => Ok(PotionEffectType::Infested { - inner: PotionEffectTypeStruct::from_raw(env, obj)?, + "NEUTRAL" => Ok(PotionEffectTypeCategory::Neutral { + inner: PotionEffectTypeCategoryStruct::from_raw(env, obj)?, }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } @@ -1299,7 +2210,7 @@ impl<'mc> JNIInstantiatable<'mc> for PotionEffectType<'mc> { } } -impl<'mc> JNIRaw<'mc> for PotionEffectTypeStruct<'mc> { +impl<'mc> JNIRaw<'mc> for PotionEffectTypeCategoryStruct<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1307,21 +2218,22 @@ impl<'mc> JNIRaw<'mc> for PotionEffectTypeStruct<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PotionEffectTypeStruct<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PotionEffectTypeCategoryStruct<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate PotionEffectTypeStruct from null object." + "Tried to instantiate PotionEffectTypeCategoryStruct from null object." ) .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/potion/PotionEffectType")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/potion/PotionEffectTypeCategory")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PotionEffectTypeStruct object, got {}", + "Invalid argument passed. Expected a PotionEffectTypeCategoryStruct object, got {}", name ) .into()) @@ -1331,119 +2243,17 @@ impl<'mc> JNIInstantiatable<'mc> for PotionEffectTypeStruct<'mc> { } } -impl<'mc> PotionEffectTypeStruct<'mc> { - #[deprecated] - /// Gets the PotionEffectType at the specified key - pub fn get_by_key( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - key: impl Into>, - ) -> Result>, Box> { - let sig = String::from("(Lorg/bukkit/NamespacedKey;)Lorg/bukkit/potion/PotionEffectType;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(key.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/potion/PotionEffectType"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getByKey", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::potion::PotionEffectType::from_raw(&jni, obj)?)) - } - #[deprecated] - /// Gets the effect type specified by the unique id. - pub fn get_by_id( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - id: i32, - ) -> Result>, Box> { - let sig = String::from("(I)Lorg/bukkit/potion/PotionEffectType;"); - let val_1 = jni::objects::JValueGen::Int(id); - let cls = jni.find_class("org/bukkit/potion/PotionEffectType"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getById", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::potion::PotionEffectType::from_raw(&jni, obj)?)) - } - #[deprecated] - /// Gets the effect type specified by the given name. - pub fn get_by_name( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - name: impl Into, - ) -> Result>, Box> { - let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/potion/PotionEffectType;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(name.into())?, - )); - let cls = jni.find_class("org/bukkit/potion/PotionEffectType"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getByName", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - let obj = res.l()?; - Ok(Some(crate::potion::PotionEffectType::from_raw(&jni, obj)?)) - } - #[deprecated] - +impl<'mc> PotionEffectTypeCategoryStruct<'mc> { pub fn values( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/potion/PotionEffectType;"); - let cls = jni.find_class("org/bukkit/potion/PotionEffectType"); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/potion/PotionEffectTypeCategory;"); + let cls = jni.find_class("org/bukkit/potion/PotionEffectTypeCategory"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method(cls, "values", sig.as_str(), vec![]); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::potion::PotionEffectType::from_raw(&jni, obj) - } - /// Return the namespaced identifier for this object. - pub fn key(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/NamespacedKey;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getKey", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::NamespacedKey::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get the translation key, suitable for use in a translation component. - pub fn translation_key(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getTranslationKey", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + crate::potion::PotionEffectTypeCategory::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1640,21 +2450,21 @@ impl<'mc> PotionEffectTypeWrapper<'mc> { jni: &blackboxmc_general::SharedJNIEnv<'mc>, key: impl Into>, ) -> Result>, Box> { - crate::potion::PotionEffectType::get_by_key(jni, key) + crate::potion::PotionEffectTypeStruct::get_by_key(jni, key) } /// Gets the effect type specified by the unique id. pub fn get_by_id( jni: &blackboxmc_general::SharedJNIEnv<'mc>, id: i32, ) -> Result>, Box> { - crate::potion::PotionEffectType::get_by_id(jni, id) + crate::potion::PotionEffectTypeStruct::get_by_id(jni, id) } /// Gets the effect type specified by the given name. pub fn get_by_name( jni: &blackboxmc_general::SharedJNIEnv<'mc>, name: impl Into, ) -> Result>, Box> { - crate::potion::PotionEffectType::get_by_name(jni, name) + crate::potion::PotionEffectTypeStruct::get_by_name(jni, name) } #[deprecated] @@ -1697,134 +2507,3 @@ impl<'mc> Into> for PotionEffectTypeWrapper .expect("Error converting PotionEffectTypeWrapper into crate::potion::PotionEffectType") } } -#[repr(C)] -pub struct PotionData<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for PotionData<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for PotionData<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate PotionData from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/potion/PotionData")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a PotionData object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> PotionData<'mc> { - /// Instantiates a final PotionData object to contain information about a - /// Potion - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - val_type: impl Into>, - extended: std::option::Option, - upgraded: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/potion/PotionType;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(val_type.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = extended { - sig += "Z"; - let val_2 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_2); - } - if let Some(a) = upgraded { - sig += "Z"; - let val_3 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_3); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/potion/PotionData"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::potion::PotionData::from_raw(&jni, res) - } - /// Gets the type of the potion, Type matches up with each kind of craftable - /// potion - pub fn get_type(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/potion/PotionType;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getType", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::potion::PotionType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Checks if the potion is in an upgraded state. This refers to whether or - /// not the potion is Tier 2, such as Potion of Fire Resistance II. - pub fn is_upgraded(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isUpgraded", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Checks if the potion is in an extended state. This refers to the extended - /// duration potions - pub fn is_extended(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isExtended", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn hash_code(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - - pub fn equals( - &self, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - let sig = String::from("(Ljava/lang/Object;)Z"); - let val_1 = jni::objects::JValueGen::Object(obj); - let res = self.jni_ref().call_method( - &self.jni_object(), - "equals", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} diff --git a/blackboxmc-rs-bukkit/src/profile/mod.rs b/blackboxmc-rs-bukkit/src/profile/mod.rs index bb80fe3..756d8fc 100644 --- a/blackboxmc-rs-bukkit/src/profile/mod.rs +++ b/blackboxmc-rs-bukkit/src/profile/mod.rs @@ -175,10 +175,29 @@ impl<'mc> PlayerTextures<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum PlayerTexturesSkinModel<'mc> {} +pub enum PlayerTexturesSkinModel<'mc> { + Classic { + inner: PlayerTexturesSkinModelStruct<'mc>, + }, + Slim { + inner: PlayerTexturesSkinModelStruct<'mc>, + }, +} impl<'mc> std::fmt::Display for PlayerTexturesSkinModel<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + PlayerTexturesSkinModel::Classic { .. } => f.write_str("CLASSIC"), + PlayerTexturesSkinModel::Slim { .. } => f.write_str("SLIM"), + } + } +} +impl<'mc> std::ops::Deref for PlayerTexturesSkinModel<'mc> { + type Target = PlayerTexturesSkinModelStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + PlayerTexturesSkinModel::Classic { inner } => inner, + PlayerTexturesSkinModel::Slim { inner } => inner, + } } } @@ -205,6 +224,13 @@ impl<'mc> PlayerTexturesSkinModel<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "CLASSIC" => Ok(PlayerTexturesSkinModel::Classic { + inner: PlayerTexturesSkinModelStruct::from_raw(env, obj)?, + }), + "SLIM" => Ok(PlayerTexturesSkinModel::Slim { + inner: PlayerTexturesSkinModelStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -218,10 +244,16 @@ pub struct PlayerTexturesSkinModelStruct<'mc>( impl<'mc> JNIRaw<'mc> for PlayerTexturesSkinModel<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Classic { inner } => inner.0.clone(), + Self::Slim { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Classic { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Slim { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for PlayerTexturesSkinModel<'mc> { @@ -251,6 +283,12 @@ impl<'mc> JNIInstantiatable<'mc> for PlayerTexturesSkinModel<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "CLASSIC" => Ok(PlayerTexturesSkinModel::Classic { + inner: PlayerTexturesSkinModelStruct::from_raw(env, obj)?, + }), + "SLIM" => Ok(PlayerTexturesSkinModel::Slim { + inner: PlayerTexturesSkinModelStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -439,12 +477,10 @@ impl<'mc> PlayerProfile<'mc> { pub fn serialize( &self, ) -> Result, Box> { - let args = Vec::new(); - let mut sig = String::from("("); - sig += ")Ljava/util/Map;"; + let sig = String::from("()Ljava/util/Map;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "serialize", sig.as_str(), args); + .call_method(&self.jni_object(), "serialize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) diff --git a/blackboxmc-rs-bukkit/src/scheduler/mod.rs b/blackboxmc-rs-bukkit/src/scheduler/mod.rs index 32af447..9874737 100644 --- a/blackboxmc-rs-bukkit/src/scheduler/mod.rs +++ b/blackboxmc-rs-bukkit/src/scheduler/mod.rs @@ -3,6 +3,256 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] +pub struct BukkitRunnable<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for BukkitRunnable<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for BukkitRunnable<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate BukkitRunnable from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/scheduler/BukkitRunnable")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BukkitRunnable object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> BukkitRunnable<'mc> { + pub fn from_extendable( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + plugin: &'mc crate::plugin::Plugin, + address: i32, + lib_name: String, + name: String, + ) -> Result> { + let obj = unsafe { plugin.new_extendable(address, "BukkitRunnable", name, lib_name) }?; + Self::from_raw(env, obj) + } + + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()V"); + let cls = jni.find_class("org/bukkit/scheduler/BukkitRunnable"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), vec![]); + let res = jni.translate_error_no_gen(res)?; + crate::scheduler::BukkitRunnable::from_raw(&jni, res) + } + /// Returns true if this task has been cancelled. + pub fn is_cancelled(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Attempts to cancel this task. + pub fn cancel(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "cancel", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Schedules this in the Bukkit scheduler to run on next tick. + pub fn run_task( + &self, + plugin: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;)Lorg/bukkit/scheduler/BukkitTask;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "runTask", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::scheduler::BukkitTask::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Asynchronous tasks should never access any API in Bukkit. Great care + /// should be taken to assure the thread-safety of asynchronous tasks. + /// + /// Schedules this in the Bukkit scheduler to run asynchronously. + pub fn run_task_asynchronously( + &self, + plugin: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;)Lorg/bukkit/scheduler/BukkitTask;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "runTaskAsynchronously", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::scheduler::BukkitTask::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Schedules this to run after the specified number of server ticks. + pub fn run_task_later( + &self, + plugin: impl Into>, + delay: i64, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;J)Lorg/bukkit/scheduler/BukkitTask;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Long(delay); + let res = self.jni_ref().call_method( + &self.jni_object(), + "runTaskLater", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + crate::scheduler::BukkitTask::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Asynchronous tasks should never access any API in Bukkit. Great care + /// should be taken to assure the thread-safety of asynchronous tasks. + /// + /// Schedules this to run asynchronously after the specified number of + /// server ticks. + pub fn run_task_later_asynchronously( + &self, + plugin: impl Into>, + delay: i64, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;J)Lorg/bukkit/scheduler/BukkitTask;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Long(delay); + let res = self.jni_ref().call_method( + &self.jni_object(), + "runTaskLaterAsynchronously", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + crate::scheduler::BukkitTask::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Schedules this to repeatedly run until cancelled, starting after the + /// specified number of server ticks. + pub fn run_task_timer( + &self, + plugin: impl Into>, + delay: i64, + period: i64, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;JJ)Lorg/bukkit/scheduler/BukkitTask;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Long(delay); + let val_3 = jni::objects::JValueGen::Long(period); + let res = self.jni_ref().call_method( + &self.jni_object(), + "runTaskTimer", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = self.jni_ref().translate_error(res)?; + crate::scheduler::BukkitTask::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Asynchronous tasks should never access any API in Bukkit. Great care + /// should be taken to assure the thread-safety of asynchronous tasks. + /// + /// Schedules this to repeatedly run asynchronously until cancelled, + /// starting after the specified number of server ticks. + pub fn run_task_timer_asynchronously( + &self, + plugin: impl Into>, + delay: i64, + period: i64, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/plugin/Plugin;JJ)Lorg/bukkit/scheduler/BukkitTask;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Long(delay); + let val_3 = jni::objects::JValueGen::Long(period); + let res = self.jni_ref().call_method( + &self.jni_object(), + "runTaskTimerAsynchronously", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = self.jni_ref().translate_error(res)?; + crate::scheduler::BukkitTask::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the task id for this runnable. + pub fn task_id(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getTaskId", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] pub struct BukkitTask<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, @@ -527,256 +777,6 @@ impl<'mc> BukkitScheduler<'mc> { } } #[repr(C)] -pub struct BukkitRunnable<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for BukkitRunnable<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for BukkitRunnable<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate BukkitRunnable from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/scheduler/BukkitRunnable")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a BukkitRunnable object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> BukkitRunnable<'mc> { - pub fn from_extendable( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - plugin: &'mc crate::plugin::Plugin, - address: i32, - lib_name: String, - name: String, - ) -> Result> { - let obj = unsafe { plugin.new_extendable(address, "BukkitRunnable", name, lib_name) }?; - Self::from_raw(env, obj) - } - - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/scheduler/BukkitRunnable"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), vec![]); - let res = jni.translate_error_no_gen(res)?; - crate::scheduler::BukkitRunnable::from_raw(&jni, res) - } - /// Returns true if this task has been cancelled. - pub fn is_cancelled(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isCancelled", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Attempts to cancel this task. - pub fn cancel(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "cancel", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Schedules this in the Bukkit scheduler to run on next tick. - pub fn run_task( - &self, - plugin: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;)Lorg/bukkit/scheduler/BukkitTask;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "runTask", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::scheduler::BukkitTask::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Asynchronous tasks should never access any API in Bukkit. Great care - /// should be taken to assure the thread-safety of asynchronous tasks. - /// - /// Schedules this in the Bukkit scheduler to run asynchronously. - pub fn run_task_asynchronously( - &self, - plugin: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;)Lorg/bukkit/scheduler/BukkitTask;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "runTaskAsynchronously", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::scheduler::BukkitTask::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Schedules this to run after the specified number of server ticks. - pub fn run_task_later( - &self, - plugin: impl Into>, - delay: i64, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;J)Lorg/bukkit/scheduler/BukkitTask;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Long(delay); - let res = self.jni_ref().call_method( - &self.jni_object(), - "runTaskLater", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - crate::scheduler::BukkitTask::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Asynchronous tasks should never access any API in Bukkit. Great care - /// should be taken to assure the thread-safety of asynchronous tasks. - /// - /// Schedules this to run asynchronously after the specified number of - /// server ticks. - pub fn run_task_later_asynchronously( - &self, - plugin: impl Into>, - delay: i64, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;J)Lorg/bukkit/scheduler/BukkitTask;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Long(delay); - let res = self.jni_ref().call_method( - &self.jni_object(), - "runTaskLaterAsynchronously", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); - let res = self.jni_ref().translate_error(res)?; - crate::scheduler::BukkitTask::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Schedules this to repeatedly run until cancelled, starting after the - /// specified number of server ticks. - pub fn run_task_timer( - &self, - plugin: impl Into>, - delay: i64, - period: i64, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;JJ)Lorg/bukkit/scheduler/BukkitTask;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Long(delay); - let val_3 = jni::objects::JValueGen::Long(period); - let res = self.jni_ref().call_method( - &self.jni_object(), - "runTaskTimer", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = self.jni_ref().translate_error(res)?; - crate::scheduler::BukkitTask::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Asynchronous tasks should never access any API in Bukkit. Great care - /// should be taken to assure the thread-safety of asynchronous tasks. - /// - /// Schedules this to repeatedly run asynchronously until cancelled, - /// starting after the specified number of server ticks. - pub fn run_task_timer_asynchronously( - &self, - plugin: impl Into>, - delay: i64, - period: i64, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/plugin/Plugin;JJ)Lorg/bukkit/scheduler/BukkitTask;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(plugin.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Long(delay); - let val_3 = jni::objects::JValueGen::Long(period); - let res = self.jni_ref().call_method( - &self.jni_object(), - "runTaskTimerAsynchronously", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); - let res = self.jni_ref().translate_error(res)?; - crate::scheduler::BukkitTask::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the task id for this runnable. - pub fn task_id(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getTaskId", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] pub struct BukkitWorker<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, diff --git a/blackboxmc-rs-bukkit/src/scoreboard/mod.rs b/blackboxmc-rs-bukkit/src/scoreboard/mod.rs index 063baa3..dc241d3 100644 --- a/blackboxmc-rs-bukkit/src/scoreboard/mod.rs +++ b/blackboxmc-rs-bukkit/src/scoreboard/mod.rs @@ -3,6 +3,147 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] +pub struct Criteria<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Criteria<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Criteria<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Criteria from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/scoreboard/Criteria")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Criteria object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Criteria<'mc> { + /// Get the name of this criteria (its unique id). + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Get whether or not this criteria is read only. If read only, scoreboards with this criteria + /// cannot have their scores changed. + pub fn is_read_only(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isReadOnly", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Get the {@link RenderType} used by default for this criteria. + pub fn default_render_type( + &self, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/scoreboard/RenderType;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getDefaultRenderType", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + crate::scoreboard::RenderType::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Get a {@link Criteria} for the specified statistic pertaining to an entity type. + /// + /// This method expects a {@link Statistic} of {@link Type#ENTITY}. This acts as a convenience + /// to create more complex compound criteria such as being killed by a specific entity type. + /// An example would be {@code Criteria.statistic(Statistic.KILL_ENTITY, EntityType.CREEPER)}, + /// returning a Criteria representing "minecraft.killed:minecraft.creeper" which will increment + /// when the player kills a creepers. + /// + /// If the provided statistic does not require additional data, {@link #statistic(Statistic)} + /// is called and returned instead. + /// + /// This method provides no guarantee that any given criteria exists on the vanilla server. + pub fn statistic( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + statistic: impl Into>, + entity_type: std::option::Option>>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Statistic;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(statistic.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = entity_type { + sig += "Lorg/bukkit/entity/EntityType;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Lorg/bukkit/scoreboard/Criteria;"; + let cls = jni.find_class("org/bukkit/scoreboard/Criteria"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "statistic", sig.as_str(), args); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::scoreboard::Criteria::from_raw(&jni, obj) + } + /// Get (or create) a new {@link Criteria} by its name. + pub fn create( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + name: impl Into, + ) -> Result, Box> { + let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/scoreboard/Criteria;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(name.into())?, + )); + let cls = jni.find_class("org/bukkit/scoreboard/Criteria"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "create", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::scoreboard::Criteria::from_raw(&jni, obj) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] pub struct Objective<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, @@ -241,10 +382,25 @@ impl<'mc> Objective<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum RenderType<'mc> {} +pub enum RenderType<'mc> { + Integer { inner: RenderTypeStruct<'mc> }, + Hearts { inner: RenderTypeStruct<'mc> }, +} impl<'mc> std::fmt::Display for RenderType<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + RenderType::Integer { .. } => f.write_str("INTEGER"), + RenderType::Hearts { .. } => f.write_str("HEARTS"), + } + } +} +impl<'mc> std::ops::Deref for RenderType<'mc> { + type Target = RenderTypeStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + RenderType::Integer { inner } => inner, + RenderType::Hearts { inner } => inner, + } } } @@ -271,6 +427,13 @@ impl<'mc> RenderType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "INTEGER" => Ok(RenderType::Integer { + inner: RenderTypeStruct::from_raw(env, obj)?, + }), + "HEARTS" => Ok(RenderType::Hearts { + inner: RenderTypeStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -284,10 +447,16 @@ pub struct RenderTypeStruct<'mc>( impl<'mc> JNIRaw<'mc> for RenderType<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Integer { inner } => inner.0.clone(), + Self::Hearts { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Integer { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Hearts { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + } } } impl<'mc> JNIInstantiatable<'mc> for RenderType<'mc> { @@ -313,6 +482,12 @@ impl<'mc> JNIInstantiatable<'mc> for RenderType<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "INTEGER" => Ok(RenderType::Integer { + inner: RenderTypeStruct::from_raw(env, obj)?, + }), + "HEARTS" => Ok(RenderType::Hearts { + inner: RenderTypeStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -935,10 +1110,28 @@ impl<'mc> Team<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum TeamOption<'mc> {} +pub enum TeamOption<'mc> { + NameTagVisibility { inner: TeamOptionStruct<'mc> }, + DeathMessageVisibility { inner: TeamOptionStruct<'mc> }, + CollisionRule { inner: TeamOptionStruct<'mc> }, +} impl<'mc> std::fmt::Display for TeamOption<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + TeamOption::NameTagVisibility { .. } => f.write_str("NAME_TAG_VISIBILITY"), + TeamOption::DeathMessageVisibility { .. } => f.write_str("DEATH_MESSAGE_VISIBILITY"), + TeamOption::CollisionRule { .. } => f.write_str("COLLISION_RULE"), + } + } +} +impl<'mc> std::ops::Deref for TeamOption<'mc> { + type Target = TeamOptionStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + TeamOption::NameTagVisibility { inner } => inner, + TeamOption::DeathMessageVisibility { inner } => inner, + TeamOption::CollisionRule { inner } => inner, + } } } @@ -965,6 +1158,16 @@ impl<'mc> TeamOption<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NAME_TAG_VISIBILITY" => Ok(TeamOption::NameTagVisibility { + inner: TeamOptionStruct::from_raw(env, obj)?, + }), + "DEATH_MESSAGE_VISIBILITY" => Ok(TeamOption::DeathMessageVisibility { + inner: TeamOptionStruct::from_raw(env, obj)?, + }), + "COLLISION_RULE" => Ok(TeamOption::CollisionRule { + inner: TeamOptionStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -978,10 +1181,24 @@ pub struct TeamOptionStruct<'mc>( impl<'mc> JNIRaw<'mc> for TeamOption<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::NameTagVisibility { inner } => inner.0.clone(), + Self::DeathMessageVisibility { inner } => inner.0.clone(), + Self::CollisionRule { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::NameTagVisibility { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::DeathMessageVisibility { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::CollisionRule { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } impl<'mc> JNIInstantiatable<'mc> for TeamOption<'mc> { @@ -1007,6 +1224,15 @@ impl<'mc> JNIInstantiatable<'mc> for TeamOption<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "NAME_TAG_VISIBILITY" => Ok(TeamOption::NameTagVisibility { + inner: TeamOptionStruct::from_raw(env, obj)?, + }), + "DEATH_MESSAGE_VISIBILITY" => Ok(TeamOption::DeathMessageVisibility { + inner: TeamOptionStruct::from_raw(env, obj)?, + }), + "COLLISION_RULE" => Ok(TeamOption::CollisionRule { + inner: TeamOptionStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -1062,10 +1288,31 @@ impl<'mc> TeamOptionStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum TeamOptionStatus<'mc> {} +pub enum TeamOptionStatus<'mc> { + Always { inner: TeamOptionStatusStruct<'mc> }, + Never { inner: TeamOptionStatusStruct<'mc> }, + ForOtherTeams { inner: TeamOptionStatusStruct<'mc> }, + ForOwnTeam { inner: TeamOptionStatusStruct<'mc> }, +} impl<'mc> std::fmt::Display for TeamOptionStatus<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + TeamOptionStatus::Always { .. } => f.write_str("ALWAYS"), + TeamOptionStatus::Never { .. } => f.write_str("NEVER"), + TeamOptionStatus::ForOtherTeams { .. } => f.write_str("FOR_OTHER_TEAMS"), + TeamOptionStatus::ForOwnTeam { .. } => f.write_str("FOR_OWN_TEAM"), + } + } +} +impl<'mc> std::ops::Deref for TeamOptionStatus<'mc> { + type Target = TeamOptionStatusStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + TeamOptionStatus::Always { inner } => inner, + TeamOptionStatus::Never { inner } => inner, + TeamOptionStatus::ForOtherTeams { inner } => inner, + TeamOptionStatus::ForOwnTeam { inner } => inner, + } } } @@ -1092,6 +1339,19 @@ impl<'mc> TeamOptionStatus<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "ALWAYS" => Ok(TeamOptionStatus::Always { + inner: TeamOptionStatusStruct::from_raw(env, obj)?, + }), + "NEVER" => Ok(TeamOptionStatus::Never { + inner: TeamOptionStatusStruct::from_raw(env, obj)?, + }), + "FOR_OTHER_TEAMS" => Ok(TeamOptionStatus::ForOtherTeams { + inner: TeamOptionStatusStruct::from_raw(env, obj)?, + }), + "FOR_OWN_TEAM" => Ok(TeamOptionStatus::ForOwnTeam { + inner: TeamOptionStatusStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -1105,10 +1365,24 @@ pub struct TeamOptionStatusStruct<'mc>( impl<'mc> JNIRaw<'mc> for TeamOptionStatus<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Always { inner } => inner.0.clone(), + Self::Never { inner } => inner.0.clone(), + Self::ForOtherTeams { inner } => inner.0.clone(), + Self::ForOwnTeam { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Always { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Never { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::ForOtherTeams { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::ForOwnTeam { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } impl<'mc> JNIInstantiatable<'mc> for TeamOptionStatus<'mc> { @@ -1136,6 +1410,18 @@ impl<'mc> JNIInstantiatable<'mc> for TeamOptionStatus<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "ALWAYS" => Ok(TeamOptionStatus::Always { + inner: TeamOptionStatusStruct::from_raw(env, obj)?, + }), + "NEVER" => Ok(TeamOptionStatus::Never { + inner: TeamOptionStatusStruct::from_raw(env, obj)?, + }), + "FOR_OTHER_TEAMS" => Ok(TeamOptionStatus::ForOtherTeams { + inner: TeamOptionStatusStruct::from_raw(env, obj)?, + }), + "FOR_OWN_TEAM" => Ok(TeamOptionStatus::ForOwnTeam { + inner: TeamOptionStatusStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -1233,10 +1519,31 @@ impl<'mc> Criterias<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum NameTagVisibility<'mc> {} +pub enum NameTagVisibility<'mc> { + Always { inner: NameTagVisibilityStruct<'mc> }, + Never { inner: NameTagVisibilityStruct<'mc> }, + HideForOtherTeams { inner: NameTagVisibilityStruct<'mc> }, + HideForOwnTeam { inner: NameTagVisibilityStruct<'mc> }, +} impl<'mc> std::fmt::Display for NameTagVisibility<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + NameTagVisibility::Always { .. } => f.write_str("ALWAYS"), + NameTagVisibility::Never { .. } => f.write_str("NEVER"), + NameTagVisibility::HideForOtherTeams { .. } => f.write_str("HIDE_FOR_OTHER_TEAMS"), + NameTagVisibility::HideForOwnTeam { .. } => f.write_str("HIDE_FOR_OWN_TEAM"), + } + } +} +impl<'mc> std::ops::Deref for NameTagVisibility<'mc> { + type Target = NameTagVisibilityStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + NameTagVisibility::Always { inner } => inner, + NameTagVisibility::Never { inner } => inner, + NameTagVisibility::HideForOtherTeams { inner } => inner, + NameTagVisibility::HideForOwnTeam { inner } => inner, + } } } @@ -1263,6 +1570,19 @@ impl<'mc> NameTagVisibility<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "ALWAYS" => Ok(NameTagVisibility::Always { + inner: NameTagVisibilityStruct::from_raw(env, obj)?, + }), + "NEVER" => Ok(NameTagVisibility::Never { + inner: NameTagVisibilityStruct::from_raw(env, obj)?, + }), + "HIDE_FOR_OTHER_TEAMS" => Ok(NameTagVisibility::HideForOtherTeams { + inner: NameTagVisibilityStruct::from_raw(env, obj)?, + }), + "HIDE_FOR_OWN_TEAM" => Ok(NameTagVisibility::HideForOwnTeam { + inner: NameTagVisibilityStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -1276,10 +1596,24 @@ pub struct NameTagVisibilityStruct<'mc>( impl<'mc> JNIRaw<'mc> for NameTagVisibility<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::Always { inner } => inner.0.clone(), + Self::Never { inner } => inner.0.clone(), + Self::HideForOtherTeams { inner } => inner.0.clone(), + Self::HideForOwnTeam { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::Always { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::Never { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::HideForOtherTeams { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::HideForOwnTeam { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } impl<'mc> JNIInstantiatable<'mc> for NameTagVisibility<'mc> { @@ -1307,6 +1641,18 @@ impl<'mc> JNIInstantiatable<'mc> for NameTagVisibility<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "ALWAYS" => Ok(NameTagVisibility::Always { + inner: NameTagVisibilityStruct::from_raw(env, obj)?, + }), + "NEVER" => Ok(NameTagVisibility::Never { + inner: NameTagVisibilityStruct::from_raw(env, obj)?, + }), + "HIDE_FOR_OTHER_TEAMS" => Ok(NameTagVisibility::HideForOtherTeams { + inner: NameTagVisibilityStruct::from_raw(env, obj)?, + }), + "HIDE_FOR_OWN_TEAM" => Ok(NameTagVisibility::HideForOwnTeam { + inner: NameTagVisibilityStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -1363,10 +1709,76 @@ impl<'mc> NameTagVisibilityStruct<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -pub enum DisplaySlot<'mc> {} +pub enum DisplaySlot<'mc> { + BelowName { inner: DisplaySlotStruct<'mc> }, + PlayerList { inner: DisplaySlotStruct<'mc> }, + Sidebar { inner: DisplaySlotStruct<'mc> }, + SidebarBlack { inner: DisplaySlotStruct<'mc> }, + SidebarDarkBlue { inner: DisplaySlotStruct<'mc> }, + SidebarDarkGreen { inner: DisplaySlotStruct<'mc> }, + SidebarDarkAqua { inner: DisplaySlotStruct<'mc> }, + SidebarDarkRed { inner: DisplaySlotStruct<'mc> }, + SidebarDarkPurple { inner: DisplaySlotStruct<'mc> }, + SidebarGold { inner: DisplaySlotStruct<'mc> }, + SidebarGray { inner: DisplaySlotStruct<'mc> }, + SidebarDarkGray { inner: DisplaySlotStruct<'mc> }, + SidebarBlue { inner: DisplaySlotStruct<'mc> }, + SidebarGreen { inner: DisplaySlotStruct<'mc> }, + SidebarAqua { inner: DisplaySlotStruct<'mc> }, + SidebarRed { inner: DisplaySlotStruct<'mc> }, + SidebarLightPurple { inner: DisplaySlotStruct<'mc> }, + SidebarYellow { inner: DisplaySlotStruct<'mc> }, + SidebarWhite { inner: DisplaySlotStruct<'mc> }, +} impl<'mc> std::fmt::Display for DisplaySlot<'mc> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self {} + match self { + DisplaySlot::BelowName { .. } => f.write_str("BELOW_NAME"), + DisplaySlot::PlayerList { .. } => f.write_str("PLAYER_LIST"), + DisplaySlot::Sidebar { .. } => f.write_str("SIDEBAR"), + DisplaySlot::SidebarBlack { .. } => f.write_str("SIDEBAR_BLACK"), + DisplaySlot::SidebarDarkBlue { .. } => f.write_str("SIDEBAR_DARK_BLUE"), + DisplaySlot::SidebarDarkGreen { .. } => f.write_str("SIDEBAR_DARK_GREEN"), + DisplaySlot::SidebarDarkAqua { .. } => f.write_str("SIDEBAR_DARK_AQUA"), + DisplaySlot::SidebarDarkRed { .. } => f.write_str("SIDEBAR_DARK_RED"), + DisplaySlot::SidebarDarkPurple { .. } => f.write_str("SIDEBAR_DARK_PURPLE"), + DisplaySlot::SidebarGold { .. } => f.write_str("SIDEBAR_GOLD"), + DisplaySlot::SidebarGray { .. } => f.write_str("SIDEBAR_GRAY"), + DisplaySlot::SidebarDarkGray { .. } => f.write_str("SIDEBAR_DARK_GRAY"), + DisplaySlot::SidebarBlue { .. } => f.write_str("SIDEBAR_BLUE"), + DisplaySlot::SidebarGreen { .. } => f.write_str("SIDEBAR_GREEN"), + DisplaySlot::SidebarAqua { .. } => f.write_str("SIDEBAR_AQUA"), + DisplaySlot::SidebarRed { .. } => f.write_str("SIDEBAR_RED"), + DisplaySlot::SidebarLightPurple { .. } => f.write_str("SIDEBAR_LIGHT_PURPLE"), + DisplaySlot::SidebarYellow { .. } => f.write_str("SIDEBAR_YELLOW"), + DisplaySlot::SidebarWhite { .. } => f.write_str("SIDEBAR_WHITE"), + } + } +} +impl<'mc> std::ops::Deref for DisplaySlot<'mc> { + type Target = DisplaySlotStruct<'mc>; + fn deref(&self) -> & as std::ops::Deref>::Target { + match self { + DisplaySlot::BelowName { inner } => inner, + DisplaySlot::PlayerList { inner } => inner, + DisplaySlot::Sidebar { inner } => inner, + DisplaySlot::SidebarBlack { inner } => inner, + DisplaySlot::SidebarDarkBlue { inner } => inner, + DisplaySlot::SidebarDarkGreen { inner } => inner, + DisplaySlot::SidebarDarkAqua { inner } => inner, + DisplaySlot::SidebarDarkRed { inner } => inner, + DisplaySlot::SidebarDarkPurple { inner } => inner, + DisplaySlot::SidebarGold { inner } => inner, + DisplaySlot::SidebarGray { inner } => inner, + DisplaySlot::SidebarDarkGray { inner } => inner, + DisplaySlot::SidebarBlue { inner } => inner, + DisplaySlot::SidebarGreen { inner } => inner, + DisplaySlot::SidebarAqua { inner } => inner, + DisplaySlot::SidebarRed { inner } => inner, + DisplaySlot::SidebarLightPurple { inner } => inner, + DisplaySlot::SidebarYellow { inner } => inner, + DisplaySlot::SidebarWhite { inner } => inner, + } } } @@ -1393,6 +1805,64 @@ impl<'mc> DisplaySlot<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "BELOW_NAME" => Ok(DisplaySlot::BelowName { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "PLAYER_LIST" => Ok(DisplaySlot::PlayerList { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR" => Ok(DisplaySlot::Sidebar { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_BLACK" => Ok(DisplaySlot::SidebarBlack { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_DARK_BLUE" => Ok(DisplaySlot::SidebarDarkBlue { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_DARK_GREEN" => Ok(DisplaySlot::SidebarDarkGreen { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_DARK_AQUA" => Ok(DisplaySlot::SidebarDarkAqua { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_DARK_RED" => Ok(DisplaySlot::SidebarDarkRed { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_DARK_PURPLE" => Ok(DisplaySlot::SidebarDarkPurple { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_GOLD" => Ok(DisplaySlot::SidebarGold { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_GRAY" => Ok(DisplaySlot::SidebarGray { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_DARK_GRAY" => Ok(DisplaySlot::SidebarDarkGray { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_BLUE" => Ok(DisplaySlot::SidebarBlue { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_GREEN" => Ok(DisplaySlot::SidebarGreen { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_AQUA" => Ok(DisplaySlot::SidebarAqua { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_RED" => Ok(DisplaySlot::SidebarRed { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_LIGHT_PURPLE" => Ok(DisplaySlot::SidebarLightPurple { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_YELLOW" => Ok(DisplaySlot::SidebarYellow { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_WHITE" => Ok(DisplaySlot::SidebarWhite { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -1406,10 +1876,86 @@ pub struct DisplaySlotStruct<'mc>( impl<'mc> JNIRaw<'mc> for DisplaySlot<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - match self {} + match self { + Self::BelowName { inner } => inner.0.clone(), + Self::PlayerList { inner } => inner.0.clone(), + Self::Sidebar { inner } => inner.0.clone(), + Self::SidebarBlack { inner } => inner.0.clone(), + Self::SidebarDarkBlue { inner } => inner.0.clone(), + Self::SidebarDarkGreen { inner } => inner.0.clone(), + Self::SidebarDarkAqua { inner } => inner.0.clone(), + Self::SidebarDarkRed { inner } => inner.0.clone(), + Self::SidebarDarkPurple { inner } => inner.0.clone(), + Self::SidebarGold { inner } => inner.0.clone(), + Self::SidebarGray { inner } => inner.0.clone(), + Self::SidebarDarkGray { inner } => inner.0.clone(), + Self::SidebarBlue { inner } => inner.0.clone(), + Self::SidebarGreen { inner } => inner.0.clone(), + Self::SidebarAqua { inner } => inner.0.clone(), + Self::SidebarRed { inner } => inner.0.clone(), + Self::SidebarLightPurple { inner } => inner.0.clone(), + Self::SidebarYellow { inner } => inner.0.clone(), + Self::SidebarWhite { inner } => inner.0.clone(), + } } fn jni_object(&self) -> jni::objects::JObject<'mc> { - match self {} + match self { + Self::BelowName { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::PlayerList { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::Sidebar { inner } => unsafe { jni::objects::JObject::from_raw(inner.1.clone()) }, + Self::SidebarBlack { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SidebarDarkBlue { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SidebarDarkGreen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SidebarDarkAqua { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SidebarDarkRed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SidebarDarkPurple { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SidebarGold { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SidebarGray { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SidebarDarkGray { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SidebarBlue { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SidebarGreen { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SidebarAqua { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SidebarRed { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SidebarLightPurple { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SidebarYellow { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + Self::SidebarWhite { inner } => unsafe { + jni::objects::JObject::from_raw(inner.1.clone()) + }, + } } } impl<'mc> JNIInstantiatable<'mc> for DisplaySlot<'mc> { @@ -1435,6 +1981,63 @@ impl<'mc> JNIInstantiatable<'mc> for DisplaySlot<'mc> { .to_string_lossy() .to_string(); match variant_str.as_str() { + "BELOW_NAME" => Ok(DisplaySlot::BelowName { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "PLAYER_LIST" => Ok(DisplaySlot::PlayerList { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR" => Ok(DisplaySlot::Sidebar { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_BLACK" => Ok(DisplaySlot::SidebarBlack { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_DARK_BLUE" => Ok(DisplaySlot::SidebarDarkBlue { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_DARK_GREEN" => Ok(DisplaySlot::SidebarDarkGreen { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_DARK_AQUA" => Ok(DisplaySlot::SidebarDarkAqua { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_DARK_RED" => Ok(DisplaySlot::SidebarDarkRed { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_DARK_PURPLE" => Ok(DisplaySlot::SidebarDarkPurple { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_GOLD" => Ok(DisplaySlot::SidebarGold { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_GRAY" => Ok(DisplaySlot::SidebarGray { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_DARK_GRAY" => Ok(DisplaySlot::SidebarDarkGray { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_BLUE" => Ok(DisplaySlot::SidebarBlue { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_GREEN" => Ok(DisplaySlot::SidebarGreen { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_AQUA" => Ok(DisplaySlot::SidebarAqua { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_RED" => Ok(DisplaySlot::SidebarRed { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_LIGHT_PURPLE" => Ok(DisplaySlot::SidebarLightPurple { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_YELLOW" => Ok(DisplaySlot::SidebarYellow { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), + "SIDEBAR_WHITE" => Ok(DisplaySlot::SidebarWhite { + inner: DisplaySlotStruct::from_raw(env, obj)?, + }), _ => Err(eyre::eyre!("String gaven for variant was invalid").into()), } } @@ -1828,147 +2431,6 @@ impl<'mc> Scoreboard<'mc> { } } #[repr(C)] -pub struct Criteria<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Criteria<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Criteria<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Criteria from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/scoreboard/Criteria")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Criteria object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Criteria<'mc> { - /// Get the name of this criteria (its unique id). - pub fn name(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getName", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Get whether or not this criteria is read only. If read only, scoreboards with this criteria - /// cannot have their scores changed. - pub fn is_read_only(&self) -> Result> { - let sig = String::from("()Z"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "isReadOnly", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Get the {@link RenderType} used by default for this criteria. - pub fn default_render_type( - &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/scoreboard/RenderType;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getDefaultRenderType", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - crate::scoreboard::RenderType::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get a {@link Criteria} for the specified statistic pertaining to an entity type. - /// - /// This method expects a {@link Statistic} of {@link Type#ENTITY}. This acts as a convenience - /// to create more complex compound criteria such as being killed by a specific entity type. - /// An example would be {@code Criteria.statistic(Statistic.KILL_ENTITY, EntityType.CREEPER)}, - /// returning a Criteria representing "minecraft.killed:minecraft.creeper" which will increment - /// when the player kills a creepers. - /// - /// If the provided statistic does not require additional data, {@link #statistic(Statistic)} - /// is called and returned instead. - /// - /// This method provides no guarantee that any given criteria exists on the vanilla server. - pub fn statistic( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - statistic: impl Into>, - entity_type: std::option::Option>>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Statistic;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(statistic.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = entity_type { - sig += "Lorg/bukkit/entity/EntityType;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Lorg/bukkit/scoreboard/Criteria;"; - let cls = jni.find_class("org/bukkit/scoreboard/Criteria"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "statistic", sig.as_str(), args); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::scoreboard::Criteria::from_raw(&jni, obj) - } - /// Get (or create) a new {@link Criteria} by its name. - pub fn create( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - name: impl Into, - ) -> Result, Box> { - let sig = String::from("(Ljava/lang/String;)Lorg/bukkit/scoreboard/Criteria;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(name.into())?, - )); - let cls = jni.find_class("org/bukkit/scoreboard/Criteria"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "create", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::scoreboard::Criteria::from_raw(&jni, obj) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] pub struct Score<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, diff --git a/blackboxmc-rs-bukkit/src/spawner/mod.rs b/blackboxmc-rs-bukkit/src/spawner/mod.rs new file mode 100644 index 0000000..a8d1654 --- /dev/null +++ b/blackboxmc-rs-bukkit/src/spawner/mod.rs @@ -0,0 +1,1231 @@ +#![allow(deprecated)] +use blackboxmc_general::JNIInstantiatable; +use blackboxmc_general::JNIRaw; +use color_eyre::eyre::Result; +#[repr(C)] +pub struct BaseSpawner<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for BaseSpawner<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for BaseSpawner<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate BaseSpawner from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/spawner/BaseSpawner")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BaseSpawner object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> BaseSpawner<'mc> { + /// Get the spawner's creature type. + pub fn spawned_type( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSpawnedType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntityType::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Set the spawner's creature type. + /// + /// This will override any entities that have been added with {@link #addPotentialSpawn} + pub fn set_spawned_type( + &self, + creature_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/EntityType;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(creature_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSpawnedType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the spawner's delay. + /// + /// This is the delay, in ticks, until the spawner will spawn its next mob. + pub fn delay(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getDelay", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the spawner's delay. + pub fn set_delay(&self, delay: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(delay); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDelay", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the maximum distance(squared) a player can be in order for this + /// spawner to be active. + /// + /// If this value is less than or equal to 0, this spawner is always active + /// (given that there are players online). + /// + /// Default value is 16. + pub fn required_player_range(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getRequiredPlayerRange", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the maximum distance (squared) a player can be in order for this + /// spawner to be active. + /// + /// Setting this value to less than or equal to 0 will make this spawner + /// always active (given that there are players online). + pub fn set_required_player_range( + &self, + required_player_range: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(required_player_range); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRequiredPlayerRange", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the radius around which the spawner will attempt to spawn mobs in. + /// + /// This area is square, includes the block the spawner is in, and is + /// centered on the spawner's x,z coordinates - not the spawner itself. + /// + /// It is 2 blocks high, centered on the spawner's y-coordinate (its bottom); + /// thus allowing mobs to spawn as high as its top surface and as low + /// as 1 block below its bottom surface. + /// + /// Default value is 4. + pub fn spawn_range(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSpawnRange", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the new spawn range. + /// + pub fn set_spawn_range(&self, spawn_range: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(spawn_range); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSpawnRange", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the {@link EntitySnapshot} that will be spawned by this spawner or null + /// if no entities have been assigned to this spawner. + /// + /// + /// All applicable data from the spawner will be copied, such as custom name, + /// health, and velocity. + /// + pub fn spawned_entity( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSpawnedEntity", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntitySnapshot::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets the {@link SpawnerEntry} that will be spawned by this spawner. + /// + /// This will override any previous entries that have been added with + /// {@link #addPotentialSpawn} + pub fn set_spawned_entity( + &self, + spawner_entry: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/block/spawner/SpawnerEntry;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(spawner_entry.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setSpawnedEntity", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Adds a new {@link EntitySnapshot} to the list of entities this spawner can + /// spawn. + /// + /// The weight will determine how often this entry is chosen to spawn, higher + /// weighted entries will spawn more often than lower weighted ones. + /// + /// The {@link SpawnRule} will determine under what conditions this entry can + /// spawn, passing null will use the default conditions for the given entity. + pub fn add_potential_spawn( + &self, + snapshot: impl Into>, + weight: std::option::Option, + spawn_rule: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/EntitySnapshot;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(snapshot.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = weight { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + if let Some(a) = spawn_rule { + sig += "Lorg/bukkit/block/spawner/SpawnRule;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_3); + } + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "addPotentialSpawn", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets a list of potential spawns from this spawner or an empty list if no + /// entities have been assigned to this spawner. + /// + /// Changes made to the returned list will not be reflected in the spawner unless + /// applied with {@link #setPotentialSpawns} + pub fn potential_spawns( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPotentialSpawns", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::spawner::SpawnerEntry::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(new_vec) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +#[repr(C)] +pub struct TrialSpawnerConfiguration<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for TrialSpawnerConfiguration<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for TrialSpawnerConfiguration<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate TrialSpawnerConfiguration from null object." + ) + .into()); + } + let (valid, name) = + env.validate_name(&obj, "org/bukkit/spawner/TrialSpawnerConfiguration")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a TrialSpawnerConfiguration object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> TrialSpawnerConfiguration<'mc> { + /// Gets the base number of entities the spawner will spawn before going into + /// cooldown. + pub fn base_spawns_before_cooldown(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBaseSpawnsBeforeCooldown", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the base number of entities the spawner will spawn before going into + /// cooldown. + pub fn set_base_spawns_before_cooldown( + &self, + amount: f32, + ) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(amount); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBaseSpawnsBeforeCooldown", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the base number of entities this spawner can track at once. + /// + /// If the limit is reached the spawner will not be able to spawn any more + /// entities until the existing entities are killed or move too far away. + pub fn base_simultaneous_entities(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBaseSimultaneousEntities", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the base number of entities this spawner can track at once. + /// + /// If the limit is reached the spawner will not be able to spawn any more + /// entities until the existing entities are killed or move too far away. + pub fn set_base_simultaneous_entities( + &self, + amount: f32, + ) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(amount); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setBaseSimultaneousEntities", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the additional number of entities the spawner will spawn per tracked player + /// before going into cooldown. + pub fn additional_spawns_before_cooldown(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAdditionalSpawnsBeforeCooldown", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the additional number of entities the spawner will spawn per tracked player + /// before going into cooldown. + pub fn set_additional_spawns_before_cooldown( + &self, + amount: f32, + ) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(amount); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAdditionalSpawnsBeforeCooldown", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the additional number of entities this spawner can track at once per + /// tracked player. + /// + /// If the limit is reached the spawner will not be able to spawn any more + /// entities until the existing entities are killed or move too far away. + pub fn additional_simultaneous_entities(&self) -> Result> { + let sig = String::from("()F"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getAdditionalSimultaneousEntities", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.f()?) + } + /// Sets the additional number of entities this spawner can track at once per + /// tracked player. + /// + /// If the limit is reached the spawner will not be able to spawn any more + /// entities until the existing entities are killed or move too far away. + pub fn set_additional_simultaneous_entities( + &self, + amount: f32, + ) -> Result<(), Box> { + let sig = String::from("(F)V"); + let val_1 = jni::objects::JValueGen::Float(amount); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setAdditionalSimultaneousEntities", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets a list of {@link LootTable}s this spawner can pick a reward from as + /// well as their associated weight to be chosen. + pub fn possible_rewards( + &self, + ) -> Result, Box> { + let sig = String::from("()Ljava/util/Map;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPossibleRewards", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + blackboxmc_java::util::JavaMap::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Add a {@link LootTable} to the list of tables this spawner can pick a reward + /// from with a given weight. + pub fn add_possible_reward( + &self, + table: impl Into>, + weight: i32, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/loot/LootTable;I)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(table.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(weight); + let res = self.jni_ref().call_method( + &self.jni_object(), + "addPossibleReward", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Removes the provided {@link LootTable} from the list of tables this spawner + /// can pick a reward from. + pub fn remove_possible_reward( + &self, + table: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/loot/LootTable;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(table.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "removePossibleReward", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Sets the list of {@link LootTable}s and their weights this spawner can pick a + /// reward from. + /// + /// All loot tables in the map must be non-null and all weights must be at least + /// 1. + pub fn set_possible_rewards( + &self, + rewards: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Ljava/util/Map;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(rewards.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setPossibleRewards", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the spawner's creature type. + pub fn spawned_type( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSpawnedType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntityType::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Set the spawner's creature type. + /// + /// This will override any entities that have been added with {@link #addPotentialSpawn} + pub fn set_spawned_type( + &self, + creature_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/EntityType;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(creature_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSpawnedType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the spawner's delay. + /// + /// This is the delay, in ticks, until the spawner will spawn its next mob. + pub fn delay(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getDelay", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the spawner's delay. + pub fn set_delay(&self, delay: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(delay); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDelay", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the maximum distance(squared) a player can be in order for this + /// spawner to be active. + /// + /// If this value is less than or equal to 0, this spawner is always active + /// (given that there are players online). + /// + /// Default value is 16. + pub fn required_player_range(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getRequiredPlayerRange", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the maximum distance (squared) a player can be in order for this + /// spawner to be active. + /// + /// Setting this value to less than or equal to 0 will make this spawner + /// always active (given that there are players online). + pub fn set_required_player_range( + &self, + required_player_range: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(required_player_range); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRequiredPlayerRange", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the radius around which the spawner will attempt to spawn mobs in. + /// + /// This area is square, includes the block the spawner is in, and is + /// centered on the spawner's x,z coordinates - not the spawner itself. + /// + /// It is 2 blocks high, centered on the spawner's y-coordinate (its bottom); + /// thus allowing mobs to spawn as high as its top surface and as low + /// as 1 block below its bottom surface. + /// + /// Default value is 4. + pub fn spawn_range(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSpawnRange", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the new spawn range. + /// + pub fn set_spawn_range(&self, spawn_range: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(spawn_range); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSpawnRange", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the {@link EntitySnapshot} that will be spawned by this spawner or null + /// if no entities have been assigned to this spawner. + /// + /// + /// All applicable data from the spawner will be copied, such as custom name, + /// health, and velocity. + /// + pub fn spawned_entity( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSpawnedEntity", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntitySnapshot::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets the {@link SpawnerEntry} that will be spawned by this spawner. + /// + /// This will override any previous entries that have been added with + /// {@link #addPotentialSpawn} + pub fn set_spawned_entity( + &self, + spawner_entry: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/block/spawner/SpawnerEntry;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(spawner_entry.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setSpawnedEntity", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Adds a new {@link EntitySnapshot} to the list of entities this spawner can + /// spawn. + /// + /// The weight will determine how often this entry is chosen to spawn, higher + /// weighted entries will spawn more often than lower weighted ones. + /// + /// The {@link SpawnRule} will determine under what conditions this entry can + /// spawn, passing null will use the default conditions for the given entity. + pub fn add_potential_spawn( + &self, + snapshot: impl Into>, + weight: std::option::Option, + spawn_rule: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/EntitySnapshot;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(snapshot.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = weight { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + if let Some(a) = spawn_rule { + sig += "Lorg/bukkit/block/spawner/SpawnRule;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_3); + } + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "addPotentialSpawn", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets a list of potential spawns from this spawner or an empty list if no + /// entities have been assigned to this spawner. + /// + /// Changes made to the returned list will not be reflected in the spawner unless + /// applied with {@link #setPotentialSpawns} + pub fn potential_spawns( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPotentialSpawns", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::spawner::SpawnerEntry::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(new_vec) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for TrialSpawnerConfiguration<'mc> { + fn into(self) -> crate::spawner::BaseSpawner<'mc> { + crate::spawner::BaseSpawner::from_raw(&self.jni_ref(), self.1) + .expect("Error converting TrialSpawnerConfiguration into crate::spawner::BaseSpawner") + } +} +#[repr(C)] +pub struct Spawner<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for Spawner<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for Spawner<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate Spawner from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/spawner/Spawner")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a Spawner object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> Spawner<'mc> { + /// {@inheritDoc} + /// + /// If set to -1, the spawn delay will be reset to a random value between + /// {@link #getMinSpawnDelay} and {@link #getMaxSpawnDelay()}. + pub fn set_delay(&self, delay: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(delay); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setDelay", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// The minimum spawn delay amount (in ticks). + /// + /// This value is used when the spawner resets its delay (for any reason). + /// It will choose a random number between {@link #getMinSpawnDelay()} + /// and {@link #getMaxSpawnDelay()} for its next {@link #getDelay()}. + /// + /// Default value is 200 ticks. + pub fn min_spawn_delay(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMinSpawnDelay", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the minimum spawn delay amount (in ticks). + pub fn set_min_spawn_delay(&self, delay: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(delay); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMinSpawnDelay", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// The maximum spawn delay amount (in ticks). + /// + /// This value is used when the spawner resets its delay (for any reason). + /// It will choose a random number between {@link #getMinSpawnDelay()} + /// and {@link #getMaxSpawnDelay()} for its next {@link #getDelay()}. + /// + /// This value must be greater than 0 and less than or equal to + /// {@link #getMaxSpawnDelay()}. + /// + /// Default value is 800 ticks. + pub fn max_spawn_delay(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaxSpawnDelay", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the maximum spawn delay amount (in ticks). + /// + /// This value must be greater than 0, as well as greater than or + /// equal to {@link #getMinSpawnDelay()} + pub fn set_max_spawn_delay(&self, delay: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(delay); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaxSpawnDelay", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get how many mobs attempt to spawn. + /// + /// Default value is 4. + pub fn spawn_count(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSpawnCount", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set how many mobs attempt to spawn. + pub fn set_spawn_count(&self, spawn_count: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(spawn_count); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSpawnCount", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Set the new maximum amount of similar entities that are allowed to be + /// within spawning range of this spawner. + /// + /// If more than the maximum number of entities are within range, the spawner + /// will not spawn and try again with a new {@link #getDelay()}. + /// + /// Default value is 16. + pub fn max_nearby_entities(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getMaxNearbyEntities", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the maximum number of similar entities that are allowed to be within + /// spawning range of this spawner. + /// + /// Similar entities are entities that are of the same {@link EntityType} + pub fn set_max_nearby_entities( + &self, + max_nearby_entities: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(max_nearby_entities); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setMaxNearbyEntities", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the spawner's creature type. + pub fn spawned_type( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntityType;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSpawnedType", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntityType::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Set the spawner's creature type. + /// + /// This will override any entities that have been added with {@link #addPotentialSpawn} + pub fn set_spawned_type( + &self, + creature_type: impl Into>, + ) -> Result<(), Box> { + let sig = String::from("(Lorg/bukkit/entity/EntityType;)V"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(creature_type.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSpawnedType", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the spawner's delay. + /// + /// This is the delay, in ticks, until the spawner will spawn its next mob. + pub fn delay(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getDelay", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Get the maximum distance(squared) a player can be in order for this + /// spawner to be active. + /// + /// If this value is less than or equal to 0, this spawner is always active + /// (given that there are players online). + /// + /// Default value is 16. + pub fn required_player_range(&self) -> Result> { + let sig = String::from("()I"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getRequiredPlayerRange", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the maximum distance (squared) a player can be in order for this + /// spawner to be active. + /// + /// Setting this value to less than or equal to 0 will make this spawner + /// always active (given that there are players online). + pub fn set_required_player_range( + &self, + required_player_range: i32, + ) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(required_player_range); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setRequiredPlayerRange", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the radius around which the spawner will attempt to spawn mobs in. + /// + /// This area is square, includes the block the spawner is in, and is + /// centered on the spawner's x,z coordinates - not the spawner itself. + /// + /// It is 2 blocks high, centered on the spawner's y-coordinate (its bottom); + /// thus allowing mobs to spawn as high as its top surface and as low + /// as 1 block below its bottom surface. + /// + /// Default value is 4. + pub fn spawn_range(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getSpawnRange", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Set the new spawn range. + /// + pub fn set_spawn_range(&self, spawn_range: i32) -> Result<(), Box> { + let sig = String::from("(I)V"); + let val_1 = jni::objects::JValueGen::Int(spawn_range); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setSpawnRange", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets the {@link EntitySnapshot} that will be spawned by this spawner or null + /// if no entities have been assigned to this spawner. + /// + /// + /// All applicable data from the spawner will be copied, such as custom name, + /// health, and velocity. + /// + pub fn spawned_entity( + &self, + ) -> Result>, Box> { + let sig = String::from("()Lorg/bukkit/entity/EntitySnapshot;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getSpawnedEntity", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::entity::EntitySnapshot::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) + } + /// Sets the {@link SpawnerEntry} that will be spawned by this spawner. + /// + /// This will override any previous entries that have been added with + /// {@link #addPotentialSpawn} + pub fn set_spawned_entity( + &self, + spawner_entry: impl Into>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/block/spawner/SpawnerEntry;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(spawner_entry.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "setSpawnedEntity", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Adds a new {@link EntitySnapshot} to the list of entities this spawner can + /// spawn. + /// + /// The weight will determine how often this entry is chosen to spawn, higher + /// weighted entries will spawn more often than lower weighted ones. + /// + /// The {@link SpawnRule} will determine under what conditions this entry can + /// spawn, passing null will use the default conditions for the given entity. + pub fn add_potential_spawn( + &self, + snapshot: impl Into>, + weight: std::option::Option, + spawn_rule: std::option::Option>>, + ) -> Result<(), Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/entity/EntitySnapshot;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(snapshot.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = weight { + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(a); + args.push(val_2); + } + if let Some(a) = spawn_rule { + sig += "Lorg/bukkit/block/spawner/SpawnRule;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_3); + } + sig += ")V"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "addPotentialSpawn", sig.as_str(), args); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Gets a list of potential spawns from this spawner or an empty list if no + /// entities have been assigned to this spawner. + /// + /// Changes made to the returned list will not be reflected in the spawner unless + /// applied with {@link #setPotentialSpawns} + pub fn potential_spawns( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/List;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getPotentialSpawns", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let list = blackboxmc_java::util::JavaList::from_raw(&self.jni_ref(), res.l()?)?; + let iter = list.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::block::spawner::SpawnerEntry::from_raw( + &self.jni_ref(), + obj, + )?); + } + Ok(new_vec) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for Spawner<'mc> { + fn into(self) -> crate::spawner::BaseSpawner<'mc> { + crate::spawner::BaseSpawner::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Spawner into crate::spawner::BaseSpawner") + } +} diff --git a/blackboxmc-rs-bukkit/src/util/io/mod.rs b/blackboxmc-rs-bukkit/src/util/io/mod.rs index 3123302..998c8dd 100644 --- a/blackboxmc-rs-bukkit/src/util/io/mod.rs +++ b/blackboxmc-rs-bukkit/src/util/io/mod.rs @@ -3,12 +3,12 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] -pub struct BukkitObjectInputStream<'mc>( +pub struct BukkitObjectOutputStream<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BukkitObjectInputStream<'mc> { +impl<'mc> JNIRaw<'mc> for BukkitObjectOutputStream<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -16,22 +16,22 @@ impl<'mc> JNIRaw<'mc> for BukkitObjectInputStream<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BukkitObjectInputStream<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BukkitObjectOutputStream<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate BukkitObjectInputStream from null object." + "Tried to instantiate BukkitObjectOutputStream from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/util/io/BukkitObjectInputStream")?; + env.validate_name(&obj, "org/bukkit/util/io/BukkitObjectOutputStream")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BukkitObjectInputStream object, got {}", + "Invalid argument passed. Expected a BukkitObjectOutputStream object, got {}", name ) .into()) @@ -41,19 +41,19 @@ impl<'mc> JNIInstantiatable<'mc> for BukkitObjectInputStream<'mc> { } } -impl<'mc> BukkitObjectInputStream<'mc> { +impl<'mc> BukkitObjectOutputStream<'mc> { pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } #[repr(C)] -pub struct BukkitObjectOutputStream<'mc>( +pub struct BukkitObjectInputStream<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BukkitObjectOutputStream<'mc> { +impl<'mc> JNIRaw<'mc> for BukkitObjectInputStream<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -61,22 +61,22 @@ impl<'mc> JNIRaw<'mc> for BukkitObjectOutputStream<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BukkitObjectOutputStream<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BukkitObjectInputStream<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err(eyre::eyre!( - "Tried to instantiate BukkitObjectOutputStream from null object." + "Tried to instantiate BukkitObjectInputStream from null object." ) .into()); } let (valid, name) = - env.validate_name(&obj, "org/bukkit/util/io/BukkitObjectOutputStream")?; + env.validate_name(&obj, "org/bukkit/util/io/BukkitObjectInputStream")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BukkitObjectOutputStream object, got {}", + "Invalid argument passed. Expected a BukkitObjectInputStream object, got {}", name ) .into()) @@ -86,7 +86,7 @@ impl<'mc> JNIInstantiatable<'mc> for BukkitObjectOutputStream<'mc> { } } -impl<'mc> BukkitObjectOutputStream<'mc> { +impl<'mc> BukkitObjectInputStream<'mc> { pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) diff --git a/blackboxmc-rs-bukkit/src/util/mod.rs b/blackboxmc-rs-bukkit/src/util/mod.rs index 24863b4..e7cda20 100644 --- a/blackboxmc-rs-bukkit/src/util/mod.rs +++ b/blackboxmc-rs-bukkit/src/util/mod.rs @@ -3,12 +3,12 @@ use blackboxmc_general::JNIInstantiatable; use blackboxmc_general::JNIRaw; use color_eyre::eyre::Result; #[repr(C)] -pub struct EntityTransformer<'mc>( +pub struct Vector<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for EntityTransformer<'mc> { +impl<'mc> JNIRaw<'mc> for Vector<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -16,20 +16,18 @@ impl<'mc> JNIRaw<'mc> for EntityTransformer<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for EntityTransformer<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Vector<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate EntityTransformer from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate Vector from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/util/EntityTransformer")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/util/Vector")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a EntityTransformer object, got {}", + "Invalid argument passed. Expected a Vector object, got {}", name ) .into()) @@ -39,1059 +37,906 @@ impl<'mc> JNIInstantiatable<'mc> for EntityTransformer<'mc> { } } -impl<'mc> EntityTransformer<'mc> { - /// Transforms a entity in a structure. - pub fn transform( +impl<'mc> Vector<'mc> { + /// Construct the vector with provided float components. + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + x: std::option::Option, + y: std::option::Option, + z: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = x { + sig += "F"; + let val_1 = jni::objects::JValueGen::Float(a); + args.push(val_1); + } + if let Some(a) = y { + sig += "F"; + let val_2 = jni::objects::JValueGen::Float(a); + args.push(val_2); + } + if let Some(a) = z { + sig += "F"; + let val_3 = jni::objects::JValueGen::Float(a); + args.push(val_3); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/util/Vector"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::util::Vector::from_raw(&jni, res) + } + /// Adds a vector to this one + pub fn add( &self, - region: impl Into>, - x: i32, - y: i32, - z: i32, - entity: impl Into>, - allowed_to_spawn: bool, - ) -> Result> { - let sig = - String::from("(Lorg/bukkit/generator/LimitedRegion;IIILorg/bukkit/entity/Entity;Z)Z"); + vec: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)Lorg/bukkit/util/Vector;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(region.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Int(x); - let val_3 = jni::objects::JValueGen::Int(y); - let val_4 = jni::objects::JValueGen::Int(z); - let val_5 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + jni::objects::JObject::from_raw(vec.into().jni_object().clone()) }); - let val_6 = jni::objects::JValueGen::Bool(allowed_to_spawn.into()); let res = self.jni_ref().call_method( &self.jni_object(), - "transform", + "add", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - jni::objects::JValueGen::from(val_5), - jni::objects::JValueGen::from(val_6), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct StructureSearchResult<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for StructureSearchResult<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Subtracts a vector from this one. + pub fn subtract( + &self, + vec: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)Lorg/bukkit/util/Vector;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(vec.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "subtract", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} -impl<'mc> JNIInstantiatable<'mc> for StructureSearchResult<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate StructureSearchResult from null object." - ) - .into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/util/StructureSearchResult")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a StructureSearchResult object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } + /// Performs scalar multiplication, multiplying all components with a + /// scalar. + pub fn multiply(&self, m: f32) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "F"; + let val_1 = jni::objects::JValueGen::Float(m); + args.push(val_1); + sig += ")Lorg/bukkit/util/Vector;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "multiply", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } -} - -impl<'mc> StructureSearchResult<'mc> { - /// Return the structure which was found. - pub fn structure( + /// Divides the vector by another. + pub fn divide( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/generator/structure/Structure;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getStructure", sig.as_str(), vec![]); + vec: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)Lorg/bukkit/util/Vector;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(vec.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "divide", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - crate::generator::structure::Structure::from_raw(&self.jni_ref(), unsafe { + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Return the location of the structure. - pub fn location(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); + /// Copies another vector + pub fn copy( + &self, + vec: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)Lorg/bukkit/util/Vector;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(vec.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "copy", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct FileUtil<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for FileUtil<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() + /// Gets the magnitude of the vector, defined as sqrt(x^2+y^2+z^2). The + /// value of this method is not cached and uses a costly square-root + /// function, so do not repeatedly call this method to get the vector's + /// magnitude. NaN will be returned if the inner result of the sqrt() + /// function overflows, which will be caused if the length is too long. + pub fn length(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "length", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + /// Gets the magnitude of the vector squared. + pub fn length_squared(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "lengthSquared", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } -} -impl<'mc> JNIInstantiatable<'mc> for FileUtil<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate FileUtil from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/util/FileUtil")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a FileUtil object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> FileUtil<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/util/FileUtil"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), vec![]); - let res = jni.translate_error_no_gen(res)?; - crate::util::FileUtil::from_raw(&jni, res) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct EulerAngle<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for EulerAngle<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for EulerAngle<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate EulerAngle from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/util/EulerAngle")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a EulerAngle object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> EulerAngle<'mc> { - /// Creates a EularAngle with each axis set to the - /// passed angle in radians - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - x: f64, - y: f64, - z: f64, - ) -> Result, Box> { - let sig = String::from("(DDD)V"); - let val_1 = jni::objects::JValueGen::Double(x); - let val_2 = jni::objects::JValueGen::Double(y); - let val_3 = jni::objects::JValueGen::Double(z); - let cls = jni.find_class("org/bukkit/util/EulerAngle"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( - cls, + /// Get the distance between this vector and another. The value of this + /// method is not cached and uses a costly square-root function, so do not + /// repeatedly call this method to get the vector's magnitude. NaN will be + /// returned if the inner result of the sqrt() function overflows, which + /// will be caused if the distance is too long. + pub fn distance( + &self, + o: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/util/Vector;)D"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(o.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "distance", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error_no_gen(res)?; - crate::util::EulerAngle::from_raw(&jni, res) - } - /// Returns the angle on the x axis in radians - pub fn x(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Returns the angle on the y axis in radians - pub fn y(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Returns the angle on the z axis in radians - pub fn z(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.d()?) } - /// Return a EulerAngle which is the result of changing - /// the x axis to the passed angle - pub fn set_x( + /// Get the squared distance between this vector and another. + pub fn distance_squared( &self, - x: f64, - ) -> Result, Box> { - let sig = String::from("(D)Lorg/bukkit/util/EulerAngle;"); - let val_1 = jni::objects::JValueGen::Double(x); + o: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/util/Vector;)D"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(o.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setX", + "distanceSquared", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::util::EulerAngle::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.d()?) } - /// Return a EulerAngle which is the result of changing - /// the y axis to the passed angle - pub fn set_y( + /// Gets the angle between this vector and another in radians. + pub fn angle( &self, - y: f64, - ) -> Result, Box> { - let sig = String::from("(D)Lorg/bukkit/util/EulerAngle;"); - let val_1 = jni::objects::JValueGen::Double(y); + other: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/util/Vector;)F"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(other.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setY", + "angle", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::util::EulerAngle::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.f()?) } - /// Return a EulerAngle which is the result of changing - /// the z axis to the passed angle - pub fn set_z( + /// Sets this vector to the midpoint between this vector and another. + pub fn midpoint( &self, - z: f64, - ) -> Result, Box> { - let sig = String::from("(D)Lorg/bukkit/util/EulerAngle;"); - let val_1 = jni::objects::JValueGen::Double(z); + other: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)Lorg/bukkit/util/Vector;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(other.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "setZ", + "midpoint", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::util::EulerAngle::from_raw(&self.jni_ref(), unsafe { + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Creates a new EulerAngle which is the result of adding - /// the x, y, z components to this EulerAngle - pub fn add( + /// Gets a new midpoint vector between this vector and another. + pub fn get_midpoint( &self, - x: f64, - y: f64, - z: f64, - ) -> Result, Box> { - let sig = String::from("(DDD)Lorg/bukkit/util/EulerAngle;"); - let val_1 = jni::objects::JValueGen::Double(x); - let val_2 = jni::objects::JValueGen::Double(y); - let val_3 = jni::objects::JValueGen::Double(z); + other: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)Lorg/bukkit/util/Vector;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(other.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "add", + "getMidpoint", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::util::EulerAngle::from_raw(&self.jni_ref(), unsafe { + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Creates a new EulerAngle which is the result of subtracting - /// the x, y, z components to this EulerAngle - pub fn subtract( + /// Calculates the dot product of this vector with another. The dot product + /// is defined as x1*x2+y1*y2+z1*z2. The returned value is a scalar. + pub fn dot( &self, - x: f64, - y: f64, - z: f64, - ) -> Result, Box> { - let sig = String::from("(DDD)Lorg/bukkit/util/EulerAngle;"); - let val_1 = jni::objects::JValueGen::Double(x); - let val_2 = jni::objects::JValueGen::Double(y); - let val_3 = jni::objects::JValueGen::Double(z); + other: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/util/Vector;)D"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(other.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "subtract", + "dot", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::util::EulerAngle::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.d()?) } - - pub fn equals( + /// Calculates the cross product of this vector with another. The cross + /// product is defined as: + ///
      + ///
    • x = y1 * z2 - y2 * z1 + ///
    • y = z1 * x2 - z2 * x1 + ///
    • z = x1 * y2 - x2 * y1 + ///
    + pub fn cross_product( &self, - o: jni::objects::JObject<'mc>, - ) -> Result> { - let sig = String::from("(Ljava/lang/Object;)Z"); - let val_1 = jni::objects::JValueGen::Object(o); + o: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)Lorg/bukkit/util/Vector;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(o.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "equals", + "crossProduct", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - - pub fn hash_code(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct BoundingBox<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for BoundingBox<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for BoundingBox<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate BoundingBox from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/util/BoundingBox")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a BoundingBox object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> BoundingBox<'mc> { - /// Creates a new bounding box from the given corner coordinates. - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - x1: std::option::Option, - y1: std::option::Option, - z1: std::option::Option, - x2: std::option::Option, - y2: std::option::Option, - z2: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = x1 { - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(a); - args.push(val_1); - } - if let Some(a) = y1 { - sig += "D"; - let val_2 = jni::objects::JValueGen::Double(a); - args.push(val_2); - } - if let Some(a) = z1 { - sig += "D"; - let val_3 = jni::objects::JValueGen::Double(a); - args.push(val_3); - } - if let Some(a) = x2 { - sig += "D"; - let val_4 = jni::objects::JValueGen::Double(a); - args.push(val_4); - } - if let Some(a) = y2 { - sig += "D"; - let val_5 = jni::objects::JValueGen::Double(a); - args.push(val_5); - } - if let Some(a) = z2 { - sig += "D"; - let val_6 = jni::objects::JValueGen::Double(a); - args.push(val_6); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/util/BoundingBox"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::util::BoundingBox::from_raw(&jni, res) + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Creates a new bounding box using the given center and extents. - pub fn of( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - center: impl Into>, - x: std::option::Option, - y: std::option::Option, - z: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/Location;"; + /// Calculates the cross product of this vector with another without mutating + /// the original. The cross product is defined as: + ///
      + ///
    • x = y1 * z2 - y2 * z1 + ///
    • y = z1 * x2 - z2 * x1 + ///
    • z = x1 * y2 - x2 * y1 + ///
    + pub fn get_cross_product( + &self, + o: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;)Lorg/bukkit/util/Vector;"); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(center.into().jni_object().clone()) + jni::objects::JObject::from_raw(o.into().jni_object().clone()) }); - args.push(val_1); - if let Some(a) = x { - sig += "D"; - let val_2 = jni::objects::JValueGen::Double(a); - args.push(val_2); - } - if let Some(a) = y { - sig += "D"; - let val_3 = jni::objects::JValueGen::Double(a); - args.push(val_3); - } - if let Some(a) = z { - sig += "D"; - let val_4 = jni::objects::JValueGen::Double(a); - args.push(val_4); - } - sig += ")Lorg/bukkit/util/BoundingBox;"; - let cls = jni.find_class("org/bukkit/util/BoundingBox"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "of", sig.as_str(), args); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::util::BoundingBox::from_raw(&jni, obj) - } - /// Resizes this bounding box. - pub fn resize( - &self, - x1: f64, - y1: f64, - z1: f64, - x2: f64, - y2: f64, - z2: f64, - ) -> Result, Box> { - let sig = String::from("(DDDDDD)Lorg/bukkit/util/BoundingBox;"); - let val_1 = jni::objects::JValueGen::Double(x1); - let val_2 = jni::objects::JValueGen::Double(y1); - let val_3 = jni::objects::JValueGen::Double(z1); - let val_4 = jni::objects::JValueGen::Double(x2); - let val_5 = jni::objects::JValueGen::Double(y2); - let val_6 = jni::objects::JValueGen::Double(z2); let res = self.jni_ref().call_method( &self.jni_object(), - "resize", + "getCrossProduct", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - jni::objects::JValueGen::from(val_4), - jni::objects::JValueGen::from(val_5), - jni::objects::JValueGen::from(val_6), - ], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the minimum x value. - pub fn min_x(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getMinX", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the minimum y value. - pub fn min_y(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getMinY", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the minimum z value. - pub fn min_z(&self) -> Result> { - let sig = String::from("()D"); + /// Converts this vector to a unit vector (a vector with length of 1). + pub fn normalize(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getMinZ", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "normalize", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the minimum corner as vector. - pub fn min(&self) -> Result, Box> { + /// Zero this vector's components. + pub fn zero(&self) -> Result, Box> { let sig = String::from("()Lorg/bukkit/util/Vector;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getMin", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "zero", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the maximum x value. - pub fn max_x(&self) -> Result> { - let sig = String::from("()D"); + /// Check whether or not each component of this vector is equal to 0. + pub fn is_zero(&self) -> Result> { + let sig = String::from("()Z"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getMaxX", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "isZero", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Gets the maximum y value. - pub fn max_y(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getMaxY", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + /// Returns whether this vector is in an axis-aligned bounding box. + /// + /// The minimum and maximum vectors given must be truly the minimum and + /// maximum X, Y and Z components. + pub fn is_in_aabb( + &self, + min: impl Into>, + max: impl Into>, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/util/Vector;Lorg/bukkit/util/Vector;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(min.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(max.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isInAABB", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets the maximum z value. - pub fn max_z(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getMaxZ", sig.as_str(), vec![]); + /// Returns whether this vector is within a sphere. + pub fn is_in_sphere( + &self, + origin: impl Into>, + radius: f64, + ) -> Result> { + let sig = String::from("(Lorg/bukkit/util/Vector;D)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(origin.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Double(radius); + let res = self.jni_ref().call_method( + &self.jni_object(), + "isInSphere", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Gets the maximum corner as vector. - pub fn max(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getMax", sig.as_str(), vec![]); + /// Returns if a vector is normalized + pub fn is_normalized(&self) -> Result> { + let sig = String::from("()Z"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "isNormalized", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Rotates the vector around the x axis. + /// + /// This piece of math is based on the standard rotation matrix for vectors + /// in three dimensional space. This matrix can be found here: + /// Rotation + /// Matrix. + pub fn rotate_around_x( + &self, + angle: f64, + ) -> Result, Box> { + let sig = String::from("(D)Lorg/bukkit/util/Vector;"); + let val_1 = jni::objects::JValueGen::Double(angle); + let res = self.jni_ref().call_method( + &self.jni_object(), + "rotateAroundX", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the width of the bounding box in the x direction. - pub fn width_x(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getWidthX", sig.as_str(), vec![]); + /// Rotates the vector around the y axis. + /// + /// This piece of math is based on the standard rotation matrix for vectors + /// in three dimensional space. This matrix can be found here: + /// Rotation + /// Matrix. + pub fn rotate_around_y( + &self, + angle: f64, + ) -> Result, Box> { + let sig = String::from("(D)Lorg/bukkit/util/Vector;"); + let val_1 = jni::objects::JValueGen::Double(angle); + let res = self.jni_ref().call_method( + &self.jni_object(), + "rotateAroundY", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the width of the bounding box in the z direction. - pub fn width_z(&self) -> Result> { + /// Rotates the vector around the z axis + /// + /// This piece of math is based on the standard rotation matrix for vectors + /// in three dimensional space. This matrix can be found here: + /// Rotation + /// Matrix. + pub fn rotate_around_z( + &self, + angle: f64, + ) -> Result, Box> { + let sig = String::from("(D)Lorg/bukkit/util/Vector;"); + let val_1 = jni::objects::JValueGen::Double(angle); + let res = self.jni_ref().call_method( + &self.jni_object(), + "rotateAroundZ", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Rotates the vector around a given arbitrary axis in 3 dimensional space. + /// + /// Rotation will follow the general Right-Hand-Rule, which means rotation + /// will be counterclockwise when the axis is pointing towards the observer. + /// + /// This method will always make sure the provided axis is a unit vector, to + /// not modify the length of the vector when rotating. If you are experienced + /// with the scaling of a non-unit axis vector, you can use + /// {@link Vector#rotateAroundNonUnitAxis(Vector, double)}. + pub fn rotate_around_axis( + &self, + axis: impl Into>, + angle: f64, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;D)Lorg/bukkit/util/Vector;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(axis.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Double(angle); + let res = self.jni_ref().call_method( + &self.jni_object(), + "rotateAroundAxis", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Rotates the vector around a given arbitrary axis in 3 dimensional space. + /// + /// Rotation will follow the general Right-Hand-Rule, which means rotation + /// will be counterclockwise when the axis is pointing towards the observer. + /// + /// Note that the vector length will change accordingly to the axis vector + /// length. If the provided axis is not a unit vector, the rotated vector + /// will not have its previous length. The scaled length of the resulting + /// vector will be related to the axis vector. If you are not perfectly sure + /// about the scaling of the vector, use + /// {@link Vector#rotateAroundAxis(Vector, double)} + pub fn rotate_around_non_unit_axis( + &self, + axis: impl Into>, + angle: f64, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/util/Vector;D)Lorg/bukkit/util/Vector;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(axis.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Double(angle); + let res = self.jni_ref().call_method( + &self.jni_object(), + "rotateAroundNonUnitAxis", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], + ); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Gets the X component. + pub fn x(&self) -> Result> { let sig = String::from("()D"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getWidthZ", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.d()?) } - /// Gets the height of the bounding box. - pub fn height(&self) -> Result> { - let sig = String::from("()D"); + /// Gets the floored value of the X component, indicating the block that + /// this vector is contained with. + pub fn block_x(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBlockX", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.i()?) } - /// Gets the volume of the bounding box. - pub fn volume(&self) -> Result> { + /// Gets the Y component. + pub fn y(&self) -> Result> { let sig = String::from("()D"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getVolume", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.d()?) } - /// Gets the x coordinate of the center of the bounding box. - pub fn center_x(&self) -> Result> { - let sig = String::from("()D"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCenterX", sig.as_str(), vec![]); + /// Gets the floored value of the Y component, indicating the block that + /// this vector is contained with. + pub fn block_y(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getBlockY", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + Ok(res.i()?) } - /// Gets the y coordinate of the center of the bounding box. - pub fn center_y(&self) -> Result> { + /// Gets the Z component. + pub fn z(&self) -> Result> { let sig = String::from("()D"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCenterY", sig.as_str(), vec![]); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.d()?) } - /// Gets the z coordinate of the center of the bounding box. - pub fn center_z(&self) -> Result> { - let sig = String::from("()D"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getCenterZ", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the center of the bounding box. - pub fn center(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); + /// Gets the floored value of the Z component, indicating the block that + /// this vector is contained with. + pub fn block_z(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getCenter", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Copies another bounding box. - pub fn copy( - &self, - other: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/util/BoundingBox;)Lorg/bukkit/util/BoundingBox;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "copy", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + .call_method(&self.jni_object(), "getBlockZ", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(res.i()?) } - /// Expands this bounding box by the given values in the corresponding - /// directions. - /// - /// Negative values will shrink the bounding box in the corresponding - /// direction. Shrinking will be limited to the point where the affected - /// opposite faces would meet if the they shrank at uniform speeds. - pub fn expand( - &self, - negative_x: f64, - negative_y: std::option::Option, - negative_z: std::option::Option, - positive_x: std::option::Option, - positive_y: std::option::Option, - positive_z: std::option::Option, - ) -> Result, Box> { + /// Set the X component. + pub fn set_x(&self, x: f32) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(negative_x); + sig += "F"; + let val_1 = jni::objects::JValueGen::Float(x); args.push(val_1); - if let Some(a) = negative_y { - sig += "D"; - let val_2 = jni::objects::JValueGen::Double(a); - args.push(val_2); - } - if let Some(a) = negative_z { - sig += "D"; - let val_3 = jni::objects::JValueGen::Double(a); - args.push(val_3); - } - if let Some(a) = positive_x { - sig += "D"; - let val_4 = jni::objects::JValueGen::Double(a); - args.push(val_4); - } - if let Some(a) = positive_y { - sig += "D"; - let val_5 = jni::objects::JValueGen::Double(a); - args.push(val_5); - } - if let Some(a) = positive_z { - sig += "D"; - let val_6 = jni::objects::JValueGen::Double(a); - args.push(val_6); - } - sig += ")Lorg/bukkit/util/BoundingBox;"; + sig += ")Lorg/bukkit/util/Vector;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "expand", sig.as_str(), args); + .call_method(&self.jni_object(), "setX", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Expands this bounding box in the specified direction. - /// - /// Negative values will expand the bounding box in the negative direction, - /// positive values will expand it in the positive direction. The magnitudes - /// of the direction components determine the corresponding amounts of - /// expansion. - pub fn expand_directional( - &self, - dir_x: f64, - dir_y: std::option::Option, - dir_z: std::option::Option, - ) -> Result, Box> { + /// Set the Y component. + pub fn set_y(&self, y: f32) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(dir_x); + sig += "F"; + let val_1 = jni::objects::JValueGen::Float(y); args.push(val_1); - if let Some(a) = dir_y { - sig += "D"; - let val_2 = jni::objects::JValueGen::Double(a); - args.push(val_2); - } - if let Some(a) = dir_z { - sig += "D"; - let val_3 = jni::objects::JValueGen::Double(a); - args.push(val_3); - } - sig += ")Lorg/bukkit/util/BoundingBox;"; - let res = - self.jni_ref() - .call_method(&self.jni_object(), "expandDirectional", sig.as_str(), args); + sig += ")Lorg/bukkit/util/Vector;"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "setY", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Expands this bounding box to contain (or border) the specified position. - pub fn union( - &self, - pos_x: f64, - pos_y: std::option::Option, - pos_z: std::option::Option, - ) -> Result, Box> { + /// Set the Z component. + pub fn set_z(&self, z: f32) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(pos_x); + sig += "F"; + let val_1 = jni::objects::JValueGen::Float(z); args.push(val_1); - if let Some(a) = pos_y { - sig += "D"; - let val_2 = jni::objects::JValueGen::Double(a); - args.push(val_2); - } - if let Some(a) = pos_z { - sig += "D"; - let val_3 = jni::objects::JValueGen::Double(a); - args.push(val_3); - } - sig += ")Lorg/bukkit/util/BoundingBox;"; + sig += ")Lorg/bukkit/util/Vector;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "union", sig.as_str(), args); + .call_method(&self.jni_object(), "setZ", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Resizes this bounding box to represent the intersection of this and the - /// given bounding box. - pub fn intersection( + /// Checks to see if two objects are equal. + /// + /// Only two Vectors can ever return true. This method uses a fuzzy match + /// to account for floating point errors. The epsilon can be retrieved + /// with epsilon. + pub fn equals( &self, - other: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/util/BoundingBox;)Lorg/bukkit/util/BoundingBox;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) - }); + obj: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(Ljava/lang/Object;)Z"); + let val_1 = jni::objects::JValueGen::Object(obj); let res = self.jni_ref().call_method( &self.jni_object(), - "intersection", + "equals", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + Ok(res.z()?) + } + /// Returns a hash code for this vector + pub fn hash_code(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + /// Get a new vector. + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Shifts this bounding box by the given amounts. - pub fn shift( + /// Returns this vector's components as x,y,z. + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) + } + /// Gets a Location version of this vector. + pub fn to_location( &self, - shift_x: f64, - shift_y: std::option::Option, - shift_z: std::option::Option, - ) -> Result, Box> { + world: impl Into>, + yaw: std::option::Option, + pitch: std::option::Option, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(shift_x); + sig += "Lorg/bukkit/World;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(world.into().jni_object().clone()) + }); args.push(val_1); - if let Some(a) = shift_y { - sig += "D"; - let val_2 = jni::objects::JValueGen::Double(a); + if let Some(a) = yaw { + sig += "F"; + let val_2 = jni::objects::JValueGen::Float(a); args.push(val_2); } - if let Some(a) = shift_z { - sig += "D"; - let val_3 = jni::objects::JValueGen::Double(a); + if let Some(a) = pitch { + sig += "F"; + let val_3 = jni::objects::JValueGen::Float(a); args.push(val_3); } - sig += ")Lorg/bukkit/util/BoundingBox;"; + sig += ")Lorg/bukkit/Location;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "shift", sig.as_str(), args); + .call_method(&self.jni_object(), "toLocation", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Checks if this bounding box overlaps with the bounding box that is - /// defined by the given corners. - /// - /// Bounding boxes that are only intersecting at the borders are not - /// considered overlapping. - pub fn overlaps( + /// Get the block vector of this vector. + pub fn to_block_vector( &self, - min: impl Into>, - max: std::option::Option>>, - ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/util/Vector;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(min.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = max { - sig += "Lorg/bukkit/util/Vector;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - sig += ")Z"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "overlaps", sig.as_str(), args); + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/BlockVector;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "toBlockVector", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::util::BlockVector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Checks if this bounding box contains the specified position. - /// - /// Positions exactly on the minimum borders of the bounding box are - /// considered to be inside the bounding box, while positions exactly on the - /// maximum borders are considered to be outside. This allows bounding boxes - /// to reside directly next to each other with positions always only residing - /// in exactly one of them. - pub fn contains( + /// Get this vector as a JOML {@link Vector3f}. + pub fn to_vector3f(&self) -> Result, Box> { + let sig = String::from("()Lorg/joml/Vector3f;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "toVector3f", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) + } + /// Get this vector as a JOML {@link Vector3d}. + pub fn to_vector3d(&self) -> Result, Box> { + let sig = String::from("()Lorg/joml/Vector3d;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "toVector3d", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) + } + /// Get this vector as a JOML {@link Vector3i}. + pub fn to_vector3i( &self, - x: f64, - y: std::option::Option, - z: std::option::Option, - ) -> Result> { + rounding_mode: std::option::Option, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(x); - args.push(val_1); - if let Some(a) = y { - sig += "D"; - let val_2 = jni::objects::JValueGen::Double(a); - args.push(val_2); - } - if let Some(a) = z { - sig += "D"; - let val_3 = jni::objects::JValueGen::Double(a); - args.push(val_3); + if let Some(a) = rounding_mode { + sig += "I"; + let val_1 = jni::objects::JValueGen::Int(a); + args.push(val_1); } - sig += ")Z"; + sig += ")Lorg/joml/Vector3i;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "contains", sig.as_str(), args); + .call_method(&self.jni_object(), "toVector3i", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.l()?) } - /// Calculates the intersection of this bounding box with the specified line - /// segment. - /// - /// Intersections at edges and corners yield one of the affected block faces - /// as hit result, but it is not defined which of them. - pub fn ray_trace( - &self, - start: impl Into>, - direction: impl Into>, - max_distance: f64, - ) -> Result>, Box> { + /// Check if each component of this Vector is finite. + pub fn check_finite(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "checkFinite", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + /// Get the threshold used for equals(). + pub fn epsilon( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + let sig = String::from("()D"); + let cls = jni.find_class("org/bukkit/util/Vector"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getEpsilon", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + Ok(res.d()?) + } + /// Gets the minimum components of two vectors. + pub fn get_minimum( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + v1: impl Into>, + v2: impl Into>, + ) -> Result, Box> { let sig = String::from( - "(Lorg/bukkit/util/Vector;Lorg/bukkit/util/Vector;D)Lorg/bukkit/util/RayTraceResult;", + "(Lorg/bukkit/util/Vector;Lorg/bukkit/util/Vector;)Lorg/bukkit/util/Vector;", ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(start.into().jni_object().clone()) + jni::objects::JObject::from_raw(v1.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(direction.into().jni_object().clone()) + jni::objects::JObject::from_raw(v2.into().jni_object().clone()) }); - let val_3 = jni::objects::JValueGen::Double(max_distance); - let res = self.jni_ref().call_method( - &self.jni_object(), - "rayTrace", + let cls = jni.find_class("org/bukkit/util/Vector"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getMinimum", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), ], ); - let res = self.jni_ref().translate_error(res)?; - if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { - return Ok(None); - } - Ok(Some(crate::util::RayTraceResult::from_raw( - &self.jni_ref(), - unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, - )?)) - } - - pub fn hash_code(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::util::Vector::from_raw(&jni, obj) } - - pub fn equals( - &self, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - let sig = String::from("(Ljava/lang/Object;)Z"); - let val_1 = jni::objects::JValueGen::Object(obj); - let res = self.jni_ref().call_method( - &self.jni_object(), - "equals", + /// Gets the maximum components of two vectors. + pub fn get_maximum( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + v1: impl Into>, + v2: impl Into>, + ) -> Result, Box> { + let sig = String::from( + "(Lorg/bukkit/util/Vector;Lorg/bukkit/util/Vector;)Lorg/bukkit/util/Vector;", + ); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(v1.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(v2.into().jni_object().clone()) + }); + let cls = jni.find_class("org/bukkit/util/Vector"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "getMaximum", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::util::Vector::from_raw(&jni, obj) } - - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + /// Gets a random vector with components having a random value between 0 + /// and 1. + pub fn random( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let cls = jni.find_class("org/bukkit/util/Vector"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getRandom", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::util::Vector::from_raw(&jni, obj) } - /// Creates a copy of this bounding box. - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Gets a vector with components that match the provided JOML {@link Vector3ic}. + pub fn from_joml( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + vector: jni::objects::JObject<'mc>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/joml/Vector3ic;"; + let val_1 = jni::objects::JValueGen::Object(vector); + args.push(val_1); + sig += ")Lorg/bukkit/util/Vector;"; + let cls = jni.find_class("org/bukkit/util/Vector"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "fromJOML", sig.as_str(), args); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::util::Vector::from_raw(&jni, obj) } pub fn serialize( @@ -1110,12 +955,12 @@ impl<'mc> BoundingBox<'mc> { pub fn deserialize( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_args: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Ljava/util/Map;)Lorg/bukkit/util/BoundingBox;"); + ) -> Result, Box> { + let sig = String::from("(Ljava/util/Map;)Lorg/bukkit/util/Vector;"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(val_args.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/util/BoundingBox"); + let cls = jni.find_class("org/bukkit/util/Vector"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method( cls, @@ -1125,7 +970,7 @@ impl<'mc> BoundingBox<'mc> { ); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::util::BoundingBox::from_raw(&jni, obj) + crate::util::Vector::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1134,29 +979,29 @@ impl<'mc> BoundingBox<'mc> { } } -impl<'mc> std::string::ToString for BoundingBox<'mc> { +impl<'mc> std::string::ToString for Vector<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling BoundingBox.toString: {}", err), + Err(err) => format!("Error calling Vector.toString: {}", err), } } } impl<'mc> Into> - for BoundingBox<'mc> + for Vector<'mc> { fn into(self) -> crate::configuration::serialization::ConfigurationSerializable<'mc> { - crate::configuration::serialization::ConfigurationSerializable::from_raw(&self.jni_ref(), self.1).expect("Error converting BoundingBox into crate::configuration::serialization::ConfigurationSerializable") + crate::configuration::serialization::ConfigurationSerializable::from_raw(&self.jni_ref(), self.1).expect("Error converting Vector into crate::configuration::serialization::ConfigurationSerializable") } } #[repr(C)] -pub struct ChatPaginator<'mc>( +pub struct Transformation<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ChatPaginator<'mc> { +impl<'mc> JNIRaw<'mc> for Transformation<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1164,18 +1009,20 @@ impl<'mc> JNIRaw<'mc> for ChatPaginator<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ChatPaginator<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Transformation<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate ChatPaginator from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate Transformation from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/util/ChatPaginator")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/util/Transformation")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ChatPaginator object, got {}", + "Invalid argument passed. Expected a Transformation object, got {}", name ) .into()) @@ -1185,78 +1032,109 @@ impl<'mc> JNIInstantiatable<'mc> for ChatPaginator<'mc> { } } -impl<'mc> ChatPaginator<'mc> { +impl<'mc> Transformation<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/util/ChatPaginator"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), vec![]); - let res = jni.translate_error_no_gen(res)?; - crate::util::ChatPaginator::from_raw(&jni, res) - } - /// Breaks a raw string up into pages using a provided width and height. - pub fn paginate( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - unpaginated_string: impl Into, - page_number: i32, - line_length: std::option::Option, - page_height: std::option::Option, - ) -> Result, Box> { + translation: jni::objects::JObject<'mc>, + left_rotation: jni::objects::JObject<'mc>, + scale: jni::objects::JObject<'mc>, + right_rotation: jni::objects::JObject<'mc>, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Ljava/lang/String;"; - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(unpaginated_string.into())?, - )); + sig += "Lorg/joml/Vector3f;"; + let val_1 = jni::objects::JValueGen::Object(translation); args.push(val_1); - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(page_number); + sig += "Lorg/joml/Quaternionf;"; + let val_2 = jni::objects::JValueGen::Object(left_rotation); args.push(val_2); - if let Some(a) = line_length { - sig += "I"; - let val_3 = jni::objects::JValueGen::Int(a); - args.push(val_3); - } - if let Some(a) = page_height { - sig += "I"; - let val_4 = jni::objects::JValueGen::Int(a); - args.push(val_4); - } - sig += ")Lorg/bukkit/util/ChatPaginator/ChatPage;"; - let cls = jni.find_class("org/bukkit/util/ChatPaginator"); + sig += "Lorg/joml/Vector3f;"; + let val_3 = jni::objects::JValueGen::Object(scale); + args.push(val_3); + sig += "Lorg/joml/Quaternionf;"; + let val_4 = jni::objects::JValueGen::Object(right_rotation); + args.push(val_4); + sig += ")V"; + let cls = jni.find_class("org/bukkit/util/Transformation"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "paginate", sig.as_str(), args); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::util::ChatPaginatorChatPage::from_raw(&jni, obj) + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::util::Transformation::from_raw(&jni, res) } - /// Breaks a raw string up into a series of lines. Words are wrapped using - /// spaces as decimeters and the newline character is respected. - pub fn word_wrap( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - raw_string: impl Into, - line_length: i32, - ) -> Result> { - let sig = String::from("(Ljava/lang/String;I)Ljava/lang/String;"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(raw_string.into())?, - )); - let val_2 = jni::objects::JValueGen::Int(line_length); - let cls = jni.find_class("org/bukkit/util/ChatPaginator"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "wordWrap", + /// Gets the translation component of this transformation. + pub fn translation(&self) -> Result, Box> { + let sig = String::from("()Lorg/joml/Vector3f;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getTranslation", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) + } + /// Gets the left rotation component of this transformation. + pub fn left_rotation(&self) -> Result, Box> { + let sig = String::from("()Lorg/joml/Quaternionf;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLeftRotation", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) + } + /// Gets the scale component of this transformation. + pub fn scale(&self) -> Result, Box> { + let sig = String::from("()Lorg/joml/Vector3f;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getScale", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) + } + /// Gets the right rotation component of this transformation. + pub fn right_rotation(&self) -> Result, Box> { + let sig = String::from("()Lorg/joml/Quaternionf;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getRightRotation", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![], ); - let res = jni.translate_error(res)?; - Ok(jni + let res = self.jni_ref().translate_error(res)?; + Ok(res.l()?) + } + + pub fn hash_code(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + + pub fn equals( + &self, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(Ljava/lang/Object;)Z"); + let val_1 = jni::objects::JValueGen::Object(obj); + let res = self.jni_ref().call_method( + &self.jni_object(), + "equals", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? .to_string_lossy() .to_string()) @@ -1267,13 +1145,23 @@ impl<'mc> ChatPaginator<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } + +impl<'mc> std::string::ToString for Transformation<'mc> { + fn to_string(&self) -> String { + match &self.internal_to_string() { + Ok(a) => a.clone(), + Err(err) => format!("Error calling Transformation.toString: {}", err), + } + } +} + #[repr(C)] -pub struct ChatPaginatorChatPage<'mc>( +pub struct StringUtil<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for ChatPaginatorChatPage<'mc> { +impl<'mc> JNIRaw<'mc> for StringUtil<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1281,21 +1169,18 @@ impl<'mc> JNIRaw<'mc> for ChatPaginatorChatPage<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for ChatPaginatorChatPage<'mc> { +impl<'mc> JNIInstantiatable<'mc> for StringUtil<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate ChatPaginatorChatPage from null object." - ) - .into()); + return Err(eyre::eyre!("Tried to instantiate StringUtil from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/util/ChatPaginator/ChatPage")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/util/StringUtil")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a ChatPaginatorChatPage object, got {}", + "Invalid argument passed. Expected a StringUtil object, got {}", name ) .into()) @@ -1305,260 +1190,45 @@ impl<'mc> JNIInstantiatable<'mc> for ChatPaginatorChatPage<'mc> { } } -impl<'mc> ChatPaginatorChatPage<'mc> { +impl<'mc> StringUtil<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - lines: impl Into, - page_number: i32, - total_pages: i32, - ) -> Result, Box> { - let sig = String::from("(Ljava/lang/String;II)V"); + ) -> Result, Box> { + let sig = String::from("()V"); + let cls = jni.find_class("org/bukkit/util/StringUtil"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), vec![]); + let res = jni.translate_error_no_gen(res)?; + crate::util::StringUtil::from_raw(&jni, res) + } + /// This method uses a region to check case-insensitive equality. This + /// means the internal array does not need to be copied like a + /// toLowerCase() call would. + pub fn starts_with_ignore_case( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + string: impl Into, + prefix: impl Into, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;Ljava/lang/String;)Z"); let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(lines.into())?, + jni.new_string(string.into())?, )); - let val_2 = jni::objects::JValueGen::Int(page_number); - let val_3 = jni::objects::JValueGen::Int(total_pages); - let cls = jni.find_class("org/bukkit/util/ChatPaginator/ChatPage"); + let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(prefix.into())?, + )); + let cls = jni.find_class("org/bukkit/util/StringUtil"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object( + let res = jni.call_static_method( cls, + "startsWithIgnoreCase", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), ], ); - let res = jni.translate_error_no_gen(res)?; - crate::util::ChatPaginatorChatPage::from_raw(&jni, res) - } - - pub fn page_number(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getPageNumber", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - - pub fn total_pages(&self) -> Result> { - let sig = String::from("()I"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTotalPages", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - - pub fn lines(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getLines", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct CachedServerIcon<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for CachedServerIcon<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for CachedServerIcon<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate CachedServerIcon from null object.").into(), - ); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/util/CachedServerIcon")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a CachedServerIcon object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> CachedServerIcon<'mc> { - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -#[repr(C)] -pub struct Consumer<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for Consumer<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for Consumer<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Consumer from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/util/Consumer")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a Consumer object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> Consumer<'mc> { - pub fn from_extendable( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - plugin: &'mc crate::plugin::Plugin, - address: i32, - lib_name: String, - name: String, - ) -> Result> { - let obj = unsafe { plugin.new_extendable(address, "Consumer", name, lib_name) }?; - Self::from_raw(env, obj) - } - /// Performs this operation on the given argument. - pub fn accept(&self, t: jni::objects::JObject<'mc>) -> Result<(), Box> { - let sig = String::from("(LT;)V"); - let val_1 = jni::objects::JValueGen::Object(t); - let res = self.jni_ref().call_method( - &self.jni_object(), - "accept", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) - } - - pub fn instance_of(&self, other: impl Into) -> Result { - let cls = &self.jni_ref().find_class(other.into().as_str())?; - self.jni_ref().is_instance_of(&self.jni_object(), cls) - } -} -impl<'mc> Into> for Consumer<'mc> { - fn into(self) -> blackboxmc_java::util::function::JavaConsumer<'mc> { - blackboxmc_java::util::function::JavaConsumer::from_raw(&self.jni_ref(), self.1) - .expect("Error converting Consumer into blackboxmc_java::util::function::JavaConsumer") - } -} -#[repr(C)] -pub struct VoxelShape<'mc>( - pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, - pub(crate) jni::objects::JObject<'mc>, -); - -impl<'mc> JNIRaw<'mc> for VoxelShape<'mc> { - fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { - self.0.clone() - } - fn jni_object(&self) -> jni::objects::JObject<'mc> { - unsafe { jni::objects::JObject::from_raw(self.1.clone()) } - } -} -impl<'mc> JNIInstantiatable<'mc> for VoxelShape<'mc> { - fn from_raw( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate VoxelShape from null object.").into()); - } - let (valid, name) = env.validate_name(&obj, "org/bukkit/util/VoxelShape")?; - if !valid { - Err(eyre::eyre!( - "Invalid argument passed. Expected a VoxelShape object, got {}", - name - ) - .into()) - } else { - Ok(Self(env.clone(), obj)) - } - } -} - -impl<'mc> VoxelShape<'mc> { - /// Converts this shape into a collection of {@link BoundingBox} equivalent - /// to the shape: a bounding box intersects with this block shape if it - /// intersects with any of the shape's bounding boxes. - pub fn bounding_boxes( - &self, - ) -> Result>, Box> { - let sig = String::from("()Ljava/util/Collection;"); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getBoundingBoxes", - sig.as_str(), - vec![], - ); - let res = self.jni_ref().translate_error(res)?; - let mut new_vec = Vec::new(); - let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; - let iter = col.iterator()?; - while iter.has_next()? { - let obj = iter.next()?; - new_vec.push(crate::util::BoundingBox::from_raw(&self.jni_ref(), obj)?); - } - Ok(new_vec) - } - /// Checks if the given bounding box intersects this block shape. - pub fn overlaps( - &self, - other: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/util/BoundingBox;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "overlaps", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let res = jni.translate_error(res)?; + Ok(res.z()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -1830,12 +1500,12 @@ impl<'mc> NumberConversions<'mc> { } } #[repr(C)] -pub struct Vector<'mc>( +pub struct FileUtil<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Vector<'mc> { +impl<'mc> JNIRaw<'mc> for FileUtil<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -1843,18 +1513,18 @@ impl<'mc> JNIRaw<'mc> for Vector<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Vector<'mc> { +impl<'mc> JNIInstantiatable<'mc> for FileUtil<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate Vector from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate FileUtil from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/util/Vector")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/util/FileUtil")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Vector object, got {}", + "Invalid argument passed. Expected a FileUtil object, got {}", name ) .into()) @@ -1864,906 +1534,898 @@ impl<'mc> JNIInstantiatable<'mc> for Vector<'mc> { } } -impl<'mc> Vector<'mc> { - /// Construct the vector with provided float components. +impl<'mc> FileUtil<'mc> { pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - x: std::option::Option, - y: std::option::Option, - z: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - if let Some(a) = x { - sig += "F"; - let val_1 = jni::objects::JValueGen::Float(a); - args.push(val_1); - } - if let Some(a) = y { - sig += "F"; - let val_2 = jni::objects::JValueGen::Float(a); - args.push(val_2); - } - if let Some(a) = z { - sig += "F"; - let val_3 = jni::objects::JValueGen::Float(a); - args.push(val_3); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/util/Vector"); + ) -> Result, Box> { + let sig = String::from("()V"); + let cls = jni.find_class("org/bukkit/util/FileUtil"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.new_object(cls, sig.as_str(), vec![]); let res = jni.translate_error_no_gen(res)?; - crate::util::Vector::from_raw(&jni, res) - } - /// Adds a vector to this one - pub fn add( - &self, - vec: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)Lorg/bukkit/util/Vector;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(vec.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "add", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Subtracts a vector from this one. - pub fn subtract( - &self, - vec: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)Lorg/bukkit/util/Vector;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(vec.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "subtract", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Performs scalar multiplication, multiplying all components with a - /// scalar. - pub fn multiply(&self, m: f32) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "F"; - let val_1 = jni::objects::JValueGen::Float(m); - args.push(val_1); - sig += ")Lorg/bukkit/util/Vector;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "multiply", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Divides the vector by another. - pub fn divide( - &self, - vec: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)Lorg/bukkit/util/Vector;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(vec.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "divide", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Copies another vector - pub fn copy( - &self, - vec: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)Lorg/bukkit/util/Vector;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(vec.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "copy", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Gets the magnitude of the vector, defined as sqrt(x^2+y^2+z^2). The - /// value of this method is not cached and uses a costly square-root - /// function, so do not repeatedly call this method to get the vector's - /// magnitude. NaN will be returned if the inner result of the sqrt() - /// function overflows, which will be caused if the length is too long. - pub fn length(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "length", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) - } - /// Gets the magnitude of the vector squared. - pub fn length_squared(&self) -> Result> { - let sig = String::from("()D"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "lengthSquared", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + crate::util::FileUtil::from_raw(&jni, res) } - /// Get the distance between this vector and another. The value of this - /// method is not cached and uses a costly square-root function, so do not - /// repeatedly call this method to get the vector's magnitude. NaN will be - /// returned if the inner result of the sqrt() function overflows, which - /// will be caused if the distance is too long. - pub fn distance( - &self, - o: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/util/Vector;)D"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(o.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "distance", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Get the squared distance between this vector and another. - pub fn distance_squared( - &self, - o: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/util/Vector;)D"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(o.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "distanceSquared", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) +} +#[repr(C)] +pub struct ChatPaginator<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ChatPaginator<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Gets the angle between this vector and another in radians. - pub fn angle( - &self, - other: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/util/Vector;)F"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "angle", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.f()?) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Sets this vector to the midpoint between this vector and another. - pub fn midpoint( - &self, - other: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)Lorg/bukkit/util/Vector;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "midpoint", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} +impl<'mc> JNIInstantiatable<'mc> for ChatPaginator<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate ChatPaginator from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/util/ChatPaginator")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ChatPaginator object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } - /// Gets a new midpoint vector between this vector and another. - pub fn get_midpoint( - &self, - other: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)Lorg/bukkit/util/Vector;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getMidpoint", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} + +impl<'mc> ChatPaginator<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()V"); + let cls = jni.find_class("org/bukkit/util/ChatPaginator"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), vec![]); + let res = jni.translate_error_no_gen(res)?; + crate::util::ChatPaginator::from_raw(&jni, res) } - /// Calculates the dot product of this vector with another. The dot product - /// is defined as x1*x2+y1*y2+z1*z2. The returned value is a scalar. - pub fn dot( - &self, - other: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/util/Vector;)D"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(other.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "dot", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + /// Breaks a raw string up into pages using a provided width and height. + pub fn paginate( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + unpaginated_string: impl Into, + page_number: i32, + line_length: std::option::Option, + page_height: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/lang/String;"; + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(unpaginated_string.into())?, + )); + args.push(val_1); + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(page_number); + args.push(val_2); + if let Some(a) = line_length { + sig += "I"; + let val_3 = jni::objects::JValueGen::Int(a); + args.push(val_3); + } + if let Some(a) = page_height { + sig += "I"; + let val_4 = jni::objects::JValueGen::Int(a); + args.push(val_4); + } + sig += ")Lorg/bukkit/util/ChatPaginator/ChatPage;"; + let cls = jni.find_class("org/bukkit/util/ChatPaginator"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "paginate", sig.as_str(), args); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::util::ChatPaginatorChatPage::from_raw(&jni, obj) } - /// Calculates the cross product of this vector with another. The cross - /// product is defined as: - ///
      - ///
    • x = y1 * z2 - y2 * z1 - ///
    • y = z1 * x2 - z2 * x1 - ///
    • z = x1 * y2 - x2 * y1 - ///
    - pub fn cross_product( - &self, - o: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)Lorg/bukkit/util/Vector;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(o.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "crossProduct", + /// Breaks a raw string up into a series of lines. Words are wrapped using + /// spaces as decimeters and the newline character is respected. + pub fn word_wrap( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + raw_string: impl Into, + line_length: i32, + ) -> Result> { + let sig = String::from("(Ljava/lang/String;I)Ljava/lang/String;"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(raw_string.into())?, + )); + let val_2 = jni::objects::JValueGen::Int(line_length); + let cls = jni.find_class("org/bukkit/util/ChatPaginator"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "wordWrap", sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + ], ); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + let res = jni.translate_error(res)?; + Ok(jni + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Calculates the cross product of this vector with another without mutating - /// the original. The cross product is defined as: - ///
      - ///
    • x = y1 * z2 - y2 * z1 - ///
    • y = z1 * x2 - z2 * x1 - ///
    • z = x1 * y2 - x2 * y1 - ///
    - pub fn get_cross_product( - &self, - o: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;)Lorg/bukkit/util/Vector;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(o.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "getCrossProduct", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Converts this vector to a unit vector (a vector with length of 1). - pub fn normalize(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "normalize", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} +#[repr(C)] +pub struct ChatPaginatorChatPage<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for ChatPaginatorChatPage<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Zero this vector's components. - pub fn zero(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "zero", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Check whether or not each component of this vector is equal to 0. - pub fn is_zero(&self) -> Result> { - let sig = String::from("()Z"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "isZero", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) +} +impl<'mc> JNIInstantiatable<'mc> for ChatPaginatorChatPage<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate ChatPaginatorChatPage from null object." + ) + .into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/util/ChatPaginator/ChatPage")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a ChatPaginatorChatPage object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } - /// Returns whether this vector is in an axis-aligned bounding box. - /// - /// The minimum and maximum vectors given must be truly the minimum and - /// maximum X, Y and Z components. - pub fn is_in_aabb( - &self, - min: impl Into>, - max: impl Into>, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/util/Vector;Lorg/bukkit/util/Vector;)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(min.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(max.into().jni_object().clone()) - }); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isInAABB", +} + +impl<'mc> ChatPaginatorChatPage<'mc> { + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + lines: impl Into, + page_number: i32, + total_pages: i32, + ) -> Result, Box> { + let sig = String::from("(Ljava/lang/String;II)V"); + let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( + jni.new_string(lines.into())?, + )); + let val_2 = jni::objects::JValueGen::Int(page_number); + let val_3 = jni::objects::JValueGen::Int(total_pages); + let cls = jni.find_class("org/bukkit/util/ChatPaginator/ChatPage"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object( + cls, sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), ], ); - let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + let res = jni.translate_error_no_gen(res)?; + crate::util::ChatPaginatorChatPage::from_raw(&jni, res) } - /// Returns whether this vector is within a sphere. - pub fn is_in_sphere( - &self, - origin: impl Into>, - radius: f64, - ) -> Result> { - let sig = String::from("(Lorg/bukkit/util/Vector;D)Z"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(origin.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Double(radius); - let res = self.jni_ref().call_method( - &self.jni_object(), - "isInSphere", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + + pub fn page_number(&self) -> Result> { + let sig = String::from("()I"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getPageNumber", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Returns if a vector is normalized - pub fn is_normalized(&self) -> Result> { - let sig = String::from("()Z"); + + pub fn total_pages(&self) -> Result> { + let sig = String::from("()I"); let res = self.jni_ref() - .call_method(&self.jni_object(), "isNormalized", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getTotalPages", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + Ok(res.i()?) } - /// Rotates the vector around the x axis. - /// - /// This piece of math is based on the standard rotation matrix for vectors - /// in three dimensional space. This matrix can be found here: - /// Rotation - /// Matrix. - pub fn rotate_around_x( - &self, - angle: f64, - ) -> Result, Box> { - let sig = String::from("(D)Lorg/bukkit/util/Vector;"); - let val_1 = jni::objects::JValueGen::Double(angle); - let res = self.jni_ref().call_method( - &self.jni_object(), - "rotateAroundX", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); + + pub fn lines(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getLines", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Rotates the vector around the y axis. - /// - /// This piece of math is based on the standard rotation matrix for vectors - /// in three dimensional space. This matrix can be found here: - /// Rotation - /// Matrix. - pub fn rotate_around_y( - &self, - angle: f64, - ) -> Result, Box> { - let sig = String::from("(D)Lorg/bukkit/util/Vector;"); - let val_1 = jni::objects::JValueGen::Double(angle); - let res = self.jni_ref().call_method( - &self.jni_object(), - "rotateAroundY", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Rotates the vector around the z axis - /// - /// This piece of math is based on the standard rotation matrix for vectors - /// in three dimensional space. This matrix can be found here: - /// Rotation - /// Matrix. - pub fn rotate_around_z( - &self, - angle: f64, - ) -> Result, Box> { - let sig = String::from("(D)Lorg/bukkit/util/Vector;"); - let val_1 = jni::objects::JValueGen::Double(angle); - let res = self.jni_ref().call_method( - &self.jni_object(), - "rotateAroundZ", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +} +#[repr(C)] +pub struct BoundingBox<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for BoundingBox<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Rotates the vector around a given arbitrary axis in 3 dimensional space. - /// - /// Rotation will follow the general Right-Hand-Rule, which means rotation - /// will be counterclockwise when the axis is pointing towards the observer. - /// - /// This method will always make sure the provided axis is a unit vector, to - /// not modify the length of the vector when rotating. If you are experienced - /// with the scaling of a non-unit axis vector, you can use - /// {@link Vector#rotateAroundNonUnitAxis(Vector, double)}. - pub fn rotate_around_axis( + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for BoundingBox<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate BoundingBox from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/util/BoundingBox")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BoundingBox object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> BoundingBox<'mc> { + /// Creates a new bounding box from the given corner coordinates. + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + x1: std::option::Option, + y1: std::option::Option, + z1: std::option::Option, + x2: std::option::Option, + y2: std::option::Option, + z2: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + if let Some(a) = x1 { + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(a); + args.push(val_1); + } + if let Some(a) = y1 { + sig += "D"; + let val_2 = jni::objects::JValueGen::Double(a); + args.push(val_2); + } + if let Some(a) = z1 { + sig += "D"; + let val_3 = jni::objects::JValueGen::Double(a); + args.push(val_3); + } + if let Some(a) = x2 { + sig += "D"; + let val_4 = jni::objects::JValueGen::Double(a); + args.push(val_4); + } + if let Some(a) = y2 { + sig += "D"; + let val_5 = jni::objects::JValueGen::Double(a); + args.push(val_5); + } + if let Some(a) = z2 { + sig += "D"; + let val_6 = jni::objects::JValueGen::Double(a); + args.push(val_6); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/util/BoundingBox"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::util::BoundingBox::from_raw(&jni, res) + } + /// Creates a new bounding box using the given center and extents. + pub fn of( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + center: impl Into>, + x: std::option::Option, + y: std::option::Option, + z: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/Location;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(center.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = x { + sig += "D"; + let val_2 = jni::objects::JValueGen::Double(a); + args.push(val_2); + } + if let Some(a) = y { + sig += "D"; + let val_3 = jni::objects::JValueGen::Double(a); + args.push(val_3); + } + if let Some(a) = z { + sig += "D"; + let val_4 = jni::objects::JValueGen::Double(a); + args.push(val_4); + } + sig += ")Lorg/bukkit/util/BoundingBox;"; + let cls = jni.find_class("org/bukkit/util/BoundingBox"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "of", sig.as_str(), args); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::util::BoundingBox::from_raw(&jni, obj) + } + /// Resizes this bounding box. + pub fn resize( &self, - axis: impl Into>, - angle: f64, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;D)Lorg/bukkit/util/Vector;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(axis.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Double(angle); + x1: f64, + y1: f64, + z1: f64, + x2: f64, + y2: f64, + z2: f64, + ) -> Result, Box> { + let sig = String::from("(DDDDDD)Lorg/bukkit/util/BoundingBox;"); + let val_1 = jni::objects::JValueGen::Double(x1); + let val_2 = jni::objects::JValueGen::Double(y1); + let val_3 = jni::objects::JValueGen::Double(z1); + let val_4 = jni::objects::JValueGen::Double(x2); + let val_5 = jni::objects::JValueGen::Double(y2); + let val_6 = jni::objects::JValueGen::Double(z2); let res = self.jni_ref().call_method( &self.jni_object(), - "rotateAroundAxis", + "resize", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + jni::objects::JValueGen::from(val_5), + jni::objects::JValueGen::from(val_6), ], ); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Rotates the vector around a given arbitrary axis in 3 dimensional space. - /// - /// Rotation will follow the general Right-Hand-Rule, which means rotation - /// will be counterclockwise when the axis is pointing towards the observer. - /// - /// Note that the vector length will change accordingly to the axis vector - /// length. If the provided axis is not a unit vector, the rotated vector - /// will not have its previous length. The scaled length of the resulting - /// vector will be related to the axis vector. If you are not perfectly sure - /// about the scaling of the vector, use - /// {@link Vector#rotateAroundAxis(Vector, double)} - pub fn rotate_around_non_unit_axis( - &self, - axis: impl Into>, - angle: f64, - ) -> Result, Box> { - let sig = String::from("(Lorg/bukkit/util/Vector;D)Lorg/bukkit/util/Vector;"); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(axis.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Double(angle); - let res = self.jni_ref().call_method( - &self.jni_object(), - "rotateAroundNonUnitAxis", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], - ); + /// Gets the minimum x value. + pub fn min_x(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getMinX", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the minimum y value. + pub fn min_y(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getMinY", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the minimum z value. + pub fn min_z(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getMinZ", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the minimum corner as vector. + pub fn min(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getMin", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; crate::util::Vector::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Gets the X component. - pub fn x(&self) -> Result> { + /// Gets the maximum x value. + pub fn max_x(&self) -> Result> { let sig = String::from("()D"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxX", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.d()?) } - /// Gets the floored value of the X component, indicating the block that - /// this vector is contained with. - pub fn block_x(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the maximum y value. + pub fn max_y(&self) -> Result> { + let sig = String::from("()D"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getBlockX", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxY", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.d()?) } - /// Gets the Y component. - pub fn y(&self) -> Result> { + /// Gets the maximum z value. + pub fn max_z(&self) -> Result> { let sig = String::from("()D"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMaxZ", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.d()?) } - /// Gets the floored value of the Y component, indicating the block that - /// this vector is contained with. - pub fn block_y(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the maximum corner as vector. + pub fn max(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getBlockY", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getMax", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Gets the Z component. - pub fn z(&self) -> Result> { + /// Gets the width of the bounding box in the x direction. + pub fn width_x(&self) -> Result> { let sig = String::from("()D"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getWidthX", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; Ok(res.d()?) } - /// Gets the floored value of the Z component, indicating the block that - /// this vector is contained with. - pub fn block_z(&self) -> Result> { - let sig = String::from("()I"); + /// Gets the width of the bounding box in the z direction. + pub fn width_z(&self) -> Result> { + let sig = String::from("()D"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getBlockZ", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getWidthZ", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + Ok(res.d()?) } - /// Set the X component. - pub fn set_x(&self, x: f32) -> Result, Box> { + /// Gets the height of the bounding box. + pub fn height(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getHeight", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the volume of the bounding box. + pub fn volume(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getVolume", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the x coordinate of the center of the bounding box. + pub fn center_x(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCenterX", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the y coordinate of the center of the bounding box. + pub fn center_y(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCenterY", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the z coordinate of the center of the bounding box. + pub fn center_z(&self) -> Result> { + let sig = String::from("()D"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getCenterZ", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) + } + /// Gets the center of the bounding box. + pub fn center(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/Vector;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getCenter", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Copies another bounding box. + pub fn copy( + &self, + other: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/util/BoundingBox;)Lorg/bukkit/util/BoundingBox;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(other.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "copy", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Expands this bounding box by the given values in the corresponding + /// directions. + /// + /// Negative values will shrink the bounding box in the corresponding + /// direction. Shrinking will be limited to the point where the affected + /// opposite faces would meet if the they shrank at uniform speeds. + pub fn expand( + &self, + negative_x: f64, + negative_y: std::option::Option, + negative_z: std::option::Option, + positive_x: std::option::Option, + positive_y: std::option::Option, + positive_z: std::option::Option, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "F"; - let val_1 = jni::objects::JValueGen::Float(x); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(negative_x); args.push(val_1); - sig += ")Lorg/bukkit/util/Vector;"; + if let Some(a) = negative_y { + sig += "D"; + let val_2 = jni::objects::JValueGen::Double(a); + args.push(val_2); + } + if let Some(a) = negative_z { + sig += "D"; + let val_3 = jni::objects::JValueGen::Double(a); + args.push(val_3); + } + if let Some(a) = positive_x { + sig += "D"; + let val_4 = jni::objects::JValueGen::Double(a); + args.push(val_4); + } + if let Some(a) = positive_y { + sig += "D"; + let val_5 = jni::objects::JValueGen::Double(a); + args.push(val_5); + } + if let Some(a) = positive_z { + sig += "D"; + let val_6 = jni::objects::JValueGen::Double(a); + args.push(val_6); + } + sig += ")Lorg/bukkit/util/BoundingBox;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "setX", sig.as_str(), args); + .call_method(&self.jni_object(), "expand", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Set the Y component. - pub fn set_y(&self, y: f32) -> Result, Box> { + /// Expands this bounding box in the specified direction. + /// + /// Negative values will expand the bounding box in the negative direction, + /// positive values will expand it in the positive direction. The magnitudes + /// of the direction components determine the corresponding amounts of + /// expansion. + pub fn expand_directional( + &self, + dir_x: f64, + dir_y: std::option::Option, + dir_z: std::option::Option, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "F"; - let val_1 = jni::objects::JValueGen::Float(y); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(dir_x); args.push(val_1); - sig += ")Lorg/bukkit/util/Vector;"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "setY", sig.as_str(), args); + if let Some(a) = dir_y { + sig += "D"; + let val_2 = jni::objects::JValueGen::Double(a); + args.push(val_2); + } + if let Some(a) = dir_z { + sig += "D"; + let val_3 = jni::objects::JValueGen::Double(a); + args.push(val_3); + } + sig += ")Lorg/bukkit/util/BoundingBox;"; + let res = + self.jni_ref() + .call_method(&self.jni_object(), "expandDirectional", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Set the Z component. - pub fn set_z(&self, z: f32) -> Result, Box> { + /// Expands this bounding box to contain (or border) the specified position. + pub fn union( + &self, + pos_x: f64, + pos_y: std::option::Option, + pos_z: std::option::Option, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "F"; - let val_1 = jni::objects::JValueGen::Float(z); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(pos_x); args.push(val_1); - sig += ")Lorg/bukkit/util/Vector;"; + if let Some(a) = pos_y { + sig += "D"; + let val_2 = jni::objects::JValueGen::Double(a); + args.push(val_2); + } + if let Some(a) = pos_z { + sig += "D"; + let val_3 = jni::objects::JValueGen::Double(a); + args.push(val_3); + } + sig += ")Lorg/bukkit/util/BoundingBox;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "setZ", sig.as_str(), args); + .call_method(&self.jni_object(), "union", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Checks to see if two objects are equal. - /// - /// Only two Vectors can ever return true. This method uses a fuzzy match - /// to account for floating point errors. The epsilon can be retrieved - /// with epsilon. - pub fn equals( + /// Resizes this bounding box to represent the intersection of this and the + /// given bounding box. + pub fn intersection( &self, - obj: jni::objects::JObject<'mc>, - ) -> Result> { - let sig = String::from("(Ljava/lang/Object;)Z"); - let val_1 = jni::objects::JValueGen::Object(obj); + other: impl Into>, + ) -> Result, Box> { + let sig = String::from("(Lorg/bukkit/util/BoundingBox;)Lorg/bukkit/util/BoundingBox;"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(other.into().jni_object().clone()) + }); let res = self.jni_ref().call_method( &self.jni_object(), - "equals", + "intersection", sig.as_str(), vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) - } - /// Returns a hash code for this vector - pub fn hash_code(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) - } - /// Get a new vector. - pub fn clone(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::Vector::from_raw(&self.jni_ref(), unsafe { + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Returns this vector's components as x,y,z. - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) - } - /// Gets a Location version of this vector. - pub fn to_location( + /// Shifts this bounding box by the given amounts. + pub fn shift( &self, - world: impl Into>, - yaw: std::option::Option, - pitch: std::option::Option, - ) -> Result, Box> { + shift_x: f64, + shift_y: std::option::Option, + shift_z: std::option::Option, + ) -> Result, Box> { let mut args = Vec::new(); let mut sig = String::from("("); - sig += "Lorg/bukkit/World;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(shift_x); args.push(val_1); - if let Some(a) = yaw { - sig += "F"; - let val_2 = jni::objects::JValueGen::Float(a); + if let Some(a) = shift_y { + sig += "D"; + let val_2 = jni::objects::JValueGen::Double(a); args.push(val_2); } - if let Some(a) = pitch { - sig += "F"; - let val_3 = jni::objects::JValueGen::Float(a); + if let Some(a) = shift_z { + sig += "D"; + let val_3 = jni::objects::JValueGen::Double(a); args.push(val_3); } - sig += ")Lorg/bukkit/Location;"; + sig += ")Lorg/bukkit/util/BoundingBox;"; let res = self .jni_ref() - .call_method(&self.jni_object(), "toLocation", sig.as_str(), args); + .call_method(&self.jni_object(), "shift", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - /// Get the block vector of this vector. - pub fn to_block_vector( + /// Checks if this bounding box overlaps with the bounding box that is + /// defined by the given corners. + /// + /// Bounding boxes that are only intersecting at the borders are not + /// considered overlapping. + pub fn overlaps( &self, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/BlockVector;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "toBlockVector", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::util::BlockVector::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) - } - /// Get this vector as a JOML {@link Vector3f}. - pub fn to_vector3f(&self) -> Result, Box> { - let sig = String::from("()Lorg/joml/Vector3f;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "toVector3f", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) - } - /// Get this vector as a JOML {@link Vector3d}. - pub fn to_vector3d(&self) -> Result, Box> { - let sig = String::from("()Lorg/joml/Vector3d;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "toVector3d", sig.as_str(), vec![]); + min: impl Into>, + max: std::option::Option>>, + ) -> Result> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/util/Vector;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(min.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = max { + sig += "Lorg/bukkit/util/Vector;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + sig += ")Z"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "overlaps", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) + Ok(res.z()?) } - /// Get this vector as a JOML {@link Vector3i}. - pub fn to_vector3i( + /// Checks if this bounding box contains the specified position. + /// + /// Positions exactly on the minimum borders of the bounding box are + /// considered to be inside the bounding box, while positions exactly on the + /// maximum borders are considered to be outside. This allows bounding boxes + /// to reside directly next to each other with positions always only residing + /// in exactly one of them. + pub fn contains( &self, - rounding_mode: std::option::Option, - ) -> Result, Box> { + x: f64, + y: std::option::Option, + z: std::option::Option, + ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); - if let Some(a) = rounding_mode { - sig += "I"; - let val_1 = jni::objects::JValueGen::Int(a); - args.push(val_1); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(x); + args.push(val_1); + if let Some(a) = y { + sig += "D"; + let val_2 = jni::objects::JValueGen::Double(a); + args.push(val_2); } - sig += ")Lorg/joml/Vector3i;"; + if let Some(a) = z { + sig += "D"; + let val_3 = jni::objects::JValueGen::Double(a); + args.push(val_3); + } + sig += ")Z"; let res = self .jni_ref() - .call_method(&self.jni_object(), "toVector3i", sig.as_str(), args); + .call_method(&self.jni_object(), "contains", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) - } - /// Check if each component of this Vector is finite. - pub fn check_finite(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "checkFinite", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - /// Get the threshold used for equals(). - pub fn epsilon( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - let sig = String::from("()D"); - let cls = jni.find_class("org/bukkit/util/Vector"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getEpsilon", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - Ok(res.d()?) + Ok(res.z()?) } - /// Gets the minimum components of two vectors. - pub fn get_minimum( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - v1: impl Into>, - v2: impl Into>, - ) -> Result, Box> { + /// Calculates the intersection of this bounding box with the specified line + /// segment. + /// + /// Intersections at edges and corners yield one of the affected block faces + /// as hit result, but it is not defined which of them. + pub fn ray_trace( + &self, + start: impl Into>, + direction: impl Into>, + max_distance: f64, + ) -> Result>, Box> { let sig = String::from( - "(Lorg/bukkit/util/Vector;Lorg/bukkit/util/Vector;)Lorg/bukkit/util/Vector;", + "(Lorg/bukkit/util/Vector;Lorg/bukkit/util/Vector;D)Lorg/bukkit/util/RayTraceResult;", ); let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(v1.into().jni_object().clone()) + jni::objects::JObject::from_raw(start.into().jni_object().clone()) }); let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(v2.into().jni_object().clone()) + jni::objects::JObject::from_raw(direction.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/util/Vector"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getMinimum", + let val_3 = jni::objects::JValueGen::Double(max_distance); + let res = self.jni_ref().call_method( + &self.jni_object(), + "rayTrace", sig.as_str(), vec![ jni::objects::JValueGen::from(val_1), jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), ], ); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::util::Vector::from_raw(&jni, obj) + let res = self.jni_ref().translate_error(res)?; + if unsafe { jni::objects::JObject::from_raw(res.as_jni().l) }.is_null() { + return Ok(None); + } + Ok(Some(crate::util::RayTraceResult::from_raw( + &self.jni_ref(), + unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }, + )?)) } - /// Gets the maximum components of two vectors. - pub fn get_maximum( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - v1: impl Into>, - v2: impl Into>, - ) -> Result, Box> { - let sig = String::from( - "(Lorg/bukkit/util/Vector;Lorg/bukkit/util/Vector;)Lorg/bukkit/util/Vector;", - ); - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(v1.into().jni_object().clone()) - }); - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(v2.into().jni_object().clone()) - }); - let cls = jni.find_class("org/bukkit/util/Vector"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "getMaximum", + + pub fn hash_code(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) + } + + pub fn equals( + &self, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(Ljava/lang/Object;)Z"); + let val_1 = jni::objects::JValueGen::Object(obj); + let res = self.jni_ref().call_method( + &self.jni_object(), + "equals", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::util::Vector::from_raw(&jni, obj) + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Gets a random vector with components having a random value between 0 - /// and 1. - pub fn random( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/Vector;"); - let cls = jni.find_class("org/bukkit/util/Vector"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getRandom", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::util::Vector::from_raw(&jni, obj) + + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Gets a vector with components that match the provided JOML {@link Vector3ic}. - pub fn from_joml( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - vector: jni::objects::JObject<'mc>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/joml/Vector3ic;"; - let val_1 = jni::objects::JValueGen::Object(vector); - args.push(val_1); - sig += ")Lorg/bukkit/util/Vector;"; - let cls = jni.find_class("org/bukkit/util/Vector"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "fromJOML", sig.as_str(), args); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::util::Vector::from_raw(&jni, obj) + /// Creates a copy of this bounding box. + pub fn clone(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/BoundingBox;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "clone", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::util::BoundingBox::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn serialize( @@ -2782,12 +2444,12 @@ impl<'mc> Vector<'mc> { pub fn deserialize( jni: &blackboxmc_general::SharedJNIEnv<'mc>, val_args: impl Into>, - ) -> Result, Box> { - let sig = String::from("(Ljava/util/Map;)Lorg/bukkit/util/Vector;"); + ) -> Result, Box> { + let sig = String::from("(Ljava/util/Map;)Lorg/bukkit/util/BoundingBox;"); let val_1 = jni::objects::JValueGen::Object(unsafe { jni::objects::JObject::from_raw(val_args.into().jni_object().clone()) }); - let cls = jni.find_class("org/bukkit/util/Vector"); + let cls = jni.find_class("org/bukkit/util/BoundingBox"); let cls = jni.translate_error_with_class(cls)?; let res = jni.call_static_method( cls, @@ -2797,7 +2459,7 @@ impl<'mc> Vector<'mc> { ); let res = jni.translate_error(res)?; let obj = res.l()?; - crate::util::Vector::from_raw(&jni, obj) + crate::util::BoundingBox::from_raw(&jni, obj) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -2806,20 +2468,20 @@ impl<'mc> Vector<'mc> { } } -impl<'mc> std::string::ToString for Vector<'mc> { +impl<'mc> std::string::ToString for BoundingBox<'mc> { fn to_string(&self) -> String { match &self.internal_to_string() { Ok(a) => a.clone(), - Err(err) => format!("Error calling Vector.toString: {}", err), + Err(err) => format!("Error calling BoundingBox.toString: {}", err), } } } impl<'mc> Into> - for Vector<'mc> + for BoundingBox<'mc> { fn into(self) -> crate::configuration::serialization::ConfigurationSerializable<'mc> { - crate::configuration::serialization::ConfigurationSerializable::from_raw(&self.jni_ref(), self.1).expect("Error converting Vector into crate::configuration::serialization::ConfigurationSerializable") + crate::configuration::serialization::ConfigurationSerializable::from_raw(&self.jni_ref(), self.1).expect("Error converting BoundingBox into crate::configuration::serialization::ConfigurationSerializable") } } #[repr(C)] @@ -3349,144 +3011,510 @@ impl<'mc> BlockVector<'mc> { jni::objects::JObject::from_raw(self.1.clone()) })?; let real: crate::util::Vector = temp_clone.into(); - real.block_z() + real.block_z() + } + /// Set the X component. + pub fn set_x(&self, x: f32) -> Result, Box> { + let temp_clone = crate::util::Vector::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::util::Vector = temp_clone.into(); + real.set_x(x) + } + /// Set the Y component. + pub fn set_y(&self, y: f32) -> Result, Box> { + let temp_clone = crate::util::Vector::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::util::Vector = temp_clone.into(); + real.set_y(y) + } + /// Set the Z component. + pub fn set_z(&self, z: f32) -> Result, Box> { + let temp_clone = crate::util::Vector::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::util::Vector = temp_clone.into(); + real.set_z(z) + } + /// Returns this vector's components as x,y,z. + #[doc(hidden)] + pub fn internal_to_string(&self) -> Result> { + let temp_clone = crate::util::Vector::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::util::Vector = temp_clone.into(); + real.internal_to_string() + } + /// Gets a Location version of this vector. + pub fn to_location( + &self, + world: impl Into>, + yaw: std::option::Option, + pitch: std::option::Option, + ) -> Result, Box> { + let temp_clone = crate::util::Vector::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::util::Vector = temp_clone.into(); + real.to_location(world, yaw, pitch) + } + /// Get the block vector of this vector. + pub fn to_block_vector( + &self, + ) -> Result, Box> { + let temp_clone = crate::util::Vector::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::util::Vector = temp_clone.into(); + real.to_block_vector() } - /// Set the X component. - pub fn set_x(&self, x: f32) -> Result, Box> { + /// Get this vector as a JOML {@link Vector3f}. + pub fn to_vector3f(&self) -> Result, Box> { let temp_clone = crate::util::Vector::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; let real: crate::util::Vector = temp_clone.into(); - real.set_x(x) + real.to_vector3f() } - /// Set the Y component. - pub fn set_y(&self, y: f32) -> Result, Box> { + /// Get this vector as a JOML {@link Vector3d}. + pub fn to_vector3d(&self) -> Result, Box> { let temp_clone = crate::util::Vector::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; let real: crate::util::Vector = temp_clone.into(); - real.set_y(y) + real.to_vector3d() } - /// Set the Z component. - pub fn set_z(&self, z: f32) -> Result, Box> { + /// Get this vector as a JOML {@link Vector3i}. + pub fn to_vector3i( + &self, + rounding_mode: std::option::Option, + ) -> Result, Box> { let temp_clone = crate::util::Vector::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; let real: crate::util::Vector = temp_clone.into(); - real.set_z(z) + real.to_vector3i(rounding_mode) } - /// Returns this vector's components as x,y,z. - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { + /// Check if each component of this Vector is finite. + pub fn check_finite(&self) -> Result<(), Box> { let temp_clone = crate::util::Vector::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; let real: crate::util::Vector = temp_clone.into(); - real.internal_to_string() + real.check_finite() } - /// Gets a Location version of this vector. - pub fn to_location( + /// Get the threshold used for equals(). + pub fn epsilon( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result> { + crate::util::Vector::epsilon(jni) + } + /// Gets the minimum components of two vectors. + pub fn get_minimum( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + v1: impl Into>, + v2: impl Into>, + ) -> Result, Box> { + crate::util::Vector::get_minimum(jni, v1, v2) + } + /// Gets the maximum components of two vectors. + pub fn get_maximum( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + v1: impl Into>, + v2: impl Into>, + ) -> Result, Box> { + crate::util::Vector::get_maximum(jni, v1, v2) + } + /// Gets a random vector with components having a random value between 0 + /// and 1. + pub fn random( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + crate::util::Vector::random(jni) + } + /// Gets a vector with components that match the provided JOML {@link Vector3ic}. + pub fn from_joml( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + vector: jni::objects::JObject<'mc>, + ) -> Result, Box> { + crate::util::Vector::from_joml(jni, vector) + } + + pub fn serialize( &self, - world: impl Into>, - yaw: std::option::Option, - pitch: std::option::Option, - ) -> Result, Box> { + ) -> Result, Box> { let temp_clone = crate::util::Vector::from_raw(&self.0, unsafe { jni::objects::JObject::from_raw(self.1.clone()) })?; let real: crate::util::Vector = temp_clone.into(); - real.to_location(world, yaw, pitch) + real.serialize() + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for BlockVector<'mc> { + fn into(self) -> crate::util::Vector<'mc> { + crate::util::Vector::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockVector into crate::util::Vector") + } +} +#[repr(C)] +pub struct BlockIterator<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for BlockIterator<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for BlockIterator<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate BlockIterator from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/util/BlockIterator")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a BlockIterator object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> BlockIterator<'mc> { + /// Constructs the BlockIterator. + /// + /// This considers all blocks as 1x1x1 in size. + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + world: impl Into>, + start: std::option::Option>>, + direction: std::option::Option>>, + y_offset: std::option::Option, + max_distance: std::option::Option, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Lorg/bukkit/World;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(world.into().jni_object().clone()) + }); + args.push(val_1); + if let Some(a) = start { + sig += "Lorg/bukkit/util/Vector;"; + let val_2 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_2); + } + if let Some(a) = direction { + sig += "Lorg/bukkit/util/Vector;"; + let val_3 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(a.into().jni_object().clone()) + }); + args.push(val_3); + } + if let Some(a) = y_offset { + sig += "D"; + let val_4 = jni::objects::JValueGen::Double(a); + args.push(val_4); + } + if let Some(a) = max_distance { + sig += "I"; + let val_5 = jni::objects::JValueGen::Int(a); + args.push(val_5); + } + sig += ")V"; + let cls = jni.find_class("org/bukkit/util/BlockIterator"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::util::BlockIterator::from_raw(&jni, res) + } + /// Returns true if the iteration has more elements + pub fn has_next(&self) -> Result> { + let sig = String::from("()Z"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "hasNext", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) + } + /// Returns the next Block in the trace + pub fn next(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/Block;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "next", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::block::Block::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + + pub fn remove(&self) -> Result<(), Box> { + let sig = String::from("()V"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); + self.jni_ref().translate_error(res)?; + Ok(()) + } + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} +impl<'mc> Into> for BlockIterator<'mc> { + fn into(self) -> blackboxmc_java::util::JavaIterator<'mc> { + blackboxmc_java::util::JavaIterator::from_raw(&self.jni_ref(), self.1) + .expect("Error converting BlockIterator into blackboxmc_java::util::JavaIterator") + } +} +#[repr(C)] +pub struct EntityTransformer<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for EntityTransformer<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for EntityTransformer<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate EntityTransformer from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/util/EntityTransformer")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a EntityTransformer object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } - /// Get the block vector of this vector. - pub fn to_block_vector( +} + +impl<'mc> EntityTransformer<'mc> { + /// Transforms a entity in a structure. + pub fn transform( &self, - ) -> Result, Box> { - let temp_clone = crate::util::Vector::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::util::Vector = temp_clone.into(); - real.to_block_vector() + region: impl Into>, + x: i32, + y: i32, + z: i32, + entity: impl Into>, + allowed_to_spawn: bool, + ) -> Result> { + let sig = + String::from("(Lorg/bukkit/generator/LimitedRegion;IIILorg/bukkit/entity/Entity;Z)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(region.into().jni_object().clone()) + }); + let val_2 = jni::objects::JValueGen::Int(x); + let val_3 = jni::objects::JValueGen::Int(y); + let val_4 = jni::objects::JValueGen::Int(z); + let val_5 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(entity.into().jni_object().clone()) + }); + let val_6 = jni::objects::JValueGen::Bool(allowed_to_spawn.into()); + let res = self.jni_ref().call_method( + &self.jni_object(), + "transform", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + jni::objects::JValueGen::from(val_4), + jni::objects::JValueGen::from(val_5), + jni::objects::JValueGen::from(val_6), + ], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.z()?) } - /// Get this vector as a JOML {@link Vector3f}. - pub fn to_vector3f(&self) -> Result, Box> { - let temp_clone = crate::util::Vector::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::util::Vector = temp_clone.into(); - real.to_vector3f() + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Get this vector as a JOML {@link Vector3d}. - pub fn to_vector3d(&self) -> Result, Box> { - let temp_clone = crate::util::Vector::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::util::Vector = temp_clone.into(); - real.to_vector3d() +} +#[repr(C)] +pub struct OldEnum<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for OldEnum<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Get this vector as a JOML {@link Vector3i}. - pub fn to_vector3i( + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for OldEnum<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!("Tried to instantiate OldEnum from null object.").into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/util/OldEnum")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a OldEnum object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } + } +} + +impl<'mc> OldEnum<'mc> { + #[deprecated] + + pub fn compare_to( &self, - rounding_mode: std::option::Option, - ) -> Result, Box> { - let temp_clone = crate::util::Vector::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::util::Vector = temp_clone.into(); - real.to_vector3i(rounding_mode) + other: jni::objects::JObject<'mc>, + ) -> Result> { + let sig = String::from("(LT;)I"); + let val_1 = jni::objects::JValueGen::Object(other); + let res = self.jni_ref().call_method( + &self.jni_object(), + "compareTo", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Check if each component of this Vector is finite. - pub fn check_finite(&self) -> Result<(), Box> { - let temp_clone = crate::util::Vector::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::util::Vector = temp_clone.into(); - real.check_finite() + #[deprecated] + + pub fn name(&self) -> Result> { + let sig = String::from("()Ljava/lang/String;"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "name", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(self + .jni_ref() + .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? + .to_string_lossy() + .to_string()) } - /// Get the threshold used for equals(). - pub fn epsilon( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result> { - crate::util::Vector::epsilon(jni) + #[deprecated] + + pub fn ordinal(&self) -> Result> { + let sig = String::from("()I"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "ordinal", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.i()?) } - /// Gets the minimum components of two vectors. - pub fn get_minimum( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - v1: impl Into>, - v2: impl Into>, - ) -> Result, Box> { - crate::util::Vector::get_minimum(jni, v1, v2) + + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) } - /// Gets the maximum components of two vectors. - pub fn get_maximum( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - v1: impl Into>, - v2: impl Into>, - ) -> Result, Box> { - crate::util::Vector::get_maximum(jni, v1, v2) +} +#[repr(C)] +pub struct StructureSearchResult<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); + +impl<'mc> JNIRaw<'mc> for StructureSearchResult<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() } - /// Gets a random vector with components having a random value between 0 - /// and 1. - pub fn random( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - crate::util::Vector::random(jni) + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } - /// Gets a vector with components that match the provided JOML {@link Vector3ic}. - pub fn from_joml( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - vector: jni::objects::JObject<'mc>, - ) -> Result, Box> { - crate::util::Vector::from_joml(jni, vector) +} +impl<'mc> JNIInstantiatable<'mc> for StructureSearchResult<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err(eyre::eyre!( + "Tried to instantiate StructureSearchResult from null object." + ) + .into()); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/util/StructureSearchResult")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a StructureSearchResult object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) + } } +} - pub fn serialize( +impl<'mc> StructureSearchResult<'mc> { + /// Return the structure which was found. + pub fn structure( &self, - ) -> Result, Box> { - let temp_clone = crate::util::Vector::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::util::Vector = temp_clone.into(); - real.serialize() + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/generator/structure/Structure;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getStructure", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::generator::structure::Structure::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Return the location of the structure. + pub fn location(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + crate::Location::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -3494,19 +3522,13 @@ impl<'mc> BlockVector<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockVector<'mc> { - fn into(self) -> crate::util::Vector<'mc> { - crate::util::Vector::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockVector into crate::util::Vector") - } -} #[repr(C)] -pub struct Transformation<'mc>( +pub struct EulerAngle<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for Transformation<'mc> { +impl<'mc> JNIRaw<'mc> for EulerAngle<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3514,20 +3536,18 @@ impl<'mc> JNIRaw<'mc> for Transformation<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for Transformation<'mc> { +impl<'mc> JNIInstantiatable<'mc> for EulerAngle<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate Transformation from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate EulerAngle from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/util/Transformation")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/util/EulerAngle")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a Transformation object, got {}", + "Invalid argument passed. Expected a EulerAngle object, got {}", name ) .into()) @@ -3537,90 +3557,178 @@ impl<'mc> JNIInstantiatable<'mc> for Transformation<'mc> { } } -impl<'mc> Transformation<'mc> { +impl<'mc> EulerAngle<'mc> { + /// Creates a EularAngle with each axis set to the + /// passed angle in radians pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - translation: jni::objects::JObject<'mc>, - left_rotation: jni::objects::JObject<'mc>, - scale: jni::objects::JObject<'mc>, - right_rotation: jni::objects::JObject<'mc>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/joml/Vector3f;"; - let val_1 = jni::objects::JValueGen::Object(translation); - args.push(val_1); - sig += "Lorg/joml/Quaternionf;"; - let val_2 = jni::objects::JValueGen::Object(left_rotation); - args.push(val_2); - sig += "Lorg/joml/Vector3f;"; - let val_3 = jni::objects::JValueGen::Object(scale); - args.push(val_3); - sig += "Lorg/joml/Quaternionf;"; - let val_4 = jni::objects::JValueGen::Object(right_rotation); - args.push(val_4); - sig += ")V"; - let cls = jni.find_class("org/bukkit/util/Transformation"); + x: f64, + y: f64, + z: f64, + ) -> Result, Box> { + let sig = String::from("(DDD)V"); + let val_1 = jni::objects::JValueGen::Double(x); + let val_2 = jni::objects::JValueGen::Double(y); + let val_3 = jni::objects::JValueGen::Double(z); + let cls = jni.find_class("org/bukkit/util/EulerAngle"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.new_object( + cls, + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); let res = jni.translate_error_no_gen(res)?; - crate::util::Transformation::from_raw(&jni, res) + crate::util::EulerAngle::from_raw(&jni, res) } - /// Gets the translation component of this transformation. - pub fn translation(&self) -> Result, Box> { - let sig = String::from("()Lorg/joml/Vector3f;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getTranslation", sig.as_str(), vec![]); + /// Returns the angle on the x axis in radians + pub fn x(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getX", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) + Ok(res.d()?) } - /// Gets the left rotation component of this transformation. - pub fn left_rotation(&self) -> Result, Box> { - let sig = String::from("()Lorg/joml/Quaternionf;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLeftRotation", sig.as_str(), vec![]); + /// Returns the angle on the y axis in radians + pub fn y(&self) -> Result> { + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getY", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) + Ok(res.d()?) } - /// Gets the scale component of this transformation. - pub fn scale(&self) -> Result, Box> { - let sig = String::from("()Lorg/joml/Vector3f;"); + /// Returns the angle on the z axis in radians + pub fn z(&self) -> Result> { + let sig = String::from("()D"); let res = self .jni_ref() - .call_method(&self.jni_object(), "getScale", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getZ", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) + Ok(res.d()?) } - /// Gets the right rotation component of this transformation. - pub fn right_rotation(&self) -> Result, Box> { - let sig = String::from("()Lorg/joml/Quaternionf;"); + /// Return a EulerAngle which is the result of changing + /// the x axis to the passed angle + pub fn set_x( + &self, + x: f64, + ) -> Result, Box> { + let sig = String::from("(D)Lorg/bukkit/util/EulerAngle;"); + let val_1 = jni::objects::JValueGen::Double(x); let res = self.jni_ref().call_method( &self.jni_object(), - "getRightRotation", + "setX", sig.as_str(), - vec![], + vec![jni::objects::JValueGen::from(val_1)], ); let res = self.jni_ref().translate_error(res)?; - Ok(res.l()?) + crate::util::EulerAngle::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - - pub fn hash_code(&self) -> Result> { - let sig = String::from("()I"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); + /// Return a EulerAngle which is the result of changing + /// the y axis to the passed angle + pub fn set_y( + &self, + y: f64, + ) -> Result, Box> { + let sig = String::from("(D)Lorg/bukkit/util/EulerAngle;"); + let val_1 = jni::objects::JValueGen::Double(y); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setY", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); let res = self.jni_ref().translate_error(res)?; - Ok(res.i()?) + crate::util::EulerAngle::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Return a EulerAngle which is the result of changing + /// the z axis to the passed angle + pub fn set_z( + &self, + z: f64, + ) -> Result, Box> { + let sig = String::from("(D)Lorg/bukkit/util/EulerAngle;"); + let val_1 = jni::objects::JValueGen::Double(z); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setZ", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = self.jni_ref().translate_error(res)?; + crate::util::EulerAngle::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Creates a new EulerAngle which is the result of adding + /// the x, y, z components to this EulerAngle + pub fn add( + &self, + x: f64, + y: f64, + z: f64, + ) -> Result, Box> { + let sig = String::from("(DDD)Lorg/bukkit/util/EulerAngle;"); + let val_1 = jni::objects::JValueGen::Double(x); + let val_2 = jni::objects::JValueGen::Double(y); + let val_3 = jni::objects::JValueGen::Double(z); + let res = self.jni_ref().call_method( + &self.jni_object(), + "add", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = self.jni_ref().translate_error(res)?; + crate::util::EulerAngle::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) + } + /// Creates a new EulerAngle which is the result of subtracting + /// the x, y, z components to this EulerAngle + pub fn subtract( + &self, + x: f64, + y: f64, + z: f64, + ) -> Result, Box> { + let sig = String::from("(DDD)Lorg/bukkit/util/EulerAngle;"); + let val_1 = jni::objects::JValueGen::Double(x); + let val_2 = jni::objects::JValueGen::Double(y); + let val_3 = jni::objects::JValueGen::Double(z); + let res = self.jni_ref().call_method( + &self.jni_object(), + "subtract", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); + let res = self.jni_ref().translate_error(res)?; + crate::util::EulerAngle::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } pub fn equals( &self, - obj: jni::objects::JObject<'mc>, + o: jni::objects::JObject<'mc>, ) -> Result> { let sig = String::from("(Ljava/lang/Object;)Z"); - let val_1 = jni::objects::JValueGen::Object(obj); + let val_1 = jni::objects::JValueGen::Object(o); let res = self.jni_ref().call_method( &self.jni_object(), "equals", @@ -3631,18 +3739,13 @@ impl<'mc> Transformation<'mc> { Ok(res.z()?) } - #[doc(hidden)] - pub fn internal_to_string(&self) -> Result> { - let sig = String::from("()Ljava/lang/String;"); + pub fn hash_code(&self) -> Result> { + let sig = String::from("()I"); let res = self .jni_ref() - .call_method(&self.jni_object(), "toString", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "hashCode", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(self - .jni_ref() - .get_string(unsafe { &jni::objects::JString::from_raw(res.as_jni().l) })? - .to_string_lossy() - .to_string()) + Ok(res.i()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -3650,23 +3753,56 @@ impl<'mc> Transformation<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +#[repr(C)] +pub struct CachedServerIcon<'mc>( + pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, + pub(crate) jni::objects::JObject<'mc>, +); -impl<'mc> std::string::ToString for Transformation<'mc> { - fn to_string(&self) -> String { - match &self.internal_to_string() { - Ok(a) => a.clone(), - Err(err) => format!("Error calling Transformation.toString: {}", err), +impl<'mc> JNIRaw<'mc> for CachedServerIcon<'mc> { + fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { + self.0.clone() + } + fn jni_object(&self) -> jni::objects::JObject<'mc> { + unsafe { jni::objects::JObject::from_raw(self.1.clone()) } + } +} +impl<'mc> JNIInstantiatable<'mc> for CachedServerIcon<'mc> { + fn from_raw( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + obj: jni::objects::JObject<'mc>, + ) -> Result> { + if obj.is_null() { + return Err( + eyre::eyre!("Tried to instantiate CachedServerIcon from null object.").into(), + ); + } + let (valid, name) = env.validate_name(&obj, "org/bukkit/util/CachedServerIcon")?; + if !valid { + Err(eyre::eyre!( + "Invalid argument passed. Expected a CachedServerIcon object, got {}", + name + ) + .into()) + } else { + Ok(Self(env.clone(), obj)) } } } - + +impl<'mc> CachedServerIcon<'mc> { + pub fn instance_of(&self, other: impl Into) -> Result { + let cls = &self.jni_ref().find_class(other.into().as_str())?; + self.jni_ref().is_instance_of(&self.jni_object(), cls) + } +} #[repr(C)] -pub struct BiomeSearchResult<'mc>( +pub struct Consumer<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BiomeSearchResult<'mc> { +impl<'mc> JNIRaw<'mc> for Consumer<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3674,20 +3810,18 @@ impl<'mc> JNIRaw<'mc> for BiomeSearchResult<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BiomeSearchResult<'mc> { +impl<'mc> JNIInstantiatable<'mc> for Consumer<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate BiomeSearchResult from null object.").into(), - ); + return Err(eyre::eyre!("Tried to instantiate Consumer from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/util/BiomeSearchResult")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/util/Consumer")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BiomeSearchResult object, got {}", + "Invalid argument passed. Expected a Consumer object, got {}", name ) .into()) @@ -3697,28 +3831,29 @@ impl<'mc> JNIInstantiatable<'mc> for BiomeSearchResult<'mc> { } } -impl<'mc> BiomeSearchResult<'mc> { - /// Return the biome which was found. - pub fn biome(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/Biome;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getBiome", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::block::Biome::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) +impl<'mc> Consumer<'mc> { + pub fn from_extendable( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + plugin: &'mc crate::plugin::Plugin, + address: i32, + lib_name: String, + name: String, + ) -> Result> { + let obj = unsafe { plugin.new_extendable(address, "Consumer", name, lib_name) }?; + Self::from_raw(env, obj) } - /// Return the location of the biome. - pub fn location(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/Location;"); - let res = - self.jni_ref() - .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - crate::Location::from_raw(&self.jni_ref(), unsafe { - jni::objects::JObject::from_raw(res.l()?.clone()) - }) + /// Performs this operation on the given argument. + pub fn accept(&self, t: jni::objects::JObject<'mc>) -> Result<(), Box> { + let sig = String::from("(LT;)V"); + let val_1 = jni::objects::JValueGen::Object(t); + let res = self.jni_ref().call_method( + &self.jni_object(), + "accept", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -3726,13 +3861,19 @@ impl<'mc> BiomeSearchResult<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for Consumer<'mc> { + fn into(self) -> blackboxmc_java::util::function::JavaConsumer<'mc> { + blackboxmc_java::util::function::JavaConsumer::from_raw(&self.jni_ref(), self.1) + .expect("Error converting Consumer into blackboxmc_java::util::function::JavaConsumer") + } +} #[repr(C)] -pub struct StringUtil<'mc>( +pub struct VoxelShape<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for StringUtil<'mc> { +impl<'mc> JNIRaw<'mc> for VoxelShape<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3740,18 +3881,18 @@ impl<'mc> JNIRaw<'mc> for StringUtil<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for StringUtil<'mc> { +impl<'mc> JNIInstantiatable<'mc> for VoxelShape<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate StringUtil from null object.").into()); + return Err(eyre::eyre!("Tried to instantiate VoxelShape from null object.").into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/util/StringUtil")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/util/VoxelShape")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a StringUtil object, got {}", + "Invalid argument passed. Expected a VoxelShape object, got {}", name ) .into()) @@ -3761,44 +3902,46 @@ impl<'mc> JNIInstantiatable<'mc> for StringUtil<'mc> { } } -impl<'mc> StringUtil<'mc> { - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/util/StringUtil"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), vec![]); - let res = jni.translate_error_no_gen(res)?; - crate::util::StringUtil::from_raw(&jni, res) +impl<'mc> VoxelShape<'mc> { + /// Converts this shape into a collection of {@link BoundingBox} equivalent + /// to the shape: a bounding box intersects with this block shape if it + /// intersects with any of the shape's bounding boxes. + pub fn bounding_boxes( + &self, + ) -> Result>, Box> { + let sig = String::from("()Ljava/util/Collection;"); + let res = self.jni_ref().call_method( + &self.jni_object(), + "getBoundingBoxes", + sig.as_str(), + vec![], + ); + let res = self.jni_ref().translate_error(res)?; + let mut new_vec = Vec::new(); + let col = blackboxmc_java::util::JavaCollection::from_raw(&self.jni_ref(), res.l()?)?; + let iter = col.iterator()?; + while iter.has_next()? { + let obj = iter.next()?; + new_vec.push(crate::util::BoundingBox::from_raw(&self.jni_ref(), obj)?); + } + Ok(new_vec) } - /// This method uses a region to check case-insensitive equality. This - /// means the internal array does not need to be copied like a - /// toLowerCase() call would. - pub fn starts_with_ignore_case( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - string: impl Into, - prefix: impl Into, + /// Checks if the given bounding box intersects this block shape. + pub fn overlaps( + &self, + other: impl Into>, ) -> Result> { - let sig = String::from("(Ljava/lang/String;Ljava/lang/String;)Z"); - let val_1 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(string.into())?, - )); - let val_2 = jni::objects::JValueGen::Object(jni::objects::JObject::from( - jni.new_string(prefix.into())?, - )); - let cls = jni.find_class("org/bukkit/util/StringUtil"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "startsWithIgnoreCase", + let sig = String::from("(Lorg/bukkit/util/BoundingBox;)Z"); + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(other.into().jni_object().clone()) + }); + let res = self.jni_ref().call_method( + &self.jni_object(), + "overlaps", sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - ], + vec![jni::objects::JValueGen::from(val_1)], ); - let res = jni.translate_error(res)?; + let res = self.jni_ref().translate_error(res)?; Ok(res.z()?) } @@ -3808,12 +3951,12 @@ impl<'mc> StringUtil<'mc> { } } #[repr(C)] -pub struct BlockIterator<'mc>( +pub struct BiomeSearchResult<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for BlockIterator<'mc> { +impl<'mc> JNIRaw<'mc> for BiomeSearchResult<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -3821,18 +3964,20 @@ impl<'mc> JNIRaw<'mc> for BlockIterator<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for BlockIterator<'mc> { +impl<'mc> JNIInstantiatable<'mc> for BiomeSearchResult<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!("Tried to instantiate BlockIterator from null object.").into()); + return Err( + eyre::eyre!("Tried to instantiate BiomeSearchResult from null object.").into(), + ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/util/BlockIterator")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/util/BiomeSearchResult")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a BlockIterator object, got {}", + "Invalid argument passed. Expected a BiomeSearchResult object, got {}", name ) .into()) @@ -3842,97 +3987,35 @@ impl<'mc> JNIInstantiatable<'mc> for BlockIterator<'mc> { } } -impl<'mc> BlockIterator<'mc> { - /// Constructs the BlockIterator. - /// - /// This considers all blocks as 1x1x1 in size. - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - world: impl Into>, - start: std::option::Option>>, - direction: std::option::Option>>, - y_offset: std::option::Option, - max_distance: std::option::Option, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Lorg/bukkit/World;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(world.into().jni_object().clone()) - }); - args.push(val_1); - if let Some(a) = start { - sig += "Lorg/bukkit/util/Vector;"; - let val_2 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_2); - } - if let Some(a) = direction { - sig += "Lorg/bukkit/util/Vector;"; - let val_3 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(a.into().jni_object().clone()) - }); - args.push(val_3); - } - if let Some(a) = y_offset { - sig += "D"; - let val_4 = jni::objects::JValueGen::Double(a); - args.push(val_4); - } - if let Some(a) = max_distance { - sig += "I"; - let val_5 = jni::objects::JValueGen::Int(a); - args.push(val_5); - } - sig += ")V"; - let cls = jni.find_class("org/bukkit/util/BlockIterator"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::util::BlockIterator::from_raw(&jni, res) - } - /// Returns true if the iteration has more elements - pub fn has_next(&self) -> Result> { - let sig = String::from("()Z"); +impl<'mc> BiomeSearchResult<'mc> { + /// Return the biome which was found. + pub fn biome(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/block/Biome;"); let res = self .jni_ref() - .call_method(&self.jni_object(), "hasNext", sig.as_str(), vec![]); + .call_method(&self.jni_object(), "getBiome", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - Ok(res.z()?) + crate::block::Biome::from_raw(&self.jni_ref(), unsafe { + jni::objects::JObject::from_raw(res.l()?.clone()) + }) } - /// Returns the next Block in the trace - pub fn next(&self) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/block/Block;"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "next", sig.as_str(), vec![]); + /// Return the location of the biome. + pub fn location(&self) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/Location;"); + let res = + self.jni_ref() + .call_method(&self.jni_object(), "getLocation", sig.as_str(), vec![]); let res = self.jni_ref().translate_error(res)?; - crate::block::Block::from_raw(&self.jni_ref(), unsafe { + crate::Location::from_raw(&self.jni_ref(), unsafe { jni::objects::JObject::from_raw(res.l()?.clone()) }) } - pub fn remove(&self) -> Result<(), Box> { - let sig = String::from("()V"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "remove", sig.as_str(), vec![]); - self.jni_ref().translate_error(res)?; - Ok(()) - } - pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for BlockIterator<'mc> { - fn into(self) -> blackboxmc_java::util::JavaIterator<'mc> { - blackboxmc_java::util::JavaIterator::from_raw(&self.jni_ref(), self.1) - .expect("Error converting BlockIterator into blackboxmc_java::util::JavaIterator") - } -} #[repr(C)] pub struct RayTraceResult<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, diff --git a/blackboxmc-rs-bukkit/src/util/noise/mod.rs b/blackboxmc-rs-bukkit/src/util/noise/mod.rs index 9688192..2635d7b 100644 --- a/blackboxmc-rs-bukkit/src/util/noise/mod.rs +++ b/blackboxmc-rs-bukkit/src/util/noise/mod.rs @@ -368,12 +368,12 @@ impl<'mc> Into> for SimplexNoiseGe } } #[repr(C)] -pub struct PerlinOctaveGenerator<'mc>( +pub struct OctaveGenerator<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PerlinOctaveGenerator<'mc> { +impl<'mc> JNIRaw<'mc> for OctaveGenerator<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -381,22 +381,20 @@ impl<'mc> JNIRaw<'mc> for PerlinOctaveGenerator<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PerlinOctaveGenerator<'mc> { +impl<'mc> JNIInstantiatable<'mc> for OctaveGenerator<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err(eyre::eyre!( - "Tried to instantiate PerlinOctaveGenerator from null object." - ) - .into()); + return Err( + eyre::eyre!("Tried to instantiate OctaveGenerator from null object.").into(), + ); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/util/noise/PerlinOctaveGenerator")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/util/noise/OctaveGenerator")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PerlinOctaveGenerator object, got {}", + "Invalid argument passed. Expected a OctaveGenerator object, got {}", name ) .into()) @@ -406,89 +404,88 @@ impl<'mc> JNIInstantiatable<'mc> for PerlinOctaveGenerator<'mc> { } } -impl<'mc> PerlinOctaveGenerator<'mc> { - /// Creates a perlin octave generator for the given {@link Random} - pub fn new( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - rand: impl Into>, - octaves: i32, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/util/Random;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(rand.into().jni_object().clone()) - }); - args.push(val_1); - sig += "I"; - let val_2 = jni::objects::JValueGen::Int(octaves); - args.push(val_2); - sig += ")V"; - let cls = jni.find_class("org/bukkit/util/noise/PerlinOctaveGenerator"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); - let res = jni.translate_error_no_gen(res)?; - crate::util::noise::PerlinOctaveGenerator::from_raw(&jni, res) - } - // SUPER CLASS: org.bukkit.util.noise.OctaveGenerator ( []) +impl<'mc> OctaveGenerator<'mc> { /// Sets the scale used for all coordinates passed to this generator. /// /// This is the equivalent to setting each coordinate to the specified /// value. pub fn set_scale(&self, scale: f64) -> Result<(), Box> { - let temp_clone = crate::util::noise::OctaveGenerator::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::util::noise::OctaveGenerator = temp_clone.into(); - real.set_scale(scale) + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(scale); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setScale", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } /// Gets the scale used for each X-coordinates passed pub fn xscale(&self) -> Result> { - let temp_clone = crate::util::noise::OctaveGenerator::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::util::noise::OctaveGenerator = temp_clone.into(); - real.xscale() + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getXScale", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } /// Sets the scale used for each X-coordinates passed pub fn set_xscale(&self, scale: f64) -> Result<(), Box> { - let temp_clone = crate::util::noise::OctaveGenerator::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::util::noise::OctaveGenerator = temp_clone.into(); - real.set_xscale(scale) + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(scale); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setXScale", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } /// Gets the scale used for each Y-coordinates passed pub fn yscale(&self) -> Result> { - let temp_clone = crate::util::noise::OctaveGenerator::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::util::noise::OctaveGenerator = temp_clone.into(); - real.yscale() + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getYScale", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } /// Sets the scale used for each Y-coordinates passed pub fn set_yscale(&self, scale: f64) -> Result<(), Box> { - let temp_clone = crate::util::noise::OctaveGenerator::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::util::noise::OctaveGenerator = temp_clone.into(); - real.set_yscale(scale) + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(scale); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setYScale", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } /// Gets the scale used for each Z-coordinates passed pub fn zscale(&self) -> Result> { - let temp_clone = crate::util::noise::OctaveGenerator::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::util::noise::OctaveGenerator = temp_clone.into(); - real.zscale() + let sig = String::from("()D"); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "getZScale", sig.as_str(), vec![]); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } /// Sets the scale used for each Z-coordinates passed pub fn set_zscale(&self, scale: f64) -> Result<(), Box> { - let temp_clone = crate::util::noise::OctaveGenerator::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::util::noise::OctaveGenerator = temp_clone.into(); - real.set_zscale(scale) + let sig = String::from("(D)V"); + let val_1 = jni::objects::JValueGen::Double(scale); + let res = self.jni_ref().call_method( + &self.jni_object(), + "setZScale", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + self.jni_ref().translate_error(res)?; + Ok(()) } /// Gets a clone of the individual octaves used within this generator pub fn octaves( @@ -514,11 +511,38 @@ impl<'mc> PerlinOctaveGenerator<'mc> { amplitude: std::option::Option, normalized: std::option::Option, ) -> Result> { - let temp_clone = crate::util::noise::OctaveGenerator::from_raw(&self.0, unsafe { - jni::objects::JObject::from_raw(self.1.clone()) - })?; - let real: crate::util::noise::OctaveGenerator = temp_clone.into(); - real.noise(x, y, z, frequency, amplitude, normalized) + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "D"; + let val_1 = jni::objects::JValueGen::Double(x); + args.push(val_1); + sig += "D"; + let val_2 = jni::objects::JValueGen::Double(y); + args.push(val_2); + sig += "D"; + let val_3 = jni::objects::JValueGen::Double(z); + args.push(val_3); + if let Some(a) = frequency { + sig += "D"; + let val_4 = jni::objects::JValueGen::Double(a); + args.push(val_4); + } + if let Some(a) = amplitude { + sig += "D"; + let val_5 = jni::objects::JValueGen::Double(a); + args.push(val_5); + } + if let Some(a) = normalized { + sig += "Z"; + let val_6 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_6); + } + sig += ")D"; + let res = self + .jni_ref() + .call_method(&self.jni_object(), "noise", sig.as_str(), args); + let res = self.jni_ref().translate_error(res)?; + Ok(res.d()?) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -526,20 +550,13 @@ impl<'mc> PerlinOctaveGenerator<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PerlinOctaveGenerator<'mc> { - fn into(self) -> crate::util::noise::OctaveGenerator<'mc> { - crate::util::noise::OctaveGenerator::from_raw(&self.jni_ref(), self.1).expect( - "Error converting PerlinOctaveGenerator into crate::util::noise::OctaveGenerator", - ) - } -} #[repr(C)] -pub struct PerlinNoiseGenerator<'mc>( +pub struct NoiseGenerator<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for PerlinNoiseGenerator<'mc> { +impl<'mc> JNIRaw<'mc> for NoiseGenerator<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -547,21 +564,20 @@ impl<'mc> JNIRaw<'mc> for PerlinNoiseGenerator<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for PerlinNoiseGenerator<'mc> { +impl<'mc> JNIInstantiatable<'mc> for NoiseGenerator<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate PerlinNoiseGenerator from null object.").into(), + eyre::eyre!("Tried to instantiate NoiseGenerator from null object.").into(), ); } - let (valid, name) = - env.validate_name(&obj, "org/bukkit/util/noise/PerlinNoiseGenerator")?; + let (valid, name) = env.validate_name(&obj, "org/bukkit/util/noise/NoiseGenerator")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a PerlinNoiseGenerator object, got {}", + "Invalid argument passed. Expected a NoiseGenerator object, got {}", name ) .into()) @@ -571,36 +587,57 @@ impl<'mc> JNIInstantiatable<'mc> for PerlinNoiseGenerator<'mc> { } } -impl<'mc> PerlinNoiseGenerator<'mc> { - /// Creates a seeded perlin noise generator with the given Random +impl<'mc> NoiseGenerator<'mc> { + pub fn from_extendable( + env: &blackboxmc_general::SharedJNIEnv<'mc>, + plugin: &'mc crate::plugin::Plugin, + address: i32, + lib_name: String, + name: String, + ) -> Result> { + let obj = unsafe { plugin.new_extendable(address, "NoiseGenerator", name, lib_name) }?; + Self::from_raw(env, obj) + } + pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - rand: impl Into>, - ) -> Result, Box> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "Ljava/util/Random;"; - let val_1 = jni::objects::JValueGen::Object(unsafe { - jni::objects::JObject::from_raw(rand.into().jni_object().clone()) - }); - args.push(val_1); - sig += ")V"; - let cls = jni.find_class("org/bukkit/util/noise/PerlinNoiseGenerator"); + ) -> Result, Box> { + let sig = String::from("()V"); + let cls = jni.find_class("org/bukkit/util/noise/NoiseGenerator"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.new_object(cls, sig.as_str(), vec![]); let res = jni.translate_error_no_gen(res)?; - crate::util::noise::PerlinNoiseGenerator::from_raw(&jni, res) + crate::util::noise::NoiseGenerator::from_raw(&jni, res) + } + /// Speedy floor, faster than (int)Math.floor(x) + pub fn floor( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + x: f64, + ) -> Result> { + let sig = String::from("(D)I"); + let val_1 = jni::objects::JValueGen::Double(x); + let cls = jni.find_class("org/bukkit/util/noise/NoiseGenerator"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method( + cls, + "floor", + sig.as_str(), + vec![jni::objects::JValueGen::from(val_1)], + ); + let res = jni.translate_error(res)?; + Ok(res.i()?) } /// Generates noise for the 3D coordinates using the specified number of /// octaves and parameters - pub fn get_noise( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, + pub fn noise( + &self, x: f64, y: std::option::Option, z: std::option::Option, octaves: std::option::Option, frequency: std::option::Option, amplitude: std::option::Option, + normalized: std::option::Option, ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); @@ -632,71 +669,31 @@ impl<'mc> PerlinNoiseGenerator<'mc> { let val_6 = jni::objects::JValueGen::Double(a); args.push(val_6); } + if let Some(a) = normalized { + sig += "Z"; + let val_7 = jni::objects::JValueGen::Bool(a.into()); + args.push(val_7); + } sig += ")D"; - let cls = jni.find_class("org/bukkit/util/noise/PerlinNoiseGenerator"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getNoise", sig.as_str(), args); - let res = jni.translate_error(res)?; - Ok(res.d()?) - } - /// Gets the singleton unseeded instance of this generator - pub fn instance( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()Lorg/bukkit/util/noise/PerlinNoiseGenerator;"); - let cls = jni.find_class("org/bukkit/util/noise/PerlinNoiseGenerator"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method(cls, "getInstance", sig.as_str(), vec![]); - let res = jni.translate_error(res)?; - let obj = res.l()?; - crate::util::noise::PerlinNoiseGenerator::from_raw(&jni, obj) - } - - pub fn noise(&self, x: f64, y: f64, z: f64) -> Result> { - let sig = String::from("(DDD)D"); - let val_1 = jni::objects::JValueGen::Double(x); - let val_2 = jni::objects::JValueGen::Double(y); - let val_3 = jni::objects::JValueGen::Double(z); - let res = self.jni_ref().call_method( - &self.jni_object(), - "noise", - sig.as_str(), - vec![ - jni::objects::JValueGen::from(val_1), - jni::objects::JValueGen::from(val_2), - jni::objects::JValueGen::from(val_3), - ], - ); + let res = self + .jni_ref() + .call_method(&self.jni_object(), "noise", sig.as_str(), args); let res = self.jni_ref().translate_error(res)?; Ok(res.d()?) } - // SUPER CLASS: org.bukkit.util.noise.NoiseGenerator ( ['getNoise', 'getInstance', 'noise']) - /// Speedy floor, faster than (int)Math.floor(x) - pub fn floor( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - x: f64, - ) -> Result> { - crate::util::noise::NoiseGenerator::floor(jni, x) - } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } -impl<'mc> Into> for PerlinNoiseGenerator<'mc> { - fn into(self) -> crate::util::noise::NoiseGenerator<'mc> { - crate::util::noise::NoiseGenerator::from_raw(&self.jni_ref(), self.1) - .expect("Error converting PerlinNoiseGenerator into crate::util::noise::NoiseGenerator") - } -} #[repr(C)] -pub struct OctaveGenerator<'mc>( +pub struct PerlinOctaveGenerator<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for OctaveGenerator<'mc> { +impl<'mc> JNIRaw<'mc> for PerlinOctaveGenerator<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -704,20 +701,22 @@ impl<'mc> JNIRaw<'mc> for OctaveGenerator<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for OctaveGenerator<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PerlinOctaveGenerator<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { - return Err( - eyre::eyre!("Tried to instantiate OctaveGenerator from null object.").into(), - ); + return Err(eyre::eyre!( + "Tried to instantiate PerlinOctaveGenerator from null object." + ) + .into()); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/util/noise/OctaveGenerator")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/util/noise/PerlinOctaveGenerator")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a OctaveGenerator object, got {}", + "Invalid argument passed. Expected a PerlinOctaveGenerator object, got {}", name ) .into()) @@ -727,88 +726,89 @@ impl<'mc> JNIInstantiatable<'mc> for OctaveGenerator<'mc> { } } -impl<'mc> OctaveGenerator<'mc> { +impl<'mc> PerlinOctaveGenerator<'mc> { + /// Creates a perlin octave generator for the given {@link Random} + pub fn new( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + rand: impl Into>, + octaves: i32, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/util/Random;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(rand.into().jni_object().clone()) + }); + args.push(val_1); + sig += "I"; + let val_2 = jni::objects::JValueGen::Int(octaves); + args.push(val_2); + sig += ")V"; + let cls = jni.find_class("org/bukkit/util/noise/PerlinOctaveGenerator"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.new_object(cls, sig.as_str(), args); + let res = jni.translate_error_no_gen(res)?; + crate::util::noise::PerlinOctaveGenerator::from_raw(&jni, res) + } + // SUPER CLASS: org.bukkit.util.noise.OctaveGenerator ( []) /// Sets the scale used for all coordinates passed to this generator. /// /// This is the equivalent to setting each coordinate to the specified /// value. pub fn set_scale(&self, scale: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(scale); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setScale", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + let temp_clone = crate::util::noise::OctaveGenerator::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::util::noise::OctaveGenerator = temp_clone.into(); + real.set_scale(scale) } /// Gets the scale used for each X-coordinates passed pub fn xscale(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getXScale", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + let temp_clone = crate::util::noise::OctaveGenerator::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::util::noise::OctaveGenerator = temp_clone.into(); + real.xscale() } /// Sets the scale used for each X-coordinates passed pub fn set_xscale(&self, scale: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(scale); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setXScale", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + let temp_clone = crate::util::noise::OctaveGenerator::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::util::noise::OctaveGenerator = temp_clone.into(); + real.set_xscale(scale) } /// Gets the scale used for each Y-coordinates passed pub fn yscale(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getYScale", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + let temp_clone = crate::util::noise::OctaveGenerator::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::util::noise::OctaveGenerator = temp_clone.into(); + real.yscale() } /// Sets the scale used for each Y-coordinates passed pub fn set_yscale(&self, scale: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(scale); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setYScale", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + let temp_clone = crate::util::noise::OctaveGenerator::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::util::noise::OctaveGenerator = temp_clone.into(); + real.set_yscale(scale) } /// Gets the scale used for each Z-coordinates passed pub fn zscale(&self) -> Result> { - let sig = String::from("()D"); - let res = self - .jni_ref() - .call_method(&self.jni_object(), "getZScale", sig.as_str(), vec![]); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + let temp_clone = crate::util::noise::OctaveGenerator::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::util::noise::OctaveGenerator = temp_clone.into(); + real.zscale() } /// Sets the scale used for each Z-coordinates passed pub fn set_zscale(&self, scale: f64) -> Result<(), Box> { - let sig = String::from("(D)V"); - let val_1 = jni::objects::JValueGen::Double(scale); - let res = self.jni_ref().call_method( - &self.jni_object(), - "setZScale", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - self.jni_ref().translate_error(res)?; - Ok(()) + let temp_clone = crate::util::noise::OctaveGenerator::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::util::noise::OctaveGenerator = temp_clone.into(); + real.set_zscale(scale) } /// Gets a clone of the individual octaves used within this generator pub fn octaves( @@ -834,38 +834,11 @@ impl<'mc> OctaveGenerator<'mc> { amplitude: std::option::Option, normalized: std::option::Option, ) -> Result> { - let mut args = Vec::new(); - let mut sig = String::from("("); - sig += "D"; - let val_1 = jni::objects::JValueGen::Double(x); - args.push(val_1); - sig += "D"; - let val_2 = jni::objects::JValueGen::Double(y); - args.push(val_2); - sig += "D"; - let val_3 = jni::objects::JValueGen::Double(z); - args.push(val_3); - if let Some(a) = frequency { - sig += "D"; - let val_4 = jni::objects::JValueGen::Double(a); - args.push(val_4); - } - if let Some(a) = amplitude { - sig += "D"; - let val_5 = jni::objects::JValueGen::Double(a); - args.push(val_5); - } - if let Some(a) = normalized { - sig += "Z"; - let val_6 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_6); - } - sig += ")D"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "noise", sig.as_str(), args); - let res = self.jni_ref().translate_error(res)?; - Ok(res.d()?) + let temp_clone = crate::util::noise::OctaveGenerator::from_raw(&self.0, unsafe { + jni::objects::JObject::from_raw(self.1.clone()) + })?; + let real: crate::util::noise::OctaveGenerator = temp_clone.into(); + real.noise(x, y, z, frequency, amplitude, normalized) } pub fn instance_of(&self, other: impl Into) -> Result { @@ -873,13 +846,20 @@ impl<'mc> OctaveGenerator<'mc> { self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for PerlinOctaveGenerator<'mc> { + fn into(self) -> crate::util::noise::OctaveGenerator<'mc> { + crate::util::noise::OctaveGenerator::from_raw(&self.jni_ref(), self.1).expect( + "Error converting PerlinOctaveGenerator into crate::util::noise::OctaveGenerator", + ) + } +} #[repr(C)] -pub struct NoiseGenerator<'mc>( +pub struct PerlinNoiseGenerator<'mc>( pub(crate) blackboxmc_general::SharedJNIEnv<'mc>, pub(crate) jni::objects::JObject<'mc>, ); -impl<'mc> JNIRaw<'mc> for NoiseGenerator<'mc> { +impl<'mc> JNIRaw<'mc> for PerlinNoiseGenerator<'mc> { fn jni_ref(&self) -> blackboxmc_general::SharedJNIEnv<'mc> { self.0.clone() } @@ -887,20 +867,21 @@ impl<'mc> JNIRaw<'mc> for NoiseGenerator<'mc> { unsafe { jni::objects::JObject::from_raw(self.1.clone()) } } } -impl<'mc> JNIInstantiatable<'mc> for NoiseGenerator<'mc> { +impl<'mc> JNIInstantiatable<'mc> for PerlinNoiseGenerator<'mc> { fn from_raw( env: &blackboxmc_general::SharedJNIEnv<'mc>, obj: jni::objects::JObject<'mc>, ) -> Result> { if obj.is_null() { return Err( - eyre::eyre!("Tried to instantiate NoiseGenerator from null object.").into(), + eyre::eyre!("Tried to instantiate PerlinNoiseGenerator from null object.").into(), ); } - let (valid, name) = env.validate_name(&obj, "org/bukkit/util/noise/NoiseGenerator")?; + let (valid, name) = + env.validate_name(&obj, "org/bukkit/util/noise/PerlinNoiseGenerator")?; if !valid { Err(eyre::eyre!( - "Invalid argument passed. Expected a NoiseGenerator object, got {}", + "Invalid argument passed. Expected a PerlinNoiseGenerator object, got {}", name ) .into()) @@ -910,57 +891,36 @@ impl<'mc> JNIInstantiatable<'mc> for NoiseGenerator<'mc> { } } -impl<'mc> NoiseGenerator<'mc> { - pub fn from_extendable( - env: &blackboxmc_general::SharedJNIEnv<'mc>, - plugin: &'mc crate::plugin::Plugin, - address: i32, - lib_name: String, - name: String, - ) -> Result> { - let obj = unsafe { plugin.new_extendable(address, "NoiseGenerator", name, lib_name) }?; - Self::from_raw(env, obj) - } - +impl<'mc> PerlinNoiseGenerator<'mc> { + /// Creates a seeded perlin noise generator with the given Random pub fn new( jni: &blackboxmc_general::SharedJNIEnv<'mc>, - ) -> Result, Box> { - let sig = String::from("()V"); - let cls = jni.find_class("org/bukkit/util/noise/NoiseGenerator"); + rand: impl Into>, + ) -> Result, Box> { + let mut args = Vec::new(); + let mut sig = String::from("("); + sig += "Ljava/util/Random;"; + let val_1 = jni::objects::JValueGen::Object(unsafe { + jni::objects::JObject::from_raw(rand.into().jni_object().clone()) + }); + args.push(val_1); + sig += ")V"; + let cls = jni.find_class("org/bukkit/util/noise/PerlinNoiseGenerator"); let cls = jni.translate_error_with_class(cls)?; - let res = jni.new_object(cls, sig.as_str(), vec![]); + let res = jni.new_object(cls, sig.as_str(), args); let res = jni.translate_error_no_gen(res)?; - crate::util::noise::NoiseGenerator::from_raw(&jni, res) - } - /// Speedy floor, faster than (int)Math.floor(x) - pub fn floor( - jni: &blackboxmc_general::SharedJNIEnv<'mc>, - x: f64, - ) -> Result> { - let sig = String::from("(D)I"); - let val_1 = jni::objects::JValueGen::Double(x); - let cls = jni.find_class("org/bukkit/util/noise/NoiseGenerator"); - let cls = jni.translate_error_with_class(cls)?; - let res = jni.call_static_method( - cls, - "floor", - sig.as_str(), - vec![jni::objects::JValueGen::from(val_1)], - ); - let res = jni.translate_error(res)?; - Ok(res.i()?) + crate::util::noise::PerlinNoiseGenerator::from_raw(&jni, res) } /// Generates noise for the 3D coordinates using the specified number of /// octaves and parameters - pub fn noise( - &self, + pub fn get_noise( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, x: f64, y: std::option::Option, z: std::option::Option, octaves: std::option::Option, frequency: std::option::Option, amplitude: std::option::Option, - normalized: std::option::Option, ) -> Result> { let mut args = Vec::new(); let mut sig = String::from("("); @@ -992,21 +952,61 @@ impl<'mc> NoiseGenerator<'mc> { let val_6 = jni::objects::JValueGen::Double(a); args.push(val_6); } - if let Some(a) = normalized { - sig += "Z"; - let val_7 = jni::objects::JValueGen::Bool(a.into()); - args.push(val_7); - } sig += ")D"; - let res = self - .jni_ref() - .call_method(&self.jni_object(), "noise", sig.as_str(), args); + let cls = jni.find_class("org/bukkit/util/noise/PerlinNoiseGenerator"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getNoise", sig.as_str(), args); + let res = jni.translate_error(res)?; + Ok(res.d()?) + } + /// Gets the singleton unseeded instance of this generator + pub fn instance( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + ) -> Result, Box> { + let sig = String::from("()Lorg/bukkit/util/noise/PerlinNoiseGenerator;"); + let cls = jni.find_class("org/bukkit/util/noise/PerlinNoiseGenerator"); + let cls = jni.translate_error_with_class(cls)?; + let res = jni.call_static_method(cls, "getInstance", sig.as_str(), vec![]); + let res = jni.translate_error(res)?; + let obj = res.l()?; + crate::util::noise::PerlinNoiseGenerator::from_raw(&jni, obj) + } + + pub fn noise(&self, x: f64, y: f64, z: f64) -> Result> { + let sig = String::from("(DDD)D"); + let val_1 = jni::objects::JValueGen::Double(x); + let val_2 = jni::objects::JValueGen::Double(y); + let val_3 = jni::objects::JValueGen::Double(z); + let res = self.jni_ref().call_method( + &self.jni_object(), + "noise", + sig.as_str(), + vec![ + jni::objects::JValueGen::from(val_1), + jni::objects::JValueGen::from(val_2), + jni::objects::JValueGen::from(val_3), + ], + ); let res = self.jni_ref().translate_error(res)?; Ok(res.d()?) } + // SUPER CLASS: org.bukkit.util.noise.NoiseGenerator ( ['getNoise', 'getInstance', 'noise']) + /// Speedy floor, faster than (int)Math.floor(x) + pub fn floor( + jni: &blackboxmc_general::SharedJNIEnv<'mc>, + x: f64, + ) -> Result> { + crate::util::noise::NoiseGenerator::floor(jni, x) + } pub fn instance_of(&self, other: impl Into) -> Result { let cls = &self.jni_ref().find_class(other.into().as_str())?; self.jni_ref().is_instance_of(&self.jni_object(), cls) } } +impl<'mc> Into> for PerlinNoiseGenerator<'mc> { + fn into(self) -> crate::util::noise::NoiseGenerator<'mc> { + crate::util::noise::NoiseGenerator::from_raw(&self.jni_ref(), self.1) + .expect("Error converting PerlinNoiseGenerator into crate::util::noise::NoiseGenerator") + } +} diff --git a/blackboxmc-rs-proc/README.md b/blackboxmc-rs-proc/README.md new file mode 100644 index 0000000..1428c8a --- /dev/null +++ b/blackboxmc-rs-proc/README.md @@ -0,0 +1,3 @@ +**Currently not useful, was pushed to crates.io in it's state because I forgot to finish it.** + +When at 1.0, this will be a proc macro for automating the process of making classes that inherit ones from Spigot. diff --git a/generate.py b/generate.py index 2b32a3a..c2a5a9f 100755 --- a/generate.py +++ b/generate.py @@ -772,7 +772,10 @@ def java_type_to_rust(argname, ty, method, i, returning, library, is_constructor else: generics_ = [] else: - generics_ = method["method"]["returnType"]["generics"] + if "generics" in method["method"]["returnType"]: + generics_ = method["method"]["returnType"]["generics"] + else: + generics_ = [] else: if i <= len(method["method"]["parameters"]): if "generics" in method["method"]["parameters"][i]: @@ -1453,7 +1456,10 @@ def parse_methods(library,name,val,mod_path,is_trait,is_trait_decl,is_constructo if val_group["type_name_alone"] in omitted_classes: continue if static: - code.append(val_group["type_name_resolved"]+"::"+name+"("+func_signature_resolved_names_only+")") + tyname = val_group["type_name_resolved"] + if(val_group["qualifiedName"] in enums): + tyname += "Struct" + code.append(tyname+"::"+name+"("+func_signature_resolved_names_only+")") else: parsed_name = parsed_names[len(parsed_names)-1] # we do an unsafe clone here but justify it because it's only to execute the method. said unsafe clone @@ -1633,6 +1639,7 @@ def parse_classes(library, val, classes): if "qualifiedName" in val["superclass"]: if val["superclass"]["qualifiedName"] == "java.lang.Enum": val["isEnum"] = True + val["fields"] = val["constants"] else: meth = list(filter(lambda f: f["name"] == "values",val["methods"])) if len(meth) >= 1 and len(val["fields"]) >= 1: @@ -1657,7 +1664,6 @@ def parse_classes(library, val, classes): val["values"] = [] val["values"] += list(map(lambda f: f["name"],val["fields"])) - print(val["fields"]) file_cache[mod_path].append( "pub enum "+name+"<'mc> {") @@ -1682,7 +1688,6 @@ def parse_classes(library, val, classes): val_proper = val_proper[0].upper() + val_proper[1:] if val_proper.lower() in reserved_words: val_proper = "Variant"+val_proper - print(v) variants.append((v,val_proper)) # DISPLAY IMPL @@ -1696,6 +1701,16 @@ def parse_classes(library, val, classes): file_cache[mod_path].append(" }") file_cache[mod_path].append("}") + file_cache[mod_path].append("impl<'mc> std::ops::Deref for "+name+"<'mc> {") + file_cache[mod_path].append(" type Target = "+name+"Struct<'mc>;") + file_cache[mod_path].append(" fn deref(&self) -> &<"+name+"<'mc> as std::ops::Deref>::Target {") + file_cache[mod_path].append(" match self {") + for (v,val_proper) in variants: + file_cache[mod_path].append(" "+name+"::"+val_proper+" { inner } => inner,") + file_cache[mod_path].append(" }") + file_cache[mod_path].append(" }") + file_cache[mod_path].append("}") + file_cache[mod_path].append(""" impl<'mc> """+name+"""<'mc> { pub fn value_of( @@ -1922,20 +1937,27 @@ def parse_annotations(annotations,comment): classes = libraries[package] for clas in classes: - if "isInterface" in clas: - if clas["isInterface"]: - interface_names.append(clas["packageName"]+"."+clas["name"]) - if "isEnum" in clas: - if clas["isEnum"]: - enums.append(clas["packageName"]+"."+clas["name"]) + + packageName = clas["qualifiedName"].replace("::",".") + if "interface" in clas["modifiers"]: + interface_names.append(packageName) + + if "superclass" in clas: + if clas["superclass"]["qualifiedName"] == "java.lang.Enum" or "org.bukkit.Keyed" in list(map(lambda f: f["qualifiedName"], clas["interfaces"])): + enums.append(packageName) + else: + meth = list(filter(lambda f: f["name"] == "clasues",clas["methods"])) + if len(meth) >= 1 and len(clas["fields"]) >= 1: + enums.append(packageName) if "classes" in clas: for cla in clas["classes"]: - if "isInterface" in cla: - if cla["isInterface"]: - interface_names.append(cla["packageName"]+"."+cla["name"]) - if "isEnum" in cla: - if cla["isEnum"]: - enums.append(cla["packageName"]+"."+cla["name"]) + if "superclass" in cla: + if cla["superclass"]["qualifiedName"] == "java.lang.Enum" or "org.bukkit.Keyed" in list(map(lambda f: f["qualifiedName"], cla["interfaces"])): + enums.append(packageName) + else: + meth = list(filter(lambda f: f["name"] == "clasues",cla["methods"])) + if len(meth) >= 1 and len(cla["fields"]) >= 1: + enums.append(packageName) for library in libraries: packages = libraries[library] diff --git a/pprint.py b/pprint.py old mode 100644 new mode 100755 index 74ba558..27404da --- a/pprint.py +++ b/pprint.py @@ -1,3 +1,4 @@ +#!/usr/bin/python import json f = open("./spigot.json","r")